From d8dd4d9c0cd4554704cbe15b5502f4d87a4674ad Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 27 Jun 2023 20:01:52 -0700 Subject: Just about got hero reflection maps working. DRTVWR-583 --- indra/llprimitive/llprimitive.cpp | 5 + indra/llprimitive/llprimitive.h | 1 + indra/llprimitive/llprimtexturelist.cpp | 10 ++ indra/llprimitive/llprimtexturelist.h | 1 + indra/llprimitive/lltextureentry.cpp | 19 +++ indra/llprimitive/lltextureentry.h | 12 +- indra/llrender/llglslshader.cpp | 4 +- indra/llrender/llglslshader.h | 1 + indra/llrender/llshadermgr.cpp | 9 ++ indra/llrender/llshadermgr.h | 1 + indra/newview/app_settings/settings.xml | 11 ++ .../shaders/class3/deferred/reflectionProbeF.glsl | 8 ++ .../shaders/class3/deferred/softenLightF.glsl | 12 +- indra/newview/llpanelface.cpp | 18 +++ indra/newview/llpanelface.h | 4 +- indra/newview/llreflectionmap.h | 11 ++ indra/newview/llreflectionmapmanager.cpp | 135 +++++++++++++++++---- indra/newview/llreflectionmapmanager.h | 15 ++- indra/newview/llselectmgr.cpp | 41 +++++++ indra/newview/llselectmgr.h | 1 + indra/newview/llviewerobject.cpp | 22 ++++ indra/newview/llviewerobject.h | 1 + indra/newview/llviewershadermgr.cpp | 2 + indra/newview/llvovolume.cpp | 10 ++ indra/newview/llvovolume.h | 1 + indra/newview/pipeline.cpp | 7 ++ 26 files changed, 331 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 5dfce4ae16..b45ead92d3 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -404,6 +404,11 @@ S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) return mTextureList.setFullbright(index, fullbright); } +S32 LLPrimitive::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) +{ + return mTextureList.setRenderableTarget(te, target); +} + S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { return mTextureList.setMediaFlags(index, media_flags); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index d2adfa4a3d..520c7c7ac8 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -485,6 +485,7 @@ public: virtual S32 setTETexGen(const U8 te, const U8 texgen); virtual S32 setTEShiny(const U8 te, const U8 shiny); virtual S32 setTEFullbright(const U8 te, const U8 fullbright); + virtual S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); virtual S32 setTEMediaFlags(const U8 te, const U8 flags); virtual S32 setTEGlow(const U8 te, const F32 glow); virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index f4f08248b8..49b59e35cb 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -341,6 +341,16 @@ S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright) return TEM_CHANGE_NONE; } +S32 LLPrimTextureList::setRenderableTarget(const U8 index, const U8 target) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->setRenderableTarget((LLTextureEntry::eRenderableTarget)target); + } + + return TEM_CHANGE_NONE; +} + S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { if (index < mEntryList.size()) diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 49c636e40f..34b87d879f 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -102,6 +102,7 @@ public: S32 setTexGen(const U8 index, const U8 texgen); S32 setShiny(const U8 index, const U8 shiny); S32 setFullbright(const U8 index, const U8 t); + S32 setRenderableTarget(const U8 index, const U8 target); S32 setMediaFlags(const U8 index, const U8 media_flags); S32 setGlow(const U8 index, const F32 glow); S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 71caff1686..d057e5ab29 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -504,6 +504,16 @@ S32 LLTextureEntry::setFullbright(U8 fullbright) return TEM_CHANGE_NONE; } +S32 LLTextureEntry::setRenderableTarget(eRenderableTarget target) +{ + if (getRenderableTarget() != target) { + mRenderableTarget = target; + return TEM_CHANGE_TEXTURE; + } + + return TEM_CHANGE_NONE; +} + S32 LLTextureEntry::setShiny(U8 shiny) { shiny &= TEM_SHINY_MASK; @@ -685,6 +695,15 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) mMaterialUpdatePending = true; } mMaterial = pMaterialParams; + + // TODO: GZ: We should avoid magic UUIDs in the future, but for development we're using one for the time being. Remove this later. + if (mMaterial->getSpecularID().asString() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") + { + setRenderableTarget(RT_MIRROR); + } else { + setRenderableTarget(RT_DISABLED); + } + return TEM_CHANGE_TEXTURE; } diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index f5f2c0172d..2c0832e1d4 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -80,6 +80,12 @@ public: TEX_GEN_SPHERICAL = 0x04, TEX_GEN_CYLINDRICAL = 0x06 } eTexGen; + + + typedef enum e_renderable_target { + RT_DISABLED = 0x00, + RT_MIRROR = 0x02 + } eRenderableTarget; LLTextureEntry(); LLTextureEntry(const LLUUID& tex_id); @@ -134,7 +140,9 @@ public: S32 setGlow(F32 glow); S32 setMaterialID(const LLMaterialID& pMaterialID); S32 setMaterialParams(const LLMaterialPtr pMaterialParams); - + + S32 setRenderableTarget(eRenderableTarget target); + virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } const F32 getAlpha() const { return mColor.mV[VALPHA]; } @@ -152,6 +160,7 @@ public: U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; } U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; } + eRenderableTarget getRenderableTarget() const { return mRenderableTarget; } U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; } U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; } U8 getBumpShinyFullbright() const { return mBump; } @@ -233,6 +242,7 @@ protected: LLColor4 mColor; U8 mBump; // Bump map, shiny, and fullbright U8 mMediaFlags; // replace with web page, movie, etc. + eRenderableTarget mRenderableTarget; F32 mGlow; bool mMaterialUpdatePending; LLMaterialID mMaterialID; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index ccfb8f69be..be5ad08fbe 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } + + S32 index = mTexture[uniform]; if (index != -1) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index b8071248e2..71b9b0f4fb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -57,6 +57,7 @@ public: bool hasAlphaMask = false; bool hasReflectionProbes = false; bool attachNothing = false; + bool hasHeroProbes = false; }; // ============= Structure for caching shader uniforms =============== diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 75d6ef6c46..177cad2508 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -238,6 +238,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + + if (features->hasHeroProbes) + { + if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl")) + { + return FALSE; + } + } if (features->hasShadows) { @@ -1260,6 +1268,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("sceneDepth"); mReservedUniforms.push_back("reflectionProbes"); mReservedUniforms.push_back("irradianceProbes"); + mReservedUniforms.push_back("heroProbes"); mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); mReservedUniforms.push_back("fullbright"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46f352aa58..cfa824c361 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -96,6 +96,7 @@ public: SCENE_DEPTH, // "sceneDepth" REFLECTION_PROBES, // "reflectionProbes" IRRADIANCE_PROBES, // "irradianceProbes" + HERO_PROBE, // "heroProbes" CLOUD_NOISE_MAP, // "cloud_noise_texture" CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next" FULLBRIGHT, // "fullbright" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2b2a2d9d1b..270d5e6869 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9175,6 +9175,17 @@ 0.00 + RenderMirrors + + Comment + Renders realtime mirrors. + Persist + 1 + Type + Boolean + Value + 1 + RenderScreenSpaceReflections Comment diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 1b2a34ef01..298ddf92a7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -31,6 +31,7 @@ float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, uniform samplerCubeArray reflectionProbes; uniform samplerCubeArray irradianceProbes; + uniform sampler2D sceneMap; uniform int cube_snapshot; uniform float max_probe_lod; @@ -70,6 +71,9 @@ layout (std140) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; + + vec4 heroPosition[1]; + int heroProbeCount; }; // Inputs @@ -513,6 +517,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, v = env_mat * v; +#if defined(HERO_PROBES) + vec3 mirror = textureLod(heroProbes, vec4(v.xyz, 0), lod).rgb; +#endif + vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 4ef003e0cb..a63d445115 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -32,6 +32,14 @@ uniform sampler2D specularRect; uniform sampler2D normalMap; uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl +uniform samplerCubeArray heroProbes; + +layout (std140) uniform HeroProbeData +{ + vec4 heroPosition[1]; + int heroProbeCount; +}; + const float M_PI = 3.14159265; #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO) @@ -290,7 +298,7 @@ void main() vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; #endif - - frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results + frag_color.rgb = textureLod(heroProbes, vec4(norm.xyz, 0), 0).rgb; + //frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7d6015f557..6b737b6895 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -592,6 +592,17 @@ void LLPanelFace::sendFullbright() LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); } +void LLPanelFace::sendMirror() +{ + LLCheckBoxCtrl* mCheckMirror = getChild("checkbox mirror"); + + if (!mCheckMirror) + return; + + LLTextureEntry::eRenderableTarget target = mCheckMirror->get() ? LLTextureEntry::RT_MIRROR : LLTextureEntry::RT_DISABLED; + LLSelectMgr::getInstance()->selectionSetRenderableTarget(target); +} + void LLPanelFace::sendColor() { @@ -1686,6 +1697,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChild("shinyOffsetV")->setValue(offset_y); getChild("glossiness")->setValue(material->getSpecularLightExponent()); getChild("environment")->setValue(material->getEnvironmentIntensity()); + getChild("mirror")->setValue(material->getEnvironmentIntensity()); updateShinyControls(!material->getSpecularID().isNull(), true); } @@ -2994,6 +3006,12 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) self->sendFullbright(); } +void LLPanelFace::onCommitMirror(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendMirror(); +} + // static void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 106259b84a..f6d6d99d9f 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -138,6 +138,7 @@ protected: void sendTexGen(); // applies and sends bump map void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright + void sendMirror(); void sendGlow(); void alignTestureLayer(); @@ -227,7 +228,8 @@ protected: static void onCommitShiny( LLUICtrl* ctrl, void* userdata); static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); - static void onCommitGlow( LLUICtrl* ctrl, void *userdata); + static void onCommitMirror(LLUICtrl* ctrl, void* userdata); + static void onCommitGlow( LLUICtrl* ctrl, void *userdata); static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 7ea0fe6187..831a6358ee 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -36,6 +36,15 @@ class alignas(16) LLReflectionMap : public LLRefCount { LL_ALIGN_NEW public: + + enum class ProbeType + { + ALL = 0, + RADIANCE, + IRRADIANCE, + REFLECTION + }; + // allocate an environment map of the given resolution LLReflectionMap(); @@ -127,5 +136,7 @@ public: GLuint mOcclusionQuery = 0; bool mOccluded = false; U32 mOcclusionPendingFrames = 0; + + ProbeType mType; }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index e30aba3df7..8e7d073167 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -130,6 +130,13 @@ void LLReflectionMapManager::update() U32 targetRes = mProbeResolution * 4; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } + + if (!mHeroRenderTarget.isComplete()) + { + U32 color_fmt = GL_RGB16F; + U32 targetRes = mHeroProbeResolution * 2; + mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + } if (mMipChain.empty()) { @@ -315,7 +322,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i); + updateProbeFace(closestDynamic, i, mProbeResolution); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -354,6 +361,10 @@ void LLReflectionMapManager::update() oldestOccluded->autoAdjustOrigin(); oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } + + + doHeroProbeUpdate(); + } LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) @@ -528,7 +539,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution); if (++mUpdatingFace == 6) { @@ -547,6 +558,21 @@ void LLReflectionMapManager::doProbeUpdate() } } +void LLReflectionMapManager::doHeroProbeUpdate() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(mHeroProbe != nullptr); + + touch_default_probe(mHeroProbe); + + for (int i = 0; i < 6; i++) + { + gPipeline.mRT = &gPipeline.mAuxillaryRT; + mHeroProbe->update(mHeroProbeResolution, i); + gPipeline.mRT = &gPipeline.mMainRT; + } +} + // Do the reflection map update render passes. // For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated // First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate @@ -555,10 +581,20 @@ void LLReflectionMapManager::doProbeUpdate() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) +void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; + + LLRenderTarget* target = &mRenderTarget; + + S32 sourceIdx = mReflectionProbeCount; + + if (probeResolution == mHeroProbeResolution) + { + sourceIdx = 0; + target = &mHeroRenderTarget; + } mLightScale = 1.f; static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); @@ -577,20 +613,18 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); - probe->update(mRenderTarget.getWidth(), face); + probe->update(target->getWidth(), face); gPipeline.popRenderTypeMask(); } else { - probe->update(mRenderTarget.getWidth(), face); + probe->update(target->getWidth(), face); } gPipeline.mRT = &gPipeline.mMainRT; - S32 sourceIdx = mReflectionProbeCount; - - if (probe != mUpdatingProbe) + if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel sourceIdx += 1; } @@ -611,7 +645,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.loadIdentity(); gGL.flush(); - U32 res = mProbeResolution * 2; + U32 res = probeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -623,20 +657,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal gGaussianProgram.uniform2f(direction, 1.f, 0.f); gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); + target->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); + target->flush(); // vertical gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + gGL.getTexUnit(diffuseChannel)->bind(target); screen_rt->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -644,7 +678,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } - S32 mips = log2((F32)mProbeResolution) + 0.5f; + S32 mips = log2((F32)probeResolution) + 0.5f; gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -663,7 +697,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) } - gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -675,14 +709,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - mTexture->bind(0); + probe->mCubeArray->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); //if (i == 0) //{ //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); //} - mTexture->unbind(); + probe->mCubeArray->unbind(); } mMipChain[i].flush(); } @@ -695,7 +729,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.unbind(); } - if (face == 5) + if (face == 5 && probe->mType != LLReflectionMap::ProbeType::REFLECTION) { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); @@ -707,7 +741,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -722,7 +756,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gRadianceGenProgram.uniform1i(sWidth, probeResolution); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -752,7 +786,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -787,7 +821,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) S32 res = mMipChain[i].getWidth(); mIrradianceMaps->bind(channel); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - mTexture->bind(channel); + probe->mCubeArray->bind(channel); } } } @@ -890,7 +924,7 @@ void LLReflectionMapManager::updateUniforms() GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth // numbrer of active refmaps - GLint refmapCount; + GLint refmapCount; }; mReflectionMaps.resize(mReflectionProbeCount); @@ -1068,7 +1102,7 @@ void LLReflectionMapManager::updateUniforms() #endif rpd.refmapCount = count; - + //copy rpd into uniform buffer object if (mUBO == 0) { @@ -1081,7 +1115,35 @@ void LLReflectionMapManager::updateUniforms() glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } + + struct HeroProbeData + { + LLVector4 heroPosition[1]; + GLint heroProbeCount = 1; + }; + + HeroProbeData hpd; + + modelview.loadu(gGLModelView); + + oa.set(0, 0, 0, 0); + hpd.heroProbeCount = 1; + modelview.affineTransform(mHeroProbe->mOrigin, oa); + hpd.heroPosition[0].set(oa.getF32ptr()); + + //copy rpd into uniform buffer object + if (mUBO == 0) + { + glGenBuffers(1, &mHeroUBO); + } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); + glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + #if 0 if (!gCubeSnapshot) { @@ -1214,7 +1276,7 @@ void LLReflectionMapManager::initReflectionMaps() { U32 count = LL_MAX_REFLECTION_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset) + if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) { mReset = false; mReflectionProbeCount = count; @@ -1263,6 +1325,22 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); + + mHeroProbeResolution = 512; + + mHeroArray = new LLCubeMapArray(); + mHeroArray->allocate(mHeroProbeResolution, 3, 1); + + if (mHeroProbe.isNull()) { + mHeroProbe = new LLReflectionMap(); + } + + mHeroProbe->mCubeIndex = 0; + mHeroProbe->mCubeArray = mHeroArray; + mHeroProbe->mDistance = 64.f; + mHeroProbe->mRadius = 4096.f; + mHeroProbe->mProbeIndex = 0; + touch_default_probe(mHeroProbe); } @@ -1291,11 +1369,13 @@ void LLReflectionMapManager::cleanup() { mVertexBuffer = nullptr; mRenderTarget.release(); + mHeroRenderTarget.release(); mMipChain.clear(); mTexture = nullptr; mIrradianceMaps = nullptr; + mHeroArray = nullptr; mProbes.clear(); mKillList.clear(); @@ -1306,9 +1386,14 @@ void LLReflectionMapManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; + + mHeroProbe = nullptr; glDeleteBuffers(1, &mUBO); mUBO = 0; + + glDeleteBuffers(1, &mHeroUBO); + mHeroUBO = 0; // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state initCubeFree(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 5a3901cae9..2ca9a8d598 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -125,11 +125,15 @@ private: // render target for cube snapshots // used to generate mipmaps without doing a copy-to-texture LLRenderTarget mRenderTarget; + + LLRenderTarget mHeroRenderTarget; std::vector mMipChain; // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; + + LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -142,9 +146,11 @@ private: // perform an update on the currently updating Probe void doProbeUpdate(); + + void doHeroProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution); // list of active reflection maps std::vector > mProbes; @@ -157,6 +163,9 @@ private: // handle to UBO U32 mUBO = 0; + + // Hero UBO + U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; @@ -176,12 +185,16 @@ private: bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) + + LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; + + U32 mHeroProbeResolution = 512; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index dca341e5a2..19ce8f6a55 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2347,6 +2347,47 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) getSelection()->applyToObjects(&sendfunc); } +void LLSelectMgr::selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target) +{ + struct f : public LLSelectedTEFunctor + { + LLTextureEntry::eRenderableTarget mRenderableTarget; + + f(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} + + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + object->setTERenderableTarget(te, mRenderableTarget); + } + + return true; + } + } setfunc(target); + + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + LLTextureEntry::eRenderableTarget mRenderableTarget; + + g(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} + + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + + return true; + } + } sendfunc(target); + + getSelection()->applyToObjects(&sendfunc); +} + // This function expects media_data to be a map containing relevant // media data name/value pairs (e.g. home_url, etc.) void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index ca9a32f0db..93d750215b 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -653,6 +653,7 @@ public: void selectionSetGlow(const F32 glow); void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); void selectionRemoveMaterial(); + void selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target); void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); void selectionSetObjectName(const std::string& name); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e67750af7c..8930b2453b 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5284,6 +5284,28 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) return retval; } +S32 LLViewerObject::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) +{ + S32 retval = 0; + + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (target != tep->getRenderableTarget()) + { + retval = LLPrimitive::setTERenderableTarget(te, target); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + //gPipeline.markMirror(mDrawable); + } + } + + return retval; +} + S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index bf82c43cd3..f4f596bfd0 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -359,6 +359,7 @@ public: /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); + /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5eae1dfb18..f6f1cf6854 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2228,6 +2228,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredSoftenProgram.addPermutation("LOCAL_LIGHT_KILL", "1"); } + + gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8160785d75..8eacdd2162 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -2344,6 +2344,16 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) return res; } +S32 LLVOVolume::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget mirror) +{ + S32 res = LLViewerObject::setTERenderableTarget(te, mirror); + if (res) + { + //gPipeline.markMirror(mDrawable); + } + return res; +} + S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index acba18383f..f2162ef244 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -209,6 +209,7 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; + /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) override; /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 38f27d4dfa..d6e0bf1b09 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8419,6 +8419,13 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } + + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) + { + mReflectionMapManager.mHeroArray->bind(channel); + bound = true; + } if (bound) { -- cgit v1.2.3 From 5ade456ee796aeb779302016b9ee9d418c728a22 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 28 Jun 2023 13:27:15 -0400 Subject: Make sure we're passing the cube array as a parameter to updateProbeFace. DRTVWR-583 --- indra/newview/llreflectionmapmanager.cpp | 36 ++++++++++++++++++++++++-------- indra/newview/llreflectionmapmanager.h | 2 +- 2 files changed, 28 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 8e7d073167..783ff69073 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -322,7 +322,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i, mProbeResolution); + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -362,8 +362,26 @@ void LLReflectionMapManager::update() oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } - - doHeroProbeUpdate(); + if (mHeroProbe != nullptr) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + // update the closest dynamic probe realtime + // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames + mHeroProbe->autoAdjustOrigin(); + + // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set + // lighting values etc + bool radiance_pass = isRadiancePass(); + mRadiancePass = mRealtimeRadiancePass; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(mHeroProbe, i, mProbeResolution, mHeroArray); + } + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } } @@ -539,7 +557,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture); if (++mUpdatingFace == 6) { @@ -709,14 +727,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - probe->mCubeArray->bind(0); + cubeArray->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); //if (i == 0) //{ //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); //} - probe->mCubeArray->unbind(); + cubeArray->unbind(); } mMipChain[i].flush(); } @@ -741,7 +759,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -786,7 +804,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -821,7 +839,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U S32 res = mMipChain[i].getWidth(); mIrradianceMaps->bind(channel); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - probe->mCubeArray->bind(channel); + cubeArray->bind(channel); } } } diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 2ca9a8d598..1275617e0a 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -150,7 +150,7 @@ private: void doHeroProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); // list of active reflection maps std::vector > mProbes; -- cgit v1.2.3 From 53b2efd13143f85c447320fa35d192df466b16ca Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 29 Jun 2023 17:35:24 -0400 Subject: Remove doHeroProbeUpdate DRTVWR-583 --- indra/newview/llreflectionmapmanager.cpp | 60 ++++++++++++-------------------- indra/newview/llreflectionmapmanager.h | 2 -- 2 files changed, 23 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 783ff69073..fe3ea15352 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -329,6 +329,28 @@ void LLReflectionMapManager::update() // restore "isRadiancePass" mRadiancePass = radiance_pass; } + + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + // update the closest dynamic probe realtime + // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames + mHeroProbe->autoAdjustOrigin(); + + // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set + // lighting values etc + bool radiance_pass = isRadiancePass(); + mRadiancePass = mRealtimeRadiancePass; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray); + } + + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) @@ -361,28 +383,6 @@ void LLReflectionMapManager::update() oldestOccluded->autoAdjustOrigin(); oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; } - - if (mHeroProbe != nullptr) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // update the closest dynamic probe realtime - // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames - mHeroProbe->autoAdjustOrigin(); - - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set - // lighting values etc - bool radiance_pass = isRadiancePass(); - mRadiancePass = mRealtimeRadiancePass; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(mHeroProbe, i, mProbeResolution, mHeroArray); - } - mRealtimeRadiancePass = !mRealtimeRadiancePass; - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - } LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) @@ -576,21 +576,6 @@ void LLReflectionMapManager::doProbeUpdate() } } -void LLReflectionMapManager::doHeroProbeUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - llassert(mHeroProbe != nullptr); - - touch_default_probe(mHeroProbe); - - for (int i = 0; i < 6; i++) - { - gPipeline.mRT = &gPipeline.mAuxillaryRT; - mHeroProbe->update(mHeroProbeResolution, i); - gPipeline.mRT = &gPipeline.mMainRT; - } -} - // Do the reflection map update render passes. // For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated // First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate @@ -1190,6 +1175,7 @@ void LLReflectionMapManager::setUniforms() updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); + glBindBufferBase(GL_UNIFORM_BUFFER, 1, mHeroUBO); } diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 1275617e0a..81b0ef8ed8 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -146,8 +146,6 @@ private: // perform an update on the currently updating Probe void doProbeUpdate(); - - void doHeroProbeUpdate(); // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); -- cgit v1.2.3 From f7f9601567ce089f3335407f1d3c7d32dbb18c60 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 17 Jul 2023 15:05:47 -0700 Subject: Got hero probes rendering from the camera. DRTVWR-583 --- indra/llplugin/llpluginprocessparent.cpp | 2 +- .../shaders/class3/deferred/softenLightF.glsl | 9 ++++---- indra/newview/llreflectionmapmanager.cpp | 26 ++++++++-------------- 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 756d0b5db8..f5966b71de 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -582,7 +582,7 @@ void LLPluginProcessParent::idle(void) params.args.add("-e"); params.args.add("tell application \"Terminal\""); params.args.add("-e"); - params.args.add(STRINGIZE("set win to do script \"gdb -pid " + params.args.add(STRINGIZE("set win to do script \"lldb -pid " << mProcess->getProcessID() << "\"")); params.args.add("-e"); params.args.add("do script \"continue\" in win"); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index a63d445115..d8118fab82 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -117,8 +117,8 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 additive, vec3 atten); -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -193,7 +193,7 @@ void main() if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 orm = texture(specularRect, tc).rgb; + vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; float metallic = orm.b; float ao = orm.r; @@ -298,7 +298,6 @@ void main() vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; #endif - frag_color.rgb = textureLod(heroProbes, vec4(norm.xyz, 0), 0).rgb; - //frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results + frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index fe3ea15352..45489fb35b 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -333,20 +333,14 @@ void LLReflectionMapManager::update() { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // update the closest dynamic probe realtime - // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames - mHeroProbe->autoAdjustOrigin(); - - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set - // lighting values etc + + mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); bool radiance_pass = isRadiancePass(); - mRadiancePass = mRealtimeRadiancePass; + mRadiancePass = true; for (U32 i = 0; i < 6; ++i) { updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray); } - - mRealtimeRadiancePass = !mRealtimeRadiancePass; // restore "isRadiancePass" mRadiancePass = radiance_pass; @@ -713,12 +707,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U { LL_PROFILE_GPU_ZONE("probe mip copy"); cubeArray->bind(0); - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - //if (i == 0) - //{ - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); - //} + cubeArray->unbind(); } mMipChain[i].flush(); @@ -732,7 +723,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gReflectionMipProgram.unbind(); } - if (face == 5 && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + if (face == 5) { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); @@ -1330,10 +1321,11 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - mHeroProbeResolution = 512; + mHeroProbeResolution = 128; mHeroArray = new LLCubeMapArray(); - mHeroArray->allocate(mHeroProbeResolution, 3, 1); + // Revise when we have both water and mirrors in hero probes. + mHeroArray->allocate(mHeroProbeResolution, 3, 2, true); if (mHeroProbe.isNull()) { mHeroProbe = new LLReflectionMap(); -- cgit v1.2.3 From 3d73326516c73f880f46e28f14b6c515307ede91 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 18 Jul 2023 00:14:34 -0700 Subject: Fix for irradiance breaking. Still need to fix the problem with individual faces getting tossed around though. Will work on that tomorrow. DRTVWR-583 --- indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 3 +-- indra/newview/llpanelface.cpp | 2 +- indra/newview/llreflectionmapmanager.cpp | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index d8118fab82..0152c0612a 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -217,6 +217,7 @@ void main() { color = atmosFragLightingLinear(color, additive, atten); } + color = texture(heroProbes, vec4(norm.xyz * env_mat, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -291,9 +292,7 @@ void main() color = atmosFragLightingLinear(color, additive, atten); } } - - #ifdef WATER_FOG vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); color = fogged.rgb; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 721b1482d9..9140888cc1 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1035,7 +1035,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mComboMatMedia->setEnabled(editable); LLRadioGroup* radio_mat_type = getChild("radio_material_type"); - + if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE) { radio_mat_type->selectNthItem(MATTYPE_DIFFUSE); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 6550686a32..99ebcf5231 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -1171,7 +1171,6 @@ void LLReflectionMapManager::setUniforms() updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); - glBindBufferBase(GL_UNIFORM_BUFFER, 1, mHeroUBO); } -- cgit v1.2.3 From b861832102abf469963bd3c56f7b009ba4432d6a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 6 Aug 2023 23:33:29 -0700 Subject: Making more progress, need to add the heroprobe manager. DRTVWR-583 --- indra/llprimitive/lltextureentry.cpp | 8 ------ .../shaders/class3/deferred/softenLightF.glsl | 4 ++- indra/newview/lldrawable.h | 1 + indra/newview/llreflectionmapmanager.cpp | 20 +++++++++------ indra/newview/llreflectionmapmanager.h | 4 ++- indra/newview/llviewerobject.h | 1 + indra/newview/llvovolume.cpp | 30 +++++++++++++++++++++- indra/newview/llvovolume.h | 2 ++ indra/newview/pipeline.cpp | 22 ++++++++++++++++ indra/newview/pipeline.h | 5 ++++ 10 files changed, 78 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index d057e5ab29..fdf3774bfa 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -696,14 +696,6 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) } mMaterial = pMaterialParams; - // TODO: GZ: We should avoid magic UUIDs in the future, but for development we're using one for the time being. Remove this later. - if (mMaterial->getSpecularID().asString() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") - { - setRenderableTarget(RT_MIRROR); - } else { - setRenderableTarget(RT_DISABLED); - } - return TEM_CHANGE_TEXTURE; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 0152c0612a..e485c26e9b 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -217,7 +217,9 @@ void main() { color = atmosFragLightingLinear(color, additive, atten); } - color = texture(heroProbes, vec4(norm.xyz * env_mat, 0), 0).xyz; + + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + color = texture(heroProbes, vec4(env_mat * refnormpersp, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 970e8c8b2a..fc182fc2e2 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -286,6 +286,7 @@ public: ANIMATED_CHILD = 0x01000000, ACTIVE_CHILD = 0x02000000, FOR_UNLOAD = 0x04000000, //should be unload from memory + MIRROR = 0x08000000, // Used as a mirror, needs a hero probe position to be calculated. } EDrawableFlags; public: diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 99ebcf5231..ad4d3d94e2 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -140,7 +140,7 @@ void LLReflectionMapManager::update() if (mMipChain.empty()) { - U32 res = mProbeResolution; + U32 res = mHeroProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -326,7 +326,7 @@ void LLReflectionMapManager::update() mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i, mProbeResolution, mTexture); + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); } mRealtimeRadiancePass = !mRealtimeRadiancePass; @@ -343,7 +343,7 @@ void LLReflectionMapManager::update() mRadiancePass = true; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray); + updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); } // restore "isRadiancePass" @@ -555,7 +555,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture); + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); if (++mUpdatingFace == 6) { @@ -582,14 +582,14 @@ void LLReflectionMapManager::doProbeUpdate() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray) +void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; LLRenderTarget* target = &mRenderTarget; - S32 sourceIdx = mReflectionProbeCount; + S32 sourceIdx = probeCount; if (probeResolution == mHeroProbeResolution) { @@ -1327,9 +1327,13 @@ void LLReflectionMapManager::initReflectionMaps() mHeroProbeResolution = 128; - mHeroArray = new LLCubeMapArray(); // Revise when we have both water and mirrors in hero probes. - mHeroArray->allocate(mHeroProbeResolution, 3, 2, true); + mHeroProbeCount = 1; + + mHeroArray = new LLCubeMapArray(); + + // We use an extra probe for scratch space on these. + mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); if (mHeroProbe.isNull()) { mHeroProbe = new LLReflectionMap(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 81b0ef8ed8..9f48ce3cfd 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -148,7 +148,7 @@ private: void doProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray); + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); // list of active reflection maps std::vector > mProbes; @@ -188,6 +188,8 @@ private: // number of reflection probes to use for rendering U32 mReflectionProbeCount; + + U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 4d49c61b23..fe33047218 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -257,6 +257,7 @@ public: virtual BOOL isRiggedMesh() const { return FALSE; } virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } + virtual BOOL isMirror() 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 diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 556ec083a7..254e945243 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1044,7 +1044,9 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) { updateReflectionProbePtr(); } - + + gPipeline.setMirror(mDrawable, isMirror()); + updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); @@ -3377,6 +3379,30 @@ F32 LLVOVolume::getLightCutoff() const } } +BOOL LLVOVolume::isMirror() const +{ + S32 faceCount = getNumFaces(); + + // Temporary hack to set the object to mirror. + for (int i = 0; i < faceCount; i++) + { + const LLTextureEntry* te = getTE(i); + + if (te->getMaterialParams().notNull()) + { + LLViewerTexture* specularp = getTESpecularMap(0); + + if (specularp && specularp->getID() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") + { + LL_INFOS() << "BELLADONNA OF SADNESS" << LL_ENDL; + return TRUE; + } + } + } + + return FALSE; +} + BOOL LLVOVolume::isReflectionProbe() const { return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -4427,6 +4453,8 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u } updateReflectionProbePtr(); + + gPipeline.setMirror(mDrawable, isMirror()); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 93aba9b8cb..cecf726763 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -308,6 +308,8 @@ public: F32 getReflectionProbeNearClip() const; bool getReflectionProbeIsBox() const; bool getReflectionProbeIsDynamic() const; + + BOOL isMirror() const override; // Flexible Objects U32 getVolumeInterfaceID() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d7188c0fe7..e742992c1d 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2761,6 +2761,23 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } +void LLPipeline::setMirror(LLDrawable *drawablep, bool is_mirror) +{ + if (drawablep && assertInitialized()) + { + if (is_mirror) + { + drawablep->setState(LLDrawable::MIRROR); + mMirrorList.insert(drawablep); + } + else + { + mMirrorList.erase(drawablep); + drawablep->clearState(LLDrawable::MIRROR); + } + } +} + void LLPipeline::shiftObjects(const LLVector3 &offset) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -5812,6 +5829,11 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { LL_INFOS() << "In mRetexturedList" << LL_ENDL; } + + if (std::find(mMirrorList.begin(), mMirrorList.end(), drawablep) != mMirrorList.end()) + { + LL_INFOS() << "In mMirrorList" << LL_ENDL; + } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index c0559ce83b..f3b35e0325 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -357,6 +357,7 @@ public: void shiftObjects(const LLVector3 &offset); void setLight(LLDrawable *drawablep, bool is_light); + void setMirror(LLDrawable *drawablep, bool is_mirror); bool hasRenderBatches(const U32 type) const; LLCullResult::drawinfo_iterator beginRenderMap(U32 type); @@ -818,6 +819,10 @@ protected: LLDrawable::ordered_drawable_set_t mLights; light_set_t mNearbyLights; // lights near camera LLColor4 mHWLightColors[8]; + + + LLDrawable::ordered_drawable_set_t mMirrorList; + LLDrawable* mNearestMirror; ///////////////////////////////////////////// // -- cgit v1.2.3 From 423820475c7201c39d03c0622dedbf4b1e8b1879 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 7 Aug 2023 00:17:04 -0700 Subject: Revert LLReflectionMapManager DRTVWR-583 --- indra/newview/CMakeLists.txt | 2 + indra/newview/llheroprobemanager.cpp | 1333 ++++++++++++++++++++++++++++++ indra/newview/llheroprobemanager.h | 208 +++++ indra/newview/llreflectionmapmanager.cpp | 168 +--- indra/newview/llreflectionmapmanager.h | 25 +- indra/newview/pipeline.cpp | 3 +- 6 files changed, 1594 insertions(+), 145 deletions(-) create mode 100644 indra/newview/llheroprobemanager.cpp create mode 100644 indra/newview/llheroprobemanager.h (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index c6d82ea260..7a57fe8fef 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -515,6 +515,7 @@ set(viewer_SOURCE_FILES llrecentpeople.cpp llreflectionmap.cpp llreflectionmapmanager.cpp + llheroprobemanager.cpp llregioninfomodel.cpp llregionposition.cpp llremoteparcelrequest.cpp @@ -1149,6 +1150,7 @@ set(viewer_HEADER_FILES llrecentpeople.h llreflectionmap.h llreflectionmapmanager.h + llheroprobemanager.h llregioninfomodel.h llregionposition.h llremoteparcelrequest.h diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp new file mode 100644 index 0000000000..54a61d000e --- /dev/null +++ b/indra/newview/llheroprobemanager.cpp @@ -0,0 +1,1333 @@ +/** + * @file LLHeroProbeManager.cpp + * @brief LLHeroProbeManager 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 "llviewerprecompiledheaders.h" + +#include "llheroprobemanager.h" +#include "llreflectionmapmanager.h" +#include "llviewercamera.h" +#include "llspatialpartition.h" +#include "llviewerregion.h" +#include "pipeline.h" +#include "llviewershadermgr.h" +#include "llviewercontrol.h" +#include "llenvironment.h" +#include "llstartup.h" + +extern BOOL gCubeSnapshot; +extern BOOL gTeleportDisplay; + +// get the next highest power of two of v (or v if v is already a power of two) +//defined in llvertexbuffer.cpp +extern U32 nhpo2(U32 v); + +static void touch_default_probe(LLReflectionMap* probe) +{ + if (LLViewerCamera::getInstance()) + { + LLVector3 origin = LLViewerCamera::getInstance()->getOrigin(); + origin.mV[2] += 64.f; + + probe->mOrigin.load3(origin.mV); + } +} + +LLHeroProbeManager::LLHeroProbeManager() +{ + initCubeFree(); +} + +void LLHeroProbeManager::initCubeFree() +{ + // start at 1 because index 0 is reserved for mDefaultProbe + for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) + { + mCubeFree.push_back(i); + } +} + +struct CompareProbeDistance +{ + LLReflectionMap* mDefaultProbe; + + bool operator()(const LLPointer& lhs, const LLPointer& rhs) + { + return lhs->mDistance < rhs->mDistance; + } +}; + +static F32 update_score(LLReflectionMap* p) +{ + return gFrameTimeSeconds - p->mLastUpdateTime - p->mDistance*0.1f; +} + +// return true if a is higher priority for an update than b +static bool check_priority(LLReflectionMap* a, LLReflectionMap* b) +{ + if (a->mCubeIndex == -1) + { // not a candidate for updating + return false; + } + else if (b->mCubeIndex == -1) + { // certainly higher priority than b + return true; + } + else if (!a->mComplete && !b->mComplete) + { //neither probe is complete, use distance + return a->mDistance < b->mDistance; + } + else if (a->mComplete && b->mComplete) + { //both probes are complete, use update_score metric + return update_score(a) > update_score(b); + } + + // one of these probes is not complete, if b is complete, a is higher priority + return b->mComplete; +} + +// helper class to seed octree with probes +void LLHeroProbeManager::update() +{ + if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + { + return; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(!gCubeSnapshot); // assert a snapshot is not in progress + if (LLAppViewer::instance()->logoutRequestSent()) + { + return; + } + + initReflectionMaps(); + + if (!mRenderTarget.isComplete()) + { + U32 color_fmt = GL_RGB16F; + U32 targetRes = mProbeResolution * 4; // super sample + mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + } + + if (!mHeroRenderTarget.isComplete()) + { + U32 color_fmt = GL_RGB16F; + U32 targetRes = mHeroProbeResolution * 2; + mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + } + + if (mMipChain.empty()) + { + U32 res = mHeroProbeResolution; + U32 count = log2((F32)res) + 0.5f; + + mMipChain.resize(count); + for (int i = 0; i < count; ++i) + { + mMipChain[i].allocate(res, res, GL_RGB16F); + res /= 2; + } + } + + llassert(mProbes[0] == mDefaultProbe); + + LLVector4a camera_pos; + camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); + + // process kill list + for (auto& probe : mKillList) + { + auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); + if (iter != mProbes.end()) + { + deleteProbe(iter - mProbes.begin()); + } + } + + mKillList.clear(); + + // process create list + for (auto& probe : mCreateList) + { + mProbes.push_back(probe); + } + + mCreateList.clear(); + + if (mProbes.empty()) + { + return; + } + + + bool did_update = false; + + static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); + static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + + bool realtime = sDetail >= (S32)LLHeroProbeManager::DetailLevel::REALTIME; + + LLReflectionMap* closestDynamic = nullptr; + + LLReflectionMap* oldestProbe = nullptr; + LLReflectionMap* oldestOccluded = nullptr; + + if (mUpdatingProbe != nullptr) + { + did_update = true; + doProbeUpdate(); + } + + // update distance to camera for all probes + std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance()); + llassert(mProbes[0] == mDefaultProbe); + llassert(mProbes[0]->mCubeArray == mTexture); + llassert(mProbes[0]->mCubeIndex == 0); + + // make sure we're assigning cube slots to the closest probes + + // first free any cube indices for distant probes + for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i) + { + LLReflectionMap* probe = mProbes[i]; + llassert(probe != nullptr); + + if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) + { // free this index + mCubeFree.push_back(probe->mCubeIndex); + + probe->mCubeArray = nullptr; + probe->mCubeIndex = -1; + probe->mComplete = false; + } + } + + // next distribute the free indices + U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size()); + + for (S32 i = 1; i < count && !mCubeFree.empty(); ++i) + { + // find the closest probe that needs a cube index + LLReflectionMap* probe = mProbes[i]; + + if (probe->mCubeIndex == -1) + { + S32 idx = allocateCubeIndex(); + llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices + probe->mCubeArray = mTexture; + probe->mCubeIndex = idx; + } + } + + for (int i = 0; i < mProbes.size(); ++i) + { + LLReflectionMap* probe = mProbes[i]; + if (probe->getNumRefs() == 1) + { // no references held outside manager, delete this probe + deleteProbe(i); + --i; + continue; + } + + if (probe != mDefaultProbe && !probe->isRelevant()) + { + continue; + } + + LLVector4a d; + + if (probe != mDefaultProbe) + { + if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to + { + probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV); + } + d.setSub(camera_pos, probe->mOrigin); + probe->mDistance = d.getLength3().getF32() - probe->mRadius; + } + else if (probe->mComplete) + { + // make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once) + probe->mDistance = 64.f; + } + else + { + probe->mDistance = -4096.f; //boost priority of default probe when it's not complete + } + + if (probe->mComplete) + { + probe->autoAdjustOrigin(); + probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); + } + if (probe->mOccluded && probe->mComplete) + { + if (oldestOccluded == nullptr) + { + oldestOccluded = probe; + } + else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime) + { + oldestOccluded = probe; + } + } + else + { + if (!did_update && + i < mReflectionProbeCount && + (oldestProbe == nullptr || + check_priority(probe, oldestProbe))) + { + oldestProbe = probe; + } + } + + if (realtime && + closestDynamic == nullptr && + probe->mCubeIndex != -1 && + probe->getIsDynamic()) + { + closestDynamic = probe; + } + } + + if (realtime && closestDynamic != nullptr) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + // update the closest dynamic probe realtime + // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames + closestDynamic->autoAdjustOrigin(); + + // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set + // lighting values etc + bool radiance_pass = isRadiancePass(); + mRadiancePass = mRealtimeRadiancePass; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + } + mRealtimeRadiancePass = !mRealtimeRadiancePass; + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } + + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); + + mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + bool radiance_pass = isRadiancePass(); + mRadiancePass = true; + for (U32 i = 0; i < 6; ++i) + { + updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); + } + + // restore "isRadiancePass" + mRadiancePass = radiance_pass; + } + + static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); + if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) + { + if (sLevel == 0) + { // when probes are disabled don't update the default probe more often than the prescribed update period + oldestProbe = nullptr; + } + } + else if (sLevel > 0) + { // when probes are enabled don't update the default probe less often than the prescribed update period + oldestProbe = mDefaultProbe; + } + + // switch to updating the next oldest probe + if (!did_update && oldestProbe != nullptr) + { + LLReflectionMap* probe = oldestProbe; + llassert(probe->mCubeIndex != -1); + + probe->autoAdjustOrigin(); + + mUpdatingProbe = probe; + doProbeUpdate(); + } + + if (oldestOccluded) + { + // as far as this occluded probe is concerned, an origin/radius update is as good as a full update + oldestOccluded->autoAdjustOrigin(); + oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; + } +} + +LLReflectionMap* LLHeroProbeManager::addProbe(LLSpatialGroup* group) +{ + LLReflectionMap* probe = new LLReflectionMap(); + probe->mGroup = group; + + if (mDefaultProbe.isNull()) + { //safety check to make sure default probe is always first probe added + mDefaultProbe = new LLReflectionMap(); + mProbes.push_back(mDefaultProbe); + } + + llassert(mProbes[0] == mDefaultProbe); + + if (group) + { + probe->mOrigin = group->getOctreeNode()->getCenter(); + } + + if (gCubeSnapshot) + { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update + mCreateList.push_back(probe); + } + else + { + mProbes.push_back(probe); + } + + return probe; +} + +struct CompareProbeDepth +{ + bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) + { + return lhs->mMinDepth < rhs->mMinDepth; + } +}; + +void LLHeroProbeManager::getReflectionMaps(std::vector& maps) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + LLVector4a oa; // scratch space for transformed origin + + U32 count = 0; + U32 lastIdx = 0; + for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i) + { + mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested + if (mProbes[i]->mCubeIndex != -1) + { + if (!mProbes[i]->mOccluded && mProbes[i]->mComplete) + { + maps[count++] = mProbes[i]; + modelview.affineTransform(mProbes[i]->mOrigin, oa); + mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius; + mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius; + } + } + else + { + mProbes[i]->mProbeIndex = -1; + } + lastIdx = i; + } + + // set remaining probe indices to -1 + for (U32 i = lastIdx+1; i < mProbes.size(); ++i) + { + mProbes[i]->mProbeIndex = -1; + } + + if (count > 1) + { + std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth()); + } + + for (U32 i = 0; i < count; ++i) + { + maps[i]->mProbeIndex = i; + } + + // null terminate list + if (count < maps.size()) + { + maps[count] = nullptr; + } +} + +LLReflectionMap* LLHeroProbeManager::registerSpatialGroup(LLSpatialGroup* group) +{ + if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) + { + OctreeNode* node = group->getOctreeNode(); + F32 size = node->getSize().getF32ptr()[0]; + if (size >= 15.f && size <= 17.f) + { + return addProbe(group); + } + } + + return nullptr; +} + +LLReflectionMap* LLHeroProbeManager::registerViewerObject(LLViewerObject* vobj) +{ + llassert(vobj != nullptr); + + LLReflectionMap* probe = new LLReflectionMap(); + probe->mViewerObject = vobj; + probe->mOrigin.load3(vobj->getPositionAgent().mV); + + if (gCubeSnapshot) + { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update + mCreateList.push_back(probe); + } + else + { + mProbes.push_back(probe); + } + + return probe; +} + +S32 LLHeroProbeManager::allocateCubeIndex() +{ + if (!mCubeFree.empty()) + { + S32 ret = mCubeFree.front(); + mCubeFree.pop_front(); + return ret; + } + + return -1; +} + +void LLHeroProbeManager::deleteProbe(U32 i) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + LLReflectionMap* probe = mProbes[i]; + + llassert(probe != mDefaultProbe); + + if (probe->mCubeIndex != -1) + { // mark the cube index used by this probe as being free + mCubeFree.push_back(probe->mCubeIndex); + } + if (mUpdatingProbe == probe) + { + mUpdatingProbe = nullptr; + mUpdatingFace = 0; + } + + // remove from any Neighbors lists + for (auto& other : probe->mNeighbors) + { + auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); + llassert(iter != other->mNeighbors.end()); + other->mNeighbors.erase(iter); + } + + mProbes.erase(mProbes.begin() + i); +} + + +void LLHeroProbeManager::doProbeUpdate() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + llassert(mUpdatingProbe != nullptr); + + updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + + if (++mUpdatingFace == 6) + { + updateNeighbors(mUpdatingProbe); + mUpdatingFace = 0; + if (isRadiancePass()) + { + mUpdatingProbe->mComplete = true; + mUpdatingProbe = nullptr; + mRadiancePass = false; + } + else + { + mRadiancePass = true; + } + } +} + +// Do the reflection map update render passes. +// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// a simple mip chain (not convolution filter). +// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe +// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. +// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. +// In effect this simulates single-bounce lighting. +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +{ + // hacky hot-swap of camera specific render targets + gPipeline.mRT = &gPipeline.mAuxillaryRT; + + LLRenderTarget* target = &mRenderTarget; + + S32 sourceIdx = probeCount; + + if (probeResolution == mHeroProbeResolution) + { + sourceIdx = 0; + target = &mHeroRenderTarget; + } + + mLightScale = 1.f; + static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); + if (!isRadiancePass() && probe->getAmbiance() > max_local_light_ambiance) + { + mLightScale = max_local_light_ambiance / probe->getAmbiance(); + } + + if (probe == mDefaultProbe) + { + touch_default_probe(probe); + + gPipeline.pushRenderTypeMask(); + + //only render sky, water, terrain, and clouds + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); + + probe->update(target->getWidth(), face); + + gPipeline.popRenderTypeMask(); + } + else + { + probe->update(target->getWidth(), face); + } + + gPipeline.mRT = &gPipeline.mMainRT; + + if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel + sourceIdx += 1; + } + + gGL.setColorMask(true, true); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + + // downsample to placeholder map + { + gGL.matrixMode(gGL.MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + + gGL.matrixMode(gGL.MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + gGL.flush(); + U32 res = probeResolution * 2; + + static LLStaticHashedString resScale("resScale"); + static LLStaticHashedString direction("direction"); + static LLStaticHashedString znear("znear"); + static LLStaticHashedString zfar("zfar"); + + LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen; + + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + target->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + target->flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(target); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + } + + + S32 mips = log2((F32)probeResolution) + 0.5f; + + gReflectionMipProgram.bind(); + S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + for (int i = 0; i < mMipChain.size(); ++i) + { + LL_PROFILE_GPU_ZONE("probe mip"); + mMipChain[i].bindTarget(); + if (i == 0) + { + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + } + else + { + gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1])); + } + + + gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + res /= 2; + + S32 mip = i - (mMipChain.size() - mips); + + if (mip >= 0) + { + LL_PROFILE_GPU_ZONE("probe mip copy"); + cubeArray->bind(0); + + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); + + cubeArray->unbind(); + } + mMipChain[i].flush(); + } + + gGL.popMatrix(); + gGL.matrixMode(gGL.MM_MODELVIEW); + gGL.popMatrix(); + + gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE); + gReflectionMipProgram.unbind(); + } + + if (face == 5) + { + mMipChain[0].bindTarget(); + static LLStaticHashedString sSourceIdx("sourceIdx"); + + if (isRadiancePass()) + { + //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + gRadianceGenProgram.bind(); + mVertexBuffer->setBuffer(); + + S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + cubeArray->bind(channel); + gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + + U32 res = mMipChain[0].getWidth(); + + for (int i = 0; i < mMipChain.size(); ++i) + { + LL_PROFILE_GPU_ZONE("probe radiance gen"); + static LLStaticHashedString sMipLevel("mipLevel"); + static LLStaticHashedString sRoughness("roughness"); + static LLStaticHashedString sWidth("u_width"); + + gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); + gRadianceGenProgram.uniform1f(sMipLevel, i); + gRadianceGenProgram.uniform1i(sWidth, probeResolution); + + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + } + + if (i != mMipChain.size() - 1) + { + res /= 2; + glViewport(0, 0, res, res); + } + } + + gRadianceGenProgram.unbind(); + } + else + { + //generate irradiance map + gIrradianceGenProgram.bind(); + S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + cubeArray->bind(channel); + + gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + + mVertexBuffer->setBuffer(); + int start_mip = 0; + // find the mip target to start with based on irradiance map resolution + for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) + { + if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) + { + break; + } + } + + //for (int i = start_mip; i < mMipChain.size(); ++i) + { + int i = start_mip; + LL_PROFILE_GPU_ZONE("probe irradiance gen"); + glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); + for (int cf = 0; cf < 6; ++cf) + { // for each cube face + LLCoordFrame frame; + frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); + + F32 mat[16]; + frame.getOpenGLRotation(mat); + gGL.loadMatrix(mat); + + mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); + + S32 res = mMipChain[i].getWidth(); + mIrradianceMaps->bind(channel); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); + cubeArray->bind(channel); + } + } + } + + mMipChain[0].flush(); + + gIrradianceGenProgram.unbind(); + } +} + +void LLHeroProbeManager::reset() +{ + mReset = true; +} + +void LLHeroProbeManager::shift(const LLVector4a& offset) +{ + for (auto& probe : mProbes) + { + probe->mOrigin.add(offset); + } +} + +void LLHeroProbeManager::updateNeighbors(LLReflectionMap* probe) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + if (mDefaultProbe == probe) + { + return; + } + + //remove from existing neighbors + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear"); + + for (auto& other : probe->mNeighbors) + { + auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); + llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly + other->mNeighbors.erase(iter); + } + + probe->mNeighbors.clear(); + } + + // search for new neighbors + if (probe->isRelevant()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search"); + for (auto& other : mProbes) + { + if (other != mDefaultProbe && other != probe) + { + if (other->isRelevant() && probe->intersects(other)) + { + probe->mNeighbors.push_back(other); + other->mNeighbors.push_back(probe); + } + } + } + } +} + +void LLHeroProbeManager::updateUniforms() +{ + if (!LLPipeline::sReflectionProbesEnabled) + { + return; + } + + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + + // structure for packing uniform buffer object + // see class3/deferred/reflectionProbeF.glsl + struct ReflectionProbeData + { + // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of + // the box probe + LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; + + // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; + + // extra parameters + // x - irradiance scale + // y - radiance scale + // z - fade in + // w - znear + LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; + + // indices used by probe: + // [i][0] - cubemap array index for this probe + // [i][1] - index into "refNeighbor" for probes that intersect this probe + // [i][2] - number of probes that intersect this probe, or -1 for no neighbors + // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; + + // list of neighbor indices + GLint refNeighbor[4096]; + + GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth + // numbrer of active refmaps + GLint refmapCount; + }; + + mReflectionMaps.resize(mReflectionProbeCount); + getReflectionMaps(mReflectionMaps); + + ReflectionProbeData rpd; + + F32 minDepth[256]; + + for (int i = 0; i < 256; ++i) + { + rpd.refBucket[i][0] = mReflectionProbeCount; + rpd.refBucket[i][1] = mReflectionProbeCount; + rpd.refBucket[i][2] = mReflectionProbeCount; + rpd.refBucket[i][3] = mReflectionProbeCount; + minDepth[i] = FLT_MAX; + } + + // load modelview matrix into matrix 4a + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + LLVector4a oa; // scratch space for transformed origin + + S32 count = 0; + U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors + + LLEnvironment& environment = LLEnvironment::instance(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + + static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); + static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); + F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, should_auto_adjust); + + bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); + F32 ambscale = is_ambiance_pass ? 0.f : 1.f; + F32 radscale = is_ambiance_pass ? 0.5f : 1.f; + + for (auto* refmap : mReflectionMaps) + { + if (refmap == nullptr) + { + break; + } + + if (refmap != mDefaultProbe) + { + // bucket search data + // theory of operation: + // 1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps) + // 2. Sort by minimum depth + // 3. Prepare a bucket for each 1m of depth out to 256m + // 4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket + // 5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence + // the current pixel. + int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255); + int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255); + for (U32 i = depth_min; i <= depth_max; ++i) + { + if (refmap->mMinDepth < minDepth[i]) + { + minDepth[i] = refmap->mMinDepth; + rpd.refBucket[i][0] = refmap->mProbeIndex; + } + } + } + + llassert(refmap->mProbeIndex == count); + llassert(mReflectionMaps[refmap->mProbeIndex] == refmap); + + llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged + + { + if (refmap->mViewerObject) + { // have active manual probes live-track the object they're associated with + refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV); + refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; + + } + modelview.affineTransform(refmap->mOrigin, oa); + rpd.refSphere[count].set(oa.getF32ptr()); + rpd.refSphere[count].mV[3] = refmap->mRadius; + } + + rpd.refIndex[count][0] = refmap->mCubeIndex; + llassert(nc % 4 == 0); + rpd.refIndex[count][1] = nc / 4; + rpd.refIndex[count][3] = refmap->mPriority; + + // for objects that are reflection probes, use the volume as the influence volume of the probe + // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres + if (refmap->getBox(rpd.refBox[count])) + { // negate priority to indicate this probe has a box influence volume + rpd.refIndex[count][3] = -rpd.refIndex[count][3]; + } + + rpd.refParams[count].set( + llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale + radscale, // radiance scale + refmap->mFadeIn, // fade in weight + oa.getF32ptr()[2] - refmap->mRadius); // z near + + 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"); + //pack neghbor list + const U32 max_neighbors = 64; + U32 neighbor_count = 0; + + for (auto& neighbor : refmap->mNeighbors) + { + if (ni >= 4096) + { // out of space + break; + } + + GLint idx = neighbor->mProbeIndex; + if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1) + { + continue; + } + + // this neighbor may be sampled + rpd.refNeighbor[ni++] = idx; + + neighbor_count++; + if (neighbor_count >= max_neighbors) + { + break; + } + } + } + + if (nc == ni) + { + //no neighbors, tag as empty + rpd.refIndex[count][1] = -1; + } + else + { + rpd.refIndex[count][2] = ni - nc; + + // move the cursor forward + nc = ni; + if (nc % 4 != 0) + { // jump to next power of 4 for compatibility with ivec4 + nc += 4 - (nc % 4); + } + } + + + count++; + } + +#if 0 + { + // fill in gaps in refBucket + S32 probe_idx = mReflectionProbeCount; + + for (int i = 0; i < 256; ++i) + { + if (i < count) + { // for debugging, store depth of mReflectionsMaps[i] + rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10); + } + + if (rpd.refBucket[i][0] == mReflectionProbeCount) + { + rpd.refBucket[i][0] = probe_idx; + } + else + { + probe_idx = rpd.refBucket[i][0]; + } + } + } +#endif + + rpd.refmapCount = count; + + //copy rpd into uniform buffer object + if (mUBO == 0) + { + glGenBuffers(1, &mUBO); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); + glBindBuffer(GL_UNIFORM_BUFFER, mUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + struct HeroProbeData + { + LLVector4 heroPosition[1]; + GLint heroProbeCount = 1; + }; + + HeroProbeData hpd; + + modelview.loadu(gGLModelView); + + oa.set(0, 0, 0, 0); + hpd.heroProbeCount = 1; + modelview.affineTransform(mHeroProbe->mOrigin, oa); + hpd.heroPosition[0].set(oa.getF32ptr()); + + //copy rpd into uniform buffer object + if (mUBO == 0) + { + glGenBuffers(1, &mHeroUBO); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); + glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); + glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + +#if 0 + if (!gCubeSnapshot) + { + for (auto& probe : mProbes) + { + LLViewerObject* vobj = probe->mViewerObject; + if (vobj) + { + F32 time = (F32)gFrameTimeSeconds - probe->mLastUpdateTime; + vobj->setDebugText(llformat("%d/%d/%d/%.1f - %.1f/%.1f", probe->mCubeIndex, probe->mProbeIndex, (U32) probe->mNeighbors.size(), probe->mMinDepth, probe->mMaxDepth, time), time > 1.f ? LLColor4::white : LLColor4::green); + } + } + } +#endif +} + +void LLHeroProbeManager::setUniforms() +{ + if (!LLPipeline::sReflectionProbesEnabled) + { + return; + } + + if (mUBO == 0) + { + updateUniforms(); + } + glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); +} + +void LLHeroProbeManager::renderDebug() +{ + gDebugProgram.bind(); + + for (auto& probe : mProbes) + { + renderReflectionProbe(probe); + } + + gDebugProgram.unbind(); +} + +void LLHeroProbeManager::initReflectionMaps() +{ + U32 count = LL_MAX_REFLECTION_PROBE_COUNT; + + if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) + { + mReset = false; + mReflectionProbeCount = count; + mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); + mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 + + mTexture = new LLCubeMapArray(); + + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); + + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); + + // reset probe state + mUpdatingFace = 0; + mUpdatingProbe = nullptr; + mRadiancePass = false; + mRealtimeRadiancePass = false; + + for (auto& probe : mProbes) + { + probe->mLastUpdateTime = 0.f; + probe->mComplete = false; + probe->mProbeIndex = -1; + probe->mCubeArray = nullptr; + probe->mCubeIndex = -1; + probe->mNeighbors.clear(); + } + + mCubeFree.clear(); + initCubeFree(); + + if (mDefaultProbe.isNull()) + { + llassert(mProbes.empty()); // default probe MUST be the first probe created + mDefaultProbe = new LLReflectionMap(); + mProbes.push_back(mDefaultProbe); + } + + llassert(mProbes[0] == mDefaultProbe); + + mDefaultProbe->mCubeIndex = 0; + mDefaultProbe->mCubeArray = mTexture; + mDefaultProbe->mDistance = 64.f; + mDefaultProbe->mRadius = 4096.f; + mDefaultProbe->mProbeIndex = 0; + touch_default_probe(mDefaultProbe); + + mHeroProbeResolution = 128; + + // Revise when we have both water and mirrors in hero probes. + mHeroProbeCount = 1; + + mHeroArray = new LLCubeMapArray(); + + // We use an extra probe for scratch space on these. + mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); + + if (mHeroProbe.isNull()) { + mHeroProbe = new LLReflectionMap(); + } + + mHeroProbe->mCubeIndex = 0; + mHeroProbe->mCubeArray = mHeroArray; + mHeroProbe->mDistance = 64.f; + mHeroProbe->mRadius = 4096.f; + mHeroProbe->mProbeIndex = 0; + touch_default_probe(mHeroProbe); + + } + + if (mVertexBuffer.isNull()) + { + U32 mask = LLVertexBuffer::MAP_VERTEX; + LLPointer buff = new LLVertexBuffer(mask); + buff->allocateBuffer(4, 0); + + LLStrider v; + + buff->getVertexStrider(v); + + v[0] = LLVector3(-1, -1, -1); + v[1] = LLVector3(1, -1, -1); + v[2] = LLVector3(-1, 1, -1); + v[3] = LLVector3(1, 1, -1); + + buff->unmapBuffer(); + + mVertexBuffer = buff; + } +} + +void LLHeroProbeManager::cleanup() +{ + mVertexBuffer = nullptr; + mRenderTarget.release(); + mHeroRenderTarget.release(); + + mMipChain.clear(); + + mTexture = nullptr; + mIrradianceMaps = nullptr; + mHeroArray = nullptr; + + mProbes.clear(); + mKillList.clear(); + mCreateList.clear(); + + mReflectionMaps.clear(); + mUpdatingFace = 0; + + mDefaultProbe = nullptr; + mUpdatingProbe = nullptr; + + mHeroProbe = nullptr; + + glDeleteBuffers(1, &mUBO); + mUBO = 0; + + glDeleteBuffers(1, &mHeroUBO); + mHeroUBO = 0; + + // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state + initCubeFree(); +} + +void LLHeroProbeManager::doOcclusion() +{ + LLVector4a eye; + eye.load3(LLViewerCamera::instance().getOrigin().mV); + + for (auto& probe : mProbes) + { + if (probe != nullptr && probe != mDefaultProbe) + { + probe->doOcclusion(eye); + } + } +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h new file mode 100644 index 0000000000..be761a680e --- /dev/null +++ b/indra/newview/llheroprobemanager.h @@ -0,0 +1,208 @@ +/** + * @file llheroprobemanager.h + * @brief LLHeroProbeManager class declaration + * + * $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$ + */ + +#pragma once + +#include "llreflectionmap.h" +#include "llrendertarget.h" +#include "llcubemaparray.h" +#include "llcubemap.h" + +class LLSpatialGroup; +class LLViewerObject; + +// number of reflection probes to keep in vram +#define LL_MAX_REFLECTION_PROBE_COUNT 256 + +// reflection probe resolution +#define LL_IRRADIANCE_MAP_RESOLUTION 64 + +// reflection probe mininum scale +#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; + +class alignas(16) LLHeroProbeManager +{ + LL_ALIGN_NEW +public: + enum class DetailLevel + { + STATIC_ONLY = 0, + STATIC_AND_DYNAMIC, + REALTIME = 2 + }; + + // allocate an environment map of the given resolution + LLHeroProbeManager(); + + // release any GL state + void cleanup(); + + // maintain reflection probes + void update(); + + // add a probe for the given spatial group + LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr); + + // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size() + // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr. + // maps -- presized array of Reflection Map pointers + void getReflectionMaps(std::vector& maps); + + // called by LLSpatialGroup constructor + // If spatial group should receive a Reflection Probe, will create one for the specified spatial group + LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group); + + // presently hacked into LLViewerObject::setTE + // Used by LLViewerObjects that are Reflection Probes + // vobj must not be null + // Guaranteed to not return null + LLReflectionMap* registerViewerObject(LLViewerObject* vobj); + + // reset all state on the next update + void reset(); + + // called on region crossing to "shift" probes into new coordinate frame + void shift(const LLVector4a& offset); + + // debug display, called from llspatialpartition if reflection + // probe debug display is active + void renderDebug(); + + // call once at startup to allocate cubemap arrays + void initReflectionMaps(); + + // True if currently updating a radiance map, false if currently updating an irradiance map + bool isRadiancePass() { return mRadiancePass; } + + // perform occlusion culling on all active reflection probes + void doOcclusion(); + +private: + friend class LLPipeline; + + // initialize mCubeFree array to default values + void initCubeFree(); + + // delete the probe with the given index in mProbes + void deleteProbe(U32 i); + + // get a free cube index + // returns -1 if allocation failed + S32 allocateCubeIndex(); + + // update the neighbors of the given probe + void updateNeighbors(LLReflectionMap* probe); + + // update UBO used for rendering (call only once per render pipe flush) + void updateUniforms(); + + // bind UBO used for rendering + void setUniforms(); + + // render target for cube snapshots + // used to generate mipmaps without doing a copy-to-texture + LLRenderTarget mRenderTarget; + + LLRenderTarget mHeroRenderTarget; + + std::vector mMipChain; + + // storage for reflection probe radiance maps (plus two scratch space cubemaps) + LLPointer mTexture; + + LLPointer mHeroArray; + + // vertex buffer for pushing verts to filter shaders + LLPointer mVertexBuffer; + + // storage for reflection probe irradiance maps + LLPointer mIrradianceMaps; + + // list of free cubemap indices + std::list mCubeFree; + + // perform an update on the currently updating Probe + void doProbeUpdate(); + + // update the specified face of the specified probe + void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + + // list of active reflection maps + std::vector > mProbes; + + // list of reflection maps to kill + std::vector > mKillList; + + // list of reflection maps to create + std::vector > mCreateList; + + // handle to UBO + U32 mUBO = 0; + + // Hero UBO + U32 mHeroUBO = 0; + + // list of maps being used for rendering + std::vector mReflectionMaps; + + LLReflectionMap* mUpdatingProbe = nullptr; + U32 mUpdatingFace = 0; + + // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. + // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, + // then generate the radiance map from a render of the world that includes irradiance. + // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. + bool mRadiancePass = false; + + // same as above, but for the realtime probe. + // Realtime probes should update all six sides of the irradiance map on "odd" frames and all six sides of the + // radiance map on "even" frames. + bool mRealtimeRadiancePass = false; + + LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) + + LLPointer mHeroProbe; + + // number of reflection probes to use for rendering + U32 mReflectionProbeCount; + + U32 mHeroProbeCount; + + // resolution of reflection probes + U32 mProbeResolution = 128; + + U32 mHeroProbeResolution = 512; + + // maximum LoD of reflection probes (mip levels - 1) + F32 mMaxProbeLOD = 6.f; + + // amount to scale local lights during an irradiance map update (set during updateProbeFace and used by LLPipeline) + F32 mLightScale = 1.f; + + // if true, reset all probe render state on the next update (for teleports and sky changes) + bool mReset = false; +}; + diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index ad4d3d94e2..e855be8fbd 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -130,17 +130,10 @@ void LLReflectionMapManager::update() U32 targetRes = mProbeResolution * 4; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } - - if (!mHeroRenderTarget.isComplete()) - { - U32 color_fmt = GL_RGB16F; - U32 targetRes = mHeroProbeResolution * 2; - mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); - } if (mMipChain.empty()) { - U32 res = mHeroProbeResolution; + U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -304,8 +297,8 @@ void LLReflectionMapManager::update() } } - if (realtime && - closestDynamic == nullptr && + if (realtime && + closestDynamic == nullptr && probe->mCubeIndex != -1 && probe->getIsDynamic()) { @@ -320,35 +313,19 @@ void LLReflectionMapManager::update() // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames closestDynamic->autoAdjustOrigin(); - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set + // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set // lighting values etc bool radiance_pass = isRadiancePass(); mRadiancePass = mRealtimeRadiancePass; for (U32 i = 0; i < 6; ++i) { - updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + updateProbeFace(closestDynamic, i); } mRealtimeRadiancePass = !mRealtimeRadiancePass; // restore "isRadiancePass" mRadiancePass = radiance_pass; } - - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - - mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); - bool radiance_pass = isRadiancePass(); - mRadiancePass = true; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); - } - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) @@ -555,7 +532,7 @@ void LLReflectionMapManager::doProbeUpdate() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(mUpdatingProbe != nullptr); - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); + updateProbeFace(mUpdatingProbe, mUpdatingFace); if (++mUpdatingFace == 6) { @@ -576,26 +553,16 @@ void LLReflectionMapManager::doProbeUpdate() // Do the reflection map update render passes. // For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated -// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate // a simple mip chain (not convolution filter). // At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - - LLRenderTarget* target = &mRenderTarget; - - S32 sourceIdx = probeCount; - - if (probeResolution == mHeroProbeResolution) - { - sourceIdx = 0; - target = &mHeroRenderTarget; - } mLightScale = 1.f; static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); @@ -614,18 +581,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); - probe->update(target->getWidth(), face); + probe->update(mRenderTarget.getWidth(), face); gPipeline.popRenderTypeMask(); } else { - probe->update(target->getWidth(), face); + probe->update(mRenderTarget.getWidth(), face); } gPipeline.mRT = &gPipeline.mMainRT; - if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) + S32 sourceIdx = mReflectionProbeCount; + + if (probe != mUpdatingProbe) { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel sourceIdx += 1; } @@ -646,7 +615,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gGL.loadIdentity(); gGL.flush(); - U32 res = probeResolution * 2; + U32 res = mProbeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -658,20 +627,20 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal gGaussianProgram.uniform2f(direction, 1.f, 0.f); gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - target->bindTarget(); + mRenderTarget.bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - target->flush(); + mRenderTarget.flush(); // vertical gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(target); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); screen_rt->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -679,7 +648,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U } - S32 mips = log2((F32)probeResolution) + 0.5f; + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -698,7 +667,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U } - gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -710,11 +679,14 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - cubeArray->bind(0); - + mTexture->bind(0); + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - - cubeArray->unbind(); + //if (i == 0) + //{ + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + //} + mTexture->unbind(); } mMipChain[i].flush(); } @@ -739,7 +711,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); + mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -754,7 +726,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, probeResolution); + gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -784,7 +756,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U //generate irradiance map gIrradianceGenProgram.bind(); S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); + mTexture->bind(channel); gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -819,7 +791,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face, U S32 res = mMipChain[i].getWidth(); mIrradianceMaps->bind(channel); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - cubeArray->bind(channel); + mTexture->bind(channel); } } } @@ -896,14 +868,14 @@ void LLReflectionMapManager::updateUniforms() // see class3/deferred/reflectionProbeF.glsl struct ReflectionProbeData { - // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of + // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of // the box probe - LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; + LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space - LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; + LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; - // extra parameters + // extra parameters // x - irradiance scale // y - radiance scale // z - fade in @@ -915,10 +887,10 @@ void LLReflectionMapManager::updateUniforms() // [i][1] - index into "refNeighbor" for probes that intersect this probe // [i][2] - number of probes that intersect this probe, or -1 for no neighbors // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) - GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; + GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; // list of neighbor indices - GLint refNeighbor[4096]; + GLint refNeighbor[4096]; GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth // numbrer of active refmaps @@ -1101,7 +1073,7 @@ void LLReflectionMapManager::updateUniforms() #endif rpd.refmapCount = count; - + //copy rpd into uniform buffer object if (mUBO == 0) { @@ -1114,35 +1086,7 @@ void LLReflectionMapManager::updateUniforms() glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - - struct HeroProbeData - { - LLVector4 heroPosition[1]; - GLint heroProbeCount = 1; - }; - - HeroProbeData hpd; - - modelview.loadu(gGLModelView); - - oa.set(0, 0, 0, 0); - hpd.heroProbeCount = 1; - modelview.affineTransform(mHeroProbe->mOrigin, oa); - hpd.heroPosition[0].set(oa.getF32ptr()); - //copy rpd into uniform buffer object - if (mUBO == 0) - { - glGenBuffers(1, &mHeroUBO); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - #if 0 if (!gCubeSnapshot) { @@ -1167,7 +1111,7 @@ void LLReflectionMapManager::setUniforms() } if (mUBO == 0) - { + { updateUniforms(); } glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); @@ -1275,7 +1219,7 @@ void LLReflectionMapManager::initReflectionMaps() { U32 count = LL_MAX_REFLECTION_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) + if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { mReset = false; mReflectionProbeCount = count; @@ -1324,27 +1268,6 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - - mHeroProbeResolution = 128; - - // Revise when we have both water and mirrors in hero probes. - mHeroProbeCount = 1; - - mHeroArray = new LLCubeMapArray(); - - // We use an extra probe for scratch space on these. - mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); - - if (mHeroProbe.isNull()) { - mHeroProbe = new LLReflectionMap(); - } - - mHeroProbe->mCubeIndex = 0; - mHeroProbe->mCubeArray = mHeroArray; - mHeroProbe->mDistance = 64.f; - mHeroProbe->mRadius = 4096.f; - mHeroProbe->mProbeIndex = 0; - touch_default_probe(mHeroProbe); } @@ -1369,17 +1292,15 @@ void LLReflectionMapManager::initReflectionMaps() } } -void LLReflectionMapManager::cleanup() -{ +void LLReflectionMapManager::cleanup() +{ mVertexBuffer = nullptr; mRenderTarget.release(); - mHeroRenderTarget.release(); mMipChain.clear(); mTexture = nullptr; mIrradianceMaps = nullptr; - mHeroArray = nullptr; mProbes.clear(); mKillList.clear(); @@ -1390,14 +1311,9 @@ void LLReflectionMapManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - mHeroProbe = nullptr; glDeleteBuffers(1, &mUBO); mUBO = 0; - - glDeleteBuffers(1, &mHeroUBO); - mHeroUBO = 0; // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state initCubeFree(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 9f48ce3cfd..7b17112814 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -43,21 +43,23 @@ class LLViewerObject; // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; +void renderReflectionProbe(LLReflectionMap* probe); + class alignas(16) LLReflectionMapManager { LL_ALIGN_NEW public: - enum class DetailLevel + enum class DetailLevel { STATIC_ONLY = 0, STATIC_AND_DYNAMIC, REALTIME = 2 }; - // allocate an environment map of the given resolution + // allocate an environment map of the given resolution LLReflectionMapManager(); - // release any GL state + // release any GL state void cleanup(); // maintain reflection probes @@ -113,7 +115,7 @@ private: // returns -1 if allocation failed S32 allocateCubeIndex(); - // update the neighbors of the given probe + // update the neighbors of the given probe void updateNeighbors(LLReflectionMap* probe); // update UBO used for rendering (call only once per render pipe flush) @@ -125,15 +127,11 @@ private: // render target for cube snapshots // used to generate mipmaps without doing a copy-to-texture LLRenderTarget mRenderTarget; - - LLRenderTarget mHeroRenderTarget; std::vector mMipChain; // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; - - LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -148,7 +146,7 @@ private: void doProbeUpdate(); // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + void updateProbeFace(LLReflectionMap* probe, U32 face); // list of active reflection maps std::vector > mProbes; @@ -161,9 +159,6 @@ private: // handle to UBO U32 mUBO = 0; - - // Hero UBO - U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; @@ -183,18 +178,12 @@ private: bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) - - LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; - - U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; - - U32 mHeroProbeResolution = 512; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e742992c1d..909c0f9aaa 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8461,13 +8461,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } - + /* channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) { mReflectionMapManager.mHeroArray->bind(channel); bound = true; } + */ if (bound) { -- cgit v1.2.3 From d5845fe3e7f3a620453f00421608211d6353905f Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 18 Aug 2023 21:47:40 -0700 Subject: Latest updates to the hero probe manager. DRTVWR-583 --- indra/newview/llappviewer.cpp | 1 + indra/newview/llheroprobemanager.cpp | 923 ++--------------------------------- indra/newview/llheroprobemanager.h | 87 +--- indra/newview/pipeline.cpp | 31 +- indra/newview/pipeline.h | 2 + 5 files changed, 75 insertions(+), 969 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 343778fe03..3b0ba77ea2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1517,6 +1517,7 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot"); pingMainloopTimeout("Main:Snapshot"); gPipeline.mReflectionMapManager.update(); + gPipeline.mHeroProbeManager.update(); LLFloaterSnapshot::update(); // take snapshots LLFloaterSimpleOutfitSnapshot::update(); gGLActive = FALSE; diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 54a61d000e..5edf819fff 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -57,55 +57,6 @@ static void touch_default_probe(LLReflectionMap* probe) LLHeroProbeManager::LLHeroProbeManager() { - initCubeFree(); -} - -void LLHeroProbeManager::initCubeFree() -{ - // start at 1 because index 0 is reserved for mDefaultProbe - for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) - { - mCubeFree.push_back(i); - } -} - -struct CompareProbeDistance -{ - LLReflectionMap* mDefaultProbe; - - bool operator()(const LLPointer& lhs, const LLPointer& rhs) - { - return lhs->mDistance < rhs->mDistance; - } -}; - -static F32 update_score(LLReflectionMap* p) -{ - return gFrameTimeSeconds - p->mLastUpdateTime - p->mDistance*0.1f; -} - -// return true if a is higher priority for an update than b -static bool check_priority(LLReflectionMap* a, LLReflectionMap* b) -{ - if (a->mCubeIndex == -1) - { // not a candidate for updating - return false; - } - else if (b->mCubeIndex == -1) - { // certainly higher priority than b - return true; - } - else if (!a->mComplete && !b->mComplete) - { //neither probe is complete, use distance - return a->mDistance < b->mDistance; - } - else if (a->mComplete && b->mComplete) - { //both probes are complete, use update_score metric - return update_score(a) > update_score(b); - } - - // one of these probes is not complete, if b is complete, a is higher priority - return b->mComplete; } // helper class to seed octree with probes @@ -131,17 +82,10 @@ void LLHeroProbeManager::update() U32 targetRes = mProbeResolution * 4; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } - - if (!mHeroRenderTarget.isComplete()) - { - U32 color_fmt = GL_RGB16F; - U32 targetRes = mHeroProbeResolution * 2; - mHeroRenderTarget.allocate(targetRes, targetRes, color_fmt, true); - } if (mMipChain.empty()) { - U32 res = mHeroProbeResolution; + U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; mMipChain.resize(count); @@ -156,422 +100,22 @@ void LLHeroProbeManager::update() LLVector4a camera_pos; camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); - - // process kill list - for (auto& probe : mKillList) - { - auto const & iter = std::find(mProbes.begin(), mProbes.end(), probe); - if (iter != mProbes.end()) - { - deleteProbe(iter - mProbes.begin()); - } - } - - mKillList.clear(); - // process create list - for (auto& probe : mCreateList) - { - mProbes.push_back(probe); - } - - mCreateList.clear(); - - if (mProbes.empty()) - { - return; - } - - - bool did_update = false; - - static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); - static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - - bool realtime = sDetail >= (S32)LLHeroProbeManager::DetailLevel::REALTIME; - - LLReflectionMap* closestDynamic = nullptr; - - LLReflectionMap* oldestProbe = nullptr; - LLReflectionMap* oldestOccluded = nullptr; - - if (mUpdatingProbe != nullptr) - { - did_update = true; - doProbeUpdate(); - } - - // update distance to camera for all probes - std::sort(mProbes.begin()+1, mProbes.end(), CompareProbeDistance()); - llassert(mProbes[0] == mDefaultProbe); - llassert(mProbes[0]->mCubeArray == mTexture); - llassert(mProbes[0]->mCubeIndex == 0); - - // make sure we're assigning cube slots to the closest probes + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); + static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); - // first free any cube indices for distant probes - for (U32 i = mReflectionProbeCount; i < mProbes.size(); ++i) - { - LLReflectionMap* probe = mProbes[i]; - llassert(probe != nullptr); - - if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) - { // free this index - mCubeFree.push_back(probe->mCubeIndex); - - probe->mCubeArray = nullptr; - probe->mCubeIndex = -1; - probe->mComplete = false; - } - } - - // next distribute the free indices - U32 count = llmin(mReflectionProbeCount, (U32)mProbes.size()); - - for (S32 i = 1; i < count && !mCubeFree.empty(); ++i) - { - // find the closest probe that needs a cube index - LLReflectionMap* probe = mProbes[i]; - - if (probe->mCubeIndex == -1) - { - S32 idx = allocateCubeIndex(); - llassert(idx > 0); //if we're still in this loop, mCubeFree should not be empty and allocateCubeIndex should be returning good indices - probe->mCubeArray = mTexture; - probe->mCubeIndex = idx; - } - } - - for (int i = 0; i < mProbes.size(); ++i) - { - LLReflectionMap* probe = mProbes[i]; - if (probe->getNumRefs() == 1) - { // no references held outside manager, delete this probe - deleteProbe(i); - --i; - continue; - } - - if (probe != mDefaultProbe && !probe->isRelevant()) - { - continue; - } - - LLVector4a d; - - if (probe != mDefaultProbe) - { - if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to - { - probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV); - } - d.setSub(camera_pos, probe->mOrigin); - probe->mDistance = d.getLength3().getF32() - probe->mRadius; - } - else if (probe->mComplete) - { - // make default probe have a distance of 64m for the purposes of prioritization (if it's already been generated once) - probe->mDistance = 64.f; - } - else - { - probe->mDistance = -4096.f; //boost priority of default probe when it's not complete - } - - if (probe->mComplete) - { - probe->autoAdjustOrigin(); - probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); - } - if (probe->mOccluded && probe->mComplete) - { - if (oldestOccluded == nullptr) - { - oldestOccluded = probe; - } - else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime) - { - oldestOccluded = probe; - } - } - else - { - if (!did_update && - i < mReflectionProbeCount && - (oldestProbe == nullptr || - check_priority(probe, oldestProbe))) - { - oldestProbe = probe; - } - } - - if (realtime && - closestDynamic == nullptr && - probe->mCubeIndex != -1 && - probe->getIsDynamic()) - { - closestDynamic = probe; - } - } - - if (realtime && closestDynamic != nullptr) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // update the closest dynamic probe realtime - // should do a full irradiance pass on "odd" frames and a radiance pass on "even" frames - closestDynamic->autoAdjustOrigin(); - - // store and override the value of "isRadiancePass" -- parts of the render pipe rely on "isRadiancePass" to set - // lighting values etc - bool radiance_pass = isRadiancePass(); - mRadiancePass = mRealtimeRadiancePass; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(closestDynamic, i, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); - } - mRealtimeRadiancePass = !mRealtimeRadiancePass; - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - - { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - mHeroProbe->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); - bool radiance_pass = isRadiancePass(); - mRadiancePass = true; - for (U32 i = 0; i < 6; ++i) - { - updateProbeFace(mHeroProbe, i, mHeroProbeResolution, mHeroArray, mMipChain, mHeroProbeCount); - } - - // restore "isRadiancePass" - mRadiancePass = radiance_pass; - } - - static LLCachedControl sUpdatePeriod(gSavedSettings, "RenderDefaultProbeUpdatePeriod", 2.f); - if ((gFrameTimeSeconds - mDefaultProbe->mLastUpdateTime) < sUpdatePeriod) - { - if (sLevel == 0) - { // when probes are disabled don't update the default probe more often than the prescribed update period - oldestProbe = nullptr; - } - } - else if (sLevel > 0) - { // when probes are enabled don't update the default probe less often than the prescribed update period - oldestProbe = mDefaultProbe; - } - - // switch to updating the next oldest probe - if (!did_update && oldestProbe != nullptr) - { - LLReflectionMap* probe = oldestProbe; - llassert(probe->mCubeIndex != -1); - - probe->autoAdjustOrigin(); - - mUpdatingProbe = probe; - doProbeUpdate(); - } - - if (oldestOccluded) - { - // as far as this occluded probe is concerned, an origin/radius update is as good as a full update - oldestOccluded->autoAdjustOrigin(); - oldestOccluded->mLastUpdateTime = gFrameTimeSeconds; - } -} - -LLReflectionMap* LLHeroProbeManager::addProbe(LLSpatialGroup* group) -{ - LLReflectionMap* probe = new LLReflectionMap(); - probe->mGroup = group; - - if (mDefaultProbe.isNull()) - { //safety check to make sure default probe is always first probe added - mDefaultProbe = new LLReflectionMap(); - mProbes.push_back(mDefaultProbe); - } - - llassert(mProbes[0] == mDefaultProbe); - - if (group) - { - probe->mOrigin = group->getOctreeNode()->getCenter(); - } - - if (gCubeSnapshot) - { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update - mCreateList.push_back(probe); - } - else - { - mProbes.push_back(probe); - } - - return probe; -} - -struct CompareProbeDepth -{ - bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) - { - return lhs->mMinDepth < rhs->mMinDepth; - } -}; - -void LLHeroProbeManager::getReflectionMaps(std::vector& maps) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - - LLMatrix4a modelview; - modelview.loadu(gGLModelView); - LLVector4a oa; // scratch space for transformed origin - - U32 count = 0; - U32 lastIdx = 0; - for (U32 i = 0; count < maps.size() && i < mProbes.size(); ++i) - { - mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested - if (mProbes[i]->mCubeIndex != -1) + // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. + mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + for (U32 j = 0; j < mProbes.size(); j++) { - if (!mProbes[i]->mOccluded && mProbes[i]->mComplete) + for (U32 i = 0; i < 6; ++i) { - maps[count++] = mProbes[i]; - modelview.affineTransform(mProbes[i]->mOrigin, oa); - mProbes[i]->mMinDepth = -oa.getF32ptr()[2] - mProbes[i]->mRadius; - mProbes[i]->mMaxDepth = -oa.getF32ptr()[2] + mProbes[i]->mRadius; + updateProbeFace(mProbes[j], i); } } - else - { - mProbes[i]->mProbeIndex = -1; - } - lastIdx = i; - } - - // set remaining probe indices to -1 - for (U32 i = lastIdx+1; i < mProbes.size(); ++i) - { - mProbes[i]->mProbeIndex = -1; - } - - if (count > 1) - { - std::sort(maps.begin(), maps.begin() + count, CompareProbeDepth()); - } - - for (U32 i = 0; i < count; ++i) - { - maps[i]->mProbeIndex = i; - } - - // null terminate list - if (count < maps.size()) - { - maps[count] = nullptr; - } -} - -LLReflectionMap* LLHeroProbeManager::registerSpatialGroup(LLSpatialGroup* group) -{ - if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) - { - OctreeNode* node = group->getOctreeNode(); - F32 size = node->getSize().getF32ptr()[0]; - if (size >= 15.f && size <= 17.f) - { - return addProbe(group); - } - } - - return nullptr; -} - -LLReflectionMap* LLHeroProbeManager::registerViewerObject(LLViewerObject* vobj) -{ - llassert(vobj != nullptr); - - LLReflectionMap* probe = new LLReflectionMap(); - probe->mViewerObject = vobj; - probe->mOrigin.load3(vobj->getPositionAgent().mV); - - if (gCubeSnapshot) - { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update - mCreateList.push_back(probe); - } - else - { - mProbes.push_back(probe); - } - - return probe; -} - -S32 LLHeroProbeManager::allocateCubeIndex() -{ - if (!mCubeFree.empty()) - { - S32 ret = mCubeFree.front(); - mCubeFree.pop_front(); - return ret; - } - - return -1; -} - -void LLHeroProbeManager::deleteProbe(U32 i) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - LLReflectionMap* probe = mProbes[i]; - - llassert(probe != mDefaultProbe); - - if (probe->mCubeIndex != -1) - { // mark the cube index used by this probe as being free - mCubeFree.push_back(probe->mCubeIndex); - } - if (mUpdatingProbe == probe) - { - mUpdatingProbe = nullptr; - mUpdatingFace = 0; - } - - // remove from any Neighbors lists - for (auto& other : probe->mNeighbors) - { - auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); - llassert(iter != other->mNeighbors.end()); - other->mNeighbors.erase(iter); - } - - mProbes.erase(mProbes.begin() + i); -} - - -void LLHeroProbeManager::doProbeUpdate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - llassert(mUpdatingProbe != nullptr); - - updateProbeFace(mUpdatingProbe, mUpdatingFace, mProbeResolution, mTexture, mMipChain, mReflectionProbeCount); - - if (++mUpdatingFace == 6) - { - updateNeighbors(mUpdatingProbe); - mUpdatingFace = 0; - if (isRadiancePass()) - { - mUpdatingProbe->mComplete = true; - mUpdatingProbe = nullptr; - mRadiancePass = false; - } - else - { - mRadiancePass = true; - } } } @@ -583,53 +127,36 @@ void LLHeroProbeManager::doProbeUpdate() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - - LLRenderTarget* target = &mRenderTarget; - - S32 sourceIdx = probeCount; - - if (probeResolution == mHeroProbeResolution) - { - sourceIdx = 0; - target = &mHeroRenderTarget; - } mLightScale = 1.f; static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); - if (!isRadiancePass() && probe->getAmbiance() > max_local_light_ambiance) + if (probe->getAmbiance() > max_local_light_ambiance) { mLightScale = max_local_light_ambiance / probe->getAmbiance(); } - if (probe == mDefaultProbe) { - touch_default_probe(probe); - gPipeline.pushRenderTypeMask(); //only render sky, water, terrain, and clouds gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, - LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES); + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::END_RENDER_TYPES); - probe->update(target->getWidth(), face); + probe->update(mRenderTarget.getWidth(), face); gPipeline.popRenderTypeMask(); } - else - { - probe->update(target->getWidth(), face); - } gPipeline.mRT = &gPipeline.mMainRT; - if (probe != mUpdatingProbe && probe->mType != LLReflectionMap::ProbeType::REFLECTION) - { // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel - sourceIdx += 1; - } + S32 sourceIdx = mReflectionProbeCount; + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. + sourceIdx += 1; gGL.setColorMask(true, true); LLGLDepthTest depth(GL_FALSE, GL_FALSE); @@ -647,7 +174,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gGL.loadIdentity(); gGL.flush(); - U32 res = probeResolution * 2; + U32 res = mProbeResolution * 2; static LLStaticHashedString resScale("resScale"); static LLStaticHashedString direction("direction"); @@ -659,20 +186,20 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (probeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal gGaussianProgram.uniform2f(direction, 1.f, 0.f); gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - target->bindTarget(); + mRenderTarget.bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - target->flush(); + mRenderTarget.flush(); // vertical gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(target); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); screen_rt->bindTarget(); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -680,7 +207,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } - S32 mips = log2((F32)probeResolution) + 0.5f; + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); @@ -699,7 +226,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } - gReflectionMipProgram.uniform1f(resScale, 1.f/(probeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -711,11 +238,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p if (mip >= 0) { LL_PROFILE_GPU_ZONE("probe mip copy"); - cubeArray->bind(0); - + mTexture->bind(0); + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - - cubeArray->unbind(); + //if (i == 0) + //{ + //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + //} + mTexture->unbind(); } mMipChain[i].flush(); } @@ -733,14 +263,13 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); - if (isRadiancePass()) { //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); + mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); @@ -755,7 +284,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, probeResolution); + gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -780,50 +309,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p gRadianceGenProgram.unbind(); } - else - { - //generate irradiance map - gIrradianceGenProgram.bind(); - S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - cubeArray->bind(channel); - - gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx); - gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - - mVertexBuffer->setBuffer(); - int start_mip = 0; - // find the mip target to start with based on irradiance map resolution - for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip) - { - if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION) - { - break; - } - } - - //for (int i = start_mip; i < mMipChain.size(); ++i) - { - int i = start_mip; - LL_PROFILE_GPU_ZONE("probe irradiance gen"); - glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight()); - for (int cf = 0; cf < 6; ++cf) - { // for each cube face - LLCoordFrame frame; - frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); - - F32 mat[16]; - frame.getOpenGLRotation(mat); - gGL.loadMatrix(mat); - - mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); - - S32 res = mMipChain[i].getWidth(); - mIrradianceMaps->bind(channel); - glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); - cubeArray->bind(channel); - } - } - } mMipChain[0].flush(); @@ -831,59 +316,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, U32 p } } -void LLHeroProbeManager::reset() -{ - mReset = true; -} - -void LLHeroProbeManager::shift(const LLVector4a& offset) -{ - for (auto& probe : mProbes) - { - probe->mOrigin.add(offset); - } -} - -void LLHeroProbeManager::updateNeighbors(LLReflectionMap* probe) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mDefaultProbe == probe) - { - return; - } - - //remove from existing neighbors - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - clear"); - - for (auto& other : probe->mNeighbors) - { - auto const & iter = std::find(other->mNeighbors.begin(), other->mNeighbors.end(), probe); - llassert(iter != other->mNeighbors.end()); // <--- bug davep if this ever happens, something broke badly - other->mNeighbors.erase(iter); - } - - probe->mNeighbors.clear(); - } - - // search for new neighbors - if (probe->isRelevant()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmun - search"); - for (auto& other : mProbes) - { - if (other != mDefaultProbe && other != probe) - { - if (other->isRelevant() && probe->intersects(other)) - { - probe->mNeighbors.push_back(other); - other->mNeighbors.push_back(probe); - } - } - } - } -} - void LLHeroProbeManager::updateUniforms() { if (!LLPipeline::sReflectionProbesEnabled) @@ -892,229 +324,6 @@ void LLHeroProbeManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - - // structure for packing uniform buffer object - // see class3/deferred/reflectionProbeF.glsl - struct ReflectionProbeData - { - // for box probes, matrix that transforms from camera space to a [-1, 1] cube representing the bounding box of - // the box probe - LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; - - // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space - LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; - - // extra parameters - // x - irradiance scale - // y - radiance scale - // z - fade in - // w - znear - LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; - - // indices used by probe: - // [i][0] - cubemap array index for this probe - // [i][1] - index into "refNeighbor" for probes that intersect this probe - // [i][2] - number of probes that intersect this probe, or -1 for no neighbors - // [i][3] - priority (probe type stored in sign bit - positive for spheres, negative for boxes) - GLint refIndex[LL_MAX_REFLECTION_PROBE_COUNT][4]; - - // list of neighbor indices - GLint refNeighbor[4096]; - - GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth - // numbrer of active refmaps - GLint refmapCount; - }; - - mReflectionMaps.resize(mReflectionProbeCount); - getReflectionMaps(mReflectionMaps); - - ReflectionProbeData rpd; - - F32 minDepth[256]; - - for (int i = 0; i < 256; ++i) - { - rpd.refBucket[i][0] = mReflectionProbeCount; - rpd.refBucket[i][1] = mReflectionProbeCount; - rpd.refBucket[i][2] = mReflectionProbeCount; - rpd.refBucket[i][3] = mReflectionProbeCount; - minDepth[i] = FLT_MAX; - } - - // load modelview matrix into matrix 4a - LLMatrix4a modelview; - modelview.loadu(gGLModelView); - LLVector4a oa; // scratch space for transformed origin - - S32 count = 0; - U32 nc = 0; // neighbor "cursor" - index into refNeighbor to start writing the next probe's list of neighbors - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); - static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, should_auto_adjust); - - bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); - F32 ambscale = is_ambiance_pass ? 0.f : 1.f; - F32 radscale = is_ambiance_pass ? 0.5f : 1.f; - - for (auto* refmap : mReflectionMaps) - { - if (refmap == nullptr) - { - break; - } - - if (refmap != mDefaultProbe) - { - // bucket search data - // theory of operation: - // 1. Determine minimum and maximum depth of each influence volume and store in mDepth (done in getReflectionMaps) - // 2. Sort by minimum depth - // 3. Prepare a bucket for each 1m of depth out to 256m - // 4. For each bucket, store the index of the nearest probe that might influence pixels in that bucket - // 5. In the shader, lookup the bucket for the pixel depth to get the index of the first probe that could possibly influence - // the current pixel. - int depth_min = llclamp(llfloor(refmap->mMinDepth), 0, 255); - int depth_max = llclamp(llfloor(refmap->mMaxDepth), 0, 255); - for (U32 i = depth_min; i <= depth_max; ++i) - { - if (refmap->mMinDepth < minDepth[i]) - { - minDepth[i] = refmap->mMinDepth; - rpd.refBucket[i][0] = refmap->mProbeIndex; - } - } - } - - llassert(refmap->mProbeIndex == count); - llassert(mReflectionMaps[refmap->mProbeIndex] == refmap); - - llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged - - { - if (refmap->mViewerObject) - { // have active manual probes live-track the object they're associated with - refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV); - refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; - - } - modelview.affineTransform(refmap->mOrigin, oa); - rpd.refSphere[count].set(oa.getF32ptr()); - rpd.refSphere[count].mV[3] = refmap->mRadius; - } - - rpd.refIndex[count][0] = refmap->mCubeIndex; - llassert(nc % 4 == 0); - rpd.refIndex[count][1] = nc / 4; - rpd.refIndex[count][3] = refmap->mPriority; - - // for objects that are reflection probes, use the volume as the influence volume of the probe - // only possibile influence volumes are boxes and spheres, so detect boxes and treat everything else as spheres - if (refmap->getBox(rpd.refBox[count])) - { // negate priority to indicate this probe has a box influence volume - rpd.refIndex[count][3] = -rpd.refIndex[count][3]; - } - - rpd.refParams[count].set( - llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale - radscale, // radiance scale - refmap->mFadeIn, // fade in weight - oa.getF32ptr()[2] - refmap->mRadius); // z near - - 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"); - //pack neghbor list - const U32 max_neighbors = 64; - U32 neighbor_count = 0; - - for (auto& neighbor : refmap->mNeighbors) - { - if (ni >= 4096) - { // out of space - break; - } - - GLint idx = neighbor->mProbeIndex; - if (idx == -1 || neighbor->mOccluded || neighbor->mCubeIndex == -1) - { - continue; - } - - // this neighbor may be sampled - rpd.refNeighbor[ni++] = idx; - - neighbor_count++; - if (neighbor_count >= max_neighbors) - { - break; - } - } - } - - if (nc == ni) - { - //no neighbors, tag as empty - rpd.refIndex[count][1] = -1; - } - else - { - rpd.refIndex[count][2] = ni - nc; - - // move the cursor forward - nc = ni; - if (nc % 4 != 0) - { // jump to next power of 4 for compatibility with ivec4 - nc += 4 - (nc % 4); - } - } - - - count++; - } - -#if 0 - { - // fill in gaps in refBucket - S32 probe_idx = mReflectionProbeCount; - - for (int i = 0; i < 256; ++i) - { - if (i < count) - { // for debugging, store depth of mReflectionsMaps[i] - rpd.refBucket[i][1] = (S32) (mReflectionMaps[i]->mDepth * 10); - } - - if (rpd.refBucket[i][0] == mReflectionProbeCount) - { - rpd.refBucket[i][0] = probe_idx; - } - else - { - probe_idx = rpd.refBucket[i][0]; - } - } - } -#endif - - rpd.refmapCount = count; - - //copy rpd into uniform buffer object - if (mUBO == 0) - { - glGenBuffers(1, &mUBO); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(ReflectionProbeData), &rpd, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } struct HeroProbeData { @@ -1124,22 +333,23 @@ void LLHeroProbeManager::updateUniforms() HeroProbeData hpd; + LLMatrix4a modelview; modelview.loadu(gGLModelView); - + LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); hpd.heroProbeCount = 1; - modelview.affineTransform(mHeroProbe->mOrigin, oa); + modelview.affineTransform(mProbes[0]->mOrigin, oa); hpd.heroPosition[0].set(oa.getF32ptr()); //copy rpd into uniform buffer object if (mUBO == 0) { - glGenBuffers(1, &mHeroUBO); + glGenBuffers(1, &mUBO); } { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mHeroUBO); + glBindBuffer(GL_UNIFORM_BUFFER, mUBO); glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } @@ -1190,11 +400,11 @@ void LLHeroProbeManager::initReflectionMaps() { U32 count = LL_MAX_REFLECTION_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset || mHeroArray.isNull()) + if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); + mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderHeroProbeResolution"), (U32)128, (U32)1024)); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); @@ -1205,25 +415,6 @@ void LLHeroProbeManager::initReflectionMaps() mIrradianceMaps = new LLCubeMapArray(); mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); - // reset probe state - mUpdatingFace = 0; - mUpdatingProbe = nullptr; - mRadiancePass = false; - mRealtimeRadiancePass = false; - - for (auto& probe : mProbes) - { - probe->mLastUpdateTime = 0.f; - probe->mComplete = false; - probe->mProbeIndex = -1; - probe->mCubeArray = nullptr; - probe->mCubeIndex = -1; - probe->mNeighbors.clear(); - } - - mCubeFree.clear(); - initCubeFree(); - if (mDefaultProbe.isNull()) { llassert(mProbes.empty()); // default probe MUST be the first probe created @@ -1233,6 +424,8 @@ void LLHeroProbeManager::initReflectionMaps() llassert(mProbes[0] == mDefaultProbe); + // For hero probes, we treat this as the main mirror probe. + mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; mDefaultProbe->mDistance = 64.f; @@ -1240,27 +433,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - mHeroProbeResolution = 128; - - // Revise when we have both water and mirrors in hero probes. - mHeroProbeCount = 1; - - mHeroArray = new LLCubeMapArray(); - - // We use an extra probe for scratch space on these. - mHeroArray->allocate(mHeroProbeResolution, 3, mHeroProbeCount + 1, true); - - if (mHeroProbe.isNull()) { - mHeroProbe = new LLReflectionMap(); - } - - mHeroProbe->mCubeIndex = 0; - mHeroProbe->mCubeArray = mHeroArray; - mHeroProbe->mDistance = 64.f; - mHeroProbe->mRadius = 4096.f; - mHeroProbe->mProbeIndex = 0; - touch_default_probe(mHeroProbe); - + mProbes.push_back(mDefaultProbe); } if (mVertexBuffer.isNull()) @@ -1294,28 +467,16 @@ void LLHeroProbeManager::cleanup() mTexture = nullptr; mIrradianceMaps = nullptr; - mHeroArray = nullptr; mProbes.clear(); - mKillList.clear(); - mCreateList.clear(); mReflectionMaps.clear(); - mUpdatingFace = 0; mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - mHeroProbe = nullptr; glDeleteBuffers(1, &mUBO); mUBO = 0; - - glDeleteBuffers(1, &mHeroUBO); - mHeroUBO = 0; - - // note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state - initCubeFree(); } void LLHeroProbeManager::doOcclusion() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index be761a680e..95e3963d1a 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -35,13 +35,7 @@ class LLSpatialGroup; class LLViewerObject; // number of reflection probes to keep in vram -#define LL_MAX_REFLECTION_PROBE_COUNT 256 - -// reflection probe resolution -#define LL_IRRADIANCE_MAP_RESOLUTION 64 - -// reflection probe mininum scale -#define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; +#define LL_MAX_HERO_PROBE_COUNT 2 class alignas(16) LLHeroProbeManager { @@ -63,30 +57,6 @@ public: // maintain reflection probes void update(); - // add a probe for the given spatial group - LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr); - - // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size() - // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr. - // maps -- presized array of Reflection Map pointers - void getReflectionMaps(std::vector& maps); - - // called by LLSpatialGroup constructor - // If spatial group should receive a Reflection Probe, will create one for the specified spatial group - LLReflectionMap* registerSpatialGroup(LLSpatialGroup* group); - - // presently hacked into LLViewerObject::setTE - // Used by LLViewerObjects that are Reflection Probes - // vobj must not be null - // Guaranteed to not return null - LLReflectionMap* registerViewerObject(LLViewerObject* vobj); - - // reset all state on the next update - void reset(); - - // called on region crossing to "shift" probes into new coordinate frame - void shift(const LLVector4a& offset); - // debug display, called from llspatialpartition if reflection // probe debug display is active void renderDebug(); @@ -94,28 +64,12 @@ public: // call once at startup to allocate cubemap arrays void initReflectionMaps(); - // True if currently updating a radiance map, false if currently updating an irradiance map - bool isRadiancePass() { return mRadiancePass; } - // perform occlusion culling on all active reflection probes void doOcclusion(); private: friend class LLPipeline; - - // initialize mCubeFree array to default values - void initCubeFree(); - - // delete the probe with the given index in mProbes - void deleteProbe(U32 i); - - // get a free cube index - // returns -1 if allocation failed - S32 allocateCubeIndex(); - - // update the neighbors of the given probe - void updateNeighbors(LLReflectionMap* probe); - + // update UBO used for rendering (call only once per render pipe flush) void updateUniforms(); @@ -132,8 +86,6 @@ private: // storage for reflection probe radiance maps (plus two scratch space cubemaps) LLPointer mTexture; - - LLPointer mHeroArray; // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; @@ -141,61 +93,28 @@ private: // storage for reflection probe irradiance maps LLPointer mIrradianceMaps; - // list of free cubemap indices - std::list mCubeFree; - - // perform an update on the currently updating Probe - void doProbeUpdate(); - // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, U32 probeResolution, LLPointer cubeArray, std::vector &mipChain, U32 probeCount); + void updateProbeFace(LLReflectionMap* probe, U32 face); // list of active reflection maps std::vector > mProbes; - // list of reflection maps to kill - std::vector > mKillList; - - // list of reflection maps to create - std::vector > mCreateList; - // handle to UBO U32 mUBO = 0; - - // Hero UBO - U32 mHeroUBO = 0; // list of maps being used for rendering std::vector mReflectionMaps; LLReflectionMap* mUpdatingProbe = nullptr; - U32 mUpdatingFace = 0; - - // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map. - // Update sequence should be to generate the irradiance map from render of the world that has no irradiance, - // then generate the radiance map from a render of the world that includes irradiance. - // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment. - bool mRadiancePass = false; - - // same as above, but for the realtime probe. - // Realtime probes should update all six sides of the irradiance map on "odd" frames and all six sides of the - // radiance map on "even" frames. - bool mRealtimeRadiancePass = false; LLPointer mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0) - - LLPointer mHeroProbe; // number of reflection probes to use for rendering U32 mReflectionProbeCount; - - U32 mHeroProbeCount; // resolution of reflection probes U32 mProbeResolution = 128; - U32 mHeroProbeResolution = 512; - // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 909c0f9aaa..4c951a9dea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -642,6 +642,7 @@ void LLPipeline::cleanup() mCubeVB = NULL; mReflectionMapManager.cleanup(); + mHeroProbeManager.cleanup(); } //============================================================================ @@ -772,6 +773,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { // hacky -- allocate auxillary buffer gCubeSnapshot = TRUE; mReflectionMapManager.initReflectionMaps(); + mHeroProbeManager.initReflectionMaps(); mRT = &mAuxillaryRT; U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); @@ -2441,6 +2443,26 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } + + if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) + { + gGL.setColorMask(false, false); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gOcclusionCubeProgram.bind(); + + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + mCubeVB->setBuffer(); + + mHeroProbeManager.doOcclusion(); + gOcclusionCubeProgram.unbind(); + + gGL.setColorMask(true, true); + } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) @@ -3809,6 +3831,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) { //update reflection probe uniform mReflectionMapManager.updateUniforms(); + mHeroProbeManager.updateUniforms(); } U32 cur_type = 0; @@ -8461,14 +8484,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) mReflectionMapManager.mIrradianceMaps->bind(channel); bound = true; } - /* + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mReflectionMapManager.mHeroArray.notNull()) + if (channel > -1 && mHeroProbeManager.mTexture.notNull()) { - mReflectionMapManager.mHeroArray->bind(channel); + mHeroProbeManager.mTexture->bind(channel); bound = true; } - */ + if (bound) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f3b35e0325..bfb9b95f4d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -39,6 +39,7 @@ #include "lldrawable.h" #include "llrendertarget.h" #include "llreflectionmapmanager.h" +#include "llheroprobemanager.h" #include @@ -454,6 +455,7 @@ public: void handleShadowDetailChanged(); LLReflectionMapManager mReflectionMapManager; + LLHeroProbeManager mHeroProbeManager; private: void unloadShaders(); -- cgit v1.2.3 From d4254538d1bdd5d93a4eadea961a955ce79ab06f Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 04:22:16 -0700 Subject: Further cleanup of the hero probe manager. DRTVWR-583 --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llheroprobemanager.cpp | 4 ---- indra/newview/pipeline.cpp | 20 -------------------- 3 files changed, 11 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f5e7f865ab..8b9c5b50ae 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10390,6 +10390,17 @@ Value 0 + RenderHeroProbeResolution + + Comment + Resolution to render hero probes used for mirrors, water, etc. + Persist + 1 + Type + S32 + Value + 512 + RenderReflectionProbeVolumes Comment diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 5edf819fff..1773dffa8b 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -106,7 +106,6 @@ void LLHeroProbeManager::update() { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); for (U32 j = 0; j < mProbes.size(); j++) @@ -311,8 +310,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) } mMipChain[0].flush(); - - gIrradianceGenProgram.unbind(); } } @@ -466,7 +463,6 @@ void LLHeroProbeManager::cleanup() mMipChain.clear(); mTexture = nullptr; - mIrradianceMaps = nullptr; mProbes.clear(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4c951a9dea..9f8cd2c7fd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2443,26 +2443,6 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } - - if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) - { - gGL.setColorMask(false, false); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - - gOcclusionCubeProgram.bind(); - - if (mCubeVB.isNull()) - { //cube VB will be used for issuing occlusion queries - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); - } - mCubeVB->setBuffer(); - - mHeroProbeManager.doOcclusion(); - gOcclusionCubeProgram.unbind(); - - gGL.setColorMask(true, true); - } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) -- cgit v1.2.3 From 869bb7f16ae3e931f11840332ab00715a4ef27af Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 05:15:48 -0700 Subject: Readd occlusion culling for hero probes. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 19 ++----------------- indra/newview/pipeline.cpp | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1773dffa8b..33a54c797e 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -132,23 +132,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mAuxillaryRT; mLightScale = 1.f; - static LLCachedControl max_local_light_ambiance(gSavedSettings, "RenderReflectionProbeMaxLocalLightAmbiance", 8.f); - if (probe->getAmbiance() > max_local_light_ambiance) - { - mLightScale = max_local_light_ambiance / probe->getAmbiance(); - } - { - gPipeline.pushRenderTypeMask(); - - //only render sky, water, terrain, and clouds - gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, - LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::END_RENDER_TYPES); - - probe->update(mRenderTarget.getWidth(), face); - - gPipeline.popRenderTypeMask(); - } + probe->update(mRenderTarget.getWidth(), face); gPipeline.mRT = &gPipeline.mMainRT; @@ -401,7 +386,7 @@ void LLHeroProbeManager::initReflectionMaps() { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderHeroProbeResolution"), (U32)128, (U32)1024)); + mProbeResolution = nhpo2(1024); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9f8cd2c7fd..4c951a9dea 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2443,6 +2443,26 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } + + if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) + { + gGL.setColorMask(false, false); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gOcclusionCubeProgram.bind(); + + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + mCubeVB->setBuffer(); + + mHeroProbeManager.doOcclusion(); + gOcclusionCubeProgram.unbind(); + + gGL.setColorMask(true, true); + } if (LLPipeline::sUseOcclusion > 1 && (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) -- cgit v1.2.3 From 0eba1396dcc7ec5c32124dbfd48abb75c1a5b524 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 21 Aug 2023 07:59:06 -0700 Subject: Experiment with placement a bit when there's no drawable. DRTVWR-583 --- .../shaders/class3/deferred/softenLightF.glsl | 5 +- indra/newview/llheroprobemanager.cpp | 80 ++++++++++++++++++++-- indra/newview/llheroprobemanager.h | 10 ++- indra/newview/llvovolume.cpp | 7 +- indra/newview/pipeline.cpp | 22 ------ indra/newview/pipeline.h | 5 -- 6 files changed, 88 insertions(+), 41 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index e485c26e9b..742b52b074 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -213,13 +213,14 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; + if (do_atmospherics) { color = atmosFragLightingLinear(color, additive, atten); } - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - color = texture(heroProbes, vec4(env_mat * refnormpersp, 0), 0).xyz; } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 33a54c797e..0d2e8da294 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -36,6 +36,11 @@ #include "llviewercontrol.h" #include "llenvironment.h" #include "llstartup.h" +#include "llagent.h" +#include "llagentcamera.h" +#include "llviewerwindow.h" +#include "llviewerjoystick.h" +#include "llviewermediafocus.h" extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; @@ -98,16 +103,60 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); - LLVector4a camera_pos; - camera_pos.load3(LLViewerCamera::instance().getOrigin().mV); + LLVector3 camera_pos = LLViewerCamera::instance().getOrigin(); + LLVector4a probe_pos; + + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } + + probe_pos.load3(((focus_point + camera_pos) / 2).mV); static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmu - realtime"); - // Probe 0 is always our mirror probe. Probe N - 1 is our water probe. - mProbes[0]->mOrigin.load3(LLViewerCamera::instance().mOrigin.mV); + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); + // Probe 0 is always our mirror probe. + mProbes[0]->mOrigin = probe_pos; for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -131,8 +180,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - mLightScale = 1.f; - probe->update(mRenderTarget.getWidth(), face); gPipeline.mRT = &gPipeline.mMainRT; @@ -458,6 +505,9 @@ void LLHeroProbeManager::cleanup() glDeleteBuffers(1, &mUBO); mUBO = 0; + + mHeroList.clear(); + mNearestHero = nullptr; } void LLHeroProbeManager::doOcclusion() @@ -473,3 +523,19 @@ void LLHeroProbeManager::doOcclusion() } } } + +void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) +{ + if (mHeroList.find(drawablep) == mHeroList.end()) + { + mHeroList.insert(drawablep); + } +} + +void LLHeroProbeManager::unregisterHeroDrawable(LLDrawable *drawablep) +{ + if (mHeroList.find(drawablep) != mHeroList.end()) + { + mHeroList.erase(drawablep); + } +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 95e3963d1a..c6df963cfd 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -30,6 +30,7 @@ #include "llrendertarget.h" #include "llcubemaparray.h" #include "llcubemap.h" +#include "lldrawable.h" class LLSpatialGroup; class LLViewerObject; @@ -67,6 +68,9 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); + void registerHeroDrawable(LLDrawable* drawablep); + void unregisterHeroDrawable(LLDrawable* drawablep); + private: friend class LLPipeline; @@ -118,10 +122,10 @@ private: // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; - // amount to scale local lights during an irradiance map update (set during updateProbeFace and used by LLPipeline) - F32 mLightScale = 1.f; - // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; + + LLDrawable::ordered_drawable_set_t mHeroList; + LLDrawable* mNearestHero; }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 254e945243..2589beefe9 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - gPipeline.setMirror(mDrawable, isMirror()); + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away @@ -4454,7 +4454,10 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u updateReflectionProbePtr(); - gPipeline.setMirror(mDrawable, isMirror()); + if (isMirror()) + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + else + gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4c951a9dea..792cad02bd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2783,23 +2783,6 @@ void LLPipeline::markShift(LLDrawable *drawablep) } } -void LLPipeline::setMirror(LLDrawable *drawablep, bool is_mirror) -{ - if (drawablep && assertInitialized()) - { - if (is_mirror) - { - drawablep->setState(LLDrawable::MIRROR); - mMirrorList.insert(drawablep); - } - else - { - mMirrorList.erase(drawablep); - drawablep->clearState(LLDrawable::MIRROR); - } - } -} - void LLPipeline::shiftObjects(const LLVector3 &offset) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; @@ -5852,11 +5835,6 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { LL_INFOS() << "In mRetexturedList" << LL_ENDL; } - - if (std::find(mMirrorList.begin(), mMirrorList.end(), drawablep) != mMirrorList.end()) - { - LL_INFOS() << "In mMirrorList" << LL_ENDL; - } if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bfb9b95f4d..1361441844 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -358,7 +358,6 @@ public: void shiftObjects(const LLVector3 &offset); void setLight(LLDrawable *drawablep, bool is_light); - void setMirror(LLDrawable *drawablep, bool is_mirror); bool hasRenderBatches(const U32 type) const; LLCullResult::drawinfo_iterator beginRenderMap(U32 type); @@ -821,10 +820,6 @@ protected: LLDrawable::ordered_drawable_set_t mLights; light_set_t mNearbyLights; // lights near camera LLColor4 mHWLightColors[8]; - - - LLDrawable::ordered_drawable_set_t mMirrorList; - LLDrawable* mNearestMirror; ///////////////////////////////////////////// // -- cgit v1.2.3 From 316052024958dde817a8d0809c77e29ec4cef64c Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 24 Aug 2023 12:51:19 -0700 Subject: Fix the probe flashing, and avatars. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 9 ++++++++- indra/newview/llreflectionmap.cpp | 5 +++-- indra/newview/llreflectionmap.h | 2 +- indra/newview/llreflectionmapmanager.h | 1 + 4 files changed, 13 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 0d2e8da294..729603e960 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -157,6 +157,11 @@ void LLHeroProbeManager::update() LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. mProbes[0]->mOrigin = probe_pos; + + bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); + + gPipeline.mReflectionMapManager.mRadiancePass = true; + for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -164,6 +169,8 @@ void LLHeroProbeManager::update() updateProbeFace(mProbes[j], i); } } + + gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } } @@ -180,7 +187,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - probe->update(mRenderTarget.getWidth(), face); + probe->update(mRenderTarget.getWidth(), face, true); gPipeline.mRT = &gPipeline.mMainRT; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index efaf068bd2..022b7d11d8 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -63,7 +63,8 @@ void LLReflectionMap::update(U32 resolution, U32 face) { resolution /= 2; } - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic()); + + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic() || force_dynamic); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 831a6358ee..a23bdc3a98 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face); + void update(U32 resolution, U32 face, bool force_dynamic = false); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 7b17112814..4ef6c5fdff 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -104,6 +104,7 @@ public: private: friend class LLPipeline; + friend class LLHeroProbeManager; // initialize mCubeFree array to default values void initCubeFree(); -- cgit v1.2.3 From fbecd348f897ee91a5639e7e9fe4f0578d72b8e2 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 29 Aug 2023 03:04:04 -0700 Subject: Add protocol level mirror support, and UI. --- indra/llprimitive/llprimitive.cpp | 39 ++++++++-- indra/llprimitive/llprimitive.h | 12 ++- indra/llprimitive/llprimtexturelist.cpp | 10 --- indra/llprimitive/llprimtexturelist.h | 1 - indra/llprimitive/lltextureentry.cpp | 10 --- indra/llprimitive/lltextureentry.h | 10 --- indra/newview/llheroprobemanager.cpp | 87 +++++++++++++--------- indra/newview/llpanelface.cpp | 17 ----- indra/newview/llpanelface.h | 2 - indra/newview/llpanelvolume.cpp | 34 +++++++++ indra/newview/llpanelvolume.h | 2 + indra/newview/llselectmgr.cpp | 41 ---------- indra/newview/llselectmgr.h | 1 - indra/newview/llviewerobject.cpp | 28 ++----- indra/newview/llviewerobject.h | 1 - indra/newview/llvovolume.cpp | 60 ++++++++------- indra/newview/llvovolume.h | 5 +- .../newview/skins/default/xui/en/floater_tools.xml | 10 ++- 18 files changed, 185 insertions(+), 185 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index b45ead92d3..703584ed62 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -404,11 +404,6 @@ S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) return mTextureList.setFullbright(index, fullbright); } -S32 LLPrimitive::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) -{ - return mTextureList.setRenderableTarget(te, target); -} - S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { return mTextureList.setMediaFlags(index, media_flags); @@ -1828,6 +1823,40 @@ bool LLLightParams::fromLLSD(LLSD& sd) //============================================================================ +LLMirrorParams::LLMirrorParams() +{ + mType = PARAMS_MIRROR; +} + +BOOL LLMirrorParams::pack(LLDataPacker &dp) const +{ + return TRUE; +} + +BOOL LLMirrorParams::unpack(LLDataPacker &dp) +{ + return TRUE; +} + +bool LLMirrorParams::operator==(const LLNetworkData& data) const +{ + if (data.mType != PARAMS_REFLECTION_PROBE) + { + return false; + } + return true; +} + +void LLMirrorParams::copy(const LLNetworkData& data) +{ + const LLMirrorParams *param = (LLMirrorParams*)&data; + mType = param->mType; +} + +//============================================================================ + +//============================================================================ + LLReflectionProbeParams::LLReflectionProbeParams() { mType = PARAMS_REFLECTION_PROBE; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 520c7c7ac8..1af9bca42e 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,6 +109,7 @@ public: PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, + PARAMS_MIRROR = 0x100, }; public: @@ -172,6 +173,16 @@ public: F32 getCutoff() const { return mCutoff; } }; +class LLMirrorParams : public LLNetworkData +{ +public: + LLMirrorParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); +}; + extern const F32 REFLECTION_PROBE_MIN_AMBIANCE; extern const F32 REFLECTION_PROBE_MAX_AMBIANCE; extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE; @@ -485,7 +496,6 @@ public: virtual S32 setTETexGen(const U8 te, const U8 texgen); virtual S32 setTEShiny(const U8 te, const U8 shiny); virtual S32 setTEFullbright(const U8 te, const U8 fullbright); - virtual S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); virtual S32 setTEMediaFlags(const U8 te, const U8 flags); virtual S32 setTEGlow(const U8 te, const F32 glow); virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index 49b59e35cb..f4f08248b8 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -341,16 +341,6 @@ S32 LLPrimTextureList::setFullbright(const U8 index, const U8 fullbright) return TEM_CHANGE_NONE; } -S32 LLPrimTextureList::setRenderableTarget(const U8 index, const U8 target) -{ - if (index < mEntryList.size()) - { - return mEntryList[index]->setRenderableTarget((LLTextureEntry::eRenderableTarget)target); - } - - return TEM_CHANGE_NONE; -} - S32 LLPrimTextureList::setMediaFlags(const U8 index, const U8 media_flags) { if (index < mEntryList.size()) diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 34b87d879f..49c636e40f 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -102,7 +102,6 @@ public: S32 setTexGen(const U8 index, const U8 texgen); S32 setShiny(const U8 index, const U8 shiny); S32 setFullbright(const U8 index, const U8 t); - S32 setRenderableTarget(const U8 index, const U8 target); S32 setMediaFlags(const U8 index, const U8 media_flags); S32 setGlow(const U8 index, const F32 glow); S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index fdf3774bfa..ee2a4c769a 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -504,16 +504,6 @@ S32 LLTextureEntry::setFullbright(U8 fullbright) return TEM_CHANGE_NONE; } -S32 LLTextureEntry::setRenderableTarget(eRenderableTarget target) -{ - if (getRenderableTarget() != target) { - mRenderableTarget = target; - return TEM_CHANGE_TEXTURE; - } - - return TEM_CHANGE_NONE; -} - S32 LLTextureEntry::setShiny(U8 shiny) { shiny &= TEM_SHINY_MASK; diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 2c0832e1d4..0935147688 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -80,12 +80,6 @@ public: TEX_GEN_SPHERICAL = 0x04, TEX_GEN_CYLINDRICAL = 0x06 } eTexGen; - - - typedef enum e_renderable_target { - RT_DISABLED = 0x00, - RT_MIRROR = 0x02 - } eRenderableTarget; LLTextureEntry(); LLTextureEntry(const LLUUID& tex_id); @@ -141,8 +135,6 @@ public: S32 setMaterialID(const LLMaterialID& pMaterialID); S32 setMaterialParams(const LLMaterialPtr pMaterialParams); - S32 setRenderableTarget(eRenderableTarget target); - virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } const F32 getAlpha() const { return mColor.mV[VALPHA]; } @@ -160,7 +152,6 @@ public: U8 getBumpmap() const { return mBump & TEM_BUMP_MASK; } U8 getFullbright() const { return (mBump>>TEM_FULLBRIGHT_SHIFT) & TEM_FULLBRIGHT_MASK; } - eRenderableTarget getRenderableTarget() const { return mRenderableTarget; } U8 getShiny() const { return (mBump>>TEM_SHINY_SHIFT) & TEM_SHINY_MASK; } U8 getBumpShiny() const { return mBump & TEM_BUMP_SHINY_MASK; } U8 getBumpShinyFullbright() const { return mBump; } @@ -242,7 +233,6 @@ protected: LLColor4 mColor; U8 mBump; // Bump map, shiny, and fullbright U8 mMediaFlags; // replace with web page, movie, etc. - eRenderableTarget mRenderableTarget; F32 mGlow; bool mMaterialUpdatePending; LLMaterialID mMaterialID; diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 729603e960..6374b10823 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -103,53 +103,71 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); - LLVector3 camera_pos = LLViewerCamera::instance().getOrigin(); - LLVector4a probe_pos; - LLVector3 focus_point; - - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) + if (mHeroList.empty()) + { + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else { - focus_point = face->getPositionAgent(); + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } } } + + probe_pos.load3(((focus_point)).mV); } - - if (focus_point.isExactlyZero()) + else { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else + // Get the nearest hero. + float distance = F32_MAX; + + for (auto drawable : mHeroList) { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) + if (drawable.notNull()) { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + if (drawable->mDistanceWRTCamera < distance) + { + probe_pos.load3(drawable->mXform.getPosition().mV); + } } } } - probe_pos.load3(((focus_point + camera_pos) / 2).mV); static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -464,7 +482,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; - mDefaultProbe->mDistance = 64.f; + mDefaultProbe->mDistance = 12.f; mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); @@ -536,6 +554,7 @@ void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) if (mHeroList.find(drawablep) == mHeroList.end()) { mHeroList.insert(drawablep); + LL_INFOS() << "Added hero drawable." << LL_ENDL; } } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 9233ec6277..25f42e6dae 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -596,17 +596,6 @@ void LLPanelFace::sendFullbright() LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); } -void LLPanelFace::sendMirror() -{ - LLCheckBoxCtrl* mCheckMirror = getChild("checkbox mirror"); - - if (!mCheckMirror) - return; - - LLTextureEntry::eRenderableTarget target = mCheckMirror->get() ? LLTextureEntry::RT_MIRROR : LLTextureEntry::RT_DISABLED; - LLSelectMgr::getInstance()->selectionSetRenderableTarget(target); -} - void LLPanelFace::sendColor() { @@ -3007,12 +2996,6 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) self->sendFullbright(); } -void LLPanelFace::onCommitMirror(LLUICtrl* ctrl, void* userdata) -{ - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendMirror(); -} - // static void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 0b7486232d..5cad8cefcf 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -139,7 +139,6 @@ protected: void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright - void sendMirror(); void sendGlow(); void alignTestureLayer(); @@ -229,7 +228,6 @@ protected: static void onCommitShiny( LLUICtrl* ctrl, void* userdata); static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); - static void onCommitMirror(LLUICtrl* ctrl, void* userdata); static void onCommitGlow( LLUICtrl* ctrl, void *userdata); static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index ed244f773c..d62a640b5c 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -114,6 +114,11 @@ BOOL LLPanelVolume::postBuild() getChild("FlexForceZ")->setValidateBeforeCommit(precommitValidate); } + // Mirror Parameters + { + childSetCommitCallback("Mirror Checkbox Ctrl", onCommitIsMirror, this); + } + // LIGHT Parameters { childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this); @@ -305,6 +310,10 @@ void LLPanelVolume::getState( ) getChildView("select_single")->setEnabled(true); } + BOOL is_mirror = volobjp && volobjp->isMirror(); + getChild("Mirror Checkbox Ctrl")->setValue(is_mirror); + getChildView("Mirror Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); + // Light properties BOOL is_light = volobjp && volobjp->getIsLight(); getChild("Light Checkbox Ctrl")->setValue(is_light); @@ -737,6 +746,25 @@ void LLPanelVolume::sendIsLight() LL_INFOS() << "update light sent" << LL_ENDL; } +void LLPanelVolume::sendIsMirror() +{ + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + // Quick hack to set the mirror locally. + + gPipeline.mHeroProbeManager.registerHeroDrawable(volobjp->mDrawable); + + BOOL value = getChild("Mirror Checkbox Ctrl")->getValue(); + volobjp->setIsMirror(value); + LL_INFOS() << "update mirror sent" << LL_ENDL; +} + + void LLPanelVolume::sendIsReflectionProbe() { LLViewerObject* objectp = mObject; @@ -1403,6 +1431,12 @@ void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata ) self->sendIsLight(); } +void LLPanelVolume::onCommitIsMirror( LLUICtrl* ctrl, void* userdata ) +{ + LLPanelVolume* self = (LLPanelVolume*) userdata; + self->sendIsMirror(); +} + // static void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index 01b7ebb75c..a658351624 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -58,6 +58,7 @@ public: void sendIsLight(); + void sendIsMirror(); // when an object is becoming a refleciton probe, present a dialog asking for confirmation // otherwise, send the reflection probe update immediately void sendIsReflectionProbe(); @@ -71,6 +72,7 @@ public: static void onCommitIsLight( LLUICtrl* ctrl, void* userdata); static void onCommitLight( LLUICtrl* ctrl, void* userdata); + static void onCommitIsMirror( LLUICtrl* ctrl, void* userdata); static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata); static void onCommitProbe(LLUICtrl* ctrl, void* userdata); void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 2b1b4b79b2..5c1a339570 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2355,47 +2355,6 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) getSelection()->applyToObjects(&sendfunc); } -void LLSelectMgr::selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target) -{ - struct f : public LLSelectedTEFunctor - { - LLTextureEntry::eRenderableTarget mRenderableTarget; - - f(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} - - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - object->setTERenderableTarget(te, mRenderableTarget); - } - - return true; - } - } setfunc(target); - - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - LLTextureEntry::eRenderableTarget mRenderableTarget; - - g(const LLTextureEntry::eRenderableTarget& t) : mRenderableTarget(t) {} - - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - - return true; - } - } sendfunc(target); - - getSelection()->applyToObjects(&sendfunc); -} - // This function expects media_data to be a map containing relevant // media data name/value pairs (e.g. home_url, etc.) void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 8ce59c6654..327134a487 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -653,7 +653,6 @@ public: void selectionSetGlow(const F32 glow); void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); void selectionRemoveMaterial(); - void selectionSetRenderableTarget(LLTextureEntry::eRenderableTarget target); void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); void selectionSetObjectName(const std::string& name); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7871815fda..68162f83c0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5296,29 +5296,6 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) return retval; } -S32 LLViewerObject::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) -{ - S32 retval = 0; - - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (target != tep->getRenderableTarget()) - { - retval = LLPrimitive::setTERenderableTarget(te, target); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - //gPipeline.markMirror(mDrawable); - } - } - - return retval; -} - - S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { // this might need work for media type @@ -6251,6 +6228,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para { new_block = new LLReflectionProbeParams(); break; + } + case LLNetworkData::PARAMS_MIRROR: + { + new_block = new LLMirrorParams(); + break; } default: { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index fe33047218..a87644476f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -360,7 +360,6 @@ public: /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); - /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target); /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2589beefe9..175ce93b14 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,10 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + if (isMirror()) + { + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + } updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away @@ -2369,16 +2372,6 @@ S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) return res; } -S32 LLVOVolume::setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget mirror) -{ - S32 res = LLViewerObject::setTERenderableTarget(te, mirror); - if (res) - { - //gPipeline.markMirror(mDrawable); - } - return res; -} - S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); @@ -3379,28 +3372,41 @@ F32 LLVOVolume::getLightCutoff() const } } -BOOL LLVOVolume::isMirror() const +bool LLVOVolume::setIsMirror(BOOL is_mirror) { - S32 faceCount = getNumFaces(); - - // Temporary hack to set the object to mirror. - for (int i = 0; i < faceCount; i++) + BOOL was_mirror = isMirror(); + if (is_mirror != was_mirror) { - const LLTextureEntry* te = getTE(i); - - if (te->getMaterialParams().notNull()) + if (is_mirror) { - LLViewerTexture* specularp = getTESpecularMap(0); - - if (specularp && specularp->getID() == "da7ecda1-e780-423f-ce27-26df7dc69cb6") - { - LL_INFOS() << "BELLADONNA OF SADNESS" << LL_ENDL; - return TRUE; - } + setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, FALSE, true); } } - return FALSE; + updateMirrorDrawable(); + + return was_mirror != is_mirror; +} + +void LLVOVolume::updateMirrorDrawable() +{ + if (isMirror()) + { + gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + } + else + { + gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + } +} + +BOOL LLVOVolume::isMirror() const +{ + return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); } BOOL LLVOVolume::isReflectionProbe() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index cecf726763..32c89ddae2 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -209,7 +209,6 @@ public: /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; - /*virtual*/ S32 setTERenderableTarget(const U8 te, const LLTextureEntry::eRenderableTarget target) override; /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; @@ -295,6 +294,10 @@ public: F32 getLightRadius() const; F32 getLightFalloff(const F32 fudge_factor = 1.f) const; F32 getLightCutoff() const; + + // Mirrors + bool setIsMirror(BOOL is_mirror); + void updateMirrorDrawable(); // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 5e999ed245..4094a487a9 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2406,7 +2406,15 @@ even though the user gets a free copy. name="object_horizontal" top_pad="10" width="278" /> - + Date: Tue, 29 Aug 2023 05:08:47 -0700 Subject: Add a probe strength uniform for hero probes. On standard reflection probes this doesn't really do anything. DRTVWR-583 --- indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + .../shaders/class1/interface/radianceGenF.glsl | 2 + indra/newview/llheroprobemanager.cpp | 73 +++++++--------------- indra/newview/llheroprobemanager.h | 7 ++- indra/newview/llreflectionmapmanager.cpp | 1 + indra/newview/llvovolume.cpp | 2 +- 7 files changed, 34 insertions(+), 53 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6730a12d6c..8bb5be0332 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1460,6 +1460,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("cloud_variance"); mReservedUniforms.push_back("reflection_probe_ambiance"); mReservedUniforms.push_back("max_probe_lod"); + mReservedUniforms.push_back("probe_strength"); mReservedUniforms.push_back("sh_input_r"); mReservedUniforms.push_back("sh_input_g"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 53c8323cff..6a5243a898 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -278,6 +278,7 @@ public: REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance" REFLECTION_PROBE_MAX_LOD, // "max_probe_lod" + REFLECTION_PROBE_STRENGTH, // "probe_strength" SH_INPUT_L1R, // "sh_input_r" SH_INPUT_L1G, // "sh_input_g" SH_INPUT_L1B, // "sh_input_b" diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index 9ecdf0bf77..cb6f34713c 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -38,6 +38,7 @@ in vec3 vary_dir; uniform float mipLevel; uniform int u_width; uniform float max_probe_lod; +uniform float probe_strength; // ============================================================================================================= @@ -163,5 +164,6 @@ void main() { vec3 N = normalize(vary_dir); frag_color = max(prefilterEnvMap(N), vec4(0)); + frag_color.a *= probe_strength; } // ============================================================================================================= diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 6374b10823..c385c9a99f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -104,68 +104,41 @@ void LLHeroProbeManager::update() llassert(mProbes[0] == mDefaultProbe); LLVector4a probe_pos; - - if (mHeroList.empty()) + LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; { - LLVector3 focus_point; + // Get the nearest hero. + float distance = F32_MAX; - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } + if (mNearestHero.notNull()) + { + distance = mNearestHero->mDistanceWRTCamera; } - if (focus_point.isExactlyZero()) + for (auto drawable : mHeroList) { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else + if (drawable.notNull() && drawable != mNearestHero) { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) + if (drawable->mDistanceWRTCamera < distance) { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + mIsInTransition = true; + mNearestHero = drawable; } } } - - probe_pos.load3(((focus_point)).mV); + } + + if (mIsInTransition && mHeroProbeStrength > 0.f) + { + mHeroProbeStrength -= 0.05f; } else { - // Get the nearest hero. - float distance = F32_MAX; + if (mNearestHero.notNull()) + probe_pos.set(mNearestHero->mXform.getPosition().mV[0], mNearestHero->mXform.getPosition().mV[1], camera_pos.mV[2]); - for (auto drawable : mHeroList) - { - if (drawable.notNull()) - { - if (drawable->mDistanceWRTCamera < distance) - { - probe_pos.load3(drawable->mXform.getPosition().mV); - } - } - } + + if (mHeroProbeStrength < 1.f) + mHeroProbeStrength += 0.05f; } static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); @@ -328,7 +301,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); + U32 res = mMipChain[0].getWidth(); for (int i = 0; i < mMipChain.size(); ++i) @@ -554,7 +528,6 @@ void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) if (mHeroList.find(drawablep) == mHeroList.end()) { mHeroList.insert(drawablep); - LL_INFOS() << "Added hero drawable." << LL_ENDL; } } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index c6df963cfd..24246af3d3 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -117,15 +117,18 @@ private: U32 mReflectionProbeCount; // resolution of reflection probes - U32 mProbeResolution = 128; + U32 mProbeResolution = 1024; // maximum LoD of reflection probes (mip levels - 1) F32 mMaxProbeLOD = 6.f; + + F32 mHeroProbeStrength = 1.f; + bool mIsInTransition = false; // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; LLDrawable::ordered_drawable_set_t mHeroList; - LLDrawable* mNearestHero; + LLPointer mNearestHero; }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index e855be8fbd..61143c61e8 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -714,6 +714,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mTexture->bind(channel); gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, 1.f); U32 res = mMipChain[0].getWidth(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6db1ae07de..3c3d8d5123 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1045,7 +1045,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - if (isMirror()) + //if (isMirror()) { gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); } -- cgit v1.2.3 From 32d1984bf98dce6e4938534342e67dbc40fbb073 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 1 Sep 2023 08:28:57 -0700 Subject: Temporary data model shenanigans. Should help tweak and tune placement with direct community guidance. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 66 +++++++++++++++++++++++++++--------- indra/newview/llheroprobemanager.h | 8 ++--- indra/newview/llpanelvolume.cpp | 4 --- indra/newview/llviewerobject.cpp | 34 ++++++++++++++++++- indra/newview/llviewerobject.h | 4 +++ indra/newview/llvovolume.cpp | 22 ++++++++---- indra/newview/llvovolume.h | 1 + 7 files changed, 107 insertions(+), 32 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c385c9a99f..166321930f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -109,16 +109,16 @@ void LLHeroProbeManager::update() // Get the nearest hero. float distance = F32_MAX; - if (mNearestHero.notNull()) + if (mNearestHero != nullptr) { - distance = mNearestHero->mDistanceWRTCamera; + distance = mNearestHero->mDrawable->mDistanceWRTCamera; } - for (auto drawable : mHeroList) + for (auto drawable : mHeroVOList) { - if (drawable.notNull() && drawable != mNearestHero) + if (drawable != nullptr && drawable != mNearestHero && drawable->mDrawable.notNull()) { - if (drawable->mDistanceWRTCamera < distance) + if (drawable->mDrawable->mDistanceWRTCamera < distance) { mIsInTransition = true; mNearestHero = drawable; @@ -133,8 +133,41 @@ void LLHeroProbeManager::update() } else { - if (mNearestHero.notNull()) - probe_pos.set(mNearestHero->mXform.getPosition().mV[0], mNearestHero->mXform.getPosition().mV[1], camera_pos.mV[2]); + + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) + { + + LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getPosition(); + switch (mNearestHero->mirrorPlacementMode()) { + case 0: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); + break; + case 1: + + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 2: + + probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + + case 3: + // Find the nearest point relative to the camera on the VOVolume. + LLVector4a hit_pos; + bool hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + probe_pos = hit_pos; + + break; + } + } if (mHeroProbeStrength < 1.f) @@ -505,7 +538,7 @@ void LLHeroProbeManager::cleanup() glDeleteBuffers(1, &mUBO); mUBO = 0; - mHeroList.clear(); + mHeroVOList.clear(); mNearestHero = nullptr; } @@ -523,18 +556,19 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerHeroDrawable(LLDrawable* drawablep) +void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { - if (mHeroList.find(drawablep) == mHeroList.end()) - { - mHeroList.insert(drawablep); - } + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + { + mHeroVOList.insert(drawablep); + LL_INFOS() << "Mirror drawable registered." << LL_ENDL; + } } -void LLHeroProbeManager::unregisterHeroDrawable(LLDrawable *drawablep) +void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) { - if (mHeroList.find(drawablep) != mHeroList.end()) + if (mHeroVOList.find(drawablep) != mHeroVOList.end()) { - mHeroList.erase(drawablep); + mHeroVOList.erase(drawablep); } } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 24246af3d3..b817b2396f 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -68,8 +68,8 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); - void registerHeroDrawable(LLDrawable* drawablep); - void unregisterHeroDrawable(LLDrawable* drawablep); + void registerHeroDrawable(LLVOVolume* drawablep); + void unregisterHeroDrawable(LLVOVolume* drawablep); private: friend class LLPipeline; @@ -128,7 +128,7 @@ private: // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; - LLDrawable::ordered_drawable_set_t mHeroList; - LLPointer mNearestHero; + std::set mHeroVOList; + LLVOVolume* mNearestHero; }; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index d62a640b5c..74c02099f8 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -755,10 +755,6 @@ void LLPanelVolume::sendIsMirror() } LLVOVolume *volobjp = (LLVOVolume *)objectp; - // Quick hack to set the mirror locally. - - gPipeline.mHeroProbeManager.registerHeroDrawable(volobjp->mDrawable); - BOOL value = getChild("Mirror Checkbox Ctrl")->getValue(); volobjp->setIsMirror(value); LL_INFOS() << "update mirror sent" << LL_ENDL; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 59a61f0c63..7032ce41d5 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1524,11 +1524,43 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); + std::stringstream ss(temp_string); + std::string word; + bool mirror_detected = false; + while (ss >> word) + { + if (word == "Mirror") + { + mirror_detected = true; + mIsMirror = true; + } + else if (word == "XAlign" && mIsMirror) + { + mMirrorPlacementMode = 0; + } + else if (word == "YAlign" && mIsMirror) + { + mMirrorPlacementMode = 1; + } + else if (word == "ZAlign" && mIsMirror) + { + mMirrorPlacementMode = 2; + } + else if (word == "NearestPoint" && mIsMirror) + { + mMirrorPlacementMode = 3; + } + } + LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); - + // alpha was flipped so that it zero encoded better coloru.mV[3] = 255 - coloru.mV[3]; + + if (mirror_detected) + coloru.mV[3] = 0; + mText->setColor(LLColor4(coloru)); mText->setString(temp_string); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 7175b088d9..c165f164a8 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -258,6 +258,7 @@ public: virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } virtual BOOL isMirror() const { return FALSE; } + virtual U8 mirrorPlacementMode() const { return 0; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -878,6 +879,9 @@ protected: F32 mPhysicsCost; F32 mLinksetPhysicsCost; + bool mIsMirror; + U8 mMirrorPlacementMode; + // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 3c3d8d5123..23580c4ec0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -249,6 +249,9 @@ LLVOVolume::~LLVOVolume() mTextureAnimp = NULL; delete mVolumeImpl; mVolumeImpl = NULL; + + if (mIsMirror) + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); gMeshRepo.unregisterMesh(this); @@ -1045,9 +1048,9 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - //if (isMirror()) + if (isMirror()) { - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); } updateRadius(); @@ -3396,17 +3399,22 @@ void LLVOVolume::updateMirrorDrawable() { if (isMirror()) { - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); } else { - gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); } } BOOL LLVOVolume::isMirror() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); + return mIsMirror; +} + +U8 LLVOVolume::mirrorPlacementMode() const +{ + return mMirrorPlacementMode; } BOOL LLVOVolume::isReflectionProbe() const @@ -4461,9 +4469,9 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u updateReflectionProbePtr(); if (isMirror()) - gPipeline.mHeroProbeManager.registerHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.registerHeroDrawable(this); else - gPipeline.mHeroProbeManager.unregisterHeroDrawable(mDrawable); + gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); } void LLVOVolume::updateReflectionProbePtr() diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 32c89ddae2..848f455e2a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,6 +298,7 @@ public: // Mirrors bool setIsMirror(BOOL is_mirror); void updateMirrorDrawable(); + U8 mirrorPlacementMode() const override; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); -- cgit v1.2.3 From 25aee5e983a8de712565d8241cbdb18da832a4d1 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 15:54:52 -0700 Subject: Some more modes for mirrors to place the probe. DRTVWR-583 --- .../shaders/class3/deferred/softenLightF.glsl | 3 + indra/newview/llheroprobemanager.cpp | 165 +++++++++++++-------- indra/newview/llviewerobject.cpp | 93 ++++++++---- 3 files changed, 171 insertions(+), 90 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 742b52b074..2483355205 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -280,6 +280,9 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); + + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; + } color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 166321930f..64c9ab1527 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -105,75 +105,121 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; + if (mHeroVOList.size() > 0) { - // Get the nearest hero. - float distance = F32_MAX; - - if (mNearestHero != nullptr) { - distance = mNearestHero->mDrawable->mDistanceWRTCamera; - } - - for (auto drawable : mHeroVOList) - { - if (drawable != nullptr && drawable != mNearestHero && drawable->mDrawable.notNull()) + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - if (drawable->mDrawable->mDistanceWRTCamera < distance) - { - mIsInTransition = true; - mNearestHero = drawable; + LLVector3 hero_pos = mNearestHero->getPosition(); + + // Make sure our camera is clamped to the hero's bounding box. + camera_pos.clamp(mNearestHero->getBoundingBoxAgent().getMinAgent(), mNearestHero->getBoundingBoxAgent().getMaxAgent()); + bool hit = false; + LLVector4a hit_pos; + LLVector3 focus_point; + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + LLQuaternion camera_rot; + + switch (mNearestHero->mirrorPlacementMode()) { + case 0: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); + break; + case 1: + + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 2: + + probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + + case 3: + // Find the nearest point relative to the camera on the VOVolume. + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + probe_pos = hit_pos; + break; + + case 4: + probe_pos.load3(hero_pos.mV); + break; + case 5: + focus_point.set(hero_pos.mV[0] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 6: + focus_point.set(hero_pos.mV[0] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 7: + + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); + + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } + + probe_pos.load3(focus_point.mV); + + break; + case 8: + camera_rot.setAngleAxis(180, 0, 0, 1); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; } } + + mHeroProbeStrength = 1; } } - - if (mIsInTransition && mHeroProbeStrength > 0.f) - { - mHeroProbeStrength -= 0.05f; - } else { - - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) - { - - LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getPosition(); - switch (mNearestHero->mirrorPlacementMode()) { - case 0: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); - break; - case 1: - - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 2: - - probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; - - case 3: - // Find the nearest point relative to the camera on the VOVolume. - LLVector4a hit_pos; - bool hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - probe_pos = hit_pos; - - break; - } - } - - - if (mHeroProbeStrength < 1.f) - mHeroProbeStrength += 0.05f; + probe_pos.load3(camera_pos.mV); } + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -224,7 +270,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); LLGLDisable blend(GL_BLEND); - + // downsample to placeholder map { gGL.matrixMode(gGL.MM_MODELVIEW); @@ -558,6 +604,7 @@ void LLHeroProbeManager::doOcclusion() void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { + mNearestHero = drawablep; if (mHeroVOList.find(drawablep) == mHeroVOList.end()) { mHeroVOList.insert(drawablep); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 7032ce41d5..adb4683af0 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -314,7 +314,9 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLastUpdateCached(FALSE), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), - mRiggedAttachedWarned(false) + mRiggedAttachedWarned(false), +mIsMirror(false), +mMirrorPlacementMode(3) { if (!is_global) { @@ -1148,6 +1150,61 @@ U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector return parent_id; } +void detectMirror(const std::string &str, bool &mirror, U8 &mode) +{ + + std::stringstream ss(str); + std::string word; + while (ss >> word) + { + if (word == "IsMirror") + { + mirror = true; + } + else if (word == "XAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera X placement." << LL_ENDL; + mode = 0; + } + else if (word == "YAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera Y placement." << LL_ENDL; + mode = 1; + } + else if (word == "ZAlign" && mirror) + { + LL_INFOS() << "Mirror wants camera Z placement." << LL_ENDL; + mode = 2; + } + else if (word == "NearestPoint" && mirror) + { + LL_INFOS() << "Mirror wants nearest point placement." << LL_ENDL; + mode = 3; + } + else if (word == "Center" && mirror) + { + LL_INFOS() << "Mirror wants center of object." << LL_ENDL; + mode = 4; + } + else if (word == "XMin" && mirror) + { + mode = 5; + } + else if (word == "XMax" && mirror) + { + mode = 6; + } + else if (word == "FocusPoint" && mirror) + { + mode = 7; + } + else if (word == "Reflected" && mirror) + { + mode = 8; + } + } +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -1524,33 +1581,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - std::stringstream ss(temp_string); - std::string word; - bool mirror_detected = false; - while (ss >> word) - { - if (word == "Mirror") - { - mirror_detected = true; - mIsMirror = true; - } - else if (word == "XAlign" && mIsMirror) - { - mMirrorPlacementMode = 0; - } - else if (word == "YAlign" && mIsMirror) - { - mMirrorPlacementMode = 1; - } - else if (word == "ZAlign" && mIsMirror) - { - mMirrorPlacementMode = 2; - } - else if (word == "NearestPoint" && mIsMirror) - { - mMirrorPlacementMode = 3; - } - } + detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1558,9 +1589,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // alpha was flipped so that it zero encoded better coloru.mV[3] = 255 - coloru.mV[3]; - if (mirror_detected) - coloru.mV[3] = 0; - mText->setColor(LLColor4(coloru)); mText->setString(temp_string); @@ -1940,6 +1968,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { std::string temp_string; dp->unpackString(temp_string, "Text"); + + detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + LLColor4U coloru; dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); coloru.mV[3] = 255 - coloru.mV[3]; -- cgit v1.2.3 From 091beab79872fbaf4e3e7de39c8e69ef08e5a1c7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 17:43:24 -0700 Subject: Even more placement modes. Reflected axis modes need work. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 93 +++++++++++++++++++++++++++++++++++- indra/newview/llviewerobject.cpp | 53 +++++++++++++++++--- 2 files changed, 138 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 64c9ab1527..caeb9d4e8e 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -159,6 +159,22 @@ void LLHeroProbeManager::update() probe_pos.load3(focus_point.mV); break; case 7: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 8: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 9: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 10: + focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); + probe_pos.load3(focus_point.mV); + break; + case 11: if (obj && obj->mDrawable && obj->isSelected()) { // focus on selected media object @@ -202,12 +218,87 @@ void LLHeroProbeManager::update() probe_pos.load3(focus_point.mV); break; - case 8: + case 12: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + + camera_rot.setAngleAxis(180, 1, 0, 0); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; + case 13: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + + camera_rot.setAngleAxis(180, 0, 1, 0); + focus_point = camera_pos - hero_pos; + focus_point.rotVec(camera_rot); + probe_pos.load3((camera_pos + focus_point).mV); + break; + case 14: + + hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), + LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), + -1, + FALSE, + FALSE, + FALSE, + NULL, + &hit_pos); + if (hit) + { + hero_pos.mV[0] = hit_pos.getF32ptr()[0]; + hero_pos.mV[1] = hit_pos.getF32ptr()[1]; + hero_pos.mV[2] = hit_pos.getF32ptr()[2]; + } + camera_rot.setAngleAxis(180, 0, 0, 1); focus_point = camera_pos - hero_pos; focus_point.rotVec(camera_rot); probe_pos.load3((camera_pos + focus_point).mV); break; + case 15: + probe_pos.set(camera_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); + break; + case 16: + probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); + break; + case 17: + probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]); + break; + case 18: + probe_pos.load3(camera_pos.mV); + break; + case 19: + probe_pos.load3(((camera_pos + hero_pos) / 2).mV); + break; } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index adb4683af0..950c672a42 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1163,27 +1163,22 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) } else if (word == "XAlign" && mirror) { - LL_INFOS() << "Mirror wants camera X placement." << LL_ENDL; mode = 0; } else if (word == "YAlign" && mirror) { - LL_INFOS() << "Mirror wants camera Y placement." << LL_ENDL; mode = 1; } else if (word == "ZAlign" && mirror) { - LL_INFOS() << "Mirror wants camera Z placement." << LL_ENDL; mode = 2; } else if (word == "NearestPoint" && mirror) { - LL_INFOS() << "Mirror wants nearest point placement." << LL_ENDL; mode = 3; } else if (word == "Center" && mirror) { - LL_INFOS() << "Mirror wants center of object." << LL_ENDL; mode = 4; } else if (word == "XMin" && mirror) @@ -1194,14 +1189,58 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mode = 6; } - else if (word == "FocusPoint" && mirror) + else if (word == "YMin" && mirror) { mode = 7; } - else if (word == "Reflected" && mirror) + else if (word == "YMax" && mirror) { mode = 8; } + else if (word == "ZMin" && mirror) + { + mode = 9; + } + else if (word == "ZMax" && mirror) + { + mode = 10; + } + else if (word == "FocusPoint" && mirror) + { + mode = 11; + } + else if (word == "ReflectedX" && mirror) + { + mode = 12; + } + else if (word == "ReflectedY" && mirror) + { + mode = 13; + } + else if (word == "ReflectedZ" && mirror) + { + mode = 14; + } + else if (word == "XYAlign" && mirror) + { + mode = 15; + } + else if (word == "XZAlign" && mirror) + { + mode = 16; + } + else if (word == "ZYAlign" && mirror) + { + mode = 17; + } + else if (word == "XYZAlign" && mirror) + { + mode = 18; + } + else if (word == "XYZAlignCenter" && mirror) + { + mode = 19; + } } } -- cgit v1.2.3 From d4c75b9b765631c1ccfc369e765529aefe3e061a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 21:29:05 -0700 Subject: Mostly fixed placement math. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 210 ++++++++--------------------------- indra/newview/llviewerobject.cpp | 74 +----------- 2 files changed, 47 insertions(+), 237 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index caeb9d4e8e..f1906272b8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -110,194 +110,57 @@ void LLHeroProbeManager::update() { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - LLVector3 hero_pos = mNearestHero->getPosition(); + LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); - // Make sure our camera is clamped to the hero's bounding box. - camera_pos.clamp(mNearestHero->getBoundingBoxAgent().getMinAgent(), mNearestHero->getBoundingBoxAgent().getMaxAgent()); bool hit = false; LLVector4a hit_pos; LLVector3 focus_point; LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); LLQuaternion camera_rot; + F32 angleInRadians = 180 * DEG_TO_RAD; + + LLMatrix4 rotationMatrix; + + LLVector3 translatedPoint; + LLVector3 rotatedTranslatedPoint; + LLVector3 rotatedPoint; switch (mNearestHero->mirrorPlacementMode()) { case 0: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]); - break; - case 1: - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 2: + hero_pos.mV[1] = camera_pos.mV[1]; - probe_pos.set(hero_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; + rotationMatrix.rotate(angleInRadians, LLVector4(1, 0, 0, 0)); - case 3: - // Find the nearest point relative to the camera on the VOVolume. - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - probe_pos = hit_pos; - break; + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - case 4: - probe_pos.load3(hero_pos.mV); - break; - case 5: - focus_point.set(hero_pos.mV[0] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); + probe_pos.load3(rotatedPoint.mV); break; - case 6: - focus_point.set(hero_pos.mV[0] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[0], hero_pos.mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 7: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 8: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[1], hero_pos.mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 9: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] - mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 10: - focus_point.set(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2] + mNearestHero->getBoundingBoxAgent().getExtentLocal().mV[2]); - probe_pos.load3(focus_point.mV); - break; - case 11: - - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } - } - - if (focus_point.isExactlyZero()) - { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); - - focus_point.set(result.getF32ptr()); - } - else - { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); - } - } - } + case 1: - probe_pos.load3(focus_point.mV); + hero_pos.mV[2] = camera_pos.mV[2]; - break; - case 12: + rotationMatrix.rotate(angleInRadians, LLVector4(0, 1, 0, 0)); - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - camera_rot.setAngleAxis(180, 1, 0, 0); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); + probe_pos.load3(rotatedPoint.mV); break; - case 13: + case 2: - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + hero_pos.mV[0] = camera_pos.mV[0]; - camera_rot.setAngleAxis(180, 0, 1, 0); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); - break; - case 14: + rotationMatrix.rotate(angleInRadians, LLVector4(0, 0, 1, 0)); - hit = mNearestHero->lineSegmentIntersect(LLVector4a(camera_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]), - LLVector4a(hero_pos.mV[0], hero_pos.mV[1], hero_pos.mV[2]), - -1, - FALSE, - FALSE, - FALSE, - NULL, - &hit_pos); - if (hit) - { - hero_pos.mV[0] = hit_pos.getF32ptr()[0]; - hero_pos.mV[1] = hit_pos.getF32ptr()[1]; - hero_pos.mV[2] = hit_pos.getF32ptr()[2]; - } + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; - camera_rot.setAngleAxis(180, 0, 0, 1); - focus_point = camera_pos - hero_pos; - focus_point.rotVec(camera_rot); - probe_pos.load3((camera_pos + focus_point).mV); - break; - case 15: - probe_pos.set(camera_pos.mV[0], camera_pos.mV[1], hero_pos.mV[2]); - break; - case 16: - probe_pos.set(camera_pos.mV[0], hero_pos.mV[1], camera_pos.mV[2]); - break; - case 17: - probe_pos.set(hero_pos.mV[0], camera_pos.mV[1], camera_pos.mV[2]); - break; - case 18: - probe_pos.load3(camera_pos.mV); - break; - case 19: - probe_pos.load3(((camera_pos + hero_pos) / 2).mV); + probe_pos.load3(rotatedPoint.mV); break; } } @@ -345,6 +208,14 @@ void LLHeroProbeManager::update() // In effect this simulates single-bounce lighting. void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { + // Make our object invisible. + + if (mNearestHero) + { + mNearestHero->setDrawableState(LLDrawable::FORCE_INVISIBLE, true); + gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); + } + // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; @@ -353,7 +224,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -512,6 +384,12 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) mMipChain[0].flush(); } + + if (mNearestHero) + { + mNearestHero->clearDrawableState(LLDrawable::FORCE_INVISIBLE, true); + gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); + } } void LLHeroProbeManager::updateUniforms() diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 950c672a42..dcdb66a6d4 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1161,85 +1161,17 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mirror = true; } - else if (word == "XAlign" && mirror) - { - mode = 0; - } - else if (word == "YAlign" && mirror) - { - mode = 1; - } - else if (word == "ZAlign" && mirror) - { - mode = 2; - } - else if (word == "NearestPoint" && mirror) - { - mode = 3; - } - else if (word == "Center" && mirror) - { - mode = 4; - } - else if (word == "XMin" && mirror) - { - mode = 5; - } - else if (word == "XMax" && mirror) - { - mode = 6; - } - else if (word == "YMin" && mirror) - { - mode = 7; - } - else if (word == "YMax" && mirror) - { - mode = 8; - } - else if (word == "ZMin" && mirror) - { - mode = 9; - } - else if (word == "ZMax" && mirror) - { - mode = 10; - } - else if (word == "FocusPoint" && mirror) - { - mode = 11; - } else if (word == "ReflectedX" && mirror) { - mode = 12; + mode = 0; } else if (word == "ReflectedY" && mirror) { - mode = 13; + mode = 1; } else if (word == "ReflectedZ" && mirror) { - mode = 14; - } - else if (word == "XYAlign" && mirror) - { - mode = 15; - } - else if (word == "XZAlign" && mirror) - { - mode = 16; - } - else if (word == "ZYAlign" && mirror) - { - mode = 17; - } - else if (word == "XYZAlign" && mirror) - { - mode = 18; - } - else if (word == "XYZAlignCenter" && mirror) - { - mode = 19; + mode = 2; } } } -- cgit v1.2.3 From 7761ebea4836e0e30148711159ea744bcaea28a9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 21:55:15 -0700 Subject: Update llheroprobemanager.cpp DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f1906272b8..13faf13a0f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -112,10 +112,8 @@ void LLHeroProbeManager::update() { LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); - bool hit = false; LLVector4a hit_pos; LLVector3 focus_point; - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); LLQuaternion camera_rot; F32 angleInRadians = 180 * DEG_TO_RAD; -- cgit v1.2.3 From 1433434bf134b76220fa2c31c16f36459b463e32 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 8 Sep 2023 23:01:16 -0700 Subject: Update reflectionProbeF.glsl DRTVWR-583 --- .../app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 7 ------- 1 file changed, 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index adbf7abdd1..549ac50280 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -71,9 +71,6 @@ layout (std140) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; - - vec4 heroPosition[1]; - int heroProbeCount; }; // Inputs @@ -523,10 +520,6 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, v = env_mat * v; -#if defined(HERO_PROBES) - vec3 mirror = textureLod(heroProbes, vec4(v.xyz, 0), lod).rgb; -#endif - vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y; return ret.rgb; -- cgit v1.2.3 From d6f15179d1a5c7bdb8977652aee557b3bd051cf7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sat, 9 Sep 2023 14:51:12 -0700 Subject: Remove the rebuild on the drawable. Wasn't working as expected anyways. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 13faf13a0f..7c616593fc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -206,14 +206,6 @@ void LLHeroProbeManager::update() // In effect this simulates single-bounce lighting. void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { - // Make our object invisible. - - if (mNearestHero) - { - mNearestHero->setDrawableState(LLDrawable::FORCE_INVISIBLE, true); - gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); - } - // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; @@ -382,12 +374,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) mMipChain[0].flush(); } - - if (mNearestHero) - { - mNearestHero->clearDrawableState(LLDrawable::FORCE_INVISIBLE, true); - gPipeline.markRebuild( mNearestHero->mDrawable, LLDrawable::REBUILD_ALL); - } } void LLHeroProbeManager::updateUniforms() -- cgit v1.2.3 From 3ff3e1a3537a5d051180aaf6223f5ddd8b540d35 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 20 Sep 2023 14:57:25 -0700 Subject: Remove some unnecessary irradiance map bits, also fix the leak. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 12 +++--------- indra/newview/llheroprobemanager.h | 3 --- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 7c616593fc..687ebbf168 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -300,12 +300,9 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) { LL_PROFILE_GPU_ZONE("probe mip copy"); mTexture->bind(0); - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); + glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); - //if (i == 0) - //{ - //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); - //} + mTexture->unbind(); } mMipChain[i].flush(); @@ -458,7 +455,7 @@ void LLHeroProbeManager::renderDebug() void LLHeroProbeManager::initReflectionMaps() { - U32 count = LL_MAX_REFLECTION_PROBE_COUNT; + U32 count = LL_MAX_HERO_PROBE_COUNT; if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { @@ -472,9 +469,6 @@ void LLHeroProbeManager::initReflectionMaps() // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); - if (mDefaultProbe.isNull()) { llassert(mProbes.empty()); // default probe MUST be the first probe created diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index b817b2396f..30943f739b 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -94,9 +94,6 @@ private: // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; - // storage for reflection probe irradiance maps - LLPointer mIrradianceMaps; - // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face); -- cgit v1.2.3 From d092f3e1dc1c322a0c3c1e55b9b6e1792d6b0f59 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 25 Sep 2023 12:18:02 -0700 Subject: Get the average normal of the face. DRTVWR-583 --- indra/newview/llface.cpp | 27 +++++++++++++++++++++++++++ indra/newview/llface.h | 5 +++++ indra/newview/llheroprobemanager.cpp | 10 ++++++++++ 3 files changed, 42 insertions(+) (limited to 'indra') diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c1776705f9..4dd991ee60 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -488,6 +488,33 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no return mGeomIndex; } +LLVector3 LLFace::getAverageNormal() +{ + if (!mHasAverageNormal) + { + if (mVertexBuffer.notNull()) + { + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + LLStrider normals; + mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); + LLVector3 normal_total; + + for (int i = 0; i < mVertexBuffer->getNumVerts(); i++) + { + normal_total += *normals.get(); + normals++; + } + + mAverageNormal = normal_total / mVertexBuffer->getNumVerts(); + mHasAverageNormal = true; + } + } + } + + return mAverageNormal; +} + void LLFace::updateCenterAgent() { if (mDrawablep->isActive()) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index eb3b47d6d6..d4f4313073 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -176,6 +176,8 @@ public: LLStrider &normals, LLStrider &texCoords, LLStrider &indices); + + LLVector3 getAverageNormal(); S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); @@ -278,6 +280,9 @@ private: U32 mIndicesCount; U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; + + LLVector3 mAverageNormal; + bool mHasAverageNormal; LLXformMatrix* mXform; diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 687ebbf168..c3d7ce6e76 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -118,11 +118,20 @@ void LLHeroProbeManager::update() F32 angleInRadians = 180 * DEG_TO_RAD; LLMatrix4 rotationMatrix; + + rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(0)->getAverageNormal())); LLVector3 translatedPoint; LLVector3 rotatedTranslatedPoint; LLVector3 rotatedPoint; + translatedPoint = camera_pos - hero_pos; + rotatedTranslatedPoint = translatedPoint * rotationMatrix; + rotatedPoint = rotatedTranslatedPoint + hero_pos; + + probe_pos.load3(rotatedPoint.mV); + + /* switch (mNearestHero->mirrorPlacementMode()) { case 0: @@ -161,6 +170,7 @@ void LLHeroProbeManager::update() probe_pos.load3(rotatedPoint.mV); break; } + */ } mHeroProbeStrength = 1; -- cgit v1.2.3 From 18b219cf83a1cd405cf36b9f58fc48f717409598 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 25 Sep 2023 19:20:46 -0700 Subject: Start removing the concept of placement mode - it's either a mirror or not. DRTVWR-583 --- indra/newview/llface.cpp | 31 ++++++++----------------------- indra/newview/llheroprobemanager.cpp | 5 +++-- indra/newview/llviewerobject.cpp | 31 +++++++++++++++++++------------ 3 files changed, 30 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 4dd991ee60..2c04224fa0 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -490,28 +490,6 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no LLVector3 LLFace::getAverageNormal() { - if (!mHasAverageNormal) - { - if (mVertexBuffer.notNull()) - { - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - LLStrider normals; - mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); - LLVector3 normal_total; - - for (int i = 0; i < mVertexBuffer->getNumVerts(); i++) - { - normal_total += *normals.get(); - normals++; - } - - mAverageNormal = normal_total / mVertexBuffer->getNumVerts(); - mHasAverageNormal = true; - } - } - } - return mAverageNormal; } @@ -1916,14 +1894,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, F32* normals = (F32*) norm.get(); LLVector4a* src = vf.mNormals; LLVector4a* end = src+num_vertices; - + + LLVector4a normal_total; + while (src < end) { LLVector4a normal; mat_normal.rotate(*src++, normal); normal.store4a(normals); + normal_total.add(normal); normals += 4; } + + normal_total.div(LLVector4a(num_vertices)); + + mAverageNormal = LLVector3(normal_total[0], normal_total[1], normal_total[2]); } if (rebuild_tangent) diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c3d7ce6e76..fe9f669365 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -110,7 +110,8 @@ void LLHeroProbeManager::update() { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - LLVector3 hero_pos = mNearestHero->mDrawable->mXform.getWorldPosition(); + + LLVector3 hero_pos = mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getPositionAgent(); LLVector4a hit_pos; LLVector3 focus_point; @@ -119,7 +120,7 @@ void LLHeroProbeManager::update() LLMatrix4 rotationMatrix; - rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(0)->getAverageNormal())); + rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getAverageNormal())); LLVector3 translatedPoint; LLVector3 rotatedTranslatedPoint; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index dcdb66a6d4..9ac9ef7ea6 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1161,18 +1161,25 @@ void detectMirror(const std::string &str, bool &mirror, U8 &mode) { mirror = true; } - else if (word == "ReflectedX" && mirror) - { - mode = 0; - } - else if (word == "ReflectedY" && mirror) - { - mode = 1; - } - else if (word == "ReflectedZ" && mirror) - { - mode = 2; - } + + if (mirror) + { + bool num = false; + std::string::const_iterator it = word.begin(); + while (it != word.end()) + { + num = std::isdigit(*it); + ++it; + + if (!num) + break; + } + + if (num) + { + mode = atoi(word.c_str()); + } + } } } -- cgit v1.2.3 From 80df1d681e7fd83fe0806f51a3f96275b10c0a5a Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 04:11:25 -0700 Subject: Can you say, generic reflectors? DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 100 +++++++++++------------------------ 1 file changed, 32 insertions(+), 68 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index fe9f669365..59345ca35f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -92,7 +92,7 @@ void LLHeroProbeManager::update() { U32 res = mProbeResolution; U32 count = log2((F32)res) + 0.5f; - + mMipChain.resize(count); for (int i = 0; i < count; ++i) { @@ -102,80 +102,44 @@ void LLHeroProbeManager::update() } llassert(mProbes[0] == mDefaultProbe); - + LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; if (mHeroVOList.size() > 0) { + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) - { + U8 mode = mNearestHero->mirrorPlacementMode(); + mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - LLVector3 hero_pos = mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getPositionAgent(); - - LLVector4a hit_pos; - LLVector3 focus_point; - LLQuaternion camera_rot; - F32 angleInRadians = 180 * DEG_TO_RAD; - - LLMatrix4 rotationMatrix; - - rotationMatrix.rotate(angleInRadians, LLVector4(mNearestHero->mDrawable->getFace(mNearestHero->mirrorPlacementMode())->getAverageNormal())); - - LLVector3 translatedPoint; - LLVector3 rotatedTranslatedPoint; - LLVector3 rotatedPoint; - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - - /* - switch (mNearestHero->mirrorPlacementMode()) { - case 0: - - hero_pos.mV[1] = camera_pos.mV[1]; - - rotationMatrix.rotate(angleInRadians, LLVector4(1, 0, 0, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - case 1: - - hero_pos.mV[2] = camera_pos.mV[2]; - - rotationMatrix.rotate(angleInRadians, LLVector4(0, 1, 0, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - case 2: - - hero_pos.mV[0] = camera_pos.mV[0]; - - rotationMatrix.rotate(angleInRadians, LLVector4(0, 0, 1, 0)); - - translatedPoint = camera_pos - hero_pos; - rotatedTranslatedPoint = translatedPoint * rotationMatrix; - rotatedPoint = rotatedTranslatedPoint + hero_pos; - - probe_pos.load3(rotatedPoint.mV); - break; - } - */ - } - - mHeroProbeStrength = 1; + LLFace *face = mNearestHero->mDrawable->getFace(mode); + LLVector3 hero_pos = face->getPositionAgent(); + + + // Calculate the average normal. + LLVector4a *posp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mPositions; + U16 *indp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mIndices; + // get first three vertices (first triangle) + LLVector4a v0 = posp[indp[0]]; + LLVector4a v1 = posp[indp[1]]; + LLVector4a v2 = posp[indp[2]]; + + v1.sub(v0); + v2.sub(v0); + LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); + + face_normal.normalize(); + face_normal *= face->getXform()->getWorldRotation(); + + LLVector3 offset = camera_pos - hero_pos; + LLVector3 project = face_normal * (offset * face_normal); + LLVector3 reject = offset - project; + LLVector3 point = (reject - project) + hero_pos; + + probe_pos.load3(point.mV); } + + mHeroProbeStrength = 1; } else { -- cgit v1.2.3 From 052d5c2802fa427ad97bc26ed4ec114b7fd1b80e Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 04:33:11 -0700 Subject: Wire up the debug settings. DRTVWR-583 --- indra/newview/app_settings/settings.xml | 13 ++++++++++++- indra/newview/llheroprobemanager.cpp | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f4e0682ee6..709dfd3844 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10421,8 +10421,19 @@ Type S32 Value - 512 + 1024 + RenderHeroProbeDistance + + Comment + Distance in meters for hero probes to render out to. + Persist + 1 + Type + F32 + Value + 16 + RenderReflectionProbeVolumes Comment diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 59345ca35f..dec75f5d2b 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -436,7 +436,7 @@ void LLHeroProbeManager::initReflectionMaps() { mReset = false; mReflectionProbeCount = count; - mProbeResolution = nhpo2(1024); + mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution"); mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1 mTexture = new LLCubeMapArray(); @@ -457,7 +457,7 @@ void LLHeroProbeManager::initReflectionMaps() mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; - mDefaultProbe->mDistance = 12.f; + mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance"); mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); -- cgit v1.2.3 From 1d3d94a514a74b41f1fafaef45e105774d5d8505 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 29 Sep 2023 16:25:25 -0700 Subject: Add probe near clipping. DRTVWR-583 --- indra/newview/app_settings/settings.xml | 11 +++++++++ indra/newview/llheroprobemanager.cpp | 41 +++++++++++++++------------------ indra/newview/llheroprobemanager.h | 2 +- indra/newview/llreflectionmap.cpp | 6 +++-- indra/newview/llreflectionmap.h | 2 +- 5 files changed, 35 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 709dfd3844..82545a5dda 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10434,6 +10434,17 @@ Value 16 + RenderHeroProbeNearClipOffset + + Comment + Distance offset in meters for hero probes to near clip. + Persist + 1 + Type + F32 + Value + 2.1 + RenderReflectionProbeVolumes Comment diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index dec75f5d2b..15b54ec6bc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -83,8 +83,8 @@ void LLHeroProbeManager::update() if (!mRenderTarget.isComplete()) { - U32 color_fmt = GL_RGB16F; - U32 targetRes = mProbeResolution * 4; // super sample + U32 color_fmt = GL_RGBA16F; + U32 targetRes = mProbeResolution; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } @@ -96,7 +96,7 @@ void LLHeroProbeManager::update() mMipChain.resize(count); for (int i = 0; i < count; ++i) { - mMipChain[i].allocate(res, res, GL_RGB16F); + mMipChain[i].allocate(res, res, GL_RGBA16F); res /= 2; } } @@ -105,6 +105,7 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; + F32 near_clip = 0.1f; if (mHeroVOList.size() > 0) { if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) @@ -136,6 +137,8 @@ void LLHeroProbeManager::update() LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; + near_clip = abs(dist_vec(hero_pos, point)) - gSavedSettings.getF32("RenderHeroProbeNearClipOffset"); + probe_pos.load3(point.mV); } @@ -163,7 +166,7 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mProbes[j], i); + updateProbeFace(mProbes[j], i, near_clip); } } @@ -179,12 +182,12 @@ void LLHeroProbeManager::update() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mAuxillaryRT; - probe->update(mRenderTarget.getWidth(), face, true); + probe->update(mRenderTarget.getWidth(), face, true, near_clip); gPipeline.mRT = &gPipeline.mMainRT; @@ -217,7 +220,8 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) static LLStaticHashedString znear("znear"); static LLStaticHashedString zfar("zfar"); - LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen; + LLRenderTarget *screen_rt = &gPipeline.mAuxillaryRT.screen; + LLRenderTarget *depth_rt = &gPipeline.mAuxillaryRT.deferredScreen; // perform a gaussian blur on the super sampled render before downsampling { @@ -247,6 +251,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gReflectionMipProgram.bind(); S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE); for (int i = 0; i < mMipChain.size(); ++i) { @@ -261,8 +266,11 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) gGL.getTexUnit(diffuseChannel)->bind(&(mMipChain[i - 1])); } + gGL.getTexUnit(depthChannel)->bind(depth_rt, true); - gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2)); + gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + gReflectionMipProgram.uniform1f(znear, probe->getNearClip()); + gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP); gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -315,10 +323,12 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face) static LLStaticHashedString sMipLevel("mipLevel"); static LLStaticHashedString sRoughness("roughness"); static LLStaticHashedString sWidth("u_width"); + static LLStaticHashedString sStrength("probe_strength"); gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); gRadianceGenProgram.uniform1f(sMipLevel, i); gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -385,21 +395,6 @@ void LLHeroProbeManager::updateUniforms() glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - -#if 0 - if (!gCubeSnapshot) - { - for (auto& probe : mProbes) - { - LLViewerObject* vobj = probe->mViewerObject; - if (vobj) - { - F32 time = (F32)gFrameTimeSeconds - probe->mLastUpdateTime; - vobj->setDebugText(llformat("%d/%d/%d/%.1f - %.1f/%.1f", probe->mCubeIndex, probe->mProbeIndex, (U32) probe->mNeighbors.size(), probe->mMinDepth, probe->mMaxDepth, time), time > 1.f ? LLColor4::white : LLColor4::green); - } - } - } -#endif } void LLHeroProbeManager::setUniforms() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 30943f739b..4a243e6cf2 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -95,7 +95,7 @@ private: LLPointer mVertexBuffer; // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face); + void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); // list of active reflection maps std::vector > mProbes; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 07c712a9a6..06624e8fea 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -63,8 +63,10 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic) { resolution /= 2; } + + F32 clip = (near_clip > 0) ? near_clip : getNearClip(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, getNearClip(), getIsDynamic() || force_dynamic); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index a23bdc3a98..e97b28c855 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face, bool force_dynamic = false); + void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); -- cgit v1.2.3 From e612d70fad8c6ec9335c109223211d516ebdf6f4 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 6 Oct 2023 06:21:53 -0700 Subject: Fix for probe stealing, and also make sure we're not super sampling. DRTVWR-583 --- indra/newview/llheroprobemanager.cpp | 41 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 15b54ec6bc..91d5f9b800 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -108,6 +108,34 @@ void LLHeroProbeManager::update() F32 near_clip = 0.1f; if (mHeroVOList.size() > 0) { + // Find our nearest hero candidate. + + float last_distance = 99999.f; + + for (auto vo : mHeroVOList) + { + if (vo) + { + if (vo->mDrawable.notNull()) + { + if (vo->mDrawable->mDistanceWRTCamera < last_distance) + { + mNearestHero = vo; + last_distance = vo->mDrawable->mDistanceWRTCamera; + } + } + else + { + // Valid drawables only please. Unregister this one. + unregisterHeroDrawable(vo); + } + } + else + { + unregisterHeroDrawable(vo); + } + } + if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { U8 mode = mNearestHero->mirrorPlacementMode(); @@ -226,7 +254,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + gGaussianProgram.uniform1f(resScale, 1.f / mProbeResolution); S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); // horizontal @@ -521,12 +549,11 @@ void LLHeroProbeManager::doOcclusion() void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) { - mNearestHero = drawablep; - if (mHeroVOList.find(drawablep) == mHeroVOList.end()) - { - mHeroVOList.insert(drawablep); - LL_INFOS() << "Mirror drawable registered." << LL_ENDL; - } + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + { + mHeroVOList.insert(drawablep); + LL_INFOS() << "Mirror drawable registered." << LL_ENDL; + } } void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) -- cgit v1.2.3 From 55f597e2ec363b5cb22fa8f7f5694f7ef6a17772 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:56:28 -0700 Subject: DRTVWR-592: Allow using RGBA textures for terrain, as the texture uploader does not consolidate opaque textures --- indra/llimage/llimage.cpp | 2 +- indra/newview/llfloaterregioninfo.cpp | 2 +- indra/newview/skins/default/xui/en/notifications.xml | 4 ++-- indra/newview/skins/default/xui/en/panel_region_terrain.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 031471d1fe..a96b6601bd 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1110,7 +1110,7 @@ void LLImageRaw::composite( LLImageRaw* src ) return; } - llassert(3 == src->getComponents()); + llassert((3 == src->getComponents()) || (4 == src->getComponents())); llassert(3 == dst->getComponents()); if( 3 == dst->getComponents() ) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index da7a4733c7..49ed58e766 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1338,7 +1338,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() //LL_INFOS() << "texture detail " << i << " is " << width << "x" << height << "x" << components << LL_ENDL; - if (components != 3) + if (components != 3 && components != 4) { LLSD args; args["TEXTURE_NUM"] = i+1; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f77b235408..5404ece6b4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -3980,7 +3980,7 @@ Are you sure you want to return objects owned by [USER_NAME]? Couldn't set region textures: Terrain texture [TEXTURE_NUM] has an invalid bit depth of [TEXTURE_BIT_DEPTH]. -Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. +Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. fail @@ -3991,7 +3991,7 @@ Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller ima Couldn't set region textures: Terrain texture [TEXTURE_NUM] is too large at [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y]. -Replace texture [TEXTURE_NUM] with a 24-bit [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. +Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. - Terrain Textures (requires 1024x1024, 24 bit .tga files) + Terrain Textures (maximum size: 1024x1024) Date: Fri, 13 Oct 2023 09:56:34 -0700 Subject: DRTVWR-592: (WIP) Add material terrain selection to GUI --- indra/newview/llfloaterregioninfo.cpp | 83 ++++++++++++++++++++++ indra/newview/llfloaterregioninfo.h | 3 + indra/newview/llpanelface.cpp | 2 +- indra/newview/lltexturectrl.cpp | 60 +++++++++------- indra/newview/lltexturectrl.h | 32 ++++++--- .../skins/default/xui/en/panel_region_terrain.xml | 76 ++++++++++++++++++-- 6 files changed, 212 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 49ed58e766..8c795432ea 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1394,12 +1394,20 @@ BOOL LLPanelRegionTerrainInfo::postBuild() initCtrl("terrain_raise_spin"); initCtrl("terrain_lower_spin"); + getChild("terrain_material_type")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onSelectMaterialType, this)); + std::string buffer; + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); initCtrl(buffer); } + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + initCtrl(buffer); + } for(S32 i = 0; i < CORNER_COUNT; ++i) { @@ -1419,6 +1427,81 @@ BOOL LLPanelRegionTerrainInfo::postBuild() return LLPanelRegionInfo::postBuild(); } +enum class TerrainMaterialType +{ + TEXTURE, + PBR_MATERIAL, + COUNT +}; + +TerrainMaterialType material_type_from_index(S32 index) +{ + if (index == 0) + { + return TerrainMaterialType::TEXTURE; + } + if (index == 1) + { + return TerrainMaterialType::PBR_MATERIAL; + } + return TerrainMaterialType::COUNT; +} + +// virtual +void LLPanelRegionTerrainInfo::refresh() +{ + std::string buffer; + + bool has_material_assets = false; + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + LLTextureCtrl* material_ctrl = getChild(buffer); + if (material_ctrl && material_ctrl->getImageAssetID().notNull()) + { + has_material_assets = true; + break; + } + } + + LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + if (material_type_ctrl) + { + const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; + material_type_ctrl->setEnabled(!(is_material_selected && has_material_assets)); + } +} + +void LLPanelRegionTerrainInfo::onSelectMaterialType() +{ + LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + if (!material_type_ctrl) { return; } + const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + const bool show_texture_controls = material_type == TerrainMaterialType::TEXTURE; + const bool show_material_controls = material_type == TerrainMaterialType::PBR_MATERIAL; + std::string buffer; + LLTextureCtrl* texture_ctrl; + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("texture_detail_%d", i); + texture_ctrl = getChild(buffer); + if (texture_ctrl) + { + texture_ctrl->setVisible(show_texture_controls); + } + } + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + texture_ctrl = getChild(buffer); + if (texture_ctrl) + { + texture_ctrl->setVisible(show_material_controls); + } + } +} + // virtual bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index c34dbb62e8..7b22002806 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -258,6 +258,9 @@ public: //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button + void refresh() override; + void onSelectMaterialType(); + virtual BOOL sendUpdate(); static void onClickDownloadRaw(void*); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 7d6015f557..ba379f77d8 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -328,7 +328,7 @@ BOOL LLPanelFace::postBuild() pbr_ctrl->setImmediateFilterPermMask(PERM_NONE); pbr_ctrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); pbr_ctrl->setBakeTextureEnabled(false); - pbr_ctrl->setInventoryPickType(LLTextureCtrl::PICK_MATERIAL); + pbr_ctrl->setInventoryPickType(EPickInventoryType::MATERIAL); } mTextureCtrl = getChild("texture control"); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 0dd1ff5483..ef58bba71e 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -176,7 +176,7 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mSetImageAssetIDCallback(NULL), mOnUpdateImageStatsCallback(NULL), mBakeTextureEnabled(FALSE), - mInventoryPickType(LLTextureCtrl::PICK_TEXTURE) + mInventoryPickType(EPickInventoryType::TEXTURE) { mCanApplyImmediately = can_apply_immediately; buildFromFile("floater_texture_ctrl.xml"); @@ -356,11 +356,11 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( bool is_material = cargo_type == DAD_MATERIAL; bool allow_dnd = false; - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { allow_dnd = is_material; } - else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (mInventoryPickType == EPickInventoryType::TEXTURE) { allow_dnd = is_texture || is_mesh; } @@ -570,7 +570,7 @@ void LLFloaterTexturePicker::draw() mGLTFMaterial = NULL; if (mImageAssetID.notNull()) { - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID); llassert(mGLTFMaterial == nullptr || dynamic_cast(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr); @@ -901,7 +901,7 @@ void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata) self->getChild("l_bake_use_texture_combo_box")->setVisible(index == 2 ? TRUE : FALSE); bool pipette_visible = (index == 0) - && (self->mInventoryPickType != LLTextureCtrl::PICK_MATERIAL); + && (self->mInventoryPickType != EPickInventoryType::MATERIAL); self->getChild("Pipette")->setVisible(pipette_visible); if (index == 2) @@ -966,15 +966,15 @@ void LLFloaterTexturePicker::onBtnAdd(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)userdata; - if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL) + if (self->mInventoryPickType == EPickInventoryType::TEXTURE_MATERIAL) { LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL_TEXTURE, true); } - else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (self->mInventoryPickType == EPickInventoryType::TEXTURE) { LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_IMAGE, true); } - else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + else if (self->mInventoryPickType == EPickInventoryType::MATERIAL) { LLFilePickerReplyThread::startPicker(boost::bind(&onPickerCallback, _1, self->getHandle()), LLFilePicker::FFLOAD_MATERIAL, true); } @@ -1229,16 +1229,16 @@ void LLFloaterTexturePicker::refreshLocalList() { mLocalScrollCtrl->clearRows(); - if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL) + if (mInventoryPickType == EPickInventoryType::TEXTURE_MATERIAL) { LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl); LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl); } - else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (mInventoryPickType == EPickInventoryType::TEXTURE) { LLLocalBitmapMgr::getInstance()->feedScrollList(mLocalScrollCtrl); } - else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + else if (mInventoryPickType == EPickInventoryType::MATERIAL) { LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(mLocalScrollCtrl); } @@ -1248,18 +1248,18 @@ void LLFloaterTexturePicker::refreshInventoryFilter() { U32 filter_types = 0x0; - if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL) + if (mInventoryPickType == EPickInventoryType::TEXTURE_MATERIAL) { filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; filter_types |= 0x1 << LLInventoryType::IT_MATERIAL; } - else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (mInventoryPickType == EPickInventoryType::TEXTURE) { filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; } - else if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + else if (mInventoryPickType == EPickInventoryType::MATERIAL) { filter_types |= 0x1 << LLInventoryType::IT_MATERIAL; } @@ -1294,13 +1294,13 @@ void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled) onModeSelect(0, this); } -void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryType type) +void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type) { mInventoryPickType = type; refreshLocalList(); refreshInventoryFilter(); - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { getChild("Pipette")->setVisible(false); } @@ -1316,7 +1316,7 @@ void LLFloaterTexturePicker::setInventoryPickType(LLTextureCtrl::EPickInventoryT setTitle(pick + mLabel); } - else if(mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + else if(mInventoryPickType == EPickInventoryType::MATERIAL) { setTitle(getString("pick_material")); } @@ -1352,16 +1352,16 @@ void LLFloaterTexturePicker::onPickerCallback(const std::vector& fi LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)handle.get(); self->mLocalScrollCtrl->clearRows(); - if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE_MATERIAL) + if (self->mInventoryPickType == EPickInventoryType::TEXTURE_MATERIAL) { LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); } - else if (self->mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (self->mInventoryPickType == EPickInventoryType::TEXTURE) { LLLocalBitmapMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); } - else if (self->mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + else if (self->mInventoryPickType == EPickInventoryType::MATERIAL) { LLLocalGLTFMaterialMgr::getInstance()->feedScrollList(self->mLocalScrollCtrl); } @@ -1374,7 +1374,7 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) if (inventory_item_id.notNull()) { LLToolPipette::getInstance()->setResult(TRUE, ""); - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { // tes have no data about material ids // Plus gltf materials are layered with overrides, @@ -1425,7 +1425,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) mShowLoadingPlaceholder( TRUE ), mOpenTexPreview(false), mBakeTextureEnabled(true), - mInventoryPickType(PICK_TEXTURE), + mInventoryPickType(p.pick_type), mImageAssetID(p.image_id), mDefaultImageAssetID(p.default_image_id), mDefaultImageName(p.default_image_name), @@ -1680,7 +1680,7 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) if (!mOpenTexPreview) { showPicker(FALSE); - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { //grab materials first... LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_MATERIAL)); @@ -1860,11 +1860,11 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, bool is_material = cargo_type == DAD_MATERIAL; bool allow_dnd = false; - if (mInventoryPickType == LLTextureCtrl::PICK_MATERIAL) + if (mInventoryPickType == EPickInventoryType::MATERIAL) { allow_dnd = is_material; } - else if (mInventoryPickType == LLTextureCtrl::PICK_TEXTURE) + else if (mInventoryPickType == EPickInventoryType::TEXTURE) { allow_dnd = is_texture || is_mesh; } @@ -2097,6 +2097,16 @@ LLSD LLTextureCtrl::getValue() const return LLSD(getImageAssetID()); } +namespace LLInitParam +{ + void TypeValues::declareValues() + { + declare("texture_material", EPickInventoryType::TEXTURE_MATERIAL); + declare("texture", EPickInventoryType::TEXTURE); + declare("material", EPickInventoryType::MATERIAL); + } +} + diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index c66e618782..28630d4ac4 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -64,10 +64,25 @@ bool get_is_predefined_texture(LLUUID asset_id); LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); bool get_can_copy_texture(LLUUID image_id); +enum class EPickInventoryType +{ + TEXTURE_MATERIAL = 0, + TEXTURE = 1, + MATERIAL = 2, +}; + +namespace LLInitParam +{ + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; +} + ////////////////////////////////////////////////////////////////////////////////////////// // LLTextureCtrl - class LLTextureCtrl : public LLUICtrl { @@ -79,19 +94,13 @@ public: TEXTURE_CANCEL } ETexturePickOp; - typedef enum e_pick_inventory_type - { - PICK_TEXTURE_MATERIAL = 0, - PICK_TEXTURE = 1, - PICK_MATERIAL = 2, - } EPickInventoryType; - public: struct Params : public LLInitParam::Block { Optional image_id; Optional default_image_id; Optional default_image_name; + Optional pick_type; Optional allow_no_texture; Optional can_apply_immediately; Optional no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty @@ -109,6 +118,7 @@ public: : image_id("image"), default_image_id("default_image_id"), default_image_name("default_image_name"), + pick_type("pick_type", EPickInventoryType::TEXTURE), allow_no_texture("allow_no_texture", false), can_apply_immediately("can_apply_immediately"), no_commit_on_selection("no_commit_on_selection", false), @@ -260,7 +270,7 @@ private: S32 mLabelWidth; bool mOpenTexPreview; bool mBakeTextureEnabled; - LLTextureCtrl::EPickInventoryType mInventoryPickType; + EPickInventoryType mInventoryPickType; }; ////////////////////////////////////////////////////////////////////////////////////////// @@ -350,7 +360,7 @@ public: void setLocalTextureEnabled(BOOL enabled); void setBakeTextureEnabled(BOOL enabled); - void setInventoryPickType(LLTextureCtrl::EPickInventoryType type); + void setInventoryPickType(EPickInventoryType type); static void onPickerCallback(const std::vector& filenames, LLHandle handle); @@ -396,7 +406,7 @@ private: bool mCanApply; bool mCanPreview; bool mPreviewSettingChanged; - LLTextureCtrl::EPickInventoryType mInventoryPickType; + EPickInventoryType mInventoryPickType; texture_selected_callback mTextureSelectedCallback; diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index 5e0dad445f..e36fb05647 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -76,29 +76,47 @@ left="8" top="30" width="460" /> + + + + - Terrain Textures (maximum size: 1024x1024) + width="200"> + Maximum size: 1024x1024 + + + + Date: Fri, 13 Oct 2023 09:56:39 -0700 Subject: DRTVWR-592: Use overrides, make mac build happy --- indra/newview/llfloaterregioninfo.h | 61 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 7b22002806..43a69e5804 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -75,9 +75,9 @@ class LLFloaterRegionInfo : public LLFloater public: - /*virtual*/ void onOpen(const LLSD& key); + void onOpen(const LLSD& key) override; /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ BOOL postBuild(); + BOOL postBuild() override; static void processEstateOwnerRequest(LLMessageSystem* msg, void**); @@ -98,7 +98,7 @@ public: static LLPanelRegionEnvironment* getPanelEnvironment(); // from LLPanel - virtual void refresh(); + void refresh() override; void onRegionChanged(); void requestRegionInfo(); @@ -145,7 +145,7 @@ public: virtual bool refreshFromRegion(LLViewerRegion* region); virtual bool estateUpdate(LLMessageSystem* msg) { return true; } - virtual BOOL postBuild(); + BOOL postBuild() override; virtual void updateChild(LLUICtrl* child_ctrl); void enableButton(const std::string& btn_name, BOOL enable = TRUE); @@ -185,16 +185,15 @@ public: : LLPanelRegionInfo() {} ~LLPanelRegionGeneralInfo() {} - virtual bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; - // LLPanel - virtual BOOL postBuild(); + BOOL postBuild() override; void onBtnSet(); void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; void onClickKick(); void onKickCommit(const uuid_vec_t& ids); static void onClickKickAll(void* userdata); @@ -215,13 +214,13 @@ public: LLPanelRegionDebugInfo() : LLPanelRegionInfo(), mTargetAvatar() {} ~LLPanelRegionDebugInfo() {} - // LLPanel - virtual BOOL postBuild(); + + BOOL postBuild() override; - virtual bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; void onClickChooseAvatar(); void callbackAvatarID(const uuid_vec_t& ids, const std::vector names); @@ -248,9 +247,9 @@ public: LLPanelRegionTerrainInfo() : LLPanelRegionInfo() {} ~LLPanelRegionTerrainInfo() {} - virtual BOOL postBuild(); // LLPanel + BOOL postBuild() override; - virtual bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator + bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region BOOL validateTextureSizes(); @@ -261,14 +260,15 @@ public: void refresh() override; void onSelectMaterialType(); - virtual BOOL sendUpdate(); - static void onClickDownloadRaw(void*); static void onClickUploadRaw(void*); static void onClickBakeTerrain(void*); bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); bool callbackTextureHeights(const LLSD& notification, const LLSD& response); +protected: + BOOL sendUpdate() override; + private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; @@ -307,13 +307,12 @@ public: static void updateEstateName(const std::string& name); static void updateEstateOwnerName(const std::string& name); - virtual bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; virtual bool estateUpdate(LLMessageSystem* msg); - // LLPanel - virtual BOOL postBuild(); + BOOL postBuild() override; virtual void updateChild(LLUICtrl* child_ctrl); - virtual void refresh(); + void refresh() override; void refreshFromEstate(); @@ -323,7 +322,7 @@ public: void setOwnerName(const std::string& name); protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; // confirmation dialog callback bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response); @@ -343,10 +342,9 @@ public: LLPanelEstateCovenant(); ~LLPanelEstateCovenant() {} - // LLPanel - virtual BOOL postBuild(); + BOOL postBuild() override; virtual void updateChild(LLUICtrl* child_ctrl); - virtual bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; virtual bool estateUpdate(LLMessageSystem* msg); // LLView overrides @@ -386,7 +384,7 @@ public: } EAssetStatus; protected: - virtual BOOL sendUpdate(); + BOOL sendUpdate() override; LLTextBox* mEstateNameText; LLTextBox* mEstateOwnerText; LLTextBox* mLastModifiedText; @@ -405,16 +403,19 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo public: LLPanelRegionExperiences(){} - /*virtual*/ BOOL postBuild(); - virtual BOOL sendUpdate(); + BOOL postBuild() override; static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); static void infoCallback(LLHandle handle, const LLSD& content); - bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; void sendPurchaseRequest()const; void processResponse( const LLSD& content ); + +protected: + BOOL sendUpdate() override; + private: void refreshRegionExperiences(); @@ -439,7 +440,7 @@ class LLPanelEstateAccess : public LLPanelRegionInfo public: LLPanelEstateAccess(); - virtual BOOL postBuild(); + BOOL postBuild() override; virtual void updateChild(LLUICtrl* child_ctrl); void updateControls(LLViewerRegion* region); @@ -448,7 +449,7 @@ public: void setPendingUpdate(bool pending) { mPendingUpdate = pending; } bool getPendingUpdate() { return mPendingUpdate; } - virtual bool refreshFromRegion(LLViewerRegion* region); + bool refreshFromRegion(LLViewerRegion* region) override; private: void onClickAddAllowedAgent(); -- cgit v1.2.3 From 410ab689919cd2915afc4d881b58b749d477fffc Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:56:44 -0700 Subject: DRTVWR-592: (WIP) Save PBR material terrain (does not yet render) --- indra/newview/llfloaterregioninfo.cpp | 101 ++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 8c795432ea..e87064bc63 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -606,6 +606,26 @@ LLPanelRegionEnvironment* LLFloaterRegionInfo::getPanelEnvironment() return panel; } +enum class TerrainMaterialType +{ + TEXTURE, + PBR_MATERIAL, + COUNT +}; + +TerrainMaterialType material_type_from_index(S32 index) +{ + if (index == 0) + { + return TerrainMaterialType::TEXTURE; + } + if (index == 1) + { + return TerrainMaterialType::PBR_MATERIAL; + } + return TerrainMaterialType::COUNT; +} + // static LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain() { @@ -1321,6 +1341,17 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { + // *TODO: Don't early-exit in PBR material terrain editing mode, and + // instead do some reasonable checks that the PBR material is compatible + // with the terrain rendering pipeline. Err on the side of permissive. + LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + if (material_type_ctrl) + { + const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; + if (is_material_selected) { return TRUE; } + } + static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { @@ -1427,26 +1458,6 @@ BOOL LLPanelRegionTerrainInfo::postBuild() return LLPanelRegionInfo::postBuild(); } -enum class TerrainMaterialType -{ - TEXTURE, - PBR_MATERIAL, - COUNT -}; - -TerrainMaterialType material_type_from_index(S32 index) -{ - if (index == 0) - { - return TerrainMaterialType::TEXTURE; - } - if (index == 1) - { - return TerrainMaterialType::PBR_MATERIAL; - } - return TerrainMaterialType::COUNT; -} - // virtual void LLPanelRegionTerrainInfo::refresh() { @@ -1518,18 +1529,31 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) getChild("region_text")->setValue(LLSD(region->getName())); LLVLComposition* compp = region->getComposition(); - LLTextureCtrl* texture_ctrl; + + // Are these 4 texture IDs or 4 material IDs? Who knows! Let's set the IDs on both pickers for now. + // *TODO: Determine the asset type of IDs, to determine which editing mode to display. + LLTextureCtrl* asset_ctrl; std::string buffer; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); - texture_ctrl = getChild(buffer); - if(texture_ctrl) + asset_ctrl = getChild(buffer); + if(asset_ctrl) { LL_DEBUGS() << "Detail Texture " << i << ": " << compp->getDetailTextureID(i) << LL_ENDL; LLUUID tmp_id(compp->getDetailTextureID(i)); - texture_ctrl->setImageAssetID(tmp_id); + asset_ctrl->setImageAssetID(tmp_id); + } + } + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl) + { + LLUUID tmp_id(compp->getDetailTextureID(i)); + asset_ctrl->setImageAssetID(tmp_id); } } @@ -1596,17 +1620,36 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() } } - LLTextureCtrl* texture_ctrl; + LLTextureCtrl* asset_ctrl; std::string id_str; LLMessageSystem* msg = gMessageSystem; + // Use material IDs instead of texture IDs if all material IDs are set + S32 materials_used = 0; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - buffer = llformat("texture_detail_%d", i); - texture_ctrl = getChild(buffer); - if(texture_ctrl) + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl && asset_ctrl->getImageAssetID().notNull()) + { + ++materials_used; + } + } + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + if (materials_used == TERRAIN_TEXTURE_COUNT) + { + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + } + else + { + buffer = llformat("texture_detail_%d", i); + asset_ctrl = getChild(buffer); + } + if(asset_ctrl) { - LLUUID tmp_id(texture_ctrl->getImageAssetID()); + LLUUID tmp_id(asset_ctrl->getImageAssetID()); tmp_id.toString(id_str); buffer = llformat("%d %s", i, id_str.c_str()); strings.push_back(buffer); -- cgit v1.2.3 From 2d10941459cf66d34073925c136d70bd6dbece3f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:56:49 -0700 Subject: DRTVWR-592: (WIP) More work on terrain texture editing GUI --- indra/newview/llfloaterregioninfo.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index e87064bc63..ff7012efb5 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1624,15 +1624,24 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() std::string id_str; LLMessageSystem* msg = gMessageSystem; - // Use material IDs instead of texture IDs if all material IDs are set + // Use material IDs instead of texture IDs if all material IDs are set, AND the mode is set to PBR materials. S32 materials_used = 0; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); - if(asset_ctrl && asset_ctrl->getImageAssetID().notNull()) - { - ++materials_used; + LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + if (material_type_ctrl) + { + const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; + if (is_material_selected) + { + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl && asset_ctrl->getImageAssetID().notNull()) + { + ++materials_used; + } + } } } for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) -- cgit v1.2.3 From 76bf3390eb119a7dfd879bbbc31b4d5e687aac8f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:56:55 -0700 Subject: DRTVWR-592: (WIP) Detect when terrain materials are loaded, use as fallback when terrain textures do not load --- indra/newview/lldrawpoolterrain.cpp | 32 +++++++- indra/newview/llfetchedgltfmaterial.h | 1 + indra/newview/llfloaterregioninfo.cpp | 6 +- indra/newview/llviewerregion.cpp | 16 ++-- indra/newview/llvlcomposition.cpp | 135 +++++++++++++++++++++++----------- indra/newview/llvlcomposition.h | 21 ++++-- 6 files changed, 150 insertions(+), 61 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 77189dceae..687ff5f462 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -121,8 +121,36 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures() LLVLComposition *compp = regionp->getComposition(); for (S32 i = 0; i < 4; i++) { - compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); - compp->mDetailTextures[i]->addTextureStats(1024.f * 1024.f); + constexpr LLGLTexture::EBoostLevel level = LLGLTexture::BOOST_TERRAIN; + constexpr float stats = 1024.f * 1024.f; + + LLPointer& tex = compp->mDetailTextures[i]; + llassert(tex.notNull()); + tex->setBoostLevel(level); + tex->addTextureStats(stats); + + LLPointer& mat = compp->mDetailMaterials[i]; + llassert(mat.notNull()); + if (mat->mBaseColorTexture) + { + mat->mBaseColorTexture->setBoostLevel(level); + mat->mBaseColorTexture->addTextureStats(stats); + } + if (mat->mNormalTexture) + { + mat->mNormalTexture->setBoostLevel(level); + mat->mNormalTexture->addTextureStats(stats); + } + if (mat->mMetallicRoughnessTexture) + { + mat->mMetallicRoughnessTexture->setBoostLevel(level); + mat->mMetallicRoughnessTexture->addTextureStats(stats); + } + if (mat->mEmissiveTexture) + { + mat->mEmissiveTexture->setBoostLevel(level); + mat->mEmissiveTexture->addTextureStats(stats); + } } } diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 1668657281..ce4d33a213 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -49,6 +49,7 @@ public: void bind(LLViewerTexture* media_tex = nullptr); bool isFetching() const { return mFetching; } + bool isLoaded() const { return !mFetching; } // Textures used for fetching/rendering LLPointer mBaseColorTexture; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index ff7012efb5..b5698c1d65 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1541,8 +1541,8 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) if(asset_ctrl) { LL_DEBUGS() << "Detail Texture " << i << ": " - << compp->getDetailTextureID(i) << LL_ENDL; - LLUUID tmp_id(compp->getDetailTextureID(i)); + << compp->getDetailAssetID(i) << LL_ENDL; + LLUUID tmp_id(compp->getDetailAssetID(i)); asset_ctrl->setImageAssetID(tmp_id); } } @@ -1552,7 +1552,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) asset_ctrl = getChild(buffer); if(asset_ctrl) { - LLUUID tmp_id(compp->getDetailTextureID(i)); + LLUUID tmp_id(compp->getDetailAssetID(i)); asset_ctrl->setImageAssetID(tmp_id); } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 6b92b16ef4..9d3e63333e 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2962,20 +2962,20 @@ void LLViewerRegion::unpackRegionHandshake() // Get the 4 textures for land msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); - changed |= (tmp_id != compp->getDetailTextureID(0)); - compp->setDetailTextureID(0, tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(0)); + compp->setDetailAssetID(0, tmp_id); msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); - changed |= (tmp_id != compp->getDetailTextureID(1)); - compp->setDetailTextureID(1, tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(1)); + compp->setDetailAssetID(1, tmp_id); msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); - changed |= (tmp_id != compp->getDetailTextureID(2)); - compp->setDetailTextureID(2, tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(2)); + compp->setDetailAssetID(2, tmp_id); msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); - changed |= (tmp_id != compp->getDetailTextureID(3)); - compp->setDetailTextureID(3, tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(3)); + compp->setDetailAssetID(3, tmp_id); // Get the start altitude and range values for land textures F32 tmp_f32; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 001fab7755..8480c9ce3d 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -65,10 +65,10 @@ LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 mSurfacep = surfacep; // Load Terrain Textures - Original ones - setDetailTextureID(0, TERRAIN_DIRT_DETAIL); - setDetailTextureID(1, TERRAIN_GRASS_DETAIL); - setDetailTextureID(2, TERRAIN_MOUNTAIN_DETAIL); - setDetailTextureID(3, TERRAIN_ROCK_DETAIL); + setDetailAssetID(0, TERRAIN_DIRT_DETAIL); + setDetailAssetID(1, TERRAIN_GRASS_DETAIL); + setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL); + setDetailAssetID(3, TERRAIN_ROCK_DETAIL); // Initialize the texture matrix to defaults. for (S32 i = 0; i < CORNER_COUNT; ++i) @@ -93,7 +93,7 @@ void LLVLComposition::setSurface(LLSurface *surfacep) } -void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id) +void LLVLComposition::setDetailAssetID(S32 corner, const LLUUID& id) { if(id.isNull()) { @@ -104,6 +104,25 @@ void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id) mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id); mDetailTextures[corner]->setNoDelete() ; mRawImages[corner] = NULL; + // *TODO: Decide if we have textures or materials. Whichever loads first determines the terrain type. + // *TODO: As the material textures are loaded, prevent deletion + mDetailMaterials[corner] = LLGLTFMaterialList::getMaterial(id); +} + +void LLVLComposition::setDetailMaterialID(S32 corner, const LLUUID& id) +{ + if(id.isNull()) + { + mDetailMaterials[corner] = nullptr; + } + else + { + // This is terrain material, but we are not setting it as BOOST_TERRAIN + // since we will be manipulating it later as needed. + mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id); + mDetailTextures[corner]->setNoDelete() ; + mRawImages[corner] = NULL; + } } BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, @@ -149,10 +168,6 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus // simple height) - // Heights map into textures as 0-1 = first, 1-2 = second, etc. - // So we need to compress heights into this range. - const S32 NUM_TEXTURES = 4; - const F32 xyScaleInv = (1.f / xyScale); const F32 zScaleInv = (1.f / zScale); @@ -199,7 +214,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component twiddle *= noise_magnitude; - F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range; + F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range; scaled_noisy_height = llmax(0.f, scaled_noisy_height); scaled_noisy_height = llmin(3.f, scaled_noisy_height); @@ -211,6 +226,37 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, static const U32 BASE_SIZE = 128; +// Boost the texture loading priority +// Return true when ready to use (i.e. texture is sufficiently loaded) +bool boost_texture_until_ready(LLPointer& tex) +{ + if (tex->getDiscardLevel() < 0) + { + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail + tex->addTextureStats(BASE_SIZE*BASE_SIZE); + return false; + } + if ((tex->getDiscardLevel() != 0 && + (tex->getWidth() < BASE_SIZE || + tex->getHeight() < BASE_SIZE))) + { + S32 width = tex->getFullWidth(); + S32 height = tex->getFullHeight(); + S32 min_dim = llmin(width, height); + S32 ddiscard = 0; + while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) + { + ddiscard++; + min_dim /= 2; + } + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail + tex->setMinDiscardLevel(ddiscard); + tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority + return false; + } + return true; +} + BOOL LLVLComposition::generateComposition() { @@ -220,35 +266,44 @@ BOOL LLVLComposition::generateComposition() return FALSE; } - for (S32 i = 0; i < 4; i++) + bool textures_ready = true; + for (S32 i = 0; i < ASSET_COUNT; i++) { - if (mDetailTextures[i]->getDiscardLevel() < 0) - { - mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail - mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); - return FALSE; - } - if ((mDetailTextures[i]->getDiscardLevel() != 0 && - (mDetailTextures[i]->getWidth() < BASE_SIZE || - mDetailTextures[i]->getHeight() < BASE_SIZE))) - { - S32 width = mDetailTextures[i]->getFullWidth(); - S32 height = mDetailTextures[i]->getFullHeight(); - S32 min_dim = llmin(width, height); - S32 ddiscard = 0; - while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) - { - ddiscard++; - min_dim /= 2; - } - mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail - mDetailTextures[i]->setMinDiscardLevel(ddiscard); - mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); // priority - return FALSE; - } + if (!boost_texture_until_ready(mDetailTextures[i])) + { + textures_ready = false; + break; + } } + + if (textures_ready) + { + return TRUE; + } - return TRUE; + bool materials_ready = true; + for (S32 i = 0; i < ASSET_COUNT; i++) + { + const LLPointer& mat = mDetailMaterials[i]; + if (!mat.isLoaded() || + (mat->mBaseColorTexture && !boost_texture_until_ready(mat->mBaseColorTexture)) || + (mat->mNormalTexture && !boost_texture_until_ready(mat->mNormalTexture)) || + (mat->mMetallicRoughnessTexture && !boost_texture_until_ready(mat->mMetallicRoughnessTexture)) || + (mat->mEmissiveTexture && !boost_texture_until_ready(mat->mEmissiveTexture))) + { + materials_ready = false; + break; + } + } + + if (materials_ready) + { + return TRUE; + } + else + { + return FALSE; + } } BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, @@ -469,16 +524,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, return TRUE; } -LLUUID LLVLComposition::getDetailTextureID(S32 corner) +LLUUID LLVLComposition::getDetailAssetID(S32 corner) { + llassert(mDetailTextures[corner] && mDetailMaterials[corner] && mDetailTextures[corner]->getID() == mDetailMaterials[corner].getID()); return mDetailTextures[corner]->getID(); } -LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner) -{ - return mDetailTextures[corner]; -} - F32 LLVLComposition::getStartHeight(S32 corner) { return mStartHeight[corner]; diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 2dd04ac5a5..3e465efc95 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -28,10 +28,13 @@ #define LL_LLVLCOMPOSITION_H #include "llviewerlayer.h" -#include "llviewertexture.h" +#include "llpointer.h" class LLSurface; +class LLViewerFetchedTexture; +class LLFetchedGLTFMaterial; + class LLVLComposition : public LLViewerLayer { public: @@ -46,6 +49,10 @@ public: // Generate texture from composition values. BOOL generateTexture(const F32 x, const F32 y, const F32 width, const F32 height); + // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. + // So we need to compress heights into this range. + static const S32 ASSET_COUNT = 4; + // Use these as indeces ito the get/setters below that use 'corner' enum ECorner { @@ -55,12 +62,12 @@ public: NORTHEAST = 3, CORNER_COUNT = 4 }; - LLUUID getDetailTextureID(S32 corner); - LLViewerFetchedTexture* getDetailTexture(S32 corner); + + LLUUID getDetailAssetID(S32 asset); F32 getStartHeight(S32 corner); F32 getHeightRange(S32 corner); - void setDetailTextureID(S32 corner, const LLUUID& id); + void setDetailAssetID(S32 asset, const LLUUID& id); void setStartHeight(S32 corner, F32 start_height); void setHeightRange(S32 corner, F32 range); @@ -73,8 +80,10 @@ protected: LLSurface *mSurfacep; BOOL mTexturesLoaded; - LLPointer mDetailTextures[CORNER_COUNT]; - LLPointer mRawImages[CORNER_COUNT]; + // TODO: Set flag to indicate whether the textures or materials loaded first + LLPointer mDetailTextures[ASSET_COUNT]; + LLPointer mRawImages[ASSET_COUNT]; + LLPointer mDetailMaterials[ASSET_COUNT]; F32 mStartHeight[CORNER_COUNT]; F32 mHeightRange[CORNER_COUNT]; -- cgit v1.2.3 From 94e824739b5e8408b52a03e5af8e3fb4e124c616 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:02 -0700 Subject: DRTVWR-592: Render PBR material terrain like legacy, using baseColor texture --- indra/newview/lldrawpoolterrain.cpp | 29 ++++- indra/newview/llvlcomposition.cpp | 239 ++++++++++++++++++++++-------------- indra/newview/llvlcomposition.h | 17 ++- 3 files changed, 187 insertions(+), 98 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 687ff5f462..9f0f9fd1b2 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -256,10 +256,31 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; - LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; - LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; - LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; + + LLViewerTexture *detail_texture0p; + LLViewerTexture *detail_texture1p; + LLViewerTexture *detail_texture2p; + LLViewerTexture *detail_texture3p; + BOOL use_textures = compp->texturesReady() || !compp->materialsReady(); + if (use_textures) + { + detail_texture0p = compp->mDetailTextures[0]; + detail_texture1p = compp->mDetailTextures[1]; + detail_texture2p = compp->mDetailTextures[2]; + detail_texture3p = compp->mDetailTextures[3]; + } + else // use materials + { + detail_texture0p = compp->mDetailMaterials[0]->mBaseColorTexture; + detail_texture1p = compp->mDetailMaterials[1]->mBaseColorTexture; + detail_texture2p = compp->mDetailMaterials[2]->mBaseColorTexture; + detail_texture3p = compp->mDetailMaterials[3]->mBaseColorTexture; + LLViewerTexture* blank = LLViewerFetchedTexture::sWhiteImagep; + if (!detail_texture0p) { detail_texture0p = blank; } + if (!detail_texture1p) { detail_texture1p = blank; } + if (!detail_texture2p) { detail_texture2p = blank; } + if (!detail_texture3p) { detail_texture3p = blank; } + } LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8480c9ce3d..9ad1a3dd17 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -34,6 +34,8 @@ #include "lltextureview.h" #include "llviewertexture.h" #include "llviewertexturelist.h" +#include "llfetchedgltfmaterial.h" +#include "llgltfmateriallist.h" #include "llviewerregion.h" #include "noise.h" #include "llregionhandle.h" // for from_region_handle @@ -59,8 +61,7 @@ F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : - LLViewerLayer(width, scale), - mParamsReady(FALSE) + LLViewerLayer(width, scale) { mSurfacep = surfacep; @@ -76,9 +77,11 @@ LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight"); mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange"); } - mTexScaleX = 16.f; - mTexScaleY = 16.f; - mTexturesLoaded = FALSE; + + for (S32 i = 0; i < ASSET_COUNT; ++i) + { + mMaterialTexturesSet[i] = false; + } } @@ -92,8 +95,19 @@ void LLVLComposition::setSurface(LLSurface *surfacep) mSurfacep = surfacep; } +LLPointer fetch_terrain_texture(const LLUUID& id) +{ + if (id.isNull()) + { + return nullptr; + } + + LLPointer tex = LLViewerTextureManager::getFetchedTexture(id); + tex->setNoDelete(); + return tex; +} -void LLVLComposition::setDetailAssetID(S32 corner, const LLUUID& id) +void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id) { if(id.isNull()) { @@ -101,28 +115,11 @@ void LLVLComposition::setDetailAssetID(S32 corner, const LLUUID& id) } // This is terrain texture, but we are not setting it as BOOST_TERRAIN // since we will be manipulating it later as needed. - mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id); - mDetailTextures[corner]->setNoDelete() ; - mRawImages[corner] = NULL; - // *TODO: Decide if we have textures or materials. Whichever loads first determines the terrain type. - // *TODO: As the material textures are loaded, prevent deletion - mDetailMaterials[corner] = LLGLTFMaterialList::getMaterial(id); -} - -void LLVLComposition::setDetailMaterialID(S32 corner, const LLUUID& id) -{ - if(id.isNull()) - { - mDetailMaterials[corner] = nullptr; - } - else - { - // This is terrain material, but we are not setting it as BOOST_TERRAIN - // since we will be manipulating it later as needed. - mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id); - mDetailTextures[corner]->setNoDelete() ; - mRawImages[corner] = NULL; - } + mDetailTextures[asset] = fetch_terrain_texture(id); + mRawImages[asset] = NULL; + LLPointer& mat = mDetailMaterials[asset]; + mat = gGLTFMaterialList.getMaterial(id); + mMaterialTexturesSet[asset] = false; } BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, @@ -228,82 +225,130 @@ static const U32 BASE_SIZE = 128; // Boost the texture loading priority // Return true when ready to use (i.e. texture is sufficiently loaded) -bool boost_texture_until_ready(LLPointer& tex) +// static +BOOL LLVLComposition::textureReady(LLPointer& tex, BOOL boost) { if (tex->getDiscardLevel() < 0) { - tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail - tex->addTextureStats(BASE_SIZE*BASE_SIZE); - return false; + if (boost) + { + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail + tex->addTextureStats(BASE_SIZE*BASE_SIZE); + } + return FALSE; } if ((tex->getDiscardLevel() != 0 && (tex->getWidth() < BASE_SIZE || tex->getHeight() < BASE_SIZE))) { - S32 width = tex->getFullWidth(); - S32 height = tex->getFullHeight(); - S32 min_dim = llmin(width, height); - S32 ddiscard = 0; - while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) + if (boost) { - ddiscard++; - min_dim /= 2; + S32 width = tex->getFullWidth(); + S32 height = tex->getFullHeight(); + S32 min_dim = llmin(width, height); + S32 ddiscard = 0; + while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) + { + ddiscard++; + min_dim /= 2; + } + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail + tex->setMinDiscardLevel(ddiscard); + tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority } - tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail - tex->setMinDiscardLevel(ddiscard); - tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority - return false; + return FALSE; } - return true; + return TRUE; } -BOOL LLVLComposition::generateComposition() +// Boost the loading priority of every known texture in the material +// Return true when ready to use (i.e. material and all textures within are sufficiently loaded) +// static +BOOL LLVLComposition::materialReady(LLPointer& mat, bool& textures_set, BOOL boost) { + if (!mat->isLoaded()) + { + return FALSE; + } - if (!mParamsReady) - { - // All the parameters haven't been set yet (we haven't gotten the message from the sim) - return FALSE; - } + // Material is loaded, but textures may not be + if (!textures_set) + { + // *NOTE: These can sometimes be set to to nullptr due to + // updateTEMaterialTextures. For the sake of robustness, we emulate + // that fetching behavior by setting textures of null IDs to nullptr. + mat->mBaseColorTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); + mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); + mat->mMetallicRoughnessTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); + mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); + textures_set = true; - bool textures_ready = true; + return FALSE; + } + + if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && !textureReady(mat->mBaseColorTexture, boost)) + { + return FALSE; + } + if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && !textureReady(mat->mNormalTexture, boost)) + { + return FALSE; + } + if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && !textureReady(mat->mMetallicRoughnessTexture, boost)) + { + return FALSE; + } + if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && !textureReady(mat->mEmissiveTexture, boost)) + { + return FALSE; + } + + return TRUE; +} + +BOOL LLVLComposition::texturesReady(BOOL boost) +{ for (S32 i = 0; i < ASSET_COUNT; i++) { - if (!boost_texture_until_ready(mDetailTextures[i])) + if (!textureReady(mDetailTextures[i], boost)) { - textures_ready = false; - break; + return FALSE; } } + return TRUE; +} - if (textures_ready) - { - return TRUE; - } - - bool materials_ready = true; +BOOL LLVLComposition::materialsReady(BOOL boost) +{ for (S32 i = 0; i < ASSET_COUNT; i++) { - const LLPointer& mat = mDetailMaterials[i]; - if (!mat.isLoaded() || - (mat->mBaseColorTexture && !boost_texture_until_ready(mat->mBaseColorTexture)) || - (mat->mNormalTexture && !boost_texture_until_ready(mat->mNormalTexture)) || - (mat->mMetallicRoughnessTexture && !boost_texture_until_ready(mat->mMetallicRoughnessTexture)) || - (mat->mEmissiveTexture && !boost_texture_until_ready(mat->mEmissiveTexture))) + if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost)) { - materials_ready = false; - break; + return FALSE; } } + return TRUE; +} - if (materials_ready) +BOOL LLVLComposition::generateComposition() +{ + if (!mParamsReady) + { + // All the parameters haven't been set yet (we haven't gotten the message from the sim) + return FALSE; + } + + if (texturesReady(TRUE)) { return TRUE; } - else + + if (materialsReady(TRUE)) { - return FALSE; + return TRUE; } + + return FALSE; } BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, @@ -323,15 +368,28 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, // // These have already been validated by generateComposition. - U8* st_data[4]; - S32 st_data_size[4]; // for debugging + U8* st_data[ASSET_COUNT]; + S32 st_data_size[ASSET_COUNT]; // for debugging + + const bool use_textures = texturesReady(); - for (S32 i = 0; i < 4; i++) + for (S32 i = 0; i < ASSET_COUNT; i++) { if (mRawImages[i].isNull()) { // Read back a raw image for this discard level, if it exists - S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight()); + LLViewerFetchedTexture* tex; + if (use_textures) + { + tex = mDetailTextures[i]; + } + else + { + tex = mDetailMaterials[i]->mBaseColorTexture; + if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } + } + + S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); S32 ddiscard = 0; while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) { @@ -339,31 +397,31 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, min_dim /= 2; } - BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ; - if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. + BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL) ; + if(tex->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. { - if (mDetailTextures[i]->getFetchPriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage()) + if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage()) { - mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP); - mDetailTextures[i]->forceToRefetchTexture(ddiscard); + tex->setBoostLevel(LLGLTexture::BOOST_MAP); + tex->forceToRefetchTexture(ddiscard); } if(delete_raw) { - mDetailTextures[i]->destroyRawImage() ; + tex->destroyRawImage() ; } - LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << " Discard: " << ddiscard << LL_ENDL; + LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << tex->getID() << " Discard: " << ddiscard << LL_ENDL; return FALSE; } - mRawImages[i] = mDetailTextures[i]->getRawImage() ; + mRawImages[i] = tex->getRawImage() ; if(delete_raw) { - mDetailTextures[i]->destroyRawImage() ; + tex->destroyRawImage() ; } - if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || - mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE || - mDetailTextures[i]->getComponents() != 3) + if (tex->getWidth(ddiscard) != BASE_SIZE || + tex->getHeight(ddiscard) != BASE_SIZE || + tex->getComponents() != 3) { LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); newraw->composite(mRawImages[i]); @@ -514,7 +572,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); - for (S32 i = 0; i < 4; i++) + for (S32 i = 0; i < ASSET_COUNT; i++) { // Un-boost detatil textures (will get re-boosted if rendering in high detail) mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE); @@ -526,7 +584,10 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, LLUUID LLVLComposition::getDetailAssetID(S32 corner) { - llassert(mDetailTextures[corner] && mDetailMaterials[corner] && mDetailTextures[corner]->getID() == mDetailMaterials[corner].getID()); + llassert(mDetailTextures[corner] && mDetailMaterials[corner]); + // *HACK: Assume both the the material and texture were fetched in the same + // way using the same UUID. However, we may not know at this point which + // one will load. return mDetailTextures[corner]->getID(); } diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 3e465efc95..af0cf9323c 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -30,6 +30,8 @@ #include "llviewerlayer.h" #include "llpointer.h" +#include "llimage.h" + class LLSurface; class LLViewerFetchedTexture; @@ -75,21 +77,26 @@ public: friend class LLDrawPoolTerrain; void setParamsReady() { mParamsReady = TRUE; } BOOL getParamsReady() const { return mParamsReady; } + BOOL texturesReady(BOOL boost = FALSE); + BOOL materialsReady(BOOL boost = FALSE); + protected: - BOOL mParamsReady; + static BOOL textureReady(LLPointer& tex, BOOL boost = FALSE); + static BOOL materialReady(LLPointer& mat, bool& textures_set, BOOL boost = FALSE); + + BOOL mParamsReady = FALSE; LLSurface *mSurfacep; - BOOL mTexturesLoaded; - // TODO: Set flag to indicate whether the textures or materials loaded first LLPointer mDetailTextures[ASSET_COUNT]; LLPointer mRawImages[ASSET_COUNT]; LLPointer mDetailMaterials[ASSET_COUNT]; + bool mMaterialTexturesSet[ASSET_COUNT]; F32 mStartHeight[CORNER_COUNT]; F32 mHeightRange[CORNER_COUNT]; - F32 mTexScaleX; - F32 mTexScaleY; + F32 mTexScaleX = 16.f; + F32 mTexScaleY = 16.f; }; #endif //LL_LLVLCOMPOSITION_H -- cgit v1.2.3 From 3553fec2084b8be3f3de86cec293c1e363c1388e Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:10 -0700 Subject: DRTVWR-592: (WIP) Separate code path for terrain rendering and shaders. Just copy/paste for now. Use same draw pool --- .../shaders/class1/deferred/pbrterrainF.glsl | 61 +++++++++ .../shaders/class1/deferred/pbrterrainV.glsl | 77 +++++++++++ indra/newview/lldrawpoolterrain.cpp | 152 +++++++++++++++++---- indra/newview/lldrawpoolterrain.h | 2 + indra/newview/llviewershadermgr.cpp | 53 ++++--- indra/newview/llviewershadermgr.h | 2 +- indra/newview/llvlcomposition.cpp | 11 +- indra/newview/llvlcomposition.h | 1 + 8 files changed, 303 insertions(+), 56 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl new file mode 100644 index 0000000000..96903aeba8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -0,0 +1,61 @@ +/** + * @file class1\deferred\terrainF.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +out vec4 frag_data[4]; + +uniform sampler2D detail_0; +uniform sampler2D detail_1; +uniform sampler2D detail_2; +uniform sampler2D detail_3; +uniform sampler2D alpha_ramp; + +in vec3 pos; +in vec3 vary_normal; +in vec4 vary_texcoord0; +in vec4 vary_texcoord1; + +vec2 encode_normal(vec3 n); + +void main() +{ + vec4 color0 = texture2D(detail_0, vary_texcoord0.xy); + vec4 color1 = texture2D(detail_1, vary_texcoord0.xy); + vec4 color2 = texture2D(detail_2, vary_texcoord0.xy); + vec4 color3 = texture2D(detail_3, vary_texcoord0.xy); + + float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a; + float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; + float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; + vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); + + outColor.a = 0.0; // yes, downstream atmospherics + + frag_data[0] = outColor; + frag_data[1] = vec4(0.0,0.0,0.0,-1.0); + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl new file mode 100644 index 0000000000..e8747a1f6b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -0,0 +1,77 @@ +/** + * @file class1\environment\pbrterrainV.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +uniform mat3 normal_matrix; +uniform mat4 texture_matrix0; +uniform mat4 modelview_projection_matrix; + +in vec3 position; +in vec3 normal; +in vec4 diffuse_color; +in vec2 texcoord0; +in vec2 texcoord1; + +out vec3 pos; +out vec3 vary_normal; +out vec4 vary_texcoord0; +out vec4 vary_texcoord1; + +uniform vec4 object_plane_s; +uniform vec4 object_plane_t; + +vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) +{ + vec4 tcoord; + + tcoord.x = dot(vpos, tp0); + tcoord.y = dot(vpos, tp1); + tcoord.z = tc.z; + tcoord.w = tc.w; + + tcoord = mat * tcoord; + + return tcoord; +} + +void main() +{ + //transform vertex + vec4 pre_pos = vec4(position.xyz, 1.0); + vec4 t_pos = modelview_projection_matrix * pre_pos; + + gl_Position = t_pos; + pos = t_pos.xyz; + + vary_normal = normalize(normal_matrix * normal); + + // Transform and pass tex coords + vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; + + vec4 t = vec4(texcoord1,0,1); + + vary_texcoord0.zw = t.xy; + vary_texcoord1.xy = t.xy-vec2(2.0, 0.0); + vary_texcoord1.zw = t.xy-vec2(1.0, 0.0); +} diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 9f0f9fd1b2..16d982ea90 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -158,10 +158,6 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); LLFacePool::beginRenderPass(pass); - - sShader = &gDeferredTerrainProgram; - - sShader->bind(); } void LLDrawPoolTerrain::endDeferredPass(S32 pass) @@ -256,31 +252,139 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - - LLViewerTexture *detail_texture0p; - LLViewerTexture *detail_texture1p; - LLViewerTexture *detail_texture2p; - LLViewerTexture *detail_texture3p; - BOOL use_textures = compp->texturesReady() || !compp->materialsReady(); + const BOOL use_textures = compp->useTextures(); + if (use_textures) { - detail_texture0p = compp->mDetailTextures[0]; - detail_texture1p = compp->mDetailTextures[1]; - detail_texture2p = compp->mDetailTextures[2]; - detail_texture3p = compp->mDetailTextures[3]; + // Use textures + sShader = &gDeferredTerrainProgram; + sShader->bind(); + renderFullShaderTextures(); } - else // use materials + else { - detail_texture0p = compp->mDetailMaterials[0]->mBaseColorTexture; - detail_texture1p = compp->mDetailMaterials[1]->mBaseColorTexture; - detail_texture2p = compp->mDetailMaterials[2]->mBaseColorTexture; - detail_texture3p = compp->mDetailMaterials[3]->mBaseColorTexture; - LLViewerTexture* blank = LLViewerFetchedTexture::sWhiteImagep; - if (!detail_texture0p) { detail_texture0p = blank; } - if (!detail_texture1p) { detail_texture1p = blank; } - if (!detail_texture2p) { detail_texture2p = blank; } - if (!detail_texture3p) { detail_texture3p = blank; } + // Use materials + sShader = &gDeferredPBRTerrainProgram; + sShader->bind(); + renderFullShaderPBR(); } +} + +void LLDrawPoolTerrain::renderFullShaderTextures() +{ + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + + LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; + LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; + LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; + LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; + + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; + + LLVector4 tp0, tp1; + + tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); + tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); + + // + // detail texture 0 + // + S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); + gGL.getTexUnit(detail0)->bind(detail_texture0p); + gGL.getTexUnit(detail0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail0)->activate(); + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); + + LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); + + // + // detail texture 1 + // + S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); + gGL.getTexUnit(detail1)->bind(detail_texture1p); + gGL.getTexUnit(detail1)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail1)->activate(); + + // detail texture 2 + // + S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); + gGL.getTexUnit(detail2)->bind(detail_texture2p); + gGL.getTexUnit(detail2)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail2)->activate(); + + + // detail texture 3 + // + S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); + gGL.getTexUnit(detail3)->bind(detail_texture3p); + gGL.getTexUnit(detail3)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail3)->activate(); + + // + // Alpha Ramp + // + S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); + gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + // GL_BLEND disabled by default + drawLoop(); + + // Disable multitexture + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); + + gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(alpha_ramp)->disable(); + gGL.getTexUnit(alpha_ramp)->activate(); + + gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail3)->disable(); + gGL.getTexUnit(detail3)->activate(); + + gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail2)->disable(); + gGL.getTexUnit(detail2)->activate(); + + gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail1)->disable(); + gGL.getTexUnit(detail1)->activate(); + + //---------------------------------------------------------------------------- + // Restore Texture Unit 0 defaults + + gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail0)->activate(); +} + +void LLDrawPoolTerrain::renderFullShaderPBR() +{ + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + + LLViewerTexture *detail_texture0p = compp->mDetailMaterials[0]->mBaseColorTexture; + LLViewerTexture *detail_texture1p = compp->mDetailMaterials[1]->mBaseColorTexture; + LLViewerTexture *detail_texture2p = compp->mDetailMaterials[2]->mBaseColorTexture; + LLViewerTexture *detail_texture3p = compp->mDetailMaterials[3]->mBaseColorTexture; + LLViewerTexture* blank = LLViewerFetchedTexture::sWhiteImagep; + if (!detail_texture0p) { detail_texture0p = blank; } + if (!detail_texture1p) { detail_texture1p = blank; } + if (!detail_texture2p) { detail_texture2p = blank; } + if (!detail_texture3p) { detail_texture3p = blank; } LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 03bef31541..fbf6a8d917 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -79,6 +79,8 @@ protected: void renderFull2TU(); void renderFull4TU(); void renderFullShader(); + void renderFullShaderTextures(); + void renderFullShaderPBR(); void drawLoop(); private: diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 4559d71d6d..19b3c59cae 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -138,7 +138,6 @@ LLGLSLShader gDeferredSkinnedDiffuseProgram; LLGLSLShader gDeferredSkinnedBumpProgram; LLGLSLShader gDeferredBumpProgram; LLGLSLShader gDeferredTerrainProgram; -LLGLSLShader gDeferredTerrainWaterProgram; LLGLSLShader gDeferredTreeProgram; LLGLSLShader gDeferredTreeShadowProgram; LLGLSLShader gDeferredSkinnedTreeShadowProgram; @@ -226,6 +225,7 @@ LLGLSLShader gDeferredPBRAlphaProgram; LLGLSLShader gDeferredSkinnedPBRAlphaProgram; LLGLSLShader gDeferredPBRAlphaWaterProgram; LLGLSLShader gDeferredSkinnedPBRAlphaWaterProgram; +LLGLSLShader gDeferredPBRTerrainProgram; //helper for making a rigged variant of a given shader bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) @@ -291,7 +291,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredEmissiveProgram); mShaderList.push_back(&gDeferredSkinnedEmissiveProgram); mShaderList.push_back(&gDeferredAvatarEyesProgram); - mShaderList.push_back(&gDeferredTerrainWaterProgram); mShaderList.push_back(&gDeferredAvatarAlphaProgram); mShaderList.push_back(&gDeferredWLSkyProgram); mShaderList.push_back(&gDeferredWLCloudProgram); @@ -939,7 +938,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedBumpProgram.unload(); gDeferredImpostorProgram.unload(); gDeferredTerrainProgram.unload(); - gDeferredTerrainWaterProgram.unload(); gDeferredLightProgram.unload(); for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i) { @@ -1026,6 +1024,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedPBRAlphaProgram.unload(); gDeferredPBRAlphaWaterProgram.unload(); gDeferredSkinnedPBRAlphaWaterProgram.unload(); + gDeferredPBRTerrainProgram.unload(); return TRUE; } @@ -1492,6 +1491,27 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = shader->createShader(NULL, NULL); llassert(success); } + + if (success) + { + gDeferredPBRTerrainProgram.mName = "Deferred PBR Terrain Shader"; + gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; + gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; + gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; + gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + gDeferredPBRTerrainProgram.mFeatures.hasWaterFog = true; + gDeferredPBRTerrainProgram.mFeatures.calculatesAtmospherics = true; + gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true; + gDeferredPBRTerrainProgram.mFeatures.hasGamma = true; + gDeferredPBRTerrainProgram.mFeatures.hasTransport = true; + + gDeferredPBRTerrainProgram.mShaderFiles.clear(); + gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainV.glsl", GL_VERTEX_SHADER)); + gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainF.glsl", GL_FRAGMENT_SHADER)); + gDeferredPBRTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredPBRTerrainProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -2430,8 +2450,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredTerrainProgram.mName = "Deferred Terrain Shader"; gDeferredTerrainProgram.mFeatures.encodesNormal = true; gDeferredTerrainProgram.mFeatures.hasSrgb = true; - gDeferredTerrainProgram.mFeatures.calculatesLighting = false; - gDeferredTerrainProgram.mFeatures.hasLighting = false; gDeferredTerrainProgram.mFeatures.isAlphaLighting = true; gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels gDeferredTerrainProgram.mFeatures.hasWaterFog = true; @@ -2447,31 +2465,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredTerrainWaterProgram.mName = "Deferred Terrain Underwater Shader"; - gDeferredTerrainWaterProgram.mFeatures.encodesNormal = true; - gDeferredTerrainWaterProgram.mFeatures.hasSrgb = true; - gDeferredTerrainWaterProgram.mFeatures.calculatesLighting = false; - gDeferredTerrainWaterProgram.mFeatures.hasLighting = false; - gDeferredTerrainWaterProgram.mFeatures.isAlphaLighting = true; - gDeferredTerrainWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredTerrainWaterProgram.mFeatures.hasWaterFog = true; - gDeferredTerrainWaterProgram.mFeatures.calculatesAtmospherics = true; - gDeferredTerrainWaterProgram.mFeatures.hasAtmospherics = true; - gDeferredTerrainWaterProgram.mFeatures.hasGamma = true; - - gDeferredTerrainWaterProgram.mShaderFiles.clear(); - gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER)); - gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER)); - gDeferredTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gDeferredTerrainWaterProgram.clearPermutations(); - gDeferredTerrainWaterProgram.addPermutation("WATER_FOG", "1"); - success = gDeferredTerrainWaterProgram.createShader(NULL, NULL); - llassert(success); - } - if (success) { gDeferredAvatarProgram.mName = "Deferred Avatar Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b0b9719d76..6765703ab8 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -211,7 +211,6 @@ extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; -extern LLGLSLShader gDeferredTerrainWaterProgram; extern LLGLSLShader gDeferredTreeProgram; extern LLGLSLShader gDeferredTreeShadowProgram; extern LLGLSLShader gDeferredLightProgram; @@ -279,4 +278,5 @@ extern LLGLSLShader gDeferredPBROpaqueProgram; extern LLGLSLShader gDeferredPBRAlphaProgram; extern LLGLSLShader gDeferredPBRAlphaWaterProgram; extern LLGLSLShader gHUDPBRAlphaProgram; +extern LLGLSLShader gDeferredPBRTerrainProgram; #endif diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 9ad1a3dd17..5d711f4e5d 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -228,6 +228,8 @@ static const U32 BASE_SIZE = 128; // static BOOL LLVLComposition::textureReady(LLPointer& tex, BOOL boost) { + llassert(tex.notNull()); + if (tex->getDiscardLevel() < 0) { if (boost) @@ -306,6 +308,13 @@ BOOL LLVLComposition::materialReady(LLPointer& mat, bool& return TRUE; } +BOOL LLVLComposition::useTextures() +{ + LL_PROFILE_ZONE_SCOPED; + + return texturesReady() || !materialsReady(); +} + BOOL LLVLComposition::texturesReady(BOOL boost) { for (S32 i = 0; i < ASSET_COUNT; i++) @@ -371,7 +380,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, U8* st_data[ASSET_COUNT]; S32 st_data_size[ASSET_COUNT]; // for debugging - const bool use_textures = texturesReady(); + const bool use_textures = useTextures(); for (S32 i = 0; i < ASSET_COUNT; i++) { diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index af0cf9323c..504441d0f2 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -77,6 +77,7 @@ public: friend class LLDrawPoolTerrain; void setParamsReady() { mParamsReady = TRUE; } BOOL getParamsReady() const { return mParamsReady; } + BOOL useTextures(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); -- cgit v1.2.3 From 474923e3cb29df35e8807006ad16861eb1dc24d0 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:17 -0700 Subject: DRTVWR-592: (WIP) Add code for generating terrain tangents (not yet used) --- indra/newview/llvosurfacepatch.cpp | 169 +++++++++++++++++++++++++++++-------- indra/newview/llvosurfacepatch.h | 16 ++-- 2 files changed, 147 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 3f5f56d378..bfa622b6c1 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -43,6 +43,9 @@ #include "pipeline.h" #include "llspatialpartition.h" +#include "mikktspace/mikktspace.h" +// mikktspace implementation already included in llvovolume object file + F32 LLVOSurfacePatch::sLODFactor = 1.f; LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -241,39 +244,53 @@ BOOL LLVOSurfacePatch::updateLOD() return TRUE; } -void LLVOSurfacePatch::getGeometry(LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp) +void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp) { LLFace* facep = mDrawable->getFace(0); - if (facep) - { - U32 index_offset = facep->getGeomIndex(); - - updateMainGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateNorthGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - updateEastGeometry(facep, - verticesp, - normalsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); - } + if (!facep) + { + return; + } + + U32 index_offset = facep->getGeomIndex(); + + updateMainGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + updateNorthGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + updateEastGeometry(facep, + verticesp, + normalsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); + + const bool has_tangents = tangentsp.get() != nullptr; + if (has_tangents) + { + // Last but not least, calculate tangents for the updated terrain vertices + genTerrainTangents(facep, + verticesp, + normalsp, + tangentsp, + texCoords0p); + } } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -759,6 +776,88 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, index_offset += num_vertices; } +struct MikktData +{ + MikktData(S32 vert_offet, + S32 vert_size, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p) : + vert_offset(vert_offset), + vert_size(vert_size), + verticesp(verticesp), + normalsp(normalsp), + texCoords0p(texCoords0p) + { + } + S32 vert_offset; + U32 vert_size; + LLStrider verticesp; + LLStrider normalsp; + LLStrider tangentsp; + LLStrider texCoords0p; +}; + + +void LLVOSurfacePatch::genTerrainTangents(LLFace *facep, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p) +{ + SMikkTSpaceInterface ms; + + ms.m_getNumFaces = [](const SMikkTSpaceContext *pContext) + { + MikktData *data = (MikktData *) pContext->m_pUserData; + return S32(data->vert_size / 3); + }; + + ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext *pContext, const int iFace) { return 3; }; + + ms.m_getPosition = [](const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) + { + MikktData *data = (MikktData *) pContext->m_pUserData; + fvPosOut[0] = data->verticesp[data->vert_offset + iVert].mV[0]; + fvPosOut[1] = data->verticesp[data->vert_offset + iVert].mV[1]; + fvPosOut[2] = data->verticesp[data->vert_offset + iVert].mV[2]; + }; + + ms.m_getNormal = [](const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) + { + MikktData *data = (MikktData *) pContext->m_pUserData; + fvNormOut[0] = data->normalsp[data->vert_offset + iVert].mV[0]; + fvNormOut[1] = data->normalsp[data->vert_offset + iVert].mV[1]; + fvNormOut[2] = data->normalsp[data->vert_offset + iVert].mV[2]; + }; + + ms.m_getTexCoord = [](const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) + { + MikktData *data = (MikktData *) pContext->m_pUserData; + fvTexcOut[0] = data->texCoords0p[data->vert_offset + iVert].mV[0]; + fvTexcOut[1] = data->texCoords0p[data->vert_offset + iVert].mV[1]; + }; + + ms.m_setTSpaceBasic = + [](const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) + { + MikktData *data = (MikktData *) pContext->m_pUserData; + data->tangentsp[data->vert_offset + iVert] = LLVector4a(fvTangent[0], fvTangent[1], fvTangent[2], fSign); + }; + + ms.m_setTSpace = nullptr; + + MikktData data(facep->getGeomIndex(), + facep->getGeomCount(), + verticesp, + normalsp, + tangentsp, + texCoords0p); + SMikkTSpaceContext ctx = { &ms, &data }; + genTangSpaceDefault(&ctx); +} + void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp) { mPatchp = patchp; @@ -998,12 +1097,16 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) //get vertex buffer striders LLStrider vertices; LLStrider normals; - LLStrider texcoords2; + LLStrider tangents; LLStrider texcoords; + LLStrider texcoords2; LLStrider indices; + const bool has_tangents = buffer->hasDataType(LLVertexBuffer::TYPE_TANGENT); + llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); + llassert_always(has_tangents ? buffer->getTangentStrider(tangents) : true); llassert_always(buffer->getTexCoord0Strider(texcoords)); llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getIndexStrider(indices)); @@ -1020,7 +1123,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); - patchp->getGeometry(vertices, normals, texcoords, texcoords2, indices); + patchp->getTerrainGeometry(vertices, normals, tangents, texcoords, texcoords2, indices); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index aed67162d1..7d0f649dea 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -63,11 +63,12 @@ public: /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); /*virtual*/ void updateFaceSize(S32 idx); - void getGeometry(LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp); + void getTerrainGeometry(LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -136,6 +137,11 @@ protected: LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset); + void genTerrainTangents(LLFace *facep, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From 49a5b79c2b1ba5f4b909d1bfab89bb7ad9c1e888 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:24 -0700 Subject: DRTVWR-592: (WIP) Debugging, rethinking --- .../shaders/class1/deferred/pbrterrainF.glsl | 3 + .../shaders/class1/deferred/pbrterrainV.glsl | 7 ++ indra/newview/lldrawpoolterrain.h | 1 + indra/newview/llvosurfacepatch.cpp | 83 +++++++++++----------- 4 files changed, 51 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 96903aeba8..2426199056 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -33,6 +33,8 @@ uniform sampler2D alpha_ramp; in vec3 pos; in vec3 vary_normal; +in vec3 vary_tangent; // TODO: Decide if we want to keep this +flat in float vary_sign; // TODO: Decide if we want to keep this in vec4 vary_texcoord0; in vec4 vary_texcoord1; @@ -53,6 +55,7 @@ void main() outColor.a = 0.0; // yes, downstream atmospherics frag_data[0] = outColor; + frag_data[0] = vec4((0.5 * (1.0 + vary_sign)) * vary_tangent.xyz, 1.0); // TODO: Remove frag_data[1] = vec4(0.0,0.0,0.0,-1.0); vec3 nvn = normalize(vary_normal); frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index e8747a1f6b..fcc4448a80 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -29,15 +29,20 @@ uniform mat4 modelview_projection_matrix; in vec3 position; in vec3 normal; +in vec4 tangent; in vec4 diffuse_color; in vec2 texcoord0; in vec2 texcoord1; out vec3 pos; out vec3 vary_normal; +out vec3 vary_tangent; // TODO: Decide if we want to keep this +flat out float vary_sign; // TODO: Decide if we want to keep this out vec4 vary_texcoord0; out vec4 vary_texcoord1; +out vec4 debug_tangent; // TODO: Remove + uniform vec4 object_plane_s; uniform vec4 object_plane_t; @@ -65,6 +70,8 @@ void main() pos = t_pos.xyz; vary_normal = normalize(normal_matrix * normal); + vary_tangent = normalize(normal_matrix * tangent.xyz); // TODO: Decide if we want to keep this + vary_sign = tangent.w; // TODO: Decide if we want to keep this // Transform and pass tex coords vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index fbf6a8d917..2a487228ed 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -37,6 +37,7 @@ public: { VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TANGENT | // Only PBR terrain uses this currently LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 }; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index bfa622b6c1..edb07ffd9b 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -776,29 +776,33 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, index_offset += num_vertices; } -struct MikktData +struct MikktTerrainData { - MikktData(S32 vert_offet, - S32 vert_size, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &tangentsp, - LLStrider &texCoords0p) : - vert_offset(vert_offset), - vert_size(vert_size), - verticesp(verticesp), - normalsp(normalsp), - texCoords0p(texCoords0p) + MikktTerrainData(U32 vert_offset, + U32 vert_size, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p) : + mVertOffset(vert_offset), + mVertSize(vert_size), + mVerticesp(verticesp), + mNormalsp(normalsp), + mTangentsp(tangentsp), + mTexCoords0p(texCoords0p) { } - S32 vert_offset; - U32 vert_size; - LLStrider verticesp; - LLStrider normalsp; - LLStrider tangentsp; - LLStrider texCoords0p; + U32 mVertOffset; + U32 mVertSize; + LLStrider mVerticesp; + LLStrider mNormalsp; + LLStrider mTangentsp; + LLStrider mTexCoords0p; }; +// TODO: mikktspace? lol no, use this instead +// void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, +// const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) void LLVOSurfacePatch::genTerrainTangents(LLFace *facep, LLStrider &verticesp, @@ -810,51 +814,46 @@ void LLVOSurfacePatch::genTerrainTangents(LLFace *facep, ms.m_getNumFaces = [](const SMikkTSpaceContext *pContext) { - MikktData *data = (MikktData *) pContext->m_pUserData; - return S32(data->vert_size / 3); + MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; + return S32(data->mVertSize / 3); }; ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext *pContext, const int iFace) { return 3; }; ms.m_getPosition = [](const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { - MikktData *data = (MikktData *) pContext->m_pUserData; - fvPosOut[0] = data->verticesp[data->vert_offset + iVert].mV[0]; - fvPosOut[1] = data->verticesp[data->vert_offset + iVert].mV[1]; - fvPosOut[2] = data->verticesp[data->vert_offset + iVert].mV[2]; + MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; + fvPosOut[0] = data->mVerticesp[data->mVertOffset + iVert].mV[0]; + fvPosOut[1] = data->mVerticesp[data->mVertOffset + iVert].mV[1]; + fvPosOut[2] = data->mVerticesp[data->mVertOffset + iVert].mV[2]; }; ms.m_getNormal = [](const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { - MikktData *data = (MikktData *) pContext->m_pUserData; - fvNormOut[0] = data->normalsp[data->vert_offset + iVert].mV[0]; - fvNormOut[1] = data->normalsp[data->vert_offset + iVert].mV[1]; - fvNormOut[2] = data->normalsp[data->vert_offset + iVert].mV[2]; + MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; + fvNormOut[0] = data->mNormalsp[data->mVertOffset + iVert].mV[0]; + fvNormOut[1] = data->mNormalsp[data->mVertOffset + iVert].mV[1]; + fvNormOut[2] = data->mNormalsp[data->mVertOffset + iVert].mV[2]; }; ms.m_getTexCoord = [](const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { - MikktData *data = (MikktData *) pContext->m_pUserData; - fvTexcOut[0] = data->texCoords0p[data->vert_offset + iVert].mV[0]; - fvTexcOut[1] = data->texCoords0p[data->vert_offset + iVert].mV[1]; + MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; + fvTexcOut[0] = data->mTexCoords0p[data->mVertOffset + iVert].mV[0]; + fvTexcOut[1] = data->mTexCoords0p[data->mVertOffset + iVert].mV[1]; }; ms.m_setTSpaceBasic = [](const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { - MikktData *data = (MikktData *) pContext->m_pUserData; - data->tangentsp[data->vert_offset + iVert] = LLVector4a(fvTangent[0], fvTangent[1], fvTangent[2], fSign); + MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; + data->mTangentsp[data->mVertOffset + iVert] = LLVector4a(fvTangent[0], fvTangent[1], fvTangent[2], fSign); }; ms.m_setTSpace = nullptr; - MikktData data(facep->getGeomIndex(), - facep->getGeomCount(), - verticesp, - normalsp, - tangentsp, - texCoords0p); - SMikkTSpaceContext ctx = { &ms, &data }; + MikktTerrainData data((U32) (facep->getGeomIndex()), (U32) (facep->getGeomCount()), verticesp, normalsp, tangentsp, texCoords0p); + SMikkTSpaceContext ctx = {&ms, &data}; genTangSpaceDefault(&ctx); } @@ -1102,11 +1101,9 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) LLStrider texcoords2; LLStrider indices; - const bool has_tangents = buffer->hasDataType(LLVertexBuffer::TYPE_TANGENT); - llassert_always(buffer->getVertexStrider(vertices)); llassert_always(buffer->getNormalStrider(normals)); - llassert_always(has_tangents ? buffer->getTangentStrider(tangents) : true); + llassert_always(buffer->getTangentStrider(tangents)); llassert_always(buffer->getTexCoord0Strider(texcoords)); llassert_always(buffer->getTexCoord1Strider(texcoords2)); llassert_always(buffer->getIndexStrider(indices)); -- cgit v1.2.3 From 763a9b5249640ef71d532ff3c9c28418bd90fb68 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:32 -0700 Subject: DRTVWR-592: Working tangent calculation, not yet used --- indra/llmath/llvolume.cpp | 7 +- indra/llmath/llvolume.h | 2 + indra/newview/llvosurfacepatch.cpp | 214 ++++++++++++++++--------------------- indra/newview/llvosurfacepatch.h | 6 -- 4 files changed, 94 insertions(+), 135 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 0e3792fda3..667108320a 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -6465,9 +6465,6 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) return TRUE; } -void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, - const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent); - void LLVolumeFace::createTangents() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; @@ -6485,7 +6482,7 @@ void LLVolumeFace::createTangents() (*ptr++).clear(); } - CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents); + LLCalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices / 3, mIndices, mTangents); //normalize normals for (U32 i = 0; i < mNumVertices; i++) @@ -7195,7 +7192,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } //adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html -void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, +void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index afed98ff36..c2586601ae 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1142,6 +1142,8 @@ public: std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); +void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent); + BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size); BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index edb07ffd9b..839eb2b737 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -39,13 +39,11 @@ #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llvlcomposition.h" +#include "llvolume.h" #include "llvovolume.h" #include "pipeline.h" #include "llspatialpartition.h" -#include "mikktspace/mikktspace.h" -// mikktspace implementation already included in llvovolume object file - F32 LLVOSurfacePatch::sLODFactor = 1.f; LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -246,7 +244,6 @@ BOOL LLVOSurfacePatch::updateLOD() void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, - LLStrider &tangentsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp) @@ -280,17 +277,6 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, texCoords1p, indicesp, index_offset); - - const bool has_tangents = tangentsp.get() != nullptr; - if (has_tangents) - { - // Last but not least, calculate tangents for the updated terrain vertices - genTerrainTangents(facep, - verticesp, - normalsp, - tangentsp, - texCoords0p); - } } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -776,87 +762,6 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, index_offset += num_vertices; } -struct MikktTerrainData -{ - MikktTerrainData(U32 vert_offset, - U32 vert_size, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &tangentsp, - LLStrider &texCoords0p) : - mVertOffset(vert_offset), - mVertSize(vert_size), - mVerticesp(verticesp), - mNormalsp(normalsp), - mTangentsp(tangentsp), - mTexCoords0p(texCoords0p) - { - } - U32 mVertOffset; - U32 mVertSize; - LLStrider mVerticesp; - LLStrider mNormalsp; - LLStrider mTangentsp; - LLStrider mTexCoords0p; -}; - -// TODO: mikktspace? lol no, use this instead -// void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, -// const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) - -void LLVOSurfacePatch::genTerrainTangents(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &tangentsp, - LLStrider &texCoords0p) -{ - SMikkTSpaceInterface ms; - - ms.m_getNumFaces = [](const SMikkTSpaceContext *pContext) - { - MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; - return S32(data->mVertSize / 3); - }; - - ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext *pContext, const int iFace) { return 3; }; - - ms.m_getPosition = [](const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) - { - MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; - fvPosOut[0] = data->mVerticesp[data->mVertOffset + iVert].mV[0]; - fvPosOut[1] = data->mVerticesp[data->mVertOffset + iVert].mV[1]; - fvPosOut[2] = data->mVerticesp[data->mVertOffset + iVert].mV[2]; - }; - - ms.m_getNormal = [](const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) - { - MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; - fvNormOut[0] = data->mNormalsp[data->mVertOffset + iVert].mV[0]; - fvNormOut[1] = data->mNormalsp[data->mVertOffset + iVert].mV[1]; - fvNormOut[2] = data->mNormalsp[data->mVertOffset + iVert].mV[2]; - }; - - ms.m_getTexCoord = [](const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) - { - MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; - fvTexcOut[0] = data->mTexCoords0p[data->mVertOffset + iVert].mV[0]; - fvTexcOut[1] = data->mTexCoords0p[data->mVertOffset + iVert].mV[1]; - }; - - ms.m_setTSpaceBasic = - [](const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) - { - MikktTerrainData *data = (MikktTerrainData *) pContext->m_pUserData; - data->mTangentsp[data->mVertOffset + iVert] = LLVector4a(fvTangent[0], fvTangent[1], fvTangent[2], fSign); - }; - - ms.m_setTSpace = nullptr; - - MikktTerrainData data((U32) (facep->getGeomIndex()), (U32) (facep->getGeomCount()), verticesp, normalsp, tangentsp, texCoords0p); - SMikkTSpaceContext ctx = {&ms, &data}; - genTangSpaceDefault(&ctx); -} - void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp) { mPatchp = patchp; @@ -1087,6 +992,47 @@ LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp) mPartitionType = LLViewerRegion::PARTITION_TERRAIN; } +// Do not add vertices; honor strict vertex count specified by strider_vertex_count +void gen_terrain_tangents(U16 strider_vertex_count, + U32 strider_index_count, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &tangentsp, + LLStrider &texCoords0p, + LLStrider &indicesp) +{ + LLVector4a *vertices = new LLVector4a[strider_vertex_count]; + LLVector4a *normals = new LLVector4a[strider_vertex_count]; + LLVector4a *tangents = new LLVector4a[strider_vertex_count]; + std::vector texcoords(strider_vertex_count); + std::vector indices(strider_index_count); + + for (U16 v = 0; v < strider_vertex_count; ++v) + { + F32 *vert = verticesp[v].mV; + vertices[v] = LLVector4a(vert[0], vert[1], vert[2], 1.f); + F32 *n = normalsp[v].mV; + normals[v] = LLVector4a(n[0], n[1], n[2], 1.f); + tangents[v] = tangentsp[v]; + texcoords[v] = texCoords0p[v]; + } + for (U32 i = 0; i < strider_index_count; ++i) + { + indices[i] = indicesp[i]; + } + + LLCalculateTangentArray(strider_vertex_count, vertices, normals, texcoords.data(), strider_index_count / 3, indices.data(), tangents); + + for (U16 v = 0; v < strider_vertex_count; ++v) + { + tangentsp[v] = tangents[v]; + } + + delete[] vertices; + delete[] normals; + delete[] tangents; +} + void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; @@ -1094,37 +1040,57 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders - LLStrider vertices; - LLStrider normals; - LLStrider tangents; - LLStrider texcoords; - LLStrider texcoords2; - LLStrider indices; - - llassert_always(buffer->getVertexStrider(vertices)); - llassert_always(buffer->getNormalStrider(normals)); - llassert_always(buffer->getTangentStrider(tangents)); - llassert_always(buffer->getTexCoord0Strider(texcoords)); - llassert_always(buffer->getTexCoord1Strider(texcoords2)); - llassert_always(buffer->getIndexStrider(indices)); - - U32 indices_index = 0; - U32 index_offset = 0; - - for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) - { - LLFace* facep = *i; + LLStrider vertices_start; + LLStrider normals_start; + LLStrider tangents_start; + LLStrider texcoords_start; + LLStrider texcoords2_start; + LLStrider indices_start; + + llassert_always(buffer->getVertexStrider(vertices_start)); + llassert_always(buffer->getNormalStrider(normals_start)); + llassert_always(buffer->getTangentStrider(tangents_start)); + llassert_always(buffer->getTexCoord0Strider(texcoords_start)); + llassert_always(buffer->getTexCoord1Strider(texcoords2_start)); + llassert_always(buffer->getIndexStrider(indices_start)); + + U32 indices_index = 0; + U32 index_offset = 0; - facep->setIndicesIndex(indices_index); - facep->setGeomIndex(index_offset); - facep->setVertexBuffer(buffer); + { + LLStrider vertices = vertices_start; + LLStrider normals = normals_start; + LLStrider texcoords = texcoords_start; + LLStrider texcoords2 = texcoords2_start; + LLStrider indices = indices_start; + + for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + + LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); + patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices); + + indices_index += facep->getIndicesCount(); + index_offset += facep->getGeomCount(); + } + } - LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); - patchp->getTerrainGeometry(vertices, normals, tangents, texcoords, texcoords2, indices); + const bool has_tangents = tangents_start.get() != nullptr; + if (has_tangents) + { + LLStrider vertices = vertices_start; + LLStrider normals = normals_start; + LLStrider tangents = tangents_start; + LLStrider texcoords = texcoords_start; + LLStrider indices = indices_start; - indices_index += facep->getIndicesCount(); - index_offset += facep->getGeomCount(); - } + gen_terrain_tangents(index_offset, indices_index, vertices, normals, tangents, texcoords, indices); + } buffer->unmapBuffer(); mFaceList.clear(); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 7d0f649dea..a3dcb945d1 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -65,7 +65,6 @@ public: /*virtual*/ void updateFaceSize(S32 idx); void getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, - LLStrider &tangentsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp); @@ -137,11 +136,6 @@ protected: LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset); - void genTerrainTangents(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &tangentsp, - LLStrider &texCoords0p); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From 7376b3e4b9c03f3ff3aa0c431c66916ac655a692 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:40 -0700 Subject: DRTVWR-592: (WIP) (does not run) PBR terrain rendering - begin work on shaders, uniforms --- indra/llrender/llshadermgr.cpp | 18 +++ indra/llrender/llshadermgr.h | 18 +++ .../shaders/class1/deferred/pbrterrainF.glsl | 142 ++++++++++++++++++--- .../shaders/class1/deferred/pbrterrainV.glsl | 21 ++- 4 files changed, 166 insertions(+), 33 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 75d6ef6c46..89f39d7011 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1427,8 +1427,26 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("detail_1"); mReservedUniforms.push_back("detail_2"); mReservedUniforms.push_back("detail_3"); + mReservedUniforms.push_back("alpha_ramp"); + mReservedUniforms.push_back("detail_0_base_color"); + mReservedUniforms.push_back("detail_1_base_color"); + mReservedUniforms.push_back("detail_2_base_color"); + mReservedUniforms.push_back("detail_3_base_color"); + mReservedUniforms.push_back("detail_0_normal"); + mReservedUniforms.push_back("detail_1_normal"); + mReservedUniforms.push_back("detail_2_normal"); + mReservedUniforms.push_back("detail_3_normal"); + mReservedUniforms.push_back("detail_0_metallic_roughness"); + mReservedUniforms.push_back("detail_1_metallic_roughness"); + mReservedUniforms.push_back("detail_2_metallic_roughness"); + mReservedUniforms.push_back("detail_3_metallic_roughness"); + mReservedUniforms.push_back("detail_0_emissive"); + mReservedUniforms.push_back("detail_1_emissive"); + mReservedUniforms.push_back("detail_2_emissive"); + mReservedUniforms.push_back("detail_3_emissive"); + mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("display_gamma"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46f352aa58..b43ccf2ec2 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -248,8 +248,26 @@ public: TERRAIN_DETAIL1, // "detail_1" TERRAIN_DETAIL2, // "detail_2" TERRAIN_DETAIL3, // "detail_3" + TERRAIN_ALPHARAMP, // "alpha_ramp" + TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF) + TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF) + TERRAIN_DETAIL2_BASE_COLOR, // "detail_2_base_color" (GLTF) + TERRAIN_DETAIL3_BASE_COLOR, // "detail_3_base_color" (GLTF) + TERRAIN_DETAIL0_NORMAL, // "detail_0_normal" (GLTF) + TERRAIN_DETAIL1_NORMAL, // "detail_1_normal" (GLTF) + TERRAIN_DETAIL2_NORMAL, // "detail_2_normal" (GLTF) + TERRAIN_DETAIL3_NORMAL, // "detail_3_normal" (GLTF) + TERRAIN_DETAIL0_METALLIC_ROUGHNESS, // "detail_0_metallic_roughness" (GLTF) + TERRAIN_DETAIL1_METALLIC_ROUGHNESS, // "detail_1_metallic_roughness" (GLTF) + TERRAIN_DETAIL2_METALLIC_ROUGHNESS, // "detail_2_metallic_roughness" (GLTF) + TERRAIN_DETAIL3_METALLIC_ROUGHNESS, // "detail_3_metallic_roughness" (GLTF) + TERRAIN_DETAIL0_EMISSIVE, // "detail_0_emissive" (GLTF) + TERRAIN_DETAIL1_EMISSIVE, // "detail_1_emissive" (GLTF) + TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF) + TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF) + SHINY_ORIGIN, // "origin" DISPLAY_GAMMA, // "display_gamma" diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 2426199056..f355b8ef98 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -25,40 +25,140 @@ out vec4 frag_data[4]; -uniform sampler2D detail_0; -uniform sampler2D detail_1; -uniform sampler2D detail_2; -uniform sampler2D detail_3; uniform sampler2D alpha_ramp; -in vec3 pos; +// TODO: Bind the right textures and uniforms during shader setup +// *TODO: Configurable quality level which disables PBR features on machines +// with limited texture availability +// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures +uniform sampler2D detail_0_base_color; +uniform sampler2D detail_1_base_color; +uniform sampler2D detail_2_base_color; +uniform sampler2D detail_3_base_color; +uniform sampler2D detail_0_normal; +uniform sampler2D detail_1_normal; +uniform sampler2D detail_2_normal; +uniform sampler2D detail_3_normal; +uniform sampler2D detail_0_metallic_roughness; +uniform sampler2D detail_1_metallic_roughness; +uniform sampler2D detail_2_metallic_roughness; +uniform sampler2D detail_3_metallic_roughness; +uniform sampler2D detail_0_emissive; +uniform sampler2D detail_1_emissive; +uniform sampler2D detail_2_emissive; +uniform sampler2D detail_3_emissive; + +// TODO: Needs new uniforms +// *TODO: More efficient packing? +uniform vec4 metallicFactors; +uniform vec4 roughnessFactors; +uniform vec3[4] emissiveColors; +uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() + in vec3 vary_normal; -in vec3 vary_tangent; // TODO: Decide if we want to keep this -flat in float vary_sign; // TODO: Decide if we want to keep this +in vec3 vary_tangent; +flat in float vary_sign; in vec4 vary_texcoord0; in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); +vec3 linear_to_srgb(vec3 c); +vec3 srgb_to_linear(vec3 c); -void main() +// TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly +float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples.w, samples.z, alpha2), mix(samples.y, samples.x, alpha1), alphaFinal ); +} + +vec3 terrain_mix(vec3[4] samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); +} + +vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); +} + +vec4 sample_and_mix_color(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec4[4] samples; + samples[0] = srgb_to_linear(texture2D(tex0, texcoord)); + samples[1] = srgb_to_linear(texture2D(tex1, texcoord)); + samples[2] = srgb_to_linear(texture2D(tex2, texcoord)); + samples[3] = srgb_to_linear(texture2D(tex3, texcoord)); + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec4 sample_and_mix_vector(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec4 color0 = texture2D(detail_0, vary_texcoord0.xy); - vec4 color1 = texture2D(detail_1, vary_texcoord0.xy); - vec4 color2 = texture2D(detail_2, vary_texcoord0.xy); - vec4 color3 = texture2D(detail_3, vary_texcoord0.xy); + vec4[4] samples; + samples[0] = texture2D(tex0, texcoord); + samples[1] = texture2D(tex1, texcoord); + samples[2] = texture2D(tex2, texcoord); + samples[3] = texture2D(tex3, texcoord); + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} +// TODO: Implement +// TODO: Don't forget calls to srgb_to_linear during texture sampling +// TODO: Wherever base color alpha is not 1.0, blend with black +void main() +{ float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a; float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; - vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - - outColor.a = 0.0; // yes, downstream atmospherics + + vec4 base_color = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_basecolor, detail_1_basecolor, detail_2_basecolor, detail_3_basecolor); + vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); + vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); + vec4 emissive_texture = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + + float metallicFactor = terrain_mix(metallicFactors, alpha1, alpha2, alphaFinal); + float roughnessFactor = terrain_mix(roughnessFactors, alpha1, alpha2, alphaFinal); + vec3 emissiveColor = terrain_mix(emissiveColors, alpha1, alpha2, alphaFinal); + float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); + + // TODO: OOh, we need blending for every GLTF uniform too + // TODO: Unfork + if (base_color.a < minimum_alpha) + { + base_color.rgb *= vec3(0.0); + } + + vec3 col = base_color.rgb; + + // from mikktspace.com + vec3 vNt = normal_texture.xyz*2.0-1.0; + float sign = vary_sign; + vec3 vN = vary_normal; + vec3 vT = vary_tangent.xyz; + + vec3 vB = sign * cross(vN, vT); + vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); + + // RGB = Occlusion, Roughness, Metal + // default values, see LLViewerTexture::sDefaultPBRORMImagep + // occlusion 1.0 + // roughness 0.0 + // metal 0.0 + vec3 spec = metallic_roughness.rgb; - frag_data[0] = outColor; - frag_data[0] = vec4((0.5 * (1.0 + vary_sign)) * vary_tangent.xyz, 1.0); // TODO: Remove - frag_data[1] = vec4(0.0,0.0,0.0,-1.0); - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + spec.g *= roughness_factor; + spec.b *= metallic_factor; + + vec3 emissive = emssive_color; + emissive *= emissive_texture.rgb; + + tnorm *= gl_FrontFacing ? 1.0 : -1.0; + + + frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse + // TODO: What is packed into vertex_color.a? + frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + // TODO: What is environment intensity and do we want it? + frag_data[2] = max(vec4(encode_normal(tnorm), 0.0, GBUFFER_FLAG_HAS_PBR | GBUFFER_FLAG_HAS_ATMOS), vec4(0)); // normal, environment intensity, flags + frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index fcc4448a80..cbfe9f3ea5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -34,15 +34,12 @@ in vec4 diffuse_color; in vec2 texcoord0; in vec2 texcoord1; -out vec3 pos; out vec3 vary_normal; -out vec3 vary_tangent; // TODO: Decide if we want to keep this -flat out float vary_sign; // TODO: Decide if we want to keep this +out vec3 vary_tangent; +flat out float vary_sign; out vec4 vary_texcoord0; out vec4 vary_texcoord1; -out vec4 debug_tangent; // TODO: Remove - uniform vec4 object_plane_s; uniform vec4 object_plane_t; @@ -63,17 +60,17 @@ vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) void main() { //transform vertex - vec4 pre_pos = vec4(position.xyz, 1.0); - vec4 t_pos = modelview_projection_matrix * pre_pos; + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - gl_Position = t_pos; - pos = t_pos.xyz; + vec3 n = normal_matrix * normal; + vec3 t = normal_matrix * tangent.xyz; - vary_normal = normalize(normal_matrix * normal); - vary_tangent = normalize(normal_matrix * tangent.xyz); // TODO: Decide if we want to keep this - vary_sign = tangent.w; // TODO: Decide if we want to keep this + vary_tangent = normalize(t); + vary_sign = tangent.w; + vary_normal = normalize(n); // Transform and pass tex coords + // *NOTE: KHR texture transform is ignored for now vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; vec4 t = vec4(texcoord1,0,1); -- cgit v1.2.3 From a7cd5f6ef9d80e77eaf87cfc605d32605f0916f1 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:48 -0700 Subject: DRTVWR-592: (WIP) (does not run) PBR terrain rendering - more work on shaders, uniforms --- indra/llrender/llshadermgr.cpp | 6 +++++ indra/llrender/llshadermgr.h | 6 +++++ .../shaders/class1/deferred/pbrterrainF.glsl | 28 +++++++++------------- 3 files changed, 23 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 89f39d7011..b2c8255d2a 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1447,6 +1447,12 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("detail_2_emissive"); mReservedUniforms.push_back("detail_3_emissive"); + mReservedUniforms.push_back("baseColorFactors"); + mReservedUniforms.push_back("metallicFactors"); + mReservedUniforms.push_back("roughnessFactors"); + mReservedUniforms.push_back("emissiveColors"); + mReservedUniforms.push_back("minimum_alphas"); + mReservedUniforms.push_back("origin"); mReservedUniforms.push_back("display_gamma"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index b43ccf2ec2..151e94093d 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -268,6 +268,12 @@ public: TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF) TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF) + TERRAIN_BASE_COLOR_FACTORS, // "baseColorFactors" (GLTF) + TERRAIN_METALLIC_FACTORS, // "metallicFactors" (GLTF) + TERRAIN_ROUGHNESS_FACTORS, // "roughnessFactors" (GLTF) + TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF) + TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF) + SHINY_ORIGIN, // "origin" DISPLAY_GAMMA, // "display_gamma" diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index f355b8ef98..4a0b324558 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -48,8 +48,8 @@ uniform sampler2D detail_1_emissive; uniform sampler2D detail_2_emissive; uniform sampler2D detail_3_emissive; -// TODO: Needs new uniforms // *TODO: More efficient packing? +uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl uniform vec4 metallicFactors; uniform vec4 roughnessFactors; uniform vec3[4] emissiveColors; @@ -101,9 +101,6 @@ vec4 sample_and_mix_vector(float alpha1, float alpha2, float alphaFinal, vec2 te return terrain_mix(samples, alpha1, alpha2, alphaFinal); } -// TODO: Implement -// TODO: Don't forget calls to srgb_to_linear during texture sampling -// TODO: Wherever base color alpha is not 1.0, blend with black void main() { float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a; @@ -111,23 +108,22 @@ void main() float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; vec4 base_color = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_basecolor, detail_1_basecolor, detail_2_basecolor, detail_3_basecolor); + float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); + if (base_color.a < minimum_alpha) + { + discard; + } + vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); vec4 emissive_texture = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + vec4 baseColorFactor = terrain_mix(baseColorFactors, alpha1, alpha2, alphaFinal); float metallicFactor = terrain_mix(metallicFactors, alpha1, alpha2, alphaFinal); float roughnessFactor = terrain_mix(roughnessFactors, alpha1, alpha2, alphaFinal); vec3 emissiveColor = terrain_mix(emissiveColors, alpha1, alpha2, alphaFinal); - float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); - - // TODO: OOh, we need blending for every GLTF uniform too - // TODO: Unfork - if (base_color.a < minimum_alpha) - { - base_color.rgb *= vec3(0.0); - } - vec3 col = base_color.rgb; + vec3 col = baseColorFactor.rgb * srgb_to_linear(basecolor.rgb); // from mikktspace.com vec3 vNt = normal_texture.xyz*2.0-1.0; @@ -155,10 +151,8 @@ void main() frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse - // TODO: What is packed into vertex_color.a? - frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - // TODO: What is environment intensity and do we want it? - frag_data[2] = max(vec4(encode_normal(tnorm), 0.0, GBUFFER_FLAG_HAS_PBR | GBUFFER_FLAG_HAS_ATMOS), vec4(0)); // normal, environment intensity, flags + frag_data[1] = max(vec4(spec.rgb,baseColorFactor.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[2] = max(vec4(encode_normal(tnorm), baseColorFactor.a, GBUFFER_FLAG_HAS_PBR | GBUFFER_FLAG_HAS_ATMOS), vec4(0)); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } -- cgit v1.2.3 From 5d046d8835563fcad9e8dcf948d889d9ccec41d7 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:57:57 -0700 Subject: DRTVWR-592: (WIP) (does not work) PBR terrain rendering - compiles, but doesn't render properly just yet --- .../shaders/class1/deferred/pbrterrainF.glsl | 41 ++++-- .../shaders/class1/deferred/pbrterrainV.glsl | 8 +- indra/newview/lldrawpoolterrain.cpp | 154 ++++++++++++--------- 3 files changed, 123 insertions(+), 80 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 4a0b324558..60e5776bc6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -27,7 +27,6 @@ out vec4 frag_data[4]; uniform sampler2D alpha_ramp; -// TODO: Bind the right textures and uniforms during shader setup // *TODO: Configurable quality level which disables PBR features on machines // with limited texture availability // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures @@ -65,7 +64,7 @@ vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); -// TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly +// *TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { return mix( mix(samples.w, samples.z, alpha2), mix(samples.y, samples.x, alpha1), alphaFinal ); @@ -81,13 +80,27 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); } -vec4 sample_and_mix_color(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec3[4] samples; + samples[0] = srgb_to_linear(texture2D(tex0, texcoord).xyz); + samples[1] = srgb_to_linear(texture2D(tex1, texcoord).xyz); + samples[2] = srgb_to_linear(texture2D(tex2, texcoord).xyz); + samples[3] = srgb_to_linear(texture2D(tex3, texcoord).xyz); + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec4[4] samples; - samples[0] = srgb_to_linear(texture2D(tex0, texcoord)); - samples[1] = srgb_to_linear(texture2D(tex1, texcoord)); - samples[2] = srgb_to_linear(texture2D(tex2, texcoord)); - samples[3] = srgb_to_linear(texture2D(tex3, texcoord)); + samples[0] = texture2D(tex0, texcoord); + samples[1] = texture2D(tex1, texcoord); + samples[2] = texture2D(tex2, texcoord); + samples[3] = texture2D(tex3, texcoord); + samples[0].xyz = srgb_to_linear(samples[0].xyz); + samples[1].xyz = srgb_to_linear(samples[1].xyz); + samples[2].xyz = srgb_to_linear(samples[2].xyz); + samples[3].xyz = srgb_to_linear(samples[3].xyz); return terrain_mix(samples, alpha1, alpha2, alphaFinal); } @@ -107,7 +120,7 @@ void main() float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; - vec4 base_color = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_basecolor, detail_1_basecolor, detail_2_basecolor, detail_3_basecolor); + vec4 base_color = sample_and_mix_color4(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); if (base_color.a < minimum_alpha) { @@ -116,14 +129,14 @@ void main() vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); - vec4 emissive_texture = sample_and_mix_color(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + vec3 emissive_texture = sample_and_mix_color3(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); vec4 baseColorFactor = terrain_mix(baseColorFactors, alpha1, alpha2, alphaFinal); float metallicFactor = terrain_mix(metallicFactors, alpha1, alpha2, alphaFinal); float roughnessFactor = terrain_mix(roughnessFactors, alpha1, alpha2, alphaFinal); vec3 emissiveColor = terrain_mix(emissiveColors, alpha1, alpha2, alphaFinal); - vec3 col = baseColorFactor.rgb * srgb_to_linear(basecolor.rgb); + vec3 col = baseColorFactor.rgb * srgb_to_linear(base_color.rgb); // from mikktspace.com vec3 vNt = normal_texture.xyz*2.0-1.0; @@ -141,10 +154,10 @@ void main() // metal 0.0 vec3 spec = metallic_roughness.rgb; - spec.g *= roughness_factor; - spec.b *= metallic_factor; + spec.g *= roughnessFactor; + spec.b *= metallicFactor; - vec3 emissive = emssive_color; + vec3 emissive = emissiveColor; emissive *= emissive_texture.rgb; tnorm *= gl_FrontFacing ? 1.0 : -1.0; @@ -152,7 +165,7 @@ void main() frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb,baseColorFactor.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(encode_normal(tnorm), baseColorFactor.a, GBUFFER_FLAG_HAS_PBR | GBUFFER_FLAG_HAS_ATMOS), vec4(0)); // normal, environment intensity, flags + frag_data[2] = max(vec4(encode_normal(tnorm), baseColorFactor.a, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index cbfe9f3ea5..6037a58c0d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -73,9 +73,9 @@ void main() // *NOTE: KHR texture transform is ignored for now vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; - vec4 t = vec4(texcoord1,0,1); + vec4 tc = vec4(texcoord1,0,1); - vary_texcoord0.zw = t.xy; - vary_texcoord1.xy = t.xy-vec2(2.0, 0.0); - vary_texcoord1.zw = t.xy-vec2(1.0, 0.0); + vary_texcoord0.zw = tc.xy; + vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0); + vary_texcoord1.zw = tc.xy-vec2(1.0, 0.0); } diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 16d982ea90..2a0a7bad1c 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -375,16 +375,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - - LLViewerTexture *detail_texture0p = compp->mDetailMaterials[0]->mBaseColorTexture; - LLViewerTexture *detail_texture1p = compp->mDetailMaterials[1]->mBaseColorTexture; - LLViewerTexture *detail_texture2p = compp->mDetailMaterials[2]->mBaseColorTexture; - LLViewerTexture *detail_texture3p = compp->mDetailMaterials[3]->mBaseColorTexture; - LLViewerTexture* blank = LLViewerFetchedTexture::sWhiteImagep; - if (!detail_texture0p) { detail_texture0p = blank; } - if (!detail_texture1p) { detail_texture1p = blank; } - if (!detail_texture2p) { detail_texture2p = blank; } - if (!detail_texture3p) { detail_texture3p = blank; } + LLPointer(& materials)[LLVLComposition::ASSET_COUNT] = compp->mDetailMaterials; LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; @@ -395,13 +386,39 @@ void LLDrawPoolTerrain::renderFullShaderPBR() tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); - // - // detail texture 0 - // - S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); - gGL.getTexUnit(detail0)->bind(detail_texture0p); - gGL.getTexUnit(detail0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail0)->activate(); + constexpr U32 terrain_material_count = LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; + S32 detail_basecolor[terrain_material_count]; + S32 detail_normal[terrain_material_count]; + S32 detail_metalrough[terrain_material_count]; + S32 detail_emissive[terrain_material_count]; + + for (U32 i = 0; i < terrain_material_count; ++i) + { + LLViewerTexture *detail_basecolor_texturep = materials[i]->mBaseColorTexture; + LLViewerTexture *detail_normal_texturep = materials[i]->mNormalTexture; + LLViewerTexture *detail_metalrough_texturep = materials[i]->mMetallicRoughnessTexture; + LLViewerTexture *detail_emissive_texturep = materials[i]->mEmissiveTexture; + + detail_basecolor[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); + gGL.getTexUnit(detail_basecolor[i])->bind(detail_basecolor_texturep); + gGL.getTexUnit(detail_basecolor[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_basecolor[i])->activate(); + + detail_normal[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); + gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep); + gGL.getTexUnit(detail_normal[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_normal[i])->activate(); + + detail_metalrough[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); + gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep); + gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_metalrough[i])->activate(); + + detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); + gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep); + gGL.getTexUnit(detail_emissive[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_emissive[i])->activate(); + } LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); @@ -411,29 +428,6 @@ void LLDrawPoolTerrain::renderFullShaderPBR() LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - // - // detail texture 1 - // - S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); - gGL.getTexUnit(detail1)->bind(detail_texture1p); - gGL.getTexUnit(detail1)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail1)->activate(); - - // detail texture 2 - // - S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); - gGL.getTexUnit(detail2)->bind(detail_texture2p); - gGL.getTexUnit(detail2)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail2)->activate(); - - - // detail texture 3 - // - S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); - gGL.getTexUnit(detail3)->bind(detail_texture3p); - gGL.getTexUnit(detail3)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail3)->activate(); - // // Alpha Ramp // @@ -441,38 +435,74 @@ void LLDrawPoolTerrain::renderFullShaderPBR() gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + // + // GLTF uniforms + // + + LLColor4 base_color_factors[terrain_material_count]; + F32 metallic_factors[terrain_material_count]; + F32 roughness_factors[terrain_material_count]; + LLColor3 emissive_colors[terrain_material_count]; + F32 minimum_alphas[terrain_material_count]; + for (U32 i = 0; i < terrain_material_count; ++i) + { + const LLFetchedGLTFMaterial* material = materials[i].get(); + + base_color_factors[i] = material->mBaseColor; + metallic_factors[i] = material->mMetallicFactor; + roughness_factors[i] = material->mRoughnessFactor; + emissive_colors[i] = material->mEmissiveColor; + // glTF 2.0 Specification 3.9.4. Alpha Coverage + // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK + // Use 0 here due to GLTF terrain blending (LLGLTFMaterial::bind uses + // -1 for easier debugging) + F32 min_alpha = 0.f; + if (material->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) + { + min_alpha = material->mAlphaCutoff; + } + + } + shader->uniform4fv(LLShaderMgr::TERRAIN_BASE_COLOR_FACTORS, terrain_material_count, (F32*)base_color_factors); + shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]); + shader->uniform4f(LLShaderMgr::TERRAIN_ROUGHNESS_FACTORS, roughness_factors[0], roughness_factors[1], roughness_factors[2], roughness_factors[3]); + shader->uniform3fv(LLShaderMgr::TERRAIN_EMISSIVE_COLORS, terrain_material_count, (F32*)emissive_colors); + shader->uniform4f(LLShaderMgr::TERRAIN_MINIMUM_ALPHAS, minimum_alphas[0], minimum_alphas[1], minimum_alphas[2], minimum_alphas[3]); + // GL_BLEND disabled by default drawLoop(); // Disable multitexture + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(alpha_ramp)->disable(); gGL.getTexUnit(alpha_ramp)->activate(); - - gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail3)->disable(); - gGL.getTexUnit(detail3)->activate(); - gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail2)->disable(); - gGL.getTexUnit(detail2)->activate(); - - gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail1)->disable(); - gGL.getTexUnit(detail1)->activate(); - - //---------------------------------------------------------------------------- - // Restore Texture Unit 0 defaults - - gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail0)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail0)->activate(); + for (U32 i = 0; i < terrain_material_count; ++i) + { + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); + + gGL.getTexUnit(detail_basecolor[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_basecolor[i])->disable(); + gGL.getTexUnit(detail_basecolor[i])->activate(); + + gGL.getTexUnit(detail_normal[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_normal[i])->disable(); + gGL.getTexUnit(detail_normal[i])->activate(); + + gGL.getTexUnit(detail_metalrough[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_metalrough[i])->disable(); + gGL.getTexUnit(detail_metalrough[i])->activate(); + + gGL.getTexUnit(detail_emissive[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_emissive[i])->disable(); + gGL.getTexUnit(detail_emissive[i])->activate(); + } } void LLDrawPoolTerrain::hilightParcelOwners() -- cgit v1.2.3 From 039116abd4166903005b8de6fa5d64f0fdf75422 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:05 -0700 Subject: DRTVWR-592: (WIP) Roughly working draft of PBR terrain --- .../shaders/class1/deferred/pbrterrainF.glsl | 20 ++++++++++++-------- indra/newview/lldrawpoolterrain.cpp | 11 +++++++---- indra/newview/llfloaterregioninfo.cpp | 1 - indra/newview/llvlcomposition.cpp | 1 + 4 files changed, 20 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 60e5776bc6..4de6b9609c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -97,10 +97,11 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 te samples[1] = texture2D(tex1, texcoord); samples[2] = texture2D(tex2, texcoord); samples[3] = texture2D(tex3, texcoord); - samples[0].xyz = srgb_to_linear(samples[0].xyz); - samples[1].xyz = srgb_to_linear(samples[1].xyz); - samples[2].xyz = srgb_to_linear(samples[2].xyz); - samples[3].xyz = srgb_to_linear(samples[3].xyz); + // TODO: Why is this needed for pbropaqueF but not here? (and is there different behavior with base color vs emissive color, that also needs to be corrected?) + //samples[0].xyz = srgb_to_linear(samples[0].xyz); + //samples[1].xyz = srgb_to_linear(samples[1].xyz); + //samples[2].xyz = srgb_to_linear(samples[2].xyz); + //samples[3].xyz = srgb_to_linear(samples[3].xyz); return terrain_mix(samples, alpha1, alpha2, alphaFinal); } @@ -116,20 +117,23 @@ vec4 sample_and_mix_vector(float alpha1, float alpha2, float alphaFinal, vec2 te void main() { + // Adjust the texture repeats for a more sensible default. + float texture_density_factor = 2.0; + vec2 terrain_texcoord = texture_density_factor * vary_texcoord0.xy; float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a; float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; - vec4 base_color = sample_and_mix_color4(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); + vec4 base_color = sample_and_mix_color4(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); if (base_color.a < minimum_alpha) { discard; } - vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); - vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); - vec3 emissive_texture = sample_and_mix_color3(alpha1, alpha2, alphaFinal, vary_texcoord0.xy, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); + vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); + vec3 emissive_texture = sample_and_mix_color3(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); vec4 baseColorFactor = terrain_mix(baseColorFactors, alpha1, alpha2, alphaFinal); float metallicFactor = terrain_mix(metallicFactors, alpha1, alpha2, alphaFinal); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 2a0a7bad1c..204fbc56fd 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -370,6 +370,7 @@ void LLDrawPoolTerrain::renderFullShaderTextures() gGL.getTexUnit(detail0)->activate(); } +// TODO: Investigate use of bindFast for PBR terrain textures void LLDrawPoolTerrain::renderFullShaderPBR() { // Hack! Get the region that this draw pool is rendering from! @@ -386,7 +387,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR() tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); - constexpr U32 terrain_material_count = LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; + constexpr U32 terrain_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; S32 detail_basecolor[terrain_material_count]; S32 detail_normal[terrain_material_count]; S32 detail_metalrough[terrain_material_count]; @@ -456,12 +457,14 @@ void LLDrawPoolTerrain::renderFullShaderPBR() // mAlphaCutoff is only valid for LLGLTFMaterial::ALPHA_MODE_MASK // Use 0 here due to GLTF terrain blending (LLGLTFMaterial::bind uses // -1 for easier debugging) - F32 min_alpha = 0.f; + F32 min_alpha = -0.0f; if (material->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) { - min_alpha = material->mAlphaCutoff; + // dividing the alpha cutoff by transparency here allows the shader to compare against + // the alpha value of the texture without needing the transparency value + min_alpha = material->mAlphaCutoff/material->mBaseColor.mV[3]; } - + minimum_alphas[i] = min_alpha; } shader->uniform4fv(LLShaderMgr::TERRAIN_BASE_COLOR_FACTORS, terrain_material_count, (F32*)base_color_factors); shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index b5698c1d65..2635ac3a71 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1531,7 +1531,6 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LLVLComposition* compp = region->getComposition(); // Are these 4 texture IDs or 4 material IDs? Who knows! Let's set the IDs on both pickers for now. - // *TODO: Determine the asset type of IDs, to determine which editing mode to display. LLTextureCtrl* asset_ctrl; std::string buffer; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 5d711f4e5d..815489f753 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -360,6 +360,7 @@ BOOL LLVLComposition::generateComposition() return FALSE; } +// TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, const F32 width, const F32 height) { -- cgit v1.2.3 From 94d8f669acc57d670000498edf22589f7b178af0 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:13 -0700 Subject: DRTVWR-592: Add debug options LocalTerrainAssetN. Fix PBR terrain texture flickering --- indra/newview/app_settings/settings.xml | 44 ++++ indra/newview/llappviewer.cpp | 1 + indra/newview/lldrawpoolterrain.cpp | 63 ++++-- indra/newview/lldrawpoolterrain.h | 2 +- indra/newview/llviewercontrol.cpp | 15 ++ indra/newview/llvlcomposition.cpp | 345 +++++++++++++++++--------------- indra/newview/llvlcomposition.h | 44 +++- 7 files changed, 328 insertions(+), 186 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 09eda2534c..013f0ca8ff 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16442,6 +16442,50 @@ Boolean Value 0 + + LocalTerrainAsset1 + + Comment + If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds. + Persist + 0 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + LocalTerrainAsset2 + + Comment + If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds. + Persist + 0 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + LocalTerrainAsset3 + + Comment + If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds. + Persist + 0 + Type + String + Value + 00000000-0000-0000-0000-000000000000 + + LocalTerrainAsset4 + + Comment + If set to a non-null UUID, overrides the terrain asset locally for all regions with material assets. Local terrain assets are not visible to others. Please keep in mind that this debug setting may be temporary. Do not rely on this setting existing in future viewer builds. + Persist + 0 + Type + String + Value + 00000000-0000-0000-0000-000000000000 PathfindingRetrieveNeighboringRegion diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index cf84094aa4..edbae465f7 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -227,6 +227,7 @@ #include "pipeline.h" #include "llgesturemgr.h" #include "llsky.h" +#include "llvlcomposition.h" #include "llvlmanager.h" #include "llviewercamera.h" #include "lldrawpoolbump.h" diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 204fbc56fd..8755e53763 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -249,10 +249,11 @@ void LLDrawPoolTerrain::drawLoop() void LLDrawPoolTerrain::renderFullShader() { + const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(TRUE); // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - const BOOL use_textures = compp->useTextures(); + const BOOL use_textures = !use_local_materials && compp->useTextures(); if (use_textures) { @@ -266,7 +267,7 @@ void LLDrawPoolTerrain::renderFullShader() // Use materials sShader = &gDeferredPBRTerrainProgram; sShader->bind(); - renderFullShaderPBR(); + renderFullShaderPBR(use_local_materials); } } @@ -371,12 +372,18 @@ void LLDrawPoolTerrain::renderFullShaderTextures() } // TODO: Investigate use of bindFast for PBR terrain textures -void LLDrawPoolTerrain::renderFullShaderPBR() +void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) { // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - LLPointer(& materials)[LLVLComposition::ASSET_COUNT] = compp->mDetailMaterials; + LLPointer (*materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; + + if (local_materials) + { + // Override region terrain with the global local override terrain + materials = &gLocalTerrainMaterials.mDetailMaterials; + } LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; @@ -395,28 +402,58 @@ void LLDrawPoolTerrain::renderFullShaderPBR() for (U32 i = 0; i < terrain_material_count; ++i) { - LLViewerTexture *detail_basecolor_texturep = materials[i]->mBaseColorTexture; - LLViewerTexture *detail_normal_texturep = materials[i]->mNormalTexture; - LLViewerTexture *detail_metalrough_texturep = materials[i]->mMetallicRoughnessTexture; - LLViewerTexture *detail_emissive_texturep = materials[i]->mEmissiveTexture; + const LLFetchedGLTFMaterial* material = (*materials)[i].get(); + + LLViewerTexture *detail_basecolor_texturep = material->mBaseColorTexture; + LLViewerTexture *detail_normal_texturep = material->mNormalTexture; + LLViewerTexture *detail_metalrough_texturep = material->mMetallicRoughnessTexture; + LLViewerTexture *detail_emissive_texturep = material->mEmissiveTexture; detail_basecolor[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); - gGL.getTexUnit(detail_basecolor[i])->bind(detail_basecolor_texturep); + if (detail_basecolor_texturep) + { + gGL.getTexUnit(detail_basecolor[i])->bind(detail_basecolor_texturep); + } + else + { + gGL.getTexUnit(detail_basecolor[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + } gGL.getTexUnit(detail_basecolor[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_basecolor[i])->activate(); detail_normal[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); - gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep); + if (detail_normal_texturep) + { + gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep); + } + else + { + gGL.getTexUnit(detail_normal[i])->bind(LLViewerFetchedTexture::sFlatNormalImagep); + } gGL.getTexUnit(detail_normal[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_normal[i])->activate(); detail_metalrough[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); - gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep); + if (detail_metalrough_texturep) + { + gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep); + } + else + { + gGL.getTexUnit(detail_metalrough[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + } gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_metalrough[i])->activate(); detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); - gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep); + if (detail_emissive_texturep) + { + gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep); + } + else + { + gGL.getTexUnit(detail_emissive[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + } gGL.getTexUnit(detail_emissive[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_emissive[i])->activate(); } @@ -447,7 +484,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR() F32 minimum_alphas[terrain_material_count]; for (U32 i = 0; i < terrain_material_count; ++i) { - const LLFetchedGLTFMaterial* material = materials[i].get(); + const LLFetchedGLTFMaterial* material = (*materials)[i].get(); base_color_factors[i] = material->mBaseColor; metallic_factors[i] = material->mMetallicFactor; diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 2a487228ed..1a27cc8be0 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -81,7 +81,7 @@ protected: void renderFull4TU(); void renderFullShader(); void renderFullShaderTextures(); - void renderFullShaderPBR(); + void renderFullShaderPBR(BOOL local_materials = false); void drawLoop(); private: diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index aae4409167..4e0ad11597 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -54,6 +54,7 @@ #include "llvotree.h" #include "llvovolume.h" #include "llworld.h" +#include "llvlcomposition.h" #include "pipeline.h" #include "llviewerjoystick.h" #include "llviewerobjectlist.h" @@ -656,6 +657,16 @@ void handleFPSTuningStrategyChanged(const LLSD& newValue) const auto newval = gSavedSettings.getU32("TuningFPSStrategy"); LLPerfStats::tunables.userFPSTuningStrategy = newval; } + +void handleLocalTerrainChanged(const LLSD& newValue) +{ + for (U32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + const auto setting = gSavedSettings.getString(std::string("LocalTerrainAsset") + std::to_string(i + 1)); + const LLUUID materialID(setting); + gLocalTerrainMaterials.setDetailAssetID(i, materialID); + } +} //////////////////////////////////////////////////////////////////////////// LLPointer setting_get_control(LLControlGroup& group, const std::string& setting) @@ -834,6 +845,10 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorFarAwayDistance", handleUserImpostorDistanceChanged); setting_setup_signal_listener(gSavedSettings, "AutoTuneImpostorByDistEnabled", handleUserImpostorByDistEnabledChanged); setting_setup_signal_listener(gSavedSettings, "TuningFPSStrategy", handleFPSTuningStrategyChanged); + setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset1", handleLocalTerrainChanged); + setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset2", handleLocalTerrainChanged); + setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset3", handleLocalTerrainChanged); + setting_setup_signal_listener(gSavedSettings, "LocalTerrainAsset4", handleLocalTerrainChanged); setting_setup_signal_listener(gSavedPerAccountSettings, "AvatarHoverOffsetZ", handleAvatarHoverOffsetChanged); } diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 815489f753..c4bed85be7 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -42,6 +42,8 @@ #include "llviewercontrol.h" +static const U32 BASE_SIZE = 128; + F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac) { @@ -59,40 +61,40 @@ F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F return result; } - -LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : - LLViewerLayer(width, scale) +LLTerrainMaterials::LLTerrainMaterials() { - mSurfacep = surfacep; - - // Load Terrain Textures - Original ones - setDetailAssetID(0, TERRAIN_DIRT_DETAIL); - setDetailAssetID(1, TERRAIN_GRASS_DETAIL); - setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL); - setDetailAssetID(3, TERRAIN_ROCK_DETAIL); - - // Initialize the texture matrix to defaults. - for (S32 i = 0; i < CORNER_COUNT; ++i) - { - mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight"); - mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange"); - } - for (S32 i = 0; i < ASSET_COUNT; ++i) { mMaterialTexturesSet[i] = false; } } - -LLVLComposition::~LLVLComposition() +LLTerrainMaterials::~LLTerrainMaterials() { } +BOOL LLTerrainMaterials::generateMaterials() +{ + if (texturesReady(TRUE)) + { + return TRUE; + } -void LLVLComposition::setSurface(LLSurface *surfacep) + if (materialsReady(TRUE)) + { + return TRUE; + } + + return FALSE; +} + +LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset) { - mSurfacep = surfacep; + llassert(mDetailTextures[asset] && mDetailMaterials[asset]); + // *HACK: Assume both the the material and texture were fetched in the same + // way using the same UUID. However, we may not know at this point which + // one will load. + return mDetailTextures[asset]->getID(); } LLPointer fetch_terrain_texture(const LLUUID& id) @@ -107,126 +109,51 @@ LLPointer fetch_terrain_texture(const LLUUID& id) return tex; } -void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id) +void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) { - if(id.isNull()) - { - return; - } // This is terrain texture, but we are not setting it as BOOST_TERRAIN // since we will be manipulating it later as needed. mDetailTextures[asset] = fetch_terrain_texture(id); - mRawImages[asset] = NULL; LLPointer& mat = mDetailMaterials[asset]; mat = gGLTFMaterialList.getMaterial(id); mMaterialTexturesSet[asset] = false; } -BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, - const F32 width, const F32 height) +BOOL LLTerrainMaterials::useTextures() { - if (!mParamsReady) - { - // All the parameters haven't been set yet (we haven't gotten the message from the sim) - return FALSE; - } - - llassert(mSurfacep); - - if (!mSurfacep || !mSurfacep->getRegion()) - { - // We don't always have the region yet here.... - return FALSE; - } - - S32 x_begin, y_begin, x_end, y_end; + LL_PROFILE_ZONE_SCOPED; - x_begin = ll_round( x * mScaleInv ); - y_begin = ll_round( y * mScaleInv ); - x_end = ll_round( (x + width) * mScaleInv ); - y_end = ll_round( (y + width) * mScaleInv ); + return texturesReady() || !materialsReady(); +} - if (x_end > mWidth) - { - x_end = mWidth; - } - if (y_end > mWidth) +BOOL LLTerrainMaterials::texturesReady(BOOL boost) +{ + for (S32 i = 0; i < ASSET_COUNT; i++) { - y_end = mWidth; + if (!textureReady(mDetailTextures[i], boost)) + { + return FALSE; + } } + return TRUE; +} - LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle()); - - // For perlin noise generation... - const F32 slope_squared = 1.5f*1.5f; - const F32 xyScale = 4.9215f; //0.93284f; - const F32 zScale = 4; //0.92165f; - const F32 z_offset = 0.f; - const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus - // simple height) - - const F32 xyScaleInv = (1.f / xyScale); - const F32 zScaleInv = (1.f / zScale); - - const F32 inv_width = 1.f/mWidth; - - // OK, for now, just have the composition value equal the height at the point. - for (S32 j = y_begin; j < y_end; j++) +BOOL LLTerrainMaterials::materialsReady(BOOL boost) +{ + for (S32 i = 0; i < ASSET_COUNT; i++) { - for (S32 i = x_begin; i < x_end; i++) - { - - F32 vec[3]; - F32 vec1[3]; - F32 twiddle; - - // Bilinearly interpolate the start height and height range of the textures - F32 start_height = bilinear(mStartHeight[SOUTHWEST], - mStartHeight[SOUTHEAST], - mStartHeight[NORTHWEST], - mStartHeight[NORTHEAST], - i*inv_width, j*inv_width); // These will be bilinearly interpolated - F32 height_range = bilinear(mHeightRange[SOUTHWEST], - mHeightRange[SOUTHEAST], - mHeightRange[NORTHWEST], - mHeightRange[NORTHEAST], - i*inv_width, j*inv_width); // These will be bilinearly interpolated - - LLVector3 location(i*mScale, j*mScale, 0.f); - - F32 height = mSurfacep->resolveHeightRegion(location) + z_offset; - - // Step 0: Measure the exact height at this texel - vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice - vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; - vec[2] = height*zScaleInv; - // - // Choose material value by adding to the exact height a random value - // - vec1[0] = vec[0]*(0.2222222222f); - vec1[1] = vec[1]*(0.2222222222f); - vec1[2] = vec[2]*(0.2222222222f); - twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions - - twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component - twiddle *= noise_magnitude; - - F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range; - - scaled_noisy_height = llmax(0.f, scaled_noisy_height); - scaled_noisy_height = llmin(3.f, scaled_noisy_height); - *(mDatap + i + j*mWidth) = scaled_noisy_height; - } - } - return TRUE; + if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost)) + { + return FALSE; + } + } + return TRUE; } -static const U32 BASE_SIZE = 128; - // Boost the texture loading priority // Return true when ready to use (i.e. texture is sufficiently loaded) // static -BOOL LLVLComposition::textureReady(LLPointer& tex, BOOL boost) +BOOL LLTerrainMaterials::textureReady(LLPointer& tex, BOOL boost) { llassert(tex.notNull()); @@ -266,9 +193,9 @@ BOOL LLVLComposition::textureReady(LLPointer& tex, BOOL // Boost the loading priority of every known texture in the material // Return true when ready to use (i.e. material and all textures within are sufficiently loaded) // static -BOOL LLVLComposition::materialReady(LLPointer& mat, bool& textures_set, BOOL boost) +BOOL LLTerrainMaterials::materialReady(LLPointer& mat, bool& textures_set, BOOL boost) { - if (!mat->isLoaded()) + if (!mat || !mat->isLoaded()) { return FALSE; } @@ -308,37 +235,140 @@ BOOL LLVLComposition::materialReady(LLPointer& mat, bool& return TRUE; } -BOOL LLVLComposition::useTextures() + +LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : + LLTerrainMaterials(), + LLViewerLayer(width, scale) +{ + // Load Terrain Textures - Original ones + setDetailAssetID(0, TERRAIN_DIRT_DETAIL); + setDetailAssetID(1, TERRAIN_GRASS_DETAIL); + setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL); + setDetailAssetID(3, TERRAIN_ROCK_DETAIL); + + mSurfacep = surfacep; + + // Initialize the texture matrix to defaults. + for (S32 i = 0; i < CORNER_COUNT; ++i) + { + mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight"); + mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange"); + } +} + + +LLVLComposition::~LLVLComposition() { - LL_PROFILE_ZONE_SCOPED; + LLTerrainMaterials::~LLTerrainMaterials(); +} - return texturesReady() || !materialsReady(); + +void LLVLComposition::setSurface(LLSurface *surfacep) +{ + mSurfacep = surfacep; } -BOOL LLVLComposition::texturesReady(BOOL boost) +BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, + const F32 width, const F32 height) { - for (S32 i = 0; i < ASSET_COUNT; i++) + if (!mParamsReady) { - if (!textureReady(mDetailTextures[i], boost)) - { - return FALSE; - } + // All the parameters haven't been set yet (we haven't gotten the message from the sim) + return FALSE; } - return TRUE; -} -BOOL LLVLComposition::materialsReady(BOOL boost) -{ - for (S32 i = 0; i < ASSET_COUNT; i++) + llassert(mSurfacep); + + if (!mSurfacep || !mSurfacep->getRegion()) { - if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost)) - { - return FALSE; - } - } - return TRUE; + // We don't always have the region yet here.... + return FALSE; + } + + S32 x_begin, y_begin, x_end, y_end; + + x_begin = ll_round( x * mScaleInv ); + y_begin = ll_round( y * mScaleInv ); + x_end = ll_round( (x + width) * mScaleInv ); + y_end = ll_round( (y + width) * mScaleInv ); + + if (x_end > mWidth) + { + x_end = mWidth; + } + if (y_end > mWidth) + { + y_end = mWidth; + } + + LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle()); + + // For perlin noise generation... + const F32 slope_squared = 1.5f*1.5f; + const F32 xyScale = 4.9215f; //0.93284f; + const F32 zScale = 4; //0.92165f; + const F32 z_offset = 0.f; + const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus + // simple height) + + const F32 xyScaleInv = (1.f / xyScale); + const F32 zScaleInv = (1.f / zScale); + + const F32 inv_width = 1.f/mWidth; + + // OK, for now, just have the composition value equal the height at the point. + for (S32 j = y_begin; j < y_end; j++) + { + for (S32 i = x_begin; i < x_end; i++) + { + + F32 vec[3]; + F32 vec1[3]; + F32 twiddle; + + // Bilinearly interpolate the start height and height range of the textures + F32 start_height = bilinear(mStartHeight[SOUTHWEST], + mStartHeight[SOUTHEAST], + mStartHeight[NORTHWEST], + mStartHeight[NORTHEAST], + i*inv_width, j*inv_width); // These will be bilinearly interpolated + F32 height_range = bilinear(mHeightRange[SOUTHWEST], + mHeightRange[SOUTHEAST], + mHeightRange[NORTHWEST], + mHeightRange[NORTHEAST], + i*inv_width, j*inv_width); // These will be bilinearly interpolated + + LLVector3 location(i*mScale, j*mScale, 0.f); + + F32 height = mSurfacep->resolveHeightRegion(location) + z_offset; + + // Step 0: Measure the exact height at this texel + vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice + vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; + vec[2] = height*zScaleInv; + // + // Choose material value by adding to the exact height a random value + // + vec1[0] = vec[0]*(0.2222222222f); + vec1[1] = vec[1]*(0.2222222222f); + vec1[2] = vec[2]*(0.2222222222f); + twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions + + twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component + twiddle *= noise_magnitude; + + F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range; + + scaled_noisy_height = llmax(0.f, scaled_noisy_height); + scaled_noisy_height = llmin(3.f, scaled_noisy_height); + *(mDatap + i + j*mWidth) = scaled_noisy_height; + } + } + return TRUE; } +LLTerrainMaterials gLocalTerrainMaterials; + BOOL LLVLComposition::generateComposition() { if (!mParamsReady) @@ -347,17 +377,7 @@ BOOL LLVLComposition::generateComposition() return FALSE; } - if (texturesReady(TRUE)) - { - return TRUE; - } - - if (materialsReady(TRUE)) - { - return TRUE; - } - - return FALSE; + return LLTerrainMaterials::generateMaterials(); } // TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. @@ -592,18 +612,19 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, return TRUE; } -LLUUID LLVLComposition::getDetailAssetID(S32 corner) +F32 LLVLComposition::getStartHeight(S32 corner) { - llassert(mDetailTextures[corner] && mDetailMaterials[corner]); - // *HACK: Assume both the the material and texture were fetched in the same - // way using the same UUID. However, we may not know at this point which - // one will load. - return mDetailTextures[corner]->getID(); + return mStartHeight[corner]; } -F32 LLVLComposition::getStartHeight(S32 corner) +void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id) { - return mStartHeight[corner]; + if (id.isNull()) + { + return; + } + LLTerrainMaterials::setDetailAssetID(asset, id); + mRawImages[asset] = NULL; } void LLVLComposition::setStartHeight(S32 corner, const F32 start_height) diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 504441d0f2..9dc0b7221e 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -37,7 +37,38 @@ class LLSurface; class LLViewerFetchedTexture; class LLFetchedGLTFMaterial; -class LLVLComposition : public LLViewerLayer +class LLTerrainMaterials +{ +public: + friend class LLDrawPoolTerrain; + + LLTerrainMaterials(); + virtual ~LLTerrainMaterials(); + + // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. + // So we need to compress heights into this range. + static const S32 ASSET_COUNT = 4; + + BOOL generateMaterials(); + + LLUUID getDetailAssetID(S32 asset); + virtual void setDetailAssetID(S32 asset, const LLUUID& id); + BOOL useTextures(); + BOOL texturesReady(BOOL boost = FALSE); + BOOL materialsReady(BOOL boost = FALSE); + +protected: + static BOOL textureReady(LLPointer& tex, BOOL boost = FALSE); + static BOOL materialReady(LLPointer& mat, bool& textures_set, BOOL boost = FALSE); + LLPointer mDetailTextures[ASSET_COUNT]; + LLPointer mDetailMaterials[ASSET_COUNT]; + bool mMaterialTexturesSet[ASSET_COUNT]; +}; + +// Local materials to override all regions +extern LLTerrainMaterials gLocalTerrainMaterials; + +class LLVLComposition : public LLTerrainMaterials, public LLViewerLayer { public: LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); @@ -65,11 +96,10 @@ public: CORNER_COUNT = 4 }; - LLUUID getDetailAssetID(S32 asset); + void setDetailAssetID(S32 asset, const LLUUID& id) override; F32 getStartHeight(S32 corner); F32 getHeightRange(S32 corner); - void setDetailAssetID(S32 asset, const LLUUID& id); void setStartHeight(S32 corner, F32 start_height); void setHeightRange(S32 corner, F32 range); @@ -77,9 +107,6 @@ public: friend class LLDrawPoolTerrain; void setParamsReady() { mParamsReady = TRUE; } BOOL getParamsReady() const { return mParamsReady; } - BOOL useTextures(); - BOOL texturesReady(BOOL boost = FALSE); - BOOL materialsReady(BOOL boost = FALSE); protected: static BOOL textureReady(LLPointer& tex, BOOL boost = FALSE); @@ -88,10 +115,7 @@ protected: BOOL mParamsReady = FALSE; LLSurface *mSurfacep; - LLPointer mDetailTextures[ASSET_COUNT]; - LLPointer mRawImages[ASSET_COUNT]; - LLPointer mDetailMaterials[ASSET_COUNT]; - bool mMaterialTexturesSet[ASSET_COUNT]; + LLPointer mRawImages[LLTerrainMaterials::ASSET_COUNT]; F32 mStartHeight[CORNER_COUNT]; F32 mHeightRange[CORNER_COUNT]; -- cgit v1.2.3 From 14c3730bf128a6f01825954ee67a06188e134526 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:20 -0700 Subject: DRTVWR-592: Fix unable to undo effect of local terrain debug setting without restarting viewer --- indra/newview/llvlcomposition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index c4bed85be7..8d55c80be8 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -115,7 +115,7 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) // since we will be manipulating it later as needed. mDetailTextures[asset] = fetch_terrain_texture(id); LLPointer& mat = mDetailMaterials[asset]; - mat = gGLTFMaterialList.getMaterial(id); + mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id); mMaterialTexturesSet[asset] = false; } -- cgit v1.2.3 From d2da77698005579f9fdaecad5a5d80189ad03f23 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:27 -0700 Subject: DRTVWR-592: Fix some virtual functions not being marked override --- indra/newview/llfloaterregioninfo.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 43a69e5804..bfdeb9440d 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -76,7 +76,7 @@ public: void onOpen(const LLSD& key) override; - /*virtual*/ void onClose(bool app_quitting); + void onClose(bool app_quitting) override; BOOL postBuild() override; static void processEstateOwnerRequest(LLMessageSystem* msg, void**); @@ -249,7 +249,7 @@ public: BOOL postBuild() override; - bool refreshFromRegion(LLViewerRegion* region); // refresh local settings from region update from simulator + bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region BOOL validateTextureSizes(); @@ -308,10 +308,10 @@ public: static void updateEstateOwnerName(const std::string& name); bool refreshFromRegion(LLViewerRegion* region) override; - virtual bool estateUpdate(LLMessageSystem* msg); + bool estateUpdate(LLMessageSystem* msg) override; BOOL postBuild() override; - virtual void updateChild(LLUICtrl* child_ctrl); + void updateChild(LLUICtrl* child_ctrl) override; void refresh() override; void refreshFromEstate(); @@ -343,15 +343,15 @@ public: ~LLPanelEstateCovenant() {} BOOL postBuild() override; - virtual void updateChild(LLUICtrl* child_ctrl); + void updateChild(LLUICtrl* child_ctrl) override; bool refreshFromRegion(LLViewerRegion* region) override; - virtual bool estateUpdate(LLMessageSystem* msg); + bool estateUpdate(LLMessageSystem* msg) override; // LLView overrides BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg); + std::string& tooltip_msg) override; static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response); static void resetCovenantID(void* userdata); static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response); @@ -441,7 +441,7 @@ public: LLPanelEstateAccess(); BOOL postBuild() override; - virtual void updateChild(LLUICtrl* child_ctrl); + void updateChild(LLUICtrl* child_ctrl) override; void updateControls(LLViewerRegion* region); void updateLists(); -- cgit v1.2.3 From 1820f23b96a50962a3a6a3d48de1aff8e1acb2c0 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:35 -0700 Subject: DRTVWR-592: Fix issues with blending of materials, for example when fading out an emissive texture. Also affects base color and ORM --- .../shaders/class1/deferred/pbrterrainF.glsl | 105 ++++++++++++--------- 1 file changed, 62 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 4de6b9609c..85691ae9b6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -80,38 +80,63 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); } -vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec3[4] samples; - samples[0] = srgb_to_linear(texture2D(tex0, texcoord).xyz); - samples[1] = srgb_to_linear(texture2D(tex1, texcoord).xyz); - samples[2] = srgb_to_linear(texture2D(tex2, texcoord).xyz); - samples[3] = srgb_to_linear(texture2D(tex3, texcoord).xyz); + samples[0] = texture2D(tex0, texcoord).xyz; + samples[1] = texture2D(tex1, texcoord).xyz; + samples[2] = texture2D(tex2, texcoord).xyz; + samples[3] = texture2D(tex3, texcoord).xyz; + samples[0] = srgb_to_linear(samples[0]); + samples[1] = srgb_to_linear(samples[1]); + samples[2] = srgb_to_linear(samples[2]); + samples[3] = srgb_to_linear(samples[3]); + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; return terrain_mix(samples, alpha1, alpha2, alphaFinal); } -vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec4[4] samples; samples[0] = texture2D(tex0, texcoord); samples[1] = texture2D(tex1, texcoord); samples[2] = texture2D(tex2, texcoord); samples[3] = texture2D(tex3, texcoord); - // TODO: Why is this needed for pbropaqueF but not here? (and is there different behavior with base color vs emissive color, that also needs to be corrected?) - //samples[0].xyz = srgb_to_linear(samples[0].xyz); - //samples[1].xyz = srgb_to_linear(samples[1].xyz); - //samples[2].xyz = srgb_to_linear(samples[2].xyz); - //samples[3].xyz = srgb_to_linear(samples[3].xyz); + samples[0].xyz = srgb_to_linear(samples[0].xyz); + samples[1].xyz = srgb_to_linear(samples[1].xyz); + samples[2].xyz = srgb_to_linear(samples[2].xyz); + samples[3].xyz = srgb_to_linear(samples[3].xyz); + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; return terrain_mix(samples, alpha1, alpha2, alphaFinal); } -vec4 sample_and_mix_vector(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec4[4] samples; - samples[0] = texture2D(tex0, texcoord); - samples[1] = texture2D(tex1, texcoord); - samples[2] = texture2D(tex2, texcoord); - samples[3] = texture2D(tex3, texcoord); + vec3[4] samples; + samples[0] = texture2D(tex0, texcoord).xyz; + samples[1] = texture2D(tex1, texcoord).xyz; + samples[2] = texture2D(tex2, texcoord).xyz; + samples[3] = texture2D(tex3, texcoord).xyz; + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec3[4] samples; + samples[0] = texture2D(tex0, texcoord).xyz; + samples[1] = texture2D(tex1, texcoord).xyz; + samples[2] = texture2D(tex2, texcoord).xyz; + samples[3] = texture2D(tex3, texcoord).xyz; return terrain_mix(samples, alpha1, alpha2, alphaFinal); } @@ -124,23 +149,30 @@ void main() float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; - vec4 base_color = sample_and_mix_color4(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); + vec4 col = sample_and_mix_color4(alpha1, alpha2, alphaFinal, terrain_texcoord, baseColorFactors, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); - if (base_color.a < minimum_alpha) + if (col.a < minimum_alpha) { discard; } - vec4 normal_texture = sample_and_mix_vector(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); - vec4 metallic_roughness = sample_and_mix_vector(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); - vec3 emissive_texture = sample_and_mix_color3(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + vec3 normal_texture = sample_and_mix_vector3_no_scale(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); - vec4 baseColorFactor = terrain_mix(baseColorFactors, alpha1, alpha2, alphaFinal); - float metallicFactor = terrain_mix(metallicFactors, alpha1, alpha2, alphaFinal); - float roughnessFactor = terrain_mix(roughnessFactors, alpha1, alpha2, alphaFinal); - vec3 emissiveColor = terrain_mix(emissiveColors, alpha1, alpha2, alphaFinal); + vec3[4] orm_factors; + orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x); + orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y); + orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z); + orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w); + // RGB = Occlusion, Roughness, Metal + // default values, see LLViewerTexture::sDefaultPBRORMImagep + // occlusion 1.0 + // roughness 0.0 + // metal 0.0 + vec3 spec = sample_and_mix_vector3(alpha1, alpha2, alphaFinal, terrain_texcoord, orm_factors, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); - vec3 col = baseColorFactor.rgb * srgb_to_linear(base_color.rgb); + vec3 emissive = sample_and_mix_color3(alpha1, alpha2, alphaFinal, terrain_texcoord, emissiveColors, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); + + float base_color_factor_alpha = terrain_mix(vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z), alpha1, alpha2, alphaFinal); // from mikktspace.com vec3 vNt = normal_texture.xyz*2.0-1.0; @@ -151,25 +183,12 @@ void main() vec3 vB = sign * cross(vN, vT); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); - // RGB = Occlusion, Roughness, Metal - // default values, see LLViewerTexture::sDefaultPBRORMImagep - // occlusion 1.0 - // roughness 0.0 - // metal 0.0 - vec3 spec = metallic_roughness.rgb; - - spec.g *= roughnessFactor; - spec.b *= metallicFactor; - - vec3 emissive = emissiveColor; - emissive *= emissive_texture.rgb; - tnorm *= gl_FrontFacing ? 1.0 : -1.0; - frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(spec.rgb,baseColorFactor.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(encode_normal(tnorm), baseColorFactor.a, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags + frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse + frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } -- cgit v1.2.3 From 3b3ba3623ac816633b1bd67f5d3b4dea65a83b17 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:43 -0700 Subject: DRTVWR-592: Overdraw is not free. Render terrain after Opaque Blinn-Phong/PBR have populated the foreground --- indra/newview/lldrawpool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index d5ef734c4b..c0bcb2b48d 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -56,9 +56,9 @@ public: POOL_SIMPLE = 1, POOL_FULLBRIGHT, POOL_BUMP, - POOL_TERRAIN, POOL_MATERIALS, POOL_GLTF_PBR, + POOL_TERRAIN, POOL_GRASS, POOL_GLTF_PBR_ALPHA_MASK, POOL_TREE, -- cgit v1.2.3 From de9184479cfc179ba6e9d6ff388aff7da7f0b4ab Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 09:58:50 -0700 Subject: DRTVWR-592: (WIP) Fix tiling only in the PBR case. Begin hooking up code for PBR-specific terrain geometry updates. Unfortunately, this version has a bug which can cause rebuilds to be skipped. Needs more work/testing --- indra/newview/lldrawpoolterrain.cpp | 2 +- indra/newview/llsurfacepatch.cpp | 1 + indra/newview/llvlcomposition.cpp | 13 ++++-- indra/newview/llvlcomposition.h | 9 +++- indra/newview/llvosurfacepatch.cpp | 84 +++++++++++++++++++++---------------- indra/newview/llvosurfacepatch.h | 12 ++++-- 6 files changed, 77 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 8755e53763..e072e1def2 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -253,7 +253,7 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - const BOOL use_textures = !use_local_materials && compp->useTextures(); + const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::MaterialType::TEXTURE); if (use_textures) { diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 449d3d95c8..81fb4cf0cd 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -209,6 +209,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } llassert_always(vertex && normal && tex0 && tex1); + // TODO: I think this is off by 1. Should use 1 less (which iirc is captured in another field member. See LLSurface::create). Do some hack to fix repeats for PBR only, while keeping legacy texture the same? U32 surface_stride = mSurfacep->getGridsPerEdge(); U32 point_offset = x + y*surface_stride; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8d55c80be8..8cd22e3bdb 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -119,13 +119,20 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) mMaterialTexturesSet[asset] = false; } -BOOL LLTerrainMaterials::useTextures() +BOOL LLTerrainMaterials::getMaterialType() +{ + return mMaterialType; +} + +void LLTerrainMaterials::updateMaterialType() { LL_PROFILE_ZONE_SCOPED; - return texturesReady() || !materialsReady(); + const BOOL use_textures = texturesReady() || !materialsReady(); + mMaterialType = use_textures ? Type::TEXTURE : Type::PBR; } + BOOL LLTerrainMaterials::texturesReady(BOOL boost) { for (S32 i = 0; i < ASSET_COUNT; i++) @@ -401,7 +408,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, U8* st_data[ASSET_COUNT]; S32 st_data_size[ASSET_COUNT]; // for debugging - const bool use_textures = useTextures(); + const bool use_textures = getMaterialType() != LLTerrainMaterial::Type::PBR; for (S32 i = 0; i < ASSET_COUNT; i++) { diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 9dc0b7221e..882c3d89b2 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -49,11 +49,18 @@ public: // So we need to compress heights into this range. static const S32 ASSET_COUNT = 4; + enum class Type + { + TEXTURE, + PBR, + COUNT + }; + BOOL generateMaterials(); LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); - BOOL useTextures(); + Type getMaterialType(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 839eb2b737..69b721c899 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -246,7 +246,8 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp) + LLStrider &indicesp, + bool pbr) { LLFace* facep = mDrawable->getFace(0); if (!facep) @@ -262,30 +263,34 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); updateNorthGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); updateEastGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 i, j, x, y; @@ -321,7 +326,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, { x = i * render_stride; y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -384,12 +389,13 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 vertex_count = 0; S32 i, x, y; @@ -421,7 +427,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -434,7 +440,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -471,7 +477,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -485,7 +491,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -529,7 +535,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -543,7 +549,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -581,12 +587,13 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, } void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 i, x, y; @@ -612,7 +619,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -624,7 +631,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -660,7 +667,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -672,7 +679,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -714,7 +721,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -726,7 +733,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -1037,6 +1044,13 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; + const LLFace* region_facep = *mFaceList.begin(); + const LLViewerObject* region_patchp = region_facep->getViewerObject(); + LLVLComposition* composition = region_patchp->mRegionp->getComposition(); + // TODO: This is not good; it will result in wrong texture repeats in cases where the assets have not loaded. Need to rebuild terrain on asset load event if it changes the composition type. Probably best to have a flag to bookkeep that, to know if the composition type has actually changed. Make sure the draw pool is boosting the textures so they load in a timely fashion. + composition->updateMaterialType(); + const bool pbr = composition->getMaterialType() == LLTerrainMaterial::Type::PBR; + LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index a3dcb945d1..06bb373578 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -67,7 +67,8 @@ public: LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp); + LLStrider &indicesp, + bool pbr); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -121,21 +122,24 @@ protected: LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From 2318d657660320b921e1566b54d3833c0401a34c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 22 May 2023 10:10:14 -0700 Subject: Revert "DRTVWR-592: (WIP) Fix tiling only in the PBR case. Begin hooking up code for PBR-specific terrain geometry updates. Unfortunately, this version has a bug which can cause rebuilds to be skipped. Needs more work/testing" This reverts commit de9184479cfc179ba6e9d6ff388aff7da7f0b4ab. --- indra/newview/lldrawpoolterrain.cpp | 2 +- indra/newview/llsurfacepatch.cpp | 1 - indra/newview/llvlcomposition.cpp | 13 ++---- indra/newview/llvlcomposition.h | 9 +--- indra/newview/llvosurfacepatch.cpp | 84 ++++++++++++++++--------------------- indra/newview/llvosurfacepatch.h | 12 ++---- 6 files changed, 44 insertions(+), 77 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index e072e1def2..8755e53763 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -253,7 +253,7 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::MaterialType::TEXTURE); + const BOOL use_textures = !use_local_materials && compp->useTextures(); if (use_textures) { diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 81fb4cf0cd..449d3d95c8 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -209,7 +209,6 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } llassert_always(vertex && normal && tex0 && tex1); - // TODO: I think this is off by 1. Should use 1 less (which iirc is captured in another field member. See LLSurface::create). Do some hack to fix repeats for PBR only, while keeping legacy texture the same? U32 surface_stride = mSurfacep->getGridsPerEdge(); U32 point_offset = x + y*surface_stride; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8cd22e3bdb..8d55c80be8 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -119,20 +119,13 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) mMaterialTexturesSet[asset] = false; } -BOOL LLTerrainMaterials::getMaterialType() -{ - return mMaterialType; -} - -void LLTerrainMaterials::updateMaterialType() +BOOL LLTerrainMaterials::useTextures() { LL_PROFILE_ZONE_SCOPED; - const BOOL use_textures = texturesReady() || !materialsReady(); - mMaterialType = use_textures ? Type::TEXTURE : Type::PBR; + return texturesReady() || !materialsReady(); } - BOOL LLTerrainMaterials::texturesReady(BOOL boost) { for (S32 i = 0; i < ASSET_COUNT; i++) @@ -408,7 +401,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, U8* st_data[ASSET_COUNT]; S32 st_data_size[ASSET_COUNT]; // for debugging - const bool use_textures = getMaterialType() != LLTerrainMaterial::Type::PBR; + const bool use_textures = useTextures(); for (S32 i = 0; i < ASSET_COUNT; i++) { diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 882c3d89b2..9dc0b7221e 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -49,18 +49,11 @@ public: // So we need to compress heights into this range. static const S32 ASSET_COUNT = 4; - enum class Type - { - TEXTURE, - PBR, - COUNT - }; - BOOL generateMaterials(); LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); - Type getMaterialType(); + BOOL useTextures(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 69b721c899..839eb2b737 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -246,8 +246,7 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp, - bool pbr) + LLStrider &indicesp) { LLFace* facep = mDrawable->getFace(0); if (!facep) @@ -263,34 +262,30 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); updateNorthGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); updateEastGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset, - bool pbr) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset) { S32 i, j, x, y; @@ -326,7 +321,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, { x = i * render_stride; y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -389,13 +384,12 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset, - bool pbr) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset) { S32 vertex_count = 0; S32 i, x, y; @@ -427,7 +421,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -440,7 +434,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -477,7 +471,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -491,7 +485,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -535,7 +529,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -549,7 +543,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -587,13 +581,12 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, } void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset, - bool pbr) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset) { S32 i, x, y; @@ -619,7 +612,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -631,7 +624,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -667,7 +660,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -679,7 +672,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -721,7 +714,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -733,7 +726,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -1044,13 +1037,6 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; - const LLFace* region_facep = *mFaceList.begin(); - const LLViewerObject* region_patchp = region_facep->getViewerObject(); - LLVLComposition* composition = region_patchp->mRegionp->getComposition(); - // TODO: This is not good; it will result in wrong texture repeats in cases where the assets have not loaded. Need to rebuild terrain on asset load event if it changes the composition type. Probably best to have a flag to bookkeep that, to know if the composition type has actually changed. Make sure the draw pool is boosting the textures so they load in a timely fashion. - composition->updateMaterialType(); - const bool pbr = composition->getMaterialType() == LLTerrainMaterial::Type::PBR; - LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 06bb373578..a3dcb945d1 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -67,8 +67,7 @@ public: LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp, - bool pbr); + LLStrider &indicesp); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -122,24 +121,21 @@ protected: LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From dfa19c5e436edb102d8bd121c853153303631b4d Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:33:16 -0700 Subject: DRTVWR-592: PBR terrain fallback for Mac/Intel: Drop emissive texture. Bump featuretable. --- indra/newview/app_settings/settings.xml | 11 +++++ .../shaders/class1/deferred/pbrterrainF.glsl | 10 ++++ indra/newview/featuretable.txt | 2 + indra/newview/featuretable_mac.txt | 1 + indra/newview/lldrawpoolterrain.cpp | 54 +++++++++++++--------- indra/newview/lldrawpoolterrain.h | 3 +- indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewershadermgr.cpp | 35 +++++++------- indra/newview/llviewershadermgr.h | 11 +++++ 9 files changed, 89 insertions(+), 39 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 013f0ca8ff..94cc5a14a4 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10711,6 +10711,17 @@ Value 12.0 + RenderTerrainPBRDetail + + Comment + Detail level for PBR terrain. 0 is full detail. Negative values drop rendering features in accordance with the GLTF specification, which reduces the number of texture binds. Some Intel and Mac graphics drivers do not support more than 16 texture binds. Because PBR terrain exceeds this limit at the highest detail level, reducing texture binds is necessary for compatibility. + Persist + 1 + Type + S32 + Value + 0 + RenderTrackerBeacon Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 85691ae9b6..344c342189 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -23,6 +23,8 @@ * $/LicenseInfo$ */ +#define TERRAIN_PBR_DETAIL_EMISSIVE 0 + out vec4 frag_data[4]; uniform sampler2D alpha_ramp; @@ -42,16 +44,20 @@ uniform sampler2D detail_0_metallic_roughness; uniform sampler2D detail_1_metallic_roughness; uniform sampler2D detail_2_metallic_roughness; uniform sampler2D detail_3_metallic_roughness; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) uniform sampler2D detail_0_emissive; uniform sampler2D detail_1_emissive; uniform sampler2D detail_2_emissive; uniform sampler2D detail_3_emissive; +#endif // *TODO: More efficient packing? uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl uniform vec4 metallicFactors; uniform vec4 roughnessFactors; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) uniform vec3[4] emissiveColors; +#endif uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() in vec3 vary_normal; @@ -170,7 +176,11 @@ void main() // metal 0.0 vec3 spec = sample_and_mix_vector3(alpha1, alpha2, alphaFinal, terrain_texcoord, orm_factors, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) vec3 emissive = sample_and_mix_color3(alpha1, alpha2, alphaFinal, terrain_texcoord, emissiveColors, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); +#else + vec3 emissive = vec3(0); +#endif float base_color_factor_alpha = terrain_mix(vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z), alpha1, alpha2, alphaFinal); diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 39f7996c7c..b8e8cffed8 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -48,6 +48,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 RenderVBOMappingDisable 1 1 @@ -312,6 +313,7 @@ RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLContextCoreProfile 1 0 RenderGLMultiThreadedMedia 1 0 +RenderTerrainPBRDetail 1 -1 list AMD RenderGLMultiThreadedTextures 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index cce403c7aa..d775f04810 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -45,6 +45,7 @@ RenderObjectBump 1 1 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 -1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 8755e53763..8442e61bb9 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -54,7 +54,10 @@ const F32 DETAIL_SCALE = 1.f/16.f; int DebugDetailMap = 0; +const S32 PBR_DETAIL_EMISSIVE = 0; + S32 LLDrawPoolTerrain::sDetailMode = 1; +S32 LLDrawPoolTerrain::sPBRDetailMode = 0; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; static LLGLSLShader* sShader = NULL; static LLTrace::BlockTimerStatHandle FTM_SHADOW_TERRAIN("Terrain Shadow"); @@ -66,7 +69,9 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : { // Hack! sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); + // TODO: This is unused. Remove? sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); + sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD); //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); @@ -106,12 +111,7 @@ U32 LLDrawPoolTerrain::getVertexDataMask() void LLDrawPoolTerrain::prerender() { sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); -} - -//static -S32 LLDrawPoolTerrain::getDetailMode() -{ - return sDetailMode; + sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); } void LLDrawPoolTerrain::boostTerrainDetailTextures() @@ -371,7 +371,7 @@ void LLDrawPoolTerrain::renderFullShaderTextures() gGL.getTexUnit(detail0)->activate(); } -// TODO: Investigate use of bindFast for PBR terrain textures +// *TODO: Investigate use of bindFast for PBR terrain textures void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) { // Hack! Get the region that this draw pool is rendering from! @@ -445,17 +445,20 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_metalrough[i])->activate(); - detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); - if (detail_emissive_texturep) - { - gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep); - } - else + if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) { - gGL.getTexUnit(detail_emissive[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); + if (detail_emissive_texturep) + { + gGL.getTexUnit(detail_emissive[i])->bind(detail_emissive_texturep); + } + else + { + gGL.getTexUnit(detail_emissive[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + } + gGL.getTexUnit(detail_emissive[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_emissive[i])->activate(); } - gGL.getTexUnit(detail_emissive[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail_emissive[i])->activate(); } LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; @@ -506,7 +509,10 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) shader->uniform4fv(LLShaderMgr::TERRAIN_BASE_COLOR_FACTORS, terrain_material_count, (F32*)base_color_factors); shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]); shader->uniform4f(LLShaderMgr::TERRAIN_ROUGHNESS_FACTORS, roughness_factors[0], roughness_factors[1], roughness_factors[2], roughness_factors[3]); - shader->uniform3fv(LLShaderMgr::TERRAIN_EMISSIVE_COLORS, terrain_material_count, (F32*)emissive_colors); + if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + { + shader->uniform3fv(LLShaderMgr::TERRAIN_EMISSIVE_COLORS, terrain_material_count, (F32*)emissive_colors); + } shader->uniform4f(LLShaderMgr::TERRAIN_MINIMUM_ALPHAS, minimum_alphas[0], minimum_alphas[1], minimum_alphas[2], minimum_alphas[3]); // GL_BLEND disabled by default @@ -525,7 +531,10 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); + if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + { + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); + } gGL.getTexUnit(detail_basecolor[i])->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(detail_basecolor[i])->disable(); @@ -539,9 +548,12 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) gGL.getTexUnit(detail_metalrough[i])->disable(); gGL.getTexUnit(detail_metalrough[i])->activate(); - gGL.getTexUnit(detail_emissive[i])->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail_emissive[i])->disable(); - gGL.getTexUnit(detail_emissive[i])->activate(); + if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + { + gGL.getTexUnit(detail_emissive[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_emissive[i])->disable(); + gGL.getTexUnit(detail_emissive[i])->activate(); + } } } diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 1a27cc8be0..060354458d 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -43,8 +43,6 @@ public: }; virtual U32 getVertexDataMask(); - static S32 getDetailMode(); - LLDrawPoolTerrain(LLViewerTexture *texturep); virtual ~LLDrawPoolTerrain(); @@ -69,6 +67,7 @@ public: LLPointer mAlphaNoiseImagep; static S32 sDetailMode; + static S32 sPBRDetailMode; static F32 sDetailScale; // meters per texture protected: diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 4e0ad11597..41b13cacbb 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -702,6 +702,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 19b3c59cae..2235b6d9a4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1494,23 +1494,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - gDeferredPBRTerrainProgram.mName = "Deferred PBR Terrain Shader"; - gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; - gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; - gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; - gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredPBRTerrainProgram.mFeatures.hasWaterFog = true; - gDeferredPBRTerrainProgram.mFeatures.calculatesAtmospherics = true; - gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true; - gDeferredPBRTerrainProgram.mFeatures.hasGamma = true; - gDeferredPBRTerrainProgram.mFeatures.hasTransport = true; - - gDeferredPBRTerrainProgram.mShaderFiles.clear(); - gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainV.glsl", GL_VERTEX_SHADER)); - gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainF.glsl", GL_FRAGMENT_SHADER)); - gDeferredPBRTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); + detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX); + gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d", detail); + gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; + gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; + gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; + gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + gDeferredPBRTerrainProgram.mFeatures.hasWaterFog = true; + gDeferredPBRTerrainProgram.mFeatures.calculatesAtmospherics = true; + gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true; + gDeferredPBRTerrainProgram.mFeatures.hasGamma = true; + gDeferredPBRTerrainProgram.mFeatures.hasTransport = true; + + gDeferredPBRTerrainProgram.mShaderFiles.clear(); + gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainV.glsl", GL_VERTEX_SHADER)); + gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainF.glsl", GL_FRAGMENT_SHADER)); + gDeferredPBRTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PBR_DETAIL", llformat("%d", detail)); success = gDeferredPBRTerrainProgram.createShader(NULL, NULL); - llassert(success); + llassert(success); } if (success) diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 6765703ab8..8b4a19f8c3 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -278,5 +278,16 @@ extern LLGLSLShader gDeferredPBROpaqueProgram; extern LLGLSLShader gDeferredPBRAlphaProgram; extern LLGLSLShader gDeferredPBRAlphaWaterProgram; extern LLGLSLShader gHUDPBRAlphaProgram; + +// Encodes detail level for dropping textures, in accordance with the GLTF spec +// 0 is highest detail, -1 drops emissive, etc +// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures +enum TerrainPBRDetail : S32 +{ + TERRAIN_PBR_DETAIL_MAX = 0, + TERRAIN_PBR_DETAIL_EMISSIVE = 0, + TERRAIN_PBR_DETAIL_OCCLUSION = -1, + TERRAIN_PBR_DETAIL_MIN = -1, +}; extern LLGLSLShader gDeferredPBRTerrainProgram; #endif -- cgit v1.2.3 From cbf202d6324dfe67218e3a0d20ec1589f2906517 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 22 May 2023 18:19:14 -0700 Subject: SL-19750: Only disable PBR terrain emissive for machines that have a limit of 16 texture binds. Bump featuretable --- indra/newview/featuretable.txt | 5 +++-- indra/newview/featuretable_mac.txt | 6 ++++-- indra/newview/llfeaturemanager.cpp | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index b8e8cffed8..cb941b424b 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 58 +version 59 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -313,7 +313,6 @@ RenderAnisotropic 1 0 RenderFSAASamples 1 0 RenderGLContextCoreProfile 1 0 RenderGLMultiThreadedMedia 1 0 -RenderTerrainPBRDetail 1 -1 list AMD RenderGLMultiThreadedTextures 1 1 @@ -323,3 +322,5 @@ RenderFSAASamples 0 0 RenderReflectionsEnabled 0 0 RenderReflectionProbeDetail 0 0 +list TexUnit16orLess +RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index d775f04810..c04c1c9a4f 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 53 +version 54 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -45,7 +45,6 @@ RenderObjectBump 1 1 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 -RenderTerrainPBRDetail 1 -1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 @@ -309,6 +308,9 @@ RenderShadowDetail 0 0 list TexUnit8orLess RenderDeferredSSAO 0 0 +list TexUnit16orLess +RenderTerrainPBRDetail 1 -1 + list AMD RenderDeferredSSAO 1 0 diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index f482d5a37d..9fff505c2a 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -664,6 +664,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("TexUnit8orLess"); } + if (gGLManager.mNumTextureImageUnits <= 16) + { + maskFeatures("TexUnit16orLess"); + } if (gGLManager.mVRAM > 512) { maskFeatures("VRAMGT512"); -- cgit v1.2.3 From a65c9dad5521d8e8d375003220e362533a142250 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:33:21 -0700 Subject: DRTVWR-592: Another attempt to fix Mac build: remove deprecated use of texture2D --- .../shaders/class1/deferred/pbrterrainF.glsl | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 344c342189..73d4d9e3bc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -89,10 +89,10 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec3[4] samples; - samples[0] = texture2D(tex0, texcoord).xyz; - samples[1] = texture2D(tex1, texcoord).xyz; - samples[2] = texture2D(tex2, texcoord).xyz; - samples[3] = texture2D(tex3, texcoord).xyz; + samples[0] = texture(tex0, texcoord).xyz; + samples[1] = texture(tex1, texcoord).xyz; + samples[2] = texture(tex2, texcoord).xyz; + samples[3] = texture(tex3, texcoord).xyz; samples[0] = srgb_to_linear(samples[0]); samples[1] = srgb_to_linear(samples[1]); samples[2] = srgb_to_linear(samples[2]); @@ -107,10 +107,10 @@ vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 te vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec4[4] samples; - samples[0] = texture2D(tex0, texcoord); - samples[1] = texture2D(tex1, texcoord); - samples[2] = texture2D(tex2, texcoord); - samples[3] = texture2D(tex3, texcoord); + samples[0] = texture(tex0, texcoord); + samples[1] = texture(tex1, texcoord); + samples[2] = texture(tex2, texcoord); + samples[3] = texture(tex3, texcoord); samples[0].xyz = srgb_to_linear(samples[0].xyz); samples[1].xyz = srgb_to_linear(samples[1].xyz); samples[2].xyz = srgb_to_linear(samples[2].xyz); @@ -125,10 +125,10 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 te vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec3[4] samples; - samples[0] = texture2D(tex0, texcoord).xyz; - samples[1] = texture2D(tex1, texcoord).xyz; - samples[2] = texture2D(tex2, texcoord).xyz; - samples[3] = texture2D(tex3, texcoord).xyz; + samples[0] = texture(tex0, texcoord).xyz; + samples[1] = texture(tex1, texcoord).xyz; + samples[2] = texture(tex2, texcoord).xyz; + samples[3] = texture(tex3, texcoord).xyz; samples[0] *= factors[0]; samples[1] *= factors[1]; samples[2] *= factors[2]; @@ -139,10 +139,10 @@ vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, vec2 t vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec3[4] samples; - samples[0] = texture2D(tex0, texcoord).xyz; - samples[1] = texture2D(tex1, texcoord).xyz; - samples[2] = texture2D(tex2, texcoord).xyz; - samples[3] = texture2D(tex3, texcoord).xyz; + samples[0] = texture(tex0, texcoord).xyz; + samples[1] = texture(tex1, texcoord).xyz; + samples[2] = texture(tex2, texcoord).xyz; + samples[3] = texture(tex3, texcoord).xyz; return terrain_mix(samples, alpha1, alpha2, alphaFinal); } @@ -151,9 +151,9 @@ void main() // Adjust the texture repeats for a more sensible default. float texture_density_factor = 2.0; vec2 terrain_texcoord = texture_density_factor * vary_texcoord0.xy; - float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a; - float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a; - float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a; + float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a; + float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; + float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; vec4 col = sample_and_mix_color4(alpha1, alpha2, alphaFinal, terrain_texcoord, baseColorFactors, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); -- cgit v1.2.3 From 57433341abffba9382e6899b164af40200f5d6d3 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:35:02 -0700 Subject: Revert "Revert "DRTVWR-592: (WIP) Fix tiling only in the PBR case. Begin hooking up code for PBR-specific terrain geometry updates. Unfortunately, this version has a bug which can cause rebuilds to be skipped. Needs more work/testing"" This reverts commit 2318d657660320b921e1566b54d3833c0401a34c. --- indra/newview/lldrawpoolterrain.cpp | 2 +- indra/newview/llsurfacepatch.cpp | 1 + indra/newview/llvlcomposition.cpp | 13 ++++-- indra/newview/llvlcomposition.h | 9 +++- indra/newview/llvosurfacepatch.cpp | 84 +++++++++++++++++++++---------------- indra/newview/llvosurfacepatch.h | 12 ++++-- 6 files changed, 77 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 8442e61bb9..926d5e78d0 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -253,7 +253,7 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - const BOOL use_textures = !use_local_materials && compp->useTextures(); + const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::MaterialType::TEXTURE); if (use_textures) { diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 449d3d95c8..81fb4cf0cd 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -209,6 +209,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } llassert_always(vertex && normal && tex0 && tex1); + // TODO: I think this is off by 1. Should use 1 less (which iirc is captured in another field member. See LLSurface::create). Do some hack to fix repeats for PBR only, while keeping legacy texture the same? U32 surface_stride = mSurfacep->getGridsPerEdge(); U32 point_offset = x + y*surface_stride; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8d55c80be8..8cd22e3bdb 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -119,13 +119,20 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) mMaterialTexturesSet[asset] = false; } -BOOL LLTerrainMaterials::useTextures() +BOOL LLTerrainMaterials::getMaterialType() +{ + return mMaterialType; +} + +void LLTerrainMaterials::updateMaterialType() { LL_PROFILE_ZONE_SCOPED; - return texturesReady() || !materialsReady(); + const BOOL use_textures = texturesReady() || !materialsReady(); + mMaterialType = use_textures ? Type::TEXTURE : Type::PBR; } + BOOL LLTerrainMaterials::texturesReady(BOOL boost) { for (S32 i = 0; i < ASSET_COUNT; i++) @@ -401,7 +408,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, U8* st_data[ASSET_COUNT]; S32 st_data_size[ASSET_COUNT]; // for debugging - const bool use_textures = useTextures(); + const bool use_textures = getMaterialType() != LLTerrainMaterial::Type::PBR; for (S32 i = 0; i < ASSET_COUNT; i++) { diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 9dc0b7221e..882c3d89b2 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -49,11 +49,18 @@ public: // So we need to compress heights into this range. static const S32 ASSET_COUNT = 4; + enum class Type + { + TEXTURE, + PBR, + COUNT + }; + BOOL generateMaterials(); LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); - BOOL useTextures(); + Type getMaterialType(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 839eb2b737..69b721c899 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -246,7 +246,8 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp) + LLStrider &indicesp, + bool pbr) { LLFace* facep = mDrawable->getFace(0); if (!facep) @@ -262,30 +263,34 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); updateNorthGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); updateEastGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset); + index_offset, + pbr); } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 i, j, x, y; @@ -321,7 +326,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, { x = i * render_stride; y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -384,12 +389,13 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 vertex_count = 0; S32 i, x, y; @@ -421,7 +427,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -434,7 +440,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -471,7 +477,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -485,7 +491,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -529,7 +535,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -543,7 +549,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -581,12 +587,13 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, } void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset) + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset, + bool pbr) { S32 i, x, y; @@ -612,7 +619,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -624,7 +631,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -660,7 +667,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -672,7 +679,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -714,7 +721,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -726,7 +733,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); verticesp++; normalsp++; texCoords0p++; @@ -1037,6 +1044,13 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; + const LLFace* region_facep = *mFaceList.begin(); + const LLViewerObject* region_patchp = region_facep->getViewerObject(); + LLVLComposition* composition = region_patchp->mRegionp->getComposition(); + // TODO: This is not good; it will result in wrong texture repeats in cases where the assets have not loaded. Need to rebuild terrain on asset load event if it changes the composition type. Probably best to have a flag to bookkeep that, to know if the composition type has actually changed. Make sure the draw pool is boosting the textures so they load in a timely fashion. + composition->updateMaterialType(); + const bool pbr = composition->getMaterialType() == LLTerrainMaterial::Type::PBR; + LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index a3dcb945d1..06bb373578 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -67,7 +67,8 @@ public: LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp); + LLStrider &indicesp, + bool pbr); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -121,21 +122,24 @@ protected: LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset); + U32 &index_offset, + bool pbr); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From b9ba57fd0004751dfbcbea90264a6e16c5849e5e Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:38:42 -0700 Subject: DRTVWR-592: (WIP) Fix terrain PBR texture repeat seam. Legacy terrain texture repeats currently broken --- .../shaders/class1/deferred/pbrterrainF.glsl | 25 +++++++++++++++++++--- .../shaders/class1/deferred/pbrterrainV.glsl | 22 +++++++++++++------ indra/newview/lldrawpoolterrain.cpp | 4 +++- indra/newview/llsurfacepatch.cpp | 14 +++++++++--- indra/newview/llsurfacepatch.h | 2 +- indra/newview/llviewercontrol.cpp | 10 +++++++++ indra/newview/llvlcomposition.cpp | 8 +++---- indra/newview/llvlcomposition.h | 2 ++ indra/newview/llvosurfacepatch.cpp | 6 +++--- 9 files changed, 71 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 73d4d9e3bc..5f94855963 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -70,6 +70,7 @@ vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); +in vec4 debug_pos; // TODO: Remove // *TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { @@ -148,9 +149,8 @@ vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFina void main() { - // Adjust the texture repeats for a more sensible default. - float texture_density_factor = 2.0; - vec2 terrain_texcoord = texture_density_factor * vary_texcoord0.xy; + vec2 terrain_texcoord = vary_texcoord0.xy; + terrain_texcoord -= vec2(21.0);// TODO: Remove float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a; float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; @@ -162,6 +162,25 @@ void main() discard; } + // TODO: Remove all of this + float debug_pos_x = debug_pos.x; + //float debug_pos_x = terrain_texcoord.y; + float debug_metric = debug_pos_x; + debug_metric = debug_metric - floor(debug_metric); + debug_metric *= debug_metric; + float debug_metric2 = debug_pos_x / 4.0; + debug_metric2 = debug_metric2 - floor(debug_metric2); + debug_metric2 *= debug_metric2; + debug_metric2 *= debug_metric2; + debug_metric2 *= 16.0; + float debug_metric3 = debug_pos_x / 16.0; + debug_metric3 = debug_metric3 - floor(debug_metric3); + debug_metric3 *= debug_metric3; + debug_metric3 *= debug_metric3; + debug_metric3 *= debug_metric3; + debug_metric3 *= 16.0; + //col.xyz = vec3(debug_metric3, debug_metric2, debug_metric);// TODO: Remove + vec3 normal_texture = sample_and_mix_vector3_no_scale(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); vec3[4] orm_factors; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 6037a58c0d..fd80d1bb2c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -43,24 +43,27 @@ out vec4 vary_texcoord1; uniform vec4 object_plane_s; uniform vec4 object_plane_t; -vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) +vec4 texgen_object_pbr(vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) { vec4 tcoord; - tcoord.x = dot(vpos, tp0); - tcoord.y = dot(vpos, tp1); - tcoord.z = tc.z; - tcoord.w = tc.w; + tcoord.x = dot(tc, tp0); + tcoord.y = dot(tc, tp1); + tcoord.z = tcoord.z; + tcoord.w = tcoord.w; tcoord = mat * tcoord; - return tcoord; + return tcoord; } +out vec4 debug_pos; // TODO: Remove + void main() { //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + debug_pos = vec4(texcoord0, 0.0, 1.0); vec3 n = normal_matrix * normal; vec3 t = normal_matrix * tangent.xyz; @@ -71,7 +74,12 @@ void main() // Transform and pass tex coords // *NOTE: KHR texture transform is ignored for now - vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; + vary_texcoord0.xy = texgen_object_pbr(vec4(texcoord0, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; + // Adjust the texture repeats for a more sensible default. + // *TODO: Remove this extra factor when KHR texture transform is added + float texture_density_factor = 3.0; + //texture_density_factor /= 256.0; // TODO: Remove + vary_texcoord0.xy *= texture_density_factor; vec4 tc = vec4(texcoord1,0,1); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 926d5e78d0..b4671963e1 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -253,7 +253,7 @@ void LLDrawPoolTerrain::renderFullShader() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::MaterialType::TEXTURE); + const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::Type::TEXTURE); if (use_textures) { @@ -385,6 +385,8 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) materials = &gLocalTerrainMaterials.mDetailMaterials; } + // *TODO: I'm seeing terrain still jump when switching regions. Might have something to do with the extra repeat factor in the shader. Or is it a numerical precision issue?... + // *TODO: If we want to change the tiling, we should change this offset modulo to prevent seams LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 81fb4cf0cd..4f9911a11c 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -201,7 +201,7 @@ LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal, - LLVector2 *tex0, LLVector2 *tex1) + LLVector2 *tex0, LLVector2 *tex1, bool pbr) { if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp) { @@ -209,8 +209,15 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } llassert_always(vertex && normal && tex0 && tex1); - // TODO: I think this is off by 1. Should use 1 less (which iirc is captured in another field member. See LLSurface::create). Do some hack to fix repeats for PBR only, while keeping legacy texture the same? + // TODO: I think this operation is being applied too early because it also affects the geometry - we only want to affect the UVs + // TODO: Figure out what correct scaling is needed to prevent seams at region borders - getPatchesPerEdge seems to not be the solution, nor is getGridsPerEdge on its own U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 texture_stride = mSurfacep->getGridsPerEdge() - 1; + if (!pbr) + { + // TODO: Re-enable legacy repeats + //texture_stride = mSurfacep->getGridsPerEdge(); + } U32 point_offset = x + y*surface_stride; *normal = getNormal(x, y); @@ -222,7 +229,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); - LLVector3 tex_pos = rel_pos * (1.f/surface_stride); + // TODO: Revert for non-PBR only here, and/or add note that non-PBR doesn't actually use it. + LLVector3 tex_pos = rel_pos * (1.f/(texture_stride * mSurfacep->getMetersPerGrid())); tex0->mV[0] = tex_pos.mV[0]; tex0->mV[1] = tex_pos.mV[1]; tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y); diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index 8c8f501dce..0e6c045145 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -106,7 +106,7 @@ public: const LLVector3 &getNormal(const U32 x, const U32 y) const; void eval(const U32 x, const U32 y, const U32 stride, - LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1); + LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1, bool pbr); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 41b13cacbb..baf5480c6a 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -124,6 +124,15 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue) return true; } +static bool handleTerrainScaleChanged(const LLSD& newvalue) +{ + F64 scale = newvalue.asReal(); + if (scale != 0.0) + { + LLDrawPoolTerrain::sDetailScale = F32(1.0 / scale); + } + return true; +} static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) { @@ -702,6 +711,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8cd22e3bdb..130d74b286 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -119,7 +119,7 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) mMaterialTexturesSet[asset] = false; } -BOOL LLTerrainMaterials::getMaterialType() +LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType() { return mMaterialType; } @@ -132,7 +132,6 @@ void LLTerrainMaterials::updateMaterialType() mMaterialType = use_textures ? Type::TEXTURE : Type::PBR; } - BOOL LLTerrainMaterials::texturesReady(BOOL boost) { for (S32 i = 0; i < ASSET_COUNT; i++) @@ -408,7 +407,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, U8* st_data[ASSET_COUNT]; S32 st_data_size[ASSET_COUNT]; // for debugging - const bool use_textures = getMaterialType() != LLTerrainMaterial::Type::PBR; + const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; for (S32 i = 0; i < ASSET_COUNT; i++) { @@ -423,8 +422,9 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, else { tex = mDetailMaterials[i]->mBaseColorTexture; - if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } } + // TODO: Why are terrain textures (not terrain materials) not loading? (that is why there is a getComponents() check here) + if (!tex || tex->getComponents() == 0) { tex = LLViewerFetchedTexture::sWhiteImagep; } S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); S32 ddiscard = 0; diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 882c3d89b2..a62302292f 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -61,6 +61,7 @@ public: LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); + void updateMaterialType(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); @@ -70,6 +71,7 @@ protected: LLPointer mDetailTextures[ASSET_COUNT]; LLPointer mDetailMaterials[ASSET_COUNT]; bool mMaterialTexturesSet[ASSET_COUNT]; + Type mMaterialType = Type::TEXTURE; }; // Local materials to override all regions diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 69b721c899..a672777914 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -1046,10 +1046,10 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) const LLFace* region_facep = *mFaceList.begin(); const LLViewerObject* region_patchp = region_facep->getViewerObject(); - LLVLComposition* composition = region_patchp->mRegionp->getComposition(); + LLVLComposition* composition = region_patchp->getRegion()->getComposition(); // TODO: This is not good; it will result in wrong texture repeats in cases where the assets have not loaded. Need to rebuild terrain on asset load event if it changes the composition type. Probably best to have a flag to bookkeep that, to know if the composition type has actually changed. Make sure the draw pool is boosting the textures so they load in a timely fashion. composition->updateMaterialType(); - const bool pbr = composition->getMaterialType() == LLTerrainMaterial::Type::PBR; + const bool pbr = composition->getMaterialType() == LLTerrainMaterials::Type::PBR; LLVertexBuffer* buffer = group->mVertexBuffer; @@ -1087,7 +1087,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); - patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices); + patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices, pbr); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); -- cgit v1.2.3 From 35d889f7af9686b79fe0e5255121a444a044beab Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:38:48 -0700 Subject: DRTVWR-592: Create separate config option for terrain repeats. Clean up debug --- indra/newview/app_settings/settings.xml | 13 ++++++++++++- .../shaders/class1/deferred/pbrterrainF.glsl | 21 --------------------- .../shaders/class1/deferred/pbrterrainV.glsl | 12 ++---------- indra/newview/lldrawpoolterrain.cpp | 13 +++++++------ indra/newview/lldrawpoolterrain.h | 3 ++- indra/newview/llsurfacepatch.cpp | 13 +++---------- indra/newview/llviewercontrol.cpp | 11 +++++++++++ 7 files changed, 37 insertions(+), 49 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 94cc5a14a4..2dac0b5d70 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10703,7 +10703,7 @@ RenderTerrainScale Comment - Terrain detail texture scale + Terrain detail texture scale (meters) Persist 1 Type @@ -10722,6 +10722,17 @@ Value 0 + RenderTerrainPBRScale + + Comment + PBR terrain detail texture scale (meters) + Persist + 1 + Type + F32 + Value + 4.0 + RenderTrackerBeacon Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 5f94855963..e6261ca85e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -70,7 +70,6 @@ vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); -in vec4 debug_pos; // TODO: Remove // *TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { @@ -150,7 +149,6 @@ vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFina void main() { vec2 terrain_texcoord = vary_texcoord0.xy; - terrain_texcoord -= vec2(21.0);// TODO: Remove float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a; float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; @@ -162,25 +160,6 @@ void main() discard; } - // TODO: Remove all of this - float debug_pos_x = debug_pos.x; - //float debug_pos_x = terrain_texcoord.y; - float debug_metric = debug_pos_x; - debug_metric = debug_metric - floor(debug_metric); - debug_metric *= debug_metric; - float debug_metric2 = debug_pos_x / 4.0; - debug_metric2 = debug_metric2 - floor(debug_metric2); - debug_metric2 *= debug_metric2; - debug_metric2 *= debug_metric2; - debug_metric2 *= 16.0; - float debug_metric3 = debug_pos_x / 16.0; - debug_metric3 = debug_metric3 - floor(debug_metric3); - debug_metric3 *= debug_metric3; - debug_metric3 *= debug_metric3; - debug_metric3 *= debug_metric3; - debug_metric3 *= 16.0; - //col.xyz = vec3(debug_metric3, debug_metric2, debug_metric);// TODO: Remove - vec3 normal_texture = sample_and_mix_vector3_no_scale(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); vec3[4] orm_factors; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index fd80d1bb2c..1653cc1a90 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -52,18 +52,15 @@ vec4 texgen_object_pbr(vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) tcoord.z = tcoord.z; tcoord.w = tcoord.w; - tcoord = mat * tcoord; + tcoord = mat * tcoord; return tcoord; } -out vec4 debug_pos; // TODO: Remove - void main() { //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - debug_pos = vec4(texcoord0, 0.0, 1.0); vec3 n = normal_matrix * normal; vec3 t = normal_matrix * tangent.xyz; @@ -71,15 +68,10 @@ void main() vary_tangent = normalize(t); vary_sign = tangent.w; vary_normal = normalize(n); - + // Transform and pass tex coords // *NOTE: KHR texture transform is ignored for now vary_texcoord0.xy = texgen_object_pbr(vec4(texcoord0, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; - // Adjust the texture repeats for a more sensible default. - // *TODO: Remove this extra factor when KHR texture transform is added - float texture_density_factor = 3.0; - //texture_density_factor /= 256.0; // TODO: Remove - vary_texcoord0.xy *= texture_density_factor; vec4 tc = vec4(texcoord1,0,1); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b4671963e1..85b4bb3dca 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -59,6 +59,7 @@ const S32 PBR_DETAIL_EMISSIVE = 0; S32 LLDrawPoolTerrain::sDetailMode = 1; S32 LLDrawPoolTerrain::sPBRDetailMode = 0; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; +F32 LLDrawPoolTerrain::sPBRDetailScale = DETAIL_SCALE; static LLGLSLShader* sShader = NULL; static LLTrace::BlockTimerStatHandle FTM_SHADOW_TERRAIN("Terrain Shadow"); @@ -69,6 +70,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : { // Hack! sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); + sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale"); // TODO: This is unused. Remove? sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); @@ -385,16 +387,15 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) materials = &gLocalTerrainMaterials.mDetailMaterials; } - // *TODO: I'm seeing terrain still jump when switching regions. Might have something to do with the extra repeat factor in the shader. Or is it a numerical precision issue?... - // *TODO: If we want to change the tiling, we should change this offset modulo to prevent seams + // *TODO: Figure out why this offset is *sometimes* producing seams at the region edge, and repeat jumps when crossing regions, when RenderTerrainPBRScale is not a factor of the region scale. LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; LLVector4 tp0, tp1; - tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); - tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); + tp0.setVec(sPBRDetailScale, 0.0f, 0.0f, offset_x); + tp1.setVec(0.0f, sPBRDetailScale, 0.0f, offset_y); constexpr U32 terrain_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; S32 detail_basecolor[terrain_material_count]; diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 060354458d..99d192da86 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -68,7 +68,8 @@ public: static S32 sDetailMode; static S32 sPBRDetailMode; - static F32 sDetailScale; // meters per texture + static F32 sDetailScale; // textures per meter + static F32 sPBRDetailScale; // textures per meter protected: void boostTerrainDetailTextures(); diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 4f9911a11c..5bc220fcbd 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -209,15 +209,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } llassert_always(vertex && normal && tex0 && tex1); - // TODO: I think this operation is being applied too early because it also affects the geometry - we only want to affect the UVs - // TODO: Figure out what correct scaling is needed to prevent seams at region borders - getPatchesPerEdge seems to not be the solution, nor is getGridsPerEdge on its own U32 surface_stride = mSurfacep->getGridsPerEdge(); - U32 texture_stride = mSurfacep->getGridsPerEdge() - 1; - if (!pbr) - { - // TODO: Re-enable legacy repeats - //texture_stride = mSurfacep->getGridsPerEdge(); - } U32 point_offset = x + y*surface_stride; *normal = getNormal(x, y); @@ -229,8 +221,9 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); - // TODO: Revert for non-PBR only here, and/or add note that non-PBR doesn't actually use it. - LLVector3 tex_pos = rel_pos * (1.f/(texture_stride * mSurfacep->getMetersPerGrid())); + // *NOTE: Only PBR terrain uses the UVs right now. Texture terrain just ignores it. + // *NOTE: In the future, UVs and horizontal position will no longer have a 1:1 relationship for PBR terrain + LLVector3 tex_pos = rel_pos; tex0->mV[0] = tex_pos.mV[0]; tex0->mV[1] = tex_pos.mV[1]; tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index baf5480c6a..8ee675820c 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -134,6 +134,16 @@ static bool handleTerrainScaleChanged(const LLSD& newvalue) return true; } +static bool handlePBRTerrainScaleChanged(const LLSD& newvalue) +{ + F64 scale = newvalue.asReal(); + if (scale != 0.0) + { + LLDrawPoolTerrain::sPBRDetailScale = F32(1.0 / scale); + } + return true; +} + static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) { std::string new_string = newvalue.asString(); @@ -712,6 +722,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRScale", handlePBRTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); -- cgit v1.2.3 From d6aced7abf0c54ec94033534124025c87fb9aeb2 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:38:54 -0700 Subject: DRTVWR-592: Remove WIP separate code path for terrain geometry rebuilds for PBR as that is not needed at the moment --- indra/newview/lldrawpoolterrain.cpp | 4 --- indra/newview/lldrawpoolterrain.h | 1 - indra/newview/llsurfacepatch.cpp | 2 +- indra/newview/llsurfacepatch.h | 2 +- indra/newview/llviewercontrol.cpp | 7 ----- indra/newview/llvlcomposition.cpp | 11 ++------ indra/newview/llvlcomposition.h | 2 -- indra/newview/llvosurfacepatch.cpp | 56 ++++++++++++++----------------------- indra/newview/llvosurfacepatch.h | 12 +++----- 9 files changed, 30 insertions(+), 67 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 85b4bb3dca..fb27729b57 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -56,7 +56,6 @@ int DebugDetailMap = 0; const S32 PBR_DETAIL_EMISSIVE = 0; -S32 LLDrawPoolTerrain::sDetailMode = 1; S32 LLDrawPoolTerrain::sPBRDetailMode = 0; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; F32 LLDrawPoolTerrain::sPBRDetailScale = DETAIL_SCALE; @@ -71,8 +70,6 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : // Hack! sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale"); - // TODO: This is unused. Remove? - sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD); @@ -112,7 +109,6 @@ U32 LLDrawPoolTerrain::getVertexDataMask() void LLDrawPoolTerrain::prerender() { - sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); } diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 99d192da86..13f031c8e7 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -66,7 +66,6 @@ public: LLPointer m2DAlphaRampImagep; LLPointer mAlphaNoiseImagep; - static S32 sDetailMode; static S32 sPBRDetailMode; static F32 sDetailScale; // textures per meter static F32 sPBRDetailScale; // textures per meter diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5bc220fcbd..b4daf71ce2 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -201,7 +201,7 @@ LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal, - LLVector2 *tex0, LLVector2 *tex1, bool pbr) + LLVector2 *tex0, LLVector2 *tex1) { if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp) { diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index 0e6c045145..8c8f501dce 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -106,7 +106,7 @@ public: const LLVector3 &getNormal(const U32 x, const U32 y) const; void eval(const U32 x, const U32 y, const U32 stride, - LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1, bool pbr); + LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 8ee675820c..ea821004a3 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -118,12 +118,6 @@ static bool handleRenderFarClipChanged(const LLSD& newvalue) return false; } -static bool handleTerrainDetailChanged(const LLSD& newvalue) -{ - LLDrawPoolTerrain::sDetailMode = newvalue.asInteger(); - return true; -} - static bool handleTerrainScaleChanged(const LLSD& newvalue) { F64 scale = newvalue.asReal(); @@ -720,7 +714,6 @@ void settings_setup_listeners() { setting_setup_signal_listener(gSavedSettings, "FirstPersonAvatarVisible", handleRenderAvatarMouselookChanged); setting_setup_signal_listener(gSavedSettings, "RenderFarClip", handleRenderFarClipChanged); - setting_setup_signal_listener(gSavedSettings, "RenderTerrainDetail", handleTerrainDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRScale", handlePBRTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 130d74b286..fa19bcae87 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -120,16 +120,11 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) } LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType() -{ - return mMaterialType; -} - -void LLTerrainMaterials::updateMaterialType() { LL_PROFILE_ZONE_SCOPED; const BOOL use_textures = texturesReady() || !materialsReady(); - mMaterialType = use_textures ? Type::TEXTURE : Type::PBR; + return use_textures ? Type::TEXTURE : Type::PBR; } BOOL LLTerrainMaterials::texturesReady(BOOL boost) @@ -386,7 +381,7 @@ BOOL LLVLComposition::generateComposition() return LLTerrainMaterials::generateMaterials(); } -// TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. +// *TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, const F32 width, const F32 height) { @@ -423,7 +418,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, { tex = mDetailMaterials[i]->mBaseColorTexture; } - // TODO: Why are terrain textures (not terrain materials) not loading? (that is why there is a getComponents() check here) + // *TODO: Why are terrain textures (not terrain materials) not loading? (that is why there is a getComponents() check here) if (!tex || tex->getComponents() == 0) { tex = LLViewerFetchedTexture::sWhiteImagep; } S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index a62302292f..882c3d89b2 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -61,7 +61,6 @@ public: LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); - void updateMaterialType(); BOOL texturesReady(BOOL boost = FALSE); BOOL materialsReady(BOOL boost = FALSE); @@ -71,7 +70,6 @@ protected: LLPointer mDetailTextures[ASSET_COUNT]; LLPointer mDetailMaterials[ASSET_COUNT]; bool mMaterialTexturesSet[ASSET_COUNT]; - Type mMaterialType = Type::TEXTURE; }; // Local materials to override all regions diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index a672777914..6318361d8d 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -246,8 +246,7 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp, - bool pbr) + LLStrider &indicesp) { LLFace* facep = mDrawable->getFace(0); if (!facep) @@ -263,24 +262,21 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); updateNorthGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); updateEastGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, - index_offset, - pbr); + index_offset); } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -289,8 +285,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr) + U32 &index_offset) { S32 i, j, x, y; @@ -326,7 +321,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, { x = i * render_stride; y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -394,8 +389,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr) + U32 &index_offset) { S32 vertex_count = 0; S32 i, x, y; @@ -427,7 +421,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -440,7 +434,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -477,7 +471,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -491,7 +485,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -535,7 +529,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -549,7 +543,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -592,8 +586,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr) + U32 &index_offset) { S32 i, x, y; @@ -619,7 +612,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -631,7 +624,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -667,7 +660,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -679,7 +672,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -721,7 +714,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -733,7 +726,7 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get(), pbr); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; texCoords0p++; @@ -1044,13 +1037,6 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; - const LLFace* region_facep = *mFaceList.begin(); - const LLViewerObject* region_patchp = region_facep->getViewerObject(); - LLVLComposition* composition = region_patchp->getRegion()->getComposition(); - // TODO: This is not good; it will result in wrong texture repeats in cases where the assets have not loaded. Need to rebuild terrain on asset load event if it changes the composition type. Probably best to have a flag to bookkeep that, to know if the composition type has actually changed. Make sure the draw pool is boosting the textures so they load in a timely fashion. - composition->updateMaterialType(); - const bool pbr = composition->getMaterialType() == LLTerrainMaterials::Type::PBR; - LLVertexBuffer* buffer = group->mVertexBuffer; //get vertex buffer striders @@ -1087,7 +1073,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); - patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices, pbr); + patchp->getTerrainGeometry(vertices, normals, texcoords, texcoords2, indices); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 06bb373578..a3dcb945d1 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -67,8 +67,7 @@ public: LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - LLStrider &indicesp, - bool pbr); + LLStrider &indicesp); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -122,24 +121,21 @@ protected: LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, - U32 &index_offset, - bool pbr); + U32 &index_offset); }; #endif // LL_VOSURFACEPATCH_H -- cgit v1.2.3 From 7f7431891661668b898e03345c8023b4bbd0d9d9 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:38:59 -0700 Subject: DRTVWR-592: Add tracy block to gen_terrain_tangents (not profiled) --- indra/newview/llvosurfacepatch.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 6318361d8d..feb1e26d57 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -1001,6 +1001,8 @@ void gen_terrain_tangents(U16 strider_vertex_count, LLStrider &texCoords0p, LLStrider &indicesp) { + LL_PROFILE_ZONE_SCOPED + LLVector4a *vertices = new LLVector4a[strider_vertex_count]; LLVector4a *normals = new LLVector4a[strider_vertex_count]; LLVector4a *tangents = new LLVector4a[strider_vertex_count]; -- cgit v1.2.3 From ab3b4edac7809008cfed6d1b77e5a4debb22c88e Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:03 -0700 Subject: DRTVWR-592: Fix broken minimap loading, improve minimap view of PBR materials (still not accurate, but better...) --- indra/llimage/llimage.cpp | 53 ++++++++++++++ indra/llimage/llimage.h | 6 ++ indra/newview/llfetchedgltfmaterial.cpp | 5 +- indra/newview/llfetchedgltfmaterial.h | 9 ++- indra/newview/llgltfmateriallist.cpp | 4 +- indra/newview/llsurfacepatch.cpp | 2 +- indra/newview/llvlcomposition.cpp | 125 ++++++++++++++++++++++++++++---- indra/newview/llvlcomposition.h | 2 +- 8 files changed, 179 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index a96b6601bd..acfc254b65 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -31,6 +31,7 @@ #include "llmath.h" #include "v4coloru.h" +#include "v3color.h" #include "llimagebmp.h" #include "llimagetga.h" @@ -1026,6 +1027,34 @@ bool LLImageRaw::optimizeAwayAlpha() return false; } +bool LLImageRaw::makeAlpha() +{ + if (getComponents() == 3) + { + U8* data = getData(); + U32 pixels = getWidth() * getHeight(); + + // alpha channel doesn't exist, make a new copy of data with alpha channel + U8* new_data = (U8*) ll_aligned_malloc_16(getWidth() * getHeight() * 4); + + for (U32 i = 0; i < pixels; ++i) + { + U32 di = i * 4; + U32 si = i * 3; + for (U32 j = 0; j < 3; ++j) + { + new_data[di+j] = data[si+j]; + } + } + + setDataAndSize(new_data, getWidth(), getHeight(), 3); + + return true; + } + + return false; +} + void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image) { // Find new sizes @@ -1268,6 +1297,30 @@ void LLImageRaw::fill( const LLColor4U& color ) } } +void LLImageRaw::tint( const LLColor3& color ) +{ + llassert( (3 == getComponents()) || (4 == getComponents()) ); + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } + + S32 pixels = getWidth() * getHeight(); + const S32 components = getComponents(); + U8* data = getData(); + for( S32 i = 0; i < pixels; i++ ) + { + const float c0 = data[0] * color.mV[0]; + const float c1 = data[1] * color.mV[1]; + const float c2 = data[2] * color.mV[2]; + data[0] = llclamp((U8)c0, 0, 255); + data[1] = llclamp((U8)c1, 0, 255); + data[2] = llclamp((U8)c2, 0, 255); + data += components; + } +} + LLPointer LLImageRaw::duplicate() { if(getNumRefs() < 2) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 8f9e1b3c54..77b5f0b7bc 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496; class LLImageFormatted; class LLImageRaw; class LLColor4U; +class LLColor3; typedef enum e_image_codec { @@ -212,6 +213,8 @@ public: // if the alpha channel is all 100% opaque, delete it // returns true if alpha channel was deleted bool optimizeAwayAlpha(); + // Create an alpha channel if this image doesn't have one + bool makeAlpha(); static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE); @@ -225,6 +228,9 @@ public: // Fill the buffer with a constant color void fill( const LLColor4U& color ); + // Multiply this raw image by the given color + void tint( const LLColor3& color ); + // Copy operations //duplicate this raw image if refCount > 1. diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1fb3577dd7..c870d4778c 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -35,8 +35,6 @@ LLFetchedGLTFMaterial::LLFetchedGLTFMaterial() : LLGLTFMaterial() , mExpectedFlusTime(0.f) - , mActive(true) - , mFetching(false) { } @@ -163,10 +161,11 @@ void LLFetchedGLTFMaterial::onMaterialComplete(std::function material_co materialCompleteCallbacks.push_back(material_complete); } -void LLFetchedGLTFMaterial::materialComplete() +void LLFetchedGLTFMaterial::materialComplete(bool success) { llassert(mFetching); mFetching = false; + mFetchSuccess = success; for (std::function material_complete : materialCompleteCallbacks) { diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index ce4d33a213..c5f6f6ca94 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -49,7 +49,7 @@ public: void bind(LLViewerTexture* media_tex = nullptr); bool isFetching() const { return mFetching; } - bool isLoaded() const { return !mFetching; } + bool isLoaded() const { return !mFetching && mFetchSuccess; } // Textures used for fetching/rendering LLPointer mBaseColorTexture; @@ -61,11 +61,12 @@ protected: // Lifetime management void materialBegin(); - void materialComplete(); + void materialComplete(bool success); F64 mExpectedFlusTime; // since epoch in seconds - bool mActive; - bool mFetching; + bool mActive = true; + bool mFetching = false; + bool mFetchSuccess = false; std::vector> materialCompleteCallbacks; }; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 99a052f719..7994515b61 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -549,7 +549,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp if (status != LL_ERR_NOERR) { LL_WARNS("GLTF") << "Error getting material asset data: " << LLAssetStorage::getErrorString(status) << " (" << status << ")" << LL_ENDL; - asset_data->mMaterial->materialComplete(); + asset_data->mMaterial->materialComplete(false); delete asset_data; } else @@ -634,7 +634,7 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp LL_DEBUGS("GLTF") << "Failed to get material " << id << LL_ENDL; } - asset_data->mMaterial->materialComplete(); + asset_data->mMaterial->materialComplete(true); delete asset_data; }); diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index b4daf71ce2..a6370e9ec2 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -741,7 +741,7 @@ void LLSurfacePatch::updateGL() updateCompositionStats(); F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; - if (comp->generateTexture((F32)origin_region[VX], (F32)origin_region[VY], + if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY], tex_patch_size, tex_patch_size)) { mSTexUpdate = FALSE; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index fa19bcae87..f645023217 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -129,26 +129,28 @@ LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType() BOOL LLTerrainMaterials::texturesReady(BOOL boost) { + BOOL ready = TRUE; for (S32 i = 0; i < ASSET_COUNT; i++) { if (!textureReady(mDetailTextures[i], boost)) { - return FALSE; + ready = FALSE; } } - return TRUE; + return ready; } BOOL LLTerrainMaterials::materialsReady(BOOL boost) { + BOOL ready = TRUE; for (S32 i = 0; i < ASSET_COUNT; i++) { if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost)) { - return FALSE; + ready = FALSE; } } - return TRUE; + return ready; } // Boost the texture loading priority @@ -188,6 +190,10 @@ BOOL LLTerrainMaterials::textureReady(LLPointer& tex, BO } return FALSE; } + if (tex->getComponents() == 0) + { + return FALSE; + } return TRUE; } @@ -381,8 +387,7 @@ BOOL LLVLComposition::generateComposition() return LLTerrainMaterials::generateMaterials(); } -// *TODO: Re-evaluate usefulness of this function in the PBR case. There is currently a hack here to treat the material base color like a legacy terrain texture, but I'm not sure if that's useful. -BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, +BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height) { LL_PROFILE_ZONE_SCOPED @@ -390,8 +395,6 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, llassert(x >= 0.f); llassert(y >= 0.f); - LLTimer gen_timer; - /////////////////////////// // // Generate raw data arrays for surface textures @@ -403,6 +406,17 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, S32 st_data_size[ASSET_COUNT]; // for debugging const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; + // *TODO: Remove this as it is reduandant computation (first and foremost + // because getMaterialType() does something similar, but also... shouldn't + // the textures/materials already be loaded by now?) + if (use_textures) + { + if (!texturesReady()) { return FALSE; } + } + else + { + if (!materialsReady()) { return FALSE; } + } for (S32 i = 0; i < ASSET_COUNT; i++) { @@ -410,16 +424,37 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, { // Read back a raw image for this discard level, if it exists LLViewerFetchedTexture* tex; + LLViewerFetchedTexture* tex_emissive; // Can be null + bool has_base_color_factor; + bool has_emissive_factor; + LLColor3 base_color_factor; + LLColor3 emissive_factor; if (use_textures) { tex = mDetailTextures[i]; + tex_emissive = nullptr; + has_base_color_factor = false; + has_emissive_factor = false; + llassert(tex); } else { tex = mDetailMaterials[i]->mBaseColorTexture; + tex_emissive = mDetailMaterials[i]->mEmissiveTexture; + base_color_factor = LLColor3(mDetailMaterials[i]->mBaseColor); + // *HACK: Treat alpha as black + base_color_factor *= (mDetailMaterials[i]->mBaseColor.mV[VW]); + emissive_factor = mDetailMaterials[i]->mEmissiveColor; + has_base_color_factor = (base_color_factor.mV[VX] != 1.f || + base_color_factor.mV[VY] != 1.f || + base_color_factor.mV[VZ] != 1.f); + has_emissive_factor = (emissive_factor.mV[VX] != 1.f || + emissive_factor.mV[VY] != 1.f || + emissive_factor.mV[VZ] != 1.f); } - // *TODO: Why are terrain textures (not terrain materials) not loading? (that is why there is a getComponents() check here) - if (!tex || tex->getComponents() == 0) { tex = LLViewerFetchedTexture::sWhiteImagep; } + + if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } + // tex_emissive can be null, and then will be ignored S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); S32 ddiscard = 0; @@ -430,8 +465,9 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, } BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL) ; - if(tex->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. + if(tex->getRawImageLevel() != ddiscard) { + // Raw image is not ready, will enter here again later. if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage()) { tex->setBoostLevel(LLGLTexture::BOOST_MAP); @@ -442,21 +478,78 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, { tex->destroyRawImage() ; } - LL_DEBUGS("Terrain") << "cached raw data for terrain detail texture is not ready yet: " << tex->getID() << " Discard: " << ddiscard << LL_ENDL; return FALSE; } + if (tex_emissive) + { + if(tex_emissive->getRawImageLevel() != ddiscard) + { + // Raw image is not ready, will enter here again later. + if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage()) + { + tex_emissive->setBoostLevel(LLGLTexture::BOOST_MAP); + tex_emissive->forceToRefetchTexture(ddiscard); + } + + if(delete_raw) + { + tex_emissive->destroyRawImage() ; + } + return FALSE; + } + } mRawImages[i] = tex->getRawImage() ; if(delete_raw) { tex->destroyRawImage() ; } - if (tex->getWidth(ddiscard) != BASE_SIZE || + + // *TODO: This isn't quite right for PBR: + // 1) It does not convert the color images from SRGB to linear + // before mixing (which will always require copying the image). + // 2) It mixes emissive and base color before mixing terrain + // materials, but it should be the other way around + // 3) The composite function used to put emissive into base color + // is not an alpha blend. + // Long-term, we should consider a method that is more + // maintainable. Shaders, perhaps? Bake shaders to textures? + LLPointer raw_emissive; + if (tex_emissive) + { + raw_emissive = tex_emissive->getRawImage(); + if (has_emissive_factor || + tex_emissive->getWidth(ddiscard) != BASE_SIZE || + tex_emissive->getHeight(ddiscard) != BASE_SIZE || + tex_emissive->getComponents() != 4) + { + LLPointer newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4); + // Copy RGB, leave alpha alone (set to opaque by default) + newraw_emissive->copy(mRawImages[i]); + if (has_emissive_factor) + { + newraw_emissive->tint(emissive_factor); + } + raw_emissive = newraw_emissive; // deletes old + } + } + if (has_base_color_factor || + raw_emissive || + tex->getWidth(ddiscard) != BASE_SIZE || tex->getHeight(ddiscard) != BASE_SIZE || tex->getComponents() != 3) { LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); newraw->composite(mRawImages[i]); + if (has_base_color_factor) + { + newraw->tint(base_color_factor); + } + // Apply emissive texture + if (raw_emissive) + { + newraw->composite(raw_emissive); + } mRawImages[i] = newraw; // deletes old } } @@ -478,12 +571,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, if (x_end > mWidth) { - LL_WARNS("Terrain") << "x end > width" << LL_ENDL; + llassert(false); x_end = mWidth; } if (y_end > mWidth) { - LL_WARNS("Terrain") << "y end > width" << LL_ENDL; + llassert(false); y_end = mWidth; } @@ -513,7 +606,7 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, if (tex_comps != st_comps) { - LL_WARNS("Terrain") << "Base texture comps != input texture comps" << LL_ENDL; + llassert(false); return FALSE; } diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 882c3d89b2..d59c0f95bb 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -87,7 +87,7 @@ public: BOOL generateHeights(const F32 x, const F32 y, const F32 width, const F32 height); BOOL generateComposition(); // Generate texture from composition values. - BOOL generateTexture(const F32 x, const F32 y, const F32 width, const F32 height); + BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height); // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. // So we need to compress heights into this range. -- cgit v1.2.3 From 754fe9d4b72c3a22fb18e32bd48daaa2ae7b02f7 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:09 -0700 Subject: DRTVWR-592: (WIP) Triplanar mapping --- indra/llrender/llglslshader.h | 1 + indra/llrender/llshadermgr.cpp | 8 ++ .../shaders/class1/deferred/pbrterrainF.glsl | 98 +++----------- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 148 +++++++++++++++++++++ .../shaders/class1/deferred/pbrterrainV.glsl | 9 +- indra/newview/llviewershadermgr.cpp | 2 + 6 files changed, 188 insertions(+), 78 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl (limited to 'indra') diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index b8071248e2..0de97da4db 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -57,6 +57,7 @@ public: bool hasAlphaMask = false; bool hasReflectionProbes = false; bool attachNothing = false; + bool isPBRTerrain = false; // include: shaders\class1\deferred\pbrterrainUtilF.glsl }; // ============= Structure for caching shader uniforms =============== diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b2c8255d2a..91412add44 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -291,6 +291,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } + if (features->isPBRTerrain) + { + if (!shader->attachFragmentObject("deferred/pbrterrainUtilF.glsl")) + { + return FALSE; + } + } + // NOTE order of shader object attaching is VERY IMPORTANT!!! if (features->hasWaterFog) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index e6261ca85e..5bf20a3020 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -25,6 +25,15 @@ #define TERRAIN_PBR_DETAIL_EMISSIVE 0 +#define TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT 3 // TODO: Move definition to config + +// TODO: Should be able to define this in another file and have it included in this one... +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 +#define TerrainCoord vec4[2] +#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 +#define TerrainCoord vec2 +#endif + out vec4 frag_data[4]; uniform sampler2D alpha_ramp; @@ -60,6 +69,7 @@ uniform vec3[4] emissiveColors; #endif uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() +in vec4[2] vary_coords; in vec3 vary_normal; in vec3 vary_tangent; flat in float vary_sign; @@ -67,88 +77,22 @@ in vec4 vary_texcoord0; in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); -vec3 linear_to_srgb(vec3 c); -vec3 srgb_to_linear(vec3 c); - -// *TODO: This mixing function feels like it can be optimized. The terrain code's use of texcoord1 is dubious. It feels like the same thing can be accomplished with less memory bandwidth by calculating the offsets on-the-fly -float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) -{ - return mix( mix(samples.w, samples.z, alpha2), mix(samples.y, samples.x, alpha1), alphaFinal ); -} - -vec3 terrain_mix(vec3[4] samples, float alpha1, float alpha2, float alphaFinal) -{ - return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); -} - -vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) -{ - return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); -} -vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - vec3[4] samples; - samples[0] = texture(tex0, texcoord).xyz; - samples[1] = texture(tex1, texcoord).xyz; - samples[2] = texture(tex2, texcoord).xyz; - samples[3] = texture(tex3, texcoord).xyz; - samples[0] = srgb_to_linear(samples[0]); - samples[1] = srgb_to_linear(samples[1]); - samples[2] = srgb_to_linear(samples[2]); - samples[3] = srgb_to_linear(samples[3]); - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); -} - -vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - vec4[4] samples; - samples[0] = texture(tex0, texcoord); - samples[1] = texture(tex1, texcoord); - samples[2] = texture(tex2, texcoord); - samples[3] = texture(tex3, texcoord); - samples[0].xyz = srgb_to_linear(samples[0].xyz); - samples[1].xyz = srgb_to_linear(samples[1].xyz); - samples[2].xyz = srgb_to_linear(samples[2].xyz); - samples[3].xyz = srgb_to_linear(samples[3].xyz); - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); -} +float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal); +vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +void main() { - vec3[4] samples; - samples[0] = texture(tex0, texcoord).xyz; - samples[1] = texture(tex1, texcoord).xyz; - samples[2] = texture(tex2, texcoord).xyz; - samples[3] = texture(tex3, texcoord).xyz; - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); -} -vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, vec2 texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - vec3[4] samples; - samples[0] = texture(tex0, texcoord).xyz; - samples[1] = texture(tex1, texcoord).xyz; - samples[2] = texture(tex2, texcoord).xyz; - samples[3] = texture(tex3, texcoord).xyz; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); -} +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 + TerrainCoord terrain_texcoord = vary_coords; +#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 + TerrainCoord terrain_texcoord = vary_texcoord0.xy; +#endif -void main() -{ - vec2 terrain_texcoord = vary_texcoord0.xy; float alpha1 = texture(alpha_ramp, vary_texcoord0.zw).a; float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl new file mode 100644 index 0000000000..4f337b5ce1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -0,0 +1,148 @@ +/** + * @file class1\deferred\pbrterrainUtilF.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +/** + * Triplanar mapping implementation adapted from Inigo Quilez' example shader, + * MIT license. + * https://www.shadertoy.com/view/MtsGWH + * Copyright © 2015 Inigo Quilez + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: The above copyright + * notice and this permission notice shall be included in all copies or + * substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +in vec3 vary_vertex_normal; + +vec3 srgb_to_linear(vec3 c); + +float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples.w, samples.z, alpha2), mix(samples.y, samples.x, alpha1), alphaFinal ); +} + +vec3 terrain_mix(vec3[4] samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); +} + +vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) +{ + return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); +} + +#define TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT 3 // TODO: Move definition to config + +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 +// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, zx, unused) +#define TerrainCoord vec4[2] +// Triplanar mapping +vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) +{ + vec4 x = texture(tex, terrain_coord[0].zw); + vec4 y = texture(tex, terrain_coord[1].xy); + vec4 z = texture(tex, terrain_coord[0].xy); + float sharpness = 8.0; + vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); + return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); +} +#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 +#define TerrainCoord vec2 +vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) +{ + return texture(tex, terrain_coord); +} +#endif + +vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec3[4] samples; + samples[0] = terrain_texture(tex0, texcoord).xyz; + samples[1] = terrain_texture(tex1, texcoord).xyz; + samples[2] = terrain_texture(tex2, texcoord).xyz; + samples[3] = terrain_texture(tex3, texcoord).xyz; + samples[0] = srgb_to_linear(samples[0]); + samples[1] = srgb_to_linear(samples[1]); + samples[2] = srgb_to_linear(samples[2]); + samples[3] = srgb_to_linear(samples[3]); + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec4[4] samples; + samples[0] = terrain_texture(tex0, texcoord); + samples[1] = terrain_texture(tex1, texcoord); + samples[2] = terrain_texture(tex2, texcoord); + samples[3] = terrain_texture(tex3, texcoord); + samples[0].xyz = srgb_to_linear(samples[0].xyz); + samples[1].xyz = srgb_to_linear(samples[1].xyz); + samples[2].xyz = srgb_to_linear(samples[2].xyz); + samples[3].xyz = srgb_to_linear(samples[3].xyz); + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec3[4] samples; + samples[0] = terrain_texture(tex0, texcoord).xyz; + samples[1] = terrain_texture(tex1, texcoord).xyz; + samples[2] = terrain_texture(tex2, texcoord).xyz; + samples[3] = terrain_texture(tex3, texcoord).xyz; + samples[0] *= factors[0]; + samples[1] *= factors[1]; + samples[2] *= factors[2]; + samples[3] *= factors[3]; + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} + +vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + vec3[4] samples; + samples[0] = terrain_texture(tex0, texcoord).xyz; + samples[1] = terrain_texture(tex1, texcoord).xyz; + samples[2] = terrain_texture(tex2, texcoord).xyz; + samples[3] = terrain_texture(tex3, texcoord).xyz; + return terrain_mix(samples, alpha1, alpha2, alphaFinal); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 1653cc1a90..991783d242 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -34,6 +34,8 @@ in vec4 diffuse_color; in vec2 texcoord0; in vec2 texcoord1; +out vec4[2] vary_coords; +out vec3 vary_vertex_normal; // Used by pbrterrainUtilF.glsl out vec3 vary_normal; out vec3 vary_tangent; flat out float vary_sign; @@ -63,6 +65,8 @@ void main() gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vec3 n = normal_matrix * normal; + // *TODO: Looks like terrain normals are per-vertex when they should be per-triangle instead, causing incorrect values on triangles touching steep edges of terrain + vary_vertex_normal = normal; vec3 t = normal_matrix * tangent.xyz; vary_tangent = normalize(t); @@ -73,7 +77,10 @@ void main() // *NOTE: KHR texture transform is ignored for now vary_texcoord0.xy = texgen_object_pbr(vec4(texcoord0, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; - vec4 tc = vec4(texcoord1,0,1); + vec4 tc = vec4(texcoord1,0,1); // TODO: This is redundant. Better to just use position and ignore texcoord? (We still need to decide how to handle alpha ramp, though...) + vary_coords[0].xy = texgen_object_pbr(vec4(position.xy, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; + vary_coords[0].zw = texgen_object_pbr(vec4(position.yz, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; + vary_coords[1].xy = texgen_object_pbr(vec4(position.zx, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; vary_texcoord0.zw = tc.xy; vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 2235b6d9a4..320801861c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -720,6 +720,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back(make_pair("deferred/pbrterrainUtilF.glsl", 1)); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); @@ -1506,6 +1507,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true; gDeferredPBRTerrainProgram.mFeatures.hasGamma = true; gDeferredPBRTerrainProgram.mFeatures.hasTransport = true; + gDeferredPBRTerrainProgram.mFeatures.isPBRTerrain = true; gDeferredPBRTerrainProgram.mShaderFiles.clear(); gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainV.glsl", GL_VERTEX_SHADER)); -- cgit v1.2.3 From 2dc3f3ade165d7d15d8579a0f04b72f6aa56c7fe Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:16 -0700 Subject: DRTVWR-592: Add triplanar mapping setting, gate to High graphics setting or higher, bump feature table --- indra/newview/app_settings/settings.xml | 11 +++++++++++ .../app_settings/shaders/class1/deferred/pbrterrainF.glsl | 3 --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 2 -- indra/newview/featuretable.txt | 8 ++++++++ indra/newview/featuretable_mac.txt | 8 ++++++++ indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewershadermgr.cpp | 15 ++++++++++++++- 7 files changed, 42 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2dac0b5d70..28ee1b3a70 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10733,6 +10733,17 @@ Value 4.0 + RenderTerrainPBRPlanarSampleCount + + Comment + How many UV planes to sample PBR terrain textures from. 1 is "flat", 3 is triplanar mapping (aka box mapping) + Persist + 1 + Type + S32 + Value + 3 + RenderTrackerBeacon Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 5bf20a3020..b9073a9361 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -25,9 +25,6 @@ #define TERRAIN_PBR_DETAIL_EMISSIVE 0 -#define TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT 3 // TODO: Move definition to config - -// TODO: Should be able to define this in another file and have it included in this one... #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 #define TerrainCoord vec4[2] #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 4f337b5ce1..b0b77398df 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -64,8 +64,6 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); } -#define TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT 3 // TODO: Move definition to config - #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, zx, unused) #define TerrainCoord vec4[2] diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index cb941b424b..4bc83b099f 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -49,6 +49,7 @@ RenderReflectionProbeDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTerrainPBRDetail 1 0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 RenderVBOMappingDisable 1 1 @@ -95,6 +96,7 @@ RenderReflectionsEnabled 1 0 RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0 RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 @@ -124,6 +126,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 @@ -151,6 +154,7 @@ RenderLocalLights 1 1 RenderTransparentWater 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.25 RenderDeferredSSAO 1 0 @@ -180,6 +184,7 @@ RenderLocalLights 1 1 RenderTransparentWater 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.375 RenderDeferredSSAO 1 0 @@ -209,6 +214,7 @@ RenderLocalLights 1 1 RenderTransparentWater 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.5 RenderDeferredSSAO 1 1 @@ -237,6 +243,7 @@ RenderMaxPartCount 1 4096 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.75 @@ -265,6 +272,7 @@ RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVolumeLODFactor 1 2.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index c04c1c9a4f..97dad655a2 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -45,6 +45,7 @@ RenderObjectBump 1 1 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVBOEnable 1 1 @@ -89,6 +90,7 @@ RenderLocalLights 1 0 RenderMaxPartCount 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 RenderVolumeLODFactor 1 1.125 @@ -118,6 +120,7 @@ RenderMaxPartCount 1 2048 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.125 @@ -147,6 +150,7 @@ RenderMaxPartCount 1 4096 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.25 @@ -176,6 +180,7 @@ RenderMaxPartCount 1 4096 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.375 @@ -205,6 +210,7 @@ RenderMaxPartCount 1 4096 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.5 @@ -234,6 +240,7 @@ RenderMaxPartCount 1 4096 RenderLocalLights 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.75 @@ -262,6 +269,7 @@ RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderVolumeLODFactor 1 2.0 diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index ea821004a3..19999545b6 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -717,6 +717,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderTerrainScale", handleTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRScale", handlePBRTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRPlanarSampleCount", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 320801861c..c23ef1c314 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -69,6 +69,14 @@ bool LLViewerShaderMgr::sSkipReload = false; LLVector4 gShinyOrigin; +S32 clamp_terrain_mapping(S32 mapping) +{ + // 1 = "flat", 2 not implemented, 3 = triplanar mapping + mapping = llclamp(mapping, 1, 3); + if (mapping == 2) { mapping = 1; } + return mapping; +} + //utility shaders LLGLSLShader gOcclusionProgram; LLGLSLShader gSkinnedOcclusionProgram; @@ -682,6 +690,9 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["REF_SAMPLE_COUNT"] = "32"; } + const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); + attribs["TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT"] = llformat("%d", mapping); + LLGLSLShader::sGlobalDefines = attribs; // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. @@ -720,7 +731,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); - index_channels.push_back(-1); shaders.push_back(make_pair("deferred/pbrterrainUtilF.glsl", 1)); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); @@ -1497,6 +1508,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX); + const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d", detail); gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; @@ -1514,6 +1526,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBRTerrainProgram.mShaderFiles.push_back(make_pair("deferred/pbrterrainF.glsl", GL_FRAGMENT_SHADER)); gDeferredPBRTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PBR_DETAIL", llformat("%d", detail)); + gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT", llformat("%d", mapping)); success = gDeferredPBRTerrainProgram.createShader(NULL, NULL); llassert(success); } -- cgit v1.2.3 From ed973f4cbc58b5460513be709a0a23f0caa1120c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:22 -0700 Subject: DRTVWR-592: Add test config for triplanar mapping blend strength --- indra/newview/app_settings/settings.xml | 11 +++++++++++ .../app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 2 +- indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewershadermgr.cpp | 8 ++++++-- 4 files changed, 19 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 28ee1b3a70..85dfe688a7 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10744,6 +10744,17 @@ Value 3 + RenderTerrainPBRTriplanarBlendFactor + + Comment + Higher values create sharper transitions, but are more likely to produce artifacts. + Persist + 1 + Type + F32 + Value + 8.0 + RenderTrackerBeacon Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index b0b77398df..ef2d030320 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -73,7 +73,7 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) vec4 x = texture(tex, terrain_coord[0].zw); vec4 y = texture(tex, terrain_coord[1].xy); vec4 z = texture(tex, terrain_coord[0].xy); - float sharpness = 8.0; + float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 19999545b6..b6f01f2843 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -718,6 +718,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRScale", handlePBRTerrainScaleChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRPlanarSampleCount", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderTerrainPBRTriplanarBlendFactor", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "OctreeStaticObjectSizeFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeDistanceFactor", handleRepartition); setting_setup_signal_listener(gSavedSettings, "OctreeMaxNodeCapacity", handleRepartition); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index c23ef1c314..f1f92132ec 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -690,8 +690,12 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["REF_SAMPLE_COUNT"] = "32"; } - const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); - attribs["TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT"] = llformat("%d", mapping); + { // PBR terrain + const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); + attribs["TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT"] = llformat("%d", mapping); + const F32 triplanar_factor = gSavedSettings.getF32("RenderTerrainPBRTriplanarBlendFactor"); + attribs["TERRAIN_TRIPLANAR_BLEND_FACTOR"] = llformat("%.2f", triplanar_factor); + } LLGLSLShader::sGlobalDefines = attribs; -- cgit v1.2.3 From 23ca385f3dd0304a92e8da54236bc60f4f52e359 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:28 -0700 Subject: DRTVWR-592: Give PBR terrain shader more descriptive name for debugging/profiling --- indra/newview/llviewershadermgr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index f1f92132ec..5849f97e0e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1513,7 +1513,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX); const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); - gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d", detail); + gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d %s", + detail, + (mapping == 1 ? "flat" : "triplanar")); gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; -- cgit v1.2.3 From db4bc52829ec041ca0366069d07e942f0d32aacd Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:34 -0700 Subject: DRTVWR-592: (WIP) PBR Terrain: Improve orientation of textures and normal maps for triplanar mapping, minor cleanup --- .../shaders/class1/deferred/pbrterrainF.glsl | 10 ++-- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 68 ++++++++++++++++++---- .../shaders/class1/deferred/pbrterrainV.glsl | 52 +++++++++-------- .../shaders/class1/deferred/textureUtilV.glsl | 2 +- indra/newview/lldrawpoolterrain.cpp | 28 +++++---- 5 files changed, 109 insertions(+), 51 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index b9073a9361..7febbe280e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -35,7 +35,7 @@ out vec4 frag_data[4]; uniform sampler2D alpha_ramp; -// *TODO: Configurable quality level which disables PBR features on machines +// *TODO: More configurable quality level which disables PBR features on machines // with limited texture availability // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures uniform sampler2D detail_0_base_color; @@ -57,7 +57,6 @@ uniform sampler2D detail_2_emissive; uniform sampler2D detail_3_emissive; #endif -// *TODO: More efficient packing? uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl uniform vec4 metallicFactors; uniform vec4 roughnessFactors; @@ -66,7 +65,9 @@ uniform vec3[4] emissiveColors; #endif uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 in vec4[2] vary_coords; +#endif in vec3 vary_normal; in vec3 vary_tangent; flat in float vary_sign; @@ -79,7 +80,7 @@ float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal); vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); void main() { @@ -101,7 +102,6 @@ void main() discard; } - vec3 normal_texture = sample_and_mix_vector3_no_scale(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); vec3[4] orm_factors; orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x); @@ -124,7 +124,7 @@ void main() float base_color_factor_alpha = terrain_mix(vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z), alpha1, alpha2, alphaFinal); // from mikktspace.com - vec3 vNt = normal_texture.xyz*2.0-1.0; + vec3 vNt = sample_and_mix_normal(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index ef2d030320..a9155cc629 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -65,14 +65,56 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) } #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 -// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, zx, unused) -#define TerrainCoord vec4[2] // Triplanar mapping + +// Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) +#define TerrainCoord vec4[2] + +vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) +{ + // If the vertex normal is negative, flip the texture back + // right-side up. + vec2 uv = uv_unflipped * vec2(sign, 1); + return texture(tex, uv); +} + +vec3 _t_texture_n(sampler2D tex, vec2 uv_unflipped, float sign) +{ + // Unpack normal from pixel to vector + vec3 n = _t_texture(tex, uv_unflipped, sign).xyz*2.0-1.0; + // If the sign is negative, rotate normal by 180 degrees + n.xy = (min(0, sign) * n.xy) + (min(0, -sign) * -n.xy); + return n; +} + vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) { - vec4 x = texture(tex, terrain_coord[0].zw); - vec4 y = texture(tex, terrain_coord[1].xy); - vec4 z = texture(tex, terrain_coord[0].xy); + // Multiplying the UVs by the sign of the normal flips the texture upright. + vec4 x = _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); + vec4 y = _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); + vec4 z = _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); + float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; + vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); + return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); +} + +// Specialized triplanar normal texture sampling implementation, taking into +// account how the rotation of the texture affects the lighting and trying to +// negate that. +// *TODO: Decide if we want this. It may be better to just calculate the +// tangents on-the-fly here rather than messing with the normals, due to the +// subtleties of the effects of triplanar mapping on UVs. These sampled normals +// are only valid on the faces of a cube, and the pregenerated tangents are +// only valid for uv = xy. +// *NOTE: Bottom face has not been tested +vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) +{ + vec3 x = _t_texture_n(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); + x.xy = vec2(-x.y, x.x); + vec3 y = _t_texture_n(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); + y.xy = -y.xy; + vec3 z = _t_texture_n(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); + float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); @@ -83,6 +125,11 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) { return texture(tex, terrain_coord); } + +vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) +{ + return texture(tex, terrain_coord).xyz; +} #endif vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) @@ -135,12 +182,13 @@ vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, Terrai return terrain_mix(samples, alpha1, alpha2, alphaFinal); } -vec3 sample_and_mix_vector3_no_scale(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +// Returns the unpacked normal texture in range [-1, 1] +vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec3[4] samples; - samples[0] = terrain_texture(tex0, texcoord).xyz; - samples[1] = terrain_texture(tex1, texcoord).xyz; - samples[2] = terrain_texture(tex2, texcoord).xyz; - samples[3] = terrain_texture(tex3, texcoord).xyz; + samples[0] = terrain_texture_normal(tex0, texcoord).xyz; + samples[1] = terrain_texture_normal(tex1, texcoord).xyz; + samples[2] = terrain_texture_normal(tex2, texcoord).xyz; + samples[3] = terrain_texture_normal(tex3, texcoord).xyz; return terrain_mix(samples, alpha1, alpha2, alphaFinal); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 991783d242..2df5faf037 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -34,7 +34,9 @@ in vec4 diffuse_color; in vec2 texcoord0; in vec2 texcoord1; +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 out vec4[2] vary_coords; +#endif out vec3 vary_vertex_normal; // Used by pbrterrainUtilF.glsl out vec3 vary_normal; out vec3 vary_tangent; @@ -42,22 +44,13 @@ flat out float vary_sign; out vec4 vary_texcoord0; out vec4 vary_texcoord1; -uniform vec4 object_plane_s; -uniform vec4 object_plane_t; +// *HACK: tangent_space_transform should use texture_normal_transform, or maybe +// we shouldn't use tangent_space_transform at all. See the call to +// tangent_space_transform below. +uniform vec4[2] texture_base_color_transform; -vec4 texgen_object_pbr(vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) -{ - vec4 tcoord; - - tcoord.x = dot(tc, tp0); - tcoord.y = dot(tc, tp1); - tcoord.z = tcoord.z; - tcoord.w = tcoord.w; - - tcoord = mat * tcoord; - - return tcoord; -} +vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); +vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); void main() { @@ -65,23 +58,36 @@ void main() gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vec3 n = normal_matrix * normal; - // *TODO: Looks like terrain normals are per-vertex when they should be per-triangle instead, causing incorrect values on triangles touching steep edges of terrain vary_vertex_normal = normal; vec3 t = normal_matrix * tangent.xyz; vary_tangent = normalize(t); + // *TODO: Decide if we want this. It may be better to just calculate the + // tangents on-the-fly in the fragment shader, due to the subtleties of the + // effect of triplanar mapping on UVs. + // *HACK: Should be using texture_normal_transform here. The KHR texture + // transform spec requires handling texture transforms separately for each + // individual texture. + vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform, texture_matrix0)); vary_sign = tangent.w; vary_normal = normalize(n); // Transform and pass tex coords - // *NOTE: KHR texture transform is ignored for now - vary_texcoord0.xy = texgen_object_pbr(vec4(texcoord0, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; - - vec4 tc = vec4(texcoord1,0,1); // TODO: This is redundant. Better to just use position and ignore texcoord? (We still need to decide how to handle alpha ramp, though...) - vary_coords[0].xy = texgen_object_pbr(vec4(position.xy, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; - vary_coords[0].zw = texgen_object_pbr(vec4(position.yz, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; - vary_coords[1].xy = texgen_object_pbr(vec4(position.zx, 0, 1), texture_matrix0, object_plane_s, object_plane_t).xy; + // *HACK: texture_base_color_transform is used for all of these here, but + // the KHR texture transform spec requires handling texture transforms + // separately for each individual texture. +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 + // xy + vary_coords[0].xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0); + // yz + vary_coords[0].zw = texture_transform(position.yz, texture_base_color_transform, texture_matrix0); + // (-x)z + vary_coords[1].xy = texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform, texture_matrix0); +#elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 + vary_texcoord0.xy = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); +#endif + vec4 tc = vec4(texcoord1,0,1); vary_texcoord0.zw = tc.xy; vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0); vary_texcoord1.zw = tc.xy-vec2(1.0, 0.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl index 636dfed4ba..732333311c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl @@ -65,7 +65,7 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl // Apply texture animation first to avoid shearing and other artifacts texcoord = (sl_animation_transform * vec4(texcoord, 0, 1)).xy; // Convert to left-handed coordinate system. The offset of 1 is necessary - // for rotations to be applied correctly. + // for rotation and scale to be applied correctly. texcoord.y = 1.0 - texcoord.y; texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy); // Convert back to right-handed coordinate system diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index fb27729b57..6f48971ca0 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -383,16 +383,6 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) materials = &gLocalTerrainMaterials.mDetailMaterials; } - // *TODO: Figure out why this offset is *sometimes* producing seams at the region edge, and repeat jumps when crossing regions, when RenderTerrainPBRScale is not a factor of the region scale. - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; - - LLVector4 tp0, tp1; - - tp0.setVec(sPBRDetailScale, 0.0f, 0.0f, offset_x); - tp1.setVec(0.0f, sPBRDetailScale, 0.0f, offset_y); - constexpr U32 terrain_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; S32 detail_basecolor[terrain_material_count]; S32 detail_normal[terrain_material_count]; @@ -463,8 +453,22 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); + + // *TODO: Figure out why this offset is *sometimes* producing seams at the + // region edge, and repeat jumps when crossing regions, when + // RenderTerrainPBRScale is not a factor of the region scale. + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; + + LLGLTFMaterial::TextureTransform base_color_transform; + base_color_transform.mScale = LLVector2(sPBRDetailScale, sPBRDetailScale); + base_color_transform.mOffset = LLVector2(offset_x, offset_y); + F32 base_color_packed[8]; + base_color_transform.getPacked(base_color_packed); + // *HACK: Use the same texture repeats for all PBR terrain textures for now + // (not compliant with KHR texture transform spec) + shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, (F32*)base_color_packed); LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); -- cgit v1.2.3 From 3e3a3c1c5262e65df3edf27c4e27a6bbc8d49a01 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:40 -0700 Subject: DRTVWR-592: Fix terrain normal sampling in non-triplanar case --- indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index a9155cc629..a89bc6f211 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -128,7 +128,7 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { - return texture(tex, terrain_coord).xyz; + return texture(tex, terrain_coord).xyz*2.0-1.0; } #endif -- cgit v1.2.3 From 2895b7bf81c3d076a8ceaa4ce77037e870069365 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:45 -0700 Subject: DRTVWR-592: Triplanar performance pass --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 63 ++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index a89bc6f211..1b13bc8836 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -109,14 +109,67 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) // *NOTE: Bottom face has not been tested vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { - vec3 x = _t_texture_n(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); + float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; + vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); + float threshold = 0.01; + vec3 significant = max(vec3(0), sign(weight - threshold)); + int sample_type = (int(significant.x) << 2) | + (int(significant.y) << 1) | + (int(significant.z) << 0); + + #define SAMPLE_X 1 << 2 + #define SAMPLE_Y 1 << 1 + #define SAMPLE_Z 1 << 0 + #define terrain_coord_x terrain_coord[0].zw + #define terrain_coord_y terrain_coord[1].xy + #define terrain_coord_z terrain_coord[0].xy + vec3 x; + vec3 y; + vec3 z; + switch (sample_type) + { + case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: + x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_X | SAMPLE_Y: + x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = vec3(0); + break; + case SAMPLE_X | SAMPLE_Z: + x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = vec3(0); + z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_Y | SAMPLE_Z: + x = vec3(0); + y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_X: + x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = vec3(0); + z = vec3(0); + break; + case SAMPLE_Y: + x = vec3(0); + y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = vec3(0); + break; + case SAMPLE_Z: + default: + x = vec3(0); + y = vec3(0); + z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + } + + // *HACK: Transform normals according to orientation of the UVs x.xy = vec2(-x.y, x.x); - vec3 y = _t_texture_n(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); y.xy = -y.xy; - vec3 z = _t_texture_n(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); - float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); } #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 -- cgit v1.2.3 From a8d69a4baecfae81b4adb68992f02e3ebc47b876 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:50 -0700 Subject: DRTVWR-592: Fix weights --- .../app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 1b13bc8836..e69ee54a8c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -112,10 +112,10 @@ vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); float threshold = 0.01; - vec3 significant = max(vec3(0), sign(weight - threshold)); - int sample_type = (int(significant.x) << 2) | - (int(significant.y) << 1) | - (int(significant.z) << 0); + weight = max(vec3(0), sign(weight - threshold)); + int sample_type = (int(weight.x) << 2) | + (int(weight.y) << 1) | + (int(weight.z) << 0); #define SAMPLE_X 1 << 2 #define SAMPLE_Y 1 << 1 -- cgit v1.2.3 From bb0ae367d705e6d45f21526b26caa962824d6375 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:39:56 -0700 Subject: DRTVWR-592: (WIP) Test impact of higher threshold on performance and visuals --- indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index e69ee54a8c..4f2619f811 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -111,7 +111,7 @@ vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); - float threshold = 0.01; + float threshold = 0.1; weight = max(vec3(0), sign(weight - threshold)); int sample_type = (int(weight.x) << 2) | (int(weight.y) << 1) | -- cgit v1.2.3 From e6777d566fddc79d1194a2090e5df5b609285d89 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:02 -0700 Subject: DRTVWR-592: Fix not thresholding texture lookups for non-normal textures. Also decrease threshold to (hopefully) reasonable level --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 72 +++++++++++++++++++--- 1 file changed, 62 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 4f2619f811..b89edc9731 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -69,6 +69,7 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] +#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) { @@ -89,12 +90,63 @@ vec3 _t_texture_n(sampler2D tex, vec2 uv_unflipped, float sign) vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) { - // Multiplying the UVs by the sign of the normal flips the texture upright. - vec4 x = _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); - vec4 y = _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); - vec4 z = _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); + vec3 weight = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); + float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; + weight = max(vec3(0), sign(weight - threshold)); + + #define SAMPLE_X 1 << 2 + #define SAMPLE_Y 1 << 1 + #define SAMPLE_Z 1 << 0 + int sample_type = (int(weight.x) * SAMPLE_X) | + (int(weight.y) * SAMPLE_Y) | + (int(weight.z) * SAMPLE_Z); + #define terrain_coord_x terrain_coord[0].zw + #define terrain_coord_y terrain_coord[1].xy + #define terrain_coord_z terrain_coord[0].xy + vec4 x; + vec4 y; + vec4 z; + switch (sample_type) + { + case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: + x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_X | SAMPLE_Y: + x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = vec4(0); + break; + case SAMPLE_X | SAMPLE_Z: + x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = vec4(0); + z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_Y | SAMPLE_Z: + x = vec4(0); + y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + case SAMPLE_X: + x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); + y = vec4(0); + z = vec4(0); + break; + case SAMPLE_Y: + x = vec4(0); + y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); + z = vec4(0); + break; + case SAMPLE_Z: + default: + x = vec4(0); + y = vec4(0); + z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + break; + } + return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); } @@ -110,16 +162,16 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - vec3 weight = pow(abs(vary_vertex_normal), vec3(sharpness)); - float threshold = 0.1; + vec3 weight = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); + float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; weight = max(vec3(0), sign(weight - threshold)); - int sample_type = (int(weight.x) << 2) | - (int(weight.y) << 1) | - (int(weight.z) << 0); #define SAMPLE_X 1 << 2 #define SAMPLE_Y 1 << 1 #define SAMPLE_Z 1 << 0 + int sample_type = (int(weight.x) * SAMPLE_X) | + (int(weight.y) * SAMPLE_Y) | + (int(weight.z) * SAMPLE_Z); #define terrain_coord_x terrain_coord[0].zw #define terrain_coord_y terrain_coord[1].xy #define terrain_coord_z terrain_coord[0].xy -- cgit v1.2.3 From 53a5055ab72c3fb77892a3e43c769c3b19c1e97d Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:07 -0700 Subject: DRTVWR-592: (WIP) (has debug) Convert colors to linear before triplanar blending. General refactor. --- .../shaders/class1/deferred/pbrterrainF.glsl | 11 + .../shaders/class1/deferred/pbrterrainUtilF.glsl | 249 ++++++++++++--------- 2 files changed, 160 insertions(+), 100 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 7febbe280e..ba917416ce 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -135,6 +135,17 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; +#if 0 // TODO: Remove debug + //col.xyz = (tnorm + 1.0) / 2.0;// TODO: Remove + //col.xyz = (vary_normal + 1.0) / 2.0;// TODO: Remove + //col.xyz = spec; // TODO: Remove + //col.xyz = vec3(1); // TODO: Remove + //float weight = 1.0; spec.rgb = (weight * spec.rgb) + ((1 - weight) * vec3(1.0, 1.0, 1.0)); // TODO: Remove + tnorm = vary_normal; // TODO: Remove + spec.r = 1.0; // TODO: Remove + spec.gb = vec2(1.0, 0.0); // TODO: Remove + emissive.rgb = vec3(0); // TODO: Remove +#endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index b89edc9731..c72bc65cca 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -69,7 +69,15 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] +#if 0 // TODO: Revert #define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 +#else +#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 +#endif + +// Positive value prevents artifacts when weights are close to zero +// TODO: Wait a minute... this doesn't prevent artifacts :( (or does it?) +#define TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD 0.0 vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) { @@ -79,35 +87,60 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) return texture(tex, uv); } -vec3 _t_texture_n(sampler2D tex, vec2 uv_unflipped, float sign) +vec4 _t_texture_c(sampler2D tex, vec2 uv_unflipped, float sign) { - // Unpack normal from pixel to vector - vec3 n = _t_texture(tex, uv_unflipped, sign).xyz*2.0-1.0; - // If the sign is negative, rotate normal by 180 degrees - n.xy = (min(0, sign) * n.xy) + (min(0, -sign) * -n.xy); - return n; + vec4 c = _t_texture(tex, uv_unflipped, sign); + c.xyz = srgb_to_linear(c.xyz); + return c; } -vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) +#define SAMPLE_X 1 << 2 +#define SAMPLE_Y 1 << 1 +#define SAMPLE_Z 1 << 0 +#define terrain_coord_x terrain_coord[0].zw +#define terrain_coord_y terrain_coord[1].xy +#define terrain_coord_z terrain_coord[0].xy +#define TERRAIN_DEBUG 1 // TODO: Remove debug +struct TerrainWeight +{ + vec3 weight; +#if TERRAIN_DEBUG + vec3 usage; +#endif + int type; +}; + +TerrainWeight _t_weight(TerrainCoord terrain_coord) { float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - vec3 weight = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; - weight = max(vec3(0), sign(weight - threshold)); - - #define SAMPLE_X 1 << 2 - #define SAMPLE_Y 1 << 1 - #define SAMPLE_Z 1 << 0 - int sample_type = (int(weight.x) * SAMPLE_X) | - (int(weight.y) * SAMPLE_Y) | - (int(weight.z) * SAMPLE_Z); - #define terrain_coord_x terrain_coord[0].zw - #define terrain_coord_y terrain_coord[1].xy - #define terrain_coord_z terrain_coord[0].xy + vec3 weight_signed = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); + weight_signed -= vec3(threshold); + TerrainWeight tw; + tw.weight = max(vec3(0), weight_signed); + vec3 usage = max(vec3(0), sign(weight_signed + TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD)); +#if TERRAIN_DEBUG + tw.usage = usage; +#endif + tw.type = (int(usage.x) * SAMPLE_X) | + (int(usage.y) * SAMPLE_Y) | + (int(usage.z) * SAMPLE_Z); + return tw; +} + +struct TerrainSample +{ vec4 x; vec4 y; vec4 z; - switch (sample_type) +}; + +TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +{ + vec4 x; + vec4 y; + vec4 z; + switch (tw.type) { case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); @@ -117,37 +150,98 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) case SAMPLE_X | SAMPLE_Y: x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = vec4(0); + z = x; break; case SAMPLE_X | SAMPLE_Z: x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = vec4(0); z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + y = x; break; case SAMPLE_Y | SAMPLE_Z: - x = vec4(0); y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + x = y; break; case SAMPLE_X: x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = vec4(0); - z = vec4(0); + y = x; + z = x; break; case SAMPLE_Y: - x = vec4(0); y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = vec4(0); + x = y; + z = y; break; case SAMPLE_Z: + z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + x = z; + y = z; + break; default: x = vec4(0); - y = vec4(0); - z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + y = x; + z = x; break; } - return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); + TerrainSample ts; + ts.x = x; + ts.y = y; + ts.z = z; + return ts; +} + +struct TerrainSampleNormal +{ + vec3 x; + vec3 y; + vec3 z; +}; + +TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +{ + TerrainSample ts = _t_sample(tex, terrain_coord, tw); + TerrainSampleNormal tsn; + tsn.x = ts.x.xyz; + tsn.y = ts.y.xyz; + tsn.z = ts.z.xyz; + vec3 ns = sign(vary_vertex_normal); + // If the sign is negative, rotate normal by 180 degrees + tsn.x.xy = (min(0, ns.x) * tsn.x.xy) + (min(0, -ns.x) * -tsn.x.xy); + tsn.y.xy = (min(0, ns.y) * tsn.y.xy) + (min(0, -ns.y) * -tsn.y.xy); + tsn.z.xy = (min(0, ns.z) * tsn.z.xy) + (min(0, -ns.z) * -tsn.z.xy); + // *HACK: Transform normals according to orientation of the UVs + tsn.x.xy = vec2(-tsn.x.y, tsn.x.x); + tsn.y.xy = -tsn.y.xy; + return tsn; +} + +TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +{ + TerrainSample ts = _t_sample(tex, terrain_coord, tw); + ts.x.xyz = srgb_to_linear(ts.x.xyz); + ts.y.xyz = srgb_to_linear(ts.y.xyz); + ts.z.xyz = srgb_to_linear(ts.z.xyz); + return ts; +} + +vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) +{ + TerrainWeight tw = _t_weight(terrain_coord); + + TerrainSample ts = _t_sample(tex, terrain_coord, tw); + +#if 1 + return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); +#else // TODO: Remove debug + //return vec4(((tw.usage - normalize(tw.weight))) / 0.5, 1.0); +#if 1 + return vec4(tw.usage, 1.0); +#else + //return vec4(tw.usage, 1.0); + return vec4((tw.usage + weight) / 2.0, 1.0); +#endif +#endif } // Specialized triplanar normal texture sampling implementation, taking into @@ -156,74 +250,26 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) // *TODO: Decide if we want this. It may be better to just calculate the // tangents on-the-fly here rather than messing with the normals, due to the // subtleties of the effects of triplanar mapping on UVs. These sampled normals -// are only valid on the faces of a cube, and the pregenerated tangents are -// only valid for uv = xy. +// are only valid on the faces of a cube. // *NOTE: Bottom face has not been tested vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { - float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - vec3 weight = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); - float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; - weight = max(vec3(0), sign(weight - threshold)); - - #define SAMPLE_X 1 << 2 - #define SAMPLE_Y 1 << 1 - #define SAMPLE_Z 1 << 0 - int sample_type = (int(weight.x) * SAMPLE_X) | - (int(weight.y) * SAMPLE_Y) | - (int(weight.z) * SAMPLE_Z); - #define terrain_coord_x terrain_coord[0].zw - #define terrain_coord_y terrain_coord[1].xy - #define terrain_coord_z terrain_coord[0].xy - vec3 x; - vec3 y; - vec3 z; - switch (sample_type) - { - case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: - x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - break; - case SAMPLE_X | SAMPLE_Y: - x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = vec3(0); - break; - case SAMPLE_X | SAMPLE_Z: - x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = vec3(0); - z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - break; - case SAMPLE_Y | SAMPLE_Z: - x = vec3(0); - y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - break; - case SAMPLE_X: - x = _t_texture_n(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = vec3(0); - z = vec3(0); - break; - case SAMPLE_Y: - x = vec3(0); - y = _t_texture_n(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = vec3(0); - break; - case SAMPLE_Z: - default: - x = vec3(0); - y = vec3(0); - z = _t_texture_n(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - break; - } + TerrainWeight tw = _t_weight(terrain_coord); - // *HACK: Transform normals according to orientation of the UVs - x.xy = vec2(-x.y, x.x); - y.xy = -y.xy; + TerrainSampleNormal ts = _t_sample_n(tex, terrain_coord, tw); - return ((x * weight.x) + (y * weight.y) + (z * weight.z)) / (weight.x + weight.y + weight.z); + return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); } + +vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) +{ + TerrainWeight tw = _t_weight(terrain_coord); + + TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); + + return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); +} + #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 #define TerrainCoord vec2 vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) @@ -235,6 +281,13 @@ vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { return texture(tex, terrain_coord).xyz*2.0-1.0; } + +vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) +{ + vec4 col = texture(tex, terrain_coord); + col.xyz = srgb_to_linear(col.xyz); + return col; +} #endif vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) @@ -258,14 +311,10 @@ vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, Terrain vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { vec4[4] samples; - samples[0] = terrain_texture(tex0, texcoord); - samples[1] = terrain_texture(tex1, texcoord); - samples[2] = terrain_texture(tex2, texcoord); - samples[3] = terrain_texture(tex3, texcoord); - samples[0].xyz = srgb_to_linear(samples[0].xyz); - samples[1].xyz = srgb_to_linear(samples[1].xyz); - samples[2].xyz = srgb_to_linear(samples[2].xyz); - samples[3].xyz = srgb_to_linear(samples[3].xyz); + samples[0] = terrain_texture_color(tex0, texcoord); + samples[1] = terrain_texture_color(tex1, texcoord); + samples[2] = terrain_texture_color(tex2, texcoord); + samples[3] = terrain_texture_color(tex3, texcoord); samples[0] *= factors[0]; samples[1] *= factors[1]; samples[2] *= factors[2]; -- cgit v1.2.3 From a9a08f72be2c30a40f7c6565bb82e7356245e8ec Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:13 -0700 Subject: DRTVWR-592: (WIP) Cleanup --- .../shaders/class1/deferred/pbrterrainF.glsl | 8 +-- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 77 ++++++++++------------ 2 files changed, 37 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index ba917416ce..10a147a039 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -141,10 +141,10 @@ void main() //col.xyz = spec; // TODO: Remove //col.xyz = vec3(1); // TODO: Remove //float weight = 1.0; spec.rgb = (weight * spec.rgb) + ((1 - weight) * vec3(1.0, 1.0, 1.0)); // TODO: Remove - tnorm = vary_normal; // TODO: Remove - spec.r = 1.0; // TODO: Remove - spec.gb = vec2(1.0, 0.0); // TODO: Remove - emissive.rgb = vec3(0); // TODO: Remove + //tnorm = vary_normal; // TODO: Remove + //spec.r = 1.0; // TODO: Remove + //spec.gb = vec2(1.0, 0.0); // TODO: Remove + //emissive.rgb = vec3(0); // TODO: Remove #endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index c72bc65cca..1f8b0b97c7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -87,19 +87,9 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) return texture(tex, uv); } -vec4 _t_texture_c(sampler2D tex, vec2 uv_unflipped, float sign) -{ - vec4 c = _t_texture(tex, uv_unflipped, sign); - c.xyz = srgb_to_linear(c.xyz); - return c; -} - #define SAMPLE_X 1 << 2 #define SAMPLE_Y 1 << 1 #define SAMPLE_Z 1 << 0 -#define terrain_coord_x terrain_coord[0].zw -#define terrain_coord_y terrain_coord[1].xy -#define terrain_coord_z terrain_coord[0].xy #define TERRAIN_DEBUG 1 // TODO: Remove debug struct TerrainWeight { @@ -137,57 +127,55 @@ struct TerrainSample TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) { - vec4 x; - vec4 y; - vec4 z; + TerrainSample ts; + +#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); +#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); +#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); switch (tw.type) { case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: - x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); + ts.x = do_sample_x(); + ts.y = do_sample_y(); + ts.z = do_sample_z(); break; case SAMPLE_X | SAMPLE_Y: - x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = x; + ts.x = do_sample_x(); + ts.y = do_sample_y(); + ts.z = ts.x; break; case SAMPLE_X | SAMPLE_Z: - x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - y = x; + ts.x = do_sample_x(); + ts.z = do_sample_z(); + ts.y = ts.x; break; case SAMPLE_Y | SAMPLE_Z: - y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - x = y; + ts.y = do_sample_y(); + ts.z = do_sample_z(); + ts.x = ts.y; break; case SAMPLE_X: - x = _t_texture(tex, terrain_coord_x, sign(vary_vertex_normal.x)); - y = x; - z = x; + ts.x = do_sample_x(); + ts.y = ts.x; + ts.z = ts.x; break; case SAMPLE_Y: - y = _t_texture(tex, terrain_coord_y, sign(vary_vertex_normal.y)); - x = y; - z = y; + ts.y = do_sample_y(); + ts.x = ts.y; + ts.z = ts.y; break; case SAMPLE_Z: - z = _t_texture(tex, terrain_coord_z, sign(vary_vertex_normal.z)); - x = z; - y = z; + ts.z = do_sample_z(); + ts.x = ts.z; + ts.y = ts.z; break; default: - x = vec4(0); - y = x; - z = x; + ts.x = vec4(0); + ts.y = ts.x; + ts.z = ts.x; break; } - TerrainSample ts; - ts.x = x; - ts.y = y; - ts.z = z; return ts; } @@ -202,9 +190,9 @@ TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, Terra { TerrainSample ts = _t_sample(tex, terrain_coord, tw); TerrainSampleNormal tsn; - tsn.x = ts.x.xyz; - tsn.y = ts.y.xyz; - tsn.z = ts.z.xyz; + tsn.x = ts.x.xyz*2.0-1.0; + tsn.y = ts.y.xyz*2.0-1.0; + tsn.z = ts.z.xyz*2.0-1.0; vec3 ns = sign(vary_vertex_normal); // If the sign is negative, rotate normal by 180 degrees tsn.x.xy = (min(0, ns.x) * tsn.x.xy) + (min(0, -ns.x) * -tsn.x.xy); @@ -261,6 +249,7 @@ vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); } +// Triplanar sampling of colors. Colors are converted to linear space before blending. vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) { TerrainWeight tw = _t_weight(terrain_coord); -- cgit v1.2.3 From d745b6321306a44ae9bbd5afc6fff376ebaf12e9 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:19 -0700 Subject: DRTVWR-592: (DEBUG) (broken) Strange sampling behavior survives weight bypass --- .../shaders/class1/deferred/pbrterrainF.glsl | 10 +++++----- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 10a147a039..19de8568b8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -135,16 +135,16 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; -#if 0 // TODO: Remove debug +#if 1 // TODO: Remove debug //col.xyz = (tnorm + 1.0) / 2.0;// TODO: Remove //col.xyz = (vary_normal + 1.0) / 2.0;// TODO: Remove //col.xyz = spec; // TODO: Remove //col.xyz = vec3(1); // TODO: Remove //float weight = 1.0; spec.rgb = (weight * spec.rgb) + ((1 - weight) * vec3(1.0, 1.0, 1.0)); // TODO: Remove - //tnorm = vary_normal; // TODO: Remove - //spec.r = 1.0; // TODO: Remove - //spec.gb = vec2(1.0, 0.0); // TODO: Remove - //emissive.rgb = vec3(0); // TODO: Remove + tnorm = vary_normal; // TODO: Remove + spec.r = 1.0; // TODO: Remove + spec.gb = vec2(1.0, 0.0); // TODO: Remove + emissive.rgb = vec3(0); // TODO: Remove #endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 1f8b0b97c7..327d23d2e7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -129,8 +129,13 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight { TerrainSample ts; -#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)); -#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)); +#if 0 +#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) +#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) +#else // TODO: Remove debug +#define do_sample_x() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) +#define do_sample_y() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) +#endif #define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); switch (tw.type) { @@ -219,15 +224,15 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) TerrainSample ts = _t_sample(tex, terrain_coord, tw); -#if 1 +#if 0 return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); #else // TODO: Remove debug //return vec4(((tw.usage - normalize(tw.weight))) / 0.5, 1.0); -#if 1 +#if 0 return vec4(tw.usage, 1.0); #else //return vec4(tw.usage, 1.0); - return vec4((tw.usage + weight) / 2.0, 1.0); + return vec4((tw.usage + tw.weight) / 2.0, 1.0); #endif #endif } @@ -256,7 +261,11 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); +#if 0 return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); +#else // TODO: Remove debug + return ts.x; +#endif } #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 -- cgit v1.2.3 From aba9185f3a27221f71aa53001b45db0337a0b904 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:24 -0700 Subject: DRTVWR-592: (DEBUG) (broken) Strange sampling behavior isolated to switch..case blocks --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 179 ++++++++++++++++++--- 1 file changed, 155 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 327d23d2e7..5067e94efe 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -79,12 +79,29 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) // TODO: Wait a minute... this doesn't prevent artifacts :( (or does it?) #define TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD 0.0 -vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) +vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) { + // Handle case where sign is 0 + // TODO: Why didn't this fix the seams? +#if 0 + float sign = (2.0*sign_or_zero) + 1.0; + sign /= sign; // If the vertex normal is negative, flip the texture back // right-side up. vec2 uv = uv_unflipped * vec2(sign, 1); return texture(tex, uv); +#else // TODO: Remove debug +#if 0 + // Name mangling test + float l_sign = (2.0*sign_or_zero) + 1.0; + l_sign /= l_sign; + vec2 l_uv = uv_unflipped * vec2(l_sign, 1); + return texture(tex, l_uv); +#else + // Simplified uv test + return texture(tex, uv_unflipped); +#endif +#endif } #define SAMPLE_X 1 << 2 @@ -94,10 +111,11 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign) struct TerrainWeight { vec3 weight; + int type; #if TERRAIN_DEBUG + vec3 weight_signed; vec3 usage; #endif - int type; }; TerrainWeight _t_weight(TerrainCoord terrain_coord) @@ -109,12 +127,13 @@ TerrainWeight _t_weight(TerrainCoord terrain_coord) TerrainWeight tw; tw.weight = max(vec3(0), weight_signed); vec3 usage = max(vec3(0), sign(weight_signed + TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD)); -#if TERRAIN_DEBUG - tw.usage = usage; -#endif tw.type = (int(usage.x) * SAMPLE_X) | (int(usage.y) * SAMPLE_Y) | (int(usage.z) * SAMPLE_Z); +#if TERRAIN_DEBUG + tw.weight_signed = weight_signed; + tw.usage = usage; +#endif return tw; } @@ -129,32 +148,44 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight { TerrainSample ts; -#if 0 +#if 1 +#if 1 +#if 1 #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) #define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) #else // TODO: Remove debug +// Still an error despite sampling the same texture three times from the same location #define do_sample_x() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) #define do_sample_y() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) #endif -#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); +#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) +#else // TODO: Remove? + vec2 coord_z = terrain_coord[0].xy; + vec2 coord_z_2 = terrain_coord[0].xy; + vec2 coord_z_3 = terrain_coord[0].xy; +#define do_sample_x() texture(tex, coord_z) +#define do_sample_y() texture(tex, coord_z_2) +#define do_sample_z() texture(tex, coord_z_3) +#endif +#if 0 switch (tw.type) { - case SAMPLE_X | SAMPLE_Y | SAMPLE_Z: + case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): ts.x = do_sample_x(); ts.y = do_sample_y(); ts.z = do_sample_z(); break; - case SAMPLE_X | SAMPLE_Y: + case (SAMPLE_X | SAMPLE_Y): ts.x = do_sample_x(); ts.y = do_sample_y(); ts.z = ts.x; break; - case SAMPLE_X | SAMPLE_Z: + case (SAMPLE_X | SAMPLE_Z): ts.x = do_sample_x(); ts.z = do_sample_z(); ts.y = ts.x; break; - case SAMPLE_Y | SAMPLE_Z: + case (SAMPLE_Y | SAMPLE_Z): ts.y = do_sample_y(); ts.z = do_sample_z(); ts.x = ts.y; @@ -175,11 +206,114 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight ts.y = ts.z; break; default: - ts.x = vec4(0); + ts.x = vec4(1.0, 0.0, 1.0, 1.0); + ts.y = ts.x; + ts.z = ts.x; + break; + } +#else // TODO: Remove debug +#if 0 + // This case works - no ant trails despite using a switch...case statement + switch (tw.type) + { + case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): + ts.x = vec4(1.0, 0.0, 0.0, 1.0); + ts.y = vec4(0.0, 1.0, 0.0, 1.0); + ts.z = vec4(0.0, 0.0, 1.0, 1.0); + break; + case (SAMPLE_X | SAMPLE_Y): + ts.x = vec4(1.0, 0.0, 0.0, 1.0); + ts.y = vec4(0.0, 1.0, 0.0, 1.0); + ts.z = ts.x; + break; + case (SAMPLE_X | SAMPLE_Z): + ts.x = vec4(1.0, 0.0, 0.0, 1.0); + ts.z = vec4(0.0, 0.0, 1.0, 1.0); + ts.y = ts.x; + break; + case (SAMPLE_Y | SAMPLE_Z): + ts.y = vec4(0.0, 1.0, 0.0, 1.0); + ts.z = vec4(0.0, 0.0, 1.0, 1.0); + ts.x = ts.y; + break; + case SAMPLE_X: + ts.x = vec4(1.0, 0.0, 0.0, 1.0); + ts.y = ts.x; + ts.z = ts.x; + break; + case SAMPLE_Y: + ts.y = vec4(0.0, 1.0, 0.0, 1.0); + ts.x = ts.y; + ts.z = ts.y; + break; + case SAMPLE_Z: + ts.z = vec4(0.0, 0.0, 1.0, 1.0); + ts.x = ts.z; + ts.y = ts.z; + break; + default: + ts.x = vec4(1.0, 0.0, 1.0, 1.0); + ts.y = ts.x; + ts.z = ts.x; + break; + } +#else +// This shows the bug: case of sampling beforehand, assigning in switch..case + vec4 x = do_sample_x(); + vec4 y = do_sample_y(); + vec4 z = do_sample_z(); + switch (tw.type) + { + case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): + ts.x = x; + ts.y = y; + ts.z = z; + break; + case (SAMPLE_X | SAMPLE_Y): + ts.x = x; + ts.y = y; + ts.z = ts.x; + break; + case (SAMPLE_X | SAMPLE_Z): + ts.x = x; + ts.z = z; + ts.y = ts.x; + break; + case (SAMPLE_Y | SAMPLE_Z): + ts.y = y; + ts.z = z; + ts.x = ts.y; + break; + case SAMPLE_X: + ts.x = x; + ts.y = ts.x; + ts.z = ts.x; + break; + case SAMPLE_Y: + ts.y = y; + ts.x = ts.y; + ts.z = ts.y; + break; + case SAMPLE_Z: + ts.z = z; + ts.x = ts.z; + ts.y = ts.z; + break; + default: + ts.x = vec4(1.0, 0.0, 1.0, 1.0); ts.y = ts.x; ts.z = ts.x; break; } +#endif +#endif +#else // TODO: Remove debug +// No error +#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); +ts.z = do_sample_z(); +ts.x = ts.z; +ts.y = ts.z; +#endif return ts; } @@ -218,23 +352,14 @@ TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainWeig return ts; } +// Triplanar sampling of things that are neither colors nor normals (i.e. orm) vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) { TerrainWeight tw = _t_weight(terrain_coord); TerrainSample ts = _t_sample(tex, terrain_coord, tw); -#if 0 return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); -#else // TODO: Remove debug - //return vec4(((tw.usage - normalize(tw.weight))) / 0.5, 1.0); -#if 0 - return vec4(tw.usage, 1.0); -#else - //return vec4(tw.usage, 1.0); - return vec4((tw.usage + tw.weight) / 2.0, 1.0); -#endif -#endif } // Specialized triplanar normal texture sampling implementation, taking into @@ -261,10 +386,16 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); -#if 0 +#if 1 return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); #else // TODO: Remove debug - return ts.x; + //return vec4(vec3(isnan(ts.x)), 1.0); + //return ts.x; +#if 0 + return vec4(1.0+sign(vary_vertex_normal)/2.0, 1.0); +#else + return vec4(isnan(tw.weight_signed), 1.0); +#endif #endif } -- cgit v1.2.3 From fb12fb4bf7bbbf457b4f81356b0d0fadf2b42664 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:40:29 -0700 Subject: DRTVWR-592: (DEBUG) (broken) Clean up a few debug cases not used for reproducing the bug --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 100 +++------------------ 1 file changed, 12 insertions(+), 88 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 5067e94efe..a40f70a9e2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -69,39 +69,22 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] -#if 0 // TODO: Revert +// TODO: Decide if we want this threshold +#if 0 #define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 -#else +#else // TODO: Remove debug #define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 #endif -// Positive value prevents artifacts when weights are close to zero -// TODO: Wait a minute... this doesn't prevent artifacts :( (or does it?) -#define TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD 0.0 - vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) { // Handle case where sign is 0 - // TODO: Why didn't this fix the seams? -#if 0 float sign = (2.0*sign_or_zero) + 1.0; sign /= sign; // If the vertex normal is negative, flip the texture back // right-side up. vec2 uv = uv_unflipped * vec2(sign, 1); return texture(tex, uv); -#else // TODO: Remove debug -#if 0 - // Name mangling test - float l_sign = (2.0*sign_or_zero) + 1.0; - l_sign /= l_sign; - vec2 l_uv = uv_unflipped * vec2(l_sign, 1); - return texture(tex, l_uv); -#else - // Simplified uv test - return texture(tex, uv_unflipped); -#endif -#endif } #define SAMPLE_X 1 << 2 @@ -126,7 +109,7 @@ TerrainWeight _t_weight(TerrainCoord terrain_coord) weight_signed -= vec3(threshold); TerrainWeight tw; tw.weight = max(vec3(0), weight_signed); - vec3 usage = max(vec3(0), sign(weight_signed + TERRAIN_TRIPLANAR_OVERDRAW_THRESHOLD)); + vec3 usage = max(vec3(0), sign(weight_signed)); tw.type = (int(usage.x) * SAMPLE_X) | (int(usage.y) * SAMPLE_Y) | (int(usage.z) * SAMPLE_Z); @@ -149,25 +132,16 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight TerrainSample ts; #if 1 -#if 1 -#if 1 +// This demonstrates the case when the bug occurs: Sampling in switch..case +#if 0 #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) #define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) #else // TODO: Remove debug -// Still an error despite sampling the same texture three times from the same location +// Bug still occurs despite sampling the same texture three times from the same location #define do_sample_x() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) #define do_sample_y() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) #endif #define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) -#else // TODO: Remove? - vec2 coord_z = terrain_coord[0].xy; - vec2 coord_z_2 = terrain_coord[0].xy; - vec2 coord_z_3 = terrain_coord[0].xy; -#define do_sample_x() texture(tex, coord_z) -#define do_sample_y() texture(tex, coord_z_2) -#define do_sample_z() texture(tex, coord_z_3) -#endif -#if 0 switch (tw.type) { case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): @@ -212,53 +186,11 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight break; } #else // TODO: Remove debug -#if 0 - // This case works - no ant trails despite using a switch...case statement - switch (tw.type) - { - case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): - ts.x = vec4(1.0, 0.0, 0.0, 1.0); - ts.y = vec4(0.0, 1.0, 0.0, 1.0); - ts.z = vec4(0.0, 0.0, 1.0, 1.0); - break; - case (SAMPLE_X | SAMPLE_Y): - ts.x = vec4(1.0, 0.0, 0.0, 1.0); - ts.y = vec4(0.0, 1.0, 0.0, 1.0); - ts.z = ts.x; - break; - case (SAMPLE_X | SAMPLE_Z): - ts.x = vec4(1.0, 0.0, 0.0, 1.0); - ts.z = vec4(0.0, 0.0, 1.0, 1.0); - ts.y = ts.x; - break; - case (SAMPLE_Y | SAMPLE_Z): - ts.y = vec4(0.0, 1.0, 0.0, 1.0); - ts.z = vec4(0.0, 0.0, 1.0, 1.0); - ts.x = ts.y; - break; - case SAMPLE_X: - ts.x = vec4(1.0, 0.0, 0.0, 1.0); - ts.y = ts.x; - ts.z = ts.x; - break; - case SAMPLE_Y: - ts.y = vec4(0.0, 1.0, 0.0, 1.0); - ts.x = ts.y; - ts.z = ts.y; - break; - case SAMPLE_Z: - ts.z = vec4(0.0, 0.0, 1.0, 1.0); - ts.x = ts.z; - ts.y = ts.z; - break; - default: - ts.x = vec4(1.0, 0.0, 1.0, 1.0); - ts.y = ts.x; - ts.z = ts.x; - break; - } -#else -// This shows the bug: case of sampling beforehand, assigning in switch..case +// This demonstrates the case when the bug does not occur: Sampling beforehand and assigning in switch..case +// This otherwise uses the same logic as in the case that reproduces the bug. +#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) +#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) +#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) vec4 x = do_sample_x(); vec4 y = do_sample_y(); vec4 z = do_sample_z(); @@ -305,14 +237,6 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight ts.z = ts.x; break; } -#endif -#endif -#else // TODO: Remove debug -// No error -#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)); -ts.z = do_sample_z(); -ts.x = ts.z; -ts.y = ts.z; #endif return ts; -- cgit v1.2.3 From be39e92f7d3c6df80eeb1f183723978ce1bf1b52 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:41:19 -0700 Subject: DRTVWR-592: (WIP) (has debug) Fix "ant trail" seams in terrain caused by multiple texture lookups in a switch..case block --- .../shaders/class1/deferred/pbrterrainF.glsl | 2 +- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 44 +++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 19de8568b8..ba917416ce 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -135,7 +135,7 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; -#if 1 // TODO: Remove debug +#if 0 // TODO: Remove debug //col.xyz = (tnorm + 1.0) / 2.0;// TODO: Remove //col.xyz = (vary_normal + 1.0) / 2.0;// TODO: Remove //col.xyz = spec; // TODO: Remove diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index a40f70a9e2..fc04afe513 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -131,7 +131,7 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight { TerrainSample ts; -#if 1 +#if 0 // This demonstrates the case when the bug occurs: Sampling in switch..case #if 0 #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) @@ -142,7 +142,12 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight #define do_sample_y() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) #endif #define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) +#if 0 switch (tw.type) +#else // TODO: Remove debug +// Bug still occurs when the type is masked + switch (tw.type & (SAMPLE_X | SAMPLE_Y | SAMPLE_Z)) +#endif { case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): ts.x = do_sample_x(); @@ -186,6 +191,7 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight break; } #else // TODO: Remove debug +#if 0 // This demonstrates the case when the bug does not occur: Sampling beforehand and assigning in switch..case // This otherwise uses the same logic as in the case that reproduces the bug. #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) @@ -237,6 +243,42 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight ts.z = ts.x; break; } +#else // TODO: Keep? +// Test case where the switch..case is broken up into three parts +// This fixes unexplained, "ant trail" seams in terrain. (as seen on Nvidia/Windows 10) +// The extra two branches are not free, but it's still a performance win +// compared to sampling along all three axes for every terrain fragment. +#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) +#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) +#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) +switch (tw.type & SAMPLE_X) +{ + case SAMPLE_X: + ts.x = do_sample_x(); + break; + default: + ts.x = vec4(1.0, 0.0, 1.0, 1.0); + break; +} +switch (tw.type & SAMPLE_Y) +{ + case SAMPLE_Y: + ts.y = do_sample_y(); + break; + default: + ts.y = vec4(1.0, 0.0, 1.0, 1.0); + break; +} +switch (tw.type & SAMPLE_Z) +{ + case SAMPLE_Z: + ts.z = do_sample_z(); + break; + default: + ts.z = vec4(1.0, 0.0, 1.0, 1.0); + break; +} +#endif #endif return ts; -- cgit v1.2.3 From 823fcddcb508fac6d1f819633f6a91230f06b114 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:02 -0700 Subject: DRTVWR-592: (WIP) (has debug) Fix removing axial sign flip of normal texture during zero check, add another zero check --- .../app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index fc04afe513..c5de74604f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -80,7 +80,7 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) { // Handle case where sign is 0 float sign = (2.0*sign_or_zero) + 1.0; - sign /= sign; + sign /= abs(sign); // If the vertex normal is negative, flip the texture back // right-side up. vec2 uv = uv_unflipped * vec2(sign, 1); @@ -190,8 +190,8 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight ts.z = ts.x; break; } -#else // TODO: Remove debug -#if 0 +#else +#if 0 // TODO: Remove debug // This demonstrates the case when the bug does not occur: Sampling beforehand and assigning in switch..case // This otherwise uses the same logic as in the case that reproduces the bug. #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) @@ -295,10 +295,15 @@ TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, Terra { TerrainSample ts = _t_sample(tex, terrain_coord, tw); TerrainSampleNormal tsn; + // Unpack normals tsn.x = ts.x.xyz*2.0-1.0; tsn.y = ts.y.xyz*2.0-1.0; tsn.z = ts.z.xyz*2.0-1.0; + // Get sign vec3 ns = sign(vary_vertex_normal); + // Handle case where sign is 0 + ns = (2.0*ns) + 1.0; + ns /= abs(ns); // If the sign is negative, rotate normal by 180 degrees tsn.x.xy = (min(0, ns.x) * tsn.x.xy) + (min(0, -ns.x) * -tsn.x.xy); tsn.y.xy = (min(0, ns.y) * tsn.y.xy) + (min(0, -ns.y) * -tsn.y.xy); -- cgit v1.2.3 From c48837ef9b7cd016577b2f54f3f6b52764c32e17 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:07 -0700 Subject: DRTVWR-592: (WIP) (has debug) More rigorous definition of usage vector for triplanar that avoids possible case where 1 = 0.9999, which gets rounded down to 0 on int cast --- .../app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index c5de74604f..1ea1ced45b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -97,7 +97,7 @@ struct TerrainWeight int type; #if TERRAIN_DEBUG vec3 weight_signed; - vec3 usage; + ivec3 usage; #endif }; @@ -109,10 +109,10 @@ TerrainWeight _t_weight(TerrainCoord terrain_coord) weight_signed -= vec3(threshold); TerrainWeight tw; tw.weight = max(vec3(0), weight_signed); - vec3 usage = max(vec3(0), sign(weight_signed)); - tw.type = (int(usage.x) * SAMPLE_X) | - (int(usage.y) * SAMPLE_Y) | - (int(usage.z) * SAMPLE_Z); + ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed)))); + tw.type = ((usage.x) * SAMPLE_X) | + ((usage.y) * SAMPLE_Y) | + ((usage.z) * SAMPLE_Z); #if TERRAIN_DEBUG tw.weight_signed = weight_signed; tw.usage = usage; -- cgit v1.2.3 From fa11e94c3cf4fad439dc10db630c747c8da42dd8 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:12 -0700 Subject: DRTVWR-592: Clean up debug and test cases for ant trails artifact. Fix whitespace --- .../shaders/class1/deferred/pbrterrainF.glsl | 11 -- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 182 +++------------------ 2 files changed, 24 insertions(+), 169 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index ba917416ce..7febbe280e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -135,17 +135,6 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; -#if 0 // TODO: Remove debug - //col.xyz = (tnorm + 1.0) / 2.0;// TODO: Remove - //col.xyz = (vary_normal + 1.0) / 2.0;// TODO: Remove - //col.xyz = spec; // TODO: Remove - //col.xyz = vec3(1); // TODO: Remove - //float weight = 1.0; spec.rgb = (weight * spec.rgb) + ((1 - weight) * vec3(1.0, 1.0, 1.0)); // TODO: Remove - tnorm = vary_normal; // TODO: Remove - spec.r = 1.0; // TODO: Remove - spec.gb = vec2(1.0, 0.0); // TODO: Remove - emissive.rgb = vec3(0); // TODO: Remove -#endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 1ea1ced45b..e2d6cdb2d6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -69,12 +69,7 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] -// TODO: Decide if we want this threshold -#if 0 #define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 -#else // TODO: Remove debug -#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 -#endif vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) { @@ -90,15 +85,10 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) #define SAMPLE_X 1 << 2 #define SAMPLE_Y 1 << 1 #define SAMPLE_Z 1 << 0 -#define TERRAIN_DEBUG 1 // TODO: Remove debug struct TerrainWeight { vec3 weight; int type; -#if TERRAIN_DEBUG - vec3 weight_signed; - ivec3 usage; -#endif }; TerrainWeight _t_weight(TerrainCoord terrain_coord) @@ -131,155 +121,41 @@ TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight { TerrainSample ts; -#if 0 -// This demonstrates the case when the bug occurs: Sampling in switch..case -#if 0 -#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) -#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) -#else // TODO: Remove debug -// Bug still occurs despite sampling the same texture three times from the same location -#define do_sample_x() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) -#define do_sample_y() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) -#endif -#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) -#if 0 - switch (tw.type) -#else // TODO: Remove debug -// Bug still occurs when the type is masked - switch (tw.type & (SAMPLE_X | SAMPLE_Y | SAMPLE_Z)) -#endif + // The switch..case is broken up into three parts deliberately. A single + // switch..case caused unexplained, "ant trail" seams in terrain. (as seen + // on Nvidia/Windows 10). The extra two branches are not free, but it's + // still a performance win compared to sampling along all three axes for + // every terrain fragment. + #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) + #define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) + #define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) + switch (tw.type & SAMPLE_X) { - case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): - ts.x = do_sample_x(); - ts.y = do_sample_y(); - ts.z = do_sample_z(); - break; - case (SAMPLE_X | SAMPLE_Y): - ts.x = do_sample_x(); - ts.y = do_sample_y(); - ts.z = ts.x; - break; - case (SAMPLE_X | SAMPLE_Z): - ts.x = do_sample_x(); - ts.z = do_sample_z(); - ts.y = ts.x; - break; - case (SAMPLE_Y | SAMPLE_Z): - ts.y = do_sample_y(); - ts.z = do_sample_z(); - ts.x = ts.y; - break; case SAMPLE_X: ts.x = do_sample_x(); - ts.y = ts.x; - ts.z = ts.x; - break; - case SAMPLE_Y: - ts.y = do_sample_y(); - ts.x = ts.y; - ts.z = ts.y; - break; - case SAMPLE_Z: - ts.z = do_sample_z(); - ts.x = ts.z; - ts.y = ts.z; - break; + break; default: ts.x = vec4(1.0, 0.0, 1.0, 1.0); - ts.y = ts.x; - ts.z = ts.x; - break; + break; } -#else -#if 0 // TODO: Remove debug -// This demonstrates the case when the bug does not occur: Sampling beforehand and assigning in switch..case -// This otherwise uses the same logic as in the case that reproduces the bug. -#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) -#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) -#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) - vec4 x = do_sample_x(); - vec4 y = do_sample_y(); - vec4 z = do_sample_z(); - switch (tw.type) + switch (tw.type & SAMPLE_Y) { - case (SAMPLE_X | SAMPLE_Y | SAMPLE_Z): - ts.x = x; - ts.y = y; - ts.z = z; - break; - case (SAMPLE_X | SAMPLE_Y): - ts.x = x; - ts.y = y; - ts.z = ts.x; - break; - case (SAMPLE_X | SAMPLE_Z): - ts.x = x; - ts.z = z; - ts.y = ts.x; - break; - case (SAMPLE_Y | SAMPLE_Z): - ts.y = y; - ts.z = z; - ts.x = ts.y; - break; - case SAMPLE_X: - ts.x = x; - ts.y = ts.x; - ts.z = ts.x; - break; case SAMPLE_Y: - ts.y = y; - ts.x = ts.y; - ts.z = ts.y; - break; + ts.y = do_sample_y(); + break; + default: + ts.y = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tw.type & SAMPLE_Z) + { case SAMPLE_Z: - ts.z = z; - ts.x = ts.z; - ts.y = ts.z; - break; + ts.z = do_sample_z(); + break; default: - ts.x = vec4(1.0, 0.0, 1.0, 1.0); - ts.y = ts.x; - ts.z = ts.x; - break; + ts.z = vec4(1.0, 0.0, 1.0, 1.0); + break; } -#else // TODO: Keep? -// Test case where the switch..case is broken up into three parts -// This fixes unexplained, "ant trail" seams in terrain. (as seen on Nvidia/Windows 10) -// The extra two branches are not free, but it's still a performance win -// compared to sampling along all three axes for every terrain fragment. -#define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) -#define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) -#define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) -switch (tw.type & SAMPLE_X) -{ - case SAMPLE_X: - ts.x = do_sample_x(); - break; - default: - ts.x = vec4(1.0, 0.0, 1.0, 1.0); - break; -} -switch (tw.type & SAMPLE_Y) -{ - case SAMPLE_Y: - ts.y = do_sample_y(); - break; - default: - ts.y = vec4(1.0, 0.0, 1.0, 1.0); - break; -} -switch (tw.type & SAMPLE_Z) -{ - case SAMPLE_Z: - ts.z = do_sample_z(); - break; - default: - ts.z = vec4(1.0, 0.0, 1.0, 1.0); - break; -} -#endif -#endif return ts; } @@ -357,17 +233,7 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); -#if 1 return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); -#else // TODO: Remove debug - //return vec4(vec3(isnan(ts.x)), 1.0); - //return ts.x; -#if 0 - return vec4(1.0+sign(vary_vertex_normal)/2.0, 1.0); -#else - return vec4(isnan(tw.weight_signed), 1.0); -#endif -#endif } #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 -- cgit v1.2.3 From b1a3a274ffe539ea61d9fd7aa6f95f44049964e2 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:18 -0700 Subject: DRTVWR-592: Don't read UVs for PBR terrain in single-plane case - works out to be more expensive than triplanar in some cases, and UVs are already trivial --- indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 2df5faf037..64ab3bbb13 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -84,7 +84,7 @@ void main() // (-x)z vary_coords[1].xy = texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform, texture_matrix0); #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 - vary_texcoord0.xy = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); + vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0); #endif vec4 tc = vec4(texcoord1,0,1); -- cgit v1.2.3 From 6e949e5d63c56a899b6a7745fcca04e0cd2f9639 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:24 -0700 Subject: DRTVWR-592: Remove shader cruft --- .../app_settings/shaders/class1/deferred/pbrterrainV.glsl | 1 - indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl | 9 +++------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 64ab3bbb13..dbb9404219 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -31,7 +31,6 @@ in vec3 position; in vec3 normal; in vec4 tangent; in vec4 diffuse_color; -in vec2 texcoord0; in vec2 texcoord1; #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index f6d3b59e85..33a78fd26d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -30,7 +30,6 @@ uniform mat4 modelview_projection_matrix; in vec3 position; in vec3 normal; in vec4 diffuse_color; -in vec2 texcoord0; in vec2 texcoord1; out vec3 pos; @@ -41,18 +40,16 @@ out vec4 vary_texcoord1; uniform vec4 object_plane_s; uniform vec4 object_plane_t; -vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) +vec2 texgen_object(vec4 vpos, mat4 mat, vec4 tp0, vec4 tp1) { vec4 tcoord; tcoord.x = dot(vpos, tp0); tcoord.y = dot(vpos, tp1); - tcoord.z = tc.z; - tcoord.w = tc.w; tcoord = mat * tcoord; - return tcoord; + return tcoord.xy; } void main() @@ -67,7 +64,7 @@ void main() vary_normal = normalize(normal_matrix * normal); // Transform and pass tex coords - vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy; + vary_texcoord0.xy = texgen_object(vec4(position, 1.0), texture_matrix0, object_plane_s, object_plane_t); vec4 t = vec4(texcoord1,0,1); -- cgit v1.2.3 From 1d885181d850388feb89c92a018cb591b5cc7f18 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:29 -0700 Subject: DRTVWR-592: (WIP) (has debug) Apply triplanar optimization technique to PBR material sampling. Use slightly different alpha ramp to hide unused materials --- .../shaders/class1/deferred/pbrterrainF.glsl | 61 ++++- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 288 +++++++++++++++++---- 2 files changed, 301 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 7febbe280e..7b5eba14b7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -82,6 +82,19 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, Terrain vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +#if 1 // TODO: Remove +#define TERRAIN_DEBUG 1 // TODO: Remove debug +struct TerrainMix +{ + vec4 weight; + int type; +#if TERRAIN_DEBUG + ivec4 usage; +#endif +}; +TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal); +#endif + void main() { @@ -125,16 +138,60 @@ void main() // from mikktspace.com vec3 vNt = sample_and_mix_normal(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); - float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; - vec3 vB = sign * cross(vN, vT); + vec3 vB = vary_sign * cross(vN, vT); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); tnorm *= gl_FrontFacing ? 1.0 : -1.0; +#if 0 // TODO: Remove (terrain weights visualization) + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); +#if 1 + // Show full usage and weights + float uw = 0.3; +#if 1 +#if 0 + vec4 mix_usage = vec4(tm.usage); +#else + vec4 mix_usage = vec4(tm.weight); +#endif +#else + // Version with easier-to-see boundaries of weights vs usage + vec4 mix_usage = mix(vec4(tm.usage), + mix(max(vec4(0.0), sign(tm.weight - 0.01)), + max(vec4(0.0), sign(tm.weight - 0.005)), + 0.5), + uw); +#endif + col.xyz = mix_usage.xyz; + col.x = max(col.x, mix_usage.w); + //col.y = 0.0; + //col.z = 0.0; +#else + // Show places where weight > usage + tolerance + float tolerance = 0.005; + vec4 weight_gt_usage = sign( + max( + vec4(0.0), + (tm.weight - (vec4(tm.usage) + vec4(tolerance))) + ) + ); + col.xyz = weight_gt_usage.xyz; + col.x = max(col.x, weight_gt_usage.w); +#endif +#endif +#if 0 // TODO: Remove (material channel discriminator) + //col.rgb = vec3(0.0, 1.0, 0.0); + //col.rgb = spec.rgb; + //col.rgb = (vNt + 1.0) / 2.0; + col.rgb = (tnorm + 1.0) / 2.0; + spec.rgb = vec3(1.0, 1.0, 0.0); + tnorm = vary_normal; + emissive = vec3(0); +#endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index e2d6cdb2d6..59b273afc3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -49,11 +49,62 @@ in vec3 vary_vertex_normal; vec3 srgb_to_linear(vec3 c); +// A relatively agressive threshold ensures that only one or two materials are used in most places +#define TERRAIN_RAMP_MIX_THRESHOLD 0.1 + +#define MIX_X 1 << 3 +#define MIX_Y 1 << 2 +#define MIX_Z 1 << 1 +#define MIX_W 1 << 0 + +#define TERRAIN_DEBUG 1 // TODO: Remove debug +struct TerrainMix +{ + vec4 weight; + int type; +#if TERRAIN_DEBUG + ivec4 usage; +#endif +}; + +#define TerrainMixSample vec4[4] +#define TerrainMixSample3 vec3[4] + +TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal) +{ + TerrainMix tm; + vec4 sample_x = vec4(1,0,0,0); + vec4 sample_y = vec4(0,1,0,0); + vec4 sample_z = vec4(0,0,1,0); + vec4 sample_w = vec4(0,0,0,1); + + tm.weight = mix( mix(sample_w, sample_z, alpha2), mix(sample_y, sample_x, alpha1), alphaFinal ); + tm.weight -= TERRAIN_RAMP_MIX_THRESHOLD; + ivec4 usage = max(ivec4(0), ivec4(ceil(tm.weight))); + // Prevent negative weights and keep weights balanced + tm.weight = normalize(tm.weight*vec4(usage)); + + tm.type = (usage.x * MIX_X) | + (usage.y * MIX_Y) | + (usage.z * MIX_Z) | + (usage.w * MIX_W); +#if TERRAIN_DEBUG // TODO: Remove debug + tm.usage = usage; +#endif + return tm; +} + float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { - return mix( mix(samples.w, samples.z, alpha2), mix(samples.y, samples.x, alpha1), alphaFinal ); + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + // Assume weights are normalized + return tm.weight.x * samples.x + + tm.weight.y * samples.y + + tm.weight.z * samples.z + + tm.weight.w * samples.w; } +#if 0 // TODO: Decide if still needed, and if so, use _t_mix internally for weights vec3 terrain_mix(vec3[4] samples, float alpha1, float alpha2, float alphaFinal) { return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); @@ -63,6 +114,25 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) { return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); } +#endif + +vec4 terrain_mix(TerrainMix tm, TerrainMixSample tms) +{ + // Assume weights are normalized + return tm.weight.x * tms[0] + + tm.weight.y * tms[1] + + tm.weight.z * tms[2] + + tm.weight.w * tms[3]; +} + +vec3 terrain_mix(TerrainMix tm, TerrainMixSample3 tms3) +{ + // Assume weights are normalized + return tm.weight.x * tms3[0] + + tm.weight.y * tms3[1] + + tm.weight.z * tms3[2] + + tm.weight.w * tms3[3]; +} #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 // Triplanar mapping @@ -98,15 +168,12 @@ TerrainWeight _t_weight(TerrainCoord terrain_coord) vec3 weight_signed = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); weight_signed -= vec3(threshold); TerrainWeight tw; - tw.weight = max(vec3(0), weight_signed); + // *NOTE: Make sure the threshold doesn't affect the materials + tw.weight = normalize(max(vec3(0), weight_signed)); ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed)))); tw.type = ((usage.x) * SAMPLE_X) | ((usage.y) * SAMPLE_Y) | ((usage.z) * SAMPLE_Z); -#if TERRAIN_DEBUG - tw.weight_signed = weight_signed; - tw.usage = usage; -#endif return tw; } @@ -256,59 +323,188 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) } #endif +// The goal of _tmix_sample and related functions is to only sample textures when necessary, ignoring if the weights are low. +// *TODO: Currently, there is much more switch..case branching than needed. This could be simplified by branching per-material rather than per-texture. + +TerrainMixSample _tmix_sample(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + TerrainMixSample tms; + + switch (tm.type & MIX_X) + { + case MIX_X: + tms[0] = terrain_texture(tex0, texcoord); + break; + default: + tms[0] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_Y) + { + case MIX_Y: + tms[1] = terrain_texture(tex1, texcoord); + break; + default: + tms[1] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_Z) + { + case MIX_Z: + tms[2] = terrain_texture(tex2, texcoord); + break; + default: + tms[2] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_W) + { + case MIX_W: + tms[3] = terrain_texture(tex3, texcoord); + break; + default: + tms[3] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + + return tms; +} + +TerrainMixSample _tmix_sample_color(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + TerrainMixSample tmix; + + switch (tm.type & MIX_X) + { + case MIX_X: + tmix[0] = terrain_texture_color(tex0, texcoord); + break; + default: + tmix[0] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_Y) + { + case MIX_Y: + tmix[1] = terrain_texture_color(tex1, texcoord); + break; + default: + tmix[1] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_Z) + { + case MIX_Z: + tmix[2] = terrain_texture_color(tex2, texcoord); + break; + default: + tmix[2] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + switch (tm.type & MIX_W) + { + case MIX_W: + tmix[3] = terrain_texture_color(tex3, texcoord); + break; + default: + tmix[3] = vec4(1.0, 0.0, 1.0, 1.0); + break; + } + + return tmix; +} + +TerrainMixSample3 _tmix_sample_normal(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) +{ + TerrainMixSample3 tmix3; + + switch (tm.type & MIX_X) + { + case MIX_X: + tmix3[0] = terrain_texture_normal(tex0, texcoord); + break; + default: + tmix3[0] = vec3(1.0, 0.0, 1.0); + break; + } + switch (tm.type & MIX_Y) + { + case MIX_Y: + tmix3[1] = terrain_texture_normal(tex1, texcoord); + break; + default: + tmix3[1] = vec3(1.0, 0.0, 1.0); + break; + } + switch (tm.type & MIX_Z) + { + case MIX_Z: + tmix3[2] = terrain_texture_normal(tex2, texcoord); + break; + default: + tmix3[2] = vec3(1.0, 0.0, 1.0); + break; + } + switch (tm.type & MIX_W) + { + case MIX_W: + tmix3[3] = terrain_texture_normal(tex3, texcoord); + break; + default: + tmix3[3] = vec3(1.0, 0.0, 1.0); + break; + } + + return tmix3; +} + vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec3[4] samples; - samples[0] = terrain_texture(tex0, texcoord).xyz; - samples[1] = terrain_texture(tex1, texcoord).xyz; - samples[2] = terrain_texture(tex2, texcoord).xyz; - samples[3] = terrain_texture(tex3, texcoord).xyz; - samples[0] = srgb_to_linear(samples[0]); - samples[1] = srgb_to_linear(samples[1]); - samples[2] = srgb_to_linear(samples[2]); - samples[3] = srgb_to_linear(samples[3]); - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); + vec3[4] tms3; + tms3[0] = tms[0].xyz; + tms3[1] = tms[1].xyz; + tms3[2] = tms[2].xyz; + tms3[3] = tms[3].xyz; + tms3[0] *= factors[0]; + tms3[1] *= factors[1]; + tms3[2] *= factors[2]; + tms3[3] *= factors[3]; + return terrain_mix(tm, tms3); } vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec4[4] samples; - samples[0] = terrain_texture_color(tex0, texcoord); - samples[1] = terrain_texture_color(tex1, texcoord); - samples[2] = terrain_texture_color(tex2, texcoord); - samples[3] = terrain_texture_color(tex3, texcoord); - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); + tms[0] *= factors[0]; + tms[1] *= factors[1]; + tms[2] *= factors[2]; + tms[3] *= factors[3]; + return terrain_mix(tm, tms); } vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec3[4] samples; - samples[0] = terrain_texture(tex0, texcoord).xyz; - samples[1] = terrain_texture(tex1, texcoord).xyz; - samples[2] = terrain_texture(tex2, texcoord).xyz; - samples[3] = terrain_texture(tex3, texcoord).xyz; - samples[0] *= factors[0]; - samples[1] *= factors[1]; - samples[2] *= factors[2]; - samples[3] *= factors[3]; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMixSample tms = _tmix_sample(tm, texcoord, tex0, tex1, tex2, tex3); + vec3[4] tms3; + tms3[0] = tms[0].xyz; + tms3[1] = tms[1].xyz; + tms3[2] = tms[2].xyz; + tms3[3] = tms[3].xyz; + tms3[0] *= factors[0]; + tms3[1] *= factors[1]; + tms3[2] *= factors[2]; + tms3[3] *= factors[3]; + return terrain_mix(tm, tms3); } // Returns the unpacked normal texture in range [-1, 1] vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - vec3[4] samples; - samples[0] = terrain_texture_normal(tex0, texcoord).xyz; - samples[1] = terrain_texture_normal(tex1, texcoord).xyz; - samples[2] = terrain_texture_normal(tex2, texcoord).xyz; - samples[3] = terrain_texture_normal(tex3, texcoord).xyz; - return terrain_mix(samples, alpha1, alpha2, alphaFinal); + TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMixSample3 tms3 = _tmix_sample_normal(tm, texcoord, tex0, tex1, tex2, tex3); + return terrain_mix(tm, tms3); } -- cgit v1.2.3 From 86f0c9faa83ce4917ce7820a3295b39369d994ee Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:35 -0700 Subject: DRTVWR-592: (WIP) (has debug) Fix PBR terrain material mixing and triplanar mapping using wrong mix, causing bright spots --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 59b273afc3..13f3934689 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -82,7 +82,8 @@ TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal) tm.weight -= TERRAIN_RAMP_MIX_THRESHOLD; ivec4 usage = max(ivec4(0), ivec4(ceil(tm.weight))); // Prevent negative weights and keep weights balanced - tm.weight = normalize(tm.weight*vec4(usage)); + tm.weight = tm.weight*vec4(usage); + tm.weight /= (tm.weight.x + tm.weight.y + tm.weight.z + tm.weight.w); tm.type = (usage.x * MIX_X) | (usage.y * MIX_Y) | @@ -97,7 +98,7 @@ TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal) float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); - // Assume weights are normalized + // Assume weights add to 1 return tm.weight.x * samples.x + tm.weight.y * samples.y + tm.weight.z * samples.z + @@ -118,7 +119,7 @@ vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) vec4 terrain_mix(TerrainMix tm, TerrainMixSample tms) { - // Assume weights are normalized + // Assume weights add to 1 return tm.weight.x * tms[0] + tm.weight.y * tms[1] + tm.weight.z * tms[2] + @@ -127,7 +128,7 @@ vec4 terrain_mix(TerrainMix tm, TerrainMixSample tms) vec3 terrain_mix(TerrainMix tm, TerrainMixSample3 tms3) { - // Assume weights are normalized + // Assume weights add to 1 return tm.weight.x * tms3[0] + tm.weight.y * tms3[1] + tm.weight.z * tms3[2] + @@ -165,11 +166,13 @@ TerrainWeight _t_weight(TerrainCoord terrain_coord) { float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; - vec3 weight_signed = normalize(pow(abs(vary_vertex_normal), vec3(sharpness))); + vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness)); + weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z); weight_signed -= vec3(threshold); TerrainWeight tw; // *NOTE: Make sure the threshold doesn't affect the materials - tw.weight = normalize(max(vec3(0), weight_signed)); + tw.weight = max(vec3(0), weight_signed); + tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z); ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed)))); tw.type = ((usage.x) * SAMPLE_X) | ((usage.y) * SAMPLE_Y) | -- cgit v1.2.3 From 00d56e2607a671b9478bf06b7df808b2f4141395 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:39 -0700 Subject: DRTVWR-592: Disable (but do not remove) shader debug --- .../shaders/class1/deferred/pbrterrainF.glsl | 9 ++++++--- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 16 +++------------- 2 files changed, 9 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 7b5eba14b7..f788b46aa7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -82,7 +82,7 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, Terrain vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -#if 1 // TODO: Remove +#if 0 // TODO: Remove #define TERRAIN_DEBUG 1 // TODO: Remove debug struct TerrainMix { @@ -147,6 +147,7 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; +#if TERRAIN_DEBUG // TODO: Remove #if 0 // TODO: Remove (terrain weights visualization) TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); #if 1 @@ -187,10 +188,12 @@ void main() //col.rgb = vec3(0.0, 1.0, 0.0); //col.rgb = spec.rgb; //col.rgb = (vNt + 1.0) / 2.0; - col.rgb = (tnorm + 1.0) / 2.0; - spec.rgb = vec3(1.0, 1.0, 0.0); + //col.rgb = (tnorm + 1.0) / 2.0; + //spec.rgb = vec3(1.0, 1.0, 0.0); + col.rgb = spec.rgb; tnorm = vary_normal; emissive = vec3(0); +#endif #endif frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 13f3934689..9d1990bd4a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -57,7 +57,9 @@ vec3 srgb_to_linear(vec3 c); #define MIX_Z 1 << 1 #define MIX_W 1 << 0 -#define TERRAIN_DEBUG 1 // TODO: Remove debug +#if 0 // TODO: Remove debug +#define TERRAIN_DEBUG 1 +#endif struct TerrainMix { vec4 weight; @@ -105,18 +107,6 @@ float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) tm.weight.w * samples.w; } -#if 0 // TODO: Decide if still needed, and if so, use _t_mix internally for weights -vec3 terrain_mix(vec3[4] samples, float alpha1, float alpha2, float alphaFinal) -{ - return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); -} - -vec4 terrain_mix(vec4[4] samples, float alpha1, float alpha2, float alphaFinal) -{ - return mix( mix(samples[3], samples[2], alpha2), mix(samples[1], samples[0], alpha1), alphaFinal ); -} -#endif - vec4 terrain_mix(TerrainMix tm, TerrainMixSample tms) { // Assume weights add to 1 -- cgit v1.2.3 From b163f72ecc2ebdb553b312e5e399d103f00eaf34 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:44 -0700 Subject: DRTVWR-592: (WIP) (has debug) Add new functions for mixing PBR materials. Not yet used. --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 286 ++++++++++++++++++--- 1 file changed, 252 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 9d1990bd4a..a8d8b1a91d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -44,18 +44,99 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#define TERRAIN_PBR_DETAIL_EMISSIVE 0 in vec3 vary_vertex_normal; vec3 srgb_to_linear(vec3 c); -// A relatively agressive threshold ensures that only one or two materials are used in most places +// A relatively agressive threshold for terrain material mixing sampling +// cutoff. This ensures that only one or two materials are used in most places, +// making PBR terrain blending more performant. Should be greater than 0 to work. #define TERRAIN_RAMP_MIX_THRESHOLD 0.1 +// A small threshold for triplanar mapping sampling cutoff. This and +// TERRAIN_TRIPLANAR_BLEND_FACTOR together ensures that only one or two samples +// per texture are used in most places, making triplanar mapping more +// performant. Should be greater than 0 to work. +// There's also an artistic design choice in the use of these factors, and the +// use of triplanar generally. Don't take these triplanar constants for granted. +#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 + +#define SAMPLE_X 1 << 0 +#define SAMPLE_Y 1 << 1 +#define SAMPLE_Z 1 << 2 +#define MIX_X 1 << 3 +#define MIX_Y 1 << 4 +#define MIX_Z 1 << 5 +#define MIX_W 1 << 6 + +struct PBRMix +{ + vec4 col; // RGB color with alpha, linear space + vec3 orm; // Occlusion, roughness, metallic + vec3 vNt; // Unpacked normal texture sample, vector +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + vec3 emissive; // RGB emissive color, linear space +#endif +}; -#define MIX_X 1 << 3 -#define MIX_Y 1 << 2 -#define MIX_Z 1 << 1 -#define MIX_W 1 << 0 +PBRMix init_pbr_mix() +{ + PBRMix mix; + mix.col = vec4(0); + mix.orm = vec3(0); + mix.vNt = vec3(0); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + mix.emissive = vec3(0); +#endif + return mix; +} + +// Usage example, for two weights: +// vec2 weights = ... // Weights must add up to 1 +// PBRMix mix = init_pbr_mix(); +// PBRMix mix1 = ... +// mix = mix_pbr(mix, mix1, weights.x); +// PBRMix mix2 = ... +// mix = mix_pbr(mix, mix2, weights.y); +PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight) +{ + PBRMix mix; + mix.col = mix1.col + (mix2.col * mix2_weight); + mix.orm = mix1.orm + (mix2.orm * mix2_weight); + mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + mix.emissive = mix1.emissive + (mix2.emissive * mix2_weight); +#endif + return mix; +} + +PBRMix sample_pbr( + vec2 uv + , sampler2D tex_col + , sampler2D tex_orm + , sampler2D tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , sampler2D tex_emissive +#endif + ) +{ + PBRMix mix; + mix.col = texture(tex_col, uv); + mix.col.rgb = srgb_to_linear(mix.col.rgb); + mix.orm = texture(tex_orm, uv).xyz; + mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + mix.emissive = srgb_to_linear(texture(tex_emissive, uv).xyz); +#endif + return mix; +} + +struct TerrainTriplanar +{ + vec3 weight; + int type; +}; #if 0 // TODO: Remove debug #define TERRAIN_DEBUG 1 @@ -97,6 +178,24 @@ TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal) return tm; } +TerrainTriplanar _t_triplanar() +{ + float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; + float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; + vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness)); + weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z); + weight_signed -= vec3(threshold); + TerrainTriplanar tw; + // *NOTE: Make sure the threshold doesn't affect the materials + tw.weight = max(vec3(0), weight_signed); + tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z); + ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed)))); + tw.type = ((usage.x) * SAMPLE_X) | + ((usage.y) * SAMPLE_Y) | + ((usage.z) * SAMPLE_Z); + return tw; +} + float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); @@ -130,7 +229,6 @@ vec3 terrain_mix(TerrainMix tm, TerrainMixSample3 tms3) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] -#define TERRAIN_TRIPLANAR_MIX_THRESHOLD 0.01 vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) { @@ -143,31 +241,50 @@ vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) return texture(tex, uv); } -#define SAMPLE_X 1 << 2 -#define SAMPLE_Y 1 << 1 -#define SAMPLE_Z 1 << 0 -struct TerrainWeight +vec2 _t_uv(vec2 uv_unflipped, float sign_or_zero) { - vec3 weight; - int type; -}; + // Handle case where sign is 0 + float sign = (2.0*sign_or_zero) + 1.0; + sign /= abs(sign); + // If the vertex normal is negative, flip the texture back + // right-side up. + vec2 uv = uv_unflipped * vec2(sign, 1); + return uv; +} -TerrainWeight _t_weight(TerrainCoord terrain_coord) +vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero) { - float sharpness = TERRAIN_TRIPLANAR_BLEND_FACTOR; - float threshold = TERRAIN_TRIPLANAR_MIX_THRESHOLD; - vec3 weight_signed = pow(abs(vary_vertex_normal), vec3(sharpness)); - weight_signed /= (weight_signed.x + weight_signed.y + weight_signed.z); - weight_signed -= vec3(threshold); - TerrainWeight tw; - // *NOTE: Make sure the threshold doesn't affect the materials - tw.weight = max(vec3(0), weight_signed); - tw.weight /= (tw.weight.x + tw.weight.y + tw.weight.z); - ivec3 usage = ivec3(round(max(vec3(0), sign(weight_signed)))); - tw.type = ((usage.x) * SAMPLE_X) | - ((usage.y) * SAMPLE_Y) | - ((usage.z) * SAMPLE_Z); - return tw; + // Assume normal is unpacked + vec3 vNt1 = vNt0; + // Get sign + float sign = sign_or_zero; + // Handle case where sign is 0 + sign = (2.0*sign) + 1.0; + sign /= abs(sign); + // If the sign is negative, rotate normal by 180 degrees + vNt1.xy = (min(0, sign) * vNt1.xy) + (min(0, -sign) * -vNt1.xy); + return vNt1; +} + +// Triplanar-specific normal texture fixes +vec3 _t_normal_post_x(vec3 vNt0) +{ + vec3 vNt_x = _t_normal_post_1(vNt0, sign(vary_vertex_normal.x)); + // *HACK: Transform normals according to orientation of the UVs + vNt_x.xy = vec2(-vNt_x.y, vNt_x.x); + return vNt_x; +} +vec3 _t_normal_post_y(vec3 vNt0) +{ + vec3 vNt_y = _t_normal_post_1(vNt0, sign(vary_vertex_normal.y)); + // *HACK: Transform normals according to orientation of the UVs + vNt_y.xy = -vNt_y.xy; + return vNt_y; +} +vec3 _t_normal_post_z(vec3 vNt0) +{ + vec3 vNt_z = _t_normal_post_1(vNt0, sign(vary_vertex_normal.z)); + return vNt_z; } struct TerrainSample @@ -177,7 +294,7 @@ struct TerrainSample vec4 z; }; -TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) { TerrainSample ts; @@ -227,7 +344,7 @@ struct TerrainSampleNormal vec3 z; }; -TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) { TerrainSample ts = _t_sample(tex, terrain_coord, tw); TerrainSampleNormal tsn; @@ -250,7 +367,7 @@ TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, Terra return tsn; } -TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainWeight tw) +TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) { TerrainSample ts = _t_sample(tex, terrain_coord, tw); ts.x.xyz = srgb_to_linear(ts.x.xyz); @@ -262,7 +379,7 @@ TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainWeig // Triplanar sampling of things that are neither colors nor normals (i.e. orm) vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) { - TerrainWeight tw = _t_weight(terrain_coord); + TerrainTriplanar tw = _t_triplanar(); TerrainSample ts = _t_sample(tex, terrain_coord, tw); @@ -279,7 +396,7 @@ vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) // *NOTE: Bottom face has not been tested vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) { - TerrainWeight tw = _t_weight(terrain_coord); + TerrainTriplanar tw = _t_triplanar(); TerrainSampleNormal ts = _t_sample_n(tex, terrain_coord, tw); @@ -289,13 +406,92 @@ vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) // Triplanar sampling of colors. Colors are converted to linear space before blending. vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) { - TerrainWeight tw = _t_weight(terrain_coord); + TerrainTriplanar tw = _t_triplanar(); TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); } +PBRMix terrain_sample_pbr( + TerrainCoord terrain_coord + , TerrainTriplanar tw + , sampler2D tex_col + , sampler2D tex_orm + , sampler2D tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , sampler2D tex_emissive +#endif + ) +{ + PBRMix mix = init_pbr_mix(); + + #define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x)) + #define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y)) + #define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z)) + switch (tw.type & SAMPLE_X) + { + case SAMPLE_X: + PBRMix mix_x = sample_pbr( + get_uv_x() + , tex_col + , tex_orm + , tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , tex_emissive +#endif + ); + // Triplanar-specific normal texture fix + mix_x.vNt = _t_normal_post_x(mix_x.vNt); + mix = mix_pbr(mix, mix_x, tw.weight.x); + break; + default: + break; + } + + switch (tw.type & SAMPLE_Y) + { + case SAMPLE_Y: + PBRMix mix_y = sample_pbr( + get_uv_y() + , tex_col + , tex_orm + , tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , tex_emissive +#endif + ); + // Triplanar-specific normal texture fix + mix_y.vNt = _t_normal_post_y(mix_y.vNt); + mix = mix_pbr(mix, mix_y, tw.weight.y); + break; + default: + break; + } + + switch (tw.type & SAMPLE_Z) + { + case SAMPLE_Z: + PBRMix mix_z = sample_pbr( + get_uv_z() + , tex_col + , tex_orm + , tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , tex_emissive +#endif + ); + // Triplanar-specific normal texture fix + mix_z.vNt = _t_normal_post_z(mix_z.vNt); + mix = mix_pbr(mix, mix_z, tw.weight.z); + break; + default: + break; + } + + return mix; +} + #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 #define TerrainCoord vec2 vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) @@ -314,6 +510,28 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) col.xyz = srgb_to_linear(col.xyz); return col; } + +// TODO: Implement this for the more complex triplanar case +PBRMix terrain_sample_pbr( + TerrainCoord terrain_coord + , sampler2D tex_col + , sampler2D tex_orm + , sampler2D tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , sampler2D tex_emissive +#endif + ) +{ + return sample_pbr( + terrain_coord + , tex_col + , tex_orm + , tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , tex_emissive +#endif + ); +} #endif // The goal of _tmix_sample and related functions is to only sample textures when necessary, ignoring if the weights are low. -- cgit v1.2.3 From b162ff3cae482a443f93d818125f6e22d647451f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:50 -0700 Subject: DRTVWR-592: Implement reduced branching terrain shader --- .../shaders/class1/deferred/pbrterrainF.glsl | 207 ++++++++++++--------- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 70 ++++++- 2 files changed, 186 insertions(+), 91 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index f788b46aa7..22071421de 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -31,6 +31,52 @@ #define TerrainCoord vec2 #endif +#if 0 // TODO: Remove debug +#define TERRAIN_DEBUG 1 +#endif + +// TODO: Decide if this struct needs to be declared +struct TerrainMix +{ + vec4 weight; + int type; +#if TERRAIN_DEBUG + ivec4 usage; +#endif +}; + +TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal); + +// TODO: Decide if this struct needs to be declared +struct PBRMix +{ + vec4 col; // RGB color with alpha, linear space + vec3 orm; // Occlusion, roughness, metallic + vec3 vNt; // Unpacked normal texture sample, vector +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + vec3 emissive; // RGB emissive color, linear space +#endif +}; + +PBRMix init_pbr_mix(); + +PBRMix terrain_sample_and_multiply_pbr( + TerrainCoord terrain_coord + , sampler2D tex_col + , sampler2D tex_orm + , sampler2D tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , sampler2D tex_emissive +#endif + , vec4 factor_col + , vec3 factor_orm +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , vec3 factor_emissive +#endif + ); + +PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight); + out vec4 frag_data[4]; uniform sampler2D alpha_ramp; @@ -82,19 +128,6 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, Terrain vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -#if 0 // TODO: Remove -#define TERRAIN_DEBUG 1 // TODO: Remove debug -struct TerrainMix -{ - vec4 weight; - int type; -#if TERRAIN_DEBUG - ivec4 usage; -#endif -}; -TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal); -#endif - void main() { @@ -108,36 +141,91 @@ void main() float alpha2 = texture(alpha_ramp,vary_texcoord1.xy).a; float alphaFinal = texture(alpha_ramp, vary_texcoord1.zw).a; - vec4 col = sample_and_mix_color4(alpha1, alpha2, alphaFinal, terrain_texcoord, baseColorFactors, detail_0_base_color, detail_1_base_color, detail_2_base_color, detail_3_base_color); - float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); - if (col.a < minimum_alpha) - { - discard; - } + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - - vec3[4] orm_factors; - orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x); - orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y); - orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z); - orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w); // RGB = Occlusion, Roughness, Metal // default values, see LLViewerTexture::sDefaultPBRORMImagep // occlusion 1.0 // roughness 0.0 // metal 0.0 - vec3 spec = sample_and_mix_vector3(alpha1, alpha2, alphaFinal, terrain_texcoord, orm_factors, detail_0_metallic_roughness, detail_1_metallic_roughness, detail_2_metallic_roughness, detail_3_metallic_roughness); + vec3[4] orm_factors; + orm_factors[0] = vec3(1.0, roughnessFactors.x, metallicFactors.x); + orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y); + orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z); + orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w); -#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - vec3 emissive = sample_and_mix_color3(alpha1, alpha2, alphaFinal, terrain_texcoord, emissiveColors, detail_0_emissive, detail_1_emissive, detail_2_emissive, detail_3_emissive); -#else - vec3 emissive = vec3(0); -#endif + PBRMix mix = init_pbr_mix(); + PBRMix mix2; + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_0_base_color + , detail_0_metallic_roughness + , detail_0_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_0_emissive + #endif + , baseColorFactors[0] + , orm_factors[0] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[0] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight[0]); + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_1_base_color + , detail_1_metallic_roughness + , detail_1_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_1_emissive + #endif + , baseColorFactors[1] + , orm_factors[1] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[1] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight[1]); + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_2_base_color + , detail_2_metallic_roughness + , detail_2_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_2_emissive + #endif + , baseColorFactors[2] + , orm_factors[2] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[2] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight[2]); + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_3_base_color + , detail_3_metallic_roughness + , detail_3_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_3_emissive + #endif + , baseColorFactors[3] + , orm_factors[3] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[3] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight[3]); + float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); + if (mix.col.a < minimum_alpha) + { + discard; + } float base_color_factor_alpha = terrain_mix(vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z), alpha1, alpha2, alphaFinal); // from mikktspace.com - vec3 vNt = sample_and_mix_normal(alpha1, alpha2, alphaFinal, terrain_texcoord, detail_0_normal, detail_1_normal, detail_2_normal, detail_3_normal); + vec3 vNt = mix.vNt; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; @@ -145,59 +233,10 @@ void main() vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); tnorm *= gl_FrontFacing ? 1.0 : -1.0; - -#if TERRAIN_DEBUG // TODO: Remove -#if 0 // TODO: Remove (terrain weights visualization) - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); -#if 1 - // Show full usage and weights - float uw = 0.3; -#if 1 -#if 0 - vec4 mix_usage = vec4(tm.usage); -#else - vec4 mix_usage = vec4(tm.weight); -#endif -#else - // Version with easier-to-see boundaries of weights vs usage - vec4 mix_usage = mix(vec4(tm.usage), - mix(max(vec4(0.0), sign(tm.weight - 0.01)), - max(vec4(0.0), sign(tm.weight - 0.005)), - 0.5), - uw); -#endif - col.xyz = mix_usage.xyz; - col.x = max(col.x, mix_usage.w); - //col.y = 0.0; - //col.z = 0.0; -#else - // Show places where weight > usage + tolerance - float tolerance = 0.005; - vec4 weight_gt_usage = sign( - max( - vec4(0.0), - (tm.weight - (vec4(tm.usage) + vec4(tolerance))) - ) - ); - col.xyz = weight_gt_usage.xyz; - col.x = max(col.x, weight_gt_usage.w); -#endif -#endif -#if 0 // TODO: Remove (material channel discriminator) - //col.rgb = vec3(0.0, 1.0, 0.0); - //col.rgb = spec.rgb; - //col.rgb = (vNt + 1.0) / 2.0; - //col.rgb = (tnorm + 1.0) / 2.0; - //spec.rgb = vec3(1.0, 1.0, 0.0); - col.rgb = spec.rgb; - tnorm = vary_normal; - emissive = vec3(0); -#endif -#endif - frag_data[0] = max(vec4(col.xyz, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(spec.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse + frag_data[1] = max(vec4(mix.orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags - frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive + frag_data[3] = max(vec4(mix.emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index a8d8b1a91d..a87927786c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -153,7 +153,7 @@ struct TerrainMix #define TerrainMixSample vec4[4] #define TerrainMixSample3 vec3[4] -TerrainMix _t_mix(float alpha1, float alpha2, float alphaFinal) +TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal) { TerrainMix tm; vec4 sample_x = vec4(1,0,0,0); @@ -198,7 +198,7 @@ TerrainTriplanar _t_triplanar() float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) { - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); // Assume weights add to 1 return tm.weight.x * samples.x + tm.weight.y * samples.y + @@ -511,7 +511,6 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) return col; } -// TODO: Implement this for the more complex triplanar case PBRMix terrain_sample_pbr( TerrainCoord terrain_coord , sampler2D tex_col @@ -671,7 +670,7 @@ TerrainMixSample3 _tmix_sample_normal(TerrainMix tm, TerrainCoord texcoord, samp vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); vec3[4] tms3; tms3[0] = tms[0].xyz; @@ -687,7 +686,7 @@ vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, Terrain vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); tms[0] *= factors[0]; tms[1] *= factors[1]; @@ -698,7 +697,7 @@ vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, Terrain vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); TerrainMixSample tms = _tmix_sample(tm, texcoord, tex0, tex1, tex2, tex3); vec3[4] tms3; tms3[0] = tms[0].xyz; @@ -715,7 +714,64 @@ vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, Terrai // Returns the unpacked normal texture in range [-1, 1] vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) { - TerrainMix tm = _t_mix(alpha1, alpha2, alphaFinal); + TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); TerrainMixSample3 tms3 = _tmix_sample_normal(tm, texcoord, tex0, tex1, tex2, tex3); return terrain_mix(tm, tms3); } + +PBRMix multiply_factors_pbr( + PBRMix mix_in + , vec4 factor_col + , vec3 factor_orm +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , vec3 factor_emissive +#endif + ) +{ + PBRMix mix = mix_in; + mix.col *= factor_col; + mix.orm *= factor_orm; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + mix.emissive *= factor_emissive; +#endif + return mix; +} + +PBRMix terrain_sample_and_multiply_pbr( + TerrainCoord terrain_coord + , sampler2D tex_col + , sampler2D tex_orm + , sampler2D tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , sampler2D tex_emissive +#endif + , vec4 factor_col + , vec3 factor_orm +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , vec3 factor_emissive +#endif + ) +{ + PBRMix mix = terrain_sample_pbr( + terrain_coord +#if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 + , _t_triplanar() +#endif + , tex_col + , tex_orm + , tex_vNt +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , tex_emissive +#endif + ); + + mix = multiply_factors_pbr(mix + , factor_col + , factor_orm +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , factor_emissive +#endif + ); + + return mix; +} -- cgit v1.2.3 From be38adebbe46d62bc07d504a70556062f4e55101 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:42:56 -0700 Subject: DRTVWR-592: Add missing branching for terrain sampling. Jury is still out on which version is faster --- .../shaders/class1/deferred/pbrterrainF.glsl | 154 +++++++++++++-------- 1 file changed, 94 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 22071421de..0a7c58451d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -31,6 +31,11 @@ #define TerrainCoord vec2 #endif +#define MIX_X 1 << 3 +#define MIX_Y 1 << 4 +#define MIX_Z 1 << 5 +#define MIX_W 1 << 6 + #if 0 // TODO: Remove debug #define TERRAIN_DEBUG 1 #endif @@ -123,6 +128,7 @@ in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal); +// TODO: Clean these up vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); @@ -156,66 +162,94 @@ void main() PBRMix mix = init_pbr_mix(); PBRMix mix2; - mix2 = terrain_sample_and_multiply_pbr( - terrain_texcoord - , detail_0_base_color - , detail_0_metallic_roughness - , detail_0_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , detail_0_emissive - #endif - , baseColorFactors[0] - , orm_factors[0] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , emissiveColors[0] - #endif - ); - mix = mix_pbr(mix, mix2, tm.weight[0]); - mix2 = terrain_sample_and_multiply_pbr( - terrain_texcoord - , detail_1_base_color - , detail_1_metallic_roughness - , detail_1_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , detail_1_emissive - #endif - , baseColorFactors[1] - , orm_factors[1] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , emissiveColors[1] - #endif - ); - mix = mix_pbr(mix, mix2, tm.weight[1]); - mix2 = terrain_sample_and_multiply_pbr( - terrain_texcoord - , detail_2_base_color - , detail_2_metallic_roughness - , detail_2_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , detail_2_emissive - #endif - , baseColorFactors[2] - , orm_factors[2] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , emissiveColors[2] - #endif - ); - mix = mix_pbr(mix, mix2, tm.weight[2]); - mix2 = terrain_sample_and_multiply_pbr( - terrain_texcoord - , detail_3_base_color - , detail_3_metallic_roughness - , detail_3_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , detail_3_emissive - #endif - , baseColorFactors[3] - , orm_factors[3] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , emissiveColors[3] - #endif - ); - mix = mix_pbr(mix, mix2, tm.weight[3]); + switch (tm.type & MIX_X) + { + case MIX_X: + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_0_base_color + , detail_0_metallic_roughness + , detail_0_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_0_emissive + #endif + , baseColorFactors[0] + , orm_factors[0] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[0] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight.x); + break; + default: + break; + } + switch (tm.type & MIX_Y) + { + case MIX_Y: + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_1_base_color + , detail_1_metallic_roughness + , detail_1_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_1_emissive + #endif + , baseColorFactors[1] + , orm_factors[1] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[1] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight.y); + break; + default: + break; + } + switch (tm.type & MIX_Z) + { + case MIX_Z: + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_2_base_color + , detail_2_metallic_roughness + , detail_2_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_2_emissive + #endif + , baseColorFactors[2] + , orm_factors[2] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[2] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight.z); + break; + default: + break; + } + switch (tm.type & MIX_W) + { + case MIX_W: + mix2 = terrain_sample_and_multiply_pbr( + terrain_texcoord + , detail_3_base_color + , detail_3_metallic_roughness + , detail_3_normal + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , detail_3_emissive + #endif + , baseColorFactors[3] + , orm_factors[3] + #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) + , emissiveColors[3] + #endif + ); + mix = mix_pbr(mix, mix2, tm.weight.w); + break; + default: + break; + } float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); if (mix.col.a < minimum_alpha) -- cgit v1.2.3 From f9bd70efc9ab25dfc1ab0b9aa10d16aec271410b Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:43:02 -0700 Subject: DRTVWR-592: Fix non-triplanar being slower somehow in some cases. --- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index a87927786c..078c753a35 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -511,26 +511,8 @@ vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) return col; } -PBRMix terrain_sample_pbr( - TerrainCoord terrain_coord - , sampler2D tex_col - , sampler2D tex_orm - , sampler2D tex_vNt -#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , sampler2D tex_emissive -#endif - ) -{ - return sample_pbr( - terrain_coord - , tex_col - , tex_orm - , tex_vNt -#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) - , tex_emissive -#endif - ); -} +#define terrain_sample_pbr sample_pbr + #endif // The goal of _tmix_sample and related functions is to only sample textures when necessary, ignoring if the weights are low. -- cgit v1.2.3 From f3c98a548a688199114763cfc4eb90bb3d2fbd5c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:43:08 -0700 Subject: DRTVWR-592: Clean up --- .../shaders/class1/deferred/pbrterrainF.glsl | 50 +-- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 387 +-------------------- 2 files changed, 30 insertions(+), 407 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 0a7c58451d..18f8c4aa73 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -36,18 +36,11 @@ #define MIX_Z 1 << 5 #define MIX_W 1 << 6 -#if 0 // TODO: Remove debug -#define TERRAIN_DEBUG 1 -#endif - // TODO: Decide if this struct needs to be declared struct TerrainMix { vec4 weight; int type; -#if TERRAIN_DEBUG - ivec4 usage; -#endif }; TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal); @@ -127,12 +120,7 @@ in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); -float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal); -// TODO: Clean these up -vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); -vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3); +float terrain_mix(TerrainMix tm, vec4 tms4); void main() { @@ -170,14 +158,14 @@ void main() , detail_0_base_color , detail_0_metallic_roughness , detail_0_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_0_emissive - #endif +#endif , baseColorFactors[0] , orm_factors[0] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[0] - #endif +#endif ); mix = mix_pbr(mix, mix2, tm.weight.x); break; @@ -192,14 +180,14 @@ void main() , detail_1_base_color , detail_1_metallic_roughness , detail_1_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_1_emissive - #endif +#endif , baseColorFactors[1] , orm_factors[1] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[1] - #endif +#endif ); mix = mix_pbr(mix, mix2, tm.weight.y); break; @@ -214,14 +202,14 @@ void main() , detail_2_base_color , detail_2_metallic_roughness , detail_2_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_2_emissive - #endif +#endif , baseColorFactors[2] , orm_factors[2] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[2] - #endif +#endif ); mix = mix_pbr(mix, mix2, tm.weight.z); break; @@ -236,14 +224,14 @@ void main() , detail_3_base_color , detail_3_metallic_roughness , detail_3_normal - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_3_emissive - #endif +#endif , baseColorFactors[3] , orm_factors[3] - #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[3] - #endif +#endif ); mix = mix_pbr(mix, mix2, tm.weight.w); break; @@ -251,12 +239,12 @@ void main() break; } - float minimum_alpha = terrain_mix(minimum_alphas, alpha1, alpha2, alphaFinal); + float minimum_alpha = terrain_mix(tm, minimum_alphas); if (mix.col.a < minimum_alpha) { discard; } - float base_color_factor_alpha = terrain_mix(vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z), alpha1, alpha2, alphaFinal); + float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z)); // from mikktspace.com vec3 vNt = mix.vNt; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 078c753a35..c18cf832f8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -138,16 +138,10 @@ struct TerrainTriplanar int type; }; -#if 0 // TODO: Remove debug -#define TERRAIN_DEBUG 1 -#endif struct TerrainMix { vec4 weight; int type; -#if TERRAIN_DEBUG - ivec4 usage; -#endif }; #define TerrainMixSample vec4[4] @@ -172,9 +166,6 @@ TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal) (usage.y * MIX_Y) | (usage.z * MIX_Z) | (usage.w * MIX_W); -#if TERRAIN_DEBUG // TODO: Remove debug - tm.usage = usage; -#endif return tm; } @@ -196,32 +187,13 @@ TerrainTriplanar _t_triplanar() return tw; } -float terrain_mix(vec4 samples, float alpha1, float alpha2, float alphaFinal) -{ - TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - // Assume weights add to 1 - return tm.weight.x * samples.x + - tm.weight.y * samples.y + - tm.weight.z * samples.z + - tm.weight.w * samples.w; -} - -vec4 terrain_mix(TerrainMix tm, TerrainMixSample tms) -{ - // Assume weights add to 1 - return tm.weight.x * tms[0] + - tm.weight.y * tms[1] + - tm.weight.z * tms[2] + - tm.weight.w * tms[3]; -} - -vec3 terrain_mix(TerrainMix tm, TerrainMixSample3 tms3) +// Assume weights add to 1 +float terrain_mix(TerrainMix tm, vec4 tms4) { - // Assume weights add to 1 - return tm.weight.x * tms3[0] + - tm.weight.y * tms3[1] + - tm.weight.z * tms3[2] + - tm.weight.w * tms3[3]; + return (tm.weight.x * tms4[0]) + + (tm.weight.y * tms4[1]) + + (tm.weight.z * tms4[2]) + + (tm.weight.w * tms4[3]); } #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 @@ -230,17 +202,6 @@ vec3 terrain_mix(TerrainMix tm, TerrainMixSample3 tms3) // Pre-transformed texture coordinates for each axial uv slice (Packing: xy, yz, (-x)z, unused) #define TerrainCoord vec4[2] -vec4 _t_texture(sampler2D tex, vec2 uv_unflipped, float sign_or_zero) -{ - // Handle case where sign is 0 - float sign = (2.0*sign_or_zero) + 1.0; - sign /= abs(sign); - // If the vertex normal is negative, flip the texture back - // right-side up. - vec2 uv = uv_unflipped * vec2(sign, 1); - return texture(tex, uv); -} - vec2 _t_uv(vec2 uv_unflipped, float sign_or_zero) { // Handle case where sign is 0 @@ -287,132 +248,6 @@ vec3 _t_normal_post_z(vec3 vNt0) return vNt_z; } -struct TerrainSample -{ - vec4 x; - vec4 y; - vec4 z; -}; - -TerrainSample _t_sample(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) -{ - TerrainSample ts; - - // The switch..case is broken up into three parts deliberately. A single - // switch..case caused unexplained, "ant trail" seams in terrain. (as seen - // on Nvidia/Windows 10). The extra two branches are not free, but it's - // still a performance win compared to sampling along all three axes for - // every terrain fragment. - #define do_sample_x() _t_texture(tex, terrain_coord[0].zw, sign(vary_vertex_normal.x)) - #define do_sample_y() _t_texture(tex, terrain_coord[1].xy, sign(vary_vertex_normal.y)) - #define do_sample_z() _t_texture(tex, terrain_coord[0].xy, sign(vary_vertex_normal.z)) - switch (tw.type & SAMPLE_X) - { - case SAMPLE_X: - ts.x = do_sample_x(); - break; - default: - ts.x = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tw.type & SAMPLE_Y) - { - case SAMPLE_Y: - ts.y = do_sample_y(); - break; - default: - ts.y = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tw.type & SAMPLE_Z) - { - case SAMPLE_Z: - ts.z = do_sample_z(); - break; - default: - ts.z = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - - return ts; -} - -struct TerrainSampleNormal -{ - vec3 x; - vec3 y; - vec3 z; -}; - -TerrainSampleNormal _t_sample_n(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) -{ - TerrainSample ts = _t_sample(tex, terrain_coord, tw); - TerrainSampleNormal tsn; - // Unpack normals - tsn.x = ts.x.xyz*2.0-1.0; - tsn.y = ts.y.xyz*2.0-1.0; - tsn.z = ts.z.xyz*2.0-1.0; - // Get sign - vec3 ns = sign(vary_vertex_normal); - // Handle case where sign is 0 - ns = (2.0*ns) + 1.0; - ns /= abs(ns); - // If the sign is negative, rotate normal by 180 degrees - tsn.x.xy = (min(0, ns.x) * tsn.x.xy) + (min(0, -ns.x) * -tsn.x.xy); - tsn.y.xy = (min(0, ns.y) * tsn.y.xy) + (min(0, -ns.y) * -tsn.y.xy); - tsn.z.xy = (min(0, ns.z) * tsn.z.xy) + (min(0, -ns.z) * -tsn.z.xy); - // *HACK: Transform normals according to orientation of the UVs - tsn.x.xy = vec2(-tsn.x.y, tsn.x.x); - tsn.y.xy = -tsn.y.xy; - return tsn; -} - -TerrainSample _t_sample_c(sampler2D tex, TerrainCoord terrain_coord, TerrainTriplanar tw) -{ - TerrainSample ts = _t_sample(tex, terrain_coord, tw); - ts.x.xyz = srgb_to_linear(ts.x.xyz); - ts.y.xyz = srgb_to_linear(ts.y.xyz); - ts.z.xyz = srgb_to_linear(ts.z.xyz); - return ts; -} - -// Triplanar sampling of things that are neither colors nor normals (i.e. orm) -vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) -{ - TerrainTriplanar tw = _t_triplanar(); - - TerrainSample ts = _t_sample(tex, terrain_coord, tw); - - return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); -} - -// Specialized triplanar normal texture sampling implementation, taking into -// account how the rotation of the texture affects the lighting and trying to -// negate that. -// *TODO: Decide if we want this. It may be better to just calculate the -// tangents on-the-fly here rather than messing with the normals, due to the -// subtleties of the effects of triplanar mapping on UVs. These sampled normals -// are only valid on the faces of a cube. -// *NOTE: Bottom face has not been tested -vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) -{ - TerrainTriplanar tw = _t_triplanar(); - - TerrainSampleNormal ts = _t_sample_n(tex, terrain_coord, tw); - - return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); -} - -// Triplanar sampling of colors. Colors are converted to linear space before blending. -vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) -{ - TerrainTriplanar tw = _t_triplanar(); - - TerrainSample ts = _t_sample_c(tex, terrain_coord, tw); - - return ((ts.x * tw.weight.x) + (ts.y * tw.weight.y) + (ts.z * tw.weight.z)) / (tw.weight.x + tw.weight.y + tw.weight.z); -} - PBRMix terrain_sample_pbr( TerrainCoord terrain_coord , TerrainTriplanar tw @@ -426,9 +261,9 @@ PBRMix terrain_sample_pbr( { PBRMix mix = init_pbr_mix(); - #define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x)) - #define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y)) - #define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z)) +#define get_uv_x() _t_uv(terrain_coord[0].zw, sign(vary_vertex_normal.x)) +#define get_uv_y() _t_uv(terrain_coord[1].xy, sign(vary_vertex_normal.y)) +#define get_uv_z() _t_uv(terrain_coord[0].xy, sign(vary_vertex_normal.z)) switch (tw.type & SAMPLE_X) { case SAMPLE_X: @@ -482,6 +317,7 @@ PBRMix terrain_sample_pbr( #endif ); // Triplanar-specific normal texture fix + // *NOTE: Bottom face has not been tested mix_z.vNt = _t_normal_post_z(mix_z.vNt); mix = mix_pbr(mix, mix_z, tw.weight.z); break; @@ -493,214 +329,13 @@ PBRMix terrain_sample_pbr( } #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 -#define TerrainCoord vec2 -vec4 terrain_texture(sampler2D tex, TerrainCoord terrain_coord) -{ - return texture(tex, terrain_coord); -} - -vec3 terrain_texture_normal(sampler2D tex, TerrainCoord terrain_coord) -{ - return texture(tex, terrain_coord).xyz*2.0-1.0; -} -vec4 terrain_texture_color(sampler2D tex, TerrainCoord terrain_coord) -{ - vec4 col = texture(tex, terrain_coord); - col.xyz = srgb_to_linear(col.xyz); - return col; -} +#define TerrainCoord vec2 #define terrain_sample_pbr sample_pbr #endif -// The goal of _tmix_sample and related functions is to only sample textures when necessary, ignoring if the weights are low. -// *TODO: Currently, there is much more switch..case branching than needed. This could be simplified by branching per-material rather than per-texture. - -TerrainMixSample _tmix_sample(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMixSample tms; - - switch (tm.type & MIX_X) - { - case MIX_X: - tms[0] = terrain_texture(tex0, texcoord); - break; - default: - tms[0] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_Y) - { - case MIX_Y: - tms[1] = terrain_texture(tex1, texcoord); - break; - default: - tms[1] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_Z) - { - case MIX_Z: - tms[2] = terrain_texture(tex2, texcoord); - break; - default: - tms[2] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_W) - { - case MIX_W: - tms[3] = terrain_texture(tex3, texcoord); - break; - default: - tms[3] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - - return tms; -} - -TerrainMixSample _tmix_sample_color(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMixSample tmix; - - switch (tm.type & MIX_X) - { - case MIX_X: - tmix[0] = terrain_texture_color(tex0, texcoord); - break; - default: - tmix[0] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_Y) - { - case MIX_Y: - tmix[1] = terrain_texture_color(tex1, texcoord); - break; - default: - tmix[1] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_Z) - { - case MIX_Z: - tmix[2] = terrain_texture_color(tex2, texcoord); - break; - default: - tmix[2] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - switch (tm.type & MIX_W) - { - case MIX_W: - tmix[3] = terrain_texture_color(tex3, texcoord); - break; - default: - tmix[3] = vec4(1.0, 0.0, 1.0, 1.0); - break; - } - - return tmix; -} - -TerrainMixSample3 _tmix_sample_normal(TerrainMix tm, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMixSample3 tmix3; - - switch (tm.type & MIX_X) - { - case MIX_X: - tmix3[0] = terrain_texture_normal(tex0, texcoord); - break; - default: - tmix3[0] = vec3(1.0, 0.0, 1.0); - break; - } - switch (tm.type & MIX_Y) - { - case MIX_Y: - tmix3[1] = terrain_texture_normal(tex1, texcoord); - break; - default: - tmix3[1] = vec3(1.0, 0.0, 1.0); - break; - } - switch (tm.type & MIX_Z) - { - case MIX_Z: - tmix3[2] = terrain_texture_normal(tex2, texcoord); - break; - default: - tmix3[2] = vec3(1.0, 0.0, 1.0); - break; - } - switch (tm.type & MIX_W) - { - case MIX_W: - tmix3[3] = terrain_texture_normal(tex3, texcoord); - break; - default: - tmix3[3] = vec3(1.0, 0.0, 1.0); - break; - } - - return tmix3; -} - -vec3 sample_and_mix_color3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); - vec3[4] tms3; - tms3[0] = tms[0].xyz; - tms3[1] = tms[1].xyz; - tms3[2] = tms[2].xyz; - tms3[3] = tms[3].xyz; - tms3[0] *= factors[0]; - tms3[1] *= factors[1]; - tms3[2] *= factors[2]; - tms3[3] *= factors[3]; - return terrain_mix(tm, tms3); -} - -vec4 sample_and_mix_color4(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec4[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - TerrainMixSample tms = _tmix_sample_color(tm, texcoord, tex0, tex1, tex2, tex3); - tms[0] *= factors[0]; - tms[1] *= factors[1]; - tms[2] *= factors[2]; - tms[3] *= factors[3]; - return terrain_mix(tm, tms); -} - -vec3 sample_and_mix_vector3(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, vec3[4] factors, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - TerrainMixSample tms = _tmix_sample(tm, texcoord, tex0, tex1, tex2, tex3); - vec3[4] tms3; - tms3[0] = tms[0].xyz; - tms3[1] = tms[1].xyz; - tms3[2] = tms[2].xyz; - tms3[3] = tms[3].xyz; - tms3[0] *= factors[0]; - tms3[1] *= factors[1]; - tms3[2] *= factors[2]; - tms3[3] *= factors[3]; - return terrain_mix(tm, tms3); -} - -// Returns the unpacked normal texture in range [-1, 1] -vec3 sample_and_mix_normal(float alpha1, float alpha2, float alphaFinal, TerrainCoord texcoord, sampler2D tex0, sampler2D tex1, sampler2D tex2, sampler2D tex3) -{ - TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); - TerrainMixSample3 tms3 = _tmix_sample_normal(tm, texcoord, tex0, tex1, tex2, tex3); - return terrain_mix(tm, tms3); -} - PBRMix multiply_factors_pbr( PBRMix mix_in , vec4 factor_col -- cgit v1.2.3 From 8d9933b37057a67652512d949cedb24b9b087810 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:43:13 -0700 Subject: DRTVWR-592: EXTRA_CODE_HERE is actually important - bring that back --- indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl | 2 ++ indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl | 2 ++ 2 files changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 18f8c4aa73..4bb9758224 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -23,6 +23,8 @@ * $/LicenseInfo$ */ +/*[EXTRA_CODE_HERE]*/ + #define TERRAIN_PBR_DETAIL_EMISSIVE 0 #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index c18cf832f8..316b751590 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -23,6 +23,8 @@ * $/LicenseInfo$ */ +/*[EXTRA_CODE_HERE]*/ + /** * Triplanar mapping implementation adapted from Inigo Quilez' example shader, * MIT license. -- cgit v1.2.3 From cc0f831aaa960552b218da436da57b44cb2dfe0f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 10:43:18 -0700 Subject: DRTVWR-592: Fix PBR terrain shader compile crash when emissive textures are disabled --- .../newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl | 8 +++++++- indra/newview/llviewershadermgr.cpp | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 4bb9758224..db03e0885c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -258,9 +258,15 @@ void main() tnorm *= gl_FrontFacing ? 1.0 : -1.0; + +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) +#define emissive mix.emissive +#else +#define emissive vec3(0) +#endif frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(mix.orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags - frag_data[3] = max(vec4(mix.emissive,0), vec4(0)); // PBR sRGB Emissive + frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5849f97e0e..d545ef97fd 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -695,6 +695,8 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT"] = llformat("%d", mapping); const F32 triplanar_factor = gSavedSettings.getF32("RenderTerrainPBRTriplanarBlendFactor"); attribs["TERRAIN_TRIPLANAR_BLEND_FACTOR"] = llformat("%.2f", triplanar_factor); + S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); + attribs["TERRAIN_PBR_DETAIL"] = llformat("%d", detail); } LLGLSLShader::sGlobalDefines = attribs; -- cgit v1.2.3 From 45547c7bbadf15804f54bb28fd1c94eb5f080bf5 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 13 Oct 2023 16:19:20 -0700 Subject: DRTVWR-592: Attempt to fix Mac build --- indra/newview/lltexturectrl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 08c530314e..ee7095dd50 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -133,7 +133,7 @@ public: : image_id("image"), default_image_id("default_image_id"), default_image_name("default_image_name"), - pick_type("pick_type", PICK_TEXTURE), + pick_type("pick_type", LLTexPickInventoryType::TEXTURE), allow_no_texture("allow_no_texture", false), can_apply_immediately("can_apply_immediately"), no_commit_on_selection("no_commit_on_selection", false), -- cgit v1.2.3 From e841c73a9972fc184487c061e8a80add3a18aff1 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 16 Oct 2023 08:45:48 -0700 Subject: Tons of masking changes and tweaks. We now support masking mirrors in the GBuffer. We also now support the concept of one arbitrary clip plane. DRTVWR-583 --- indra/llrender/llshadermgr.cpp | 4 +++ indra/llrender/llshadermgr.h | 3 ++ .../shaders/class1/deferred/materialV.glsl | 17 +++-------- .../shaders/class1/deferred/pbropaqueF.glsl | 27 ++++++++++++++++++ .../shaders/class3/deferred/materialF.glsl | 30 ++++++++++++++++++-- .../shaders/class3/deferred/softenLightF.glsl | 6 ++-- indra/newview/lldrawpoolmaterials.cpp | 13 +++++++++ indra/newview/llfetchedgltfmaterial.cpp | 1 + indra/newview/llheroprobemanager.cpp | 33 +++++++++++++++++----- indra/newview/llheroprobemanager.h | 11 ++++++++ indra/newview/llreflectionmap.cpp | 4 +-- indra/newview/llreflectionmap.h | 2 +- indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/llviewerwindow.cpp | 15 +++++++++- indra/newview/llviewerwindow.h | 3 +- 15 files changed, 140 insertions(+), 31 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 645a78bfac..8ae23989c9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -651,6 +651,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0 extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1 + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2 extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n"); if (defines) @@ -1256,6 +1257,9 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("emissiveColor"); mReservedUniforms.push_back("metallicFactor"); mReservedUniforms.push_back("roughnessFactor"); + mReservedUniforms.push_back("mirror_flag"); + mReservedUniforms.push_back("clipPlane"); + mReservedUniforms.push_back("clipSign"); mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index a326a5593d..5824c03e2a 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -85,6 +85,9 @@ public: EMISSIVE_COLOR, // "emissiveColor" METALLIC_FACTOR, // "metallicFactor" ROUGHNESS_FACTOR, // "roughnessFactor" + MIRROR_FLAG, // "mirror_flag" + CLIP_PLANE, // "clipPlane" + CLIP_SIGN, // "clipSign" DIFFUSE_MAP, // "diffuseMap" ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap" SPECULAR_MAP, // "specularMap" diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 7cdddfe8db..65706e2c3f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -28,25 +28,18 @@ #define DIFFUSE_ALPHA_MODE_MASK 2 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3 -#ifdef HAS_SKIN uniform mat4 modelview_matrix; uniform mat4 projection_matrix; +uniform mat4 modelview_projection_matrix; + +#ifdef HAS_SKIN mat4 getObjectSkinnedTransform(); #else uniform mat3 normal_matrix; -uniform mat4 modelview_projection_matrix; -#endif - -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) - -#if !defined(HAS_SKIN) -uniform mat4 modelview_matrix; #endif out vec3 vary_position; -#endif - uniform mat4 texture_matrix0; in vec3 position; @@ -133,10 +126,8 @@ void main() vertex_color = diffuse_color; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) #if !defined(HAS_SKIN) - vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; -#endif + vary_position = (projection_matrix*vec4(position.xyz, 1.0)).xyz; #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index faa273b834..9b98a37925 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -58,10 +58,37 @@ vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); +uniform vec4 clipPlane; +uniform float clipSign; +uniform float mirror_flag; +void applyClip(vec3 pos) +{ + if (mirror_flag > 0) + { + // TODO: make this less branchy + if (clipSign > 0) + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) + { + discard; + } + } + else + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) + { + discard; + } + } + } +} + uniform mat3 normal_matrix; void main() { + applyClip(vary_position); + vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; if (basecolor.a < minimum_alpha) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 319f2f25b7..af49e76984 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -51,6 +51,23 @@ vec3 linear_to_srgb(vec3 cs); vec3 legacy_adjust(vec3 c); vec3 legacy_adjust_fullbright(vec3 c); +uniform vec4 clipPlane; +uniform float clipSign; +uniform float mirror_flag; +void applyClip(vec3 pos) +{ + float funnyClip = 0; + if (mirror_flag > 0) + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) + { + discard; + } + } +} + +in vec3 vary_position; + #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) out vec4 frag_color; @@ -72,12 +89,12 @@ uniform vec4 morphFactor; uniform vec3 camPosLocal; uniform mat3 env_mat; +uniform float is_mirror; + uniform vec3 sun_dir; uniform vec3 moon_dir; in vec2 vary_fragcoord; -in vec3 vary_position; - uniform mat4 proj_mat; uniform mat4 inv_proj; uniform vec2 screen_res; @@ -291,6 +308,7 @@ float getShadow(vec3 pos, vec3 norm) void main() { + applyClip(vary_position); waterClip(); // diffcol == diffuse map combined with vertex color @@ -419,9 +437,15 @@ void main() #else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl + + float flag = GBUFFER_FLAG_HAS_ATMOS; + + if (mirror_flag > 0) + flag = 1; + frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. - frag_data[2] = vec4(encode_normal(norm), env, GBUFFER_FLAG_HAS_ATMOS);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) + frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) frag_data[3] = vec4(0); #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 20a5ad66b6..d42388ae78 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -191,7 +191,7 @@ void main() vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) { vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; @@ -214,7 +214,9 @@ void main() color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; + + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) + color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; if (do_atmospherics) { diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 6a7e05ac74..373103ce0a 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -190,6 +190,19 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) glUniform4fv(specular, 1, lastSpecular.mV); } + if (gPipeline.mHeroProbeManager.isMirrorPass()) + { + glUniform1f(LLShaderMgr::MIRROR_FLAG, 1); + } + + LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0], + gPipeline.mHeroProbeManager.currentMirrorClip()[1], + gPipeline.mHeroProbeManager.currentMirrorClip()[2], + gPipeline.mHeroProbeManager.currentMirrorClip()[3]); + + mShader->uniform4fv(LLShaderMgr::CLIP_PLANE, + 1, clipPlane.mV); + LLVOAvatar* lastAvatar = nullptr; for (LLCullResult::drawinfo_iterator i = begin; i != end; ) diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1fb3577dd7..9590066b55 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -128,6 +128,7 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor); shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor); shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV); + shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); F32 normal_packed[8]; mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 91d5f9b800..b6db123cd9 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -141,13 +141,13 @@ void LLHeroProbeManager::update() U8 mode = mNearestHero->mirrorPlacementMode(); mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - LLFace *face = mNearestHero->mDrawable->getFace(mode); - LLVector3 hero_pos = face->getPositionAgent(); + mCurrentFace = mNearestHero->mDrawable->getFace(mode); + LLVector3 hero_pos = mCurrentFace->getPositionAgent(); // Calculate the average normal. - LLVector4a *posp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mPositions; - U16 *indp = face->getViewerObject()->getVolume()->getVolumeFace(face->getTEOffset()).mIndices; + LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions; + U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices; // get first three vertices (first triangle) LLVector4a v0 = posp[indp[0]]; LLVector4a v1 = posp[indp[1]]; @@ -158,14 +158,27 @@ void LLHeroProbeManager::update() LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); face_normal.normalize(); - face_normal *= face->getXform()->getWorldRotation(); + face_normal *= mCurrentFace->getXform()->getWorldRotation(); LLVector3 offset = camera_pos - hero_pos; LLVector3 project = face_normal * (offset * face_normal); LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; - near_clip = abs(dist_vec(hero_pos, point)) - gSavedSettings.getF32("RenderHeroProbeNearClipOffset"); + glh::matrix4f mat = copy_matrix(gGLModelView); + glh::vec4f tc(face_normal.mV); + mat.mult_matrix_vec(tc); + + LLVector3 mirror_normal; + mirror_normal.set(tc.v); + + LLVector3 hero_pos_render; + tc = glh::vec4f(hero_pos.mV); + + mat.mult_matrix_vec(tc); + hero_pos_render.set(tc.v); + + mCurrentClipPlane.setVec(hero_pos_render, mirror_normal); probe_pos.load3(point.mV); } @@ -189,7 +202,7 @@ void LLHeroProbeManager::update() bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); gPipeline.mReflectionMapManager.mRadiancePass = true; - + mRenderingMirror = true; for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) @@ -197,6 +210,7 @@ void LLHeroProbeManager::update() updateProbeFace(mProbes[j], i, near_clip); } } + mRenderingMirror = false; gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } @@ -563,3 +577,8 @@ void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) mHeroVOList.erase(drawablep); } } + +bool LLHeroProbeManager::isViableMirror(LLFace* face) const +{ + return face == mCurrentFace; +} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 4a243e6cf2..68cfdbfd99 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -70,6 +70,12 @@ public: void registerHeroDrawable(LLVOVolume* drawablep); void unregisterHeroDrawable(LLVOVolume* drawablep); + + bool isViableMirror(LLFace* face) const; + + bool isMirrorPass() const { return mRenderingMirror; } + + LLPlane currentMirrorClip() const { return mCurrentClipPlane; } private: friend class LLPipeline; @@ -94,6 +100,8 @@ private: // vertex buffer for pushing verts to filter shaders LLPointer mVertexBuffer; + LLPlane mCurrentClipPlane; + // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); @@ -124,8 +132,11 @@ private: // if true, reset all probe render state on the next update (for teleports and sky changes) bool mReset = false; + + bool mRenderingMirror = false; std::set mHeroVOList; LLVOVolume* mNearestHero; + LLFace* mCurrentFace; }; diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 06624e8fea..5fc9851709 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -49,7 +49,7 @@ LLReflectionMap::~LLReflectionMap() } } -void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip) +void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; mLastUpdateTime = gFrameTimeSeconds; @@ -66,7 +66,7 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 n F32 clip = (near_clip > 0) ? near_clip : getNearClip(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane); } void LLReflectionMap::autoAdjustOrigin() diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index e97b28c855..9e888f20d0 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -52,7 +52,7 @@ public: // update this environment map // resolution - size of cube map to generate - void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f); + void update(U32 resolution, U32 face, bool force_dynamic = false, F32 near_clip = -1.f, bool useClipPlane = false, LLPlane clipPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1))); // for volume partition probes, try to place this probe in the best spot void autoAdjustOrigin(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 04ca62e0ec..a1e7d69ae4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1063,7 +1063,7 @@ void display_cube_face() LLSpatialGroup::sNoDelete = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots + LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data static LLCullResult result; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ba2b6e1c7c..e0ec8eec25 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -5304,7 +5304,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 dynamic_render) +BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubearray, S32 cubeIndex, S32 face, F32 near_clip, bool dynamic_render, bool useCustomClipPlane, LLPlane clipPlane) { // NOTE: implementation derived from LLFloater360Capture::capture360Images() and simpleSnapshot LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; @@ -5335,6 +5335,14 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea camera->setOrigin(origin); camera->setNear(near_clip); + LLPlane previousClipPlane; + + if (useCustomClipPlane) + { + previousClipPlane = camera->getUserClipPlane(); + camera->setUserClipPlane(clipPlane); + } + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); U32 dynamic_render_types[] = { @@ -5441,6 +5449,11 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea gPipeline.resetDrawOrders(); mWorldViewRectRaw = window_rect; + + if (useCustomClipPlane) + { + camera->setUserClipPlane(previousClipPlane); + } // restore original view/camera/avatar settings settings *camera = saved_camera; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6e8a5b2f4e..4da6a1360f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -374,7 +374,8 @@ 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 render_avatars); + BOOL cubeSnapshot(const LLVector3 &origin, LLCubeMapArray *cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars, + bool customCullingPlane = false, LLPlane cullingPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1))); // special implementation of simpleSnapshot for reflection maps -- cgit v1.2.3 From 0ed6112967f2240de689b08373bf61905321e199 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 17 Jan 2024 16:23:16 -0600 Subject: https://github.com/secondlife/viewer-issues/issues/21 Add RenderMaxTextureResolution debug setting --- indra/newview/app_settings/settings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 77ca52a7f7..76e635744e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9405,6 +9405,17 @@ U32 Value 16 + + RenderMaxTextureResolution + + Comment + Maximum texture resolution. + Persist + 1 + Type + U32 + Value + 1024 RenderDebugTextureBind -- cgit v1.2.3 From 19163fd0fea6c92712b37e29f34b72edbbfe152d Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 18 Jan 2024 10:33:02 -0600 Subject: Allow for upload of 2k textures (#652) * SL-20760 Allow 2k texture uploads * SL-20760 Fix for textures not downloading. --- indra/llimage/llimage.h | 8 ++++---- indra/llrender/llgltexture.h | 2 +- indra/newview/llmaterialeditor.cpp | 2 +- indra/newview/llviewertexture.cpp | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 8f9e1b3c54..d1929b693f 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -33,7 +33,7 @@ #include "lltrace.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 -const S32 MAX_IMAGE_MIP = 11; // 2048x2048 +const S32 MAX_IMAGE_MIP = 12; // 4096x4096 // *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number // of levels is read from the header's file, not inferred from its size. @@ -44,7 +44,7 @@ const S32 MAX_DISCARD_LEVEL = 5; // and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL. const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is) -const S32 MAX_PRECINCT_SIZE = 2048; // No reason to be bigger than MAX_IMAGE_SIZE +const S32 MAX_PRECINCT_SIZE = 4096; // No reason to be bigger than MAX_IMAGE_SIZE const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec @@ -52,11 +52,11 @@ const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after hea const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit) const S32 MIN_IMAGE_SIZE = (1<getDataSize() << LL_ENDL; } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 56bba51692..8436159e14 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1699,7 +1699,7 @@ void LLViewerFetchedTexture::processTextureStats() { if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) { - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 } else { @@ -1712,7 +1712,7 @@ void LLViewerFetchedTexture::processTextureStats() } else { - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) { if (mFullWidth > desired_size || mFullHeight > desired_size) @@ -3089,7 +3089,7 @@ void LLViewerLODTexture::processTextureStats() { mDesiredDiscardLevel = 0; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 } else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) { @@ -3134,7 +3134,7 @@ void LLViewerLODTexture::processTextureStats() discard_level = floorf(discard_level); F32 min_discard = 0.f; - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED) { desired_size = DESIRED_NORMAL_TEXTURE_SIZE; -- cgit v1.2.3 From 46bc94074d59a898e94eefd73363aed2d27f3e05 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 19 Jan 2024 10:22:52 -0600 Subject: https://github.com/secondlife/viewer-issues/issues/21 Just use existing settings to block uploads larger than 1024. --- indra/newview/app_settings/settings.xml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 76e635744e..4a95cb1ed2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9405,17 +9405,6 @@ U32 Value 16 - - RenderMaxTextureResolution - - Comment - Maximum texture resolution. - Persist - 1 - Type - U32 - Value - 1024 RenderDebugTextureBind @@ -15700,7 +15689,7 @@ Type S32 Value - 2048 + 1024 max_texture_dimension_Y @@ -15711,7 +15700,7 @@ Type S32 Value - 2048 + 1024 teleport_offer_invitation_max_length -- cgit v1.2.3 From ae3990e24f3ec27ce66b00faa57bf27f3bbdaef5 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 28 Nov 2023 16:47:44 -0800 Subject: SL-20606: Remove unused LLRenderPass func --- indra/newview/lldrawpool.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 0925a01439..f6200d1f6d 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -349,8 +349,6 @@ public: void resetDrawOrders() { } static void applyModelMatrix(const LLDrawInfo& params); - // Use before a non-GLTF batch if it is interleaved with GLTF batches that share the same shader - static void resetGLTFTextureTransform(); void pushBatches(U32 type, bool texture = true, bool batch_textures = false); void pushUntexturedBatches(U32 type); -- cgit v1.2.3 From 7c2c49dd262020fcf36c12ce3fcb23d2222c146d Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 28 Nov 2023 17:23:59 -0800 Subject: SL-20606: Make push GLTF single batch static --- indra/newview/lldrawpool.cpp | 4 ++++ indra/newview/lldrawpool.h | 8 ++++---- indra/newview/pipeline.cpp | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 50210b06c4..f10c9047a3 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -746,6 +746,7 @@ void LLRenderPass::pushUntexturedGLTFBatches(U32 type) } } +// static void LLRenderPass::pushGLTFBatch(LLDrawInfo& params) { auto& mat = params.mGLTFMaterial; @@ -764,6 +765,7 @@ void LLRenderPass::pushGLTFBatch(LLDrawInfo& params) teardown_texture_matrix(params); } +// static void LLRenderPass::pushUntexturedGLTFBatch(LLDrawInfo& params) { auto& mat = params.mGLTFMaterial; @@ -825,6 +827,7 @@ void LLRenderPass::pushUntexturedRiggedGLTFBatches(U32 type) } +// static void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId) { if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash)) @@ -837,6 +840,7 @@ void LLRenderPass::pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvat pushGLTFBatch(params); } +// static void LLRenderPass::pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId) { if (params.mAvatar.notNull() && (lastAvatar != params.mAvatar || lastMeshId != params.mSkinInfo->mHash)) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index f6200d1f6d..365c022285 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -372,10 +372,10 @@ public: void pushUntexturedRiggedGLTFBatches(U32 type); // push a single GLTF draw call - void pushGLTFBatch(LLDrawInfo& params); - void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); - void pushUntexturedGLTFBatch(LLDrawInfo& params); - void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); + static void pushGLTFBatch(LLDrawInfo& params); + static void pushRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); + static void pushUntexturedGLTFBatch(LLDrawInfo& params); + static void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false); void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f740fa60be..3882472b49 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6536,7 +6536,7 @@ void LLPipeline::renderAlphaObjects(bool rigged) LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); - mSimplePool->pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId); + LLRenderPass::pushRiggedGLTFBatch(*pparams, lastAvatar, lastMeshId); } else { @@ -6562,7 +6562,7 @@ void LLPipeline::renderAlphaObjects(bool rigged) LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); - mSimplePool->pushGLTFBatch(*pparams); + LLRenderPass::pushGLTFBatch(*pparams); } else { -- cgit v1.2.3 From 42dafa5f09d3921617f54be712907ee12f1e8940 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 15 Sep 2023 17:18:07 -0700 Subject: SL-20606: Refactor model matrix code --- indra/newview/lldrawpool.cpp | 13 +++++++++---- indra/newview/lldrawpool.h | 2 ++ indra/newview/lldrawpoolterrain.cpp | 15 ++------------- indra/newview/lldrawpooltree.cpp | 13 ++----------- 4 files changed, 15 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index f10c9047a3..556760632a 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -567,14 +567,19 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) { - if (params.mModelMatrix != gGLLastMatrix) + applyModelMatrix(params.mModelMatrix); +} + +void LLRenderPass::applyModelMatrix(const LLMatrix4* model_matrix) +{ + if (model_matrix != gGLLastMatrix) { - gGLLastMatrix = params.mModelMatrix; + gGLLastMatrix = model_matrix; gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.loadMatrix(gGLModelView); - if (params.mModelMatrix) + if (model_matrix) { - gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix); + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); } gPipeline.mMatrixOpCount++; } diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 365c022285..0a9c2cc420 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -349,6 +349,8 @@ public: void resetDrawOrders() { } static void applyModelMatrix(const LLDrawInfo& params); + // For rendering that doesn't use LLDrawInfo for some reason + static void applyModelMatrix(const LLMatrix4* model_matrix); void pushBatches(U32 type, bool texture = true, bool batch_textures = false); void pushUntexturedBatches(U32 type); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 77189dceae..43f7587591 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -204,19 +204,8 @@ void LLDrawPoolTerrain::drawLoop() { LLFace *facep = *iter; - LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); - - if (model_matrix != gGLLastMatrix) - { - llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); - gGLLastMatrix = model_matrix; - gGL.loadMatrix(gGLModelView); - if (model_matrix) - { - gGL.multMatrix((GLfloat*) model_matrix->mMatrix); - } - gPipeline.mMatrixOpCount++; - } + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); + LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix); facep->renderIndexed(); } diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 9dcbc48697..50c4a2c1b3 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -85,17 +85,8 @@ void LLDrawPoolTree::renderDeferred(S32 pass) { LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); - if (model_matrix != gGLLastMatrix) - { - gGLLastMatrix = model_matrix; - gGL.loadMatrix(gGLModelView); - if (model_matrix) - { - llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); - gGL.multMatrix((GLfloat*)model_matrix->mMatrix); - } - gPipeline.mMatrixOpCount++; - } + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); + LLRenderPass::applyModelMatrix(model_matrix); buff->setBuffer(); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts() - 1, buff->getNumIndices(), 0); -- cgit v1.2.3 From 22d0d81f719ef00d28255d4f8af5702752c731f6 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 4 Dec 2023 12:18:56 -0800 Subject: SL-20606: Add Tracy profile zone for LLViewerDynamicTexture::updateAllInstances --- indra/newview/lldynamictexture.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 425acd3392..1a817e4fd9 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -181,6 +181,8 @@ void LLViewerDynamicTexture::postRender(BOOL success) //----------------------------------------------------------------------------- BOOL LLViewerDynamicTexture::updateAllInstances() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + sNumRenders = 0; if (gGLManager.mIsDisabled) { -- cgit v1.2.3 From c2a30057f8c8dde913d12c0ee21d98191f58c5f1 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 12 Dec 2023 17:47:33 -0800 Subject: SL-20606: Remove unused strider getters --- indra/llrender/llvertexbuffer.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index f2d146d4bb..197fdbb189 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -187,10 +187,6 @@ public: bool getWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); bool getWeight4Strider(LLStrider& strider, U32 index=0, S32 count = -1); bool getClothWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getBasecolorTexcoordStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getNormalTexcoordStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getMetallicRoughnessTexcoordStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getEmissiveTexcoordStrider(LLStrider& strider, U32 index=0, S32 count = -1); void setPositionData(const LLVector4a* data); void setTexCoordData(const LLVector2* data); -- cgit v1.2.3 From 2f18d74f9ab3165da680ce2ee2f0c455ce7e0796 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 13 Nov 2023 17:26:14 -0800 Subject: SL-20606: Full GLTF material preview. Works for most materials. --- indra/llmath/llcamera.h | 1 - indra/llrender/llvertexbuffer.cpp | 4 + indra/llrender/llvertexbuffer.h | 1 + indra/newview/CMakeLists.txt | 2 + .../class1/deferred/postDeferredNoDoFF.glsl | 4 + indra/newview/lldynamictexture.cpp | 27 +- indra/newview/llfetchedgltfmaterial.cpp | 52 --- indra/newview/llfetchedgltfmaterial.h | 5 - indra/newview/llgltfmaterialpreviewmgr.cpp | 501 +++++++++++++++++++++ indra/newview/llgltfmaterialpreviewmgr.h | 82 ++++ indra/newview/llreflectionmapmanager.cpp | 32 ++ indra/newview/llreflectionmapmanager.h | 5 + indra/newview/lltexturectrl.cpp | 93 ++-- indra/newview/lltexturectrl.h | 3 + indra/newview/pipeline.cpp | 15 +- indra/newview/pipeline.h | 4 +- 16 files changed, 728 insertions(+), 103 deletions(-) create mode 100644 indra/newview/llgltfmaterialpreviewmgr.cpp create mode 100644 indra/newview/llgltfmaterialpreviewmgr.h (limited to 'indra') diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index c4d04f5d02..e1d3536f66 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -65,7 +65,6 @@ class LLCamera : public LLCoordFrame { public: - LLCamera(const LLCamera& rhs) { *this = rhs; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index de27636c33..4f5f30d7c2 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1319,6 +1319,10 @@ bool LLVertexBuffer::getNormalStrider(LLStrider& strider, U32 index, { return VertexBufferStrider::get(*this, strider, index, count); } +bool LLVertexBuffer::getNormalStrider(LLStrider& strider, U32 index, S32 count) +{ + return VertexBufferStrider::get(*this, strider, index, count); +} bool LLVertexBuffer::getTangentStrider(LLStrider& strider, U32 index, S32 count) { return VertexBufferStrider::get(*this, strider, index, count); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 197fdbb189..cc59e322ed 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -180,6 +180,7 @@ public: bool getTexCoord1Strider(LLStrider& strider, U32 index=0, S32 count = -1); bool getTexCoord2Strider(LLStrider& strider, U32 index=0, S32 count = -1); bool getNormalStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getNormalStrider(LLStrider& strider, U32 index = 0, S32 count = -1); bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); bool getColorStrider(LLStrider& strider, U32 index=0, S32 count = -1); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7a70d0b6e6..8268fb3d97 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES llgiveinventory.cpp llglsandbox.cpp llgltfmateriallist.cpp + llgltfmaterialpreviewmgr.cpp llgroupactions.cpp llgroupiconctrl.cpp llgrouplist.cpp @@ -963,6 +964,7 @@ set(viewer_HEADER_FILES llgesturemgr.h llgiveinventory.h llgltfmateriallist.h + llgltfmaterialpreviewmgr.h llgroupactions.h llgroupiconctrl.h llgrouplist.h diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index bace9b8c90..cd4ae8110a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -37,7 +37,11 @@ void main() { vec4 diff = texture(diffuseRect, vary_fragcoord.xy); +#if 1 frag_color = diff; +#else + frag_color = vec4(1,0,1,1); +#endif gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r; } diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 1a817e4fd9..a66c3876fc 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -189,13 +189,18 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } - bool use_fbo = gPipeline.mBake.isComplete() && !gGLManager.mIsAMD; + LLRenderTarget& bake_target = gPipeline.mAuxillaryRT.deferredScreen; - if (use_fbo) - { - gPipeline.mBake.bindTarget(); - gPipeline.mBake.clear(); - } + if (!bake_target.isComplete()) + { + llassert(false); + return FALSE; + } + llassert(bake_target.getWidth() >= LLPipeline::MAX_BAKE_WIDTH); + llassert(bake_target.getHeight() >= LLPipeline::MAX_BAKE_WIDTH); + + bake_target.bindTarget(); + bake_target.clear(); LLGLSLShader::unbind(); LLVertexBuffer::unbind(); @@ -210,11 +215,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances() LLViewerDynamicTexture *dynamicTexture = *iter; if (dynamicTexture->needsRender()) { + llassert(dynamicTexture->getFullWidth() <= LLPipeline::MAX_BAKE_WIDTH); + llassert(dynamicTexture->getFullHeight() <= LLPipeline::MAX_BAKE_WIDTH); + glClear(GL_DEPTH_BUFFER_BIT); gDepthDirty = TRUE; gGL.color4f(1,1,1,1); - dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr); + dynamicTexture->setBoundTarget(&bake_target); dynamicTexture->preRender(); // Must be called outside of startRender() result = FALSE; if (dynamicTexture->render()) @@ -231,10 +239,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } } - if (use_fbo) - { - gPipeline.mBake.flush(); - } + bake_target.flush(); gGL.flush(); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 46b9dffae9..90ec08391d 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -254,55 +254,3 @@ void LLFetchedGLTFMaterial::materialComplete() materialCompleteCallbacks.clear(); materialCompleteCallbacks.shrink_to_fit(); } - -LLPointer LLFetchedGLTFMaterial::getUITexture() -{ - if (mFetching) - { - return nullptr; - } - - auto fetch_texture_for_ui = [](LLPointer& img, const LLUUID& id) - { - if (id.notNull()) - { - if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) - { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if (obj) - { - LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id); - img = viewerTexture ? dynamic_cast(viewerTexture) : NULL; - } - - } - else - { - img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - } - if (img) - { - img->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - img->forceToSaveRawImage(0); - } - }; - - fetch_texture_for_ui(mBaseColorTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); - fetch_texture_for_ui(mNormalTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); - fetch_texture_for_ui(mMetallicRoughnessTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); - fetch_texture_for_ui(mEmissiveTexture, mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); - - if ((mBaseColorTexture && (mBaseColorTexture->getRawImageLevel() != 0)) || - (mNormalTexture && (mNormalTexture->getRawImageLevel() != 0)) || - (mMetallicRoughnessTexture && (mMetallicRoughnessTexture->getRawImageLevel() != 0)) || - (mEmissiveTexture && (mEmissiveTexture->getRawImageLevel() != 0))) - { - return nullptr; - } - - // *HACK: Use one of the PBR texture components as the preview texture for now - mPreviewTexture = mBaseColorTexture; - - return mPreviewTexture; -} diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index a9e539633d..2559aa46cc 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -50,8 +50,6 @@ public: bool isFetching() const { return mFetching; } - LLPointer getUITexture(); - void addTextureEntry(LLTextureEntry* te) override; void removeTextureEntry(LLTextureEntry* te) override; virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) override; @@ -65,9 +63,6 @@ public: std::set mTextureEntires; - // Texture used for previewing the material in the UI - LLPointer mPreviewTexture; - protected: // Lifetime management diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp new file mode 100644 index 0000000000..9ef1bbf884 --- /dev/null +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -0,0 +1,501 @@ +/** + * @file llgltfmaterialpreviewmgr.cpp + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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 "llviewerprecompiledheaders.h" + +#include "llgltfmaterialpreviewmgr.h" + +#include + +#include "llavatarappearancedefines.h" +#include "llenvironment.h" +#include "llselectmgr.h" +#include "llviewercamera.h" +#include "llviewerobject.h" +#include "llviewershadermgr.h" +#include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llvolumemgr.h" +#include "pipeline.h" + +LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr; + +namespace +{ + constexpr S32 FULLY_LOADED = 0; + constexpr S32 NOT_LOADED = 99; +}; + +LLGLTFPreviewTexture::MaterialLoadLevels::MaterialLoadLevels() +{ + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + levels[i] = NOT_LOADED; + } +} + +S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) +{ + llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT); + return levels[i]; +} + +const S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) const +{ + llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT); + return levels[i]; +} + +bool LLGLTFPreviewTexture::MaterialLoadLevels::operator<(const MaterialLoadLevels& other) const +{ + bool less = false; + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (((*this)[i] > other[i])) { return false; } + less = less || ((*this)[i] < other[i]); + } + return less; +} + +bool LLGLTFPreviewTexture::MaterialLoadLevels::operator>(const MaterialLoadLevels& other) const +{ + bool great = false; + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (((*this)[i] < other[i])) { return false; } + great = great || ((*this)[i] > other[i]); + } + return great; +} + +namespace +{ + void fetch_texture_for_ui(LLPointer& img, const LLUUID& id) + { + if (id.notNull()) + { + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) + { + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (obj) + { + LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(id); + img = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + } + } + else + { + img = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + } + if (img) + { + img->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + img->forceToSaveRawImage(0); + } + }; + + // *NOTE: Does not use the same conventions as texture discard level. Lower is better. + S32 get_texture_load_level(const LLPointer& texture) + { + if (!texture) { return FULLY_LOADED; } + const S32 raw_level = texture->getDiscardLevel(); + if (raw_level < 0) { return NOT_LOADED; } + return raw_level; + } + + LLGLTFPreviewTexture::MaterialLoadLevels get_material_load_levels(LLFetchedGLTFMaterial& material) + { + using MaterialTextures = LLPointer*[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; + + MaterialTextures textures; + + textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = &material.mBaseColorTexture; + textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = &material.mNormalTexture; + textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = &material.mMetallicRoughnessTexture; + textures[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = &material.mEmissiveTexture; + + LLGLTFPreviewTexture::MaterialLoadLevels levels; + + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + fetch_texture_for_ui(*textures[i], material.mTextureId[i]); + levels[i] = get_texture_load_level(*textures[i]); + } + + return levels; + } + + // Is the material loaded enough to start rendering a preview? + bool is_material_loaded_enough_for_ui(LLFetchedGLTFMaterial& material) + { + if (material.isFetching()) + { + return false; + } + + LLGLTFPreviewTexture::MaterialLoadLevels levels = get_material_load_levels(material); + + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (levels[i] == NOT_LOADED) + { + return false; + } + } + + return true; + } + +}; // namespace + +LLGLTFPreviewTexture::LLGLTFPreviewTexture(LLPointer material, S32 width) + : LLViewerDynamicTexture(width, width, 4, EOrder::ORDER_MIDDLE, FALSE) + , mGLTFMaterial(material) +{ +} + +// static +LLPointer LLGLTFPreviewTexture::create(LLPointer material) +{ + return new LLGLTFPreviewTexture(material, LLPipeline::MAX_BAKE_WIDTH); +} + +void LLGLTFPreviewTexture::preRender(BOOL clear_depth) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + + MaterialLoadLevels current_load = get_material_load_levels(*mGLTFMaterial.get()); + if (current_load < mBestLoad) + { + mShouldRender = true; + mBestLoad = current_load; + } + + if (!mShouldRender) { return; } + + LLViewerDynamicTexture::preRender(clear_depth); +} + + +namespace { + +struct GLTFPreviewModel +{ + GLTFPreviewModel(LLPointer& info, const LLMatrix4& mat) + : mDrawInfo(info) + , mModelMatrix(mat) + { + mDrawInfo->mModelMatrix = &mModelMatrix; + } + LLPointer mDrawInfo; + LLMatrix4 mModelMatrix; // Referenced by mDrawInfo +}; + +// Like LLVolumeGeometryManager::registerFace but without batching or too-many-indices/vertices checking. +std::vector create_preview_sphere(LLPointer& material, const LLMatrix4& model_matrix) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + + const LLColor4U vertex_color(material->mBaseColor); + + LLPrimitive prim; + prim.init_primitive(LL_PCODE_VOLUME); + LLVolumeParams params; + params.setType(LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE); + params.setBeginAndEndS(0.f, 1.f); + params.setBeginAndEndT(0.f, 1.f); + params.setRatio(1, 1); + params.setShear(0, 0); + constexpr auto MAX_LOD = LLVolumeLODGroup::NUM_LODS - 1; + prim.setVolume(params, MAX_LOD); + + LLVolume* volume = prim.getVolume(); + llassert(volume); + for (LLVolumeFace& face : volume->getVolumeFaces()) + { + face.createTangents(); + } + + std::vector preview_sphere; + preview_sphere.reserve(volume->getNumFaces()); + + LLPointer buf = new LLVertexBuffer( + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TANGENT + ); + U32 nv = 0; + U32 ni = 0; + for (LLVolumeFace& face : volume->getVolumeFaces()) + { + nv += face.mNumVertices; + ni += face.mNumIndices; + } + buf->allocateBuffer(nv, ni); + + // UV hacks + // Higher factor helps to see more details on the preview sphere + const LLVector2 uv_factor(2.0f, 2.0f); + // Offset places center of material in center of view + const LLVector2 uv_offset(-0.5f, -0.5f); + + LLStrider indices; + LLStrider positions; + LLStrider normals; + LLStrider texcoords; + LLStrider colors; + LLStrider tangents; + buf->getIndexStrider(indices); + buf->getVertexStrider(positions); + buf->getNormalStrider(normals); + buf->getTexCoord0Strider(texcoords); + buf->getColorStrider(colors); + buf->getTangentStrider(tangents); + U32 index_offset = 0; + U32 vertex_offset = 0; + for (const LLVolumeFace& face : volume->getVolumeFaces()) + { + for (S32 i = 0; i < face.mNumIndices; ++i) + { + *indices++ = face.mIndices[i] + vertex_offset; + } + for (S32 v = 0; v < face.mNumVertices; ++v) + { + *positions++ = face.mPositions[v]; + *normals++ = face.mNormals[v]; + LLVector2 uv(face.mTexCoords[v]); + uv.scaleVec(uv_factor); + uv += uv_offset; + *texcoords++ = uv; + *colors++ = vertex_color; + *tangents++ = face.mTangents[v]; + } + + constexpr LLViewerTexture* no_media = nullptr; + LLPointer info = new LLDrawInfo(U16(vertex_offset), U16(vertex_offset + face.mNumVertices - 1), face.mNumIndices, index_offset, no_media, buf.get()); + info->mGLTFMaterial = material; + preview_sphere.emplace_back(info, model_matrix); + index_offset += face.mNumIndices; + vertex_offset += face.mNumVertices; + } + + buf->unmapBuffer(); + + return preview_sphere; +} + +// Final, direct modifications to shader constants, just before render +void fixup_shader_constants(LLGLSLShader& shader) +{ + // Sunlight intensity of 0 no matter what + shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, 1); + shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, LLColor3::white.mV); + shader.uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, 0.0f); + + // Ignore sun shadow (if enabled) + for (U32 i = 0; i < 6; i++) + { + const S32 channel = shader.getTextureChannel(LLShaderMgr::DEFERRED_SHADOW0+i); + if (channel != -1) + { + gGL.getTexUnit(channel)->bind(LLViewerFetchedTexture::sWhiteImagep, TRUE); + } + } +} + +// Set a variable to a value temporarily, and restor the variable's old value +// when this object leaves scope. +template +struct SetTemporarily +{ + T* mRef; + T mOldVal; + SetTemporarily(T* var, T temp_val) + { + mRef = var; + mOldVal = *mRef; + *mRef = temp_val; + } + ~SetTemporarily() + { + *mRef = mOldVal; + } +}; + +}; // namespace + +BOOL LLGLTFPreviewTexture::render() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + + if (!mShouldRender) { return FALSE; } + + LLGLDepthTest(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); + LLGLDisable scissor(GL_SCISSOR_TEST); + SetTemporarily no_glow(&LLPipeline::sRenderGlow, false); + SetTemporarily no_ssr(&LLPipeline::RenderScreenSpaceReflections, false); + SetTemporarily no_fxaa(&LLPipeline::RenderFSAASamples, U32(0)); + SetTemporarily use_auxiliary_render_target(&gPipeline.mRT, &gPipeline.mAuxillaryRT); + + LLVector3 light_dir3(1.0f, 1.0f, 1.0f); + light_dir3.normalize(); + const LLVector4 light_dir = LLVector4(light_dir3, 0); + SetTemporarily sun_light_only(&LLPipeline::RenderLocalLightCount, 0); + + gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(); + + LLViewerCamera camera; + + // Calculate the object distance at which the object of a given radius will + // span the partial width of the screen given by fill_ratio. + // Assume the primitive has a scale of 1 (this is the default). + constexpr F32 fill_ratio = 0.8f; + constexpr F32 object_radius = 0.5f; + const F32 object_distance = (object_radius / fill_ratio) * tan(camera.getDefaultFOV()); + // Negative coordinate shows the textures on the sphere right-side up, when + // combined with the UV hacks in create_preview_sphere + const LLVector3 object_position(0.0, -object_distance, 0.0); + LLMatrix4 object_transform; + object_transform.translate(object_position); + + // Set up camera and viewport + const LLVector3 origin(0.0, 0.0, 0.0); + camera.lookAt(origin, object_position); + camera.setAspect(mFullHeight / mFullWidth); + const LLRect texture_rect(0, mFullHeight, mFullWidth, 0); + camera.setPerspective(NOT_FOR_SELECTION, texture_rect.mLeft, texture_rect.mBottom, texture_rect.getWidth(), texture_rect.getHeight(), FALSE, camera.getNear(), MAX_FAR_CLIP*2.f); + + // Generate sphere object on-the-fly. Discard afterwards. (Vertex buffer is + // discarded, but the sphere should be cached in LLVolumeMgr.) + std::vector preview_sphere = create_preview_sphere(mGLTFMaterial, object_transform); + + glClearColor(0, 0, 0, 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gPipeline.setupHWLights(); + glh::matrix4f mat = copy_matrix(gGLModelView); + glh::vec4f transformed_light_dir(light_dir.mV); + mat.mult_matrix_vec(transformed_light_dir); + SetTemporarily force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir.v)); + // Override lights to ensure the sun is always shining from a certain direction (low graphics) + // See also force_sun_direction_high_graphics and fixup_shader_constants + { + LLLightState* light = gGL.getLight(0); + light->setPosition(light_dir); + constexpr bool sun_up = true; + light->setSunPrimary(sun_up); + } + + LLRenderTarget& screen = gPipeline.mAuxillaryRT.screen; + +#if 0 + if (mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE || mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) + { + // *TODO: Opaque/alpha mask rendering (gDeferredPBROpaqueProgram) + } + else +#endif + { + // Alpha blend rendering + + screen.bindTarget(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + LLGLSLShader& shader = gDeferredPBRAlphaProgram; + + gPipeline.bindDeferredShader(shader); + fixup_shader_constants(shader); + + for (GLTFPreviewModel& part : preview_sphere) + { + LLRenderPass::pushGLTFBatch(*part.mDrawInfo); + } + + gPipeline.unbindDeferredShader(shader); + + screen.flush(); + } + + gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap); + gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap); + gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap); + gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap); + LLVertexBuffer::unbind(); + gPipeline.generateGlow(&gPipeline.mPostMap); + gPipeline.combineGlow(&gPipeline.mPostMap, &screen); + gPipeline.renderDoF(&screen, &gPipeline.mPostMap); + gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + + gDeferredPostNoDoFProgram.bind(); + + // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems." + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen); + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true); + + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + gDeferredPostNoDoFProgram.unbind(); + + // Clean up + gPipeline.setupHWLights(); + gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(false); + + return TRUE; +} + +void LLGLTFPreviewTexture::postRender(BOOL success) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + + if (!mShouldRender) { return; } + mShouldRender = false; + + LLViewerDynamicTexture::postRender(success); +} + +// static +LLPointer LLGLTFMaterialPreviewMgr::getPreview(LLPointer &material) +{ + if (!material) + { + return nullptr; + } + + if (!is_material_loaded_enough_for_ui(*material)) + { + return nullptr; + } + + return LLGLTFPreviewTexture::create(material); +} diff --git a/indra/newview/llgltfmaterialpreviewmgr.h b/indra/newview/llgltfmaterialpreviewmgr.h new file mode 100644 index 0000000000..cc40a6f2e2 --- /dev/null +++ b/indra/newview/llgltfmaterialpreviewmgr.h @@ -0,0 +1,82 @@ +/** + * @file llgltfmaterialpreviewmgr.h + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +#pragma once + +#include "lldrawpool.h" +#include "lldynamictexture.h" +#include "llfetchedgltfmaterial.h" +#include "llsingleton.h" +#include "lltexture.h" + +class LLGLTFPreviewTexture : public LLViewerDynamicTexture +{ +protected: + LLGLTFPreviewTexture(LLPointer material, S32 width); + +public: + // Width scales with size of material's textures + static LLPointer create(LLPointer material); + + BOOL needsRender() override { return mNeedsRender; } + void preRender(BOOL clear_depth = TRUE) override; + BOOL render() override; + void postRender(BOOL success) override; + + struct MaterialLoadLevels + { + S32 levels[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; + + MaterialLoadLevels(); + + S32& operator[](size_t i); + + const S32& operator[](size_t i) const; + + // Less is better + // Returns false if lhs is not strictly less or equal for all levels + bool operator<(const MaterialLoadLevels& other) const; + + // Less is better + // Returns false if lhs is not strictly greater or equal for all levels + bool operator>(const MaterialLoadLevels& other) const; + }; + +private: + LLPointer mGLTFMaterial; + bool mNeedsRender = true; + bool mShouldRender = true; + MaterialLoadLevels mBestLoad; +}; + +class LLGLTFMaterialPreviewMgr +{ + public: + // Returns null if the material is not loaded yet. + // *NOTE: User should cache the texture if the same material is being previewed + LLPointer getPreview(LLPointer &material); +}; + +extern LLGLTFMaterialPreviewMgr gGLTFMaterialPreviewMgr; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 69674417c1..84f6dd7a4f 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -27,6 +27,9 @@ #include "llviewerprecompiledheaders.h" #include "llreflectionmapmanager.h" + +#include + #include "llviewercamera.h" #include "llspatialpartition.h" #include "llviewerregion.h" @@ -1383,3 +1386,32 @@ void LLReflectionMapManager::doOcclusion() } } } + +void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force) +{ + static std::bitset mProbeWasOccluded; + + if (force) + { + for (size_t i = 0; i < mProbes.size(); ++i) + { + auto& probe = mProbes[i]; + mProbeWasOccluded[i] = probe->mOccluded; + if (probe != nullptr && probe != mDefaultProbe) + { + probe->mOccluded = true; + } + } + + updateUniforms(); + } + else + { + for (size_t i = 0; i < mProbes.size(); ++i) + { + auto& probe = mProbes[i]; + llassert(probe->mOccluded == (probe != mDefaultProbe)); + probe->mOccluded = mProbeWasOccluded[i]; + } + } +} diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index b77a33da89..dd641452ae 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -106,6 +106,11 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); + // *HACK: "cull" all reflection probes except the default one. Only call + // this if you don't intend to call updateUniforms directly. Call again + // with false when done. + void forceDefaultProbeAndUpdateUniforms(bool force = true); + private: friend class LLPipeline; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 233b864fba..b9cb00b561 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -72,6 +72,7 @@ #include "llradiogroup.h" #include "llfloaterreg.h" +#include "llgltfmaterialpreviewmgr.h" #include "lllocalbitmaps.h" #include "lllocalgltfmaterials.h" #include "llerror.h" @@ -657,6 +658,7 @@ void LLFloaterTexturePicker::draw() if( mOwner ) { mTexturep = NULL; + LLPointer old_material = mGLTFMaterial; mGLTFMaterial = NULL; if (mImageAssetID.notNull()) { @@ -664,10 +666,23 @@ void LLFloaterTexturePicker::draw() { mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID); llassert(mGLTFMaterial == nullptr || dynamic_cast(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr); + if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get()))) + { + // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. + if (mGLTFMaterial.isNull()) + { + mGLTFPreview = nullptr; + } + else + { + mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); + } + } } else { LLPointer texture = NULL; + mGLTFPreview = nullptr; if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) { @@ -677,7 +692,7 @@ void LLFloaterTexturePicker::draw() if (obj) { LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); - texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; } } @@ -718,27 +733,29 @@ void LLFloaterTexturePicker::draw() // If the floater is focused, don't apply its alpha to the texture (STORM-677). const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - LLViewerTexture* texture = nullptr; + LLViewerTexture* preview = nullptr; if (mGLTFMaterial) { - texture = mGLTFMaterial->getUITexture(); + preview = mGLTFPreview.get(); } else { - texture = mTexturep.get(); + preview = mTexturep.get(); + if (mTexturep) + { + // Pump the priority + mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } } - if( texture ) + if( preview ) { - if( texture->getComponents() == 4 ) + if( preview->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior, alpha ); } - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), texture, UI_VERTEX_COLOR % alpha ); - - // Pump the priority - texture->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha ); } else if (!mFallbackImage.isNull()) { @@ -2156,48 +2173,69 @@ void LLTextureCtrl::draw() { mBorder->setKeyboardFocusHighlight(hasFocus()); + LLPointer preview = NULL; + if (!mValid) { mTexturep = NULL; + mGLTFMaterial = NULL; + mGLTFPreview = NULL; } else if (!mImageAssetID.isNull()) { - LLPointer texture = NULL; - if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) { LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (obj) { LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); - texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + mTexturep = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + mGLTFMaterial = NULL; + mGLTFPreview = NULL; + + preview = mTexturep; } } - if (texture.isNull()) + if (preview.isNull()) { + LLPointer old_material = mGLTFMaterial; + mGLTFMaterial = NULL; + mTexturep = NULL; if (mInventoryPickType == PICK_MATERIAL) { - LLPointer material = gGLTFMaterialList.getMaterial(mImageAssetID); - if (material) + mGLTFMaterial = gGLTFMaterialList.getMaterial(mImageAssetID); + if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get()))) { - texture = material->getUITexture(); + // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. + if (mGLTFMaterial.isNull()) + { + mGLTFPreview = nullptr; + } + else + { + mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); + } } + + preview = mGLTFPreview; } else { - texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - texture->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - texture->forceToSaveRawImage(0); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + mTexturep->forceToSaveRawImage(0); + + preview = mTexturep; } } - - mTexturep = texture; } else//mImageAssetID == LLUUID::null { mTexturep = NULL; + mGLTFMaterial = NULL; + mGLTFPreview = NULL; } // Border @@ -2210,15 +2248,18 @@ void LLTextureCtrl::draw() // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677). const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - if( mTexturep ) + if( preview ) { - if( mTexturep->getComponents() == 4 ) + if( preview->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior, alpha ); } - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha); - mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha); + if (mTexturep) + { + mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); + } } else if (!mFallbackImage.isNull()) { diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index cb6ce636e0..77919637ac 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -250,6 +250,8 @@ private: commit_callback_t mOnCloseCallback; texture_selected_callback mOnTextureSelectedCallback; LLPointer mTexturep; + LLPointer mGLTFMaterial; + LLPointer mGLTFPreview; LLUIColor mBorderColor; LLUUID mImageItemID; LLUUID mImageAssetID; @@ -382,6 +384,7 @@ protected: LLPointer mTexturep; LLPointer mGLTFMaterial; + LLPointer mGLTFPreview; LLView* mOwner; LLUUID mImageAssetID; // Currently selected texture diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3882472b49..f34d5360e2 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -163,6 +163,7 @@ F32 LLPipeline::CameraFocusTransitionTime; F32 LLPipeline::CameraFNumber; F32 LLPipeline::CameraFocalLength; F32 LLPipeline::CameraFieldOfView; +S32 LLPipeline::RenderLocalLightCount; F32 LLPipeline::RenderShadowNoise; F32 LLPipeline::RenderShadowBlurSize; F32 LLPipeline::RenderSSAOScale; @@ -200,6 +201,8 @@ S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples; S32 LLPipeline::RenderBufferVisualization; LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); +const U32 LLPipeline::MAX_BAKE_WIDTH = 512; + const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f; const F32 ALPHA_BLEND_CUTOFF = 0.598f; @@ -521,6 +524,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("CameraFNumber"); connectRefreshCachedSettingsSafe("CameraFocalLength"); connectRefreshCachedSettingsSafe("CameraFieldOfView"); + connectRefreshCachedSettingsSafe("RenderLocalLightCount"); connectRefreshCachedSettingsSafe("RenderShadowNoise"); connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); connectRefreshCachedSettingsSafe("RenderSSAOScale"); @@ -1009,6 +1013,7 @@ void LLPipeline::refreshCachedSettings() CameraFNumber = gSavedSettings.getF32("CameraFNumber"); CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); + RenderLocalLightCount = gSavedSettings.getS32("RenderLocalLightCount"); RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); @@ -1072,7 +1077,6 @@ void LLPipeline::releaseGLBuffers() releaseLUTBuffers(); mWaterDis.release(); - mBake.release(); mSceneMap.release(); @@ -1151,9 +1155,6 @@ void LLPipeline::createGLBuffers() stop_glerror(); assertInitialized(); - // Use FBO for bake tex - mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview - stop_glerror(); GLuint resX = gViewerWindow->getWorldViewWidthRaw(); @@ -5227,7 +5228,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) return; } - static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); + const S32 local_light_count = LLPipeline::RenderLocalLightCount; if (local_light_count >= 1) { @@ -5496,7 +5497,7 @@ void LLPipeline::setupHWLights() mLightMovingMask = 0; - static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); + const S32 local_light_count = LLPipeline::RenderLocalLightCount; if (local_light_count >= 1) { @@ -7930,7 +7931,7 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredSoftenProgram); } - static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); + const S32 local_light_count = LLPipeline::RenderLocalLightCount; if (local_light_count > 0) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 88a7eab813..dd5040f76e 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -694,6 +694,7 @@ public: RenderTargetPack mMainRT; // auxillary 512x512 render target pack + // used by reflection probes and dynamic texture bakes RenderTargetPack mAuxillaryRT; // currently used render target pack @@ -754,7 +755,7 @@ public: //water distortion texture (refraction) LLRenderTarget mWaterDis; - LLRenderTarget mBake; + static const U32 MAX_BAKE_WIDTH; //texture for making the glow LLRenderTarget mGlow[3]; @@ -1012,6 +1013,7 @@ public: static F32 CameraFNumber; static F32 CameraFocalLength; static F32 CameraFieldOfView; + static S32 RenderLocalLightCount; static F32 RenderShadowNoise; static F32 RenderShadowBlurSize; static F32 RenderSSAOScale; -- cgit v1.2.3 From 8a3d82dd5fb6a9c5003a60a67e1c8c204caa67ab Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 18 Jan 2024 16:22:20 -0800 Subject: SL-20606: Reuse vertex buffer between preview renders. Fix preview sometimes zoomed in too much. Miscellaneous cleanup --- .../class1/deferred/postDeferredNoDoFF.glsl | 4 -- indra/newview/llgltfmaterialpreviewmgr.cpp | 76 ++++++++++++++++++---- 2 files changed, 65 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index cd4ae8110a..bace9b8c90 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -37,11 +37,7 @@ void main() { vec4 diff = texture(diffuseRect, vary_fragcoord.xy); -#if 1 frag_color = diff; -#else - frag_color = vec4(1,0,1,1); -#endif gl_FragDepth = texture(depthMap, vary_fragcoord.xy).r; } diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 9ef1bbf884..a8ea3429f4 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -27,6 +27,7 @@ #include "llgltfmaterialpreviewmgr.h" +#include #include #include "llavatarappearancedefines.h" @@ -210,12 +211,22 @@ struct GLTFPreviewModel { mDrawInfo->mModelMatrix = &mModelMatrix; } + GLTFPreviewModel(GLTFPreviewModel&) = delete; + ~GLTFPreviewModel() + { + // No model matrix necromancy + llassert(gGLLastMatrix != &mModelMatrix); + gGLLastMatrix = nullptr; + } LLPointer mDrawInfo; LLMatrix4 mModelMatrix; // Referenced by mDrawInfo }; +using PreviewSpherePart = std::unique_ptr; +using PreviewSphere = std::vector; + // Like LLVolumeGeometryManager::registerFace but without batching or too-many-indices/vertices checking. -std::vector create_preview_sphere(LLPointer& material, const LLMatrix4& model_matrix) +PreviewSphere create_preview_sphere(LLPointer& material, const LLMatrix4& model_matrix) { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; @@ -239,7 +250,7 @@ std::vector create_preview_sphere(LLPointer preview_sphere; + PreviewSphere preview_sphere; preview_sphere.reserve(volume->getNumFaces()); LLPointer buf = new LLVertexBuffer( @@ -299,7 +310,7 @@ std::vector create_preview_sphere(LLPointer info = new LLDrawInfo(U16(vertex_offset), U16(vertex_offset + face.mNumVertices - 1), face.mNumIndices, index_offset, no_media, buf.get()); info->mGLTFMaterial = material; - preview_sphere.emplace_back(info, model_matrix); + preview_sphere.emplace_back(std::make_unique(info, model_matrix)); index_offset += face.mNumIndices; vertex_offset += face.mNumVertices; } @@ -309,6 +320,44 @@ std::vector create_preview_sphere(LLPointer& material) +{ + llassert(!preview_sphere.empty()); + if (preview_sphere.empty()) { return; } + + const LLColor4U vertex_color(material->mBaseColor); + + // See comments about unmapBuffer in llvertexbuffer.h + for (PreviewSpherePart& part : preview_sphere) + { + LLDrawInfo* info = part->mDrawInfo.get(); + info->mGLTFMaterial = material; + LLVertexBuffer* buf = info->mVertexBuffer.get(); + LLStrider colors; + const S32 count = info->mEnd - info->mStart; + buf->getColorStrider(colors, info->mStart, count); + for (S32 i = 0; i < count; ++i) + { + *colors++ = vertex_color; + } + buf->unmapBuffer(); + } +} + +PreviewSphere& get_preview_sphere(LLPointer& material, const LLMatrix4& model_matrix) +{ + static PreviewSphere preview_sphere; + if (preview_sphere.empty()) + { + preview_sphere = create_preview_sphere(material, model_matrix); + } + else + { + set_preview_sphere_material(preview_sphere, material); + } + return preview_sphere; +} + // Final, direct modifications to shader constants, just before render void fixup_shader_constants(LLGLSLShader& shader) { @@ -354,10 +403,14 @@ BOOL LLGLTFPreviewTexture::render() LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; if (!mShouldRender) { return FALSE; } + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); LLGLDepthTest(GL_FALSE); LLGLDisable stencil(GL_STENCIL_TEST); LLGLDisable scissor(GL_SCISSOR_TEST); + SetTemporarily no_dof(&LLPipeline::RenderDepthOfField, false); SetTemporarily no_glow(&LLPipeline::sRenderGlow, false); SetTemporarily no_ssr(&LLPipeline::RenderScreenSpaceReflections, false); SetTemporarily no_fxaa(&LLPipeline::RenderFSAASamples, U32(0)); @@ -393,11 +446,7 @@ BOOL LLGLTFPreviewTexture::render() // Generate sphere object on-the-fly. Discard afterwards. (Vertex buffer is // discarded, but the sphere should be cached in LLVolumeMgr.) - std::vector preview_sphere = create_preview_sphere(mGLTFMaterial, object_transform); - - glClearColor(0, 0, 0, 0); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + PreviewSphere& preview_sphere = get_preview_sphere(mGLTFMaterial, object_transform); gPipeline.setupHWLights(); glh::matrix4f mat = copy_matrix(gGLModelView); @@ -415,10 +464,13 @@ BOOL LLGLTFPreviewTexture::render() LLRenderTarget& screen = gPipeline.mAuxillaryRT.screen; + // *HACK: Force reset of the model matrix + gGLLastMatrix = nullptr; + #if 0 if (mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE || mGLTFMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) { - // *TODO: Opaque/alpha mask rendering (gDeferredPBROpaqueProgram) + // *TODO: Opaque/alpha mask rendering } else #endif @@ -433,9 +485,9 @@ BOOL LLGLTFPreviewTexture::render() gPipeline.bindDeferredShader(shader); fixup_shader_constants(shader); - for (GLTFPreviewModel& part : preview_sphere) + for (PreviewSpherePart& part : preview_sphere) { - LLRenderPass::pushGLTFBatch(*part.mDrawInfo); + LLRenderPass::pushGLTFBatch(*part->mDrawInfo); } gPipeline.unbindDeferredShader(shader); @@ -453,6 +505,8 @@ BOOL LLGLTFPreviewTexture::render() gPipeline.renderDoF(&screen, &gPipeline.mPostMap); gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + // Final render + gDeferredPostNoDoFProgram.bind(); // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems." -- cgit v1.2.3 From 529d56ed9cc0b8399df79af40bea44431fc1def5 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 19 Jan 2024 17:09:11 -0800 Subject: SL-20606: Fix cached probe flags for material preview potentially exceeding storage bounds --- indra/newview/llreflectionmapmanager.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 84f6dd7a4f..2b6985b214 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -28,7 +28,7 @@ #include "llreflectionmapmanager.h" -#include +#include #include "llviewercamera.h" #include "llspatialpartition.h" @@ -1389,14 +1389,16 @@ void LLReflectionMapManager::doOcclusion() void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force) { - static std::bitset mProbeWasOccluded; + static std::vector mProbeWasOccluded; if (force) { + llassert(mProbeWasOccluded.empty()); + for (size_t i = 0; i < mProbes.size(); ++i) { auto& probe = mProbes[i]; - mProbeWasOccluded[i] = probe->mOccluded; + mProbeWasOccluded.push_back(probe->mOccluded); if (probe != nullptr && probe != mDefaultProbe) { probe->mOccluded = true; @@ -1407,11 +1409,16 @@ void LLReflectionMapManager::forceDefaultProbeAndUpdateUniforms(bool force) } else { - for (size_t i = 0; i < mProbes.size(); ++i) + llassert(mProbes.size() == mProbeWasOccluded.size()); + + const size_t n = llmin(mProbes.size(), mProbeWasOccluded.size()); + for (size_t i = 0; i < n; ++i) { auto& probe = mProbes[i]; llassert(probe->mOccluded == (probe != mDefaultProbe)); probe->mOccluded = mProbeWasOccluded[i]; } + mProbeWasOccluded.clear(); + mProbeWasOccluded.shrink_to_fit(); } } -- cgit v1.2.3 From 42623ad81142f93290b31b380cc0f888a1c3c3b6 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 19 Jan 2024 17:11:54 -0800 Subject: SL-20606: Fix no material preview on OpenGL 3.2 --- indra/newview/pipeline.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f34d5360e2..53be4c135e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -768,10 +768,13 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - if (mRT == &mMainRT && sReflectionProbesEnabled) + if (mRT == &mMainRT) { // hacky -- allocate auxillary buffer - gCubeSnapshot = TRUE; - mReflectionMapManager.initReflectionMaps(); + if (sReflectionProbesEnabled) + { + gCubeSnapshot = TRUE; + mReflectionMapManager.initReflectionMaps(); + } mRT = &mAuxillaryRT; U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); -- cgit v1.2.3 From 0625516e3838b940d3ed4be1167b7def147f5d22 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 22 Jan 2024 11:58:48 -0600 Subject: https://github.com/secondlife/viewer-issues/issues/22 partial build fix --- indra/newview/llviewershadermgr.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index f9c2906170..6495692e9a 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1275,7 +1275,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredPBRTerrainProgram.mFeatures.hasWaterFog = true; gDeferredPBRTerrainProgram.mFeatures.calculatesAtmospherics = true; gDeferredPBRTerrainProgram.mFeatures.hasAtmospherics = true; gDeferredPBRTerrainProgram.mFeatures.hasGamma = true; -- cgit v1.2.3 From 210d9204813318f55fb39505fda88d4a3544ae0e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 22 Jan 2024 20:43:53 +0200 Subject: Build fix for issues/22 --- indra/newview/lltexturectrl.cpp | 12 ++++++------ indra/newview/lltexturectrl.h | 28 ++++++++-------------------- 2 files changed, 14 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index c330696fb2..368222f7a0 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -2367,12 +2367,12 @@ LLSD LLTextureCtrl::getValue() const namespace LLInitParam { - void TypeValues::declareValues() - { - declare("texture_material", LLTextureCtrl::PICK_TEXTURE_MATERIAL); - declare("texture", LLTextureCtrl::PICK_TEXTURE); - declare("material", LLTextureCtrl::PICK_MATERIAL); - } + void TypeValues::declareValues() + { + declare("texture_material", PICK_TEXTURE_MATERIAL); + declare("texture", PICK_TEXTURE); + declare("material", PICK_MATERIAL); + } } diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index d71566c526..5c7091a9b5 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -64,17 +64,18 @@ bool get_is_predefined_texture(LLUUID asset_id); LLUUID get_copy_free_item_by_asset_id(LLUUID image_id, bool no_trans_perm = false); bool get_can_copy_texture(LLUUID image_id); -enum class LLTexPickInventoryType : U32 + +typedef enum e_pick_inventory_type { - TEXTURE_MATERIAL = 0, - TEXTURE = 1, - MATERIAL = 2, -}; + PICK_TEXTURE_MATERIAL = 0, + PICK_TEXTURE = 1, + PICK_MATERIAL = 2, +} EPickInventoryType; namespace LLInitParam { template<> - struct TypeValues : public TypeValuesHelper + struct TypeValues : public TypeValuesHelper { static void declareValues(); }; @@ -88,13 +89,6 @@ enum LLPickerSource PICKER_UNKNOWN, // on cancel, default ids }; -typedef enum e_pick_inventory_type -{ - PICK_TEXTURE_MATERIAL = 0, - PICK_TEXTURE = 1, - PICK_MATERIAL = 2, -} EPickInventoryType; - ////////////////////////////////////////////////////////////////////////////////////////// // LLTextureCtrl @@ -110,12 +104,6 @@ public: TEXTURE_CANCEL } ETexturePickOp; - // *HACK: Can't forward-declare an enum scoped inside a class. Maybe there's a better way to initialize LLInitParam::TypeValues that doesn't run into this limitation. - typedef LLTexPickInventoryType EPickInventoryType; - static const EPickInventoryType PICK_TEXTURE_MATERIAL = LLTexPickInventoryType::TEXTURE_MATERIAL; - static const EPickInventoryType PICK_TEXTURE = LLTexPickInventoryType::TEXTURE; - static const EPickInventoryType PICK_MATERIAL = LLTexPickInventoryType::MATERIAL; - public: struct Params : public LLInitParam::Block { @@ -140,7 +128,7 @@ public: : image_id("image"), default_image_id("default_image_id"), default_image_name("default_image_name"), - pick_type("pick_type", LLTexPickInventoryType::TEXTURE), + pick_type("pick_type", PICK_TEXTURE), allow_no_texture("allow_no_texture", false), can_apply_immediately("can_apply_immediately"), no_commit_on_selection("no_commit_on_selection", false), -- cgit v1.2.3 From 7b0372ac1f6191ef9216296cef2f476caadee40c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 23 Jan 2024 13:12:54 -0800 Subject: Put PBR terrain behind feature flag --- indra/newview/app_settings/settings.xml | 11 ++++++ indra/newview/llfloaterregioninfo.cpp | 41 ++++++++++++++-------- .../skins/default/xui/en/panel_region_terrain.xml | 16 ++++++++- 3 files changed, 53 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 578bb02387..df30b8d298 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10833,6 +10833,17 @@ Value 12.0 + RenderTerrainPBREnabled + + Comment + EXPERIMENTAL: Enable PBR Terrain features. Requires restart. + Persist + 1 + Type + Boolean + Value + 0 + RenderTerrainPBRDetail Comment diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 15ac46dc21..2c743d596e 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1441,32 +1441,45 @@ BOOL LLPanelRegionTerrainInfo::postBuild() mAskedTextureHeights = false; mConfirmedTextureHeights = false; + refresh(); + return LLPanelRegionInfo::postBuild(); } // virtual void LLPanelRegionTerrainInfo::refresh() { - std::string buffer; + // For simplicity, require restart + static BOOL feature_pbr_terrain_enabled = gSavedSettings.getBOOL("RenderTerrainPBREnabled"); - bool has_material_assets = false; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - LLTextureCtrl* material_ctrl = getChild(buffer); - if (material_ctrl && material_ctrl->getImageAssetID().notNull()) - { - has_material_assets = true; - break; - } - } + LLTextBox* texture_text = getChild("detail_texture_text"); + if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); } LLComboBox* material_type_ctrl = getChild("terrain_material_type"); if (material_type_ctrl) { - const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + material_type_ctrl->setVisible(feature_pbr_terrain_enabled); + + bool has_material_assets = false; + + std::string buffer; + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + LLTextureCtrl* material_ctrl = getChild(buffer); + if (material_ctrl && material_ctrl->getImageAssetID().notNull()) + { + has_material_assets = true; + break; + } + } + + TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); + + if (!feature_pbr_terrain_enabled) { material_type = TerrainMaterialType::TEXTURE; } + const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; - material_type_ctrl->setEnabled(!(is_material_selected && has_material_assets)); + material_type_ctrl->setEnabled(feature_pbr_terrain_enabled && !(is_material_selected && has_material_assets)); } } diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index e36fb05647..88855ab739 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -92,6 +92,20 @@ name="PBRMaterials" value="PBRMaterials" /> + + Terrain Textures + Maximum size: 1024x1024 -- cgit v1.2.3 From 4d39d889976dcc3b7aa7098bc70ab7ebb881c0a8 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 15:50:13 -0800 Subject: https://github.com/secondlife/viewer/issues/671 Wire up the RenderMirrors debug setting. --- indra/newview/app_settings/settings.xml | 2 +- .../app_settings/shaders/class3/deferred/softenLightF.glsl | 11 ++++++----- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llviewershadermgr.cpp | 5 ++++- indra/newview/pipeline.cpp | 14 ++++++++++---- indra/newview/pipeline.h | 1 + 6 files changed, 23 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 493ccec560..242e274daf 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9206,7 +9206,7 @@ Type Boolean Value - 1 + 0 RenderScreenSpaceReflections diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index f5541df227..79d9000482 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -34,11 +34,13 @@ uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal uniform samplerCubeArray heroProbes; +#if defined(HERO_PROBES) layout (std140) uniform HeroProbeData { vec4 heroPosition[1]; int heroProbeCount; }; +#endif const float M_PI = 3.14159265; @@ -196,15 +198,12 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); + #ifdef HERO_PROBES vec3 refnormpersp = reflect(pos.xyz, norm.xyz); if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; - - if (do_atmospherics) - { - color = atmosFragLightingLinear(color, additive, atten); - } + #endif } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -263,7 +262,9 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); + #ifdef HERO_PROBES color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; + #endif } diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index b6db123cd9..fdf782adee 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -67,7 +67,7 @@ LLHeroProbeManager::LLHeroProbeManager() // helper class to seed octree with probes void LLHeroProbeManager::update() { - if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) { return; } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 693297d1e1..48c54f3dcc 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1805,7 +1805,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); + if (LLPipeline::RenderMirrors) + { + gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); + } if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9e6af24f80..94f2dc4a2a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -199,6 +199,7 @@ F32 LLPipeline::RenderScreenSpaceReflectionDepthRejectBias; F32 LLPipeline::RenderScreenSpaceReflectionAdaptiveStepMultiplier; S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples; S32 LLPipeline::RenderBufferVisualization; +bool LLPipeline::RenderMirrors; LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); const U32 LLPipeline::MAX_BAKE_WIDTH = 512; @@ -559,6 +560,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionGlossySamples"); connectRefreshCachedSettingsSafe("RenderBufferVisualization"); + connectRefreshCachedSettingsSafe("RenderMirrors"); gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } @@ -1058,6 +1060,7 @@ void LLPipeline::refreshCachedSettings() RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples"); RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); + RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; @@ -8645,11 +8648,14 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) bound = true; } - channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mHeroProbeManager.mTexture.notNull()) + if (RenderMirrors) { - mHeroProbeManager.mTexture->bind(channel); - bound = true; + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mHeroProbeManager.mTexture.notNull()) + { + mHeroProbeManager.mTexture->bind(channel); + bound = true; + } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 30bc95ad19..21c1d9a25d 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1051,6 +1051,7 @@ public: static F32 RenderScreenSpaceReflectionAdaptiveStepMultiplier; static S32 RenderScreenSpaceReflectionGlossySamples; static S32 RenderBufferVisualization; + static bool RenderMirrors; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.2.3 From 42b51bfd2cccba1dfdc820a4a033481fd42c1907 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 16:02:31 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Fix for merge up to the featurettes branch, and reflection probes being "hazy" --- .../shaders/class3/deferred/softenLightF.glsl | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 79d9000482..f1de0b88d6 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -114,8 +114,8 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 additive, vec3 atten); -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -176,9 +176,9 @@ void main() vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR) || GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) + if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 orm = texture(specularRect, tc).rgb; + vec3 orm = texture(specularRect, tc).rgb; float perceptualRoughness = orm.g; float metallic = orm.b; float ao = orm.r; @@ -275,12 +275,7 @@ void main() applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity); } } - - #ifdef WATER_FOG - vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom)); - color = fogged.rgb; - #endif - + frag_color.rgb = max(color.rgb, vec3(0)); //output linear since local lights will be added to this shader's results frag_color.a = 0.0; } -- cgit v1.2.3 From a888531fd1fbf7de0d71b4d04195d4267c882154 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 16:22:45 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Make the face selection for mirrors actually reflect what it does --- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llviewerobject.cpp | 8 ++++---- indra/newview/llviewerobject.h | 4 ++-- indra/newview/llvovolume.cpp | 4 ++-- indra/newview/llvovolume.h | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index fdf782adee..1ecafd4f54 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -138,7 +138,7 @@ void LLHeroProbeManager::update() if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - U8 mode = mNearestHero->mirrorPlacementMode(); + U8 mode = mNearestHero->mirrorFace(); mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); mCurrentFace = mNearestHero->mDrawable->getFace(mode); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 88494f419c..691a2e14d3 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -314,8 +314,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), mRiggedAttachedWarned(false), -mIsMirror(false), -mMirrorPlacementMode(3) + mIsMirror(false), + mMirrorFace(3) { if (!is_global) { @@ -1558,7 +1558,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + detectMirror(temp_string, mIsMirror, mMirrorFace); LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1946,7 +1946,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; dp->unpackString(temp_string, "Text"); - detectMirror(temp_string, mIsMirror, mMirrorPlacementMode); + detectMirror(temp_string, mIsMirror, mMirrorFace); LLColor4U coloru; dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 6ed37bf014..f3c00e83dc 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -258,7 +258,7 @@ public: virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } virtual BOOL isMirror() const { return FALSE; } - virtual U8 mirrorPlacementMode() const { return 0; } + virtual U8 mirrorFace() const { return 0; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -881,7 +881,7 @@ protected: F32 mLinksetPhysicsCost; bool mIsMirror; - U8 mMirrorPlacementMode; + U8 mMirrorFace; // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 91e64d611c..9813039145 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3364,9 +3364,9 @@ BOOL LLVOVolume::isMirror() const return mIsMirror; } -U8 LLVOVolume::mirrorPlacementMode() const +U8 LLVOVolume::mirrorFace() const { - return mMirrorPlacementMode; + return mMirrorFace; } BOOL LLVOVolume::isReflectionProbe() const diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 848f455e2a..b03fc4b862 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,7 +298,7 @@ public: // Mirrors bool setIsMirror(BOOL is_mirror); void updateMirrorDrawable(); - U8 mirrorPlacementMode() const override; + U8 mirrorFace() const override; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); -- cgit v1.2.3 From 2510134f40c2edd2eea40f486f094517b8ffaa51 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 17:07:56 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/23 Cleaning out some unused code. --- indra/newview/llface.cpp | 12 ------------ indra/newview/llface.h | 5 ----- 2 files changed, 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 2c04224fa0..69e43bb458 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -488,11 +488,6 @@ U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &no return mGeomIndex; } -LLVector3 LLFace::getAverageNormal() -{ - return mAverageNormal; -} - void LLFace::updateCenterAgent() { if (mDrawablep->isActive()) @@ -1895,20 +1890,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a* src = vf.mNormals; LLVector4a* end = src+num_vertices; - LLVector4a normal_total; - while (src < end) { LLVector4a normal; mat_normal.rotate(*src++, normal); normal.store4a(normals); - normal_total.add(normal); normals += 4; } - - normal_total.div(LLVector4a(num_vertices)); - - mAverageNormal = LLVector3(normal_total[0], normal_total[1], normal_total[2]); } if (rebuild_tangent) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index d4f4313073..eb3b47d6d6 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -176,8 +176,6 @@ public: LLStrider &normals, LLStrider &texCoords, LLStrider &indices); - - LLVector3 getAverageNormal(); S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); @@ -280,9 +278,6 @@ private: U32 mIndicesCount; U32 mIndicesIndex; // index into mVertexBuffer's index array S32 mIndexInTex[LLRender::NUM_TEXTURE_CHANNELS]; - - LLVector3 mAverageNormal; - bool mHasAverageNormal; LLXformMatrix* mXform; -- cgit v1.2.3 From 4e90bd3cc0a4c1021cf8e688e008a0f0418d8364 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 24 Jan 2024 22:34:25 -0800 Subject: https://github.com/secondlife/viewer-issues/issues/36 Make sure we set the mirror flag appropriately. --- indra/newview/lldrawpoolmaterials.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index ec229711ea..063dd948f7 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -185,7 +185,11 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) if (gPipeline.mHeroProbeManager.isMirrorPass()) { - glUniform1f(LLShaderMgr::MIRROR_FLAG, 1); + mShader->uniform1f(LLShaderMgr::MIRROR_FLAG, 1); + } + else + { + mShader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); } LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0], -- cgit v1.2.3 From 97764080b0eaf7b359b7e2332e6c1257ba86a71a Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 23 Jan 2024 15:17:15 -0800 Subject: Review feedback: Remove static RenderLocalLightCount, as cached settings refresh has surprising performance cost --- indra/newview/llgltfmaterialpreviewmgr.cpp | 5 ++++- indra/newview/pipeline.cpp | 9 +++------ indra/newview/pipeline.h | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index a8ea3429f4..1dba3f082f 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -34,6 +34,7 @@ #include "llenvironment.h" #include "llselectmgr.h" #include "llviewercamera.h" +#include "llviewercontrol.h" #include "llviewerobject.h" #include "llviewershadermgr.h" #include "llviewertexturelist.h" @@ -419,7 +420,8 @@ BOOL LLGLTFPreviewTexture::render() LLVector3 light_dir3(1.0f, 1.0f, 1.0f); light_dir3.normalize(); const LLVector4 light_dir = LLVector4(light_dir3, 0); - SetTemporarily sun_light_only(&LLPipeline::RenderLocalLightCount, 0); + const S32 old_local_light_count = gSavedSettings.get("RenderLocalLightCount"); + gSavedSettings.set("RenderLocalLightCount", 0); gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(); @@ -524,6 +526,7 @@ BOOL LLGLTFPreviewTexture::render() // Clean up gPipeline.setupHWLights(); gPipeline.mReflectionMapManager.forceDefaultProbeAndUpdateUniforms(false); + gSavedSettings.set("RenderLocalLightCount", old_local_light_count); return TRUE; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 94f2dc4a2a..d81bcef259 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -163,7 +163,6 @@ F32 LLPipeline::CameraFocusTransitionTime; F32 LLPipeline::CameraFNumber; F32 LLPipeline::CameraFocalLength; F32 LLPipeline::CameraFieldOfView; -S32 LLPipeline::RenderLocalLightCount; F32 LLPipeline::RenderShadowNoise; F32 LLPipeline::RenderShadowBlurSize; F32 LLPipeline::RenderSSAOScale; @@ -525,7 +524,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("CameraFNumber"); connectRefreshCachedSettingsSafe("CameraFocalLength"); connectRefreshCachedSettingsSafe("CameraFieldOfView"); - connectRefreshCachedSettingsSafe("RenderLocalLightCount"); connectRefreshCachedSettingsSafe("RenderShadowNoise"); connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); connectRefreshCachedSettingsSafe("RenderSSAOScale"); @@ -1025,7 +1023,6 @@ void LLPipeline::refreshCachedSettings() CameraFNumber = gSavedSettings.getF32("CameraFNumber"); CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); - RenderLocalLightCount = gSavedSettings.getS32("RenderLocalLightCount"); RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); @@ -5262,7 +5259,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) return; } - const S32 local_light_count = LLPipeline::RenderLocalLightCount; + static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); if (local_light_count >= 1) { @@ -5531,7 +5528,7 @@ void LLPipeline::setupHWLights() mLightMovingMask = 0; - const S32 local_light_count = LLPipeline::RenderLocalLightCount; + static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); if (local_light_count >= 1) { @@ -7965,7 +7962,7 @@ void LLPipeline::renderDeferredLighting() unbindDeferredShader(gDeferredSoftenProgram); } - const S32 local_light_count = LLPipeline::RenderLocalLightCount; + static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); if (local_light_count > 0) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 21c1d9a25d..5ace90b000 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1015,7 +1015,6 @@ public: static F32 CameraFNumber; static F32 CameraFocalLength; static F32 CameraFieldOfView; - static S32 RenderLocalLightCount; static F32 RenderShadowNoise; static F32 RenderShadowBlurSize; static F32 RenderSSAOScale; -- cgit v1.2.3 From 1691a25ce801bfd22cfc89958a07c4f53d3af772 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 24 Jan 2024 13:57:46 -0800 Subject: Fix material preview sometimes not updating when transitioning from blank material to non-blank material --- indra/newview/llfetchedgltfmaterial.h | 2 ++ indra/newview/llgltfmaterialpreviewmgr.cpp | 2 ++ indra/newview/lltexturectrl.cpp | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 3fa4619d8c..42c835a416 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -40,6 +40,8 @@ public: virtual ~LLFetchedGLTFMaterial(); LLFetchedGLTFMaterial& operator=(const LLFetchedGLTFMaterial& rhs); + // LLGLTFMaterial::operator== is defined, but LLFetchedGLTFMaterial::operator== is not. + bool operator==(const LLGLTFMaterial& rhs) const = delete; // If this material is loaded, fire the given function void onMaterialComplete(std::function material_complete); diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 1dba3f082f..394f600a92 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -130,6 +130,8 @@ namespace LLGLTFPreviewTexture::MaterialLoadLevels get_material_load_levels(LLFetchedGLTFMaterial& material) { + llassert(!material.isFetching()); + using MaterialTextures = LLPointer*[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; MaterialTextures textures; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 916c0194c2..febda177e2 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -666,7 +666,7 @@ void LLFloaterTexturePicker::draw() { mGLTFMaterial = (LLFetchedGLTFMaterial*) gGLTFMaterialList.getMaterial(mImageAssetID); llassert(mGLTFMaterial == nullptr || dynamic_cast(gGLTFMaterialList.getMaterial(mImageAssetID)) != nullptr); - if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get()))) + if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (old_material.get() != mGLTFMaterial.get()))) { // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. if (mGLTFMaterial.isNull()) @@ -2206,7 +2206,7 @@ void LLTextureCtrl::draw() if (mInventoryPickType == PICK_MATERIAL) { mGLTFMaterial = gGLTFMaterialList.getMaterial(mImageAssetID); - if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (*old_material.get() != *mGLTFMaterial.get()))) + if (mGLTFPreview.isNull() || mGLTFMaterial.isNull() || (old_material.notNull() && (old_material.get() != mGLTFMaterial.get()))) { // Only update the preview if needed, since gGLTFMaterialPreviewMgr does not cache the preview. if (mGLTFMaterial.isNull()) -- cgit v1.2.3 From 8a1e2f98cbbc242d2721deaa92ed34c3f3fcf788 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 24 Jan 2024 14:33:24 -0800 Subject: Fix vertex color indexing in material preview --- indra/newview/llgltfmaterialpreviewmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 394f600a92..09a2954710 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -337,7 +337,7 @@ void set_preview_sphere_material(PreviewSphere& preview_sphere, LLPointermGLTFMaterial = material; LLVertexBuffer* buf = info->mVertexBuffer.get(); LLStrider colors; - const S32 count = info->mEnd - info->mStart; + const S32 count = info->mEnd - info->mStart + 1; buf->getColorStrider(colors, info->mStart, count); for (S32 i = 0; i < count; ++i) { -- cgit v1.2.3 From 18669f3be7d61815203eddbfb866d551aba9bc69 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 25 Jan 2024 16:05:55 -0800 Subject: Don't refetch textures for LLFetchedGLTFMaterial if present --- indra/newview/llgltfmaterialpreviewmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 09a2954710..53d9d7d0ba 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -96,7 +96,7 @@ namespace { void fetch_texture_for_ui(LLPointer& img, const LLUUID& id) { - if (id.notNull()) + if (!img && id.notNull()) { if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) { -- cgit v1.2.3 From 00c65b62707f5c30cf2d48c0bd0c975c3bceb513 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 15 Sep 2023 14:27:15 -0700 Subject: secondlife/viewer-issues#43: Fix debug normals not rendering for terrain --- indra/llrender/llshadermgr.cpp | 23 ++- indra/llrender/llshadermgr.h | 3 + .../shaders/class1/interface/normaldebugF.glsl | 33 ++++ .../shaders/class1/interface/normaldebugG.glsl | 76 +++++++++ .../shaders/class1/interface/normaldebugV.glsl | 74 +++++++++ indra/newview/llspatialpartition.cpp | 171 +++++++++++++++------ indra/newview/llviewershadermgr.cpp | 29 ++++ indra/newview/llviewershadermgr.h | 8 + indra/newview/pipeline.cpp | 1 + 9 files changed, 365 insertions(+), 53 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl create mode 100644 indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 14f3086eb6..33d229bcc9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -588,11 +588,22 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } else { - //set version to 1.40 - shader_code_text[shader_code_count++] = strdup("#version 140\n"); - //some implementations of GLSL 1.30 require integer precision be explicitly declared - extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); - extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); + if (type == GL_GEOMETRY_SHADER) + { + //set version to 1.50 + shader_code_text[shader_code_count++] = strdup("#version 150\n"); + //some implementations of GLSL 1.30 require integer precision be explicitly declared + extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); + extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); + } + else + { + //set version to 1.40 + shader_code_text[shader_code_count++] = strdup("#version 140\n"); + //some implementations of GLSL 1.30 require integer precision be explicitly declared + extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); + extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); + } } extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); @@ -1453,6 +1464,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("sun_up_factor"); mReservedUniforms.push_back("moonlight_color"); + mReservedUniforms.push_back("debug_normal_draw_length"); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); std::set dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index ebd682141d..4ee5c8ef47 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -316,6 +316,9 @@ public: WATER_EDGE_FACTOR, // "water_edge" SUN_UP_FACTOR, // "sun_up_factor" MOONLIGHT_COLOR, // "moonlight_color" + + DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length" + END_RESERVED_UNIFORMS } eGLSLReservedUniforms; // clang-format on diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl new file mode 100644 index 0000000000..388042e7e0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl @@ -0,0 +1,33 @@ +/** + * @file normaldebugF.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +out vec4 frag_color; + +in vec4 vertex_color; + +void main() +{ + frag_color = max(vertex_color, vec4(0)); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl new file mode 100644 index 0000000000..ea04ce1cae --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl @@ -0,0 +1,76 @@ +/** + * @file normaldebugG.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +// *NOTE: Geometry shaders have a reputation for being slow. Consider using +// compute shaders instead, which have a reputation for being fast. This +// geometry shader in particular seems to run fine on my machine, but I won't +// vouch for this in performance-critical areas. +// -Cosmic,2023-09-28 + +out vec4 vertex_color; + +in vec4 normal_g[]; +#if HAS_ATTRIBUTE_TANGENT == 1 +in vec4 tangent_g[]; +#endif + +layout(TRIANGLES) in; +#if HAS_ATTRIBUTE_TANGENT == 1 +layout(LINE_STRIP, max_vertices = 12) out; +#else +layout(LINE_STRIP, max_vertices = 6) out; +#endif + +void triangle_normal_debug(int i) +{ + // Normal + vec4 normal_color = vec4(1.0, 1.0, 0.0, 1.0); + gl_Position = gl_in[i].gl_Position; + vertex_color = normal_color; + EmitVertex(); + gl_Position = normal_g[i]; + vertex_color = normal_color; + EmitVertex(); + EndPrimitive(); + +#if HAS_ATTRIBUTE_TANGENT == 1 + // Tangent + vec4 tangent_color = vec4(0.0, 1.0, 1.0, 1.0); + gl_Position = gl_in[i].gl_Position; + vertex_color = tangent_color; + EmitVertex(); + gl_Position = tangent_g[i]; + vertex_color = tangent_color; + EmitVertex(); + EndPrimitive(); +#endif +} + +void main() +{ + triangle_normal_debug(0); + triangle_normal_debug(1); + triangle_normal_debug(2); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl new file mode 100644 index 0000000000..d1596b9d2a --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl @@ -0,0 +1,74 @@ +/** + * @file normaldebugV.glsl + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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$ + */ + +in vec3 position; +in vec3 normal; +out vec4 normal_g; +#if HAS_ATTRIBUTE_TANGENT == 1 +in vec4 tangent; +out vec4 tangent_g; +#endif + +uniform float debug_normal_draw_length; + +#ifdef HAS_SKIN +mat4 getObjectSkinnedTransform(); +#else +uniform mat3 normal_matrix; +#endif +uniform mat4 projection_matrix; +uniform mat4 modelview_matrix; + +// *NOTE: Should use the modelview_projection_matrix here in the non-skinned +// case for efficiency, but opting for the simplier implementation for now as +// this is debug code. Also, the skinned version hasn't beeen tested yet. +// world_pos = mat * vec4(position.xyz, 1.0) +vec4 get_screen_normal(vec3 position, vec4 world_pos, vec3 normal, mat4 mat) +{ + vec4 world_norm = mat * vec4((position + normal), 1.0); + world_norm.xyz -= world_pos.xyz; + world_norm.xyz = debug_normal_draw_length * normalize(world_norm.xyz); + world_norm.xyz += world_pos.xyz; + return projection_matrix * world_norm; +} + +void main() +{ +#ifdef HAS_SKIN + mat4 mat = getObjectSkinnedTransform(); + mat = modelview_matrix * mat; +#else +#define mat modelview_matrix +#endif + + vec4 world_pos = mat * vec4(position.xyz,1.0); + + gl_Position = projection_matrix * world_pos; + normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat); +#if HAS_ATTRIBUTE_TANGENT == 1 + tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat); +#endif +} + diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 931880a475..40e8e526d1 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -47,6 +47,7 @@ #include "pipeline.h" #include "llmeshrepository.h" #include "llrender.h" +#include "lldrawpool.h" #include "lloctree.h" #include "llphysicsshapebuilderutil.h" #include "llvoavatar.h" @@ -2000,7 +2001,11 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) drawBoxOutline(pos,size); } } - +// *TODO: LLDrawables which are not part of LLVOVolumes fall into a different +// code path which uses a shader - it was tested to be faster than mapping a +// vertex buffer in the terrain case. Consider using it for LLVOVolumes as well +// to simplify and speed up this debug code. Alternatively, a compute shader is +// likely faster. -Cosmic,2023-09-28 void renderNormals(LLDrawable *drawablep) { if (!drawablep->isVisible()) @@ -2008,11 +2013,13 @@ void renderNormals(LLDrawable *drawablep) LLVertexBuffer::unbind(); + LLViewerObject* obj = drawablep->getVObj(); LLVOVolume *vol = drawablep->getVOVolume(); - if (vol) + if (obj) { - LLVolume *volume = vol->getVolume(); + LLGLEnable blend(GL_BLEND); + LLGLDepthTest gl_depth(GL_TRUE, GL_FALSE); // Drawable's normals & tangents are stored in model space, i.e. before any scaling is applied. // @@ -2021,68 +2028,136 @@ void renderNormals(LLDrawable *drawablep) // transform. We get that effect here by pre-applying the inverse scale (twice, because // one forward scale will be re-applied via the MVP in the vertex shader) - LLVector3 scale_v3 = vol->getScale(); - float scale_len = scale_v3.length(); - LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]); - obj_scale.normalize3(); + LLVector4a inv_scale; + float scale_len; + if (vol) + { + LLVector3 scale_v3 = vol->getScale(); + LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]); + obj_scale.normalize3(); - // Normals &tangent line segments get scaled along with the object. Divide by scale length - // to keep the as-viewed lengths (relatively) constant with the debug setting length - float draw_length = gSavedSettings.getF32("RenderDebugNormalScale") / scale_len; + // Create inverse-scale vector for normals + inv_scale.set(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ], 0.0); + inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice - // Create inverse-scale vector for normals - LLVector4a inv_scale(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ]); - inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice - inv_scale.normalize3fast(); + inv_scale.normalize3fast(); + scale_len = scale_v3.length(); + } + else + { + inv_scale.set(1.0, 1.0, 1.0, 0.0); + scale_len = 1.0; + } gGL.pushMatrix(); - gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix); + if (vol) + { + gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix); + } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + // Normals &tangent line segments get scaled along with the object. Divide by scale length + // to keep the as-viewed lengths (relatively) constant with the debug setting length + float draw_length = gSavedSettings.getF32("RenderDebugNormalScale") / scale_len; + + std::vector* faces = nullptr; + std::vector* drawable_faces = nullptr; + if (vol) + { + LLVolume* volume = vol->getVolume(); + faces = &volume->getVolumeFaces(); + } + else { - const LLVolumeFace &face = volume->getVolumeFace(i); + drawable_faces = &drawablep->getFaces(); + } - gGL.flush(); - gGL.diffuseColor4f(1, 1, 0, 1); - gGL.begin(LLRender::LINES); - for (S32 j = 0; j < face.mNumVertices; ++j) - { - LLVector4a n, p; + if (faces) + { + for (auto it = faces->begin(); it != faces->end(); ++it) + { + const LLVolumeFace& face = *it; + + gGL.flush(); + gGL.diffuseColor4f(1, 1, 0, 1); + gGL.begin(LLRender::LINES); + for (S32 j = 0; j < face.mNumVertices; ++j) + { + LLVector4a n, p; - n.setMul(face.mNormals[j], 1.0); - n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP - n.normalize3fast(); - n.mul(draw_length); - p.setAdd(face.mPositions[j], n); + n.setMul(face.mNormals[j], 1.0); + n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP + n.normalize3fast(); + n.mul(draw_length); + p.setAdd(face.mPositions[j], n); - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - } - gGL.end(); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + + // Tangents are simple vectors and do not require reorientation via pre-scaling + if (face.mTangents) + { + gGL.flush(); + gGL.diffuseColor4f(0, 1, 1, 1); + gGL.begin(LLRender::LINES); + for (S32 j = 0; j < face.mNumVertices; ++j) + { + LLVector4a t, p; - // Tangents are simple vectors and do not require reorientation via pre-scaling - if (face.mTangents) + t.setMul(face.mTangents[j], 1.0f); + t.normalize3fast(); + t.mul(draw_length); + p.setAdd(face.mPositions[j], t); + + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + } + } + } + else if (drawable_faces) + { + // *HACK: Prepare to restore previous shader as other debug code depends on a simpler shader being present + llassert(LLGLSLShader::sCurBoundShaderPtr == &gDebugProgram); + LLGLSLShader* prev_shader = LLGLSLShader::sCurBoundShaderPtr; + for (auto it = drawable_faces->begin(); it != drawable_faces->end(); ++it) { - gGL.flush(); - gGL.diffuseColor4f(0, 1, 1, 1); - gGL.begin(LLRender::LINES); - for (S32 j = 0; j < face.mNumVertices; ++j) + LLFace* facep = *it; + LLFace& face = **it; + LLVertexBuffer* buf = face.getVertexBuffer(); + if (!buf) { continue; } + U32 mask_vn = LLVertexBuffer::TYPE_VERTEX | LLVertexBuffer::TYPE_NORMAL; + if ((buf->getTypeMask() & mask_vn) != mask_vn) { continue; } + + LLGLSLShader* shader; + if ((buf->getTypeMask() & LLVertexBuffer::TYPE_TANGENT) != LLVertexBuffer::TYPE_TANGENT) { - LLVector4a t, p; + shader = &gNormalDebugProgram[NORMAL_DEBUG_SHADER_DEFAULT]; + } + else + { + shader = &gNormalDebugProgram[NORMAL_DEBUG_SHADER_WITH_TANGENTS]; + } + shader->bind(); - t.setMul(face.mTangents[j], 1.0f); - t.normalize3fast(); - t.mul(draw_length); - p.setAdd(face.mPositions[j], t); + shader->uniform1f(LLShaderMgr::DEBUG_NORMAL_DRAW_LENGTH, draw_length); - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - } - gGL.end(); + LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix); + + buf->setBuffer(); + // *NOTE: The render type in the vertex shader is TRIANGLES, but gets converted to LINES in the geometry shader + // *NOTE: For terrain normal debug, this seems to also include vertices for water, which is technically not part of the terrain. Should fix that at some point. + buf->drawRange(LLRender::TRIANGLES, face.getGeomIndex(), face.getGeomIndex() + face.getGeomCount()-1, face.getIndicesCount(), face.getIndicesStart()); } - } + if (prev_shader) + { + prev_shader->bind(); + } + } gGL.popMatrix(); } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 48c54f3dcc..7e49ea3b7c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -91,6 +91,8 @@ LLGLSLShader gTwoTextureCompareProgram; LLGLSLShader gOneTextureFilterProgram; LLGLSLShader gDebugProgram; LLGLSLShader gSkinnedDebugProgram; +LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; LLGLSLShader gClipProgram; LLGLSLShader gAlphaMaskProgram; LLGLSLShader gBenchmarkProgram; @@ -2692,6 +2694,33 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = success && gDebugProgram.createShader(NULL, NULL); } + if (success) + { + for (S32 variant = 0; variant < NORMAL_DEBUG_SHADER_COUNT; ++variant) + { + LLGLSLShader& shader = gNormalDebugProgram[variant]; + LLGLSLShader& skinned_shader = gSkinnedNormalDebugProgram[variant]; + shader.mName = "Normal Debug Shader"; + shader.mShaderFiles.clear(); + shader.mShaderFiles.push_back(make_pair("interface/normaldebugV.glsl", GL_VERTEX_SHADER)); + // *NOTE: Geometry shaders have a reputation for being slow. + // Consider using compute shaders instead, which have a reputation + // for being fast. This geometry shader in particular seems to run + // fine on my machine, but I won't vouch for this in + // performance-critical areas. -Cosmic,2023-09-28 + shader.mShaderFiles.push_back(make_pair("interface/normaldebugG.glsl", GL_GEOMETRY_SHADER)); + shader.mShaderFiles.push_back(make_pair("interface/normaldebugF.glsl", GL_FRAGMENT_SHADER)); + shader.mRiggedVariant = &skinned_shader; + shader.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + if (variant == NORMAL_DEBUG_SHADER_WITH_TANGENTS) + { + shader.addPermutation("HAS_ATTRIBUTE_TANGENT", "1"); + } + success = make_rigged_variant(shader, skinned_shader); + success = success && shader.createShader(NULL, NULL); + } + } + if (success) { gClipProgram.mName = "Clip Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index cb1729cd1b..4273c3e70c 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -156,6 +156,14 @@ extern LLGLSLShader gRadianceGenProgram; extern LLGLSLShader gIrradianceGenProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; +enum NormalDebugShaderVariant : S32 +{ + NORMAL_DEBUG_SHADER_DEFAULT, + NORMAL_DEBUG_SHADER_WITH_TANGENTS, + NORMAL_DEBUG_SHADER_COUNT +}; +extern LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +extern LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; extern LLGLSLShader gClipProgram; extern LLGLSLShader gBenchmarkProgram; extern LLGLSLShader gReflectionProbeDisplayProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d81bcef259..fb57042110 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8241,6 +8241,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_CONTROL_AV, LLPipeline::RENDER_TYPE_ALPHA_MASK, LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_WATER, END_RENDER_TYPES); -- cgit v1.2.3 From 118996225bb588dcaef415dfe18f5e4aca9c35b8 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 29 Sep 2023 17:19:48 -0700 Subject: secondlife/viewer-issues#43: Proof-of-concept PBR terrain normal gen feature flag. Final implementation would likely be very different. --- indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llsurface.cpp | 14 +- indra/newview/llsurface.h | 6 +- indra/newview/llsurfacepatch.cpp | 197 +++++++++++++++++++-- indra/newview/llsurfacepatch.h | 13 ++ indra/newview/llviewermenu.cpp | 18 ++ indra/newview/llviewerregion.cpp | 35 +++- indra/newview/llviewerregion.h | 3 + indra/newview/llvosurfacepatch.cpp | 1 + indra/newview/pipeline.cpp | 9 + indra/newview/pipeline.h | 2 + indra/newview/skins/default/xui/en/menu_viewer.xml | 7 + 12 files changed, 292 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 242e274daf..ff0f4fd8a1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10932,6 +10932,17 @@ Value 8.0 + RenderTerrainPBRNormalsEnabled + + Comment + EXPERIMENTAL: Change normal gen for PBR Terrain. + Persist + 1 + Type + Boolean + Value + 0 + RenderTrackerBeacon Comment diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 1418499f8b..804afe6266 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -643,17 +643,18 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) } } -BOOL LLSurface::idleUpdate(F32 max_update_time) +template +bool LLSurface::idleUpdate(F32 max_update_time) { if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) { - return FALSE; + return false; } // Perform idle time update of non-critical stuff. // In this case, texture and normal updates. LLTimer update_timer; - BOOL did_update = FALSE; + bool did_update = false; // If the Z height data has changed, we need to rebuild our // property line vertex arrays. @@ -669,13 +670,13 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) { std::set::iterator curiter = iter++; LLSurfacePatch *patchp = *curiter; - patchp->updateNormals(); + patchp->updateNormals(); patchp->updateVerticalStats(); if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) { if (patchp->updateTexture()) { - did_update = TRUE; + did_update = true; patchp->clearDirty(); mDirtyPatchList.erase(curiter); } @@ -691,6 +692,9 @@ BOOL LLSurface::idleUpdate(F32 max_update_time) return did_update; } +template bool LLSurface::idleUpdate(F32 max_update_time); +template bool LLSurface::idleUpdate(F32 max_update_time); + void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch) { diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index 33a64ae7d5..b7b47d2a1c 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -112,7 +112,8 @@ public: LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; // Update methods (called during idle, normally) - BOOL idleUpdate(F32 max_update_time); + template + bool idleUpdate(F32 max_update_time); BOOL containsPosition(const LLVector3 &position); @@ -224,6 +225,9 @@ private: static S32 sTextureSize; // Size of the surface texture }; +extern template bool LLSurface::idleUpdate(F32 max_update_time); +extern template bool LLSurface::idleUpdate(F32 max_update_time); + // . __. diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index a6370e9ec2..92b1273041 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -243,7 +243,8 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 } -void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) +template<> +void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) { U32 patch_width = mSurfacep->mPVArray.mPatchWidth; U32 surface_stride = mSurfacep->getGridsPerEdge(); @@ -356,6 +357,166 @@ void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) *(mDataNorm + surface_stride * y + x) = normal; } +template<> +void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) +{ + llassert(mDataNorm); + constexpr U32 index = 0; + + const U32 surface_stride = mSurfacep->getGridsPerEdge(); + LLVector3& normal_out = *(mDataNorm + surface_stride * y + x); + calcNormalFlat(normal_out, x, y, index); +} + +// Calculate the flat normal of a triangle whose least coordinate is specified by the given x,y values. +// If index = 0, calculate the normal of the first triangle, otherwise calculate the normal of the second. +void LLSurfacePatch::calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index) +{ + llassert(index == 0 || index == 1); + + U32 patch_width = mSurfacep->mPVArray.mPatchWidth; + U32 surface_stride = mSurfacep->getGridsPerEdge(); + + // Vertex stride is always 1 because we want the flat surface of the current triangle face + constexpr U32 stride = 1; + + const F32 mpg = mSurfacep->getMetersPerGrid() * stride; + + S32 poffsets[2][2][2]; + poffsets[0][0][0] = x; + poffsets[0][0][1] = y; + + poffsets[0][1][0] = x; + poffsets[0][1][1] = y + stride; + + poffsets[1][0][0] = x + stride; + poffsets[1][0][1] = y; + + poffsets[1][1][0] = x + stride; + poffsets[1][1][1] = y + stride; + + const LLSurfacePatch *ppatches[2][2]; + + // LLVector3 p1, p2, p3, p4; + + ppatches[0][0] = this; + ppatches[0][1] = this; + ppatches[1][0] = this; + ppatches[1][1] = this; + + U32 i, j; + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + { + if (poffsets[i][j][0] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(WEST)) + { + poffsets[i][j][0] = 0; + } + else + { + poffsets[i][j][0] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); + } + } + if (poffsets[i][j][1] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(SOUTH)) + { + poffsets[i][j][1] = 0; + } + else + { + poffsets[i][j][1] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); + } + } + if (poffsets[i][j][0] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(EAST)) + { + poffsets[i][j][0] = patch_width - 1; + } + else + { + poffsets[i][j][0] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); + } + } + if (poffsets[i][j][1] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(NORTH)) + { + poffsets[i][j][1] = patch_width - 1; + } + else + { + poffsets[i][j][1] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); + } + } + } + } + + LLVector3 p00(-mpg,-mpg, + *(ppatches[0][0]->mDataZ + + poffsets[0][0][0] + + poffsets[0][0][1]*surface_stride)); + LLVector3 p01(-mpg,+mpg, + *(ppatches[0][1]->mDataZ + + poffsets[0][1][0] + + poffsets[0][1][1]*surface_stride)); + LLVector3 p10(+mpg,-mpg, + *(ppatches[1][0]->mDataZ + + poffsets[1][0][0] + + poffsets[1][0][1]*surface_stride)); + LLVector3 p11(+mpg,+mpg, + *(ppatches[1][1]->mDataZ + + poffsets[1][1][0] + + poffsets[1][1][1]*surface_stride)); + + // Triangle index / coordinate convention + // for a single surface patch + // + // p01 p11 + // + // ^ ._____. + // | |\ | + // | | \ 1 | + // | | \ | + // | 0 \ | + // y |____\| + // + // p00 x ---> p10 + // + // (z up / out of the screen due to right-handed coordinate system) + + LLVector3 normal; + if (index == 0) + { + LLVector3 c1 = p10 - p00; + LLVector3 c2 = p01 - p00; + + normal = c1; + normal %= c2; + normal.normVec(); + } + else // index == 1 + { + LLVector3 c1 = p11 - p01; + LLVector3 c2 = p11 - p10; + + normal = c1; + normal %= c2; + normal.normVec(); + } + + llassert(&normal_out); + normal_out = normal; +} + const LLVector3 &LLSurfacePatch::getNormal(const U32 x, const U32 y) const { U32 surface_stride = mSurfacep->getGridsPerEdge(); @@ -453,6 +614,7 @@ void LLSurfacePatch::updateVerticalStats() } +template void LLSurfacePatch::updateNormals() { if (mSurfacep->mType == 'w') @@ -470,9 +632,9 @@ void LLSurfacePatch::updateNormals() { for (j = 0; j <= grids_per_patch_edge; j++) { - calcNormal(grids_per_patch_edge, j, 2); - calcNormal(grids_per_patch_edge - 1, j, 2); - calcNormal(grids_per_patch_edge - 2, j, 2); + calcNormal(grids_per_patch_edge, j, 2); + calcNormal(grids_per_patch_edge - 1, j, 2); + calcNormal(grids_per_patch_edge - 2, j, 2); } dirty_patch = TRUE; @@ -483,9 +645,9 @@ void LLSurfacePatch::updateNormals() { for (i = 0; i <= grids_per_patch_edge; i++) { - calcNormal(i, grids_per_patch_edge, 2); - calcNormal(i, grids_per_patch_edge - 1, 2); - calcNormal(i, grids_per_patch_edge - 2, 2); + calcNormal(i, grids_per_patch_edge, 2); + calcNormal(i, grids_per_patch_edge - 1, 2); + calcNormal(i, grids_per_patch_edge - 2, 2); } dirty_patch = TRUE; @@ -496,8 +658,8 @@ void LLSurfacePatch::updateNormals() { for (j = 0; j < grids_per_patch_edge; j++) { - calcNormal(0, j, 2); - calcNormal(1, j, 2); + calcNormal(0, j, 2); + calcNormal(1, j, 2); } dirty_patch = TRUE; } @@ -507,8 +669,8 @@ void LLSurfacePatch::updateNormals() { for (i = 0; i < grids_per_patch_edge; i++) { - calcNormal(i, 0, 2); - calcNormal(i, 1, 2); + calcNormal(i, 0, 2); + calcNormal(i, 1, 2); } dirty_patch = TRUE; } @@ -584,10 +746,10 @@ void LLSurfacePatch::updateNormals() // We've got a northeast patch in the same surface. // The z and normals will be handled by that patch. } - calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2); - calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2); - calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2); - calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2); + calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2); + calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2); + calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2); + calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2); dirty_patch = TRUE; } @@ -598,7 +760,7 @@ void LLSurfacePatch::updateNormals() { for (i=2; i < grids_per_patch_edge - 2; i++) { - calcNormal(i, j, 2); + calcNormal(i, j, 2); } } dirty_patch = TRUE; @@ -615,6 +777,9 @@ void LLSurfacePatch::updateNormals() } } +template void LLSurfacePatch::updateNormals(); +template void LLSurfacePatch::updateNormals(); + void LLSurfacePatch::updateEastEdge() { U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index 8c8f501dce..ec3864ce44 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -77,6 +77,7 @@ public: void updateVerticalStats(); void updateCompositionStats(); + template void updateNormals(); void updateEastEdge(); @@ -102,9 +103,18 @@ public: LLVector3 getPointAgent(const U32 x, const U32 y) const; // get the point at the offset. LLVector2 getTexCoords(const U32 x, const U32 y) const; + // Per-vertex normals + // *TODO: PBR=true is a test implementation solely for proof-of-concept. + // Final implementation would likely be very different and may not even use + // this function. If we decide to keep calcNormalFlat, remove index as it + // is a debug parameter for testing. + template void calcNormal(const U32 x, const U32 y, const U32 stride); const LLVector3 &getNormal(const U32 x, const U32 y) const; + // Per-triangle normals for flat edges + void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */); + void eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1); @@ -181,5 +191,8 @@ protected: LLSurface *mSurfacep; // Pointer to "parent" surface }; +extern template void LLSurfacePatch::updateNormals(); +extern template void LLSurfacePatch::updateNormals(); + #endif // LL_LLSURFACEPATCH_H diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9db9d97ddc..da7b1131a3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2122,6 +2122,20 @@ class LLAdvancedPurgeShaderCache : public view_listener_t } }; +///////////////////// +// REBUILD TERRAIN // +///////////////////// + + +class LLAdvancedRebuildTerrain : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + gPipeline.rebuildTerrain(); + return true; + } +}; + //////////////////// // EVENT Recorder // /////////////////// @@ -9492,6 +9506,10 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); + if (gSavedSettings.get("RenderTerrainPBREnabled")) + { + view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); + } #ifdef TOGGLE_HACKED_GODLIKE_VIEWER view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode"); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index dae476d9d7..d541bb6647 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1105,6 +1105,11 @@ void LLViewerRegion::dirtyHeights() } } +void LLViewerRegion::dirtyAllPatches() +{ + getLand().dirtyAllPatches(); +} + //physically delete the cache entry void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering) { @@ -1605,7 +1610,19 @@ void LLViewerRegion::idleUpdate(F32 max_update_time) mLastUpdate = LLViewerOctreeEntryData::getCurrentFrame(); - mImpl->mLandp->idleUpdate(max_update_time); + static bool pbr_terrain_enabled = gSavedSettings.get("RenderTerrainPBREnabled"); + static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", FALSE); + bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); + bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; + + if (!pbr_land) + { + mImpl->mLandp->idleUpdate(max_update_time); + } + else + { + mImpl->mLandp->idleUpdate(max_update_time); + } if (mParcelOverlay) { @@ -1906,7 +1923,21 @@ LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* o // As above, but forcibly do the update. void LLViewerRegion::forceUpdate() { - mImpl->mLandp->idleUpdate(0.f); + constexpr F32 max_update_time = 0.f; + + static bool pbr_terrain_enabled = gSavedSettings.get("RenderTerrainPBREnabled"); + static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", FALSE); + bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); + bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; + + if (!pbr_land) + { + mImpl->mLandp->idleUpdate(max_update_time); + } + else + { + mImpl->mLandp->idleUpdate(max_update_time); + } if (mParcelOverlay) { diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 622490c881..1c2ff9bc97 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -163,6 +163,9 @@ public: // Call this whenever you change the height data in the region. // (Automatically called by LLSurfacePatch's update routine) void dirtyHeights(); + // Call this whenever you want to force all terrain to rebuild. + // (For example, if a global terrain config option has changed) + void dirtyAllPatches(); LLViewerParcelOverlay *getParcelOverlay() const { return mParcelOverlay; } diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 9544450a69..69b9476d38 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -214,6 +214,7 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) void LLVOSurfacePatch::updateFaceSize(S32 idx) { + LL_PROFILE_ZONE_SCOPED; if (idx != 0) { LL_WARNS() << "Terrain partition requested invalid face!!!" << LL_ENDL; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fb57042110..d63b9d317e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -10870,3 +10870,12 @@ void LLPipeline::rebuildDrawInfo() } } +void LLPipeline::rebuildTerrain() +{ + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + region->dirtyAllPatches(); + } +} diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5ace90b000..fb28a0e41c 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -134,6 +134,8 @@ public: // rebuild all LLVOVolume render batches void rebuildDrawInfo(); + // Rebuild all terrain + void rebuildTerrain(); // Clear LLFace mVertexBuffer pointers void resetVertexBuffers(LLDrawable* drawable); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 660f4b62c7..9b238693e0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3297,6 +3297,13 @@ function="World.EnvPreset" + + + Date: Wed, 31 Jan 2024 15:54:14 -0800 Subject: #677 Some clipping WIP --- .../shaders/class1/deferred/materialV.glsl | 2 +- .../shaders/class3/deferred/materialF.glsl | 12 +++++++----- .../shaders/class3/deferred/softenLightF.glsl | 1 - indra/newview/lldrawpoolmaterials.cpp | 8 ++++---- indra/newview/llheroprobemanager.cpp | 18 ++++-------------- indra/newview/llheroprobemanager.h | 5 ++++- indra/newview/llsettingsvo.cpp | 12 +++++++++++- 7 files changed, 31 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 65706e2c3f..41112bce30 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -127,7 +127,7 @@ void main() vertex_color = diffuse_color; #if !defined(HAS_SKIN) - vary_position = (projection_matrix*vec4(position.xyz, 1.0)).xyz; + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index b3b1aaed56..8fe0e1cec8 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -48,15 +48,18 @@ vec3 linear_to_srgb(vec3 cs); uniform vec4 clipPlane; uniform float clipSign; uniform float mirror_flag; +uniform mat4 modelview_matrix; +uniform mat3 normal_matrix; void applyClip(vec3 pos) { - float funnyClip = 0; + if (mirror_flag > 0) { - if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) - { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) + { discard; - } + } + } } @@ -308,7 +311,6 @@ void main() // diffcol == diffuse map combined with vertex color vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy); diffcol.rgb *= vertex_color.rgb; - alphaMask(diffcol.a); // spec == specular map combined with specular color diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index f1de0b88d6..b49c3386db 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -201,7 +201,6 @@ void main() #ifdef HERO_PROBES vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_MIRROR)) color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; #endif } diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 063dd948f7..15033160d5 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -192,10 +192,10 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) mShader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); } - LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.currentMirrorClip()[0], - gPipeline.mHeroProbeManager.currentMirrorClip()[1], - gPipeline.mHeroProbeManager.currentMirrorClip()[2], - gPipeline.mHeroProbeManager.currentMirrorClip()[3]); + LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.mMirrorPosition[0], + gPipeline.mHeroProbeManager.mMirrorPosition[1], + gPipeline.mHeroProbeManager.mMirrorPosition[2], + 1); mShader->uniform4fv(LLShaderMgr::CLIP_PLANE, 1, clipPlane.mV); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1ecafd4f54..bbe493f6a9 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -165,20 +165,10 @@ void LLHeroProbeManager::update() LLVector3 reject = offset - project; LLVector3 point = (reject - project) + hero_pos; - glh::matrix4f mat = copy_matrix(gGLModelView); - glh::vec4f tc(face_normal.mV); - mat.mult_matrix_vec(tc); - - LLVector3 mirror_normal; - mirror_normal.set(tc.v); - - LLVector3 hero_pos_render; - tc = glh::vec4f(hero_pos.mV); - - mat.mult_matrix_vec(tc); - hero_pos_render.set(tc.v); - - mCurrentClipPlane.setVec(hero_pos_render, mirror_normal); + mCurrentClipPlane.setVec(hero_pos, face_normal); + mMirrorPosition = hero_pos; + mMirrorNormal = LLVector3(0, 0, 1); + probe_pos.load3(point.mV); } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 68cfdbfd99..0b32768bb1 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -75,7 +75,9 @@ public: bool isMirrorPass() const { return mRenderingMirror; } - LLPlane currentMirrorClip() const { return mCurrentClipPlane; } + LLPlane currentMirrorClip() const { return mCurrentClipPlane; } + LLVector3 mMirrorPosition; + LLVector3 mMirrorNormal; private: friend class LLPipeline; @@ -102,6 +104,7 @@ private: LLPlane mCurrentClipPlane; + // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index c07c939862..9cfb774a90 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -1017,10 +1017,20 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); + norm = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorNormal.mV[0], gPipeline.mHeroProbeManager.mMirrorNormal.mV[1], + gPipeline.mHeroProbeManager.mMirrorNormal.mV[2]); + p = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorPosition.mV[0], gPipeline.mHeroProbeManager.mMirrorPosition.mV[1], + gPipeline.mHeroProbeManager.mMirrorPosition.mV[2]); + invtrans.mult_matrix_vec(norm, enorm); + enorm.normalize(); + mat.mult_matrix_vec(p, ep); + + LLVector4 mirrorPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); + LLDrawPoolAlpha::sWaterPlane = waterPlane; shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, waterPlane.mV); - + shader->uniform4fv(LLShaderMgr::CLIP_PLANE, mirrorPlane.mV); LLVector4 light_direction = env.getClampedLightNorm(); F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP); -- cgit v1.2.3 From a4225663ac3feb641fb8fb416889fd46b52763f5 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 1 Feb 2024 10:16:52 -0600 Subject: #677 Set mirror pass flag in llsettingsvo --- indra/newview/lldrawpoolmaterials.cpp | 17 ----------------- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llsettingsvo.cpp | 9 +++++++++ 3 files changed, 10 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index 15033160d5..c0e4ed38c1 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -183,23 +183,6 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass) glUniform4fv(specular, 1, lastSpecular.mV); } - if (gPipeline.mHeroProbeManager.isMirrorPass()) - { - mShader->uniform1f(LLShaderMgr::MIRROR_FLAG, 1); - } - else - { - mShader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); - } - - LLVector4 clipPlane = LLVector4(gPipeline.mHeroProbeManager.mMirrorPosition[0], - gPipeline.mHeroProbeManager.mMirrorPosition[1], - gPipeline.mHeroProbeManager.mMirrorPosition[2], - 1); - - mShader->uniform4fv(LLShaderMgr::CLIP_PLANE, - 1, clipPlane.mV); - LLVOAvatar* lastAvatar = nullptr; for (LLCullResult::drawinfo_iterator i = begin; i != end; ) diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index bbe493f6a9..ed37a67c85 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -166,7 +166,7 @@ void LLHeroProbeManager::update() LLVector3 point = (reject - project) + hero_pos; mCurrentClipPlane.setVec(hero_pos, face_normal); - mMirrorPosition = hero_pos; + mMirrorPosition = mNearestHero->getPositionAgent(); mMirrorNormal = LLVector3(0, 0, 1); diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 9cfb774a90..da5504f83f 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -1033,6 +1033,15 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) shader->uniform4fv(LLShaderMgr::CLIP_PLANE, mirrorPlane.mV); LLVector4 light_direction = env.getClampedLightNorm(); + if (gPipeline.mHeroProbeManager.isMirrorPass()) + { + shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 1); + } + else + { + shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); + } + F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP); shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS); -- cgit v1.2.3 From 78140786ce4a89a4ee252dabc74e3a28461e9c15 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 10:18:17 -0800 Subject: #689 Fix for mirror stuttering. --- indra/newview/llappviewer.cpp | 1 - indra/newview/llviewerdisplay.cpp | 10 +++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 038858321c..28dd2a3c9a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1520,7 +1520,6 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Snapshot"); pingMainloopTimeout("Main:Snapshot"); gPipeline.mReflectionMapManager.update(); - gPipeline.mHeroProbeManager.update(); LLFloaterSnapshot::update(); // take snapshots LLFloaterSimpleSnapshot::update(); gGLActive = FALSE; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 6261f62fbe..1d168de80d 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -656,6 +656,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (!gDisconnected) { + // Render mirrors and associated hero probes before we render the rest of the scene. + // This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it. + if (gPipeline.RenderMirrors && !gSnapshot) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes"); + gPipeline.mHeroProbeManager.update(); + } + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 1"); LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) @@ -696,7 +704,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gPipeline.updateGL(); - + stop_glerror(); LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); -- cgit v1.2.3 From b2462355a39a8473065c279c66daba307f1fa9bf Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 1 Feb 2024 13:19:20 -0600 Subject: #677 WIP -- add mirror clipping to more shaders --- indra/llrender/llshadermgr.cpp | 8 +++- .../shaders/class1/deferred/bumpF.glsl | 4 ++ .../shaders/class1/deferred/bumpV.glsl | 5 ++- .../shaders/class1/deferred/diffuseF.glsl | 3 ++ .../shaders/class1/deferred/diffuseIndexedF.glsl | 3 ++ .../shaders/class1/deferred/diffuseV.glsl | 7 +++- .../shaders/class1/deferred/fullbrightF.glsl | 4 +- .../shaders/class1/deferred/globalF.glsl | 45 ++++++++++++++++++++++ .../shaders/class1/deferred/pbropaqueF.glsl | 26 ++----------- .../app_settings/shaders/class1/objects/bumpF.glsl | 4 ++ .../app_settings/shaders/class1/objects/bumpV.glsl | 5 ++- .../shaders/class3/deferred/fullbrightShinyF.glsl | 3 ++ .../shaders/class3/deferred/materialF.glsl | 22 ++--------- indra/newview/llviewershadermgr.cpp | 4 ++ 14 files changed, 96 insertions(+), 47 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/deferred/globalF.glsl (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 14f3086eb6..758b54cf1f 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -183,7 +183,13 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) // Attach Fragment Shader Features Next /////////////////////////////////////// -// NOTE order of shader object attaching is VERY IMPORTANT!!! + // NOTE order of shader object attaching is VERY IMPORTANT!!! + + if (!shader->attachFragmentObject("deferred/globalF.glsl")) + { + return FALSE; + } + if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred) { if (!shader->attachFragmentObject("environment/srgbF.glsl")) diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 35f483f633..a22c174349 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -37,11 +37,15 @@ in vec3 vary_mat2; in vec4 vertex_color; in vec2 vary_texcoord0; +in vec3 vary_position; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); void main() { + mirrorClip(vary_position); + vec4 col = texture(diffuseMap, vary_texcoord0.xy); if(col.a < minimum_alpha) diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 3af2eab1e4..74319349f6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -23,6 +23,7 @@ * $/LicenseInfo$ */ +uniform mat4 modelview_matrix; uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; @@ -38,11 +39,11 @@ out vec3 vary_mat1; out vec3 vary_mat2; out vec4 vertex_color; out vec2 vary_texcoord0; +out vec3 vary_position; #ifdef HAS_SKIN mat4 getObjectSkinnedTransform(); uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; #endif void main() @@ -52,11 +53,13 @@ void main() mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; + vary_position = pos; gl_Position = projection_matrix*vec4(pos, 1.0); vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); #else + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vec3 n = normalize(normal_matrix * normal); vec3 t = normalize(normal_matrix * tangent.xyz); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 68fb8bf499..76776ede2c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -32,11 +32,14 @@ uniform sampler2D diffuseMap; in vec3 vary_normal; in vec4 vertex_color; in vec2 vary_texcoord0; +in vec3 vary_position; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); void main() { + mirrorClip(vary_position); vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb; frag_data[0] = vec4(col, 0.0); frag_data[1] = vertex_color.aaaa; // spec diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index 93d561504e..b983acf657 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -30,12 +30,15 @@ out vec4 frag_data[4]; in vec3 vary_normal; in vec4 vertex_color; in vec2 vary_texcoord0; +in vec3 vary_position; +void mirrorClip(vec3 pos); vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); void main() { + mirrorClip(vary_position); vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; vec3 spec; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 2402cc3b70..64230dc680 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -36,13 +36,16 @@ out vec3 vary_normal; out vec4 vertex_color; out vec2 vary_texcoord0; +out vec3 vary_position; void passTextureIndex(); +uniform mat4 modelview_matrix; + #ifdef HAS_SKIN mat4 getObjectSkinnedTransform(); uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; + #endif void main() @@ -51,9 +54,11 @@ void main() mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; vec4 pos = mat * vec4(position.xyz, 1.0); + vary_position = pos.xyz; gl_Position = projection_matrix * pos; vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); #else + vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_normal = normalize(normal_matrix * normal); #endif diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index a6fab10791..52dfed06ae 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -50,9 +50,11 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); #endif +void mirrorClip(vec3 pos); + void main() { - + mirrorClip(vary_position); #ifdef IS_ALPHA waterClip(vary_position.xyz); #endif diff --git a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl new file mode 100644 index 0000000000..7e3e7d9271 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl @@ -0,0 +1,45 @@ +/** + * @file class1/deferred/globalF.glsl + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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$ + */ + + + // Global helper functions included in every fragment shader + // DO NOT declare sampler uniforms here as OS X doesn't compile + // them out + +uniform float mirror_flag; +uniform vec4 clipPlane; +uniform float clipSign; + +void mirrorClip(vec3 pos) +{ + if (mirror_flag > 0) + { + if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) + { + discard; + } + } +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index 9b98a37925..0683236460 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -60,34 +60,14 @@ vec3 srgb_to_linear(vec3 c); uniform vec4 clipPlane; uniform float clipSign; -uniform float mirror_flag; -void applyClip(vec3 pos) -{ - if (mirror_flag > 0) - { - // TODO: make this less branchy - if (clipSign > 0) - { - if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) - { - discard; - } - } - else - { - if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) > 0.0) - { - discard; - } - } - } -} + +void mirrorClip(vec3 pos); uniform mat3 normal_matrix; void main() { - applyClip(vary_position); + mirrorClip(vary_position); vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; if (basecolor.a < minimum_alpha) diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl index 67c99530e3..142f2a5d71 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl @@ -30,9 +30,13 @@ uniform sampler2D texture1; in vec2 vary_texcoord0; in vec2 vary_texcoord1; +in vec3 vary_position; + +void mirrorClip(vec3 pos); void main() { + mirrorClip(vary_position); float tex0 = texture(texture0, vary_texcoord0.xy).a; float tex1 = texture(texture1, vary_texcoord1.xy).a; diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl index 7d5417919e..b8a02fbdec 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl @@ -23,6 +23,7 @@ * $/LicenseInfo$ */ +uniform mat4 modelview_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; @@ -32,11 +33,11 @@ in vec2 texcoord1; out vec2 vary_texcoord0; out vec2 vary_texcoord1; +out vec3 vary_position; #ifdef HAS_SKIN mat4 getObjectSkinnedTransform(); uniform mat4 projection_matrix; -uniform mat4 modelview_matrix; #endif void main() @@ -46,8 +47,10 @@ void main() mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; vec4 pos = mat * vec4(position.xyz, 1.0); + vary_position = pos.xyz; gl_Position = projection_matrix * pos; #else + vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); #endif vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl index 8430cca325..c382a9fbc0 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl @@ -53,8 +53,11 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); +void mirrorClip(vec3 pos); + void main() { + mirrorClip(vary_position); #ifdef HAS_DIFFUSE_LOOKUP vec4 color = diffuseLookup(vary_texcoord0.xy); #else diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 8fe0e1cec8..0476b98e10 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -45,26 +45,13 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float vec3 srgb_to_linear(vec3 cs); vec3 linear_to_srgb(vec3 cs); -uniform vec4 clipPlane; -uniform float clipSign; -uniform float mirror_flag; uniform mat4 modelview_matrix; uniform mat3 normal_matrix; -void applyClip(vec3 pos) -{ - - if (mirror_flag > 0) - { - if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) - { - discard; - } - - } -} in vec3 vary_position; +void mirrorClip(vec3 pos); + #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) out vec4 frag_color; @@ -305,7 +292,7 @@ float getShadow(vec3 pos, vec3 norm) void main() { - applyClip(vary_position); + mirrorClip(vary_position); waterClip(); // diffcol == diffuse map combined with vertex color @@ -430,9 +417,6 @@ void main() float flag = GBUFFER_FLAG_HAS_ATMOS; - if (mirror_flag > 0) - flag = 1; - frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 48c54f3dcc..a93d60cb70 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -291,6 +291,9 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma mShaderList.push_back(&gNoPostGammaCorrectProgram); mShaderList.push_back(&gLegacyPostGammaCorrectProgram); + mShaderList.push_back(&gDeferredDiffuseProgram); + mShaderList.push_back(&gObjectBumpProgram); + mShaderList.push_back(&gDeferredBumpProgram); } @@ -676,6 +679,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "environment/encodeNormF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/globalF.glsl", 1)); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) ); -- cgit v1.2.3 From 169562bf13ca6ed47dac1e73c6d8e72cd89861eb Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 1 Feb 2024 13:50:47 -0600 Subject: #677 WIP -- Add clipping to alpha and pbr (not working on PBR for some reason) --- indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl | 7 +++++-- indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl | 4 ++++ indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl | 3 +++ indra/newview/llviewershadermgr.cpp | 3 ++- 4 files changed, 14 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl index 160ae7a215..5e0141910b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl @@ -28,8 +28,9 @@ //deferred opaque implementation -#ifdef HAS_SKIN uniform mat4 modelview_matrix; + +#ifdef HAS_SKIN uniform mat4 projection_matrix; mat4 getObjectSkinnedTransform(); #else @@ -59,6 +60,7 @@ out vec4 vertex_color; out vec3 vary_tangent; flat out float vary_sign; out vec3 vary_normal; +out vec3 vary_position; vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); @@ -71,10 +73,11 @@ void main() mat = modelview_matrix * mat; vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; - + vary_position = pos; gl_Position = projection_matrix*vec4(pos,1.0); #else + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); #endif diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index acd32a81b3..4aef22c296 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -78,6 +78,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); float getAmbientClamp(); +void mirrorClip(vec3 pos); + void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); @@ -167,6 +169,8 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec void main() { + mirrorClip(vary_position); + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; vec4 pos = vec4(vary_position, 1.0); diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl index 003dd05e6f..059c2a64ce 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl @@ -90,6 +90,7 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); +void mirrorClip(vec3 pos); void waterClip(vec3 pos); void calcDiffuseSpecular(vec3 baseColor, float metallic, inout vec3 diffuseColor, inout vec3 specularColor); @@ -156,6 +157,8 @@ vec3 calcPointLightOrSpotLight(vec3 diffuseColor, vec3 specularColor, void main() { + mirrorClip(vary_position); + vec3 color = vec3(0,0,0); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index a93d60cb70..7dbfad4b82 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -294,7 +294,8 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredDiffuseProgram); mShaderList.push_back(&gObjectBumpProgram); mShaderList.push_back(&gDeferredBumpProgram); - + mShaderList.push_back(&gDeferredPBROpaqueProgram); + mShaderList.push_back(&gDeferredPBRAlphaProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() -- cgit v1.2.3 From b1410c8b679c14432038a62bff2de772f490bc4a Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 1 Feb 2024 14:00:40 -0600 Subject: #677 WIP -- fix PBR and avatar mirror clipping. --- indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl | 4 ++++ indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl | 2 ++ indra/newview/llfetchedgltfmaterial.cpp | 1 - indra/newview/llviewershadermgr.cpp | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index 6ebe4ce251..c0607d0149 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -33,11 +33,15 @@ uniform float minimum_alpha; in vec3 vary_normal; in vec2 vary_texcoord0; +in vec3 vary_position; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); void main() { + mirrorClip(vary_position); + vec4 diff = texture(diffuseMap, vary_texcoord0.xy); if (diff.a < minimum_alpha) diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index bc0c11ec46..5cc2846156 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -35,6 +35,7 @@ in vec4 weight; out vec3 vary_normal; out vec2 vary_texcoord0; +out vec3 vary_position; void main() { @@ -57,6 +58,7 @@ void main() vary_normal = norm; + vary_position = pos.xyz; gl_Position = projection_matrix * pos; } diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 6bd613622e..97b959e5cb 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -128,7 +128,6 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) shader->uniform1f(LLShaderMgr::ROUGHNESS_FACTOR, mRoughnessFactor); shader->uniform1f(LLShaderMgr::METALLIC_FACTOR, mMetallicFactor); shader->uniform3fv(LLShaderMgr::EMISSIVE_COLOR, 1, mEmissiveColor.mV); - shader->uniform1f(LLShaderMgr::MIRROR_FLAG, 0); F32 normal_packed[8]; mTextureTransform[GLTF_TEXTURE_INFO_NORMAL].getPacked(normal_packed); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 7dbfad4b82..bb60ceed2a 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -296,6 +296,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredBumpProgram); mShaderList.push_back(&gDeferredPBROpaqueProgram); mShaderList.push_back(&gDeferredPBRAlphaProgram); + mShaderList.push_back(&gDeferredAvatarProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() -- cgit v1.2.3 From fac63e473a4b2b7b9b361c4d5656c94d47d88ef0 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 12:11:20 -0800 Subject: #684 Fix pixellation on mirrors regardless of mirror resolution. --- indra/newview/app_settings/settings.xml | 15 ++--------- .../shaders/class1/interface/radianceGenF.glsl | 2 +- indra/newview/llheroprobemanager.cpp | 29 +++++++++++----------- indra/newview/llviewershadermgr.cpp | 16 +++++++++++- indra/newview/llviewershadermgr.h | 1 + indra/newview/pipeline.cpp | 5 ++++ indra/newview/pipeline.h | 3 +++ 7 files changed, 42 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 242e274daf..f2ba4ba29e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10421,7 +10421,7 @@ Type S32 Value - 1024 + 2048 RenderHeroProbeDistance @@ -10432,18 +10432,7 @@ Type F32 Value - 16 - - RenderHeroProbeNearClipOffset - - Comment - Distance offset in meters for hero probes to near clip. - Persist - 1 - Type - F32 - Value - 2.1 + 8 RenderReflectionProbeVolumes diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index cb6f34713c..c1ed1bfe6e 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -130,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R) float totalWeight = 0.0; float envMapDim = float(textureSize(reflectionProbes, 0).s); float roughness = mipLevel/max_probe_lod; - int numSamples = max(int(32*roughness), 1); + int numSamples = max(int(PROBE_FILTER_SAMPLES*roughness), 1); float numMips = max_probe_lod+1; diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ed37a67c85..42c8d4fb3f 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -217,7 +217,7 @@ void LLHeroProbeManager::update() void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) { // hacky hot-swap of camera specific render targets - gPipeline.mRT = &gPipeline.mAuxillaryRT; + gPipeline.mRT = &gPipeline.mHeroProbeRT; probe->update(mRenderTarget.getWidth(), face, true, near_clip); @@ -252,9 +252,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n static LLStaticHashedString znear("znear"); static LLStaticHashedString zfar("zfar"); - LLRenderTarget *screen_rt = &gPipeline.mAuxillaryRT.screen; - LLRenderTarget *depth_rt = &gPipeline.mAuxillaryRT.deferredScreen; + LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; + LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + /* // perform a gaussian blur on the super sampled render before downsampling { gGaussianProgram.bind(); @@ -277,7 +278,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); screen_rt->flush(); } - + */ S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -338,14 +339,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n { //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) - gRadianceGenProgram.bind(); + gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); - S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + S32 channel = gHeroRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); mTexture->bind(channel); - gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); - gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); - gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); + gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); + gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); + gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); U32 res = mMipChain[0].getWidth(); @@ -357,10 +358,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n static LLStaticHashedString sWidth("u_width"); static LLStaticHashedString sStrength("probe_strength"); - gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1)); - gRadianceGenProgram.uniform1f(sMipLevel, i); - gRadianceGenProgram.uniform1i(sWidth, mProbeResolution); - gRadianceGenProgram.uniform1f(sStrength, 1); + gHeroRadianceGenProgram.uniform1f(sRoughness, (F32) i / (F32) (mMipChain.size() - 1)); + gHeroRadianceGenProgram.uniform1f(sMipLevel, i); + gHeroRadianceGenProgram.uniform1i(sWidth, mProbeResolution); + gHeroRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) { // for each cube face @@ -383,7 +384,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n } } - gRadianceGenProgram.unbind(); + gHeroRadianceGenProgram.unbind(); } mMipChain[0].flush(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index a93d60cb70..5e9c8f5595 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -84,7 +84,8 @@ LLGLSLShader gOcclusionCubeProgram; LLGLSLShader gGlowCombineProgram; LLGLSLShader gReflectionMipProgram; LLGLSLShader gGaussianProgram; -LLGLSLShader gRadianceGenProgram; +LLGLSLShader gRadianceGenProgram; +LLGLSLShader gHeroRadianceGenProgram; LLGLSLShader gIrradianceGenProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureCompareProgram; @@ -2799,8 +2800,21 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenV.glsl", GL_VERTEX_SHADER)); gRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenF.glsl", GL_FRAGMENT_SHADER)); gRadianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + gRadianceGenProgram.addPermutation("PROBE_FILTER_SAMPLES", "32"); success = gRadianceGenProgram.createShader(NULL, NULL); } + + if (success && gGLManager.mHasCubeMapArray) + { + gHeroRadianceGenProgram.mName = "Hero Radiance Gen Shader"; + gHeroRadianceGenProgram.mShaderFiles.clear(); + gHeroRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenV.glsl", GL_VERTEX_SHADER)); + gHeroRadianceGenProgram.mShaderFiles.push_back(make_pair("interface/radianceGenF.glsl", GL_FRAGMENT_SHADER)); + gHeroRadianceGenProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + gHeroRadianceGenProgram.addPermutation("HERO_PROBES", "1"); + gHeroRadianceGenProgram.addPermutation("PROBE_FILTER_SAMPLES", "4"); + success = gHeroRadianceGenProgram.createShader(NULL, NULL); + } if (success && gGLManager.mHasCubeMapArray) { diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index cb1729cd1b..21c8d2089b 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -153,6 +153,7 @@ extern LLGLSLShader gGlowCombineProgram; extern LLGLSLShader gReflectionMipProgram; extern LLGLSLShader gGaussianProgram; extern LLGLSLShader gRadianceGenProgram; +extern LLGLSLShader gHeroRadianceGenProgram; extern LLGLSLShader gIrradianceGenProgram; extern LLGLSLShader gGlowCombineFXAAProgram; extern LLGLSLShader gDebugProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d81bcef259..3bd7acb06a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -785,6 +785,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mRT = &mAuxillaryRT; U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); + + res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. + mRT = &mHeroProbeRT; + allocateScreenBuffer(res, res, samples); + mRT = &mMainRT; gCubeSnapshot = FALSE; } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5ace90b000..bbe34933f7 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -699,6 +699,9 @@ public: // used by reflection probes and dynamic texture bakes RenderTargetPack mAuxillaryRT; + // Auxillary render target pack scaled to the hero probe's per-face size. + RenderTargetPack mHeroProbeRT; + // currently used render target pack RenderTargetPack* mRT; -- cgit v1.2.3 From aab98046b9971717ecdc739b2230377278c83da3 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 13:03:28 -0800 Subject: #677 More clipping fixes. --- .../shaders/class1/deferred/terrainF.glsl | 2 ++ .../shaders/class3/environment/waterF.glsl | 3 +++ indra/newview/llheroprobemanager.cpp | 27 +--------------------- 3 files changed, 6 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index f6d509e2c6..2dba7cb9d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -39,9 +39,11 @@ in vec4 vary_texcoord0; in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 position); void main() { + mirrorClip(pos); /// Note: This should duplicate the blending functionality currently used for the terrain rendering. vec4 color0 = texture(detail_0, vary_texcoord0.xy); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index b364e454e8..b2a81aa025 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -35,6 +35,8 @@ vec3 scaleSoftClipFragLinear(vec3 l); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); vec4 applyWaterFogViewLinear(vec3 pos, vec4 color); +void mirrorClip(vec3 pos); + // PBR interface vec2 BRDF(float NoV, float roughness); @@ -129,6 +131,7 @@ vec3 getPositionWithNDC(vec3 ndc); void main() { + mirrorClip(vary_position); vN = vary_normal; vT = vary_tangent; vB = cross(vN, vT); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 42c8d4fb3f..39f5bdec5a 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -167,7 +167,7 @@ void LLHeroProbeManager::update() mCurrentClipPlane.setVec(hero_pos, face_normal); mMirrorPosition = mNearestHero->getPositionAgent(); - mMirrorNormal = LLVector3(0, 0, 1); + mMirrorNormal = face_normal; probe_pos.load3(point.mV); @@ -255,31 +255,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; - /* - // perform a gaussian blur on the super sampled render before downsampling - { - gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / mProbeResolution); - S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); - - // horizontal - gGaussianProgram.uniform2f(direction, 1.f, 0.f); - gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); - - // vertical - gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); - screen_rt->bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - screen_rt->flush(); - } - */ - S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); -- cgit v1.2.3 From 2d4a63833c2515ae36c614fce8101f41be0e1d61 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 1 Feb 2024 15:34:34 -0800 Subject: #677 Clip underwater. --- indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index 223e55eb69..ef086fc3be 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -55,9 +55,11 @@ in vec4 view; in vec3 vary_position; vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color); +void mirrorClip(vec3 position); void main() { + mirrorClip(vary_position); vec4 color; //get detail normals -- cgit v1.2.3 From ee5fe08603a1250fb5e2c1196a082897134ebb53 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 2 Feb 2024 11:52:18 -0600 Subject: #677 Fix clip plane glitching out at certain angles --- indra/newview/llsettingsvo.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index da5504f83f..deeecc6b3c 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -1009,6 +1009,7 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) glh::matrix4f mat(modelView); glh::matrix4f invtrans = mat.inverse().transpose(); + invtrans.m[3] = invtrans.m[7] = invtrans.m[11] = 0.f; glh::vec3f enorm; glh::vec3f ep; invtrans.mult_matrix_vec(norm, enorm); @@ -1017,10 +1018,8 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm)); - norm = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorNormal.mV[0], gPipeline.mHeroProbeManager.mMirrorNormal.mV[1], - gPipeline.mHeroProbeManager.mMirrorNormal.mV[2]); - p = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorPosition.mV[0], gPipeline.mHeroProbeManager.mMirrorPosition.mV[1], - gPipeline.mHeroProbeManager.mMirrorPosition.mV[2]); + norm = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorNormal.mV); + p = glh::vec3f(gPipeline.mHeroProbeManager.mMirrorPosition.mV); invtrans.mult_matrix_vec(norm, enorm); enorm.normalize(); mat.mult_matrix_vec(p, ep); -- cgit v1.2.3 From 6846600e3ef1eec7fade19f61d2d45614ae1a8b0 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 2 Feb 2024 13:49:06 -0600 Subject: #677 Fix terrain clipping and tweak hero probe mixing with radiance --- .../shaders/class1/deferred/terrainV.glsl | 3 +- .../shaders/class3/deferred/softenLightF.glsl | 34 +++++++++++++++++++--- indra/newview/llviewershadermgr.cpp | 1 + 3 files changed, 33 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index 33a78fd26d..8e1e4b54d5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -25,6 +25,7 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; +uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; in vec3 position; @@ -59,7 +60,7 @@ void main() vec4 t_pos = modelview_projection_matrix * pre_pos; gl_Position = t_pos; - pos = t_pos.xyz; + pos = (modelview_matrix*pre_pos).xyz; vary_normal = normalize(normal_matrix * normal); diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index b49c3386db..be180b877f 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -60,6 +60,7 @@ uniform float ssao_irradiance_max; #endif // Inputs +uniform vec4 clipPlane; uniform mat3 env_mat; uniform mat3 ssao_effect_mat; uniform vec3 sun_dir; @@ -189,6 +190,19 @@ void main() sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss, false, amblit_linear); + #ifdef HERO_PROBES + float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; + if (clipDist > 0.0 && clipDist < 0.1 && perceptualRoughness < 0.2) + { + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) + { + radiance = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), perceptualRoughness*11).xyz; + } + } + #endif + + adjustIrradiance(irradiance, ambocc); vec3 diffuseColor; @@ -198,11 +212,11 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); - #ifdef HERO_PROBES + /*#ifdef HERO_PROBES vec3 refnormpersp = reflect(pos.xyz, norm.xyz); color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; - #endif + #endif*/ } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -226,6 +240,18 @@ void main() sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity, false, amblit_linear); + #ifdef HERO_PROBES + float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; + if (clipDist > 0.0 && clipDist < 0.1 && spec.a > 0.8) + { + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) + { + radiance = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-spec.a)*11).xyz; + } + } + #endif + adjustIrradiance(irradiance, ambocc); // apply lambertian IBL only (see pbrIbl) @@ -261,9 +287,9 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); - #ifdef HERO_PROBES + /*#ifdef HERO_PROBES color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; - #endif + #endif*/ } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index d0a54d8cfc..0aa0e13270 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -298,6 +298,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredPBROpaqueProgram); mShaderList.push_back(&gDeferredPBRAlphaProgram); mShaderList.push_back(&gDeferredAvatarProgram); + mShaderList.push_back(&gDeferredTerrainProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() -- cgit v1.2.3 From 5abc68ad438c1feb79f008aa8148dda77aae2af9 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 2 Feb 2024 15:43:56 -0600 Subject: #677 Move PBR mirror radiance mixing to reflectionProbeF so transparent PBR surfaces can be mirrors --- indra/llrender/llshadermgr.cpp | 6 ++++++ indra/llrender/llshadermgr.h | 1 + .../shaders/class3/deferred/reflectionProbeF.glsl | 18 ++++++++++++++++++ .../shaders/class3/deferred/softenLightF.glsl | 13 ------------- indra/newview/llviewercamera.cpp | 6 ++++++ indra/newview/llviewershadermgr.cpp | 7 ++----- 6 files changed, 33 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 758b54cf1f..e974fb636d 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -44,6 +44,7 @@ using std::make_pair; using std::string; LLShaderMgr * LLShaderMgr::sInstance = NULL; +bool LLShaderMgr::sMirrorsEnabled = false; LLShaderMgr::LLShaderMgr() { @@ -604,6 +605,11 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); } + if (sMirrorsEnabled) + { + extra_code_text[extra_code_count++] = strdup("#define HERO_PROBES 1\n"); + } + // Use alpha float to store bit flags // See: C++: addDeferredAttachment(), shader: frag_data[2] extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index ebd682141d..2c66965344 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -365,6 +365,7 @@ public: bool mShaderCacheInitialized = false; bool mShaderCacheEnabled = false; std::string mShaderCacheDir; + static bool sMirrorsEnabled; protected: diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index d9dc83bb10..fe2647452f 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -682,6 +682,12 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit) return col[1]+col[0]; } + +#if defined(HERO_PROBES) +uniform vec4 clipPlane; +uniform samplerCubeArray heroProbes; +#endif + void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit) { @@ -713,6 +719,18 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, glossenv = mix(glossenv, ssr.rgb, ssr.a); } #endif + +#if defined(HERO_PROBES) + float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; + if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8) + { + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) + { + glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz; + } + } +#endif } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index be180b877f..a8cfc3537e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -189,19 +189,6 @@ void main() float gloss = 1.0 - perceptualRoughness; sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss, false, amblit_linear); - - #ifdef HERO_PROBES - float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; - if (clipDist > 0.0 && clipDist < 0.1 && perceptualRoughness < 0.2) - { - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) - { - radiance = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), perceptualRoughness*11).xyz; - } - } - #endif - adjustIrradiance(irradiance, ambocc); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 4134e35f87..9ba42e4f47 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -764,6 +764,12 @@ BOOL LLViewerCamera::cameraUnderWater() const { LLViewerRegion* regionp = LLWorld::instance().getRegionFromPosAgent(getOrigin()); + if (gPipeline.mHeroProbeManager.isMirrorPass()) + { + // TODO: figure out how to handle this case + return FALSE; + } + if (!regionp) { regionp = gAgent.getRegion(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 0aa0e13270..e9562d64e4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -359,6 +359,8 @@ void LLViewerShaderMgr::setShaders() return; } + LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors; + if (!gGLManager.mHasRequirements) { // Viewer will show 'hardware requirements' warning later @@ -1813,11 +1815,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - if (LLPipeline::RenderMirrors) - { - gDeferredSoftenProgram.addPermutation("HERO_PROBES", "1"); - } - if (gSavedSettings.getBOOL("RenderDeferredSSAO")) { //if using SSAO, take screen space light map into account as if shadows are enabled gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2); -- cgit v1.2.3 From 4e61152ca2fc2fdaedc9e27c4d1a16e248b59d9a Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 5 Feb 2024 12:00:38 -0600 Subject: #677 Add clipping to trees and alpha masked blinn-phong --- .../app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl | 6 ++++++ .../shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl | 5 +++++ indra/newview/app_settings/shaders/class1/deferred/treeF.glsl | 3 +++ indra/newview/app_settings/shaders/class1/deferred/treeV.glsl | 4 ++++ indra/newview/llviewershadermgr.cpp | 3 +++ 5 files changed, 21 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index 6f3b94f734..e8ead91504 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -31,14 +31,20 @@ uniform float minimum_alpha; uniform sampler2D diffuseMap; +in vec3 vary_position; + in vec3 vary_normal; in vec4 vertex_color; in vec2 vary_texcoord0; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); + void main() { + mirrorClip(vary_position); + vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color; if (col.a < minimum_alpha) diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index e5f2af2c53..a07c892d8e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -28,6 +28,7 @@ out vec4 frag_data[4]; in vec3 vary_normal; +in vec3 vary_position; uniform float minimum_alpha; @@ -36,8 +37,12 @@ in vec2 vary_texcoord0; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); + void main() { + mirrorClip(vary_position); + vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color; if (col.a < minimum_alpha) diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index e2d87e68fa..f108faf283 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -32,13 +32,16 @@ uniform sampler2D diffuseMap; in vec4 vertex_color; in vec3 vary_normal; in vec2 vary_texcoord0; +in vec3 vary_position; uniform float minimum_alpha; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 pos); void main() { + mirrorClip(vary_position); vec4 col = texture(diffuseMap, vary_texcoord0.xy); if (col.a < minimum_alpha) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index ce8a10712c..c84fccd4c6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -24,6 +24,7 @@ */ uniform mat4 texture_matrix0; +uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; uniform mat3 normal_matrix; @@ -34,11 +35,14 @@ in vec2 texcoord0; out vec3 vary_normal; out vec4 vertex_color; out vec2 vary_texcoord0; +out vec3 vary_position; void main() { //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; vary_normal = normalize(normal_matrix * normal); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e9562d64e4..1fecf90c1f 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -299,6 +299,9 @@ LLViewerShaderMgr::LLViewerShaderMgr() : mShaderList.push_back(&gDeferredPBRAlphaProgram); mShaderList.push_back(&gDeferredAvatarProgram); mShaderList.push_back(&gDeferredTerrainProgram); + mShaderList.push_back(&gDeferredDiffuseAlphaMaskProgram); + mShaderList.push_back(&gDeferredNonIndexedDiffuseAlphaMaskProgram); + mShaderList.push_back(&gDeferredTreeProgram); } LLViewerShaderMgr::~LLViewerShaderMgr() -- cgit v1.2.3 From 0e91d18da3f203bcef681d3134b736978114c2bd Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 5 Feb 2024 15:36:42 -0600 Subject: #677 Add mirror clipping to rigged shaders --- .../shaders/class1/deferred/materialV.glsl | 2 - indra/newview/llenvironment.cpp | 6 +- indra/newview/llviewershadermgr.cpp | 118 +++++++++++++-------- indra/newview/llviewershadermgr.h | 5 +- 4 files changed, 83 insertions(+), 48 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index 41112bce30..ddf878ae60 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -78,9 +78,7 @@ void main() vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; -#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) vary_position = pos; -#endif gl_Position = projection_matrix*vec4(pos,1.0); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 60c2682078..affea3f69c 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1675,8 +1675,6 @@ void LLEnvironment::update(const LLViewerCamera * cam) updateSettingsUniforms(); - // *TODO: potential optimization - this block may only need to be - // executed some of the time. For example for water shaders only. { LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; end_shaders = LLViewerShaderMgr::instance()->endShaders(); @@ -1687,6 +1685,10 @@ void LLEnvironment::update(const LLViewerCamera * cam) || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)) { shaders_iter->mUniformsDirty = TRUE; + if (shaders_iter->mRiggedVariant) + { + shaders_iter->mRiggedVariant->mUniformsDirty = TRUE; + } } } } diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 1fecf90c1f..164b36af65 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -104,7 +104,6 @@ LLGLSLShader gObjectPreviewProgram; LLGLSLShader gSkinnedObjectPreviewProgram; LLGLSLShader gPhysicsPreviewProgram; LLGLSLShader gObjectFullbrightAlphaMaskProgram; -LLGLSLShader gSkinnedObjectFullbrightAlphaMaskProgram; LLGLSLShader gObjectBumpProgram; LLGLSLShader gSkinnedObjectBumpProgram; LLGLSLShader gObjectAlphaMaskNoColorProgram; @@ -226,7 +225,7 @@ LLGLSLShader gDeferredSkinnedPBRAlphaProgram; LLGLSLShader gDeferredPBRTerrainProgram; //helper for making a rigged variant of a given shader -bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) +static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) { riggedShader.mName = llformat("Skinned %s", shader.mName.c_str()); riggedShader.mFeatures = shader.mFeatures; @@ -241,73 +240,94 @@ bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) return riggedShader.createShader(NULL, NULL); } +static bool no_redundant_shaders(const std::vector& shaders) +{ + std::set names; + for (LLGLSLShader* shader : shaders) + { + if (names.find(shader->mName) != names.end()) + { + LL_WARNS("Shader") << "Redundant shader: " << shader->mName << LL_ENDL; + return false; + } + names.insert(shader->mName); + + if (shader->mRiggedVariant) + { + if (names.find(shader->mRiggedVariant->mName) != names.end()) + { + LL_WARNS("Shader") << "Redundant shader: " << shader->mRiggedVariant->mName << LL_ENDL; + return false; + } + names.insert(shader->mRiggedVariant->mName); + } + } + return true; +} + + LLViewerShaderMgr::LLViewerShaderMgr() : mShaderLevel(SHADER_COUNT, 0), mMaxAvatarShaderLevel(0) { +} + +LLViewerShaderMgr::~LLViewerShaderMgr() +{ + mShaderLevel.clear(); + mShaderList.clear(); +} + +void LLViewerShaderMgr::finalizeShaderList() +{ //ONLY shaders that need WL Param management should be added here - mShaderList.push_back(&gAvatarProgram); - mShaderList.push_back(&gWaterProgram); - mShaderList.push_back(&gWaterEdgeProgram); - mShaderList.push_back(&gAvatarEyeballProgram); - mShaderList.push_back(&gImpostorProgram); - mShaderList.push_back(&gObjectBumpProgram); - mShaderList.push_back(&gSkinnedObjectBumpProgram); - mShaderList.push_back(&gObjectFullbrightAlphaMaskProgram); - mShaderList.push_back(&gSkinnedObjectFullbrightAlphaMaskProgram); - mShaderList.push_back(&gObjectAlphaMaskNoColorProgram); - mShaderList.push_back(&gUnderWaterProgram); - mShaderList.push_back(&gDeferredSunProgram); + mShaderList.push_back(&gAvatarProgram); + mShaderList.push_back(&gWaterProgram); + mShaderList.push_back(&gWaterEdgeProgram); + mShaderList.push_back(&gAvatarEyeballProgram); + mShaderList.push_back(&gImpostorProgram); + mShaderList.push_back(&gObjectBumpProgram); + mShaderList.push_back(&gObjectFullbrightAlphaMaskProgram); + mShaderList.push_back(&gObjectAlphaMaskNoColorProgram); + mShaderList.push_back(&gUnderWaterProgram); + mShaderList.push_back(&gDeferredSunProgram); mShaderList.push_back(&gHazeProgram); mShaderList.push_back(&gHazeWaterProgram); - mShaderList.push_back(&gDeferredSoftenProgram); - mShaderList.push_back(&gDeferredAlphaProgram); + mShaderList.push_back(&gDeferredSoftenProgram); + mShaderList.push_back(&gDeferredAlphaProgram); mShaderList.push_back(&gHUDAlphaProgram); - mShaderList.push_back(&gDeferredSkinnedAlphaProgram); - mShaderList.push_back(&gDeferredAlphaImpostorProgram); - mShaderList.push_back(&gDeferredSkinnedAlphaImpostorProgram); - mShaderList.push_back(&gDeferredFullbrightProgram); + mShaderList.push_back(&gDeferredAlphaImpostorProgram); + mShaderList.push_back(&gDeferredFullbrightProgram); mShaderList.push_back(&gHUDFullbrightProgram); - mShaderList.push_back(&gDeferredFullbrightAlphaMaskProgram); + mShaderList.push_back(&gDeferredFullbrightAlphaMaskProgram); mShaderList.push_back(&gHUDFullbrightAlphaMaskProgram); mShaderList.push_back(&gDeferredFullbrightAlphaMaskAlphaProgram); mShaderList.push_back(&gHUDFullbrightAlphaMaskAlphaProgram); - mShaderList.push_back(&gDeferredFullbrightShinyProgram); + mShaderList.push_back(&gDeferredFullbrightShinyProgram); mShaderList.push_back(&gHUDFullbrightShinyProgram); - mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram); - mShaderList.push_back(&gDeferredSkinnedFullbrightProgram); - mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskProgram); - mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskAlphaProgram); - mShaderList.push_back(&gDeferredEmissiveProgram); - mShaderList.push_back(&gDeferredSkinnedEmissiveProgram); - mShaderList.push_back(&gDeferredAvatarEyesProgram); - mShaderList.push_back(&gDeferredAvatarAlphaProgram); - mShaderList.push_back(&gDeferredWLSkyProgram); - mShaderList.push_back(&gDeferredWLCloudProgram); + mShaderList.push_back(&gDeferredEmissiveProgram); + mShaderList.push_back(&gDeferredAvatarEyesProgram); + mShaderList.push_back(&gDeferredAvatarAlphaProgram); + mShaderList.push_back(&gDeferredWLSkyProgram); + mShaderList.push_back(&gDeferredWLCloudProgram); mShaderList.push_back(&gDeferredWLMoonProgram); mShaderList.push_back(&gDeferredWLSunProgram); mShaderList.push_back(&gDeferredPBRAlphaProgram); mShaderList.push_back(&gHUDPBRAlphaProgram); - mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram); mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma mShaderList.push_back(&gNoPostGammaCorrectProgram); mShaderList.push_back(&gLegacyPostGammaCorrectProgram); mShaderList.push_back(&gDeferredDiffuseProgram); - mShaderList.push_back(&gObjectBumpProgram); mShaderList.push_back(&gDeferredBumpProgram); mShaderList.push_back(&gDeferredPBROpaqueProgram); - mShaderList.push_back(&gDeferredPBRAlphaProgram); mShaderList.push_back(&gDeferredAvatarProgram); mShaderList.push_back(&gDeferredTerrainProgram); mShaderList.push_back(&gDeferredDiffuseAlphaMaskProgram); mShaderList.push_back(&gDeferredNonIndexedDiffuseAlphaMaskProgram); mShaderList.push_back(&gDeferredTreeProgram); -} -LLViewerShaderMgr::~LLViewerShaderMgr() -{ - mShaderLevel.clear(); - mShaderList.clear(); + // make sure there are no redundancies + llassert(no_redundant_shaders(mShaderList)); } // static @@ -362,6 +382,8 @@ void LLViewerShaderMgr::setShaders() return; } + mShaderList.clear(); + LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors; if (!gGLManager.mHasRequirements) @@ -545,6 +567,8 @@ void LLViewerShaderMgr::setShaders() } gPipeline.createGLBuffers(); + finalizeShaderList(); + reentrance = false; } @@ -1077,9 +1101,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { if (success) { - mShaderList.push_back(&gDeferredMaterialProgram[i]); + bool has_skin = i & 0x10; - gDeferredMaterialProgram[i].mName = llformat("Deferred Material Shader %d", i); + if (!has_skin) + { + mShaderList.push_back(&gDeferredMaterialProgram[i]); + gDeferredMaterialProgram[i].mName = llformat("Material Shader %d", i); + } + else + { + gDeferredMaterialProgram[i].mName = llformat("Skinned Material Shader %d", i); + } U32 alpha_mode = i & 0x3; @@ -1116,7 +1148,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); } - bool has_skin = i & 0x10; + gDeferredMaterialProgram[i].mFeatures.hasSrgb = true; gDeferredMaterialProgram[i].mFeatures.encodesNormal = true; gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 21c8d2089b..9b4583cacf 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -41,6 +41,10 @@ public: LLViewerShaderMgr(); /* virtual */ ~LLViewerShaderMgr(); + // Add shaders to mShaderList for later uniform propagation + // Will assert on redundant shader entries in debug builds + void finalizeShaderList(); + // singleton pattern implementation static LLViewerShaderMgr * instance(); static void releaseInstance(); @@ -172,7 +176,6 @@ extern LLGLSLShader gOneTextureFilterProgram; //object shaders extern LLGLSLShader gObjectPreviewProgram; extern LLGLSLShader gPhysicsPreviewProgram; -extern LLGLSLShader gSkinnedObjectFullbrightAlphaMaskProgram; extern LLGLSLShader gObjectBumpProgram; extern LLGLSLShader gSkinnedObjectBumpProgram; extern LLGLSLShader gObjectAlphaMaskNoColorProgram; -- cgit v1.2.3 From 75b67c3750083e5ea150432d999866a0e383f927 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 5 Feb 2024 16:01:47 -0600 Subject: #677 Add hero probes to blinn-phong surfaces --- .../shaders/class3/deferred/reflectionProbeF.glsl | 39 ++++++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index fe2647452f..4f6e01764a 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -684,10 +684,33 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit) #if defined(HERO_PROBES) + uniform vec4 clipPlane; uniform samplerCubeArray heroProbes; + +void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) +{ + float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; + if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8) + { + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) + { + glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz; + } + } +} + +#else + +void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) +{ +} + #endif + + void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit) { @@ -720,17 +743,7 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, } #endif -#if defined(HERO_PROBES) - float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; - if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8) - { - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) - { - glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz; - } - } -#endif + tapHeroProbe(glossenv, pos, norm, glossiness); } void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, @@ -818,6 +831,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout { float lod = (1.0-glossiness)*reflection_lods; glossenv = sampleProbes(pos, normalize(refnormpersp), lod); + } if (envIntensity > 0.0) @@ -845,6 +859,9 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout } #endif + tapHeroProbe(glossenv, pos, norm, glossiness); + tapHeroProbe(legacyenv, pos, norm, 1.0); + glossenv = clamp(glossenv, vec3(0), vec3(10)); } -- cgit v1.2.3 From 086249191078bcfb81d2697509c325fb34ffaf94 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 6 Feb 2024 01:31:13 -0800 Subject: #679 Add mirror update params to the volume floater. #740 Add support for FLAG_MIRROR in the viewer for mirror probes. --- indra/llprimitive/llprimitive.cpp | 13 ++++++ indra/llprimitive/llprimitive.h | 3 ++ indra/newview/llpanelvolume.cpp | 38 ++++++++++++++--- indra/newview/llvovolume.cpp | 44 ++++++++++++++++++++ indra/newview/llvovolume.h | 4 ++ .../newview/skins/default/xui/en/floater_tools.xml | 47 ++++++++++++++-------- 6 files changed, 127 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index f67959de5b..0f538ffd0c 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1968,6 +1968,19 @@ void LLReflectionProbeParams::setIsDynamic(bool is_dynamic) } } + +void LLReflectionProbeParams::setIsMirror(bool is_mirror) +{ + if (is_mirror) + { + mFlags |= FLAG_MIRROR; + } + else + { + mFlags &= ~FLAG_MIRROR; + } +} + //============================================================================ LLFlexibleObjectData::LLFlexibleObjectData() { diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 88bac34ef2..db4f4ddeba 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -197,6 +197,7 @@ public: { FLAG_BOX_VOLUME = 0x01, // use a box influence volume FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe + FLAG_MIRROR = 0x04, // This probe is used for reflections on realtime mirrors. }; protected: @@ -220,11 +221,13 @@ public: void setClipDistance(F32 distance) { mClipDistance = llclamp(distance, REFLECTION_PROBE_MIN_CLIP_DISTANCE, REFLECTION_PROBE_MAX_CLIP_DISTANCE); } void setIsBox(bool is_box); void setIsDynamic(bool is_dynamic); + void setIsMirror(bool is_mirror); F32 getAmbiance() const { return mAmbiance; } F32 getClipDistance() const { return mClipDistance; } bool getIsBox() const { return (mFlags & FLAG_BOX_VOLUME) != 0; } bool getIsDynamic() const { return (mFlags & FLAG_DYNAMIC) != 0; } + bool getIsMirror() const { return (mFlags & FLAG_MIRROR) != 0; } }; //------------------------------------------------- diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index a306a0a9ac..c03f52d23f 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -155,7 +155,7 @@ BOOL LLPanelVolume::postBuild() // REFLECTION PROBE Parameters { childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this); - childSetCommitCallback("Probe Dynamic", onCommitProbe, this); + childSetCommitCallback("Probe Update Type", onCommitProbe, this); childSetCommitCallback("Probe Volume Type", onCommitProbe, this); childSetCommitCallback("Probe Ambiance", onCommitProbe, this); childSetCommitCallback("Probe Near Clip", onCommitProbe, this); @@ -401,17 +401,18 @@ void LLPanelVolume::getState( ) bool probe_enabled = is_probe && editable && single_volume; - getChildView("Probe Dynamic")->setEnabled(probe_enabled); + getChildView("Probe Update Type")->setEnabled(probe_enabled); getChildView("Probe Volume Type")->setEnabled(probe_enabled); getChildView("Probe Ambiance")->setEnabled(probe_enabled); getChildView("Probe Near Clip")->setEnabled(probe_enabled); + getChildView("Probe Update Label")->setEnabled(probe_enabled); if (!probe_enabled) { getChild("Probe Volume Type", true)->clear(); getChild("Probe Ambiance", true)->clear(); getChild("Probe Near Clip", true)->clear(); - getChild("Probe Dynamic", true)->clear(); + getChild("Probe Update Type", true)->clear(); } else { @@ -425,10 +426,28 @@ void LLPanelVolume::getState( ) volume_type = "Sphere"; } + std::string update_type; + if (volobjp->getReflectionProbeIsDynamic()) + { + update_type = "Dynamic"; + } + else if (volobjp->getReflectionProbeIsMirror()) + { + update_type = "Mirror"; + + } + else + { + update_type = "Static"; + } + + getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); + getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror"); + 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()); + getChild("Probe Update Type", true)->setValue(update_type); } // Animated Mesh @@ -715,7 +734,7 @@ void LLPanelVolume::clearCtrls() getChildView("Reflection Probe")->setEnabled(false);; getChildView("Probe Volume Type")->setEnabled(false); - getChildView("Probe Dynamic")->setEnabled(false); + getChildView("Probe Update Type")->setEnabled(false); getChildView("Probe Ambiance")->setEnabled(false); getChildView("Probe Near Clip")->setEnabled(false); getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false); @@ -1422,7 +1441,14 @@ 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 update_type = self->getChild("Probe Update Type")->getValue().asString(); + + volobjp->setReflectionProbeIsDynamic(update_type == "Dynamic"); + volobjp->setReflectionProbeIsMirror(update_type == "Mirror"); + + self->getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); + self->getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror"); std::string shape_type = self->getChild("Probe Volume Type")->getValue().asString(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9813039145..77f654be23 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3442,6 +3442,22 @@ bool LLVOVolume::setReflectionProbeIsBox(bool is_box) return false; } +bool LLVOVolume::setReflectionProbeIsPlane(bool is_plane) +{ + LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getIsBox() != is_plane) + { + param_block->setIsBox(is_plane); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + return true; + } + } + + return false; +} + bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) { LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -3458,6 +3474,22 @@ bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) return false; } +bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) +{ + LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + if (param_block->getIsMirror() != is_mirror) + { + param_block->setIsMirror(is_mirror); + parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + return true; + } + } + + return false; +} + F32 LLVOVolume::getReflectionProbeAmbiance() const { const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -3506,6 +3538,18 @@ bool LLVOVolume::getReflectionProbeIsDynamic() const return false; } +bool LLVOVolume::getReflectionProbeIsMirror() const +{ + const LLReflectionProbeParams *param_block = + (const LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + if (param_block) + { + return param_block->getIsMirror(); + } + + return false; +} + U32 LLVOVolume::getVolumeInterfaceID() const { if (mVolumeImpl) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index b03fc4b862..89ef1d7d7a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -305,13 +305,17 @@ public: bool setReflectionProbeAmbiance(F32 ambiance); bool setReflectionProbeNearClip(F32 near_clip); bool setReflectionProbeIsBox(bool is_box); + bool setReflectionProbeIsPlane(bool is_plane); bool setReflectionProbeIsDynamic(bool is_dynamic); + bool setReflectionProbeIsMirror(bool is_mirror); BOOL isReflectionProbe() const override; F32 getReflectionProbeAmbiance() const; F32 getReflectionProbeNearClip() const; bool getReflectionProbeIsBox() const; + bool getReflectionProbeIsPlane() const; bool getReflectionProbeIsDynamic() const; + bool getReflectionProbeIsMirror() const; BOOL isMirror() const override; diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 510351b471..4f4216c85a 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2410,15 +2410,6 @@ even though the user gets a free copy. name="object_horizontal" top_pad="10" width="278" /> - - + name="Probe Update Label" + text_readonly_color="LabelDisabledColor" + width="100"> + Probe Update + + + + + + Date: Tue, 6 Feb 2024 02:53:57 -0800 Subject: #740 Make sure we evaluate if the probe is a mirror probe or not. #682 Re-enable gaussian filtering, and reduce the mirror resolution back to 1024. Also just generally clean up the code a bit. --- indra/llprimitive/llprimitive.cpp | 34 ------------ indra/llprimitive/llprimitive.h | 11 ---- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llheroprobemanager.cpp | 65 ++++++++++++----------- indra/newview/llheroprobemanager.h | 7 +-- indra/newview/llpanelvolume.cpp | 29 ----------- indra/newview/llpanelvolume.h | 4 +- indra/newview/llviewerobject.cpp | 46 +---------------- indra/newview/llviewerobject.h | 5 -- indra/newview/llvovolume.cpp | 91 ++++++--------------------------- indra/newview/llvovolume.h | 9 ---- 11 files changed, 57 insertions(+), 246 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 0f538ffd0c..53d09df618 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1825,40 +1825,6 @@ bool LLLightParams::fromLLSD(LLSD& sd) //============================================================================ -LLMirrorParams::LLMirrorParams() -{ - mType = PARAMS_MIRROR; -} - -BOOL LLMirrorParams::pack(LLDataPacker &dp) const -{ - return TRUE; -} - -BOOL LLMirrorParams::unpack(LLDataPacker &dp) -{ - return TRUE; -} - -bool LLMirrorParams::operator==(const LLNetworkData& data) const -{ - if (data.mType != PARAMS_REFLECTION_PROBE) - { - return false; - } - return true; -} - -void LLMirrorParams::copy(const LLNetworkData& data) -{ - const LLMirrorParams *param = (LLMirrorParams*)&data; - mType = param->mType; -} - -//============================================================================ - -//============================================================================ - LLReflectionProbeParams::LLReflectionProbeParams() { mType = PARAMS_REFLECTION_PROBE; diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index db4f4ddeba..5622483861 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,7 +109,6 @@ public: PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, - PARAMS_MIRROR = 0x100, }; public: @@ -173,16 +172,6 @@ public: F32 getCutoff() const { return mCutoff; } }; -class LLMirrorParams : public LLNetworkData -{ -public: - LLMirrorParams(); - /*virtual*/ BOOL pack(LLDataPacker &dp) const; - /*virtual*/ BOOL unpack(LLDataPacker &dp); - /*virtual*/ bool operator==(const LLNetworkData& data) const; - /*virtual*/ void copy(const LLNetworkData& data); -}; - extern const F32 REFLECTION_PROBE_MIN_AMBIANCE; extern const F32 REFLECTION_PROBE_MAX_AMBIANCE; extern const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f2ba4ba29e..ef51c7f0dc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10421,7 +10421,7 @@ Type S32 Value - 2048 + 1024 RenderHeroProbeDistance diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 39f5bdec5a..c9728b8d93 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -127,38 +127,22 @@ void LLHeroProbeManager::update() else { // Valid drawables only please. Unregister this one. - unregisterHeroDrawable(vo); + unregisterViewerObject(vo); } } else { - unregisterHeroDrawable(vo); + unregisterViewerObject(vo); } } if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) { - U8 mode = mNearestHero->mirrorFace(); - mode = llmin(mNearestHero->mDrawable->getNumFaces() - 1, mode); - - mCurrentFace = mNearestHero->mDrawable->getFace(mode); - LLVector3 hero_pos = mCurrentFace->getPositionAgent(); - - - // Calculate the average normal. - LLVector4a *posp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mPositions; - U16 *indp = mCurrentFace->getViewerObject()->getVolume()->getVolumeFace(mCurrentFace->getTEOffset()).mIndices; - // get first three vertices (first triangle) - LLVector4a v0 = posp[indp[0]]; - LLVector4a v1 = posp[indp[1]]; - LLVector4a v2 = posp[indp[2]]; - - v1.sub(v0); - v2.sub(v0); - LLVector3 face_normal = LLVector3(v1[0], v1[1], v1[2]) % LLVector3(v2[0], v2[1], v2[2]); + LLVector3 hero_pos = mNearestHero->getPositionAgent(); + LLVector3 face_normal = LLVector3(0, 0, 1); + face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation(); face_normal.normalize(); - face_normal *= mCurrentFace->getXform()->getWorldRotation(); LLVector3 offset = camera_pos - hero_pos; LLVector3 project = face_normal * (offset * face_normal); @@ -166,7 +150,7 @@ void LLHeroProbeManager::update() LLVector3 point = (reject - project) + hero_pos; mCurrentClipPlane.setVec(hero_pos, face_normal); - mMirrorPosition = mNearestHero->getPositionAgent(); + mMirrorPosition = hero_pos; mMirrorNormal = face_normal; @@ -254,6 +238,30 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + mRenderTarget.bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mRenderTarget.flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + gGaussianProgram.unbind(); + } S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -527,24 +535,21 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerHeroDrawable(LLVOVolume* drawablep) +void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { + llassert(drawablep != nullptr); + if (mHeroVOList.find(drawablep) == mHeroVOList.end()) { + // Probe isn't in our list for consideration. Add it. mHeroVOList.insert(drawablep); - LL_INFOS() << "Mirror drawable registered." << LL_ENDL; } } -void LLHeroProbeManager::unregisterHeroDrawable(LLVOVolume* drawablep) +void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { if (mHeroVOList.find(drawablep) != mHeroVOList.end()) { mHeroVOList.erase(drawablep); } } - -bool LLHeroProbeManager::isViableMirror(LLFace* face) const -{ - return face == mCurrentFace; -} diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 0b32768bb1..7485a8cd72 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -68,10 +68,8 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); - void registerHeroDrawable(LLVOVolume* drawablep); - void unregisterHeroDrawable(LLVOVolume* drawablep); - - bool isViableMirror(LLFace* face) const; + void registerViewerObject(LLVOVolume *drawablep); + void unregisterViewerObject(LLVOVolume* drawablep); bool isMirrorPass() const { return mRenderingMirror; } @@ -140,6 +138,5 @@ private: std::set mHeroVOList; LLVOVolume* mNearestHero; - LLFace* mCurrentFace; }; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index c03f52d23f..e0d95c5386 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -114,11 +114,6 @@ BOOL LLPanelVolume::postBuild() getChild("FlexForceZ")->setValidateBeforeCommit(precommitValidate); } - // Mirror Parameters - { - childSetCommitCallback("Mirror Checkbox Ctrl", onCommitIsMirror, this); - } - // LIGHT Parameters { childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this); @@ -309,10 +304,6 @@ void LLPanelVolume::getState( ) getChildView("select_single")->setVisible(true); getChildView("select_single")->setEnabled(true); } - - BOOL is_mirror = volobjp && volobjp->isMirror(); - getChild("Mirror Checkbox Ctrl")->setValue(is_mirror); - getChildView("Mirror Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); // Light properties BOOL is_light = volobjp && volobjp->getIsLight(); @@ -774,20 +765,6 @@ void LLPanelVolume::sendIsLight() LL_INFOS() << "update light sent" << LL_ENDL; } -void LLPanelVolume::sendIsMirror() -{ - LLViewerObject* objectp = mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - - BOOL value = getChild("Mirror Checkbox Ctrl")->getValue(); - volobjp->setIsMirror(value); - LL_INFOS() << "update mirror sent" << LL_ENDL; -} - void notify_cant_select_reflection_probe() { if (!gSavedSettings.getBOOL("SelectReflectionProbes")) @@ -1495,12 +1472,6 @@ void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata ) self->sendIsLight(); } -void LLPanelVolume::onCommitIsMirror( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelVolume* self = (LLPanelVolume*) userdata; - self->sendIsMirror(); -} - // static void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp) { diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index a658351624..aafefa918f 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -57,8 +57,7 @@ public: void refresh(); void sendIsLight(); - - void sendIsMirror(); + // when an object is becoming a refleciton probe, present a dialog asking for confirmation // otherwise, send the reflection probe update immediately void sendIsReflectionProbe(); @@ -72,7 +71,6 @@ public: static void onCommitIsLight( LLUICtrl* ctrl, void* userdata); static void onCommitLight( LLUICtrl* ctrl, void* userdata); - static void onCommitIsMirror( LLUICtrl* ctrl, void* userdata); static void onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata); static void onCommitProbe(LLUICtrl* ctrl, void* userdata); void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 691a2e14d3..d71814bd3f 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -313,9 +313,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLastUpdateCached(FALSE), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), - mRiggedAttachedWarned(false), - mIsMirror(false), - mMirrorFace(3) + mRiggedAttachedWarned(false) { if (!is_global) { @@ -1149,39 +1147,6 @@ U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector return parent_id; } -void detectMirror(const std::string &str, bool &mirror, U8 &mode) -{ - - std::stringstream ss(str); - std::string word; - while (ss >> word) - { - if (word == "IsMirror") - { - mirror = true; - } - - if (mirror) - { - bool num = false; - std::string::const_iterator it = word.begin(); - while (it != word.end()) - { - num = std::isdigit(*it); - ++it; - - if (!num) - break; - } - - if (num) - { - mode = atoi(word.c_str()); - } - } - } -} - U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -1557,8 +1522,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - - detectMirror(temp_string, mIsMirror, mMirrorFace); LLColor4U coloru; mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); @@ -1946,8 +1909,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string temp_string; dp->unpackString(temp_string, "Text"); - detectMirror(temp_string, mIsMirror, mMirrorFace); - LLColor4U coloru; dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); coloru.mV[3] = 255 - coloru.mV[3]; @@ -6327,11 +6288,6 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para { new_block = new LLReflectionProbeParams(); break; - } - case LLNetworkData::PARAMS_MIRROR: - { - new_block = new LLMirrorParams(); - break; } default: { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index f3c00e83dc..80da7b2f73 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -257,8 +257,6 @@ public: virtual BOOL isRiggedMesh() const { return FALSE; } virtual BOOL hasLightTexture() const { return FALSE; } virtual BOOL isReflectionProbe() const { return FALSE; } - virtual BOOL isMirror() const { return FALSE; } - virtual U8 mirrorFace() const { return 0; } // This method returns true if the object is over land owned by // the agent, one of its groups, or it encroaches and @@ -880,9 +878,6 @@ protected: F32 mPhysicsCost; F32 mLinksetPhysicsCost; - bool mIsMirror; - U8 mMirrorFace; - // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 77f654be23..54e0a0113d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -249,9 +249,6 @@ LLVOVolume::~LLVOVolume() mTextureAnimp = NULL; delete mVolumeImpl; mVolumeImpl = NULL; - - if (mIsMirror) - gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); gMeshRepo.unregisterMesh(this); @@ -1000,11 +997,6 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) updateReflectionProbePtr(); } - if (isMirror()) - { - gPipeline.mHeroProbeManager.registerHeroDrawable(this); - } - updateRadius(); bool force_update = true; // avoid non-alpha mDistance update being optimized away mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); @@ -3327,48 +3319,6 @@ F32 LLVOVolume::getLightCutoff() const } } -bool LLVOVolume::setIsMirror(BOOL is_mirror) -{ - BOOL was_mirror = isMirror(); - if (is_mirror != was_mirror) - { - if (is_mirror) - { - setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, TRUE, true); - } - else - { - setParameterEntryInUse(LLNetworkData::PARAMS_MIRROR, FALSE, true); - } - } - - updateMirrorDrawable(); - - return was_mirror != is_mirror; -} - -void LLVOVolume::updateMirrorDrawable() -{ - if (isMirror()) - { - gPipeline.mHeroProbeManager.registerHeroDrawable(this); - } - else - { - gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); - } -} - -BOOL LLVOVolume::isMirror() const -{ - return mIsMirror; -} - -U8 LLVOVolume::mirrorFace() const -{ - return mMirrorFace; -} - BOOL LLVOVolume::isReflectionProbe() const { return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -3442,22 +3392,6 @@ bool LLVOVolume::setReflectionProbeIsBox(bool is_box) return false; } -bool LLVOVolume::setReflectionProbeIsPlane(bool is_plane) -{ - LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); - if (param_block) - { - if (param_block->getIsBox() != is_plane) - { - param_block->setIsBox(is_plane); - parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); - return true; - } - } - - return false; -} - bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) { LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); @@ -4463,25 +4397,34 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u } updateReflectionProbePtr(); - - if (isMirror()) - gPipeline.mHeroProbeManager.registerHeroDrawable(this); - else - gPipeline.mHeroProbeManager.unregisterHeroDrawable(this); } void LLVOVolume::updateReflectionProbePtr() { if (isReflectionProbe()) { - if (mReflectionProbe.isNull()) + if (mReflectionProbe.isNull() && !getReflectionProbeIsMirror()) { mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this); } + else if (mReflectionProbe.isNull() && getReflectionProbeIsMirror()) + { + // Geenz: This is a special case - what we want here is a hero probe. + // What we want to do here is instantiate a hero probe from the hero probe manager. + gPipeline.mHeroProbeManager.registerViewerObject(this); + } } - else if (mReflectionProbe.notNull()) + else if (mReflectionProbe.notNull() || getReflectionProbeIsMirror()) { - mReflectionProbe = nullptr; + if (mReflectionProbe.notNull()) + { + mReflectionProbe = nullptr; + } + + if (getReflectionProbeIsMirror()) + { + gPipeline.mHeroProbeManager.unregisterViewerObject(this); + } } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 89ef1d7d7a..cac09609b3 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -294,18 +294,12 @@ public: F32 getLightRadius() const; F32 getLightFalloff(const F32 fudge_factor = 1.f) const; F32 getLightCutoff() const; - - // Mirrors - bool setIsMirror(BOOL is_mirror); - void updateMirrorDrawable(); - U8 mirrorFace() const override; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); bool setReflectionProbeAmbiance(F32 ambiance); bool setReflectionProbeNearClip(F32 near_clip); bool setReflectionProbeIsBox(bool is_box); - bool setReflectionProbeIsPlane(bool is_plane); bool setReflectionProbeIsDynamic(bool is_dynamic); bool setReflectionProbeIsMirror(bool is_mirror); @@ -313,11 +307,8 @@ public: F32 getReflectionProbeAmbiance() const; F32 getReflectionProbeNearClip() const; bool getReflectionProbeIsBox() const; - bool getReflectionProbeIsPlane() const; bool getReflectionProbeIsDynamic() const; bool getReflectionProbeIsMirror() const; - - BOOL isMirror() const override; // Flexible Objects U32 getVolumeInterfaceID() const; -- cgit v1.2.3 From b0c7dc653dc730f1f95aa95fc6df876dfe7b04a0 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 6 Feb 2024 12:02:51 -0600 Subject: #677 Fix for mac build --- indra/newview/llviewershadermgr.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra') diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 164b36af65..91983f6603 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -240,6 +240,9 @@ static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader return riggedShader.createShader(NULL, NULL); } +#ifdef SHOW_ASSERT +// return true if there are no redundant shaders in the given vector +// also checks for redundant variants static bool no_redundant_shaders(const std::vector& shaders) { std::set names; @@ -264,6 +267,7 @@ static bool no_redundant_shaders(const std::vector& shaders) } return true; } +#endif LLViewerShaderMgr::LLViewerShaderMgr() : -- cgit v1.2.3 From dd8f936ba8e18171770e9971675a2433d25751f1 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 7 Feb 2024 11:09:27 -0600 Subject: #665 Make viewer respect MaxTextureResolution from SimulatorFeatures --- indra/newview/llviewerregion.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index dae476d9d7..53dd3af9ef 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2407,7 +2407,19 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) mSimulatorFeatures = sim_features; setSimulatorFeaturesReceived(true); - + + // if region has MaxTextureResolution, set max_texture_dimension settings, otherwise use default + if (mSimulatorFeatures.has("MaxTextureResolution")) + { + S32 max_texture_resolution = mSimulatorFeatures["MaxTextureResolution"].asInteger(); + gSavedSettings.setS32("max_texture_dimension_X", max_texture_resolution); + gSavedSettings.setS32("max_texture_dimension_Y", max_texture_resolution); + } + else + { + gSavedSettings.setS32("max_texture_dimension_X", 1024); + gSavedSettings.setS32("max_texture_dimension_Y", 1024); + } } //this is called when the parent is not cacheable. -- cgit v1.2.3 From c583c666d2f463e9de43a571a62b74c3817e5038 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 7 Feb 2024 09:05:25 -0800 Subject: secondlife/viewer#67: (debug) Add temporary setting to force-load PBR terrain --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llvlcomposition.cpp | 21 +++++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4413cf9269..e1fb82be32 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10844,6 +10844,17 @@ Value 0 + RenderTerrainPBRForce + + Comment + Force-load PBR terrain if enabled + Persist + 0 + Type + Boolean + Value + 0 + RenderTerrainPBRDetail Comment diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index f645023217..7c16ee4f61 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -142,6 +142,27 @@ BOOL LLTerrainMaterials::texturesReady(BOOL boost) BOOL LLTerrainMaterials::materialsReady(BOOL boost) { +#if 1 + static bool sRenderTerrainPBREnabled = gSavedSettings.get("RenderTerrainPBREnabled"); + static LLCachedControl sRenderTerrainPBRForce(gSavedSettings, "RenderTerrainPBRForce", false); + if (sRenderTerrainPBREnabled && sRenderTerrainPBRForce) + { + bool defined = true; + for (S32 i = 0; i < ASSET_COUNT; i++) + { + if (!mDetailMaterials[i]) + { + defined = false; + break; + } + } + if (defined) + { + return TRUE; + } + } +#endif + BOOL ready = TRUE; for (S32 i = 0; i < ASSET_COUNT; i++) { -- cgit v1.2.3 From 78f7423bcd1d0980a1e99cfa92b620dc74063169 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 31 Jan 2024 17:03:28 -0800 Subject: secondlife/viewer#711: More thoroughly clamp terrain PBR detail --- indra/newview/llviewershadermgr.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 7e49ea3b7c..7149dc781f 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -640,6 +640,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() const F32 triplanar_factor = gSavedSettings.getF32("RenderTerrainPBRTriplanarBlendFactor"); attribs["TERRAIN_TRIPLANAR_BLEND_FACTOR"] = llformat("%.2f", triplanar_factor); S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); + detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX); attribs["TERRAIN_PBR_DETAIL"] = llformat("%d", detail); } -- cgit v1.2.3 From 139c10dbeb4270259160e8e7988c6d916033c32e Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 31 Jan 2024 17:50:04 -0800 Subject: secondlife/viewer#711: Add more options to drop textures from terrain, not yet used --- indra/newview/app_settings/settings.xml | 2 +- .../shaders/class1/deferred/pbrterrainF.glsl | 80 +++++++++++++++++++- .../shaders/class1/deferred/pbrterrainUtilF.glsl | 77 +++++++++++++++++++ indra/newview/lldrawpoolterrain.cpp | 87 +++++++++++++--------- indra/newview/llviewershadermgr.h | 14 ++-- 5 files changed, 217 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e1fb82be32..85b90a8da5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10858,7 +10858,7 @@ RenderTerrainPBRDetail Comment - Detail level for PBR terrain. 0 is full detail. Negative values drop rendering features in accordance with the GLTF specification, which reduces the number of texture binds. Some Intel and Mac graphics drivers do not support more than 16 texture binds. Because PBR terrain exceeds this limit at the highest detail level, reducing texture binds is necessary for compatibility. + Detail level for PBR terrain. 0 is full detail. Negative values drop rendering features, in accordance with the GLTF specification when possible, which reduces the number of texture binds. Persist 1 Type diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index db03e0885c..adb3319934 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -26,6 +26,9 @@ /*[EXTRA_CODE_HERE]*/ #define TERRAIN_PBR_DETAIL_EMISSIVE 0 +#define TERRAIN_PBR_DETAIL_OCCLUSION -1 +#define TERRAIN_PBR_DETAIL_NORMAL -2 +#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3 #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 #define TerrainCoord vec4[2] @@ -51,8 +54,14 @@ TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal) struct PBRMix { vec4 col; // RGB color with alpha, linear space +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) vec3 orm; // Occlusion, roughness, metallic +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + vec2 rm; // Roughness, metallic +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) vec3 vNt; // Unpacked normal texture sample, vector +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) vec3 emissive; // RGB emissive color, linear space #endif @@ -63,13 +72,21 @@ PBRMix init_pbr_mix(); PBRMix terrain_sample_and_multiply_pbr( TerrainCoord terrain_coord , sampler2D tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , sampler2D tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , sampler2D tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , sampler2D tex_emissive #endif , vec4 factor_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , vec3 factor_orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , vec2 factor_rm +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , vec3 factor_emissive #endif @@ -81,21 +98,23 @@ out vec4 frag_data[4]; uniform sampler2D alpha_ramp; -// *TODO: More configurable quality level which disables PBR features on machines -// with limited texture availability // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures uniform sampler2D detail_0_base_color; uniform sampler2D detail_1_base_color; uniform sampler2D detail_2_base_color; uniform sampler2D detail_3_base_color; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) uniform sampler2D detail_0_normal; uniform sampler2D detail_1_normal; uniform sampler2D detail_2_normal; uniform sampler2D detail_3_normal; +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) uniform sampler2D detail_0_metallic_roughness; uniform sampler2D detail_1_metallic_roughness; uniform sampler2D detail_2_metallic_roughness; uniform sampler2D detail_3_metallic_roughness; +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) uniform sampler2D detail_0_emissive; uniform sampler2D detail_1_emissive; @@ -104,8 +123,10 @@ uniform sampler2D detail_3_emissive; #endif uniform vec4[4] baseColorFactors; // See also vertex_color in pbropaqueV.glsl +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) uniform vec4 metallicFactors; uniform vec4 roughnessFactors; +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) uniform vec3[4] emissiveColors; #endif @@ -139,6 +160,7 @@ void main() TerrainMix tm = get_terrain_mix_weights(alpha1, alpha2, alphaFinal); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) // RGB = Occlusion, Roughness, Metal // default values, see LLViewerTexture::sDefaultPBRORMImagep // occlusion 1.0 @@ -149,6 +171,13 @@ void main() orm_factors[1] = vec3(1.0, roughnessFactors.y, metallicFactors.y); orm_factors[2] = vec3(1.0, roughnessFactors.z, metallicFactors.z); orm_factors[3] = vec3(1.0, roughnessFactors.w, metallicFactors.w); +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + vec2[4] rm_factors; + rm_factors[0] = vec2(roughnessFactors.x, metallicFactors.x); + rm_factors[1] = vec2(roughnessFactors.y, metallicFactors.y); + rm_factors[2] = vec2(roughnessFactors.z, metallicFactors.z); + rm_factors[3] = vec2(roughnessFactors.w, metallicFactors.w); +#endif PBRMix mix = init_pbr_mix(); PBRMix mix2; @@ -158,13 +187,21 @@ void main() mix2 = terrain_sample_and_multiply_pbr( terrain_texcoord , detail_0_base_color +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , detail_0_metallic_roughness +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , detail_0_normal +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_0_emissive #endif , baseColorFactors[0] +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , orm_factors[0] +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , rm_factors[0] +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[0] #endif @@ -180,13 +217,21 @@ void main() mix2 = terrain_sample_and_multiply_pbr( terrain_texcoord , detail_1_base_color +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , detail_1_metallic_roughness +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , detail_1_normal +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_1_emissive #endif , baseColorFactors[1] +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , orm_factors[1] +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , rm_factors[1] +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[1] #endif @@ -202,13 +247,21 @@ void main() mix2 = terrain_sample_and_multiply_pbr( terrain_texcoord , detail_2_base_color +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , detail_2_metallic_roughness +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , detail_2_normal +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_2_emissive #endif , baseColorFactors[2] +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , orm_factors[2] +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , rm_factors[2] +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[2] #endif @@ -224,13 +277,21 @@ void main() mix2 = terrain_sample_and_multiply_pbr( terrain_texcoord , detail_3_base_color +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , detail_3_metallic_roughness +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , detail_3_normal +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , detail_3_emissive #endif , baseColorFactors[3] +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , orm_factors[3] +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , rm_factors[3] +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , emissiveColors[3] #endif @@ -248,6 +309,7 @@ void main() } float base_color_factor_alpha = terrain_mix(tm, vec4(baseColorFactors[0].z, baseColorFactors[1].z, baseColorFactors[2].z, baseColorFactors[3].z)); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) // from mikktspace.com vec3 vNt = mix.vNt; vec3 vN = vary_normal; @@ -257,15 +319,27 @@ void main() vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); tnorm *= gl_FrontFacing ? 1.0 : -1.0; +#else + vec3 tnorm = vary_normal; + tnorm *= gl_FrontFacing ? 1.0 : -1.0; +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) #define emissive mix.emissive #else #define emissive vec3(0) +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) +#define orm mix.orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) +#define orm vec3(1.0, mix.rm) +#else +// Matte plastic potato terrain +#define orm vec3(1.0, 1.0, 0.0) #endif frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(mix.orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[1] = max(vec4(orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 316b751590..935c3f9301 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -47,6 +47,9 @@ */ #define TERRAIN_PBR_DETAIL_EMISSIVE 0 +#define TERRAIN_PBR_DETAIL_OCCLUSION -1 +#define TERRAIN_PBR_DETAIL_NORMAL -2 +#define TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS -3 in vec3 vary_vertex_normal; @@ -75,8 +78,14 @@ vec3 srgb_to_linear(vec3 c); struct PBRMix { vec4 col; // RGB color with alpha, linear space +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) vec3 orm; // Occlusion, roughness, metallic +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + vec2 rm; // Roughness, metallic +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) vec3 vNt; // Unpacked normal texture sample, vector +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) vec3 emissive; // RGB emissive color, linear space #endif @@ -86,8 +95,14 @@ PBRMix init_pbr_mix() { PBRMix mix; mix.col = vec4(0); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) mix.orm = vec3(0); +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + mix.rm = vec2(0); +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) mix.vNt = vec3(0); +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) mix.emissive = vec3(0); #endif @@ -105,8 +120,14 @@ PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight) { PBRMix mix; mix.col = mix1.col + (mix2.col * mix2_weight); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) mix.orm = mix1.orm + (mix2.orm * mix2_weight); +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + mix.rm = mix1.rm + (mix2.rm * mix2_weight); +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) mix.vNt = mix1.vNt + (mix2.vNt * mix2_weight); +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) mix.emissive = mix1.emissive + (mix2.emissive * mix2_weight); #endif @@ -116,8 +137,12 @@ PBRMix mix_pbr(PBRMix mix1, PBRMix mix2, float mix2_weight) PBRMix sample_pbr( vec2 uv , sampler2D tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , sampler2D tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , sampler2D tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , sampler2D tex_emissive #endif @@ -126,8 +151,14 @@ PBRMix sample_pbr( PBRMix mix; mix.col = texture(tex_col, uv); mix.col.rgb = srgb_to_linear(mix.col.rgb); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) mix.orm = texture(tex_orm, uv).xyz; +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + mix.rm = texture(tex_orm, uv).yz; +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) mix.vNt = texture(tex_vNt, uv).xyz*2.0-1.0; +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) mix.emissive = srgb_to_linear(texture(tex_emissive, uv).xyz); #endif @@ -254,8 +285,12 @@ PBRMix terrain_sample_pbr( TerrainCoord terrain_coord , TerrainTriplanar tw , sampler2D tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , sampler2D tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , sampler2D tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , sampler2D tex_emissive #endif @@ -272,14 +307,20 @@ PBRMix terrain_sample_pbr( PBRMix mix_x = sample_pbr( get_uv_x() , tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , tex_emissive #endif ); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) // Triplanar-specific normal texture fix mix_x.vNt = _t_normal_post_x(mix_x.vNt); +#endif mix = mix_pbr(mix, mix_x, tw.weight.x); break; default: @@ -292,14 +333,20 @@ PBRMix terrain_sample_pbr( PBRMix mix_y = sample_pbr( get_uv_y() , tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , tex_emissive #endif ); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) // Triplanar-specific normal texture fix mix_y.vNt = _t_normal_post_y(mix_y.vNt); +#endif mix = mix_pbr(mix, mix_y, tw.weight.y); break; default: @@ -312,15 +359,21 @@ PBRMix terrain_sample_pbr( PBRMix mix_z = sample_pbr( get_uv_z() , tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , tex_emissive #endif ); +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) // Triplanar-specific normal texture fix // *NOTE: Bottom face has not been tested mix_z.vNt = _t_normal_post_z(mix_z.vNt); +#endif mix = mix_pbr(mix, mix_z, tw.weight.z); break; default: @@ -341,7 +394,11 @@ PBRMix terrain_sample_pbr( PBRMix multiply_factors_pbr( PBRMix mix_in , vec4 factor_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , vec3 factor_orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , vec2 factor_rm +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , vec3 factor_emissive #endif @@ -349,7 +406,11 @@ PBRMix multiply_factors_pbr( { PBRMix mix = mix_in; mix.col *= factor_col; +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) mix.orm *= factor_orm; +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + mix.rm *= factor_rm; +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) mix.emissive *= factor_emissive; #endif @@ -359,13 +420,21 @@ PBRMix multiply_factors_pbr( PBRMix terrain_sample_and_multiply_pbr( TerrainCoord terrain_coord , sampler2D tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , sampler2D tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , sampler2D tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , sampler2D tex_emissive #endif , vec4 factor_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , vec3 factor_orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , vec2 factor_rm +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , vec3 factor_emissive #endif @@ -377,8 +446,12 @@ PBRMix terrain_sample_and_multiply_pbr( , _t_triplanar() #endif , tex_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) , tex_orm +#endif +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) , tex_vNt +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , tex_emissive #endif @@ -386,7 +459,11 @@ PBRMix terrain_sample_and_multiply_pbr( mix = multiply_factors_pbr(mix , factor_col +#if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) , factor_orm +#elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + , factor_rm +#endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) , factor_emissive #endif diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index fc8e9fcfe5..3a943f27f6 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -54,8 +54,6 @@ const F32 DETAIL_SCALE = 1.f/16.f; int DebugDetailMap = 0; -const S32 PBR_DETAIL_EMISSIVE = 0; - S32 LLDrawPoolTerrain::sPBRDetailMode = 0; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; F32 LLDrawPoolTerrain::sPBRDetailScale = DETAIL_SCALE; @@ -399,31 +397,37 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) gGL.getTexUnit(detail_basecolor[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); gGL.getTexUnit(detail_basecolor[i])->activate(); - detail_normal[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); - if (detail_normal_texturep) - { - gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep); - } - else + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL) { - gGL.getTexUnit(detail_normal[i])->bind(LLViewerFetchedTexture::sFlatNormalImagep); + detail_normal[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); + if (detail_normal_texturep) + { + gGL.getTexUnit(detail_normal[i])->bind(detail_normal_texturep); + } + else + { + gGL.getTexUnit(detail_normal[i])->bind(LLViewerFetchedTexture::sFlatNormalImagep); + } + gGL.getTexUnit(detail_normal[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_normal[i])->activate(); } - gGL.getTexUnit(detail_normal[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail_normal[i])->activate(); - detail_metalrough[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); - if (detail_metalrough_texturep) + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) { - gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep); - } - else - { - gGL.getTexUnit(detail_metalrough[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + detail_metalrough[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); + if (detail_metalrough_texturep) + { + gGL.getTexUnit(detail_metalrough[i])->bind(detail_metalrough_texturep); + } + else + { + gGL.getTexUnit(detail_metalrough[i])->bind(LLViewerFetchedTexture::sWhiteImagep); + } + gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail_metalrough[i])->activate(); } - gGL.getTexUnit(detail_metalrough[i])->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail_metalrough[i])->activate(); - if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_EMISSIVE) { detail_emissive[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); if (detail_emissive_texturep) @@ -499,9 +503,12 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) minimum_alphas[i] = min_alpha; } shader->uniform4fv(LLShaderMgr::TERRAIN_BASE_COLOR_FACTORS, terrain_material_count, (F32*)base_color_factors); - shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]); - shader->uniform4f(LLShaderMgr::TERRAIN_ROUGHNESS_FACTORS, roughness_factors[0], roughness_factors[1], roughness_factors[2], roughness_factors[3]); - if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + { + shader->uniform4f(LLShaderMgr::TERRAIN_METALLIC_FACTORS, metallic_factors[0], metallic_factors[1], metallic_factors[2], metallic_factors[3]); + shader->uniform4f(LLShaderMgr::TERRAIN_ROUGHNESS_FACTORS, roughness_factors[0], roughness_factors[1], roughness_factors[2], roughness_factors[3]); + } + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_EMISSIVE) { shader->uniform3fv(LLShaderMgr::TERRAIN_EMISSIVE_COLORS, terrain_material_count, (F32*)emissive_colors); } @@ -521,9 +528,15 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) for (U32 i = 0; i < terrain_material_count; ++i) { sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); - if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL) + { + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_NORMAL + i); + } + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + { + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_METALLIC_ROUGHNESS + i); + } + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_EMISSIVE) { sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_EMISSIVE + i); } @@ -532,15 +545,21 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) gGL.getTexUnit(detail_basecolor[i])->disable(); gGL.getTexUnit(detail_basecolor[i])->activate(); - gGL.getTexUnit(detail_normal[i])->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail_normal[i])->disable(); - gGL.getTexUnit(detail_normal[i])->activate(); + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_NORMAL) + { + gGL.getTexUnit(detail_normal[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_normal[i])->disable(); + gGL.getTexUnit(detail_normal[i])->activate(); + } - gGL.getTexUnit(detail_metalrough[i])->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail_metalrough[i])->disable(); - gGL.getTexUnit(detail_metalrough[i])->activate(); + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) + { + gGL.getTexUnit(detail_metalrough[i])->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail_metalrough[i])->disable(); + gGL.getTexUnit(detail_metalrough[i])->activate(); + } - if (sPBRDetailMode >= PBR_DETAIL_EMISSIVE) + if (sPBRDetailMode >= TERRAIN_PBR_DETAIL_EMISSIVE) { gGL.getTexUnit(detail_emissive[i])->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(detail_emissive[i])->disable(); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 4273c3e70c..824c66ab49 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -281,15 +281,19 @@ extern LLGLSLShader gDeferredPBROpaqueProgram; extern LLGLSLShader gDeferredPBRAlphaProgram; extern LLGLSLShader gHUDPBRAlphaProgram; -// Encodes detail level for dropping textures, in accordance with the GLTF spec +// Encodes detail level for dropping textures, in accordance with the GLTF spec where possible // 0 is highest detail, -1 drops emissive, etc +// Dropping metallic roughness is off-spec - Reserve for potato machines as needed // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#additional-textures enum TerrainPBRDetail : S32 { - TERRAIN_PBR_DETAIL_MAX = 0, - TERRAIN_PBR_DETAIL_EMISSIVE = 0, - TERRAIN_PBR_DETAIL_OCCLUSION = -1, - TERRAIN_PBR_DETAIL_MIN = -1, + TERRAIN_PBR_DETAIL_MAX = 0, + TERRAIN_PBR_DETAIL_EMISSIVE = 0, + TERRAIN_PBR_DETAIL_OCCLUSION = -1, + TERRAIN_PBR_DETAIL_NORMAL = -2, + TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS = -3, + TERRAIN_PBR_DETAIL_BASE_COLOR = -4, + TERRAIN_PBR_DETAIL_MIN = -4, }; extern LLGLSLShader gDeferredPBRTerrainProgram; #endif -- cgit v1.2.3 From c790fe58e63b851a730c1aaedde62e3ffbdf064a Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 7 Feb 2024 09:34:52 -0800 Subject: secondlife/viewer#711: Reduce PBR terrain textures at low graphics settings --- .../newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl | 2 -- indra/newview/featuretable.txt | 7 +++++++ indra/newview/featuretable_mac.txt | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index adb3319934..c83a6be85d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -41,7 +41,6 @@ #define MIX_Z 1 << 5 #define MIX_W 1 << 6 -// TODO: Decide if this struct needs to be declared struct TerrainMix { vec4 weight; @@ -50,7 +49,6 @@ struct TerrainMix TerrainMix get_terrain_mix_weights(float alpha1, float alpha2, float alphaFinal); -// TODO: Decide if this struct needs to be declared struct PBRMix { vec4 col; // RGB color with alpha, linear space diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index c341097dfc..f32c0f698b 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -96,6 +96,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTerrainPBRDetail 1 -4 RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0 RenderVolumeLODFactor 1 1.125 @@ -126,6 +127,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTerrainPBRDetail 1 -1 RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.125 @@ -154,6 +156,7 @@ RenderLocalLightCount 1 512 RenderTransparentWater 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.25 @@ -184,6 +187,7 @@ RenderLocalLightCount 1 1024 RenderTransparentWater 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 1 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.375 @@ -214,6 +218,7 @@ RenderLocalLightCount 1 2048 RenderTransparentWater 1 1 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.5 @@ -243,6 +248,7 @@ RenderMaxPartCount 1 4096 RenderLocalLightCount 1 4096 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -272,6 +278,7 @@ RenderLocalLightCount 1 8192 RenderMaxPartCount 1 8192 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index ac0ac15bd0..8770ca3c7f 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -45,6 +45,7 @@ RenderObjectBump 1 1 RenderLocalLightCount 1 4096 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 @@ -90,6 +91,7 @@ RenderLocalLightCount 1 8 RenderMaxPartCount 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTerrainPBRDetail 1 -4 RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 0 RenderTreeLODFactor 1 0 @@ -120,6 +122,7 @@ RenderMaxPartCount 1 2048 RenderLocalLightCount 1 256 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTerrainPBRDetail 1 -1 RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -150,6 +153,7 @@ RenderMaxPartCount 1 4096 RenderLocalLightCount 1 512 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -180,6 +184,7 @@ RenderMaxPartCount 1 4096 RenderLocalLightCount 1 1024 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 1 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -210,6 +215,7 @@ RenderMaxPartCount 1 4096 RenderLocalLightCount 1 2048 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -240,6 +246,7 @@ RenderMaxPartCount 1 4096 RenderLocalLightCount 1 4096 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 @@ -269,6 +276,7 @@ RenderLocalLightCount 1 8192 RenderMaxPartCount 1 8192 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTerrainPBRDetail 1 0 RenderTerrainPBRPlanarSampleCount 1 3 RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 -- cgit v1.2.3 From cae3e086ce7937d2851238f30f4f13fa41eadc6c Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 7 Feb 2024 09:36:50 -0800 Subject: secondlife/viewer#711: Bump featuretable --- indra/newview/featuretable.txt | 2 +- indra/newview/featuretable_mac.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index f32c0f698b..965391b5cf 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 59 +version 60 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 8770ca3c7f..61cde82512 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 56 +version 57 // The version number above should be incremented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended -- cgit v1.2.3 From 1940188e75806ffdd60807017210092b0dbe0dcf Mon Sep 17 00:00:00 2001 From: Henri Beauchamp Date: Wed, 7 Feb 2024 21:40:17 +0100 Subject: Confusion between light diffuse and light color in HDR auto-adjust mode While the SUNLIGHT_COLOR uniform is initialized with getSunlightColor() when not auto-adjusting for HDR, it is overwritten with getSunDiffuse()*auto_adjust_factor when auto-adjusting, causing very bad lighting discrepancies in the latter mode (especially when not at midday or midnight). Let's use getSunlightColor() everywhere, shall we ?... --- indra/newview/llsettingsvo.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 7009fb98ab..17405ca864 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -718,11 +718,11 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); // TODO -- make these getters return vec3s - LLVector3 sunDiffuse = LLVector3(psky->getSunlightColor().mV); - LLVector3 moonDiffuse = LLVector3(psky->getMoonlightColor().mV); + LLVector3 sun_light_color = LLVector3(psky->getSunlightColor().mV); + LLVector3 moon_light_color = LLVector3(psky->getMoonlightColor().mV); - shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); - shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); + shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_light_color); + shader->uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, moon_light_color); shader->uniform3fv(LLShaderMgr::CLOUD_COLOR, LLVector3(psky->getCloudColor().mV)); @@ -766,9 +766,9 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, auto_adjust_hdr_scale); LLColor3 blue_horizon = getBlueHorizon() * auto_adjust_blue_horizon_scale; LLColor3 blue_density = getBlueDensity() * auto_adjust_blue_density_scale; - LLColor3 sun_diffuse = getSunDiffuse() * auto_adjust_sun_color_scale; + sun_light_color = sun_light_color * auto_adjust_sun_color_scale; - shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_diffuse.mV); + shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_light_color.mV); shader->uniform3fv(LLShaderMgr::BLUE_DENSITY, blue_density.mV); shader->uniform3fv(LLShaderMgr::BLUE_HORIZON, blue_horizon.mV); -- cgit v1.2.3 From 192e77344f44d4a2d6bc765403b27f611b106240 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 8 Feb 2024 10:40:56 -0800 Subject: Make the UI conditional. --- indra/newview/llpanelvolume.cpp | 5 +++++ indra/newview/skins/default/xui/en/floater_tools.xml | 14 +++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index e0d95c5386..6b5b691587 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -392,6 +392,11 @@ void LLPanelVolume::getState( ) bool probe_enabled = is_probe && editable && single_volume; + getChildView("Probe Update Type")->setVisible(LLPipeline::RenderMirrors); + getChildView("Probe Update Label")->setVisible(LLPipeline::RenderMirrors); + getChildView("Probe Dynamic")->setVisible(!LLPipeline::RenderMirrors); + + getChildView("Probe Dynamic")->setEnabled(probe_enabled); getChildView("Probe Update Type")->setEnabled(probe_enabled); getChildView("Probe Volume Type")->setEnabled(probe_enabled); getChildView("Probe Ambiance")->setEnabled(probe_enabled); diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 4f4216c85a..72c78fec3d 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2559,7 +2559,19 @@ even though the user gets a free copy. name="Box" value="Box"/> + + + - Date: Thu, 8 Feb 2024 11:39:35 -0800 Subject: #671 Setup the viewer to respect the MirrorsEnabled simulator feature. --- indra/llrender/llshadermgr.cpp | 8 -------- indra/newview/llheroprobemanager.cpp | 12 ++++++++++++ indra/newview/llheroprobemanager.h | 3 ++- indra/newview/llpanelvolume.cpp | 8 +++++--- indra/newview/llviewershadermgr.cpp | 2 +- indra/newview/pipeline.cpp | 6 +++++- 6 files changed, 25 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index d510e061a2..5384133220 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -231,14 +231,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } - - if (features->hasHeroProbes) - { - if (!shader->attachFragmentObject("deferred/heroProbesUtil.glsl")) - { - return FALSE; - } - } if (features->hasShadows) { diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c9728b8d93..a105fd2fa8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -72,6 +72,18 @@ void LLHeroProbeManager::update() return; } + // This should be moved elsewhere. + LLSD features; + gAgent.getRegion()->getSimulatorFeatures(features); + if (mHasMirrors != features.has("MirrorsEnabled")) + { + mHasMirrors = features.has("MirrorsEnabled"); + LLViewerShaderMgr::instance()->setShaders(); + } + + if (!mHasMirrors) + return; + LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 7485a8cd72..5ec1101b45 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -72,8 +72,8 @@ public: void unregisterViewerObject(LLVOVolume* drawablep); bool isMirrorPass() const { return mRenderingMirror; } + bool hasMirrors() const { return mHasMirrors; } - LLPlane currentMirrorClip() const { return mCurrentClipPlane; } LLVector3 mMirrorPosition; LLVector3 mMirrorNormal; @@ -135,6 +135,7 @@ private: bool mReset = false; bool mRenderingMirror = false; + bool mHasMirrors = false; std::set mHeroVOList; LLVOVolume* mNearestHero; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 6b5b691587..f64106948f 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -392,9 +392,11 @@ void LLPanelVolume::getState( ) bool probe_enabled = is_probe && editable && single_volume; - getChildView("Probe Update Type")->setVisible(LLPipeline::RenderMirrors); - getChildView("Probe Update Label")->setVisible(LLPipeline::RenderMirrors); - getChildView("Probe Dynamic")->setVisible(!LLPipeline::RenderMirrors); + bool mirrors_enabled = LLPipeline::RenderMirrors && gPipeline.mHeroProbeManager.hasMirrors(); + + getChildView("Probe Update Type")->setVisible(mirrors_enabled); + getChildView("Probe Update Label")->setVisible(mirrors_enabled); + getChildView("Probe Dynamic")->setVisible(!mirrors_enabled); getChildView("Probe Dynamic")->setEnabled(probe_enabled); getChildView("Probe Update Type")->setEnabled(probe_enabled); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index e3c2c429da..e6cf37bc3c 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -390,7 +390,7 @@ void LLViewerShaderMgr::setShaders() mShaderList.clear(); - LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors; + LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors && gPipeline.mHeroProbeManager.hasMirrors(); if (!gGLManager.mHasRequirements) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9fb9ade943..32c7563aa0 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1062,7 +1062,11 @@ void LLPipeline::refreshCachedSettings() RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples"); RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); - RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); + if (gSavedSettings.getBOOL("RenderMirrors") != (BOOL)RenderMirrors) + { + RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); + LLViewerShaderMgr::instance()->setShaders(); + } sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; -- cgit v1.2.3 From c721152c444ee7a13e4217f86dfcce34b7488ee5 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 8 Feb 2024 14:54:01 -0600 Subject: Fix for crash in LLHeroProbeManager --- indra/newview/llheroprobemanager.cpp | 8 ++++++-- indra/newview/llheroprobemanager.h | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index a105fd2fa8..c66054f618 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -126,7 +126,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo) + if (vo && !vo->isDead()) { if (vo->mDrawable.notNull()) { @@ -148,7 +148,7 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && mNearestHero->mDrawable.notNull()) + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); @@ -168,6 +168,10 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); } + else + { + mNearestHero = nullptr; + } mHeroProbeStrength = 1; } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 5ec1101b45..9151189a92 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -137,7 +137,7 @@ private: bool mRenderingMirror = false; bool mHasMirrors = false; - std::set mHeroVOList; - LLVOVolume* mNearestHero; + std::set> mHeroVOList; + LLPointer mNearestHero; }; -- cgit v1.2.3 From a7310ae7417b2f6e7013762a1cfe3211a163a8d7 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 8 Feb 2024 15:07:54 -0600 Subject: #671 Nudge RenderMirrors and clear shader cache as needed based on SimulatorFeatures --- indra/newview/llheroprobemanager.cpp | 12 ------------ indra/newview/llheroprobemanager.h | 2 -- indra/newview/llpanelvolume.cpp | 2 +- indra/newview/llviewerregion.cpp | 8 ++++++++ indra/newview/llviewershadermgr.cpp | 2 +- indra/newview/pipeline.cpp | 1 + 6 files changed, 11 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index c66054f618..2a81919856 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -72,18 +72,6 @@ void LLHeroProbeManager::update() return; } - // This should be moved elsewhere. - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (mHasMirrors != features.has("MirrorsEnabled")) - { - mHasMirrors = features.has("MirrorsEnabled"); - LLViewerShaderMgr::instance()->setShaders(); - } - - if (!mHasMirrors) - return; - LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; llassert(!gCubeSnapshot); // assert a snapshot is not in progress if (LLAppViewer::instance()->logoutRequestSent()) diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 9151189a92..552c5dcaab 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -72,7 +72,6 @@ public: void unregisterViewerObject(LLVOVolume* drawablep); bool isMirrorPass() const { return mRenderingMirror; } - bool hasMirrors() const { return mHasMirrors; } LLVector3 mMirrorPosition; LLVector3 mMirrorNormal; @@ -135,7 +134,6 @@ private: bool mReset = false; bool mRenderingMirror = false; - bool mHasMirrors = false; std::set> mHeroVOList; LLPointer mNearestHero; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index f64106948f..8d8263448d 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -392,7 +392,7 @@ void LLPanelVolume::getState( ) bool probe_enabled = is_probe && editable && single_volume; - bool mirrors_enabled = LLPipeline::RenderMirrors && gPipeline.mHeroProbeManager.hasMirrors(); + bool mirrors_enabled = LLPipeline::RenderMirrors; getChildView("Probe Update Type")->setVisible(mirrors_enabled); getChildView("Probe Update Label")->setVisible(mirrors_enabled); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index ce57585d82..cea083e07d 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2451,6 +2451,14 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) gSavedSettings.setS32("max_texture_dimension_X", 1024); gSavedSettings.setS32("max_texture_dimension_Y", 1024); } + + bool mirrors_enabled = false; + if (mSimulatorFeatures.has("MirrorsEnabled")) + { + mirrors_enabled = mSimulatorFeatures["MirrorsEnabled"].asBoolean(); + } + + gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); } //this is called when the parent is not cacheable. diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index b175172b9b..4eb934114d 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -390,7 +390,7 @@ void LLViewerShaderMgr::setShaders() mShaderList.clear(); - LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors && gPipeline.mHeroProbeManager.hasMirrors(); + LLShaderMgr::sMirrorsEnabled = LLPipeline::RenderMirrors; if (!gGLManager.mHasRequirements) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 32c7563aa0..9d90002eb9 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1065,6 +1065,7 @@ void LLPipeline::refreshCachedSettings() if (gSavedSettings.getBOOL("RenderMirrors") != (BOOL)RenderMirrors) { RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); + LLViewerShaderMgr::instance()->clearShaderCache(); LLViewerShaderMgr::instance()->setShaders(); } sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); -- cgit v1.2.3 From c3d4f571aa5522e3028842c6d7caa977819a7393 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 8 Feb 2024 13:22:10 -0800 Subject: Update softenLightF.glsl --- .../shaders/class3/deferred/softenLightF.glsl | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index a8cfc3537e..cc6e16c64f 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -198,12 +198,6 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); - - /*#ifdef HERO_PROBES - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - - color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - gloss) * 11).xyz * specularColor; - #endif*/ } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { @@ -226,18 +220,6 @@ void main() vec3 legacyenv = vec3(0); sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity, false, amblit_linear); - - #ifdef HERO_PROBES - float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; - if (clipDist > 0.0 && clipDist < 0.1 && spec.a > 0.8) - { - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) - { - radiance = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-spec.a)*11).xyz; - } - } - #endif adjustIrradiance(irradiance, ambocc); @@ -274,10 +256,6 @@ void main() // add radiance map applyGlossEnv(color, glossenv, spec, pos.xyz, norm.xyz); - /*#ifdef HERO_PROBES - color = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0 - spec.a) * 11).xyz * spec.rgb; - #endif*/ - } color.rgb = mix(color.rgb, baseColor.rgb, baseColor.a); -- cgit v1.2.3 From 9c6e351e05d7e0580700f040af8161da52de7a08 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 8 Feb 2024 13:24:16 -0800 Subject: secondlife/viewer-issues#67: Improve PBR terrain loading robustness --- indra/newview/lldrawpoolterrain.cpp | 78 +++++++++++++--------- indra/newview/llvlcomposition.cpp | 128 +++++++++++++++++++++--------------- indra/newview/llvlcomposition.h | 16 +++-- 3 files changed, 133 insertions(+), 89 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 3a943f27f6..8844f1d7e4 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -125,27 +125,29 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures() tex->setBoostLevel(level); tex->addTextureStats(stats); - LLPointer& mat = compp->mDetailMaterials[i]; - llassert(mat.notNull()); - if (mat->mBaseColorTexture) + LLPointer& fetched_material = compp->mDetailMaterials[i]; + if (fetched_material) { - mat->mBaseColorTexture->setBoostLevel(level); - mat->mBaseColorTexture->addTextureStats(stats); - } - if (mat->mNormalTexture) - { - mat->mNormalTexture->setBoostLevel(level); - mat->mNormalTexture->addTextureStats(stats); - } - if (mat->mMetallicRoughnessTexture) - { - mat->mMetallicRoughnessTexture->setBoostLevel(level); - mat->mMetallicRoughnessTexture->addTextureStats(stats); - } - if (mat->mEmissiveTexture) - { - mat->mEmissiveTexture->setBoostLevel(level); - mat->mEmissiveTexture->addTextureStats(stats); + if (fetched_material->mBaseColorTexture) + { + fetched_material->mBaseColorTexture->setBoostLevel(level); + fetched_material->mBaseColorTexture->addTextureStats(stats); + } + if (fetched_material->mNormalTexture) + { + fetched_material->mNormalTexture->setBoostLevel(level); + fetched_material->mNormalTexture->addTextureStats(stats); + } + if (fetched_material->mMetallicRoughnessTexture) + { + fetched_material->mMetallicRoughnessTexture->setBoostLevel(level); + fetched_material->mMetallicRoughnessTexture->addTextureStats(stats); + } + if (fetched_material->mEmissiveTexture) + { + fetched_material->mEmissiveTexture->setBoostLevel(level); + fetched_material->mEmissiveTexture->addTextureStats(stats); + } } } } @@ -234,7 +236,7 @@ void LLDrawPoolTerrain::drawLoop() void LLDrawPoolTerrain::renderFullShader() { - const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(TRUE); + const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(true, false); // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); @@ -362,15 +364,24 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - LLPointer (*materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; + LLPointer (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; + + constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; + constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT; + llassert(shader_material_count == terrain_material_count); if (local_materials) { // Override region terrain with the global local override terrain - materials = &gLocalTerrainMaterials.mDetailMaterials; + fetched_materials = &gLocalTerrainMaterials.mDetailMaterials; } + const LLGLTFMaterial* materials[terrain_material_count]; + for (U32 i = 0; i < terrain_material_count; ++i) + { + materials[i] = (*fetched_materials)[i].get(); + if (!materials[i]) { materials[i] = &LLGLTFMaterial::sDefault; } + } - constexpr U32 terrain_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; S32 detail_basecolor[terrain_material_count]; S32 detail_normal[terrain_material_count]; S32 detail_metalrough[terrain_material_count]; @@ -378,12 +389,19 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) for (U32 i = 0; i < terrain_material_count; ++i) { - const LLFetchedGLTFMaterial* material = (*materials)[i].get(); + LLViewerTexture* detail_basecolor_texturep = nullptr; + LLViewerTexture* detail_normal_texturep = nullptr; + LLViewerTexture* detail_metalrough_texturep = nullptr; + LLViewerTexture* detail_emissive_texturep = nullptr; - LLViewerTexture *detail_basecolor_texturep = material->mBaseColorTexture; - LLViewerTexture *detail_normal_texturep = material->mNormalTexture; - LLViewerTexture *detail_metalrough_texturep = material->mMetallicRoughnessTexture; - LLViewerTexture *detail_emissive_texturep = material->mEmissiveTexture; + const LLFetchedGLTFMaterial* fetched_material = (*fetched_materials)[i].get(); + if (fetched_material) + { + detail_basecolor_texturep = fetched_material->mBaseColorTexture; + detail_normal_texturep = fetched_material->mNormalTexture; + detail_metalrough_texturep = fetched_material->mMetallicRoughnessTexture; + detail_emissive_texturep = fetched_material->mEmissiveTexture; + } detail_basecolor[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); if (detail_basecolor_texturep) @@ -483,7 +501,7 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) F32 minimum_alphas[terrain_material_count]; for (U32 i = 0; i < terrain_material_count; ++i) { - const LLFetchedGLTFMaterial* material = (*materials)[i].get(); + const LLGLTFMaterial* material = materials[i]; base_color_factors[i] = material->mBaseColor; metallic_factors[i] = material->mMetallicFactor; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 7c16ee4f61..c092eb82f3 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -75,12 +75,12 @@ LLTerrainMaterials::~LLTerrainMaterials() BOOL LLTerrainMaterials::generateMaterials() { - if (texturesReady(TRUE)) + if (texturesReady(true, true)) { return TRUE; } - if (materialsReady(TRUE)) + if (materialsReady(true, true)) { return TRUE; } @@ -123,25 +123,41 @@ LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType() { LL_PROFILE_ZONE_SCOPED; - const BOOL use_textures = texturesReady() || !materialsReady(); + const BOOL use_textures = texturesReady(false, false) || !materialsReady(false, false); return use_textures ? Type::TEXTURE : Type::PBR; } -BOOL LLTerrainMaterials::texturesReady(BOOL boost) +bool LLTerrainMaterials::texturesReady(bool boost, bool strict) { - BOOL ready = TRUE; - for (S32 i = 0; i < ASSET_COUNT; i++) - { - if (!textureReady(mDetailTextures[i], boost)) + bool ready[ASSET_COUNT]; + // *NOTE: Calls to textureReady may boost textures. Do not early-return. + for (S32 i = 0; i < ASSET_COUNT; i++) + { + ready[i] = textureReady(mDetailTextures[i], boost); + } + + bool one_ready = false; + for (S32 i = 0; i < ASSET_COUNT; i++) + { + const bool current_ready = ready[i]; + one_ready = one_ready || current_ready; + if (!current_ready && strict) { - ready = FALSE; + return false; } - } - return ready; + } + return one_ready; } -BOOL LLTerrainMaterials::materialsReady(BOOL boost) +bool LLTerrainMaterials::materialsReady(bool boost, bool strict) { + bool ready[ASSET_COUNT]; + // *NOTE: Calls to materialReady may boost materials/textures. Do not early-return. + for (S32 i = 0; i < ASSET_COUNT; i++) + { + ready[i] = materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost, strict); + } + #if 1 static bool sRenderTerrainPBREnabled = gSavedSettings.get("RenderTerrainPBREnabled"); static LLCachedControl sRenderTerrainPBRForce(gSavedSettings, "RenderTerrainPBRForce", false); @@ -158,28 +174,31 @@ BOOL LLTerrainMaterials::materialsReady(BOOL boost) } if (defined) { - return TRUE; + return true; } } #endif - BOOL ready = TRUE; - for (S32 i = 0; i < ASSET_COUNT; i++) - { - if (!materialReady(mDetailMaterials[i], mMaterialTexturesSet[i], boost)) + bool one_ready = false; + for (S32 i = 0; i < ASSET_COUNT; i++) + { + const bool current_ready = ready[i]; + one_ready = one_ready || current_ready; + if (!current_ready && strict) { - ready = FALSE; + return false; } } - return ready; + return one_ready; } // Boost the texture loading priority // Return true when ready to use (i.e. texture is sufficiently loaded) // static -BOOL LLTerrainMaterials::textureReady(LLPointer& tex, BOOL boost) +bool LLTerrainMaterials::textureReady(LLPointer& tex, bool boost) { - llassert(tex.notNull()); + llassert(tex); + if (!tex) { return false; } if (tex->getDiscardLevel() < 0) { @@ -188,7 +207,7 @@ BOOL LLTerrainMaterials::textureReady(LLPointer& tex, BO tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail tex->addTextureStats(BASE_SIZE*BASE_SIZE); } - return FALSE; + return false; } if ((tex->getDiscardLevel() != 0 && (tex->getWidth() < BASE_SIZE || @@ -209,23 +228,23 @@ BOOL LLTerrainMaterials::textureReady(LLPointer& tex, BO tex->setMinDiscardLevel(ddiscard); tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority } - return FALSE; + return false; } if (tex->getComponents() == 0) { - return FALSE; + return false; } - return TRUE; + return true; } // Boost the loading priority of every known texture in the material -// Return true when ready to use (i.e. material and all textures within are sufficiently loaded) +// Return true when ready to use // static -BOOL LLTerrainMaterials::materialReady(LLPointer& mat, bool& textures_set, BOOL boost) +bool LLTerrainMaterials::materialReady(LLPointer &mat, bool &textures_set, bool boost, bool strict) { if (!mat || !mat->isLoaded()) { - return FALSE; + return false; } // Material is loaded, but textures may not be @@ -234,33 +253,39 @@ BOOL LLTerrainMaterials::materialReady(LLPointer& mat, bo // *NOTE: These can sometimes be set to to nullptr due to // updateTEMaterialTextures. For the sake of robustness, we emulate // that fetching behavior by setting textures of null IDs to nullptr. - mat->mBaseColorTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); - mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); + mat->mBaseColorTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); + mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); mat->mMetallicRoughnessTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); - mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); - textures_set = true; + mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); + textures_set = true; - return FALSE; + return false; } - if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && !textureReady(mat->mBaseColorTexture, boost)) - { - return FALSE; - } - if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && !textureReady(mat->mNormalTexture, boost)) - { - return FALSE; - } - if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && !textureReady(mat->mMetallicRoughnessTexture, boost)) + // *NOTE: Calls to textureReady may boost textures. Do not early-return. + bool ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; + ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = + mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].isNull() || textureReady(mat->mBaseColorTexture, boost); + ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = + mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].isNull() || textureReady(mat->mNormalTexture, boost); + ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = + mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].isNull() || + textureReady(mat->mMetallicRoughnessTexture, boost); + ready[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = + mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].isNull() || textureReady(mat->mEmissiveTexture, boost); + + if (strict) { - return FALSE; - } - if (mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && !textureReady(mat->mEmissiveTexture, boost)) - { - return FALSE; + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (!ready[i]) + { + return false; + } + } } - return TRUE; + return true; } @@ -427,16 +452,13 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, S32 st_data_size[ASSET_COUNT]; // for debugging const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; - // *TODO: Remove this as it is reduandant computation (first and foremost - // because getMaterialType() does something similar, but also... shouldn't - // the textures/materials already be loaded by now?) if (use_textures) { - if (!texturesReady()) { return FALSE; } + if (!texturesReady(true, true)) { return FALSE; } } else { - if (!materialsReady()) { return FALSE; } + if (!materialsReady(true, true)) { return FALSE; } } for (S32 i = 0; i < ASSET_COUNT; i++) diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index d59c0f95bb..73bfca6ed4 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -61,12 +61,16 @@ public: LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); - BOOL texturesReady(BOOL boost = FALSE); - BOOL materialsReady(BOOL boost = FALSE); + bool texturesReady(bool boost, bool strict); + // strict = true -> all materials must be sufficiently loaded + // strict = false -> at least one material must be loaded + bool materialsReady(bool boost, bool strict); protected: - static BOOL textureReady(LLPointer& tex, BOOL boost = FALSE); - static BOOL materialReady(LLPointer& mat, bool& textures_set, BOOL boost = FALSE); + static bool textureReady(LLPointer& tex, bool boost); + // strict = true -> all materials must be sufficiently loaded + // strict = false -> at least one material must be loaded + static bool materialReady(LLPointer& mat, bool& textures_set, bool boost, bool strict); LLPointer mDetailTextures[ASSET_COUNT]; LLPointer mDetailMaterials[ASSET_COUNT]; bool mMaterialTexturesSet[ASSET_COUNT]; @@ -116,8 +120,8 @@ public: BOOL getParamsReady() const { return mParamsReady; } protected: - static BOOL textureReady(LLPointer& tex, BOOL boost = FALSE); - static BOOL materialReady(LLPointer& mat, bool& textures_set, BOOL boost = FALSE); + static bool textureReady(LLPointer& tex, bool boost = false); + static bool materialReady(LLPointer& mat, bool& textures_set, bool boost = false); BOOL mParamsReady = FALSE; LLSurface *mSurfacep; -- cgit v1.2.3 From ae46dc068e47475c9a874c22047312152cd8fdab Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 8 Feb 2024 14:39:31 -0800 Subject: secondlife/viewer-issues#67: Fix Windows release build warning --- indra/newview/lldrawpoolterrain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 8844f1d7e4..2d198c5b4b 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -366,9 +366,11 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) LLVLComposition *compp = regionp->getComposition(); LLPointer (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; - constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT; +#ifdef SHOW_ASSERT + constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; llassert(shader_material_count == terrain_material_count); +#endif if (local_materials) { -- cgit v1.2.3 From d6048bfcb2442ca7ec278864b9827d74873efa3a Mon Sep 17 00:00:00 2001 From: cosmic-linden <111533034+cosmic-linden@users.noreply.github.com> Date: Fri, 9 Feb 2024 07:16:01 -0800 Subject: Put PBR material swatch behind feature flag (#775) * secondlife/viewer#771: Put PBR material swatch behind feature flag * secondlife/viewer#771: Make viewer respect PBRMaterialSwatchEnabled from SimulatorFeatures --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llgltfmaterialpreviewmgr.cpp | 8 +++++++- indra/newview/lltexturectrl.cpp | 21 +++++++++++---------- indra/newview/llviewerregion.cpp | 10 ++++++++++ 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6ec9a9acc5..1a614062d9 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13829,6 +13829,17 @@ Value 2 + UIPreviewMaterial + + Comment + Whether or not PBR material swatch is enabled + Persist + 1 + Type + Boolean + Value + 0 + UIResizeBarHeight Comment diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 53d9d7d0ba..901db87eed 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -543,7 +543,6 @@ void LLGLTFPreviewTexture::postRender(BOOL success) LLViewerDynamicTexture::postRender(success); } -// static LLPointer LLGLTFMaterialPreviewMgr::getPreview(LLPointer &material) { if (!material) @@ -551,6 +550,13 @@ LLPointer LLGLTFMaterialPreviewMgr::getPreview(LLPointer sUIPreviewMaterial(gSavedSettings, "UIPreviewMaterial", false); + if (!sUIPreviewMaterial) + { + fetch_texture_for_ui(material->mBaseColorTexture, material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); + return material->mBaseColorTexture; + } + if (!is_material_loaded_enough_for_ui(*material)) { return nullptr; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 0439b0b115..5415f9bd9a 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -680,6 +680,10 @@ void LLFloaterTexturePicker::draw() mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); } } + if (mGLTFPreview) + { + mGLTFPreview->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + } } else { @@ -735,7 +739,7 @@ void LLFloaterTexturePicker::draw() // If the floater is focused, don't apply its alpha to the texture (STORM-677). const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - LLViewerTexture* preview = nullptr; + LLViewerTexture* preview; if (mGLTFMaterial) { preview = mGLTFPreview.get(); @@ -743,15 +747,11 @@ void LLFloaterTexturePicker::draw() else { preview = mTexturep.get(); - if (mTexturep) - { - // Pump the priority - mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); - } } if( preview ) { + preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); if( preview->getComponents() == 4 ) { gl_rect_2d_checkerboard( interior, alpha ); @@ -2219,6 +2219,10 @@ void LLTextureCtrl::draw() mGLTFPreview = gGLTFMaterialPreviewMgr.getPreview(mGLTFMaterial); } } + if (mGLTFPreview) + { + mGLTFPreview->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + } preview = mGLTFPreview; } @@ -2257,10 +2261,7 @@ void LLTextureCtrl::draw() } gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha); - if (mTexturep) - { - mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); - } + preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); } else if (!mFallbackImage.isNull()) { diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index cea083e07d..5b51267cbe 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2459,6 +2459,16 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) } gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); + + if (mSimulatorFeatures.has("PBRMaterialSwatchEnabled")) + { + bool enabled = mSimulatorFeatures["PBRMaterialSwatchEnabled"]; + gSavedSettings.setBOOL("UIPreviewMaterial", enabled); + } + else + { + gSavedSettings.setBOOL("UIPreviewMaterial", false); + } } //this is called when the parent is not cacheable. -- cgit v1.2.3 From 4e5344ba76dd89373259e7286807ceba48bb5f82 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 9 Feb 2024 13:10:26 -0600 Subject: https://github.com/secondlife/jira-archive-internal/issues/70847 Fix for more inaccurate than usual alpha sorting (#781) --- indra/newview/app_settings/settings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1a614062d9..e7d947b85f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8699,7 +8699,7 @@ OctreeAlphaDistanceFactor Comment - Multiplier on alpha object distance for determining octree node size + Multiplier on alpha object distance for determining octree node size. First two parameters are currently unused. Third parameter is distance at which to perform detailed alpha sorting. Persist 1 Type @@ -8708,7 +8708,7 @@ 0.1 0.0 - 0.0 + 64.0 -- cgit v1.2.3 From 2cbf4a15df940d92d38003d302e61fda14e1dc51 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 9 Feb 2024 12:34:02 -0800 Subject: secondlife/viewer#773: Fix RenderTerrainPBREnabled requiring restart and respect simulator feature PBRTerrainEnabled --- indra/newview/llfloaterregioninfo.cpp | 32 ++++++++++++++++++++++++++++++-- indra/newview/llfloaterregioninfo.h | 3 +++ indra/newview/llviewermenu.cpp | 5 +---- indra/newview/llviewerregion.cpp | 18 ++++++++++++++---- indra/newview/llvlcomposition.cpp | 2 +- 5 files changed, 49 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 2c743d596e..8b335d57d7 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1441,6 +1441,11 @@ BOOL LLPanelRegionTerrainInfo::postBuild() mAskedTextureHeights = false; mConfirmedTextureHeights = false; + if (!mRegionChangedSlot.connected()) + { + mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLPanelRegionTerrainInfo::onRegionChanged,this)); + } + refresh(); return LLPanelRegionInfo::postBuild(); @@ -1449,8 +1454,7 @@ BOOL LLPanelRegionTerrainInfo::postBuild() // virtual void LLPanelRegionTerrainInfo::refresh() { - // For simplicity, require restart - static BOOL feature_pbr_terrain_enabled = gSavedSettings.getBOOL("RenderTerrainPBREnabled"); + static LLCachedControl feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); LLTextBox* texture_text = getChild("detail_texture_text"); if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); } @@ -1512,6 +1516,27 @@ void LLPanelRegionTerrainInfo::onSelectMaterialType() } } +void LLPanelRegionTerrainInfo::onRegionChanged() +{ + LLViewerRegion *region = gAgent.getRegion(); + if (!region) { return; } + + if (region->simulatorFeaturesReceived()) + { + onSimulatorFeaturesReceived(region->getRegionID(), region); + } + else + { + // See "RenderTerrainPBREnabled" in LLViewerRegion::setSimulatorFeatures + region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLPanelRegionTerrainInfo::onSimulatorFeaturesReceived,this,_1, _2)); + } +} + +void LLPanelRegionTerrainInfo::onSimulatorFeaturesReceived(const LLUUID& region_id, LLViewerRegion* regionp) +{ + refresh(); +} + // virtual bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { @@ -1568,6 +1593,9 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LL_DEBUGS() << "no region set" << LL_ENDL; getChild("region_text")->setValue(LLSD("")); } + + // Update visibility of terrain swatches, etc + refresh(); getChildView("download_raw_btn")->setEnabled(owner_or_god); getChildView("upload_raw_btn")->setEnabled(owner_or_god); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 91fd54fcf9..91e1f5b058 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -248,6 +248,8 @@ public: BOOL postBuild() override; + void onRegionChanged(); + void onSimulatorFeaturesReceived(const LLUUID& region_id, LLViewerRegion* regionp); bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region @@ -271,6 +273,7 @@ protected: private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; + boost::signals2::connection mRegionChangedSlot; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index da7b1131a3..981984db6a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9506,10 +9506,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); - if (gSavedSettings.get("RenderTerrainPBREnabled")) - { - view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); - } + view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); #ifdef TOGGLE_HACKED_GODLIKE_VIEWER view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode"); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 5b51267cbe..d887a579e4 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1610,8 +1610,8 @@ void LLViewerRegion::idleUpdate(F32 max_update_time) mLastUpdate = LLViewerOctreeEntryData::getCurrentFrame(); - static bool pbr_terrain_enabled = gSavedSettings.get("RenderTerrainPBREnabled"); - static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", FALSE); + static LLCachedControl pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); + static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", false); bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; @@ -1925,8 +1925,8 @@ void LLViewerRegion::forceUpdate() { constexpr F32 max_update_time = 0.f; - static bool pbr_terrain_enabled = gSavedSettings.get("RenderTerrainPBREnabled"); - static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", FALSE); + static LLCachedControl pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); + static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", false); bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; @@ -2460,6 +2460,16 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); + if (mSimulatorFeatures.has("PBRTerrainEnabled")) + { + bool enabled = mSimulatorFeatures["PBRTerrainEnabled"]; + gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled); + } + else + { + gSavedSettings.setBOOL("RenderTerrainPBREnabled", false); + } + if (mSimulatorFeatures.has("PBRMaterialSwatchEnabled")) { bool enabled = mSimulatorFeatures["PBRMaterialSwatchEnabled"]; diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index c092eb82f3..09b21e4e0a 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -159,7 +159,7 @@ bool LLTerrainMaterials::materialsReady(bool boost, bool strict) } #if 1 - static bool sRenderTerrainPBREnabled = gSavedSettings.get("RenderTerrainPBREnabled"); + static LLCachedControl sRenderTerrainPBREnabled(gSavedSettings, "RenderTerrainPBREnabled", false); static LLCachedControl sRenderTerrainPBRForce(gSavedSettings, "RenderTerrainPBRForce", false); if (sRenderTerrainPBREnabled && sRenderTerrainPBRForce) { -- cgit v1.2.3 From 7a9cdf2b52ca95c8e269e2bb4ed01379b76434d6 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Thu, 15 Feb 2024 09:38:29 -0800 Subject: #682 Do conservative updates on probes. --- indra/newview/llheroprobemanager.cpp | 22 +++++++++++++++++++++- indra/newview/llheroprobemanager.h | 1 + indra/newview/pipeline.cpp | 9 ++++++--- 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 2a81919856..1f050a5166 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -155,6 +155,25 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); + + // Collect the list of faces that need updating based upon the camera's rotation. + LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + + static LLVector3 cubeFaces[6] = { + LLVector3(1, 0, 0), + LLVector3(-1, 0, 0), + LLVector3(0, 1, 0), + LLVector3(0, -1, 0), + LLVector3(0, 0, 1), + LLVector3(0, 0, -1) + }; + + for (int i = 0; i < 6; i++) + { + bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; + + mFaceUpdateList[i] = shouldUpdate; + } } else { @@ -185,7 +204,8 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - updateProbeFace(mProbes[j], i, near_clip); + if (mFaceUpdateList[i]) + updateProbeFace(mProbes[j], i, near_clip); } } mRenderingMirror = false; diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 552c5dcaab..d2a319c500 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -134,6 +134,7 @@ private: bool mReset = false; bool mRenderingMirror = false; + std::map mFaceUpdateList; std::set> mHeroVOList; LLPointer mNearestHero; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9d90002eb9..180204b0ce 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -786,9 +786,12 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); - res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. - mRT = &mHeroProbeRT; - allocateScreenBuffer(res, res, samples); + if (RenderMirrors) + { + res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. + mRT = &mHeroProbeRT; + allocateScreenBuffer(res, res, samples); + } mRT = &mMainRT; gCubeSnapshot = FALSE; -- cgit v1.2.3 From 3e4e414011b032e64b5fd477f2c561fc2b4553f7 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 16 Feb 2024 09:49:45 -0800 Subject: secondlife/viewer-issues#72: Material preview shouldRender should return false if no render needed --- indra/newview/lldynamictexture.cpp | 2 ++ indra/newview/llgltfmaterialpreviewmgr.cpp | 20 +++++++++++++++++++- indra/newview/llgltfmaterialpreviewmgr.h | 8 ++------ 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index a66c3876fc..f8a6195bdd 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -118,6 +118,8 @@ BOOL LLViewerDynamicTexture::render() //----------------------------------------------------------------------------- void LLViewerDynamicTexture::preRender(BOOL clear_depth) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; + //use the bottom left corner mOrigin.set(0, 0); diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 901db87eed..36bd552c31 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -58,6 +58,15 @@ LLGLTFPreviewTexture::MaterialLoadLevels::MaterialLoadLevels() } } +bool LLGLTFPreviewTexture::MaterialLoadLevels::isFullyLoaded() +{ + for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (levels[i] != FULLY_LOADED) { return false; } + } + return true; +} + S32& LLGLTFPreviewTexture::MaterialLoadLevels::operator[](size_t i) { llassert(i >= 0 && i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT); @@ -187,17 +196,26 @@ LLPointer LLGLTFPreviewTexture::create(LLPointer create(LLPointer material); - BOOL needsRender() override { return mNeedsRender; } + BOOL needsRender() override; void preRender(BOOL clear_depth = TRUE) override; BOOL render() override; void postRender(BOOL success) override; @@ -50,15 +50,12 @@ public: S32 levels[LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT]; MaterialLoadLevels(); - + bool isFullyLoaded(); S32& operator[](size_t i); - const S32& operator[](size_t i) const; - // Less is better // Returns false if lhs is not strictly less or equal for all levels bool operator<(const MaterialLoadLevels& other) const; - // Less is better // Returns false if lhs is not strictly greater or equal for all levels bool operator>(const MaterialLoadLevels& other) const; @@ -66,7 +63,6 @@ public: private: LLPointer mGLTFMaterial; - bool mNeedsRender = true; bool mShouldRender = true; MaterialLoadLevels mBestLoad; }; -- cgit v1.2.3 From ab9ec50df9dda3ac52752d44b7d5529ed26db7bf Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 16 Feb 2024 12:52:50 -0800 Subject: secondlife/viewer-issues#72: Don't dirty depth in LLViewerDynamicTexture::updateAllInstances --- indra/newview/lldynamictexture.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index f8a6195bdd..24818241ab 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -221,7 +221,6 @@ BOOL LLViewerDynamicTexture::updateAllInstances() llassert(dynamicTexture->getFullHeight() <= LLPipeline::MAX_BAKE_WIDTH); glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = TRUE; gGL.color4f(1,1,1,1); dynamicTexture->setBoundTarget(&bake_target); -- cgit v1.2.3 From bbc7d63a79b9744acaff51315e5e9a9d7299bd12 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 20 Feb 2024 16:10:05 -0800 Subject: secondlife/viewer-issues#72: Clean up material preview when hidden or floater closed --- indra/newview/lltexturectrl.cpp | 15 +++++++++++++++ indra/newview/lltexturectrl.h | 2 ++ 2 files changed, 17 insertions(+) (limited to 'indra') diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 5415f9bd9a..d9001bc16a 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -538,6 +538,8 @@ void LLFloaterTexturePicker::onClose(bool app_quitting) } stopUsingPipette(); sLastPickerMode = mModeSelector->getValue().asInteger(); + // *NOTE: Vertex buffer for sphere preview is still cached + mGLTFPreview = nullptr; } // virtual @@ -1760,6 +1762,19 @@ void LLTextureCtrl::setFilterPermissionMasks(PermissionMask mask) setDnDFilterPermMask(mask); } +void LLTextureCtrl::onVisibilityChange(BOOL new_visibility) +{ + if (!new_visibility) + { + // *NOTE: Vertex buffer for sphere preview is still cached + mGLTFPreview = nullptr; + } + else + { + llassert(!mGLTFPreview); + } +} + void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 05ea185b1b..a19c8b6e3d 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -160,6 +160,8 @@ public: virtual void setVisible( BOOL visible ); virtual void setEnabled( BOOL enabled ); + void onVisibilityChange(BOOL new_visibility) override; + void setValid(BOOL valid); // LLUICtrl interface -- cgit v1.2.3 From 8cea28511448eb750561252f202f96ae815e37f8 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 20 Feb 2024 18:21:45 -0800 Subject: #682 Separate out the radiance gen. --- indra/newview/llheroprobemanager.cpp | 45 ++++++++++++------------------------ indra/newview/llheroprobemanager.h | 1 + 2 files changed, 16 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1f050a5166..929364be44 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -157,7 +157,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(0, 0, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -207,6 +207,7 @@ void LLHeroProbeManager::update() if (mFaceUpdateList[i]) updateProbeFace(mProbes[j], i, near_clip); } + generateRadiance(mProbes[j]); } mRenderingMirror = false; @@ -262,30 +263,6 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; - - // perform a gaussian blur on the super sampled render before downsampling - { - gGaussianProgram.bind(); - gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); - S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); - - // horizontal - gGaussianProgram.uniform2f(direction, 1.f, 0.f); - gGL.getTexUnit(diffuseChannel)->bind(screen_rt); - mRenderTarget.bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - mRenderTarget.flush(); - - // vertical - gGaussianProgram.uniform2f(direction, 0.f, 1.f); - gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); - screen_rt->bindTarget(); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - screen_rt->flush(); - gGaussianProgram.unbind(); - } S32 mips = log2((F32)mProbeResolution) + 0.5f; @@ -338,14 +315,22 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gGL.getTexUnit(diffuseChannel)->unbind(LLTexUnit::TT_TEXTURE); gReflectionMipProgram.unbind(); } +} - if (face == 5) +void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) +{ + S32 sourceIdx = mReflectionProbeCount; + + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. + sourceIdx += 1; { mMipChain[0].bindTarget(); static LLStaticHashedString sSourceIdx("sourceIdx"); { - //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) + + + // generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); @@ -354,10 +339,10 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD); gHeroRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_STRENGTH, mHeroProbeStrength); - + U32 res = mMipChain[0].getWidth(); - for (int i = 0; i < mMipChain.size(); ++i) + for (int i = 0; i < mMipChain.size() / 4; ++i) { LL_PROFILE_GPU_ZONE("probe radiance gen"); static LLStaticHashedString sMipLevel("mipLevel"); @@ -371,7 +356,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n gHeroRadianceGenProgram.uniform1f(sStrength, 1); for (int cf = 0; cf < 6; ++cf) - { // for each cube face + { // for each cube face LLCoordFrame frame; frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]); diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index d2a319c500..7cc7e3b144 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -104,6 +104,7 @@ private: // update the specified face of the specified probe void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); + void generateRadiance(LLReflectionMap *probe); // list of active reflection maps std::vector > mProbes; -- cgit v1.2.3 From e68735ad3a6da635a447eb9ed1981e5c360fd2f2 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 21 Feb 2024 11:51:46 -0800 Subject: #682 Add an update rate parameter to help throttle mirror updates. So far 4 seems like a good balance for performance and quality. 2 is great for quality, with 6 or 8 being for higher performance. Also bring back the gaussian filter - may end up adding the FXAA filter though instead. --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llheroprobemanager.cpp | 24 ++++++++++++++++++++++++ indra/newview/llviewerdisplay.cpp | 2 +- indra/newview/pipeline.cpp | 4 ++++ indra/newview/pipeline.h | 1 + 5 files changed, 41 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6ec9a9acc5..7e4058cc6e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10390,6 +10390,17 @@ Value 8 + RenderHeroProbeUpdateRate + + Comment + How many frames to wait for until it's time to render the probe. E.g., every other frame (1), every two frames (2), every three frames (3) etc. + Persist + 1 + Type + S32 + Value + 1 + RenderReflectionProbeVolumes Comment diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 929364be44..0d9efb860a 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -264,6 +264,30 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n LLRenderTarget *screen_rt = &gPipeline.mHeroProbeRT.screen; LLRenderTarget *depth_rt = &gPipeline.mHeroProbeRT.deferredScreen; + // perform a gaussian blur on the super sampled render before downsampling + { + gGaussianProgram.bind(); + gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); + S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE); + + // horizontal + gGaussianProgram.uniform2f(direction, 1.f, 0.f); + gGL.getTexUnit(diffuseChannel)->bind(screen_rt); + mRenderTarget.bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mRenderTarget.flush(); + + // vertical + gGaussianProgram.uniform2f(direction, 0.f, 1.f); + gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget); + screen_rt->bindTarget(); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + screen_rt->flush(); + gGaussianProgram.unbind(); + } + S32 mips = log2((F32)mProbeResolution) + 0.5f; gReflectionMipProgram.bind(); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index e6d9aed1a3..2a77146101 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -658,7 +658,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { // Render mirrors and associated hero probes before we render the rest of the scene. // This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it. - if (gPipeline.RenderMirrors && !gSnapshot) + if (gPipeline.RenderMirrors && !gSnapshot && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0)) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes"); gPipeline.mHeroProbeManager.update(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 180204b0ce..269b40a6c5 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -199,6 +199,7 @@ F32 LLPipeline::RenderScreenSpaceReflectionAdaptiveStepMultiplier; S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples; S32 LLPipeline::RenderBufferVisualization; bool LLPipeline::RenderMirrors; +S32 LLPipeline::RenderHeroProbeUpdateRate; LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); const U32 LLPipeline::MAX_BAKE_WIDTH = 512; @@ -559,6 +560,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionGlossySamples"); connectRefreshCachedSettingsSafe("RenderBufferVisualization"); connectRefreshCachedSettingsSafe("RenderMirrors"); + connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate"); gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } @@ -1071,6 +1073,8 @@ void LLPipeline::refreshCachedSettings() LLViewerShaderMgr::instance()->clearShaderCache(); LLViewerShaderMgr::instance()->setShaders(); } + RenderHeroProbeUpdateRate = gSavedSettings.getS32("RenderHeroProbeUpdateRate"); + sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e8c6da1473..2937b1fa1a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1056,6 +1056,7 @@ public: static S32 RenderScreenSpaceReflectionGlossySamples; static S32 RenderBufferVisualization; static bool RenderMirrors; + static S32 RenderHeroProbeUpdateRate; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.2.3 From 589910f445efa9690b543a37b9e2e14792a0e133 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 21 Feb 2024 12:53:10 -0800 Subject: secondlife/viewer-issues#72: Fix material preview affecting exposure on main screen --- indra/llrender/llrendertarget.cpp | 26 ++++++++ indra/llrender/llrendertarget.h | 3 + .../shaders/class1/deferred/exposureF.glsl | 6 +- indra/newview/llgltfmaterialpreviewmgr.cpp | 8 ++- indra/newview/llviewershadermgr.cpp | 17 ++++++ indra/newview/llviewershadermgr.h | 1 + indra/newview/pipeline.cpp | 71 ++++++++++++++-------- indra/newview/pipeline.h | 2 +- 8 files changed, 104 insertions(+), 30 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 88c48e5166..3dccb9c8fd 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -567,4 +567,30 @@ bool LLRenderTarget::isBoundInStack() const return cur == this; } +void LLRenderTarget::swapFBORefs(LLRenderTarget& other) +{ + // Must be initialized + llassert(mFBO); + llassert(other.mFBO); + // Must be unbound + // *NOTE: mPreviousRT can be non-null even if this target is unbound - presumably for debugging purposes? + llassert(sCurFBO != mFBO); + llassert(sCurFBO != other.mFBO); + llassert(!isBoundInStack()); + llassert(!other.isBoundInStack()); + + // Must be same type + llassert(sUseFBO == other.sUseFBO); + llassert(mResX == other.mResX); + llassert(mResY == other.mResY); + llassert(mInternalFormat == other.mInternalFormat); + llassert(mTex.size() == other.mTex.size()); + llassert(mDepth == other.mDepth); + llassert(mUseDepth == other.mUseDepth); + llassert(mGenerateMipMaps == other.mGenerateMipMaps); + llassert(mMipLevels == other.mMipLevels); + llassert(mUsage == other.mUsage); + + std::swap(mFBO, other.mFBO); +} diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 9fcea35e3d..da401572d1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -169,6 +169,9 @@ public: static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } + // *HACK + void swapFBORefs(LLRenderTarget& other); + protected: U32 mResX; U32 mResY; diff --git a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl index 9ac4ceb37e..eff7221ae7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl @@ -28,7 +28,9 @@ out vec4 frag_color; uniform sampler2D emissiveRect; +#ifdef USE_LAST_EXPOSURE uniform sampler2D exposureMap; +#endif uniform float dt; uniform vec2 noiseVec; @@ -51,10 +53,12 @@ void main() L /= max_L; L = pow(L, 2.0); float s = mix(dynamic_exposure_params.z, dynamic_exposure_params.y, L); - + +#ifdef USE_LAST_EXPOSURE float prev = texture(exposureMap, vec2(0.5,0.5)).r; s = mix(prev, s, min(dt*2.0*abs(prev-s), 0.04)); +#endif frag_color = max(vec4(s, s, s, dt), vec4(0.0)); } diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 36bd552c31..1c39f1ae7d 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -517,9 +517,12 @@ BOOL LLGLTFPreviewTexture::render() screen.flush(); } + // *HACK: Hide mExposureMap from generateExposure + gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure); + gPipeline.copyScreenSpaceReflections(&screen, &gPipeline.mSceneMap); gPipeline.generateLuminance(&screen, &gPipeline.mLuminanceMap); - gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap); + gPipeline.generateExposure(&gPipeline.mLuminanceMap, &gPipeline.mExposureMap, /*use_history = */ false); gPipeline.gammaCorrect(&screen, &gPipeline.mPostMap); LLVertexBuffer::unbind(); gPipeline.generateGlow(&gPipeline.mPostMap); @@ -527,6 +530,9 @@ BOOL LLGLTFPreviewTexture::render() gPipeline.renderDoF(&screen, &gPipeline.mPostMap); gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + // *HACK: Restore mExposureMap (it will be consumed by generateExposure next frame) + gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure); + // Final render gDeferredPostNoDoFProgram.bind(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 4eb934114d..354cc79036 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -196,6 +196,7 @@ LLGLSLShader gDeferredPostGammaCorrectProgram; LLGLSLShader gNoPostGammaCorrectProgram; LLGLSLShader gLegacyPostGammaCorrectProgram; LLGLSLShader gExposureProgram; +LLGLSLShader gExposureProgramNoFade; LLGLSLShader gLuminanceProgram; LLGLSLShader gFXAAProgram; LLGLSLShader gDeferredPostNoDoFProgram; @@ -980,6 +981,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredCoFProgram.unload(); gDeferredDoFCombineProgram.unload(); gExposureProgram.unload(); + gExposureProgramNoFade.unload(); gLuminanceProgram.unload(); gDeferredPostGammaCorrectProgram.unload(); gNoPostGammaCorrectProgram.unload(); @@ -2127,6 +2129,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gExposureProgram.mFeatures.isDeferred = true; gExposureProgram.mShaderFiles.clear(); gExposureProgram.clearPermutations(); + gExposureProgram.addPermutation("USE_LAST_EXPOSURE", "1"); gExposureProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); gExposureProgram.mShaderFiles.push_back(make_pair("deferred/exposureF.glsl", GL_FRAGMENT_SHADER)); gExposureProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; @@ -2134,6 +2137,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } + if (success) + { + gExposureProgramNoFade.mName = "Exposure (no fade)"; + gExposureProgramNoFade.mFeatures.hasSrgb = true; + gExposureProgramNoFade.mFeatures.isDeferred = true; + gExposureProgramNoFade.mShaderFiles.clear(); + gExposureProgramNoFade.clearPermutations(); + gExposureProgramNoFade.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gExposureProgramNoFade.mShaderFiles.push_back(make_pair("deferred/exposureF.glsl", GL_FRAGMENT_SHADER)); + gExposureProgramNoFade.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gExposureProgramNoFade.createShader(NULL, NULL); + llassert(success); + } + if (success) { gLuminanceProgram.mName = "Luminance"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 57fc66ce0d..2502be6bb1 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -249,6 +249,7 @@ extern LLGLSLShader gDeferredPostGammaCorrectProgram; extern LLGLSLShader gNoPostGammaCorrectProgram; extern LLGLSLShader gLegacyPostGammaCorrectProgram; extern LLGLSLShader gExposureProgram; +extern LLGLSLShader gExposureProgramNoFade; extern LLGLSLShader gLuminanceProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; extern LLGLSLShader gDeferredAvatarAlphaShadowProgram; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9d90002eb9..6ceaca731b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6772,11 +6772,12 @@ void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) } } -void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst) { +void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history) { // exposure sample { LL_PROFILE_GPU_ZONE("exposure sample"); + if (use_history) { // copy last frame's exposure into mLastExposure mLastExposure.bindTarget(); @@ -6793,51 +6794,67 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst) { LLGLDepthTest depth(GL_FALSE, GL_FALSE); - gExposureProgram.bind(); + LLGLSLShader* shader; + if (use_history) + { + shader = &gExposureProgram; + } + else + { + shader = &gExposureProgramNoFade; + } + + shader->bind(); - S32 channel = gExposureProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); if (channel > -1) { - mLuminanceMap.bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); + src->bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); } - channel = gExposureProgram.enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) + if (use_history) { - mLastExposure.bindTexture(0, channel); + channel = shader->enableTexture(LLShaderMgr::EXPOSURE_MAP); + if (channel > -1) + { + mLastExposure.bindTexture(0, channel); + } } static LLStaticHashedString dt("dt"); static LLStaticHashedString noiseVec("noiseVec"); static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); static LLCachedControl dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); - static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); + static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky(); + LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky(); - F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust); - F32 exp_min = 1.f; - F32 exp_max = 1.f; - - if (probe_ambiance > 0.f) - { - F32 hdr_scale = sqrtf(LLEnvironment::instance().getCurrentSky()->getGamma())*2.f; + F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust); + F32 exp_min = 1.f; + F32 exp_max = 1.f; - if (hdr_scale > 1.f) - { - exp_min = 1.f / hdr_scale; - exp_max = hdr_scale; - } - } - gExposureProgram.uniform1f(dt, gFrameIntervalSeconds); - gExposureProgram.uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); - gExposureProgram.uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max); + if (probe_ambiance > 0.f) + { + F32 hdr_scale = sqrtf(LLEnvironment::instance().getCurrentSky()->getGamma()) * 2.f; + + if (hdr_scale > 1.f) + { + exp_min = 1.f / hdr_scale; + exp_max = hdr_scale; + } + } + shader->uniform1f(dt, gFrameIntervalSeconds); + shader->uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); + shader->uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gGL.getTexUnit(channel)->unbind(mLastExposure.getUsage()); - gExposureProgram.unbind(); + if (use_history) + { + gGL.getTexUnit(channel)->unbind(mLastExposure.getUsage()); + } + shader->unbind(); dst->flush(); } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e8c6da1473..259dc3f9d0 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -154,7 +154,7 @@ public: void renderFinalize(); void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst); void generateLuminance(LLRenderTarget* src, LLRenderTarget* dst); - void generateExposure(LLRenderTarget* src, LLRenderTarget* dst); + void generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history = true); void gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst); void generateGlow(LLRenderTarget* src); void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst); -- cgit v1.2.3 From 97f049db3b396c7a12d723f3305084570866a475 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 21 Feb 2024 13:00:53 -0800 Subject: secondlife/viewer-issues#72: Fix clang warnings (virtual override) --- indra/newview/lltexturectrl.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index a19c8b6e3d..f193b0c083 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -148,28 +148,28 @@ public: // LLView interface - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, void *cargo_data, - EAcceptance *accept, - std::string& tooltip_msg); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) override; + BOOL handleHover(S32 x, S32 y, MASK mask) override; + BOOL handleUnicodeCharHere(llwchar uni_char) override; - virtual void draw(); - virtual void setVisible( BOOL visible ); - virtual void setEnabled( BOOL enabled ); + void draw() override; + void setVisible( BOOL visible ) override; + void setEnabled( BOOL enabled ) override; - void onVisibilityChange(BOOL new_visibility) override; + void onVisibilityChange(BOOL new_visibility) override; - void setValid(BOOL valid); + void setValid(BOOL valid); - // LLUICtrl interface - virtual void clear(); + // LLUICtrl interface + void clear() override; - // Takes a UUID, wraps get/setImageAssetID - virtual void setValue(const LLSD& value); - virtual LLSD getValue() const; + // Takes a UUID, wraps get/setImageAssetID + void setValue(const LLSD& value) override; + LLSD getValue() const override; // LLTextureCtrl interface void showPicker(BOOL take_focus); -- cgit v1.2.3 From fc7abe8cb9ef737cb1ad4431e30c42f08d6e8899 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 21 Feb 2024 16:06:11 -0800 Subject: secondlife/viewer-issues#72: More correct interpretation of swapFBORefs --- indra/llrender/llrendertarget.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 3dccb9c8fd..9cd7527d3e 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -593,4 +593,5 @@ void LLRenderTarget::swapFBORefs(LLRenderTarget& other) llassert(mUsage == other.mUsage); std::swap(mFBO, other.mFBO); + std::swap(mTex, other.mTex); } -- cgit v1.2.3 From f1e9d13b9918e44dda635a7085c4ffdd924172bd Mon Sep 17 00:00:00 2001 From: Brad Linden Date: Fri, 23 Feb 2024 14:11:31 -0800 Subject: Fixes for some shader compilation failures on mac. * conditional compilation should use #ifdef * layout keywords need to be lowercase --- .../app_settings/shaders/class1/interface/normaldebugG.glsl | 12 ++++++------ .../app_settings/shaders/class1/interface/normaldebugV.glsl | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl index ea04ce1cae..51d05cd507 100644 --- a/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugG.glsl @@ -32,15 +32,15 @@ out vec4 vertex_color; in vec4 normal_g[]; -#if HAS_ATTRIBUTE_TANGENT == 1 +#ifdef HAS_ATTRIBUTE_TANGENT in vec4 tangent_g[]; #endif -layout(TRIANGLES) in; -#if HAS_ATTRIBUTE_TANGENT == 1 -layout(LINE_STRIP, max_vertices = 12) out; +layout(triangles) in; +#ifdef HAS_ATTRIBUTE_TANGENT +layout(line_strip, max_vertices = 12) out; #else -layout(LINE_STRIP, max_vertices = 6) out; +layout(line_strip, max_vertices = 6) out; #endif void triangle_normal_debug(int i) @@ -55,7 +55,7 @@ void triangle_normal_debug(int i) EmitVertex(); EndPrimitive(); -#if HAS_ATTRIBUTE_TANGENT == 1 +#ifdef HAS_ATTRIBUTE_TANGENT // Tangent vec4 tangent_color = vec4(0.0, 1.0, 1.0, 1.0); gl_Position = gl_in[i].gl_Position; diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl index d1596b9d2a..b198bc2485 100644 --- a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl @@ -26,7 +26,7 @@ in vec3 position; in vec3 normal; out vec4 normal_g; -#if HAS_ATTRIBUTE_TANGENT == 1 +#ifdef HAS_ATTRIBUTE_TANGENT in vec4 tangent; out vec4 tangent_g; #endif @@ -67,7 +67,7 @@ void main() gl_Position = projection_matrix * world_pos; normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat); -#if HAS_ATTRIBUTE_TANGENT == 1 +#ifdef HAS_ATTRIBUTE_TANGENT tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat); #endif } -- cgit v1.2.3 From 5557254c93582166b2ab2ac4ec27b6f60e4b232e Mon Sep 17 00:00:00 2001 From: Brad Linden Date: Fri, 23 Feb 2024 14:21:52 -0800 Subject: Fix for deferred avatar eyes shader failing to link on Intel GPU. --- indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl index 83b0ba096c..43863dd37a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl @@ -26,6 +26,7 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; uniform mat4 modelview_projection_matrix; +uniform mat4 modelview_matrix; in vec3 position; in vec3 normal; @@ -35,10 +36,12 @@ in vec2 texcoord0; out vec3 vary_normal; out vec4 vertex_color; out vec2 vary_texcoord0; +out vec3 vary_position; void main() { //transform vertex + vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; -- cgit v1.2.3 From 320258729757e9ef14e9509c22eca1ce6a0da856 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 22:52:23 -0800 Subject: #682 Add a low priority path for conservative probe face updates. This will update the "low priority" faces at half of the the probe update rate. Useful for less planar reflection geometry. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++++++++++++------- indra/newview/llheroprobemanager.h | 11 +++++++---- indra/newview/llviewerobject.h | 1 + indra/newview/llvovolume.cpp | 7 ++++++- 4 files changed, 36 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 0d9efb860a..f350b28bf5 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && !vo->isDead()) + if (vo && (!vo->isDead() || vo != nullptr)) { if (vo->mDrawable.notNull()) { @@ -135,7 +135,7 @@ void LLHeroProbeManager::update() unregisterViewerObject(vo); } } - + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); @@ -205,7 +205,16 @@ void LLHeroProbeManager::update() for (U32 i = 0; i < 6; ++i) { if (mFaceUpdateList[i]) + { updateProbeFace(mProbes[j], i, near_clip); + } + else + { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + updateProbeFace(mProbes[j], i, near_clip); + mCurrentProbeUpdateFrame = 0; + } + } } generateRadiance(mProbes[j]); } @@ -213,6 +222,8 @@ void LLHeroProbeManager::update() gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; } + + mCurrentProbeUpdateFrame++; } // Do the reflection map update render passes. @@ -568,21 +579,25 @@ void LLHeroProbeManager::doOcclusion() } } -void LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) +bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { llassert(drawablep != nullptr); - if (mHeroVOList.find(drawablep) == mHeroVOList.end()) + if (std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep) == mHeroVOList.end()) { // Probe isn't in our list for consideration. Add it. - mHeroVOList.insert(drawablep); + mHeroVOList.push_back(drawablep); + return true; } + + return false; } void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { - if (mHeroVOList.find(drawablep) != mHeroVOList.end()) + std::vector::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); + if (found_itr != mHeroVOList.end()) { - mHeroVOList.erase(drawablep); + mHeroVOList.erase(found_itr); } } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 7cc7e3b144..b1907ef185 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -68,7 +68,7 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); - void registerViewerObject(LLVOVolume *drawablep); + bool registerViewerObject(LLVOVolume *drawablep); void unregisterViewerObject(LLVOVolume* drawablep); bool isMirrorPass() const { return mRenderingMirror; } @@ -107,7 +107,7 @@ private: void generateRadiance(LLReflectionMap *probe); // list of active reflection maps - std::vector > mProbes; + std::vector> mProbes; // handle to UBO U32 mUBO = 0; @@ -137,7 +137,10 @@ private: bool mRenderingMirror = false; std::map mFaceUpdateList; - std::set> mHeroVOList; - LLPointer mNearestHero; + U32 mCurrentProbeUpdateFrame = 0; + U32 mLowPriorityFaceThrottle = 2; + + std::vector mHeroVOList; + LLVOVolume* mNearestHero; }; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 80da7b2f73..0c4d958aed 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -944,6 +944,7 @@ public: // reflection probe state bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager LLPointer mReflectionProbe = nullptr; // reflection probe coupled to this viewer object. If not null, should be deregistered when this object is destroyed + bool mIsHeroProbe = false; // This is a special case for mirrors and other high resolution probes. // the amount of GPU time (in ms) it took to render this object according to LLPipeline::profileAvatar // -1.f if no profile data available diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 27d2e6af71..149abaf573 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -296,6 +296,11 @@ void LLVOVolume::markDead() { mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); } + + if (mIsHeroProbe) + { + gPipeline.mHeroProbeManager.unregisterViewerObject(this); + } } LLViewerObject::markDead(); @@ -4411,7 +4416,7 @@ void LLVOVolume::updateReflectionProbePtr() { // Geenz: This is a special case - what we want here is a hero probe. // What we want to do here is instantiate a hero probe from the hero probe manager. - gPipeline.mHeroProbeManager.registerViewerObject(this); + mIsHeroProbe = gPipeline.mHeroProbeManager.registerViewerObject(this); } } else if (mReflectionProbe.notNull() || getReflectionProbeIsMirror()) -- cgit v1.2.3 From 2ba5449b8b888b64ed87ef801426f7eab6e0be95 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Sun, 25 Feb 2024 23:38:11 -0800 Subject: #889 Start removing mDrawable references. These may be null. --- indra/newview/llheroprobemanager.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index f350b28bf5..feb81394cf 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -116,18 +116,11 @@ void LLHeroProbeManager::update() { if (vo && (!vo->isDead() || vo != nullptr)) { - if (vo->mDrawable.notNull()) + float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); + if (distance < last_distance) { - if (vo->mDrawable->mDistanceWRTCamera < last_distance) - { - mNearestHero = vo; - last_distance = vo->mDrawable->mDistanceWRTCamera; - } - } - else - { - // Valid drawables only please. Unregister this one. - unregisterViewerObject(vo); + mNearestHero = vo; + last_distance = distance; } } else @@ -136,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) + if (mNearestHero != nullptr && !mNearestHero->isDead()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - face_normal *= mNearestHero->mDrawable->getXform()->getWorldRotation(); + face_normal *= mNearestHero->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -210,7 +203,8 @@ void LLHeroProbeManager::update() } else { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) { + if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) + { updateProbeFace(mProbes[j], i, near_clip); mCurrentProbeUpdateFrame = 0; } @@ -352,6 +346,9 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 n } } +// Separate out radiance generation as a separate stage. +// This is to better enable independent control over how we generate radiance vs. having it coupled with processing the final face of the probe. +// Useful when we may not always be rendering a full set of faces of the probe. void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) { S32 sourceIdx = mReflectionProbeCount; -- cgit v1.2.3 From 1b8523a7b6293db89b16ca8e08330969cf1d9166 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 00:30:44 -0800 Subject: #890 Make sure we're doing the correct distance check. #682 Improve the conservative update functionality for mirror faces. Make it attenuate depending on how much the camera is facing that specific cubemap face. --- indra/newview/llheroprobemanager.cpp | 29 ++++++++++++----------------- indra/newview/llheroprobemanager.h | 2 +- 2 files changed, 13 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index feb81394cf..3adf460432 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -114,7 +114,7 @@ void LLHeroProbeManager::update() for (auto vo : mHeroVOList) { - if (vo && (!vo->isDead() || vo != nullptr)) + if (vo && !vo->isDead() && vo->mDrawable.notNull()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); if (distance < last_distance) @@ -129,12 +129,12 @@ void LLHeroProbeManager::update() } } - if (mNearestHero != nullptr && !mNearestHero->isDead()) + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - - face_normal *= mNearestHero->getWorldRotation(); + + face_normal *= mNearestHero->mDrawable->getWorldRotation(); face_normal.normalize(); LLVector3 offset = camera_pos - hero_pos; @@ -150,7 +150,7 @@ void LLHeroProbeManager::update() probe_pos.load3(point.mV); // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(-1, -1, -1) * LLViewerCamera::instance().getQuaternion(); + LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -163,9 +163,11 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { - bool shouldUpdate = (cam_direction * cubeFaces[i]) > 0; - - mFaceUpdateList[i] = shouldUpdate; + float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; + + int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + + mFaceUpdateList[i] = updateRate; } } else @@ -197,17 +199,10 @@ void LLHeroProbeManager::update() { for (U32 i = 0; i < 6; ++i) { - if (mFaceUpdateList[i]) + if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) { updateProbeFace(mProbes[j], i, near_clip); - } - else - { - if (mLowPriorityFaceThrottle > 0 && mCurrentProbeUpdateFrame % mLowPriorityFaceThrottle == 0) - { - updateProbeFace(mProbes[j], i, near_clip); - mCurrentProbeUpdateFrame = 0; - } + mCurrentProbeUpdateFrame = 0; } } generateRadiance(mProbes[j]); diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index b1907ef185..038a8fd45a 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -135,7 +135,7 @@ private: bool mReset = false; bool mRenderingMirror = false; - std::map mFaceUpdateList; + std::map mFaceUpdateList; U32 mCurrentProbeUpdateFrame = 0; U32 mLowPriorityFaceThrottle = 2; -- cgit v1.2.3 From 8c79297a8957fec13fadd2a2932b4b03b148d5a5 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 01:21:41 -0800 Subject: #682 Further tweak the conservative update mechanism. --- indra/newview/app_settings/settings.xml | 13 ++++++++++++- indra/newview/llheroprobemanager.cpp | 7 ++++++- indra/newview/llheroprobemanager.h | 1 - indra/newview/pipeline.cpp | 3 +++ indra/newview/pipeline.h | 1 + 5 files changed, 22 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6a84f64030..e707e1eb5e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10399,7 +10399,18 @@ Type S32 Value - 1 + 2 + + RenderHeroProbeConservativeUpdateMultiplier + + Comment + How many probe updates to wait until it's time to update faces that are not directly facing the camera. Acts as a multiplier. E.g., frames to the periphery of the camera updating once every 3 updates, vs ones directly facing the camera updating every update. + Persist + 1 + Type + S32 + Value + 16 RenderReflectionProbeVolumes diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 3adf460432..a00b6d6b5d 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -165,7 +165,12 @@ void LLHeroProbeManager::update() { float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; - int updateRate = fmaxf(1, (1 - shouldUpdate) * 8); + int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); + + // Chances are this is a face that's non-visible to the camera when it's being reflected. + // Set it to 0. It will be skipped below. + if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier) + updateRate = 0; mFaceUpdateList[i] = updateRate; } diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 038a8fd45a..e430cae203 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -138,7 +138,6 @@ private: std::map mFaceUpdateList; U32 mCurrentProbeUpdateFrame = 0; - U32 mLowPriorityFaceThrottle = 2; std::vector mHeroVOList; LLVOVolume* mNearestHero; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e3e2da3b30..94ec5c0817 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -200,6 +200,7 @@ S32 LLPipeline::RenderScreenSpaceReflectionGlossySamples; S32 LLPipeline::RenderBufferVisualization; bool LLPipeline::RenderMirrors; S32 LLPipeline::RenderHeroProbeUpdateRate; +S32 LLPipeline::RenderHeroProbeConservativeUpdateMultiplier; LLTrace::EventStatHandle LLPipeline::sStatBatchSize("renderbatchsize"); const U32 LLPipeline::MAX_BAKE_WIDTH = 512; @@ -561,6 +562,7 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderBufferVisualization"); connectRefreshCachedSettingsSafe("RenderMirrors"); connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate"); + connectRefreshCachedSettingsSafe("RenderHeroProbeConservativeUpdateMultiplier"); gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } @@ -1074,6 +1076,7 @@ void LLPipeline::refreshCachedSettings() LLViewerShaderMgr::instance()->setShaders(); } RenderHeroProbeUpdateRate = gSavedSettings.getS32("RenderHeroProbeUpdateRate"); + RenderHeroProbeConservativeUpdateMultiplier = gSavedSettings.getS32("RenderHeroProbeConservativeUpdateMultiplier"); sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); RenderSpotLight = nullptr; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index fe00c52e6d..817750b4a1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1057,6 +1057,7 @@ public: static S32 RenderBufferVisualization; static bool RenderMirrors; static S32 RenderHeroProbeUpdateRate; + static S32 RenderHeroProbeConservativeUpdateMultiplier; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); -- cgit v1.2.3 From 4ed5b59a601cfc58c3d5a5d4c1b56d4cdc73be2c Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 01:34:40 -0800 Subject: Make sure to check if we're a hero probe before attempting to register with the hero probe manager. If we're already in the list, this will return false. --- indra/newview/llvovolume.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 149abaf573..d7af7a42d1 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4416,7 +4416,9 @@ void LLVOVolume::updateReflectionProbePtr() { // Geenz: This is a special case - what we want here is a hero probe. // What we want to do here is instantiate a hero probe from the hero probe manager. - mIsHeroProbe = gPipeline.mHeroProbeManager.registerViewerObject(this); + + if (!mIsHeroProbe) + mIsHeroProbe = gPipeline.mHeroProbeManager.registerViewerObject(this); } } else if (mReflectionProbe.notNull() || getReflectionProbeIsMirror()) -- cgit v1.2.3 From b3283036af886de56f45c731ab21e2b16383a770 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 26 Feb 2024 04:02:09 -0800 Subject: #681 Start adding blending boilerplate. --- .../shaders/class3/deferred/reflectionProbeF.glsl | 71 +++++++++++++++++++++- .../shaders/class3/deferred/softenLightF.glsl | 10 --- indra/newview/llheroprobemanager.cpp | 37 +++++++++-- indra/newview/llreflectionmapmanager.cpp | 1 - 4 files changed, 100 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 4f6e01764a..14d9cf798f 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -686,17 +686,82 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit) #if defined(HERO_PROBES) uniform vec4 clipPlane; -uniform samplerCubeArray heroProbes; + +uniform samplerCubeArray heroProbes; + +layout (std140) uniform HeroProbeData +{ + mat4 heroBox[1]; + vec4 heroSphere[1]; + uint heroShape[1]; + int heroMipCount; + int heroProbeCount; +}; + +vec3 boxIntersectHero(vec3 origin, vec3 dir, int i, out float d, float scale) +{ + // Intersection with OBB convert to unit box space + // Transform in local unit parallax cube space (scaled and rotated) + mat4 clipToLocal = heroBox[i]; + + vec3 RayLS = mat3(clipToLocal) * dir; + vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; + + d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z)); + + vec3 Unitary = vec3(scale); + vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS; + vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; + vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); + float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); + + // Use Distance in CS directly to recover intersection + vec3 IntersectPositionCS = origin + dir * Distance; + + return IntersectPositionCS; +} + +float sphereWeightHero(vec3 pos, vec3 dir, vec3 origin, float r, out float dw) +{ + float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) + vec3 delta = pos.xyz - origin; + float d2 = max(length(delta), 0.001); + + float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001); + float w = 1.0 / d2; + + dw = w * atten * max(r, 1.0)*4; + + w *= atten; + + return w; +} void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) { float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; - if (clipDist > 0.0 && clipDist < 0.1 && glossiness > 0.8) + float w = 0; + float dw = 0; + if (heroShape[0] < 1) + { + float d = 0; + boxIntersectHero(pos, norm, 0, d, 1.0); + + w = max(d, 0.001); + } + else + { + float r = heroSphere[0].w; + //v = sphereIntersect(pos, norm, heroSphere[0].xyz, 4096.0*4096.0); + + w = sphereWeightHero(pos, norm, heroSphere[0].xyz, r, dw); + } + { vec3 refnormpersp = reflect(pos.xyz, norm.xyz); if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) { - glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*10).xyz; + glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz * w; } } } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index cc6e16c64f..2f90249169 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -32,16 +32,6 @@ uniform sampler2D specularRect; uniform sampler2D normalMap; uniform sampler2D emissiveRect; // PBR linear packed Occlusion, Roughness, Metal. See: pbropaqueF.glsl -uniform samplerCubeArray heroProbes; - -#if defined(HERO_PROBES) -layout (std140) uniform HeroProbeData -{ - vec4 heroPosition[1]; - int heroProbeCount; -}; -#endif - const float M_PI = 3.14159265; #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO) diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index a00b6d6b5d..ee993c6ba1 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -417,7 +417,7 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) void LLHeroProbeManager::updateUniforms() { - if (!LLPipeline::sReflectionProbesEnabled) + if (!gPipeline.RenderMirrors) { return; } @@ -426,8 +426,11 @@ void LLHeroProbeManager::updateUniforms() struct HeroProbeData { - LLVector4 heroPosition[1]; - GLint heroProbeCount = 1; + LLMatrix4 heroBox[1]; + LLVector4 heroSphere[1]; + GLint heroShape[1]; + GLint heroMipCount; + GLint heroProbeCount; }; HeroProbeData hpd; @@ -437,8 +440,32 @@ void LLHeroProbeManager::updateUniforms() LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); hpd.heroProbeCount = 1; - modelview.affineTransform(mProbes[0]->mOrigin, oa); - hpd.heroPosition[0].set(oa.getF32ptr()); + + if (mNearestHero != nullptr) + { + mProbes[0]->mViewerObject = mNearestHero; + if (mNearestHero->getReflectionProbeIsBox()) + { + LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); + mProbes[0]->mRadius = s.magVec(); + } + else + { + mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f; + } + + modelview.affineTransform(mProbes[0]->mOrigin, oa); + hpd.heroShape[0] = 0; + if (!mProbes[0]->getBox(hpd.heroBox[0])) + { + hpd.heroShape[0] = 1; + } + + hpd.heroSphere[0].set(oa.getF32ptr()); + hpd.heroSphere[0].mV[3] = mProbes[0]->mRadius; + } + + hpd.heroMipCount = mMipChain.size(); //copy rpd into uniform buffer object if (mUBO == 0) diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 8506886409..3144260905 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -1016,7 +1016,6 @@ void LLReflectionMapManager::updateUniforms() { refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f; } - } modelview.affineTransform(refmap->mOrigin, oa); rpd.refSphere[count].set(oa.getF32ptr()); -- cgit v1.2.3 From 95e1badaa4566bea41479623bf5b5112f7184cd5 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 26 Feb 2024 13:46:39 -0600 Subject: https://github.com/secondlife/jira-archive-internal/issues/71006 Fix for probes going off the rails -- sanity clamp sky glow (#893) --- .../app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index a1da4b1f9a..8769cc0239 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -98,7 +98,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) haze_glow *= glow.x; // higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = pow(haze_glow, glow.z); + haze_glow = clamp(pow(haze_glow, glow.z), -10, 10); // glow.z should be negative, so we're doing a sort of (1 / "angle") function // add "minimum anti-solar illumination" -- cgit v1.2.3 From 8b374f733360650c95d3ec021f1ec351e8b5dc21 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 27 Feb 2024 13:18:03 -0800 Subject: #681 Make our sampling code for probes a good deal more generic to make sure all probes can benefit from the same blending functions. --- .../shaders/class3/deferred/reflectionProbeF.glsl | 49 ++++++---------------- 1 file changed, 13 insertions(+), 36 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 14d9cf798f..7df9bdba5d 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -366,11 +366,11 @@ return texCUBE(envMap, ReflDirectionWS); // i - probe index in refBox/refSphere // d - distance to nearest wall in clip space // scale - scale of box, default 1.0 -vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale) +vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d, float scale) { // Intersection with OBB convert to unit box space // Transform in local unit parallax cube space (scaled and rotated) - mat4 clipToLocal = refBox[i]; + mat4 clipToLocal = i; vec3 RayLS = mat3(clipToLocal) * dir; vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; @@ -389,7 +389,7 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d, float scale) return IntersectPositionCS; } -vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d) +vec3 boxIntersect(vec3 origin, vec3 dir, mat4 i, out float d) { return boxIntersect(origin, dir, i, d, 1.0); } @@ -444,9 +444,9 @@ void boxIntersectionDebug( in vec3 ro, in vec3 p, vec3 boxSize, inout vec4 col) } -void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col) +void boxIntersectDebug(vec3 origin, vec3 pos, mat4 i, inout vec4 col) { - mat4 clipToLocal = refBox[i]; + mat4 clipToLocal = i; // transform into unit cube space origin = (clipToLocal * vec4(origin, 1.0)).xyz; @@ -463,7 +463,7 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col) // r - radius of probe influence volume // i - index of probe in refSphere // dw - distance weight -float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw) +float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, vec4 i, out float dw) { float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) vec3 delta = pos.xyz - origin; @@ -472,7 +472,7 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, int i, out float dw float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001); float w = 1.0 / d2; - w *= refParams[i].z; + w *= i.z; dw = w * atten * max(r, 1.0)*4; @@ -498,7 +498,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, if (refIndex[i].w < 0) { // box probe float d = 0; - v = boxIntersect(pos, dir, i, d); + v = boxIntersect(pos, dir, refBox[i], d); w = max(d, 0.001); } @@ -512,7 +512,7 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres rr); - w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw); + w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw); } v -= c; @@ -538,7 +538,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int if (refIndex[i].w < 0) { float d = 0.0; - v = boxIntersect(pos, dir, i, d, 3.0); + v = boxIntersect(pos, dir, refBox[i], d, 3.0); w = max(d, 0.001); } else @@ -552,7 +552,7 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres rr); - w = sphereWeight(pos, dir, refSphere[i].xyz, r, i, dw); + w = sphereWeight(pos, dir, refSphere[i].xyz, r, refParams[i], dw); } v -= c; @@ -698,29 +698,6 @@ layout (std140) uniform HeroProbeData int heroProbeCount; }; -vec3 boxIntersectHero(vec3 origin, vec3 dir, int i, out float d, float scale) -{ - // Intersection with OBB convert to unit box space - // Transform in local unit parallax cube space (scaled and rotated) - mat4 clipToLocal = heroBox[i]; - - vec3 RayLS = mat3(clipToLocal) * dir; - vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz; - - d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z)); - - vec3 Unitary = vec3(scale); - vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS; - vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS; - vec3 FurthestPlane = max(FirstPlaneIntersect, SecondPlaneIntersect); - float Distance = min(FurthestPlane.x, min(FurthestPlane.y, FurthestPlane.z)); - - // Use Distance in CS directly to recover intersection - vec3 IntersectPositionCS = origin + dir * Distance; - - return IntersectPositionCS; -} - float sphereWeightHero(vec3 pos, vec3 dir, vec3 origin, float r, out float dw) { float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) @@ -745,7 +722,7 @@ void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) if (heroShape[0] < 1) { float d = 0; - boxIntersectHero(pos, norm, 0, d, 1.0); + boxIntersect(pos, norm, heroBox[0], d, 1.0); w = max(d, 0.001); } @@ -844,7 +821,7 @@ void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) { if (refIndex[i].w < 0) { - boxIntersectDebug(origin, pos, i, col); + boxIntersectDebug(origin, pos, refBox[i], col); } else { -- cgit v1.2.3 From 47cd3cb0ad03c91f118fd20fea8d8924759fd2b7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 27 Feb 2024 13:46:49 -0800 Subject: #681 More generalization of falloff. --- .../shaders/class3/deferred/reflectionProbeF.glsl | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 7df9bdba5d..257299258e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -698,22 +698,6 @@ layout (std140) uniform HeroProbeData int heroProbeCount; }; -float sphereWeightHero(vec3 pos, vec3 dir, vec3 origin, float r, out float dw) -{ - float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down) - vec3 delta = pos.xyz - origin; - float d2 = max(length(delta), 0.001); - - float atten = 1.0 - max(d2 - r1, 0.0) / max((r - r1), 0.001); - float w = 1.0 / d2; - - dw = w * atten * max(r, 1.0)*4; - - w *= atten; - - return w; -} - void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) { float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; @@ -729,16 +713,15 @@ void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) else { float r = heroSphere[0].w; - //v = sphereIntersect(pos, norm, heroSphere[0].xyz, 4096.0*4096.0); - w = sphereWeightHero(pos, norm, heroSphere[0].xyz, r, dw); + w = sphereWeight(pos, norm, heroSphere[0].xyz, r, vec4(1), dw); } { vec3 refnormpersp = reflect(pos.xyz, norm.xyz); if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) { - glossenv = textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz * w; + glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w); } } } -- cgit v1.2.3 From d79498e25991e425510643ecd1303a5675c5fbf6 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 28 Feb 2024 15:02:18 -0800 Subject: secondlife/viewer#712: More intuitive selection of PBR vs texture terrain, and update dropdown to match --- indra/newview/llfloaterregioninfo.cpp | 183 +++++++++++++++++++--------------- indra/newview/llfloaterregioninfo.h | 2 +- indra/newview/llvlcomposition.cpp | 14 ++- indra/newview/llvlcomposition.h | 2 +- 4 files changed, 108 insertions(+), 93 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 8b335d57d7..8e2fb24923 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -340,7 +340,6 @@ void LLFloaterRegionInfo::onRegionChanged() } } -// static void LLFloaterRegionInfo::requestRegionInfo() { LLTabContainer* tab = findChild("region_panels"); @@ -1327,9 +1326,6 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { - // *TODO: Don't early-exit in PBR material terrain editing mode, and - // instead do some reasonable checks that the PBR material is compatible - // with the terrain rendering pipeline. Err on the side of permissive. LLComboBox* material_type_ctrl = getChild("terrain_material_type"); if (material_type_ctrl) { @@ -1446,54 +1442,24 @@ BOOL LLPanelRegionTerrainInfo::postBuild() mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLPanelRegionTerrainInfo::onRegionChanged,this)); } - refresh(); - return LLPanelRegionInfo::postBuild(); } -// virtual -void LLPanelRegionTerrainInfo::refresh() +void LLPanelRegionTerrainInfo::onSelectMaterialType() { - static LLCachedControl feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); - - LLTextBox* texture_text = getChild("detail_texture_text"); - if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); } - - LLComboBox* material_type_ctrl = getChild("terrain_material_type"); - if (material_type_ctrl) - { - material_type_ctrl->setVisible(feature_pbr_terrain_enabled); - - bool has_material_assets = false; - - std::string buffer; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - LLTextureCtrl* material_ctrl = getChild(buffer); - if (material_ctrl && material_ctrl->getImageAssetID().notNull()) - { - has_material_assets = true; - break; - } - } - - TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); - - if (!feature_pbr_terrain_enabled) { material_type = TerrainMaterialType::TEXTURE; } - - const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; - material_type_ctrl->setEnabled(feature_pbr_terrain_enabled && !(is_material_selected && has_material_assets)); - } + updateForMaterialType(); + onChangeAnything(); } -void LLPanelRegionTerrainInfo::onSelectMaterialType() +void LLPanelRegionTerrainInfo::updateForMaterialType() { LLComboBox* material_type_ctrl = getChild("terrain_material_type"); if (!material_type_ctrl) { return; } const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); const bool show_texture_controls = material_type == TerrainMaterialType::TEXTURE; const bool show_material_controls = material_type == TerrainMaterialType::PBR_MATERIAL; + + // Toggle visibility of correct swatches std::string buffer; LLTextureCtrl* texture_ctrl; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) @@ -1554,31 +1520,98 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LLVLComposition* compp = region->getComposition(); - // Are these 4 texture IDs or 4 material IDs? Who knows! Let's set the IDs on both pickers for now. + static LLCachedControl feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); + + const bool textures_ready = compp->texturesReady(false, false); + const bool materials_ready = feature_pbr_terrain_enabled && compp->materialsReady(false, false); + + LLTextBox* texture_text = getChild("detail_texture_text"); + if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); } + + bool set_texture_swatches; + bool set_material_swatches; + bool clear_texture_swatches; + bool clear_material_swatches; + LLTerrainMaterials::Type material_type; + if (!textures_ready && !materials_ready) + { + // Are these 4 texture IDs or 4 material IDs? Who knows! Let's set + // the IDs on both pickers for now. + material_type = LLTerrainMaterials::Type::TEXTURE; + set_texture_swatches = true; + set_material_swatches = true; + clear_texture_swatches = false; + clear_material_swatches = false; + } + else + { + material_type = compp->getMaterialType(); + set_texture_swatches = material_type == LLTerrainMaterials::Type::TEXTURE; + set_material_swatches = !set_texture_swatches; + clear_texture_swatches = !set_texture_swatches; + clear_material_swatches = !set_material_swatches; + } + + LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + if (material_type_ctrl) { material_type_ctrl->setCurrentByIndex(S32(material_type)); } + updateForMaterialType(); + LLTextureCtrl* asset_ctrl; std::string buffer; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("texture_detail_%d", i); - asset_ctrl = getChild(buffer); - if(asset_ctrl) - { - LL_DEBUGS() << "Detail Texture " << i << ": " - << compp->getDetailAssetID(i) << LL_ENDL; - LLUUID tmp_id(compp->getDetailAssetID(i)); - asset_ctrl->setImageAssetID(tmp_id); - } - } - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); - if(asset_ctrl) - { - LLUUID tmp_id(compp->getDetailAssetID(i)); - asset_ctrl->setImageAssetID(tmp_id); - } - } + if (set_texture_swatches) + { + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("texture_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl) + { + LL_DEBUGS() << "Detail Texture " << i << ": " + << compp->getDetailAssetID(i) << LL_ENDL; + LLUUID tmp_id(compp->getDetailAssetID(i)); + asset_ctrl->setImageAssetID(tmp_id); + } + } + } + if (set_material_swatches) + { + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl) + { + LL_DEBUGS() << "Detail Material " << i << ": " + << compp->getDetailAssetID(i) << LL_ENDL; + LLUUID tmp_id(compp->getDetailAssetID(i)); + asset_ctrl->setImageAssetID(tmp_id); + } + } + } + if (clear_texture_swatches) + { + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("texture_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl) + { + asset_ctrl->setImageAssetID(LLUUID::null); + } + } + } + if (clear_material_swatches) + { + for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + asset_ctrl = getChild(buffer); + if(asset_ctrl) + { + asset_ctrl->setImageAssetID(LLUUID::null); + } + } + } for(S32 i = 0; i < CORNER_COUNT; ++i) { @@ -1650,29 +1683,13 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() std::string id_str; LLMessageSystem* msg = gMessageSystem; - // Use material IDs instead of texture IDs if all material IDs are set, AND the mode is set to PBR materials. - S32 materials_used = 0; + // Send either material IDs instead of texture IDs depending on + // terrain_material_type - they both occupy the same slot. LLComboBox* material_type_ctrl = getChild("terrain_material_type"); - if (material_type_ctrl) - { - const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); - const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; - if (is_material_selected) - { - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); - if(asset_ctrl && asset_ctrl->getImageAssetID().notNull()) - { - ++materials_used; - } - } - } - } + const TerrainMaterialType material_type = material_type_ctrl ? material_type_from_index(material_type_ctrl->getCurrentIndex()) : TerrainMaterialType::TEXTURE; for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - if (materials_used == TERRAIN_TEXTURE_COUNT) + if (material_type == TerrainMaterialType::PBR_MATERIAL) { buffer = llformat("material_detail_%d", i); asset_ctrl = getChild(buffer); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 91e1f5b058..abd8e21503 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -258,8 +258,8 @@ public: //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button - void refresh() override; void onSelectMaterialType(); + void updateForMaterialType(); static void onClickDownloadRaw(void*); static void onClickUploadRaw(void*); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 09b21e4e0a..9c64381a07 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -91,10 +91,10 @@ BOOL LLTerrainMaterials::generateMaterials() LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset) { llassert(mDetailTextures[asset] && mDetailMaterials[asset]); - // *HACK: Assume both the the material and texture were fetched in the same - // way using the same UUID. However, we may not know at this point which - // one will load. - return mDetailTextures[asset]->getID(); + // Assume both the the material and texture were fetched in the same way + // using the same UUID. However, we may not know at this point which one + // will load. + return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null; } LLPointer fetch_terrain_texture(const LLUUID& id) @@ -133,7 +133,7 @@ bool LLTerrainMaterials::texturesReady(bool boost, bool strict) // *NOTE: Calls to textureReady may boost textures. Do not early-return. for (S32 i = 0; i < ASSET_COUNT; i++) { - ready[i] = textureReady(mDetailTextures[i], boost); + ready[i] = mDetailTextures[i].notNull() && textureReady(mDetailTextures[i], boost); } bool one_ready = false; @@ -250,6 +250,7 @@ bool LLTerrainMaterials::materialReady(LLPointer &mat, bo // Material is loaded, but textures may not be if (!textures_set) { + textures_set = true; // *NOTE: These can sometimes be set to to nullptr due to // updateTEMaterialTextures. For the sake of robustness, we emulate // that fetching behavior by setting textures of null IDs to nullptr. @@ -257,9 +258,6 @@ bool LLTerrainMaterials::materialReady(LLPointer &mat, bo mat->mNormalTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); mat->mMetallicRoughnessTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); mat->mEmissiveTexture = fetch_terrain_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]); - textures_set = true; - - return false; } // *NOTE: Calls to textureReady may boost textures. Do not early-return. diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 73bfca6ed4..dea776849a 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -58,7 +58,7 @@ public: BOOL generateMaterials(); - LLUUID getDetailAssetID(S32 asset); + virtual LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); bool texturesReady(bool boost, bool strict); -- cgit v1.2.3 From 0cb9e7f7e5bd02ded8b9f2bd9cd6c57a70187dcc Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 29 Feb 2024 16:52:35 -0800 Subject: secondlife/viewer#712: Remember previously set textures/materials when possible. Not persistent. --- indra/newview/llfloaterregioninfo.cpp | 88 ++++++++++++++++++++++------------- indra/newview/llfloaterregioninfo.h | 5 +- indra/newview/llvlcomposition.cpp | 22 +++++++-- indra/newview/llvlcomposition.h | 9 ++-- 4 files changed, 81 insertions(+), 43 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 8e2fb24923..a865ad19d3 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -86,7 +86,6 @@ #include "llviewerstats.h" #include "llviewertexteditor.h" #include "llviewerwindow.h" -#include "llvlcomposition.h" #include "lltrans.h" #include "llagentui.h" #include "llmeshrepository.h" @@ -100,7 +99,6 @@ #include "llavatarnamecache.h" #include "llenvironment.h" -const S32 TERRAIN_TEXTURE_COUNT = 4; const S32 CORNER_COUNT = 4; const U32 MAX_LISTED_NAMES = 100; @@ -1335,7 +1333,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() } static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { std::string buffer; buffer = llformat("texture_detail_%d", i); @@ -1397,6 +1395,21 @@ BOOL LLPanelRegionTerrainInfo::validateTextureHeights() ///////////////////////////////////////////////////////////////////////////// // LLPanelRegionTerrainInfo ///////////////////////////////////////////////////////////////////////////// + +LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo() +: LLPanelRegionInfo() +{ + const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures(); + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + mLastSetTextures[i] = default_textures[i]; + } + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + mLastSetMaterials[i] = LLUUID::null; + } +} + // Initialize statics BOOL LLPanelRegionTerrainInfo::postBuild() @@ -1411,12 +1424,12 @@ BOOL LLPanelRegionTerrainInfo::postBuild() std::string buffer; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); initCtrl(buffer); } - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); initCtrl(buffer); @@ -1462,7 +1475,7 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() // Toggle visibility of correct swatches std::string buffer; LLTextureCtrl* texture_ctrl; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); texture_ctrl = getChild(buffer); @@ -1471,7 +1484,7 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() texture_ctrl->setVisible(show_texture_controls); } } - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); texture_ctrl = getChild(buffer); @@ -1530,8 +1543,8 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) bool set_texture_swatches; bool set_material_swatches; - bool clear_texture_swatches; - bool clear_material_swatches; + bool reset_texture_swatches; + bool reset_material_swatches; LLTerrainMaterials::Type material_type; if (!textures_ready && !materials_ready) { @@ -1540,16 +1553,16 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) material_type = LLTerrainMaterials::Type::TEXTURE; set_texture_swatches = true; set_material_swatches = true; - clear_texture_swatches = false; - clear_material_swatches = false; + reset_texture_swatches = false; + reset_material_swatches = false; } else { material_type = compp->getMaterialType(); set_texture_swatches = material_type == LLTerrainMaterials::Type::TEXTURE; set_material_swatches = !set_texture_swatches; - clear_texture_swatches = !set_texture_swatches; - clear_material_swatches = !set_material_swatches; + reset_texture_swatches = !set_texture_swatches; + reset_material_swatches = !set_material_swatches; } LLComboBox* material_type_ctrl = getChild("terrain_material_type"); @@ -1560,7 +1573,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) std::string buffer; if (set_texture_swatches) { - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); asset_ctrl = getChild(buffer); @@ -1575,7 +1588,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) } if (set_material_swatches) { - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); asset_ctrl = getChild(buffer); @@ -1588,27 +1601,27 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) } } } - if (clear_texture_swatches) + if (reset_texture_swatches) { - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); asset_ctrl = getChild(buffer); if(asset_ctrl) { - asset_ctrl->setImageAssetID(LLUUID::null); + asset_ctrl->setImageAssetID(mLastSetTextures[i]); } } } - if (clear_material_swatches) + if (reset_material_swatches) { - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); asset_ctrl = getChild(buffer); if(asset_ctrl) { - asset_ctrl->setImageAssetID(LLUUID::null); + asset_ctrl->setImageAssetID(mLastSetMaterials[i]); } } } @@ -1687,26 +1700,35 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() // terrain_material_type - they both occupy the same slot. LLComboBox* material_type_ctrl = getChild("terrain_material_type"); const TerrainMaterialType material_type = material_type_ctrl ? material_type_from_index(material_type_ctrl->getCurrentIndex()) : TerrainMaterialType::TEXTURE; - for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) - { + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { if (material_type == TerrainMaterialType::PBR_MATERIAL) { buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); } else { buffer = llformat("texture_detail_%d", i); - asset_ctrl = getChild(buffer); } - if(asset_ctrl) - { - LLUUID tmp_id(asset_ctrl->getImageAssetID()); - tmp_id.toString(id_str); - buffer = llformat("%d %s", i, id_str.c_str()); - strings.push_back(buffer); - } - } + asset_ctrl = getChild(buffer); + + if (!asset_ctrl) { continue; } + + LLUUID tmp_id(asset_ctrl->getImageAssetID()); + tmp_id.toString(id_str); + buffer = llformat("%d %s", i, id_str.c_str()); + strings.push_back(buffer); + + // Store asset for later terrain editing + if (material_type == TerrainMaterialType::PBR_MATERIAL) + { + mLastSetMaterials[i] = tmp_id; + } + else + { + mLastSetTextures[i] = tmp_id; + } + } sendEstateOwnerMessage(msg, "texturedetail", invoice, strings); strings.clear(); diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index abd8e21503..315c6aca0f 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -36,6 +36,7 @@ #include "llpanel.h" #include "llextendedstatus.h" #include "llpanelenvironment.h" +#include "llvlcomposition.h" #include "lleventcoro.h" @@ -243,7 +244,7 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo LOG_CLASS(LLPanelRegionTerrainInfo); public: - LLPanelRegionTerrainInfo() : LLPanelRegionInfo() {} + LLPanelRegionTerrainInfo(); ~LLPanelRegionTerrainInfo() {} BOOL postBuild() override; @@ -274,6 +275,8 @@ private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; boost::signals2::connection mRegionChangedSlot; + LLUUID mLastSetTextures[LLTerrainMaterials::ASSET_COUNT]; + LLUUID mLastSetMaterials[LLTerrainMaterials::ASSET_COUNT]; }; ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 9c64381a07..506ab005c5 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -44,7 +44,6 @@ static const U32 BASE_SIZE = 128; - F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac) { // Not sure if this is the right math... @@ -286,16 +285,29 @@ bool LLTerrainMaterials::materialReady(LLPointer &mat, bo return true; } +// static +const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT] +{ + const static LLUUID default_textures[LLVLComposition::ASSET_COUNT] = + { + TERRAIN_DIRT_DETAIL, + TERRAIN_GRASS_DETAIL, + TERRAIN_MOUNTAIN_DETAIL, + TERRAIN_ROCK_DETAIL + }; + return default_textures; +} LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : LLTerrainMaterials(), LLViewerLayer(width, scale) { // Load Terrain Textures - Original ones - setDetailAssetID(0, TERRAIN_DIRT_DETAIL); - setDetailAssetID(1, TERRAIN_GRASS_DETAIL); - setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL); - setDetailAssetID(3, TERRAIN_ROCK_DETAIL); + const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures(); + for (S32 i = 0; i < ASSET_COUNT; ++i) + { + setDetailAssetID(i, default_textures[i]); + } mSurfacep = surfacep; diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index dea776849a..7397ff1e8d 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -82,6 +82,11 @@ extern LLTerrainMaterials gLocalTerrainMaterials; class LLVLComposition : public LLTerrainMaterials, public LLViewerLayer { public: + // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. + // So we need to compress heights into this range. + static const S32 ASSET_COUNT = 4; + static const LLUUID (&getDefaultTextures())[ASSET_COUNT]; + LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); /*virtual*/ ~LLVLComposition(); @@ -93,10 +98,6 @@ public: // Generate texture from composition values. BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height); - // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. - // So we need to compress heights into this range. - static const S32 ASSET_COUNT = 4; - // Use these as indeces ito the get/setters below that use 'corner' enum ECorner { -- cgit v1.2.3 From 94c5baeb6146598a9a280e27e584c241b7b3b9e0 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 1 Mar 2024 17:26:24 -0800 Subject: secondlife/viewer#712: Use checkbox to make it more obvious that only one set of terrain assets is preserved. Clean up enums. --- indra/newview/llfloaterregioninfo.cpp | 56 ++++++++++------------ .../skins/default/xui/en/panel_region_terrain.xml | 45 ++++++++--------- 2 files changed, 46 insertions(+), 55 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index a865ad19d3..6e8e37621e 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -602,24 +602,14 @@ LLPanelRegionEnvironment* LLFloaterRegionInfo::getPanelEnvironment() return panel; } -enum class TerrainMaterialType +LLTerrainMaterials::Type material_type_from_ctrl(LLCheckBoxCtrl* ctrl) { - TEXTURE, - PBR_MATERIAL, - COUNT -}; + return ctrl->get() ? LLTerrainMaterials::Type::PBR : LLTerrainMaterials::Type::TEXTURE; +} -TerrainMaterialType material_type_from_index(S32 index) +void material_type_to_ctrl(LLCheckBoxCtrl* ctrl, LLTerrainMaterials::Type new_type) { - if (index == 0) - { - return TerrainMaterialType::TEXTURE; - } - if (index == 1) - { - return TerrainMaterialType::PBR_MATERIAL; - } - return TerrainMaterialType::COUNT; + ctrl->set(new_type == LLTerrainMaterials::Type::PBR); } // static @@ -1324,11 +1314,11 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { - LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); if (material_type_ctrl) { - const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); - const bool is_material_selected = material_type == TerrainMaterialType::PBR_MATERIAL; + const LLTerrainMaterials::Type material_type = material_type_from_ctrl(material_type_ctrl); + const bool is_material_selected = material_type == LLTerrainMaterials::Type::PBR; if (is_material_selected) { return TRUE; } } @@ -1466,11 +1456,11 @@ void LLPanelRegionTerrainInfo::onSelectMaterialType() void LLPanelRegionTerrainInfo::updateForMaterialType() { - LLComboBox* material_type_ctrl = getChild("terrain_material_type"); + LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); if (!material_type_ctrl) { return; } - const TerrainMaterialType material_type = material_type_from_index(material_type_ctrl->getCurrentIndex()); - const bool show_texture_controls = material_type == TerrainMaterialType::TEXTURE; - const bool show_material_controls = material_type == TerrainMaterialType::PBR_MATERIAL; + const LLTerrainMaterials::Type material_type = material_type_from_ctrl(material_type_ctrl); + const bool show_texture_controls = material_type == LLTerrainMaterials::Type::TEXTURE; + const bool show_material_controls = material_type == LLTerrainMaterials::Type::PBR; // Toggle visibility of correct swatches std::string buffer; @@ -1493,6 +1483,12 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() texture_ctrl->setVisible(show_material_controls); } } + + // Toggle visibility of labels + LLUICtrl* texture_label = getChild("detail_texture_text"); + if (texture_label) { texture_label->setVisible(show_texture_controls); } + LLUICtrl* material_label = getChild("detail_material_text"); + if (material_label) { material_label->setVisible(show_material_controls); } } void LLPanelRegionTerrainInfo::onRegionChanged() @@ -1538,9 +1534,6 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) const bool textures_ready = compp->texturesReady(false, false); const bool materials_ready = feature_pbr_terrain_enabled && compp->materialsReady(false, false); - LLTextBox* texture_text = getChild("detail_texture_text"); - if (texture_text) { texture_text->setVisible(!feature_pbr_terrain_enabled); } - bool set_texture_swatches; bool set_material_swatches; bool reset_texture_swatches; @@ -1565,9 +1558,10 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) reset_material_swatches = !set_material_swatches; } - LLComboBox* material_type_ctrl = getChild("terrain_material_type"); - if (material_type_ctrl) { material_type_ctrl->setCurrentByIndex(S32(material_type)); } + LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); + if (material_type_ctrl) { material_type_to_ctrl(material_type_ctrl, material_type); } updateForMaterialType(); + material_type_ctrl->setVisible(feature_pbr_terrain_enabled); LLTextureCtrl* asset_ctrl; std::string buffer; @@ -1698,11 +1692,11 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() // Send either material IDs instead of texture IDs depending on // terrain_material_type - they both occupy the same slot. - LLComboBox* material_type_ctrl = getChild("terrain_material_type"); - const TerrainMaterialType material_type = material_type_ctrl ? material_type_from_index(material_type_ctrl->getCurrentIndex()) : TerrainMaterialType::TEXTURE; + LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); + const LLTerrainMaterials::Type material_type = material_type_ctrl ? material_type_from_ctrl(material_type_ctrl) : LLTerrainMaterials::Type::TEXTURE; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - if (material_type == TerrainMaterialType::PBR_MATERIAL) + if (material_type == LLTerrainMaterials::Type::PBR) { buffer = llformat("material_detail_%d", i); } @@ -1720,7 +1714,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() strings.push_back(buffer); // Store asset for later terrain editing - if (material_type == TerrainMaterialType::PBR_MATERIAL) + if (material_type == LLTerrainMaterials::Type::PBR) { mLastSetMaterials[i] = tmp_id; } diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index 88855ab739..f8d2c90d0a 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -76,33 +76,17 @@ left="8" top="30" width="460" /> - - - - Terrain Textures @@ -114,12 +98,25 @@ follows="left|top" height="20" layout="topleft" - top_delta="0" - left_delta="180" - name="detail_texture_limits_text" - width="200"> - Maximum size: 1024x1024 + name="detail_material_text" + left="10" + top="105" + width="170"> + Terrain Materials + Date: Wed, 6 Mar 2024 13:04:40 -0800 Subject: secondlife/viewer#712: Clean up unused region change callback checks --- indra/newview/llfloaterregioninfo.cpp | 26 -------------------------- indra/newview/llfloaterregioninfo.h | 3 --- 2 files changed, 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 6e8e37621e..3256527ee5 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1440,11 +1440,6 @@ BOOL LLPanelRegionTerrainInfo::postBuild() mAskedTextureHeights = false; mConfirmedTextureHeights = false; - if (!mRegionChangedSlot.connected()) - { - mRegionChangedSlot = gAgent.addRegionChangedCallback(boost::bind(&LLPanelRegionTerrainInfo::onRegionChanged,this)); - } - return LLPanelRegionInfo::postBuild(); } @@ -1491,27 +1486,6 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() if (material_label) { material_label->setVisible(show_material_controls); } } -void LLPanelRegionTerrainInfo::onRegionChanged() -{ - LLViewerRegion *region = gAgent.getRegion(); - if (!region) { return; } - - if (region->simulatorFeaturesReceived()) - { - onSimulatorFeaturesReceived(region->getRegionID(), region); - } - else - { - // See "RenderTerrainPBREnabled" in LLViewerRegion::setSimulatorFeatures - region->setSimulatorFeaturesReceivedCallback(boost::bind(&LLPanelRegionTerrainInfo::onSimulatorFeaturesReceived,this,_1, _2)); - } -} - -void LLPanelRegionTerrainInfo::onSimulatorFeaturesReceived(const LLUUID& region_id, LLViewerRegion* regionp) -{ - refresh(); -} - // virtual bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 315c6aca0f..93a4d3a795 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -249,8 +249,6 @@ public: BOOL postBuild() override; - void onRegionChanged(); - void onSimulatorFeaturesReceived(const LLUUID& region_id, LLViewerRegion* regionp); bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region @@ -274,7 +272,6 @@ protected: private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; - boost::signals2::connection mRegionChangedSlot; LLUUID mLastSetTextures[LLTerrainMaterials::ASSET_COUNT]; LLUUID mLastSetMaterials[LLTerrainMaterials::ASSET_COUNT]; }; -- cgit v1.2.3 From 1fc45a50ff15e6f31a4554da83256b7f59b1af15 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 6 Mar 2024 17:56:16 -0800 Subject: #681 Add probe blending for mirrors. --- .../shaders/class1/deferred/pbrterrainF.glsl | 4 ++ .../shaders/class1/deferred/pbrterrainV.glsl | 3 ++ .../shaders/class3/deferred/reflectionProbeF.glsl | 43 +++++++-------- indra/newview/llheroprobemanager.cpp | 62 +++++----------------- indra/newview/llheroprobemanager.h | 18 +++++-- indra/newview/llreflectionmapmanager.cpp | 18 +++++++ 6 files changed, 69 insertions(+), 79 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index c83a6be85d..57c0a6024f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -133,6 +133,7 @@ uniform vec4 minimum_alphas; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlpha #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 in vec4[2] vary_coords; #endif +in vec3 vary_position; in vec3 vary_normal; in vec3 vary_tangent; flat in float vary_sign; @@ -140,11 +141,14 @@ in vec4 vary_texcoord0; in vec4 vary_texcoord1; vec2 encode_normal(vec3 n); +void mirrorClip(vec3 position); float terrain_mix(TerrainMix tm, vec4 tms4); void main() { + // Make sure we clip the terrain if we're in a mirror. + mirrorClip(vary_position); #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 TerrainCoord terrain_texcoord = vary_coords; diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index dbb9404219..489fc26e3f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -25,6 +25,7 @@ uniform mat3 normal_matrix; uniform mat4 texture_matrix0; +uniform mat4 modelview_matrix; uniform mat4 modelview_projection_matrix; in vec3 position; @@ -42,6 +43,7 @@ out vec3 vary_tangent; flat out float vary_sign; out vec4 vary_texcoord0; out vec4 vary_texcoord1; +out vec3 vary_position; // *HACK: tangent_space_transform should use texture_normal_transform, or maybe // we shouldn't use tangent_space_transform at all. See the call to @@ -55,6 +57,7 @@ void main() { //transform vertex gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; vec3 n = normal_matrix * normal; vary_vertex_normal = normal; diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 257299258e..4f2475b101 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -48,6 +48,7 @@ layout (std140) uniform ReflectionProbes /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation // box[3][0..2] - plane thickness mat4 refBox[MAX_REFMAP_COUNT]; + mat4 heroBox; // list of bounding spheres for reflection probes sorted by distance to camera (closest first) vec4 refSphere[MAX_REFMAP_COUNT]; // extra parameters @@ -56,6 +57,7 @@ layout (std140) uniform ReflectionProbes // z - fade in // w - znear vec4 refParams[MAX_REFMAP_COUNT]; + vec4 heroSphere; // 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 @@ -71,6 +73,10 @@ layout (std140) uniform ReflectionProbes // number of reflection probes present in refSphere int refmapCount; + + int heroShape; + int heroMipCount; + int heroProbeCount; }; // Inputs @@ -682,48 +688,37 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir, vec3 amblit) return col[1]+col[0]; } - #if defined(HERO_PROBES) uniform vec4 clipPlane; - uniform samplerCubeArray heroProbes; -layout (std140) uniform HeroProbeData -{ - mat4 heroBox[1]; - vec4 heroSphere[1]; - uint heroShape[1]; - int heroMipCount; - int heroProbeCount; -}; - void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) { float clipDist = dot(pos.xyz, clipPlane.xyz) + clipPlane.w; float w = 0; float dw = 0; - if (heroShape[0] < 1) + float falloffMult = 10; + vec3 refnormpersp = reflect(pos.xyz, norm.xyz); + if (heroShape < 1) { float d = 0; - boxIntersect(pos, norm, heroBox[0], d, 1.0); + boxIntersect(pos, norm, heroBox, d, 1.0); - w = max(d, 0.001); + w = max(d, 0); } else { - float r = heroSphere[0].w; + float r = heroSphere.w; - w = sphereWeight(pos, norm, heroSphere[0].xyz, r, vec4(1), dw); - } - - { - vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - if (dot(refnormpersp.xyz, clipPlane.xyz) > 0.0) - { - glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w); - } + w = sphereWeight(pos, refnormpersp, heroSphere.xyz, r, vec4(1), dw); } + + clipDist = clipDist * 0.95 + 0.05; + clipDist = clamp(clipDist * falloffMult, 0, 1); + w = clamp(w * falloffMult * clipDist, 0, 1); + + glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w); } #else diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ee993c6ba1..8f1c1848cc 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -151,6 +151,7 @@ void LLHeroProbeManager::update() // Collect the list of faces that need updating based upon the camera's rotation. LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); + cam_direction.normalize(); static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), @@ -163,7 +164,7 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { - float shouldUpdate = cam_direction * cubeFaces[i] * 0.5 + 0.5; + float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5)); int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); @@ -215,6 +216,9 @@ void LLHeroProbeManager::update() mRenderingMirror = false; gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; + + mProbes[0]->mViewerObject = mNearestHero; + mProbes[0]->autoAdjustOrigin(); } mCurrentProbeUpdateFrame++; @@ -424,26 +428,14 @@ void LLHeroProbeManager::updateUniforms() LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - struct HeroProbeData - { - LLMatrix4 heroBox[1]; - LLVector4 heroSphere[1]; - GLint heroShape[1]; - GLint heroMipCount; - GLint heroProbeCount; - }; - - HeroProbeData hpd; - LLMatrix4a modelview; modelview.loadu(gGLModelView); LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); - hpd.heroProbeCount = 1; + mHeroData.heroProbeCount = 1; if (mNearestHero != nullptr) { - mProbes[0]->mViewerObject = mNearestHero; if (mNearestHero->getReflectionProbeIsBox()) { LLVector3 s = mNearestHero->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); @@ -455,44 +447,17 @@ void LLHeroProbeManager::updateUniforms() } modelview.affineTransform(mProbes[0]->mOrigin, oa); - hpd.heroShape[0] = 0; - if (!mProbes[0]->getBox(hpd.heroBox[0])) + mHeroData.heroShape = 0; + if (!mProbes[0]->getBox(mHeroData.heroBox)) { - hpd.heroShape[0] = 1; + mHeroData.heroShape = 1; } - hpd.heroSphere[0].set(oa.getF32ptr()); - hpd.heroSphere[0].mV[3] = mProbes[0]->mRadius; + mHeroData.heroSphere.set(oa.getF32ptr()); + mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius; } - hpd.heroMipCount = mMipChain.size(); - - //copy rpd into uniform buffer object - if (mUBO == 0) - { - glGenBuffers(1, &mUBO); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - update buffer"); - glBindBuffer(GL_UNIFORM_BUFFER, mUBO); - glBufferData(GL_UNIFORM_BUFFER, sizeof(HeroProbeData), &hpd, GL_STREAM_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } -} - -void LLHeroProbeManager::setUniforms() -{ - if (!LLPipeline::sReflectionProbesEnabled) - { - return; - } - - if (mUBO == 0) - { - updateUniforms(); - } - glBindBufferBase(GL_UNIFORM_BUFFER, 1, mUBO); + mHeroData.heroMipCount = mMipChain.size(); } void LLHeroProbeManager::renderDebug() @@ -581,9 +546,6 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - glDeleteBuffers(1, &mUBO); - mUBO = 0; mHeroVOList.clear(); mNearestHero = nullptr; diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index e430cae203..04027cd57e 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -38,6 +38,15 @@ class LLViewerObject; // number of reflection probes to keep in vram #define LL_MAX_HERO_PROBE_COUNT 2 +struct HeroProbeData +{ + LLMatrix4 heroBox; + LLVector4 heroSphere; + GLint heroShape; + GLint heroMipCount; + GLint heroProbeCount; +}; + class alignas(16) LLHeroProbeManager { LL_ALIGN_NEW @@ -74,16 +83,17 @@ public: bool isMirrorPass() const { return mRenderingMirror; } LLVector3 mMirrorPosition; - LLVector3 mMirrorNormal; + LLVector3 mMirrorNormal; + HeroProbeData mHeroData; private: friend class LLPipeline; + friend class LLReflectionMapManager; // update UBO used for rendering (call only once per render pipe flush) void updateUniforms(); // bind UBO used for rendering - void setUniforms(); // render target for cube snapshots // used to generate mipmaps without doing a copy-to-texture @@ -109,9 +119,6 @@ private: // list of active reflection maps std::vector> mProbes; - // handle to UBO - U32 mUBO = 0; - // list of maps being used for rendering std::vector mReflectionMaps; @@ -141,5 +148,6 @@ private: std::vector mHeroVOList; LLVOVolume* mNearestHero; + }; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 3144260905..ce389a5cad 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -906,6 +906,8 @@ void LLReflectionMapManager::updateUniforms() // the box probe LLMatrix4 refBox[LL_MAX_REFLECTION_PROBE_COUNT]; + LLMatrix4 heroBox; + // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT]; @@ -916,6 +918,8 @@ void LLReflectionMapManager::updateUniforms() // w - znear LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT]; + LLVector4 heroSphere; + // indices used by probe: // [i][0] - cubemap array index for this probe // [i][1] - index into "refNeighbor" for probes that intersect this probe @@ -929,6 +933,10 @@ void LLReflectionMapManager::updateUniforms() GLint refBucket[256][4]; //lookup table for which index to start with for the given Z depth // numbrer of active refmaps GLint refmapCount; + + GLint heroShape; + GLint heroMipCount; + GLint heroProbeCount; }; mReflectionMaps.resize(mReflectionProbeCount); @@ -1118,6 +1126,16 @@ void LLReflectionMapManager::updateUniforms() rpd.refmapCount = count; + gPipeline.mHeroProbeManager.updateUniforms(); + + // Get the hero data. + + rpd.heroBox = gPipeline.mHeroProbeManager.mHeroData.heroBox; + rpd.heroSphere = gPipeline.mHeroProbeManager.mHeroData.heroSphere; + rpd.heroShape = gPipeline.mHeroProbeManager.mHeroData.heroShape; + rpd.heroMipCount = gPipeline.mHeroProbeManager.mHeroData.heroMipCount; + rpd.heroProbeCount = gPipeline.mHeroProbeManager.mHeroData.heroProbeCount; + //copy rpd into uniform buffer object if (mUBO == 0) { -- cgit v1.2.3 From 4b738a619a475447af8b917644357cb49dc22fb9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 6 Mar 2024 18:24:36 -0800 Subject: #681 Small fix for if a viewer object may be dead. --- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llreflectionmap.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 8f1c1848cc..10b743ceef 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -434,7 +434,7 @@ void LLHeroProbeManager::updateUniforms() oa.set(0, 0, 0, 0); mHeroData.heroProbeCount = 1; - if (mNearestHero != nullptr) + if (mNearestHero != nullptr && !mNearestHero->isDead()) { if (mNearestHero->getReflectionProbeIsBox()) { diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 6d5797395c..30a61144b9 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -166,7 +166,7 @@ void LLReflectionMap::autoAdjustOrigin() } } - else if (mViewerObject) + else if (mViewerObject && !mViewerObject->isDead()) { mPriority = 1; mOrigin.load3(mViewerObject->getPositionAgent().mV); -- cgit v1.2.3 From 327764231543df768c09a976441e35312f6f2c49 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 7 Mar 2024 02:14:08 +0200 Subject: viewer-private#41 Texture fail to apply to materials in some cases Shift-dropping textures can fail if one of 'early' faces has nomod material --- indra/newview/lltooldraganddrop.cpp | 96 ++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index bfa9386cd4..2a17882ff1 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1077,51 +1077,71 @@ void set_texture_to_material(LLViewerObject* hit_obj, LLGLTFMaterial::TextureInfo drop_channel) { LLTextureEntry* te = hit_obj->getTE(hit_face); - if (te) + if (!te) { - LLPointer material = te->getGLTFMaterialOverride(); + return; + } - // make a copy to not invalidate existing - // material for multiple objects - if (material.isNull()) - { - // Start with a material override which does not make any changes - material = new LLGLTFMaterial(); - } - else - { - material = new LLGLTFMaterial(*material); - } + const LLUUID base_mat_id = hit_obj->getRenderMaterialID(hit_face); + if (base_mat_id.isNull()) + { + return; + } - switch (drop_channel) - { - case LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR: - default: - { - material->setBaseColorId(asset_id); - } - break; + if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) + { + hit_obj->requestInventory(); + return; + } - case LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS: - { - material->setOcclusionRoughnessMetallicId(asset_id); - } - break; + LLViewerInventoryItem* mat_item = hit_obj->getInventoryItemByAsset(base_mat_id); + if (mat_item && !mat_item->getPermissions().allowModifyBy(gAgentID)) + { + return; + } - case LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE: - { - material->setEmissiveId(asset_id); - } - break; + LLPointer material = te->getGLTFMaterialOverride(); - case LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL: - { - material->setNormalId(asset_id); - } - break; - } - LLGLTFMaterialList::queueModify(hit_obj, hit_face, material); + // make a copy to not invalidate existing + // material for multiple objects + if (material.isNull()) + { + // Start with a material override which does not make any changes + material = new LLGLTFMaterial(); + } + else + { + material = new LLGLTFMaterial(*material); + } + + switch (drop_channel) + { + case LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR: + default: + { + material->setBaseColorId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS: + { + material->setOcclusionRoughnessMetallicId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE: + { + material->setEmissiveId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL: + { + material->setNormalId(asset_id); + } + break; } + LLGLTFMaterialList::queueModify(hit_obj, hit_face, material); } void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, -- cgit v1.2.3 From 7f2e3d0f278f55d8c831273547e49077764c9f14 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 7 Mar 2024 17:32:23 -0800 Subject: secondlife/viewer#712: Consolidate accesses to terrain_material_type control --- indra/newview/llfloaterregioninfo.cpp | 48 +++++++++++++++++------------------ indra/newview/llfloaterregioninfo.h | 1 + 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 3256527ee5..c6d8317128 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1314,10 +1314,9 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { - LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); - if (material_type_ctrl) + if (mMaterialTypeCtrl) { - const LLTerrainMaterials::Type material_type = material_type_from_ctrl(material_type_ctrl); + const LLTerrainMaterials::Type material_type = material_type_from_ctrl(mMaterialTypeCtrl); const bool is_material_selected = material_type == LLTerrainMaterials::Type::PBR; if (is_material_selected) { return TRUE; } } @@ -1327,7 +1326,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() { std::string buffer; buffer = llformat("texture_detail_%d", i); - LLTextureCtrl* texture_ctrl = getChild(buffer); + LLTextureCtrl* texture_ctrl = findChild(buffer); if (!texture_ctrl) continue; LLUUID image_asset_id = texture_ctrl->getImageAssetID(); @@ -1410,7 +1409,8 @@ BOOL LLPanelRegionTerrainInfo::postBuild() initCtrl("terrain_raise_spin"); initCtrl("terrain_lower_spin"); - getChild("terrain_material_type")->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onSelectMaterialType, this)); + mMaterialTypeCtrl = findChild("terrain_material_type"); + if (mMaterialTypeCtrl) { mMaterialTypeCtrl->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onSelectMaterialType, this)); } std::string buffer; @@ -1451,9 +1451,8 @@ void LLPanelRegionTerrainInfo::onSelectMaterialType() void LLPanelRegionTerrainInfo::updateForMaterialType() { - LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); - if (!material_type_ctrl) { return; } - const LLTerrainMaterials::Type material_type = material_type_from_ctrl(material_type_ctrl); + if (!mMaterialTypeCtrl) { return; } + const LLTerrainMaterials::Type material_type = material_type_from_ctrl(mMaterialTypeCtrl); const bool show_texture_controls = material_type == LLTerrainMaterials::Type::TEXTURE; const bool show_material_controls = material_type == LLTerrainMaterials::Type::PBR; @@ -1463,7 +1462,7 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); - texture_ctrl = getChild(buffer); + texture_ctrl = findChild(buffer); if (texture_ctrl) { texture_ctrl->setVisible(show_texture_controls); @@ -1472,7 +1471,7 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); - texture_ctrl = getChild(buffer); + texture_ctrl = findChild(buffer); if (texture_ctrl) { texture_ctrl->setVisible(show_material_controls); @@ -1480,9 +1479,9 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() } // Toggle visibility of labels - LLUICtrl* texture_label = getChild("detail_texture_text"); + LLUICtrl* texture_label = findChild("detail_texture_text"); if (texture_label) { texture_label->setVisible(show_texture_controls); } - LLUICtrl* material_label = getChild("detail_material_text"); + LLUICtrl* material_label = findChild("detail_material_text"); if (material_label) { material_label->setVisible(show_material_controls); } } @@ -1532,10 +1531,12 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) reset_material_swatches = !set_material_swatches; } - LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); - if (material_type_ctrl) { material_type_to_ctrl(material_type_ctrl, material_type); } - updateForMaterialType(); - material_type_ctrl->setVisible(feature_pbr_terrain_enabled); + if (mMaterialTypeCtrl) + { + material_type_to_ctrl(mMaterialTypeCtrl, material_type); + updateForMaterialType(); + mMaterialTypeCtrl->setVisible(feature_pbr_terrain_enabled); + } LLTextureCtrl* asset_ctrl; std::string buffer; @@ -1544,7 +1545,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); - asset_ctrl = getChild(buffer); + asset_ctrl = findChild(buffer); if(asset_ctrl) { LL_DEBUGS() << "Detail Texture " << i << ": " @@ -1559,7 +1560,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); + asset_ctrl = findChild(buffer); if(asset_ctrl) { LL_DEBUGS() << "Detail Material " << i << ": " @@ -1574,7 +1575,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("texture_detail_%d", i); - asset_ctrl = getChild(buffer); + asset_ctrl = findChild(buffer); if(asset_ctrl) { asset_ctrl->setImageAssetID(mLastSetTextures[i]); @@ -1586,7 +1587,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); - asset_ctrl = getChild(buffer); + asset_ctrl = findChild(buffer); if(asset_ctrl) { asset_ctrl->setImageAssetID(mLastSetMaterials[i]); @@ -1665,9 +1666,8 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() LLMessageSystem* msg = gMessageSystem; // Send either material IDs instead of texture IDs depending on - // terrain_material_type - they both occupy the same slot. - LLCheckBoxCtrl* material_type_ctrl = getChild("terrain_material_type"); - const LLTerrainMaterials::Type material_type = material_type_ctrl ? material_type_from_ctrl(material_type_ctrl) : LLTerrainMaterials::Type::TEXTURE; + // material_type - they both occupy the same slot. + const LLTerrainMaterials::Type material_type = mMaterialTypeCtrl ? material_type_from_ctrl(mMaterialTypeCtrl) : LLTerrainMaterials::Type::TEXTURE; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { if (material_type == LLTerrainMaterials::Type::PBR) @@ -1678,7 +1678,7 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() { buffer = llformat("texture_detail_%d", i); } - asset_ctrl = getChild(buffer); + asset_ctrl = findChild(buffer); if (!asset_ctrl) { continue; } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 93a4d3a795..a38344c861 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -272,6 +272,7 @@ protected: private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; + LLCheckBoxCtrl* mMaterialTypeCtrl = nullptr; LLUUID mLastSetTextures[LLTerrainMaterials::ASSET_COUNT]; LLUUID mLastSetMaterials[LLTerrainMaterials::ASSET_COUNT]; }; -- cgit v1.2.3 From c1bde75768e1374d4f094936d52ed29f6f5d3cba Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 8 Mar 2024 12:01:20 -0600 Subject: HDRI Local Preview (#953) * #926 WIP - HDRI import prototype v0 * #926 WIP -- add OpenEXR to autobuild.xml * #926 WIP -- Add OpenEXR cmake * #926 WIP -- Attempt at using OpenEXR autobuild package and don't hard code .exr file to load * #926 Unmangle autobuild.xml and get dll's in the right place (thanks, Caladbolg!) * implement mac shared libs plumbing for OpenEXR for secondlife/viewer#926 * Fix Xcode/clang compile error regarding new[]/delete[] mismatch * #926 HDRI Preview finishing touches. - Full ACES when HDRI is enabled - Fix for probes getting stuck paused - Add exposure and rotation controls --------- Co-authored-by: Brad Linden --- indra/cmake/Copy3rdPartyLibs.cmake | 12 ++ indra/cmake/OpenEXR.cmake | 18 +++ indra/llrender/llshadermgr.cpp | 2 +- indra/newview/CMakeLists.txt | 9 +- indra/newview/app_settings/settings.xml | 33 ++++++ .../class1/deferred/postDeferredGammaCorrect.glsl | 3 +- .../app_settings/shaders/class1/deferred/skyF.glsl | 23 +++- .../app_settings/shaders/class1/deferred/skyV.glsl | 8 ++ .../shaders/class3/deferred/softenLightF.glsl | 4 + indra/newview/lldrawpoolwlsky.cpp | 38 +++++- indra/newview/llenvironment.cpp | 8 +- indra/newview/llfilepicker.cpp | 7 ++ indra/newview/llfilepicker.h | 1 + indra/newview/llreflectionmapmanager.cpp | 131 ++++++++++++++++++++- indra/newview/llreflectionmapmanager.h | 4 +- indra/newview/llviewermenu.cpp | 14 +++ indra/newview/llviewershadermgr.cpp | 23 ++++ indra/newview/llviewershadermgr.h | 1 + indra/newview/llvoavatar.cpp | 3 - indra/newview/pipeline.cpp | 4 + indra/newview/skins/default/xui/en/menu_viewer.xml | 6 + .../newview/skins/default/xui/en/notifications.xml | 9 ++ indra/newview/viewer_manifest.py | 14 +++ 23 files changed, 359 insertions(+), 16 deletions(-) create mode 100644 indra/cmake/OpenEXR.cmake (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 9f79c13a97..415641f65f 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -60,6 +60,12 @@ if(WINDOWS) nghttp2.dll libhunspell.dll uriparser.dll + Iex-3_2.dll + IlmThread-3_2.dll + Imath-3_1.dll + OpenEXR-3_2.dll + OpenEXRCore-3_2.dll + OpenEXRUtil-3_2.dll ) # ICU4C (same filenames for 32 and 64 bit builds) @@ -184,6 +190,12 @@ elseif(DARWIN) liburiparser.dylib liburiparser.1.dylib liburiparser.1.0.27.dylib + libIex-3_2.dylib + libIlmThread-3_2.dylib + libImath-3_1.dylib + libOpenEXR-3_2.dylib + libOpenEXRCore-3_2.dylib + libOpenEXRUtil-3_2.dylib ) if (TARGET ll::fmodstudio) diff --git a/indra/cmake/OpenEXR.cmake b/indra/cmake/OpenEXR.cmake new file mode 100644 index 0000000000..ee21fac541 --- /dev/null +++ b/indra/cmake/OpenEXR.cmake @@ -0,0 +1,18 @@ +# -*- cmake -*- + +include(Prebuilt) + +include_guard() +add_library( ll::openexr INTERFACE IMPORTED ) + +if(USE_CONAN ) + target_link_libraries( ll::openexr INTERFACE CONAN_PKG::openexr ) + return() +endif() + +use_prebuilt_binary(openexr) + +target_link_libraries( ll::openexr INTERFACE Iex-3_2 IlmThread-3_2 Imath-3_1 OpenEXR-3_2 OpenEXRCore-3_2 OpenEXRUtil-3_2) + +target_include_directories( ll::openexr SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/OpenEXR ${LIBS_PREBUILT_DIR}/include/Imath) + diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 5384133220..6cfe065355 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -618,7 +618,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0 extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1 - extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_MIRROR 1.0\n"); // bit 2 + extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_HDRI 1.0\n"); // bit 2 extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n"); if (defines) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b15e847a3..8494ba5b49 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -34,6 +34,7 @@ include(LLWindow) include(NDOF) include(NVAPI) include(OPENAL) +include(OpenEXR) include(OpenGL) include(OpenSSL) include(PNG) @@ -72,7 +73,6 @@ if (NOT HAVOK_TPV) endif() endif (NOT HAVOK_TPV) - set(viewer_SOURCE_FILES groupchatlistener.cpp llaccountingcostmanager.cpp @@ -1744,6 +1744,12 @@ if (WINDOWS) media_plugin_cef media_plugin_libvlc media_plugin_example + ${SHARED_LIB_STAGING_DIR}/Iex-3_2.dll + ${SHARED_LIB_STAGING_DIR}/IlmThread-3_2.dll + ${SHARED_LIB_STAGING_DIR}/Imath-3_1.dll + ${SHARED_LIB_STAGING_DIR}/OpenEXR-3_2.dll + ${SHARED_LIB_STAGING_DIR}/OpenEXRCore-3_2.dll + ${SHARED_LIB_STAGING_DIR}/OpenEXRUtil-3_2.dll ) if (ADDRESS_SIZE EQUAL 64) @@ -1937,6 +1943,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ll::bugsplat ll::tracy ll::icu4c + ll::openexr ) if( TARGET ll::intel_memops ) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9d4f4cf911..8420f32db8 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9274,6 +9274,17 @@ Value 1 + RenderDesaturateIrradiance + + Comment + Desaturate irradiance to remove blue tint + Persist + 1 + Type + Boolean + Value + 1 + RenderDebugAlphaMask Comment @@ -9340,6 +9351,28 @@ Value 0 + RenderHDRIExposure + + Comment + Exposure adjustment of HDRI when previewing an HDRI. Units are EV. Sane values would be -10 to 10. + Persist + 1 + Type + F32 + Value + 0.0 + + RenderHDRIRotation + + Comment + Rotation (in degrees) of environment when previewing an HDRI. + Persist + 1 + Type + F32 + Value + 0.0 + RenderMaxOpenGLVersion Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 3443785e1a..d89377326e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -97,6 +97,7 @@ vec3 toneMapACES_Hill(vec3 color) uniform float exposure; uniform float gamma; +uniform float aces_mix; vec3 toneMap(vec3 color) { @@ -106,7 +107,7 @@ vec3 toneMap(vec3 color) color *= exposure * exp_scale; // mix ACES and Linear here as a compromise to avoid over-darkening legacy content - color = mix(toneMapACES_Hill(color), color, 0.3); + color = mix(toneMapACES_Hill(color), color, aces_mix); #endif return color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 9d9ba49d82..cc5280d929 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -27,6 +27,13 @@ in vec3 vary_HazeColor; in float vary_LightNormPosDot; +#ifdef HAS_HDRI +in vec3 vary_position; +uniform float sky_hdr_scale; +uniform mat3 env_mat; +uniform sampler2D environmentMap; +#endif + uniform sampler2D rainbow_map; uniform sampler2D halo_map; @@ -37,6 +44,9 @@ uniform float ice_level; out vec4 frag_data[4]; vec3 srgb_to_linear(vec3 c); +vec3 linear_to_srgb(vec3 c); + +#define PI 3.14159265 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky @@ -71,6 +81,14 @@ vec3 halo22(float d) void main() { +#ifdef HAS_HDRI + vec3 pos = normalize(vary_position); + pos = env_mat * pos; + vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI); + vec3 color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale; + color = min(color, vec3(8192*8192*16)); +#else + // Potential Fill-rate optimization. Add cloud calculation // back in and output alpha of 0 (so that alpha culling kills // the fragment) if the sky wouldn't show up because the clouds @@ -86,9 +104,12 @@ void main() color.rgb *= 2.; color.rgb = clamp(color.rgb, vec3(0), vec3(5)); +#endif + frag_data[0] = vec4(0); frag_data[1] = vec4(0); - frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); frag_data[3] = vec4(color.rgb, 1.0); + } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 17ce2dee5b..bbe9a5a838 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -35,6 +35,10 @@ in vec3 position; out vec3 vary_HazeColor; out float vary_LightNormPosDot; +#ifdef HAS_HDRI +out vec3 vary_position; +#endif + // Inputs uniform vec3 camPosLocal; @@ -72,6 +76,10 @@ void main() // Get relative position vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); +#ifdef HAS_HDRI + vary_position = rel_pos; +#endif + // Adj position vector to clamp altitude if (rel_pos.y > 0.) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 2f90249169..5cc7ea698a 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -189,6 +189,10 @@ void main() vec3 v = -normalize(pos.xyz); color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten); } + else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI)) + { + color = texture(emissiveRect, tc).rgb; + } else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) { //should only be true of WL sky, just port over base color value diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index b14235f25c..a9cc138549 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -44,6 +44,7 @@ #include "llsky.h" #include "llvowlsky.h" #include "llsettingsvo.h" +#include "llviewercontrol.h" extern BOOL gCubeSnapshot; @@ -127,6 +128,8 @@ void LLDrawPoolWLSky::renderDome(const LLVector3& camPosLocal, F32 camHeightLoca gGL.popMatrix(); } +extern LLPointer gEXRImage; + void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const { if (!gSky.mVOSkyp) @@ -138,9 +141,33 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { + if (gEXRImage.notNull()) + { + sky_shader = &gEnvironmentMapProgram; + sky_shader->bind(); + S32 idx = sky_shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP); + if (idx > -1) + { + gGL.getTexUnit(idx)->bind(gEXRImage); + } + + static LLCachedControl hdri_exposure(gSavedSettings, "RenderHDRIExposure", 0.0f); + static LLCachedControl hdri_rotation(gSavedSettings, "RenderHDRIRotation", 0.f); + + LLMatrix3 rot; + rot.setRot(0.f, hdri_rotation*DEG_TO_RAD, 0.f); + + sky_shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, powf(2.f, hdri_exposure)); + sky_shader->uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, GL_FALSE, (F32*) rot.mMatrix); + } + else + { + sky_shader->bind(); + } + LLGLSPipelineDepthTestSkyBox sky(true, true); - sky_shader->bind(); + sky_shader->uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0); @@ -180,7 +207,7 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const { - if (!gSky.mVOSkyp) + if (!gSky.mVOSkyp || gEXRImage.notNull()) { return; } @@ -251,6 +278,11 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const { + if (gEXRImage.notNull()) + { + return; + } + if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp && gSky.mVOSkyp->getCloudNoiseTex()) { LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); @@ -310,7 +342,7 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 void LLDrawPoolWLSky::renderHeavenlyBodies() { - if (!gSky.mVOSkyp) return; + if (!gSky.mVOSkyp || gEXRImage.notNull()) return; LLGLSPipelineBlendSkyBox gls_skybox(true, true); // SL-14113 we need moon to write to depth to clip stars behind diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index affea3f69c..0b535e15b0 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1770,8 +1770,10 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con case LLSD::TypeArray: { LLVector4 vect4(value); + // always identify as a radiance pass if desaturating irradiance is disabled + static LLCachedControl desaturate_irradiance(gSavedSettings, "RenderDesaturateIrradiance", true); - if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass()) + if (desaturate_irradiance && gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass()) { // maximize and remove tinting if this is an irradiance map render pass and the parameter feeds into the sky background color auto max_vec = [](LLVector4 col) { @@ -2966,7 +2968,7 @@ void LLEnvironment::DayTransition::animate() // pause probe updates and reset reflection maps on sky change - gPipeline.mReflectionMapManager.pause(); + gPipeline.mReflectionMapManager.pause(mTransitionTime); gPipeline.mReflectionMapManager.reset(); mSky = mStartSky->buildClone(); @@ -3569,7 +3571,7 @@ namespace mInjectedSky->setSource(target_sky); // clear reflection probes and pause updates during sky change - gPipeline.mReflectionMapManager.pause(); + gPipeline.mReflectionMapManager.pause(transition); gPipeline.mReflectionMapManager.reset(); mBlenderSky = std::make_shared(target_sky, start_sky, psky, transition); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 4ad136e13a..b82172c506 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -61,6 +61,7 @@ LLFilePicker LLFilePicker::sInstance; #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0" #define MATERIAL_FILTER L"GLTF Files (*.gltf; *.glb)\0*.gltf;*.glb\0" +#define HDRI_FILTER L"HDRI Files (*.exr)\0*.exr\0" #define MATERIAL_TEXTURES_FILTER L"GLTF Import (*.gltf; *.glb; *.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.gltf;*.glb;*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0" #define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0" @@ -228,6 +229,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) IMAGE_FILTER \ L"\0"; break; + case FFLOAD_HDRI: + mOFN.lpstrFilter = HDRI_FILTER \ + L"\0"; + break; case FFLOAD_SCRIPT: mOFN.lpstrFilter = SCRIPT_FILTER \ L"\0"; @@ -663,6 +668,8 @@ std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadF allowedv->push_back("gltf"); allowedv->push_back("glb"); break; + case FFLOAD_HDRI: + allowedv->push_back("exr"); case FFLOAD_COLLADA: allowedv->push_back("dae"); break; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 38daff9937..891c0c0482 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -89,6 +89,7 @@ public: FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin FFLOAD_MATERIAL = 15, FFLOAD_MATERIAL_TEXTURE = 16, + FFLOAD_HDRI = 17, }; enum ESaveFilter diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index ce389a5cad..f9c5421866 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -38,6 +38,126 @@ #include "llviewercontrol.h" #include "llenvironment.h" #include "llstartup.h" +#include "llviewermenufile.h" +#include "llnotificationsutil.h" + + +// load an OpenEXR image from a file +#define IMATH_HALF_NO_LOOKUP_TABLE 1 +#include +#include +#include +#include +#include + +LLPointer gEXRImage; + +void load_exr(const std::string& filename) +{ + // reset reflection maps when previewing a new HDRI + gPipeline.mReflectionMapManager.reset(); + gPipeline.mReflectionMapManager.initReflectionMaps(); + + try { + Imf::InputFile file(filename.c_str()); + Imath::Box2i dw = file.header().dataWindow(); + int width = dw.max.x - dw.min.x + 1; + int height = dw.max.y - dw.min.y + 1; + + Imf::Array2D rPixels; + Imf::Array2D gPixels; + Imf::Array2D bPixels; + + rPixels.resizeErase(height, width); + gPixels.resizeErase(height, width); + bPixels.resizeErase(height, width); + + Imf::FrameBuffer frameBuffer; + + frameBuffer.insert("R", // name + Imf::Slice(Imf::HALF, // type + (char*)(&rPixels[0][0] - // base + dw.min.x - + dw.min.y * width), + sizeof(rPixels[0][0]) * 1, // xStride + sizeof(rPixels[0][0]) * width, // yStride + 1, 1, // x/y sampling + 0.0)); // fillValue + + frameBuffer.insert("G", // name + Imf::Slice(Imf::HALF, // type + (char*)(&gPixels[0][0] - // base + dw.min.x - + dw.min.y * width), + sizeof(gPixels[0][0]) * 1, // xStride + sizeof(gPixels[0][0]) * width, // yStride + 1, 1, // x/y sampling + 0.0)); // fillValue + + frameBuffer.insert("B", // name + Imf::Slice(Imf::HALF, // type + (char*)(&bPixels[0][0] - // base + dw.min.x - + dw.min.y * width), + sizeof(bPixels[0][0]) * 1, // xStride + sizeof(bPixels[0][0]) * width, // yStride + 1, 1, // x/y sampling + FLT_MAX)); // fillValue + + file.setFrameBuffer(frameBuffer); + file.readPixels(dw.min.y, dw.max.y); + + U32 texName = 0; + LLImageGL::generateTextures(1, &texName); + + gEXRImage = new LLImageGL(texName, 4, GL_TEXTURE_2D, GL_RGB16F, GL_RGB16F, GL_FLOAT, LLTexUnit::TAM_CLAMP); + gEXRImage->setHasMipMaps(TRUE); + gEXRImage->setUseMipMaps(TRUE); + gEXRImage->setFilteringOption(LLTexUnit::TFO_TRILINEAR); + + gGL.getTexUnit(0)->bind(gEXRImage); + + std::vector data(width * height * 3); + for (int i = 0; i < width * height; ++i) + { + data[i * 3 + 0] = rPixels[i / width][i % width]; + data[i * 3 + 1] = gPixels[i / width][i % width]; + data[i * 3 + 2] = bPixels[i / width][i % width]; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data.data()); + + glGenerateMipmap(GL_TEXTURE_2D); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + } + catch (const std::exception& e) { + LLSD notif_args; + notif_args["WHAT"] = filename; + notif_args["REASON"] = e.what(); + LLNotificationsUtil::add("CannotLoad", notif_args); + return; + } +} + +void hdri_preview() +{ + LLFilePickerReplyThread::startPicker( + [](const std::vector& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter) + { + if (LLAppViewer::instance()->quitRequested()) + { + return; + } + if (filenames.size() > 0) + { + load_exr(filenames[0]); + } + }, + LLFilePicker::FFLOAD_HDRI, + true); +} extern BOOL gCubeSnapshot; extern BOOL gTeleportDisplay; @@ -133,6 +253,11 @@ void LLReflectionMapManager::update() return; } + if (mPaused && gFrameTimeSeconds > mResumeTime) + { + resume(); + } + initReflectionMaps(); if (!mRenderTarget.isComplete()) @@ -831,9 +956,10 @@ void LLReflectionMapManager::reset() mReset = true; } -void LLReflectionMapManager::pause() +void LLReflectionMapManager::pause(F32 duration) { mPaused = true; + mResumeTime = gFrameTimeSeconds + duration; } void LLReflectionMapManager::resume() @@ -1283,6 +1409,8 @@ void LLReflectionMapManager::initReflectionMaps() if (mTexture.isNull() || mReflectionProbeCount != count || mReset) { + gEXRImage = nullptr; + mReset = false; mReflectionProbeCount = count; mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512)); @@ -1340,7 +1468,6 @@ void LLReflectionMapManager::initReflectionMaps() mDefaultProbe->mComplete = default_complete; touch_default_probe(mDefaultProbe); - } if (mVertexBuffer.isNull()) diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 0fee99eefc..5c0651bc24 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -87,7 +87,8 @@ public: void reset(); // pause all updates other than the default probe - void pause(); + // duration - number of seconds to pause (default 10) + void pause(F32 duration = 10.f); // unpause (see pause) void resume(); @@ -208,5 +209,6 @@ private: // if true, only update the default probe bool mPaused = false; + F32 mResumeTime = 0.f; }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d5e4de03a9..c50ae2e153 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7890,6 +7890,19 @@ class LLAdvancedClickRenderBenchmark: public view_listener_t } }; +void hdri_preview(); + +class LLAdvancedClickHDRIPreview: public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + // open personal lighting floater when previewing an HDRI (keeps HDRI from implicitly unloading when opening build tools) + LLFloaterReg::showInstance("env_adjust_snapshot"); + hdri_preview(); + return true; + } +}; + // these are used in the gl menus to set control values that require shader recompilation class LLToggleShaderControl : public view_listener_t { @@ -9529,6 +9542,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption"); view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); + view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview"); view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 354cc79036..dc20f035c9 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -201,6 +201,7 @@ LLGLSLShader gLuminanceProgram; LLGLSLShader gFXAAProgram; LLGLSLShader gDeferredPostNoDoFProgram; LLGLSLShader gDeferredWLSkyProgram; +LLGLSLShader gEnvironmentMapProgram; LLGLSLShader gDeferredWLCloudProgram; LLGLSLShader gDeferredWLSunProgram; LLGLSLShader gDeferredWLMoonProgram; @@ -315,6 +316,7 @@ void LLViewerShaderMgr::finalizeShaderList() mShaderList.push_back(&gDeferredEmissiveProgram); mShaderList.push_back(&gDeferredAvatarEyesProgram); mShaderList.push_back(&gDeferredAvatarAlphaProgram); + mShaderList.push_back(&gEnvironmentMapProgram); mShaderList.push_back(&gDeferredWLSkyProgram); mShaderList.push_back(&gDeferredWLCloudProgram); mShaderList.push_back(&gDeferredWLMoonProgram); @@ -987,6 +989,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gNoPostGammaCorrectProgram.unload(); gLegacyPostGammaCorrectProgram.unload(); gFXAAProgram.unload(); + gEnvironmentMapProgram.unload(); gDeferredWLSkyProgram.unload(); gDeferredWLCloudProgram.unload(); gDeferredWLSunProgram.unload(); @@ -2268,6 +2271,26 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } + if (success) + { + gEnvironmentMapProgram.mName = "Environment Map Program"; + gEnvironmentMapProgram.mShaderFiles.clear(); + gEnvironmentMapProgram.mFeatures.calculatesAtmospherics = true; + gEnvironmentMapProgram.mFeatures.hasAtmospherics = true; + gEnvironmentMapProgram.mFeatures.hasGamma = true; + gEnvironmentMapProgram.mFeatures.hasSrgb = true; + + gEnvironmentMapProgram.clearPermutations(); + gEnvironmentMapProgram.addPermutation("HAS_HDRI", "1"); + gEnvironmentMapProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER)); + gEnvironmentMapProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER)); + gEnvironmentMapProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gEnvironmentMapProgram.mShaderGroup = LLGLSLShader::SG_SKY; + + success = gEnvironmentMapProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) { gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 2502be6bb1..c51f583ebc 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -266,6 +266,7 @@ extern LLGLSLShader gHUDFullbrightAlphaMaskAlphaProgram; extern LLGLSLShader gDeferredEmissiveProgram; extern LLGLSLShader gDeferredAvatarEyesProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; +extern LLGLSLShader gEnvironmentMapProgram; extern LLGLSLShader gDeferredWLSkyProgram; extern LLGLSLShader gDeferredWLCloudProgram; extern LLGLSLShader gDeferredWLSunProgram; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index fee00eb6f4..35e45c6cd9 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5233,9 +5233,6 @@ U32 LLVOAvatar::renderRigid() return 0; } - bool should_alpha_mask = shouldAlphaMask(); - LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 94ec5c0817..7809129743 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6869,6 +6869,8 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool } } +extern LLPointer gEXRImage; + void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { dst->bindTarget(); // gamma correct lighting @@ -6905,8 +6907,10 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { F32 e = llclamp(exposure(), 0.5f, 4.f); static LLStaticHashedString s_exposure("exposure"); + static LLStaticHashedString aces_mix("aces_mix"); shader.uniform1f(s_exposure, e); + shader.uniform1f(aces_mix, gEXRImage.notNull() ? 0.f : 0.3f); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 4719b091ab..591b5537c7 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2824,6 +2824,12 @@ function="World.EnvPreset" + + + fail + + Unable to load [WHAT]. + [REASON] + fail + + Date: Fri, 8 Mar 2024 15:13:35 -0800 Subject: secondlife/viewer#712: Consolidate accesses to texture_detail_* and material_detail_* controls --- indra/newview/llfloaterregioninfo.cpp | 40 +++++++++++++---------------------- indra/newview/llfloaterregioninfo.h | 3 +++ 2 files changed, 18 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index c6d8317128..f71cbf61fc 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1324,9 +1324,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - std::string buffer; - buffer = llformat("texture_detail_%d", i); - LLTextureCtrl* texture_ctrl = findChild(buffer); + LLTextureCtrl* texture_ctrl = mTextureDetailCtrl[i]; if (!texture_ctrl) continue; LLUUID image_asset_id = texture_ctrl->getImageAssetID(); @@ -1418,11 +1416,13 @@ BOOL LLPanelRegionTerrainInfo::postBuild() { buffer = llformat("texture_detail_%d", i); initCtrl(buffer); + mTextureDetailCtrl[i] = findChild(buffer); } for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { buffer = llformat("material_detail_%d", i); initCtrl(buffer); + mMaterialDetailCtrl[i] = findChild(buffer); } for(S32 i = 0; i < CORNER_COUNT; ++i) @@ -1457,12 +1457,9 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() const bool show_material_controls = material_type == LLTerrainMaterials::Type::PBR; // Toggle visibility of correct swatches - std::string buffer; - LLTextureCtrl* texture_ctrl; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("texture_detail_%d", i); - texture_ctrl = findChild(buffer); + LLTextureCtrl* texture_ctrl = mTextureDetailCtrl[i]; if (texture_ctrl) { texture_ctrl->setVisible(show_texture_controls); @@ -1470,11 +1467,10 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() } for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("material_detail_%d", i); - texture_ctrl = findChild(buffer); - if (texture_ctrl) + LLTextureCtrl* material_ctrl = mMaterialDetailCtrl[i]; + if (material_ctrl) { - texture_ctrl->setVisible(show_material_controls); + material_ctrl->setVisible(show_material_controls); } } @@ -1538,14 +1534,11 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) mMaterialTypeCtrl->setVisible(feature_pbr_terrain_enabled); } - LLTextureCtrl* asset_ctrl; - std::string buffer; if (set_texture_swatches) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("texture_detail_%d", i); - asset_ctrl = findChild(buffer); + LLTextureCtrl* asset_ctrl = mTextureDetailCtrl[i]; if(asset_ctrl) { LL_DEBUGS() << "Detail Texture " << i << ": " @@ -1559,8 +1552,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("material_detail_%d", i); - asset_ctrl = findChild(buffer); + LLTextureCtrl* asset_ctrl = mMaterialDetailCtrl[i]; if(asset_ctrl) { LL_DEBUGS() << "Detail Material " << i << ": " @@ -1574,8 +1566,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("texture_detail_%d", i); - asset_ctrl = findChild(buffer); + LLTextureCtrl* asset_ctrl = mTextureDetailCtrl[i]; if(asset_ctrl) { asset_ctrl->setImageAssetID(mLastSetTextures[i]); @@ -1586,8 +1577,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("material_detail_%d", i); - asset_ctrl = findChild(buffer); + LLTextureCtrl* asset_ctrl = mMaterialDetailCtrl[i]; if(asset_ctrl) { asset_ctrl->setImageAssetID(mLastSetMaterials[i]); @@ -1595,6 +1585,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) } } + std::string buffer; for(S32 i = 0; i < CORNER_COUNT; ++i) { buffer = llformat("height_start_spin_%d", i); @@ -1661,7 +1652,6 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() } } - LLTextureCtrl* asset_ctrl; std::string id_str; LLMessageSystem* msg = gMessageSystem; @@ -1670,15 +1660,15 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() const LLTerrainMaterials::Type material_type = mMaterialTypeCtrl ? material_type_from_ctrl(mMaterialTypeCtrl) : LLTerrainMaterials::Type::TEXTURE; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { + LLTextureCtrl* asset_ctrl; if (material_type == LLTerrainMaterials::Type::PBR) { - buffer = llformat("material_detail_%d", i); + asset_ctrl = mMaterialDetailCtrl[i]; } else { - buffer = llformat("texture_detail_%d", i); + asset_ctrl = mTextureDetailCtrl[i]; } - asset_ctrl = findChild(buffer); if (!asset_ctrl) { continue; } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index a38344c861..99774e5db3 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -56,6 +56,7 @@ class LLRadioGroup; class LLSliderCtrl; class LLSpinCtrl; class LLTextBox; +class LLTextureCtrl; class LLPanelRegionGeneralInfo; class LLPanelRegionDebugInfo; @@ -273,6 +274,8 @@ private: bool mConfirmedTextureHeights; bool mAskedTextureHeights; LLCheckBoxCtrl* mMaterialTypeCtrl = nullptr; + LLTextureCtrl* mTextureDetailCtrl[LLTerrainMaterials::ASSET_COUNT]; + LLTextureCtrl* mMaterialDetailCtrl[LLTerrainMaterials::ASSET_COUNT]; LLUUID mLastSetTextures[LLTerrainMaterials::ASSET_COUNT]; LLUUID mLastSetMaterials[LLTerrainMaterials::ASSET_COUNT]; }; -- cgit v1.2.3 From b84d76e243ed54b1d7db6401b78ce9122714b6e4 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 8 Mar 2024 16:29:00 -0800 Subject: secondlife/viewer#712: Slightly improved logging in refreshFromRegion --- indra/newview/llfloaterregioninfo.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index f71cbf61fc..454842999d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1541,7 +1541,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LLTextureCtrl* asset_ctrl = mTextureDetailCtrl[i]; if(asset_ctrl) { - LL_DEBUGS() << "Detail Texture " << i << ": " + LL_DEBUGS("Terrain", "Texture") << "Detail Texture " << i << ": " << compp->getDetailAssetID(i) << LL_ENDL; LLUUID tmp_id(compp->getDetailAssetID(i)); asset_ctrl->setImageAssetID(tmp_id); @@ -1555,7 +1555,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LLTextureCtrl* asset_ctrl = mMaterialDetailCtrl[i]; if(asset_ctrl) { - LL_DEBUGS() << "Detail Material " << i << ": " + LL_DEBUGS("Terrain", "Material") << "Detail Material " << i << ": " << compp->getDetailAssetID(i) << LL_ENDL; LLUUID tmp_id(compp->getDetailAssetID(i)); asset_ctrl->setImageAssetID(tmp_id); @@ -1566,6 +1566,8 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { + LL_DEBUGS("Terrain", "Texture") << "Reset Texture swatch " << i + << LL_ENDL; LLTextureCtrl* asset_ctrl = mTextureDetailCtrl[i]; if(asset_ctrl) { @@ -1577,6 +1579,8 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { + LL_DEBUGS("Terrain", "Material") << "Reset Material swatch " << i + << LL_ENDL; LLTextureCtrl* asset_ctrl = mMaterialDetailCtrl[i]; if(asset_ctrl) { -- cgit v1.2.3 From 457b720fd9b2ced6f288d4bbc71045cefaed4a49 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 12 Mar 2024 14:26:21 -0500 Subject: #965 Fix for EEP skies being too bright --- indra/newview/app_settings/shaders/class1/deferred/skyF.glsl | 7 ++++--- .../newview/app_settings/shaders/class3/deferred/softenLightF.glsl | 5 +++-- indra/newview/lldrawpoolwlsky.cpp | 3 --- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index cc5280d929..596e9321e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -86,7 +86,9 @@ void main() pos = env_mat * pos; vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI); vec3 color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale; - color = min(color, vec3(8192*8192*16)); + color = min(color, vec3(8192*8192*16)); // stupidly large value arrived at by binary search -- avoids framebuffer corruption from some HDRIs + + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_HAS_HDRI); #else // Potential Fill-rate optimization. Add cloud calculation @@ -104,12 +106,11 @@ void main() color.rgb *= 2.; color.rgb = clamp(color.rgb, vec3(0), vec3(5)); + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); #endif frag_data[0] = vec4(0); frag_data[1] = vec4(0); - frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); frag_data[3] = vec4(color.rgb, 1.0); - } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 5cc7ea698a..9b9739ba22 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -191,11 +191,12 @@ void main() } else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI)) { + // actual HDRI sky, just copy color value color = texture(emissiveRect, tc).rgb; } - else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS)) + else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS)) { - //should only be true of WL sky, just port over base color value + //should only be true of WL sky, port over base color value and scale for fake HDR color = texture(emissiveRect, tc).rgb; color = srgb_to_linear(color); color *= sky_hdr_scale; diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index a9cc138549..303916110c 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -470,8 +470,6 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) const F32 camHeightLocal = LLEnvironment::instance().getCamHeight(); - gGL.setColorMask(true, false); - LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); if (gPipeline.canUseWindLightShaders()) @@ -488,7 +486,6 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) renderSkyCloudsDeferred(origin, camHeightLocal, cloud_shader); } } - gGL.setColorMask(true, true); } -- cgit v1.2.3 From ab5ea5d13479c5a419c982433a1052bf3b2d8322 Mon Sep 17 00:00:00 2001 From: Brad Linden Date: Tue, 12 Mar 2024 16:49:20 -0700 Subject: secondlife/viewer#926 switching cmake config for mac openexr to use new static libs --- indra/cmake/Copy3rdPartyLibs.cmake | 6 ------ indra/newview/viewer_manifest.py | 6 ------ 2 files changed, 12 deletions(-) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 415641f65f..873253b419 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -190,12 +190,6 @@ elseif(DARWIN) liburiparser.dylib liburiparser.1.dylib liburiparser.1.0.27.dylib - libIex-3_2.dylib - libIlmThread-3_2.dylib - libImath-3_1.dylib - libOpenEXR-3_2.dylib - libOpenEXRCore-3_2.dylib - libOpenEXRUtil-3_2.dylib ) if (TARGET ll::fmodstudio) diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 70121ecc64..5258842b75 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -942,12 +942,6 @@ class Darwin_x86_64_Manifest(ViewerManifest): with self.prefix(src=relpkgdir, dst=""): self.path("libndofdev.dylib") self.path("libhunspell-*.dylib") - self.path("libIex-3_2.dylib") - self.path("libIlmThread-3_2.dylib") - self.path("libImath-3_1.dylib") - self.path("libOpenEXR-3_2.dylib") - self.path("libOpenEXRCore-3_2.dylib") - self.path("libOpenEXRUtil-3_2.dylib") with self.prefix(src_dst="cursors_mac"): self.path("*.tif") -- cgit v1.2.3 From 3d13a3733d5d4c960be3b519df9e70d6943f7bbe Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 13 Mar 2024 09:50:33 -0700 Subject: secondlife/viewer#906: Bump PBR terrain scale, decreasing texel density by 1/2 --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8420f32db8..aaab7f1d45 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10919,7 +10919,7 @@ Type F32 Value - 4.0 + 8.0 RenderTerrainPBRPlanarSampleCount -- cgit v1.2.3 From ef755235551d68b2790ed7c5363038f46a226306 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 13 Mar 2024 12:22:12 -0500 Subject: 983 add debug setting to control the maximum download resolution (#986) * Create RenderMaxTextureResolution.md * #983 Add RenderMaxTextureResolution setting. Incidental crash fix. --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llheroprobemanager.h | 4 ++-- indra/newview/llviewertexture.cpp | 10 +++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index aaab7f1d45..f248fac2ee 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9405,6 +9405,17 @@ U32 Value 16 + + RenderMaxTextureResolution + + Comment + Maximum texture resolution to download for non-boosted textures. + Persist + 1 + Type + U32 + Value + 2048 RenderDebugTextureBind diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 10b743ceef..13c12b5e55 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -581,7 +581,7 @@ bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) void LLHeroProbeManager::unregisterViewerObject(LLVOVolume* drawablep) { - std::vector::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); + std::vector>::iterator found_itr = std::find(mHeroVOList.begin(), mHeroVOList.end(), drawablep); if (found_itr != mHeroVOList.end()) { mHeroVOList.erase(found_itr); diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 04027cd57e..17e75a18d4 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -146,8 +146,8 @@ private: U32 mCurrentProbeUpdateFrame = 0; - std::vector mHeroVOList; - LLVOVolume* mNearestHero; + std::vector> mHeroVOList; + LLPointer mNearestHero; }; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8436159e14..9759b9a31b 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -3079,7 +3079,15 @@ void LLViewerLODTexture::processTextureStats() updateVirtualSize(); static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); - + + { // restrict texture resolution to download based on RenderMaxTextureResolution + static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); + // sanity clamp debug setting to avoid settings hack shenanigans + F32 tex_res = (F32)llclamp((S32)max_texture_resolution, 512, 2048); + tex_res *= tex_res; + mMaxVirtualSize = llmin(mMaxVirtualSize, tex_res); + } + if (textures_fullres) { mDesiredDiscardLevel = 0; -- cgit v1.2.3 From d909e7243861320b43634ab9cafd2bb5a8dc558b Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 13 Mar 2024 12:27:33 -0500 Subject: #975 Add RenderHDRISplitScreen debug setting (#976) * #975 Add RenderHDRISplitScreen debug setting * Create hdri_local_preview.md --- indra/newview/app_settings/settings.xml | 11 ++++ .../app_settings/shaders/class1/deferred/skyF.glsl | 60 ++++++++++++---------- .../app_settings/shaders/class1/deferred/skyV.glsl | 6 ++- indra/newview/lldrawpoolwlsky.cpp | 5 +- 4 files changed, 53 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f248fac2ee..a28ea7294c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9373,6 +9373,17 @@ Value 0.0 + RenderHDRISplitScreen + + Comment + What percentage of screen to render using HDRI vs EEP sky. + Persist + 1 + Type + F32 + Value + 1.0 + RenderMaxOpenGLVersion Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 596e9321e8..785c748234 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -28,8 +28,10 @@ in vec3 vary_HazeColor; in float vary_LightNormPosDot; #ifdef HAS_HDRI -in vec3 vary_position; +in vec4 vary_position; +in vec3 vary_rel_pos; uniform float sky_hdr_scale; +uniform float hdri_split_screen; uniform mat3 env_mat; uniform sampler2D environmentMap; #endif @@ -81,33 +83,39 @@ vec3 halo22(float d) void main() { + vec3 color; #ifdef HAS_HDRI - vec3 pos = normalize(vary_position); - pos = env_mat * pos; - vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI); - vec3 color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale; - color = min(color, vec3(8192*8192*16)); // stupidly large value arrived at by binary search -- avoids framebuffer corruption from some HDRIs - - frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_HAS_HDRI); -#else - - // Potential Fill-rate optimization. Add cloud calculation - // back in and output alpha of 0 (so that alpha culling kills - // the fragment) if the sky wouldn't show up because the clouds - // are fully opaque. - - vec3 color = vary_HazeColor; - - float rel_pos_lightnorm = vary_LightNormPosDot; - float optic_d = rel_pos_lightnorm; - vec3 halo_22 = halo22(optic_d); - color.rgb += rainbow(optic_d); - color.rgb += halo_22; - color.rgb *= 2.; - color.rgb = clamp(color.rgb, vec3(0), vec3(5)); - - frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); + vec3 frag_coord = vary_position.xyz/vary_position.w; + if (-frag_coord.x > ((1.0-hdri_split_screen)*2.0-1.0)) + { + vec3 pos = normalize(vary_rel_pos); + pos = env_mat * pos; + vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI); + color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale; + color = min(color, vec3(8192*8192*16)); // stupidly large value arrived at by binary search -- avoids framebuffer corruption from some HDRIs + + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_HAS_HDRI); + } + else #endif + { + // Potential Fill-rate optimization. Add cloud calculation + // back in and output alpha of 0 (so that alpha culling kills + // the fragment) if the sky wouldn't show up because the clouds + // are fully opaque. + + color = vary_HazeColor; + + float rel_pos_lightnorm = vary_LightNormPosDot; + float optic_d = rel_pos_lightnorm; + vec3 halo_22 = halo22(optic_d); + color.rgb += rainbow(optic_d); + color.rgb += halo_22; + color.rgb *= 2.; + color.rgb = clamp(color.rgb, vec3(0), vec3(5)); + + frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); + } frag_data[0] = vec4(0); frag_data[1] = vec4(0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index bbe9a5a838..e48f69dab5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -36,7 +36,8 @@ out vec3 vary_HazeColor; out float vary_LightNormPosDot; #ifdef HAS_HDRI -out vec3 vary_position; +out vec4 vary_position; +out vec3 vary_rel_pos; #endif // Inputs @@ -77,7 +78,8 @@ void main() vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); #ifdef HAS_HDRI - vary_position = rel_pos; + vary_rel_pos = rel_pos; + vary_position = pos; #endif // Adj position vector to clamp altitude diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 303916110c..323ab5fc07 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -153,12 +153,15 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca static LLCachedControl hdri_exposure(gSavedSettings, "RenderHDRIExposure", 0.0f); static LLCachedControl hdri_rotation(gSavedSettings, "RenderHDRIRotation", 0.f); - + static LLCachedControl hdri_split(gSavedSettings, "RenderHDRISplitScreen", 1.f); + static LLStaticHashedString hdri_split_screen("hdri_split_screen"); + LLMatrix3 rot; rot.setRot(0.f, hdri_rotation*DEG_TO_RAD, 0.f); sky_shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, powf(2.f, hdri_exposure)); sky_shader->uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, GL_FALSE, (F32*) rot.mMatrix); + sky_shader->uniform1f(hdri_split_screen, hdri_split); } else { -- cgit v1.2.3 From e42297fb1982a26ce23df14193e314aaa5a431b4 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 13 Mar 2024 16:11:49 -0700 Subject: secondlife/viewer#76: Change wording of terrain blending documentation when using materials --- indra/newview/llfloaterregioninfo.cpp | 13 ++++++++ .../skins/default/xui/en/panel_region_terrain.xml | 37 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 454842999d..6ad776643d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1479,6 +1479,19 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() if (texture_label) { texture_label->setVisible(show_texture_controls); } LLUICtrl* material_label = findChild("detail_material_text"); if (material_label) { material_label->setVisible(show_material_controls); } + + // Toggle visibility of documentation labels for terrain blending ranges + const std::vector doc_suffixes { "5", "10", "11" }; + std::string buffer; + for (const std::string& suffix : doc_suffixes) + { + buffer = "height_text_lbl" + suffix; + LLUICtrl* texture_doc_label = findChild(buffer); + if (texture_doc_label) { texture_doc_label->setVisible(show_texture_controls); } + buffer += "_material"; + LLUICtrl* material_doc_label = findChild(buffer); + if (material_doc_label) { material_doc_label->setVisible(show_material_controls); } + } } // virtual diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index f8d2c90d0a..38d885d72d 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -257,6 +257,19 @@ width="300"> Texture Elevation Ranges + + Material Elevation Ranges + These values represent the blend range for the textures above. + + These values represent the blend range for the materials above. + Measured in meters, the LOW value is the MAXIMUM height of Texture #1, and the HIGH value is the MINIMUM height of Texture #4. + + Measured in meters, the LOW value is the MAXIMUM height of Material #1, and the HIGH value is the MINIMUM height of Material #4. + Date: Wed, 13 Mar 2024 17:06:07 -0700 Subject: secondlife/viewer#988: Fix terrain composition label getting cut off --- indra/newview/skins/default/xui/de/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/es/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/fr/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/it/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/ja/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/pl/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/pt/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/ru/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/tr/panel_region_terrain.xml | 2 +- indra/newview/skins/default/xui/zh/panel_region_terrain.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/de/panel_region_terrain.xml b/indra/newview/skins/default/xui/de/panel_region_terrain.xml index 42ba5b5269..7738427fe3 100644 --- a/indra/newview/skins/default/xui/de/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/de/panel_region_terrain.xml @@ -10,7 +10,7 @@ - Terraintexturen (erfordert 24-Bit-.tga-Dateien mit einer Größe von 1024x1024) + Terraintexturen 1 (niedrig) diff --git a/indra/newview/skins/default/xui/es/panel_region_terrain.xml b/indra/newview/skins/default/xui/es/panel_region_terrain.xml index 9aba5299cb..5e6e89893e 100644 --- a/indra/newview/skins/default/xui/es/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/es/panel_region_terrain.xml @@ -12,7 +12,7 @@ del terreno" name="terrain_raise_spin"/> - Texturas del terreno (requiere archivos .tga de 1024x1024, 24 bits) + Texturas del terreno 1 (bajo) diff --git a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml index bbab00ca24..d99948804a 100644 --- a/indra/newview/skins/default/xui/fr/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/fr/panel_region_terrain.xml @@ -12,7 +12,7 @@ terrain" name="terrain_raise_spin"/> - Textures du terrain (fichiers .tga 1024 x 1024, 24 bit requis) + Textures du terrain 1 (Bas) diff --git a/indra/newview/skins/default/xui/it/panel_region_terrain.xml b/indra/newview/skins/default/xui/it/panel_region_terrain.xml index e08c55f63b..0583b4e02e 100644 --- a/indra/newview/skins/default/xui/it/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/it/panel_region_terrain.xml @@ -12,7 +12,7 @@ terreno" name="terrain_raise_spin"/> - Texture terreno (richiede file 1024x1024, 24 bit .tga) + Texture terreno 1 (basso) diff --git a/indra/newview/skins/default/xui/ja/panel_region_terrain.xml b/indra/newview/skins/default/xui/ja/panel_region_terrain.xml index 5470bd6e3b..11e8d0d169 100644 --- a/indra/newview/skins/default/xui/ja/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/ja/panel_region_terrain.xml @@ -10,7 +10,7 @@ - 地形テクスチャ(1024✕1024 の 24 bit .tga ファイル) + 地形テクスチャ 1(低) diff --git a/indra/newview/skins/default/xui/pl/panel_region_terrain.xml b/indra/newview/skins/default/xui/pl/panel_region_terrain.xml index 2d4286334f..c1dde04ff0 100644 --- a/indra/newview/skins/default/xui/pl/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/pl/panel_region_terrain.xml @@ -7,7 +7,7 @@ - Tekstury terenu (1024x1024, 24 bitowy plik .tga) + Tekstury terenu 1 (Nisko) diff --git a/indra/newview/skins/default/xui/pt/panel_region_terrain.xml b/indra/newview/skins/default/xui/pt/panel_region_terrain.xml index 1d312aeed9..92d6859882 100644 --- a/indra/newview/skins/default/xui/pt/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/pt/panel_region_terrain.xml @@ -12,7 +12,7 @@ terreno" name="terrain_raise_spin"/> - Texturas de terreno (exige arquivos .tga 1024x1024, 24 bit) + Texturas de terreno 1 (Baixo) diff --git a/indra/newview/skins/default/xui/ru/panel_region_terrain.xml b/indra/newview/skins/default/xui/ru/panel_region_terrain.xml index 76b4f513a8..2752d409cb 100644 --- a/indra/newview/skins/default/xui/ru/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/ru/panel_region_terrain.xml @@ -10,7 +10,7 @@ - Текстуры ландшафта (требования: 1024x1024, 24-битные, TGA) + Текстуры ландшафта 1 (Низ) diff --git a/indra/newview/skins/default/xui/tr/panel_region_terrain.xml b/indra/newview/skins/default/xui/tr/panel_region_terrain.xml index e25047301d..00560d4c5b 100644 --- a/indra/newview/skins/default/xui/tr/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/tr/panel_region_terrain.xml @@ -10,7 +10,7 @@ - Yüzey Dokuları (1024x1024, 24 bit .tga dosyalar gerektirir) + Yüzey Dokuları 1 (Düşük) diff --git a/indra/newview/skins/default/xui/zh/panel_region_terrain.xml b/indra/newview/skins/default/xui/zh/panel_region_terrain.xml index 81bce46876..8490eeaafc 100644 --- a/indra/newview/skins/default/xui/zh/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/zh/panel_region_terrain.xml @@ -10,7 +10,7 @@ - 地形材質(須 1024x1024,24 位元 .tga 檔格式) + 地形材質 1(低) -- cgit v1.2.3 From cb1b23d8bf72a0e2fe0fff8b430cf144501ca586 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 15 Mar 2024 10:45:53 -0700 Subject: secondlife/viewer#760: Fix terrain texture validator not respecting RenderMaxTextureResolution --- indra/newview/llfloaterregioninfo.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 6ad776643d..5de11d6699 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1321,7 +1321,8 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() if (is_material_selected) { return TRUE; } } - static const S32 MAX_TERRAIN_TEXTURE_SIZE = 1024; + static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); + const S32 max_terrain_texture_size = (S32)max_texture_resolution; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { LLTextureCtrl* texture_ctrl = mTextureDetailCtrl[i]; @@ -1341,19 +1342,19 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() LLSD args; args["TEXTURE_NUM"] = i+1; args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); - args["MAX_SIZE"] = MAX_TERRAIN_TEXTURE_SIZE; + args["MAX_SIZE"] = max_terrain_texture_size; LLNotificationsUtil::add("InvalidTerrainBitDepth", args); return FALSE; } - if (width > MAX_TERRAIN_TEXTURE_SIZE || height > MAX_TERRAIN_TEXTURE_SIZE) + if (width > max_terrain_texture_size || height > max_terrain_texture_size) { LLSD args; args["TEXTURE_NUM"] = i+1; args["TEXTURE_SIZE_X"] = width; args["TEXTURE_SIZE_Y"] = height; - args["MAX_SIZE"] = MAX_TERRAIN_TEXTURE_SIZE; + args["MAX_SIZE"] = max_terrain_texture_size; LLNotificationsUtil::add("InvalidTerrainSize", args); return FALSE; -- cgit v1.2.3 From faa0f3696465a1e3ab80a277d0aad09c0775e450 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 15 Mar 2024 16:19:42 -0700 Subject: secondlife/viewer#1006: Don't send terrain update if validation fails --- indra/newview/llfloaterregioninfo.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 5de11d6699..084ff98851 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1633,21 +1633,6 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) BOOL LLPanelRegionTerrainInfo::sendUpdate() { LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL; - std::string buffer; - strings_t strings; - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - - // update the model - LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); - region_info.mWaterHeight = (F32) getChild("water_height_spin")->getValue().asReal(); - region_info.mTerrainRaiseLimit = (F32) getChild("terrain_raise_spin")->getValue().asReal(); - region_info.mTerrainLowerLimit = (F32) getChild("terrain_lower_spin")->getValue().asReal(); - - // and sync the region with it - region_info.sendRegionTerrain(invoice); - - // ======================================= - // Assemble and send texturedetail message // Make sure user hasn't chosen wacky textures. if (!validateTextureSizes()) @@ -1670,6 +1655,22 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() } } + std::string buffer; + strings_t strings; + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + + // update the model + LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); + region_info.mWaterHeight = (F32) getChild("water_height_spin")->getValue().asReal(); + region_info.mTerrainRaiseLimit = (F32) getChild("terrain_raise_spin")->getValue().asReal(); + region_info.mTerrainLowerLimit = (F32) getChild("terrain_lower_spin")->getValue().asReal(); + + // and sync the region with it + region_info.sendRegionTerrain(invoice); + + // ======================================= + // Assemble and send texturedetail message + std::string id_str; LLMessageSystem* msg = gMessageSystem; -- cgit v1.2.3 From 7ae7f9554d794abc62d6162043d41ea2aada9316 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 15 Mar 2024 16:43:20 -0700 Subject: secondlife/viewer#1006: Prevent PBR terrain material swatches from being null. Default to blank material for now. --- indra/newview/llfloaterregioninfo.cpp | 3 ++- indra/newview/skins/default/xui/en/panel_region_terrain.xml | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 084ff98851..8c4b6fc857 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -62,6 +62,7 @@ #include "llfloaterreg.h" #include "llfloaterregiondebugconsole.h" #include "llfloatertelehub.h" +#include "llgltfmateriallist.h" #include "llinventorymodel.h" #include "lllineeditor.h" #include "llnamelistctrl.h" @@ -1394,7 +1395,7 @@ LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo() } for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - mLastSetMaterials[i] = LLUUID::null; + mLastSetMaterials[i] = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; } } diff --git a/indra/newview/skins/default/xui/en/panel_region_terrain.xml b/indra/newview/skins/default/xui/en/panel_region_terrain.xml index 38d885d72d..4a2c0d42b9 100644 --- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml +++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml @@ -161,7 +161,7 @@ left="10" name="material_detail_0" pick_type="material" - allow_no_texture="true" + default_image_id="968cbad0-4dad-d64e-71b5-72bf13ad051a" top_delta="0" width="100" /> Date: Mon, 18 Mar 2024 13:57:01 -0700 Subject: secondlife/viewer#1006: Move blank material constant to indra_constants.h --- indra/llcommon/indra_constants.cpp | 1 + indra/llcommon/indra_constants.h | 2 ++ indra/newview/llfloaterregioninfo.cpp | 2 +- indra/newview/llgltfmateriallist.cpp | 2 -- indra/newview/llgltfmateriallist.h | 2 -- indra/newview/llmaterialeditor.cpp | 2 +- indra/newview/llpanelface.cpp | 4 ++-- indra/newview/llselectmgr.cpp | 4 ++-- indra/newview/lltexturectrl.cpp | 10 +++++----- indra/newview/lltooldraganddrop.cpp | 4 ++-- 10 files changed, 16 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp index 9a0c565b06..39e232e480 100644 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp @@ -89,3 +89,4 @@ const LLUUID IMG_USE_BAKED_AUX1 ("9742065b-19b5-297c-858a-29711d539043"); const LLUUID IMG_USE_BAKED_AUX2 ("03642e83-2bd1-4eb9-34b4-4c47ed586d2d"); const LLUUID IMG_USE_BAKED_AUX3 ("edd51b77-fc10-ce7a-4b3d-011dfc349e4f"); +const LLUUID BLANK_MATERIAL_ASSET_ID ("968cbad0-4dad-d64e-71b5-72bf13ad051a"); diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index a16cfac2b9..a4b2efef98 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -236,6 +236,8 @@ LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_SPECULAR; LL_COMMON_API extern const LLUUID DEFAULT_OBJECT_NORMAL; LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL; +LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID; + // radius within which a chat message is fully audible const F32 CHAT_NORMAL_RADIUS = 20.f; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 8c4b6fc857..2ed0e4195a 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1395,7 +1395,7 @@ LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo() } for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - mLastSetMaterials[i] = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + mLastSetMaterials[i] = BLANK_MATERIAL_ASSET_ID; } } diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index a9216ae656..f07ea7ee4f 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -58,8 +58,6 @@ LLGLTFMaterialList::modify_queue_t LLGLTFMaterialList::sModifyQueue; LLGLTFMaterialList::apply_queue_t LLGLTFMaterialList::sApplyQueue; LLSD LLGLTFMaterialList::sUpdates; -const LLUUID LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID("968cbad0-4dad-d64e-71b5-72bf13ad051a"); - #ifdef SHOW_ASSERT // return true if given data is (probably) valid update message for ModifyMaterialParams capability static bool is_valid_update(const LLSD& data) diff --git a/indra/newview/llgltfmateriallist.h b/indra/newview/llgltfmateriallist.h index f1c4ce20f9..6eab86ff0a 100644 --- a/indra/newview/llgltfmateriallist.h +++ b/indra/newview/llgltfmateriallist.h @@ -40,8 +40,6 @@ class LLGLTFOverrideCacheEntry; class LLGLTFMaterialList { public: - static const LLUUID BLANK_MATERIAL_ASSET_ID; - LLGLTFMaterialList() {} diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index f939418893..b54617870c 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2124,7 +2124,7 @@ bool can_use_objects_material(LLSelectedTEGetMatData& func, const std::vectorsetDefaultImageAssetID(LLUUID::null); - pbr_ctrl->setBlankImageAssetID(LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID); + pbr_ctrl->setBlankImageAssetID(BLANK_MATERIAL_ASSET_ID); pbr_ctrl->setCommitCallback(boost::bind(&LLPanelFace::onCommitPbr, this, _2)); pbr_ctrl->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelPbr, this, _2)); pbr_ctrl->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectPbr, this, _2)); @@ -2029,7 +2029,7 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, { mVOInventoryListener = nullptr; } - if (!identical_pbr || pbr_id.isNull() || pbr_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID) + if (!identical_pbr || pbr_id.isNull() || pbr_id == BLANK_MATERIAL_ASSET_ID) { mAgentInventoryListener = nullptr; } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 620dcad760..a4c43d8ddc 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1782,7 +1782,7 @@ bool LLObjectSelection::applyRestrictedPbrMaterialToTEs(LLViewerInventoryItem* i LLUUID asset_id = item->getAssetUUID(); if (asset_id.isNull()) { - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } bool material_copied_all_faces = true; @@ -1987,7 +1987,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) asset_id = mItem->getAssetUUID(); if (asset_id.isNull()) { - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } } diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index d9001bc16a..91c2755ea5 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -230,7 +230,7 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID()); if (mInventoryPickType == PICK_MATERIAL - && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID + && mImageAssetID == BLANK_MATERIAL_ASSET_ID && itemp && itemp->getAssetUUID().isNull()) { item_id = inv_view->getUUID(); @@ -273,7 +273,7 @@ void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bo if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull()) { // If an inventory item has a null asset, consider it a valid blank material(gltf) - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } setImageID(asset_id, set_selection); } @@ -813,7 +813,7 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co } LLUUID loockup_id = asset_id; - if (mInventoryPickType == PICK_MATERIAL && loockup_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID) + if (mInventoryPickType == PICK_MATERIAL && loockup_id == BLANK_MATERIAL_ASSET_ID) { // default asset id means we are looking for an inventory item with a default asset UUID (null) loockup_id = LLUUID::null; @@ -908,7 +908,7 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) LLInventoryItem* itemp = gInventory.getItem(inv_view->getUUID()); if (mInventoryPickType == PICK_MATERIAL - && mImageAssetID == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID + && mImageAssetID == BLANK_MATERIAL_ASSET_ID && itemp && itemp->getAssetUUID().isNull()) { inventory_id = inv_view->getUUID(); @@ -2395,7 +2395,7 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) if (mInventoryPickType == PICK_MATERIAL && asset_id.isNull()) { // If an inventory material has a null asset, consider it a valid blank material(gltf) - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } setImageAssetID(asset_id); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 2a17882ff1..293c47bf73 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1282,7 +1282,7 @@ void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj, if (asset_id.isNull()) { // use blank material - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } hit_obj->setRenderMaterialID(hit_face, asset_id); @@ -1318,7 +1318,7 @@ void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj, if (asset_id.isNull()) { // use blank material - asset_id = LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID; + asset_id = BLANK_MATERIAL_ASSET_ID; } hit_obj->setRenderMaterialIDs(asset_id); -- cgit v1.2.3 From 7792e62d3c9e3f8b2a27e7e9cbbc8db2c584b682 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 19 Mar 2024 16:03:57 -0700 Subject: secondlife/viewer-issues#82: Don't allow transparent texture terrain --- indra/llimage/llimage.cpp | 22 ++++++++++++++++ indra/llimage/llimage.h | 2 ++ indra/newview/llfloaterregioninfo.cpp | 29 +++++++++++++++++++++- .../newview/skins/default/xui/en/notifications.xml | 26 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index acfc254b65..16609b60be 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -990,6 +990,28 @@ void LLImageRaw::verticalFlip() } +bool LLImageRaw::checkHasTransparentPixels() +{ + if (getComponents() != 4) + { + return false; + } + + U8* data = getData(); + U32 pixels = getWidth() * getHeight(); + + // check alpha channel for all 255 + for (U32 i = 0; i < pixels; ++i) + { + if (data[i * 4 + 3] != 255) + { + return true; + } + } + + return false; +} + bool LLImageRaw::optimizeAwayAlpha() { if (getComponents() == 4) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index fc8d62cc96..93b58b2356 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -210,6 +210,8 @@ public: void verticalFlip(); + // Returns true if the image is not fully opaque + bool checkHasTransparentPixels(); // if the alpha channel is all 100% opaque, delete it // returns true if alpha channel was deleted bool optimizeAwayAlpha(); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 8c4b6fc857..706f7cf943 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1330,7 +1330,7 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() if (!texture_ctrl) continue; LLUUID image_asset_id = texture_ctrl->getImageAssetID(); - LLViewerTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id); + LLViewerFetchedTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id); S32 components = img->getComponents(); // Must ask for highest resolution version's width. JC S32 width = img->getFullWidth(); @@ -1348,6 +1348,33 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() return FALSE; } + if (components == 4) + { + if (!img->hasSavedRawImage()) + { + // Raw image isn't loaded yet + // Assume it's invalid due to presence of alpha channel + LLSD args; + args["TEXTURE_NUM"] = i+1; + args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); + LLNotificationsUtil::add("InvalidTerrainAlphaNotFullyLoaded", args); + return FALSE; + } + // Slower path: Calculate alpha from raw image pixels (not needed + // for GLTF materials, which use alphaMode to determine + // transparency) + // Raw image is pretty much guaranteed to be saved due to the texture swatches + LLImageRaw* raw = img->getSavedRawImage(); + if (raw->checkHasTransparentPixels()) + { + LLSD args; + args["TEXTURE_NUM"] = i+1; + LLNotificationsUtil::add("InvalidTerrainAlpha", args); + return FALSE; + } + LL_WARNS() << "Terrain texture image in slot " << i << " with ID " << image_asset_id << " has alpha channel, but pixels are opaque. Is alpha being optimized away in the texture uploader?" << LL_ENDL; + } + if (width > max_terrain_texture_size || height > max_terrain_texture_size) { diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1a6cadf43e..c1e6e7b9f0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4008,6 +4008,32 @@ Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image fail + +Couldn't set region textures: +Terrain texture [TEXTURE_NUM] is not fully loaded, but is assumed to contain transparency due to a bit depth of [TEXTURE_BIT_DEPTH]. Transparency is not currently supported for terrain textures. + +If texture [TEXTURE_NUM] is opaque, wait for the texture to fully load and then click "Apply" again. + +Alpha is only supported for terrain materials (PBR Metallic Roughness), when alphaMode="MASK" and doubleSided=false. + fail + + + +Couldn't set region textures: +Terrain texture [TEXTURE_NUM] contains transparency. Transparency is not currently supported for terrain textures. + +Replace texture [TEXTURE_NUM] with an opaque RGB image, then click "Apply" again. + +Alpha is only supported for terrain materials (PBR Metallic Roughness), when alphaMode="MASK" and doubleSided=false. + fail + + Date: Wed, 20 Mar 2024 10:22:29 -0700 Subject: secondlife/viewer-issues#83: Disallow alpha blend/double sided from PBR terrain --- indra/newview/llfloaterregioninfo.cpp | 62 ++++++++++++++++++++++ indra/newview/llfloaterregioninfo.h | 1 + .../newview/skins/default/xui/en/notifications.xml | 40 ++++++++++++++ 3 files changed, 103 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 706f7cf943..65b4feba11 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1392,6 +1392,62 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() return TRUE; } +bool LLPanelRegionTerrainInfo::validateMaterials() +{ + if (mMaterialTypeCtrl) + { + const LLTerrainMaterials::Type material_type = material_type_from_ctrl(mMaterialTypeCtrl); + const bool is_texture_selected = material_type == LLTerrainMaterials::Type::TEXTURE; + if (is_texture_selected) { return true; } + } + + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + LLTextureCtrl* material_ctrl = mMaterialDetailCtrl[i]; + if (!material_ctrl) { continue; } + + const LLUUID& material_asset_id = material_ctrl->getImageAssetID(); + llassert(material_asset_id.notNull()); + if (material_asset_id.isNull()) { return false; } + const LLFetchedGLTFMaterial* material = gGLTFMaterialList.getMaterial(material_asset_id); + if (!material->isLoaded()) + { + if (material->isFetching()) + { + LLSD args; + args["MATERIAL_NUM"] = i + 1; + LLNotificationsUtil::add("InvalidTerrainMaterialNotLoaded", args); + } + else // Loading failed + { + LLSD args; + args["MATERIAL_NUM"] = i + 1; + LLNotificationsUtil::add("InvalidTerrainMaterialLoadFailed", args); + } + return false; + } + + if (material->mDoubleSided) + { + LLSD args; + args["MATERIAL_NUM"] = i + 1; + LLNotificationsUtil::add("InvalidTerrainMaterialDoubleSided", args); + return false; + } + if (material->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE && material->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_MASK) + { + LLSD args; + args["MATERIAL_NUM"] = i + 1; + const char* alpha_mode = material->getAlphaMode(); + args["MATERIAL_ALPHA_MODE"] = alpha_mode; + LLNotificationsUtil::add("InvalidTerrainMaterialAlphaMode", args); + return false; + } + } + + return true; +} + BOOL LLPanelRegionTerrainInfo::validateTextureHeights() { for (S32 i = 0; i < CORNER_COUNT; ++i) @@ -1668,6 +1724,12 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() return FALSE; } + // Prevent applying unsupported alpha blend/double-sided materials + if (!validateMaterials()) + { + return FALSE; + } + // Check if terrain Elevation Ranges are correct if (gSavedSettings.getBOOL("RegionCheckTextureHeights") && !validateTextureHeights()) { diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 99774e5db3..ac3a8fc717 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -254,6 +254,7 @@ public: void setEnvControls(bool available); // Whether environment settings are available for this region BOOL validateTextureSizes(); + bool validateMaterials(); BOOL validateTextureHeights(); //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c1e6e7b9f0..44807aa6c7 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4044,6 +4044,46 @@ Terrain texture [TEXTURE_NUM] is too large at [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y]. Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image then click "Apply" again. + +Couldn't set region materials: +Terrain material [MATERIAL_NUM] is not loaded. + +Wait for the material to load, or replace material [TEXTURE_NUM] with a valid material. + + + +Couldn't set region materials: +Terrain material [MATERIAL_NUM] failed to load. + +Replace material [TEXTURE_NUM] with a valid material. + + + +Couldn't set region materials: +Terrain material [MATERIAL_NUM] is double-sided. Double-sided materials are not currently supported for PBR terrain. + +Replace material [MATERIAL_NUM] with a material with doubleSided=false. + + + +Couldn't set region materials: +Terrain material [MATERIAL_NUM] is using the unsupported alphaMode="[MATERIAL_ALPHA_MODE]". + +Replace material [MATERIAL_NUM] with a material with alphaMode="OPAQUE" or alphaMode="MASK". + + Date: Wed, 20 Mar 2024 12:51:58 -0700 Subject: secondlife/viewer-issues#83, secondlife/viewer-issues#82: Mark texture/material terrain save notifications as unique, to prevent duplicates --- indra/newview/skins/default/xui/en/notifications.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 44807aa6c7..9f99a76bd0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4001,6 +4001,7 @@ Are you sure you want to return objects owned by [USER_NAME]? icon="alertmodal.tga" name="InvalidTerrainBitDepth" type="alertmodal"> + Couldn't set region textures: Terrain texture [TEXTURE_NUM] has an invalid bit depth of [TEXTURE_BIT_DEPTH]. @@ -4012,6 +4013,7 @@ Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image icon="alertmodal.tga" name="InvalidTerrainAlphaNotFullyLoaded" type="alertmodal"> + Couldn't set region textures: Terrain texture [TEXTURE_NUM] is not fully loaded, but is assumed to contain transparency due to a bit depth of [TEXTURE_BIT_DEPTH]. Transparency is not currently supported for terrain textures. @@ -4025,6 +4027,7 @@ Alpha is only supported for terrain materials (PBR Metallic Roughness), when alp icon="alertmodal.tga" name="InvalidTerrainAlpha" type="alertmodal"> + Couldn't set region textures: Terrain texture [TEXTURE_NUM] contains transparency. Transparency is not currently supported for terrain textures. @@ -4038,6 +4041,7 @@ Alpha is only supported for terrain materials (PBR Metallic Roughness), when alp icon="alertmodal.tga" name="InvalidTerrainSize" type="alertmodal"> + Couldn't set region textures: Terrain texture [TEXTURE_NUM] is too large at [TEXTURE_SIZE_X]x[TEXTURE_SIZE_Y]. @@ -4048,6 +4052,7 @@ Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image icon="alertmodal.tga" name="InvalidTerrainMaterialNotLoaded" type="alertmodal"> + Couldn't set region materials: Terrain material [MATERIAL_NUM] is not loaded. @@ -4058,6 +4063,7 @@ Wait for the material to load, or replace material [TEXTURE_NUM] with a valid ma icon="alertmodal.tga" name="InvalidTerrainMaterialLoadFailed" type="alertmodal"> + Couldn't set region materials: Terrain material [MATERIAL_NUM] failed to load. @@ -4068,6 +4074,7 @@ Replace material [TEXTURE_NUM] with a valid material. icon="alertmodal.tga" name="InvalidTerrainMaterialDoubleSided" type="alertmodal"> + Couldn't set region materials: Terrain material [MATERIAL_NUM] is double-sided. Double-sided materials are not currently supported for PBR terrain. @@ -4078,6 +4085,7 @@ Replace material [MATERIAL_NUM] with a material with doubleSided=false. icon="alertmodal.tga" name="InvalidTerrainMaterialAlphaMode" type="alertmodal"> + Couldn't set region materials: Terrain material [MATERIAL_NUM] is using the unsupported alphaMode="[MATERIAL_ALPHA_MODE]". -- cgit v1.2.3 From d21813786ae51ba62b906e648908f7feaf6bcb32 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 20 Mar 2024 13:14:43 -0700 Subject: secondlife/viewer-issues#83, secondlife/viewer-issues#82: Combine terrain save error notifications --- indra/newview/llfloaterregioninfo.cpp | 50 ++++++++++++++++++++--------------- indra/newview/llfloaterregioninfo.h | 2 +- 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 65b4feba11..aaae43bdc9 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1313,15 +1313,16 @@ void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) LLFloaterReg::showInstance("region_debug_console"); } -BOOL LLPanelRegionTerrainInfo::validateTextureSizes() +bool LLPanelRegionTerrainInfo::validateTextureSizes() { if (mMaterialTypeCtrl) { const LLTerrainMaterials::Type material_type = material_type_from_ctrl(mMaterialTypeCtrl); const bool is_material_selected = material_type == LLTerrainMaterials::Type::PBR; - if (is_material_selected) { return TRUE; } + if (is_material_selected) { return true; } } + bool valid = true; static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); const S32 max_terrain_texture_size = (S32)max_texture_resolution; for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) @@ -1345,7 +1346,8 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); args["MAX_SIZE"] = max_terrain_texture_size; LLNotificationsUtil::add("InvalidTerrainBitDepth", args); - return FALSE; + valid = false; + continue; } if (components == 4) @@ -1358,21 +1360,24 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() args["TEXTURE_NUM"] = i+1; args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); LLNotificationsUtil::add("InvalidTerrainAlphaNotFullyLoaded", args); - return FALSE; + valid = false; } - // Slower path: Calculate alpha from raw image pixels (not needed - // for GLTF materials, which use alphaMode to determine - // transparency) - // Raw image is pretty much guaranteed to be saved due to the texture swatches - LLImageRaw* raw = img->getSavedRawImage(); - if (raw->checkHasTransparentPixels()) + else { - LLSD args; - args["TEXTURE_NUM"] = i+1; - LLNotificationsUtil::add("InvalidTerrainAlpha", args); - return FALSE; + // Slower path: Calculate alpha from raw image pixels (not needed + // for GLTF materials, which use alphaMode to determine + // transparency) + // Raw image is pretty much guaranteed to be saved due to the texture swatches + LLImageRaw* raw = img->getSavedRawImage(); + if (raw->checkHasTransparentPixels()) + { + LLSD args; + args["TEXTURE_NUM"] = i+1; + LLNotificationsUtil::add("InvalidTerrainAlpha", args); + valid = false; + } + LL_WARNS() << "Terrain texture image in slot " << i << " with ID " << image_asset_id << " has alpha channel, but pixels are opaque. Is alpha being optimized away in the texture uploader?" << LL_ENDL; } - LL_WARNS() << "Terrain texture image in slot " << i << " with ID " << image_asset_id << " has alpha channel, but pixels are opaque. Is alpha being optimized away in the texture uploader?" << LL_ENDL; } if (width > max_terrain_texture_size || height > max_terrain_texture_size) @@ -1384,12 +1389,11 @@ BOOL LLPanelRegionTerrainInfo::validateTextureSizes() args["TEXTURE_SIZE_Y"] = height; args["MAX_SIZE"] = max_terrain_texture_size; LLNotificationsUtil::add("InvalidTerrainSize", args); - return FALSE; - + valid = false; } } - return TRUE; + return valid; } bool LLPanelRegionTerrainInfo::validateMaterials() @@ -1401,6 +1405,7 @@ bool LLPanelRegionTerrainInfo::validateMaterials() if (is_texture_selected) { return true; } } + bool valid = true; for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { LLTextureCtrl* material_ctrl = mMaterialDetailCtrl[i]; @@ -1424,7 +1429,8 @@ bool LLPanelRegionTerrainInfo::validateMaterials() args["MATERIAL_NUM"] = i + 1; LLNotificationsUtil::add("InvalidTerrainMaterialLoadFailed", args); } - return false; + valid = false; + continue; } if (material->mDoubleSided) @@ -1432,7 +1438,7 @@ bool LLPanelRegionTerrainInfo::validateMaterials() LLSD args; args["MATERIAL_NUM"] = i + 1; LLNotificationsUtil::add("InvalidTerrainMaterialDoubleSided", args); - return false; + valid = false; } if (material->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE && material->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_MASK) { @@ -1441,11 +1447,11 @@ bool LLPanelRegionTerrainInfo::validateMaterials() const char* alpha_mode = material->getAlphaMode(); args["MATERIAL_ALPHA_MODE"] = alpha_mode; LLNotificationsUtil::add("InvalidTerrainMaterialAlphaMode", args); - return false; + valid = false; } } - return true; + return valid; } BOOL LLPanelRegionTerrainInfo::validateTextureHeights() diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index ac3a8fc717..da17212016 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -253,7 +253,7 @@ public: bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator void setEnvControls(bool available); // Whether environment settings are available for this region - BOOL validateTextureSizes(); + bool validateTextureSizes(); bool validateMaterials(); BOOL validateTextureHeights(); -- cgit v1.2.3 From 294eaa3c57d97c74074330e1c4ac4d2903619757 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 20 Mar 2024 13:36:20 -0700 Subject: secondlife/viewer-issues#83: Add TODO/assert for deciding when to allow candidate future extensions on PBR terrain --- indra/llprimitive/llgltfmaterial.h | 11 +++++++++++ indra/newview/llfloaterregioninfo.cpp | 14 ++++++++++++++ 2 files changed, 25 insertions(+) (limited to 'indra') diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 02f62fb08c..d14ae6970b 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -129,6 +129,17 @@ public: bool mOverrideDoubleSided = false; bool mOverrideAlphaMode = false; + // *TODO: If/when we implement additional GLTF extensions, they may not be + // compatible with our GLTF terrain implementation. We may want to disallow + // materials with some features from being set on terrain, if their + // implementation on terrain is not compliant with the spec: + // - KHR_materials_transmission: Probably OK? + // - KHR_materials_ior: Probably OK? + // - KHR_materials_volume: Likely incompatible, as our terrain + // heightmaps cannot currently be described as finite enclosed + // volumes. + // See also LLPanelRegionTerrainInfo::validateMaterials + // get a UUID based on a hash of this LLGLTFMaterial LLUUID getHash() const; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index aaae43bdc9..98656d6a58 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1405,6 +1405,20 @@ bool LLPanelRegionTerrainInfo::validateMaterials() if (is_texture_selected) { return true; } } + // *TODO: If/when we implement additional GLTF extensions, they may not be + // compatible with our GLTF terrain implementation. We may want to disallow + // materials with some features from being set on terrain, if their + // implementation on terrain is not compliant with the spec: + // - KHR_materials_transmission: Probably OK? + // - KHR_materials_ior: Probably OK? + // - KHR_materials_volume: Likely incompatible, as our terrain + // heightmaps cannot currently be described as finite enclosed + // volumes. + // See also LLGLTFMaterial +#ifdef LL_WINDOWS + llassert(sizeof(LLGLTFMaterial) == 232); +#endif + bool valid = true; for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { -- cgit v1.2.3 From 96933d05ec8af6e9b5e8cee11c18232027e74ff5 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 20 Mar 2024 17:07:44 -0700 Subject: secondlife/viewer#1027: Fix noise on transparent PBR materials on minimap --- indra/newview/llvlcomposition.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'indra') diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 506ab005c5..6b42804a90 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -42,6 +42,8 @@ #include "llviewercontrol.h" +extern LLColor4U MAX_WATER_COLOR; + static const U32 BASE_SIZE = 128; F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac) @@ -480,6 +482,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, LLViewerFetchedTexture* tex_emissive; // Can be null bool has_base_color_factor; bool has_emissive_factor; + bool has_alpha; LLColor3 base_color_factor; LLColor3 emissive_factor; if (use_textures) @@ -488,6 +491,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, tex_emissive = nullptr; has_base_color_factor = false; has_emissive_factor = false; + has_alpha = false; llassert(tex); } else @@ -504,6 +508,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, has_emissive_factor = (emissive_factor.mV[VX] != 1.f || emissive_factor.mV[VY] != 1.f || emissive_factor.mV[VZ] != 1.f); + has_alpha = mDetailMaterials[i]->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE; } if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } @@ -588,11 +593,21 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, } if (has_base_color_factor || raw_emissive || + has_alpha || tex->getWidth(ddiscard) != BASE_SIZE || tex->getHeight(ddiscard) != BASE_SIZE || tex->getComponents() != 3) { LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); + if (has_alpha) + { + // Approximate the water underneath terrain alpha with solid water color + newraw->clear( + MAX_WATER_COLOR.mV[VX], + MAX_WATER_COLOR.mV[VY], + MAX_WATER_COLOR.mV[VZ], + 255); + } newraw->composite(mRawImages[i]); if (has_base_color_factor) { -- cgit v1.2.3 From aa687c002b8258a75bfd657a220a4349da073038 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 22 Mar 2024 16:46:04 +0200 Subject: viewer-issues#85: update advanced graphics preferences UI layout --- .../xui/en/floater_preferences_graphics_advanced.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'indra') 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 bc237322af..a3b18563d0 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 @@ -534,7 +534,7 @@ layout="topleft" left="420" name="TransparentWater" - top_delta="16" + top_delta="18" width="300"> @@ -555,7 +555,7 @@ max_val="128" name="SkyMeshDetail" show_text="false" - top_delta="16" + top_delta="22" width="260"> @@ -597,7 +597,7 @@ layout="topleft" left="420" name="UseDoF" - top_delta="16" + top_delta="20" width="240"> @@ -612,7 +612,7 @@ left="420" name="RenderShadowDetailText" text_readonly_color="LabelDisabledColor" - top_delta="16" + top_delta="22" width="128"> Shadows: @@ -646,7 +646,7 @@ layout="topleft" left="420" name="ScreenSpaceReflections" - top_delta="16" + top_delta="24" width="240"> @@ -661,7 +661,7 @@ left="420" name="ReflectionDetailText" text_readonly_color="LabelDisabledColor" - top_delta="16" + top_delta="22" width="128"> Reflection Detail: @@ -697,7 +697,7 @@ left="420" name="ReflectionProbeText" text_readonly_color="LabelDisabledColor" - top_delta="16" + top_delta="22" width="128"> Reflection Coverage: @@ -743,7 +743,7 @@ max_val="1.5" name="RenderExposure" show_text="true" - top_delta="20" + top_delta="24" width="260"> -- cgit v1.2.3 From 0b159ef78175ab5ff1429aada0abc0c9dd232ea4 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 25 Mar 2024 15:40:43 -0500 Subject: https://github.com/secondlife/jira-archive-internal/issues/71091 Fix for divide by zero when alpha masking a PBR material with 0 alpha. (#1044) --- indra/newview/llfetchedgltfmaterial.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 97b959e5cb..1ca7ffaec1 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -76,7 +76,14 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) { // dividing the alpha cutoff by transparency here allows the shader to compare against // the alpha value of the texture without needing the transparency value - min_alpha = mAlphaCutoff/mBaseColor.mV[3]; + if (mBaseColor.mV[3] > 0.f) + { + min_alpha = mAlphaCutoff / mBaseColor.mV[3]; + } + else + { + min_alpha = 1024.f; + } } shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha); } -- cgit v1.2.3 From d1278d33ff6a47fb4102f1bfad35c5758359e975 Mon Sep 17 00:00:00 2001 From: cosmic-linden <111533034+cosmic-linden@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:47:01 -0700 Subject: viewer#1051: Fix UI typos in PBR terrain error messages (#1052) --- indra/newview/skins/default/xui/en/notifications.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 9f99a76bd0..8769ac9b95 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4056,7 +4056,7 @@ Replace texture [TEXTURE_NUM] with an RGB [MAX_SIZE]x[MAX_SIZE] or smaller image Couldn't set region materials: Terrain material [MATERIAL_NUM] is not loaded. -Wait for the material to load, or replace material [TEXTURE_NUM] with a valid material. +Wait for the material to load, or replace material [MATERIAL_NUM] with a valid material. Date: Tue, 26 Mar 2024 13:47:56 -0700 Subject: secondlife/viewer#1050: Fix mirror clipping for PBR terrain. Also fixes environment settings for PBR terrain. --- indra/newview/llviewershadermgr.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index dc20f035c9..65b1fee54b 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -331,6 +331,7 @@ void LLViewerShaderMgr::finalizeShaderList() mShaderList.push_back(&gDeferredPBROpaqueProgram); mShaderList.push_back(&gDeferredAvatarProgram); mShaderList.push_back(&gDeferredTerrainProgram); + mShaderList.push_back(&gDeferredPBRTerrainProgram); mShaderList.push_back(&gDeferredDiffuseAlphaMaskProgram); mShaderList.push_back(&gDeferredNonIndexedDiffuseAlphaMaskProgram); mShaderList.push_back(&gDeferredTreeProgram); -- cgit v1.2.3 From 617436b7cb9a574c08e49974046c330da1b706e0 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 28 Mar 2024 14:06:11 -0500 Subject: #1046 Tweak auto-exposure to not underexpose bright scenes (#1084) --- indra/newview/app_settings/settings.xml | 11 +++++++++++ .../shaders/class1/deferred/luminanceF.glsl | 18 +++++++++++++++++- .../class1/deferred/postDeferredGammaCorrect.glsl | 12 +++++++++++- indra/newview/pipeline.cpp | 12 ++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a28ea7294c..a988c515ce 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10832,6 +10832,17 @@ F32 Value 0.5 + + RenderDiffuseLuminanceScale + + Comment + Luminance adjustment for diffuse surfaces to aid auto-exposure behavior + Persist + 0 + Type + F32 + Value + 0.5 RenderShaderLODThreshold diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index c8afacf9bb..95b2f80e06 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -34,6 +34,8 @@ in vec2 vary_fragcoord; uniform sampler2D diffuseRect; uniform sampler2D emissiveRect; +uniform sampler2D normalMap; +uniform float diffuse_luminance_scale; float lum(vec3 col) { @@ -45,7 +47,21 @@ void main() { vec2 tc = vary_fragcoord*0.6+0.2; tc.y -= 0.1; // HACK - nudge exposure sample down a little bit to favor ground over sky - vec3 c = texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb; + vec3 c = texture(diffuseRect, tc).rgb; + + vec4 norm = texture(normalMap, tc); + + if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI) && + !GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS)) + { + // Apply the diffuse luminance scale to objects but not the sky + // Prevents underexposing when looking at bright environments + // while still allowing for realistically bright skies. + c *= diffuse_luminance_scale; + } + + c += texture(emissiveRect, tc).rgb; + float L = lum(c); frag_color = vec4(max(L, 0.0)); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index d89377326e..1629ed91c8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -153,6 +153,15 @@ float noise(vec2 x) { //============================= +void debugExposure(inout vec3 color) +{ + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + exp_scale *= 0.5; + if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1) + { + color = vec3(1,0,0); + } +} vec3 legacyGamma(vec3 color) { @@ -181,7 +190,8 @@ void main() vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y); vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb)); diff.rgb += nz*0.003; - + + //debugExposure(diff.rgb); frag_color = max(diff, vec4(0)); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7809129743..ef6e7c3994 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6759,6 +6759,8 @@ void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) gLuminanceProgram.bind(); + static LLCachedControl diffuse_luminance_scale(gSavedSettings, "RenderDiffuseLuminanceScale", 1.0f); + S32 channel = 0; channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); if (channel > -1) @@ -6772,6 +6774,16 @@ void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) mGlow[1].bindTexture(0, channel); } + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_NORMAL); + if (channel > -1) + { + // bind the normal map to get the environment mask + mRT->deferredScreen.bindTexture(2, channel, LLTexUnit::TFO_POINT); + } + + static LLStaticHashedString diffuse_luminance_scale_s("diffuse_luminance_scale"); + gLuminanceProgram.uniform1f(diffuse_luminance_scale_s, diffuse_luminance_scale); + mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); dst->flush(); -- cgit v1.2.3 From 43e605b8339105151fa7e97b27359d87479a3461 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Thu, 28 Mar 2024 16:07:09 -0500 Subject: #731 Fix for divide by zero when haze density set to zero (#1085) --- indra/newview/app_settings/shaders/class1/deferred/skyV.glsl | 2 +- .../app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index e48f69dab5..24d2db2183 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -108,7 +108,7 @@ void main() vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights - vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density)); + vec3 combined_haze = max(abs(blue_density) + vec3(abs(haze_density)), vec3(1e-6)); vec3 blue_weight = blue_density / combined_haze; vec3 haze_weight = haze_density / combined_haze; diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 8769cc0239..40b7f9cf0e 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -66,7 +66,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou // I had thought blue_density and haze_density should have equal weighting, // but attenuation due to haze_density tends to seem too strong - vec3 combined_haze = blue_density + vec3(haze_density); + vec3 combined_haze = max(blue_density + vec3(haze_density), vec3(1e-6)); vec3 blue_weight = blue_density / combined_haze; vec3 haze_weight = vec3(haze_density) / combined_haze; -- cgit v1.2.3 From 18ef2e3b2ba5a6f0ac397fe6f0652c5b55bdaea8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 29 Mar 2024 01:30:16 +0200 Subject: viewer#1081 Account for 2K texture upload price in material and texture upload --- indra/newview/llagentbenefits.cpp | 11 +++- indra/newview/llagentbenefits.h | 4 ++ indra/newview/llfloaterimagepreview.cpp | 21 +++++++ indra/newview/llfloaterimagepreview.h | 16 ++--- indra/newview/llfloaternamedesc.h | 2 +- indra/newview/llmaterialeditor.cpp | 69 ++++++++++++++++++---- indra/newview/llpanelmaininventory.cpp | 4 -- indra/newview/llviewermenu.cpp | 4 +- indra/newview/llviewermenufile.cpp | 48 ++++++++++++--- .../skins/default/xui/en/menu_inventory_add.xml | 2 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 2 +- 11 files changed, 143 insertions(+), 40 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp index 2d219735a0..7362082029 100644 --- a/indra/newview/llagentbenefits.cpp +++ b/indra/newview/llagentbenefits.cpp @@ -34,7 +34,8 @@ LLAgentBenefits::LLAgentBenefits(): m_group_membership_limit(-1), m_picks_limit(-1), m_sound_upload_cost(-1), - m_texture_upload_cost(-1) + m_texture_upload_cost(-1), + m_2k_texture_upload_cost(-1) { } @@ -94,6 +95,7 @@ bool LLAgentBenefits::init(const LLSD& benefits_sd) { return false; } + get_required_S32(benefits_sd, "large_texture_upload_cost", m_2k_texture_upload_cost); // FIXME PREMIUM - either use this field or get rid of it m_initalized = true; @@ -140,12 +142,17 @@ S32 LLAgentBenefits::getTextureUploadCost() const return m_texture_upload_cost; } +S32 LLAgentBenefits::get2KTextureUploadCost() const +{ + return m_2k_texture_upload_cost; +} + bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const { bool succ = false; if (asset_type == LLAssetType::AT_TEXTURE) { - cost = getTextureUploadCost(); + cost = getTextureUploadCost(); succ = true; } else if (asset_type == LLAssetType::AT_SOUND) diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h index 48aa6bd869..e3a03ba1ca 100644 --- a/indra/newview/llagentbenefits.h +++ b/indra/newview/llagentbenefits.h @@ -33,6 +33,8 @@ class LLAgentBenefits { public: + static constexpr S32 MIN_2K_TEXTURE_AREA = 1024 * 1024; + LLAgentBenefits(); ~LLAgentBenefits(); LOG_CLASS(LLAgentBenefits); @@ -47,6 +49,7 @@ public: S32 getPicksLimit() const; S32 getSoundUploadCost() const; S32 getTextureUploadCost() const; + S32 get2KTextureUploadCost() const; bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const; @@ -59,6 +62,7 @@ private: S32 m_picks_limit; S32 m_sound_upload_cost; S32 m_texture_upload_cost; + S32 m_2k_texture_upload_cost; bool m_initalized; }; diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index ba0f97e2e1..68dd7bfdd6 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -34,6 +34,7 @@ #include "llimagepng.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -144,6 +145,26 @@ BOOL LLFloaterImagePreview::postBuild() return TRUE; } + +//----------------------------------------------------------------------------- +// getExpectedUploadCost() +//----------------------------------------------------------------------------- +S32 LLFloaterImagePreview::getExpectedUploadCost() const +{ + if (mRawImagep.notNull()) + { + if (mRawImagep->getWidth() * mRawImagep->getHeight() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + return LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + } + else + { + return LLAgentBenefitsMgr::current().getTextureUploadCost(); + } + } + return 0; +} + //----------------------------------------------------------------------------- // LLFloaterImagePreview() //----------------------------------------------------------------------------- diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h index d034622c35..13e198426b 100644 --- a/indra/newview/llfloaterimagepreview.h +++ b/indra/newview/llfloaterimagepreview.h @@ -81,7 +81,7 @@ protected: public: LLImagePreviewAvatar(S32 width, S32 height); - /*virtual*/ S8 getType() const ; + S8 getType() const override; void setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male); void setTexture(U32 name) { mTextureName = name; } @@ -113,12 +113,14 @@ public: LLFloaterImagePreview(const std::string& filename); virtual ~LLFloaterImagePreview(); - virtual BOOL postBuild(); + BOOL postBuild() override; + + S32 getExpectedUploadCost() const override; - BOOL handleMouseDown(S32 x, S32 y, MASK mask); - BOOL handleMouseUp(S32 x, S32 y, MASK mask); - BOOL handleHover(S32 x, S32 y, MASK mask); - BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleHover(S32 x, S32 y, MASK mask) override; + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; static void onMouseCaptureLostImagePreview(LLMouseHandler*); @@ -126,7 +128,7 @@ public: protected: static void onPreviewTypeCommit(LLUICtrl*,void*); - void draw(); + void draw() override; bool loadImage(const std::string& filename); LLPointer mRawImagep; diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h index 589f470e82..cf3b512fab 100644 --- a/indra/newview/llfloaternamedesc.h +++ b/indra/newview/llfloaternamedesc.h @@ -47,7 +47,7 @@ public: void onBtnCancel(); void doCommit(); - S32 getExpectedUploadCost() const; + virtual S32 getExpectedUploadCost() const; protected: virtual void onCommit(); diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index b54617870c..fc3c0bb022 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -489,11 +489,20 @@ BOOL LLMaterialEditor::postBuild() } else { - S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); - getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + S32 upload_cost_base = LLAgentBenefitsMgr::current().getTextureUploadCost(); + S32 upload_cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + + bool large_texture = mBaseColorFetched && (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); + + large_texture = mMetallicRoughnessFetched && (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); + + large_texture = mEmissiveFetched && (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); + + large_texture = mNormalFetched && (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); } boost::function changes_callback = [this](LLUICtrl * ctrl, void* userData) @@ -843,24 +852,54 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) } S32 upload_texture_count = 0; - if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId()) + S32 upload_2k_texture_count = 0; + if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched) { - upload_texture_count++; + if (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + upload_2k_texture_count++; + } + else + { + upload_texture_count++; + } } - if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId()) + if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched) { - upload_texture_count++; + if (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + upload_2k_texture_count++; + } + else + { + upload_texture_count++; + } } - if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId()) + if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched) { - upload_texture_count++; + if (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + upload_2k_texture_count++; + } + else + { + upload_texture_count++; + } } - if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId()) + if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched) { - upload_texture_count++; + if (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + upload_2k_texture_count++; + } + else + { + upload_texture_count++; + } } mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost(); + mExpectedUploadCost += upload_2k_texture_count * LLAgentBenefitsMgr::current().get2KTextureUploadCost(); getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); } @@ -3496,6 +3535,10 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con buffer.assign((const char*) img->getData(), img->getDataSize()); U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + if (img->getWidth() * img->getHeight() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + } LLSD key = getKey(); std::function failed_upload([key](LLUUID assetId, LLSD response, std::string reason) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 20241aac24..2db431d165 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -276,14 +276,12 @@ BOOL LLPanelMainInventory::postBuild() initListCommandsHandlers(); - const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if (menu) { - menu->getChild("Upload Image")->setLabelArg("[COST]", texture_upload_cost_str); menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); } @@ -2229,11 +2227,9 @@ void LLPanelMainInventory::setUploadCostIfNeeded() LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); if(mNeedUploadCost && menu) { - const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - menu->getChild("Upload Image")->setLabelArg("[COST]", texture_upload_cost_str); menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c50ae2e153..52e5c5ff12 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -526,10 +526,8 @@ void init_menus() LLGridManager::getInstance()->isInProductionGrid()); // *TODO:Also fix cost in llfolderview.cpp for Inventory menus - const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - gMenuHolder->childSetLabelArg("Upload Image", "[COST]", texture_upload_cost_str); gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); @@ -9245,6 +9243,8 @@ void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str) if (asset_type_str == "texture") { + // This use minimal texture cost to allow bulk and + // texture upload menu options to be visible upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); } else if (asset_type_str == "animation") diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 5461e0f362..60956fab03 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -612,6 +612,7 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 if (ext == "gltf" || ext == "glb") { S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + S32 texture_2k_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); tinygltf::Model model; @@ -630,23 +631,52 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 // Todo: make it account for possibility of same texture in different // materials and even in scope of same material S32 texture_count = 0; - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull()) + S32 texture_2k_count = 0; + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && material->mBaseColorTexture) { - texture_count++; + if (material->mBaseColorTexture->getFullHeight() * material->mBaseColorTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + texture_2k_count++; + } + else + { + texture_count++; + } } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull()) + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && material->mMetallicRoughnessTexture) { - texture_count++; + if (material->mMetallicRoughnessTexture->getFullHeight() * material->mMetallicRoughnessTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + texture_2k_count++; + } + else + { + texture_count++; + } } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull()) + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && material->mNormalTexture) { - texture_count++; + if (material->mNormalTexture->getFullHeight() * material->mNormalTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + texture_2k_count++; + } + else + { + texture_count++; + } } - if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull()) + if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && material->mEmissiveTexture) { - texture_count++; + if (material->mEmissiveTexture->getFullHeight() * material->mEmissiveTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + texture_2k_count++; + } + else + { + texture_count++; + } } - total_cost += texture_count * texture_upload_cost; + total_cost += texture_count * texture_upload_cost + texture_2k_count * texture_2k_upload_cost; file_count++; } } diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index 284dd8d9fc..5bf26b41c6 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -13,7 +13,7 @@ name="upload" tear_off="true"> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 591b5537c7..992b3b2023 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1612,7 +1612,7 @@ function="World.EnvPreset" name="Upload" tear_off="true"> -- cgit v1.2.3 From e1e0b6fc5bb3eaa210fac24e2421fefbaeafe561 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 29 Mar 2024 21:57:58 +0200 Subject: viewer#1081 Account for 2K texture upload price in bulk upload --- indra/newview/llagentbenefits.h | 2 +- indra/newview/llfloaterimagepreview.cpp | 2 +- indra/newview/llfloaterimagepreview.h | 10 +-- indra/newview/llmaterialeditor.cpp | 25 +++++--- indra/newview/llviewermenufile.cpp | 104 +++++++++++++++++++++++--------- 5 files changed, 99 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h index e3a03ba1ca..e48cedd95c 100644 --- a/indra/newview/llagentbenefits.h +++ b/indra/newview/llagentbenefits.h @@ -33,7 +33,7 @@ class LLAgentBenefits { public: - static constexpr S32 MIN_2K_TEXTURE_AREA = 1024 * 1024; + static constexpr S32 MIN_2K_TEXTURE_AREA = 1024 * 1024 + 1; LLAgentBenefits(); ~LLAgentBenefits(); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 68dd7bfdd6..87fe0a4dd6 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -153,7 +153,7 @@ S32 LLFloaterImagePreview::getExpectedUploadCost() const { if (mRawImagep.notNull()) { - if (mRawImagep->getWidth() * mRawImagep->getHeight() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (mRawImagep->getWidth() * mRawImagep->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { return LLAgentBenefitsMgr::current().get2KTextureUploadCost(); } diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h index 13e198426b..426dd926ae 100644 --- a/indra/newview/llfloaterimagepreview.h +++ b/indra/newview/llfloaterimagepreview.h @@ -48,17 +48,17 @@ protected: public: LLImagePreviewSculpted(S32 width, S32 height); - /*virtual*/ S8 getType() const ; + S8 getType() const override; void setPreviewTarget(LLImageRaw *imagep, F32 distance); void setTexture(U32 name) { mTextureName = name; } - BOOL render(); + BOOL render() override; void refresh(); void rotate(F32 yaw_radians, F32 pitch_radians); void zoom(F32 zoom_amt); void pan(F32 right, F32 up); - virtual BOOL needsRender() { return mNeedsUpdate; } + virtual BOOL needsRender() override { return mNeedsUpdate; } protected: BOOL mNeedsUpdate; @@ -87,12 +87,12 @@ public: void setTexture(U32 name) { mTextureName = name; } void clearPreviewTexture(const std::string& mesh_name); - BOOL render(); + BOOL render() override; void refresh(); void rotate(F32 yaw_radians, F32 pitch_radians); void zoom(F32 zoom_amt); void pan(F32 right, F32 up); - virtual BOOL needsRender() { return mNeedsUpdate; } + virtual BOOL needsRender() override { return mNeedsUpdate; } protected: BOOL mNeedsUpdate; diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index fc3c0bb022..1783621530 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -492,16 +492,16 @@ BOOL LLMaterialEditor::postBuild() S32 upload_cost_base = LLAgentBenefitsMgr::current().getTextureUploadCost(); S32 upload_cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - bool large_texture = mBaseColorFetched && (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + bool large_texture = mBaseColorFetched && (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - large_texture = mMetallicRoughnessFetched && (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + large_texture = mMetallicRoughnessFetched && (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - large_texture = mEmissiveFetched && (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + large_texture = mEmissiveFetched && (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - large_texture = mNormalFetched && (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA); + large_texture = mNormalFetched && (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); } @@ -855,7 +855,7 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) S32 upload_2k_texture_count = 0; if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched) { - if (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { upload_2k_texture_count++; } @@ -866,7 +866,7 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) } if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched) { - if (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { upload_2k_texture_count++; } @@ -877,7 +877,7 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) } if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched) { - if (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { upload_2k_texture_count++; } @@ -888,7 +888,7 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) } if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched) { - if (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { upload_2k_texture_count++; } @@ -899,7 +899,12 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) } mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost(); - mExpectedUploadCost += upload_2k_texture_count * LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + S32 cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + if (cost_2k < 0) + { + cost_2k = 0; + } + mExpectedUploadCost += upload_2k_texture_count * cost_2k; getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); } @@ -3535,7 +3540,7 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con buffer.assign((const char*) img->getData(), img->getDataSize()); U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - if (img->getWidth() * img->getHeight() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (img->getWidth() * img->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 60956fab03..6fe5ef00ab 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -546,21 +546,50 @@ void do_bulk_upload(std::vector filenames, const LLSD& notification std::string ext = gDirUtilp->getExtension(filename); LLAssetType::EType asset_type; U32 codec; - S32 expected_upload_cost; - if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) && - LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost)) - { - LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo( - filename, - asset_name, - asset_name, 0, - LLFolderType::FT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms("Uploads"), - LLFloaterPerms::getGroupPerms("Uploads"), - LLFloaterPerms::getEveryonePerms("Uploads"), - expected_upload_cost)); - - upload_new_resource(uploadInfo); + S32 expected_upload_cost = 0; + + if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec)) + { + bool resource_upload = false; + if (asset_type == LLAssetType::AT_TEXTURE) + { + LLPointer image_frmted = LLImageFormatted::createFromType(codec); + if (gDirUtilp->fileExists(filename) && image_frmted->load(filename)) + { + if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); + if (expected_upload_cost >= 0) + { + resource_upload = true; + } + } + else + { + expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + resource_upload = true; + } + } + } + else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost)) + { + resource_upload = true; + } + + if (resource_upload) + { + LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo( + filename, + asset_name, + asset_name, 0, + LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), + expected_upload_cost)); + + upload_new_resource(uploadInfo); + } } // gltf does not use normal upload procedure @@ -588,6 +617,8 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 total_cost = 0; file_count = 0; bvh_count = 0; + S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + S32 texture_2k_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) { std::string filename = (*in_iter); @@ -602,18 +633,37 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 U32 codec; S32 cost; - if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) && - LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost)) + if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec)) { - total_cost += cost; - file_count++; - } + if (asset_type == LLAssetType::AT_TEXTURE) + { + LLPointer image_frmted = LLImageFormatted::createFromType(codec); + if (gDirUtilp->fileExists(filename) && image_frmted->load(filename)) + { + if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) + { + if (texture_2k_upload_cost >= 0) + { + total_cost += texture_2k_upload_cost; + file_count++; + } + } + else + { + total_cost += texture_upload_cost; + file_count++; + } + } + } + else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost)) + { + total_cost += cost; + file_count++; + } + } if (ext == "gltf" || ext == "glb") { - S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - S32 texture_2k_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - tinygltf::Model model; if (LLTinyGLTFHelper::loadModel(filename, model)) @@ -634,7 +684,7 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 S32 texture_2k_count = 0; if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && material->mBaseColorTexture) { - if (material->mBaseColorTexture->getFullHeight() * material->mBaseColorTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (material->mBaseColorTexture->getFullHeight() * material->mBaseColorTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { texture_2k_count++; } @@ -645,7 +695,7 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && material->mMetallicRoughnessTexture) { - if (material->mMetallicRoughnessTexture->getFullHeight() * material->mMetallicRoughnessTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (material->mMetallicRoughnessTexture->getFullHeight() * material->mMetallicRoughnessTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { texture_2k_count++; } @@ -656,7 +706,7 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && material->mNormalTexture) { - if (material->mNormalTexture->getFullHeight() * material->mNormalTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (material->mNormalTexture->getFullHeight() * material->mNormalTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { texture_2k_count++; } @@ -667,7 +717,7 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && material->mEmissiveTexture) { - if (material->mEmissiveTexture->getFullHeight() * material->mEmissiveTexture->getFullWidth() > LLAgentBenefits::MIN_2K_TEXTURE_AREA) + if (material->mEmissiveTexture->getFullHeight() * material->mEmissiveTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) { texture_2k_count++; } -- cgit v1.2.3 From 422ab40704cdbf36cd28fa0a78d5941c9456c1ad Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 2 Apr 2024 14:04:42 -0500 Subject: https://github.com/secondlife/jira-archive-internal/issues/71062 Fix for avatar not responding to keyboard inputs when not visible (#1113) --- indra/newview/llvoavatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 35e45c6cd9..aae13e3327 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4681,7 +4681,7 @@ bool LLVOAvatar::updateCharacter(LLAgent &agent) mSpeed = speed; // update animations - if (!visible) + if (!visible && !isSelf()) // NOTE: never do a "hidden update" for self avatar as it interrupts controller processing { updateMotions(LLCharacter::HIDDEN_UPDATE); } -- cgit v1.2.3 From 92efb16039619b8ac440cfc862f29b0f7c6c0fd6 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 2 Apr 2024 15:27:22 -0500 Subject: #854 Fix for skies that shouldn't be auto-adjusted getting auto-adjusted. (#1115) --- indra/llinventory/llsettingssky.cpp | 28 +++++----------------------- indra/llinventory/llsettingssky.h | 9 +-------- indra/newview/app_settings/settings.xml | 11 ----------- indra/newview/llreflectionmapmanager.cpp | 3 +-- indra/newview/llsettingsvo.cpp | 3 +-- 5 files changed, 8 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index c3cd7262fb..6688dadd3a 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -407,7 +407,6 @@ LLSettingsSky::LLSettingsSky(const LLSD &data) : mNextRainbowTextureId(), mNextHaloTextureId() { - mCanAutoAdjust = !data.has(SETTING_REFLECTION_PROBE_AMBIANCE); } LLSettingsSky::LLSettingsSky(): @@ -430,8 +429,6 @@ void LLSettingsSky::replaceSettings(LLSD settings) mNextBloomTextureId.setNull(); mNextRainbowTextureId.setNull(); mNextHaloTextureId.setNull(); - - mCanAutoAdjust = !settings.has(SETTING_REFLECTION_PROBE_AMBIANCE); } void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) @@ -444,7 +441,6 @@ void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) mNextBloomTextureId = pother->mNextBloomTextureId; mNextRainbowTextureId = pother->mNextRainbowTextureId; mNextHaloTextureId = pother->mNextHaloTextureId; - mCanAutoAdjust = pother->mCanAutoAdjust; } void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) @@ -1146,7 +1142,6 @@ void LLSettingsSky::setSkyIceLevel(F32 ice_level) void LLSettingsSky::setReflectionProbeAmbiance(F32 ambiance) { - mCanAutoAdjust = false; // we've now touched this sky in a "new" way, it can no longer auto adjust setValue(SETTING_REFLECTION_PROBE_AMBIANCE, ambiance); } @@ -1448,24 +1443,6 @@ F32 LLSettingsSky::getReflectionProbeAmbiance(bool auto_adjust) const return mSettings[SETTING_REFLECTION_PROBE_AMBIANCE].asReal(); } -F32 LLSettingsSky::getTotalReflectionProbeAmbiance(F32 cloud_shadow_scale, bool auto_adjust) const -{ -#if 0 - // feed cloud shadow back into reflection probe ambiance to mimic pre-reflection-probe behavior - // without brightening dark/interior spaces - F32 probe_ambiance = getReflectionProbeAmbiance(auto_adjust); - - if (probe_ambiance > 0.f && probe_ambiance < 1.f) - { - probe_ambiance += (1.f - probe_ambiance) * getCloudShadow() * cloud_shadow_scale; - } - - return probe_ambiance; -#else - return getReflectionProbeAmbiance(auto_adjust); -#endif -} - F32 LLSettingsSky::getSkyBottomRadius() const { return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal(); @@ -1810,3 +1787,8 @@ LLUUID LLSettingsSky::getNextBloomTextureId() const return mNextBloomTextureId; } +// if true, this sky is a candidate for auto-adjustment +bool LLSettingsSky::canAutoAdjust() const +{ + return !mSettings.has(SETTING_REFLECTION_PROBE_AMBIANCE); +} diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h index 7ba7a9ba06..222ab040cb 100644 --- a/indra/llinventory/llsettingssky.h +++ b/indra/llinventory/llsettingssky.h @@ -139,10 +139,6 @@ public: // auto_adjust - if true and canAutoAdjust() is true, return 1.0 F32 getReflectionProbeAmbiance(bool auto_adjust = false) const; - // get the probe ambiance setting to use for rendering (adjusted by cloud shadow, aka cloud coverage) - // auto_adjust - if true and canAutoAdjust() is true, return 1.0 - F32 getTotalReflectionProbeAmbiance(F32 cloud_shadow_scale, bool auto_adjust = false) const; - // Return first (only) profile layer represented in LLSD LLSD getRayleighConfig() const; LLSD getMieConfig() const; @@ -340,7 +336,7 @@ public: virtual void updateSettings() SETTINGS_OVERRIDE; // if true, this sky is a candidate for auto-adjustment - bool canAutoAdjust() const { return mCanAutoAdjust; } + bool canAutoAdjust() const; protected: static const std::string SETTING_LEGACY_EAST_ANGLE; @@ -385,9 +381,6 @@ private: mutable LLColor4 mTotalAmbient; mutable LLColor4 mHazeColor; - // if true, this sky is a candidate for auto adjustment - bool mCanAutoAdjust = true; - typedef std::map mapNameToUniformId_t; static mapNameToUniformId_t sNameToUniformMapping; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a988c515ce..3ef7cb9ef7 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8828,17 +8828,6 @@ Value 32.0 - RenderCloudShadowAmbianceFactor - - Comment - Amount that cloud shadow (aka cloud coverage) contributes to reflection probe ambiance - Persist - 1 - Type - F32 - Value - 0.1 - RenderCPUBasis Comment diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index f9c5421866..3e4992e4e7 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -1092,9 +1092,8 @@ void LLReflectionMapManager::updateUniforms() LLEnvironment& environment = LLEnvironment::instance(); LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale, should_auto_adjust); + F32 minimum_ambiance = psky->getReflectionProbeAmbiance(should_auto_adjust); bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); F32 ambscale = is_ambiance_pass ? 0.f : 1.f; diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index afae5f140b..ff9332aeee 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -745,8 +745,7 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::SKY_SUNLIGHT_SCALE, sunlight_scale); shader->uniform1f(LLShaderMgr::SKY_AMBIENT_SCALE, ambient_scale); - static LLCachedControl cloud_shadow_scale(gSavedSettings, "RenderCloudShadowAmbianceFactor", 0.125f); - F32 probe_ambiance = getTotalReflectionProbeAmbiance(cloud_shadow_scale); + F32 probe_ambiance = getReflectionProbeAmbiance(); if (irradiance_pass) { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue) -- cgit v1.2.3 From 54fc10acb10eeaeeadec3f06a373e9c94d8676cb Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 2 Apr 2024 16:09:20 -0500 Subject: #1116 HDRI preview enhancements (#1119) Don't split sky in radiance and irradiance maps Allow for applying HDRI sky to only irradiance map Allow for showing entire EEP sky (clouds and all) when split is set to zero --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/lldrawpoolwlsky.cpp | 23 ++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3ef7cb9ef7..30b307677b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9373,6 +9373,17 @@ Value 1.0 + RenderHDRIIrradianceOnly + + Comment + Only use HDRI sky for irradiance map when RenderHDRISplitScreen is 0 + Persist + 1 + Type + Boolean + Value + 0 + RenderMaxOpenGLVersion Comment diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 323ab5fc07..68be354533 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -130,6 +130,17 @@ void LLDrawPoolWLSky::renderDome(const LLVector3& camPosLocal, F32 camHeightLoca extern LLPointer gEXRImage; +static bool use_hdri_sky() +{ + static LLCachedControl hdri_split(gSavedSettings, "RenderHDRISplitScreen", 1.f); + static LLCachedControl irradiance_only(gSavedSettings, "RenderHDRIIrradianceOnly", false); + + return gCubeSnapshot && (!irradiance_only || !gPipeline.mReflectionMapManager.isRadiancePass()) ? gEXRImage.notNull() : // always use HDRI for reflection probes when available + gEXRImage.notNull() ? hdri_split > 0.f : // fallback to EEP sky when split screen is zero + false; // no HDRI available, always use EEP sky + +} + void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const { if (!gSky.mVOSkyp) @@ -141,7 +152,7 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { - if (gEXRImage.notNull()) + if (use_hdri_sky()) { sky_shader = &gEnvironmentMapProgram; sky_shader->bind(); @@ -161,7 +172,7 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca sky_shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, powf(2.f, hdri_exposure)); sky_shader->uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, GL_FALSE, (F32*) rot.mMatrix); - sky_shader->uniform1f(hdri_split_screen, hdri_split); + sky_shader->uniform1f(hdri_split_screen, gCubeSnapshot ? 1.f : hdri_split); } else { @@ -170,8 +181,6 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca LLGLSPipelineDepthTestSkyBox sky(true, true); - - sky_shader->uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0); LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); @@ -210,7 +219,7 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const { - if (!gSky.mVOSkyp || gEXRImage.notNull()) + if (!gSky.mVOSkyp || use_hdri_sky()) { return; } @@ -281,7 +290,7 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const { - if (gEXRImage.notNull()) + if (use_hdri_sky()) { return; } @@ -345,7 +354,7 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 void LLDrawPoolWLSky::renderHeavenlyBodies() { - if (!gSky.mVOSkyp || gEXRImage.notNull()) return; + if (!gSky.mVOSkyp || use_hdri_sky()) return; LLGLSPipelineBlendSkyBox gls_skybox(true, true); // SL-14113 we need moon to write to depth to clip stars behind -- cgit v1.2.3 From dea219281453f371c49962d1e792578f81c47ebb Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 3 Apr 2024 10:08:09 -0700 Subject: secondlife/viewer#773: Amend dev setting description for RenderTerrainPBREnabled --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 30b307677b..0ed4b629bb 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10913,7 +10913,7 @@ RenderTerrainPBREnabled Comment - EXPERIMENTAL: Enable PBR Terrain features. Requires restart. + EXPERIMENTAL: Enable PBR Terrain features. Persist 1 Type -- cgit v1.2.3 From 7c92398cf6d0c588a9e3504f107eb1d513877234 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 25 Mar 2024 15:04:08 -0700 Subject: secondlife/viewer#759: Fix minimap loading for 2k PBR materials, and probably other odd cases --- indra/newview/llvlcomposition.cpp | 130 +++++++++++++++++++++++++++----------- 1 file changed, 93 insertions(+), 37 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 6b42804a90..234b24e440 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -46,21 +46,40 @@ extern LLColor4U MAX_WATER_COLOR; static const U32 BASE_SIZE = 128; -F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac) +namespace { - // Not sure if this is the right math... - // Take weighted average of all four points (bilinear interpolation) - F32 result; - - const F32 inv_x_frac = 1.f - x_frac; - const F32 inv_y_frac = 1.f - y_frac; - result = inv_x_frac*inv_y_frac*v00 - + x_frac*inv_y_frac*v10 - + inv_x_frac*y_frac*v01 - + x_frac*y_frac*v11; - - return result; -} + F32 bilinear(const F32 v00, const F32 v01, const F32 v10, const F32 v11, const F32 x_frac, const F32 y_frac) + { + // Not sure if this is the right math... + // Take weighted average of all four points (bilinear interpolation) + F32 result; + + const F32 inv_x_frac = 1.f - x_frac; + const F32 inv_y_frac = 1.f - y_frac; + result = inv_x_frac*inv_y_frac*v00 + + x_frac*inv_y_frac*v10 + + inv_x_frac*y_frac*v01 + + x_frac*y_frac*v11; + + return result; + } + + void unboost_minimap_texture(LLPointer& tex) + { + if (!tex) { return; } + tex->setBoostLevel(LLGLTexture::BOOST_NONE); + tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); + } + + void unboost_minimap_material(LLPointer& mat) + { + if (!mat) { return; } + unboost_minimap_texture(mat->mBaseColorTexture); + unboost_minimap_texture(mat->mNormalTexture); + unboost_minimap_texture(mat->mMetallicRoughnessTexture); + unboost_minimap_texture(mat->mEmissiveTexture); + } +}; LLTerrainMaterials::LLTerrainMaterials() { @@ -514,21 +533,47 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } // tex_emissive can be null, and then will be ignored - S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); - S32 ddiscard = 0; - while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) - { - ddiscard++; - min_dim /= 2; + S32 ddiscard = 0; + { + S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); + while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) + { + ddiscard++; + min_dim /= 2; + } + } + + S32 ddiscard_emissive = 0; + if (tex_emissive) + { + S32 min_dim_emissive = llmin(tex_emissive->getFullWidth(), tex_emissive->getFullHeight()); + while (min_dim_emissive > BASE_SIZE && ddiscard_emissive < MAX_DISCARD_LEVEL) + { + ddiscard_emissive++; + min_dim_emissive /= 2; + } } - BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL) ; + // *NOTE: It is probably safe to call destroyRawImage no matter + // what, as LLViewerFetchedTexture::mRawImage is managed by + // LLPointer and not modified with the rare exception of + // icons (see BOOST_ICON). Nevertheless, gate this fix for now, as + // it may have unintended consequences on texture loading. + // We may want to also set the boost level in setDetailAssetID, but + // that is not guaranteed to work if a texture is loaded on an object + // before being loaded as terrain, so we will need this fix + // regardless. + static LLCachedControl sRenderTerrainPBREnabled(gSavedSettings, "RenderTerrainPBREnabled", false); + BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL || sRenderTerrainPBREnabled); + BOOL delete_raw_emissive = (tex_emissive && + (tex_emissive->reloadRawImage(ddiscard_emissive) != NULL || sRenderTerrainPBREnabled)); + if(tex->getRawImageLevel() != ddiscard) { // Raw image is not ready, will enter here again later. if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage()) { - tex->setBoostLevel(LLGLTexture::BOOST_MAP); + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); tex->forceToRefetchTexture(ddiscard); } @@ -540,16 +585,16 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, } if (tex_emissive) { - if(tex_emissive->getRawImageLevel() != ddiscard) + if(tex_emissive->getRawImageLevel() != ddiscard_emissive) { // Raw image is not ready, will enter here again later. if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage()) { - tex_emissive->setBoostLevel(LLGLTexture::BOOST_MAP); - tex_emissive->forceToRefetchTexture(ddiscard); + tex_emissive->setBoostLevel(LLGLTexture::BOOST_TERRAIN); + tex_emissive->forceToRefetchTexture(ddiscard_emissive); } - if(delete_raw) + if(delete_raw_emissive) { tex_emissive->destroyRawImage() ; } @@ -577,8 +622,8 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { raw_emissive = tex_emissive->getRawImage(); if (has_emissive_factor || - tex_emissive->getWidth(ddiscard) != BASE_SIZE || - tex_emissive->getHeight(ddiscard) != BASE_SIZE || + tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE || + tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != BASE_SIZE || tex_emissive->getComponents() != 4) { LLPointer newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4); @@ -588,14 +633,14 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { newraw_emissive->tint(emissive_factor); } - raw_emissive = newraw_emissive; // deletes old + raw_emissive = newraw_emissive; } } if (has_base_color_factor || raw_emissive || has_alpha || - tex->getWidth(ddiscard) != BASE_SIZE || - tex->getHeight(ddiscard) != BASE_SIZE || + tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE || + tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE || tex->getComponents() != 3) { LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); @@ -618,8 +663,14 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { newraw->composite(raw_emissive); } + mRawImages[i] = newraw; // deletes old } + + if (delete_raw_emissive) + { + tex_emissive->destroyRawImage(); + } } st_data[i] = mRawImages[i]->getData(); st_data_size[i] = mRawImages[i]->getDataSize(); @@ -765,12 +816,17 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); - for (S32 i = 0; i < ASSET_COUNT; i++) - { - // Un-boost detatil textures (will get re-boosted if rendering in high detail) - mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_NONE); - mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); - } + // Un-boost detail textures (will get re-boosted if rendering in high detail) + for (S32 i = 0; i < ASSET_COUNT; i++) + { + unboost_minimap_texture(mDetailTextures[i]); + } + + // Un-boost textures for each detail material (will get re-boosted if rendering in high detail) + for (S32 i = 0; i < ASSET_COUNT; i++) + { + unboost_minimap_material(mDetailMaterials[i]); + } return TRUE; } -- cgit v1.2.3 From b2a450a3087fb8393024876f6069a7cec9855bfd Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 9 Apr 2024 19:21:10 -0500 Subject: #1126 gltf scene import prototype (#1172) * #1126 GLTF Scene import initial prototype (working geometry import for some assets) * #1126 WIP -- Expand support for more vertex formats, PoC material import, shadow support, scale support * #1126 move GLTF implementation to newview/gltf * #1126 Refactor attribute loading to be less copy/pasta for each combination of types * #1126 Partially working object selection. Ability to have multiple scenes at once. Helpful message on how to use the preview button. * #1126 Add bounding box debug display and untangle GLTF raycast from LLVOVolume raycast * #1126 Working raycast on GLTF scenes. * #1126 Remove some #pragma optimize offs --- indra/llmath/llvolume.cpp | 85 +--- indra/llmath/llvolume.h | 5 +- indra/llmath/llvolumeoctree.cpp | 8 +- indra/llmath/llvolumeoctree.h | 95 +++- indra/llrender/llvertexbuffer.cpp | 2 +- indra/newview/CMakeLists.txt | 6 + indra/newview/gltf/asset.cpp | 209 +++++++++ indra/newview/gltf/asset.h | 445 +++++++++++++++++++ indra/newview/gltf/primitive.cpp | 480 +++++++++++++++++++++ indra/newview/gltf/primitive.h | 140 ++++++ indra/newview/gltfscenemanager.cpp | 469 ++++++++++++++++++++ indra/newview/gltfscenemanager.h | 64 +++ indra/newview/llappviewer.cpp | 6 +- indra/newview/lldrawpoolpbropaque.cpp | 4 + indra/newview/llspatialpartition.cpp | 28 +- indra/newview/lltinygltfhelper.cpp | 27 +- indra/newview/lltinygltfhelper.h | 9 +- indra/newview/llviewermenu.cpp | 13 + indra/newview/llviewerobject.h | 3 + indra/newview/llvovolume.cpp | 4 +- indra/newview/pipeline.cpp | 17 + indra/newview/skins/default/xui/en/menu_viewer.xml | 6 + .../newview/skins/default/xui/en/notifications.xml | 13 +- 23 files changed, 2015 insertions(+), 123 deletions(-) create mode 100644 indra/newview/gltf/asset.cpp create mode 100644 indra/newview/gltf/asset.h create mode 100644 indra/newview/gltf/primitive.cpp create mode 100644 indra/newview/gltf/primitive.h create mode 100644 indra/newview/gltfscenemanager.cpp create mode 100644 indra/newview/gltfscenemanager.h (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 29eeebcf67..2f25a4359d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -45,13 +45,13 @@ #include "llmatrix3a.h" #include "lloctree.h" #include "llvolume.h" -#include "llvolumeoctree.h" #include "llstl.h" #include "llsdserialize.h" #include "llvector4a.h" #include "llmatrix4a.h" #include "llmeshoptimizer.h" #include "lltimer.h" +#include "llvolumeoctree.h" #include "mikktspace/mikktspace.h" #include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file @@ -377,77 +377,6 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons } } -class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst -{ -public: - const LLVolumeFace* mFace; - - LLVolumeOctreeRebound(const LLVolumeFace* face) - { - mFace = face; - } - - virtual void visit(const LLOctreeNode* branch) - { //this is a depth first traversal, so it's safe to assum all children have complete - //bounding data - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); - - LLVector4a& min = node->mExtents[0]; - LLVector4a& max = node->mExtents[1]; - - if (!branch->isEmpty()) - { //node has data, find AABB that binds data set - const LLVolumeTriangle* tri = *(branch->getDataBegin()); - - //initialize min/max to first available vertex - min = *(tri->mV[0]); - max = *(tri->mV[0]); - - for (LLOctreeNode::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) - { //for each triangle in node - - //stretch by triangles in node - tri = *iter; - - min.setMin(min, *tri->mV[0]); - min.setMin(min, *tri->mV[1]); - min.setMin(min, *tri->mV[2]); - - max.setMax(max, *tri->mV[0]); - max.setMax(max, *tri->mV[1]); - max.setMax(max, *tri->mV[2]); - } - } - else if (branch->getChildCount() > 0) - { //no data, but child nodes exist - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); - - //initialize min/max to extents of first child - min = child->mExtents[0]; - max = child->mExtents[1]; - } - else - { - llassert(!branch->isLeaf()); // Empty leaf - } - - for (S32 i = 0; i < branch->getChildCount(); ++i) - { //stretch by child extents - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - min.setMin(min, child->mExtents[0]); - max.setMax(max, child->mExtents[1]); - } - - node->mBounds[0].setAdd(min, max); - node->mBounds[0].mul(0.5f); - - node->mBounds[1].setSub(max,min); - node->mBounds[1].mul(0.5f); - } -}; - //------------------------------------------------------------------- // statics //------------------------------------------------------------------- @@ -5509,7 +5438,6 @@ struct MikktData } }; - bool LLVolumeFace::cacheOptimize(bool gen_tangents) { //optimize for vertex cache according to Forsyth method: LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; @@ -5687,8 +5615,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe llassert(mNumIndices % 3 == 0); - mOctree = new LLOctreeRoot(center, size, NULL); - new LLVolumeOctreeListener(mOctree); + mOctree = new LLVolumeOctree(center, size); const U32 num_triangles = mNumIndices / 3; // Initialize all the triangles we need mOctreeTriangles = new LLVolumeTriangle[num_triangles]; @@ -5743,7 +5670,7 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe while (!mOctree->balance()) { } //calculate AABB for each node - LLVolumeOctreeRebound rebound(this); + LLVolumeOctreeRebound rebound; rebound.traverse(mOctree); if (gDebugGL) @@ -5756,12 +5683,12 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe void LLVolumeFace::destroyOctree() { delete mOctree; - mOctree = NULL; + mOctree = nullptr; delete[] mOctreeTriangles; - mOctreeTriangles = NULL; + mOctreeTriangles = nullptr; } -const LLOctreeNode* LLVolumeFace::getOctree() const +const LLVolumeOctree* LLVolumeFace::getOctree() const { return mOctree; } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c2586601ae..cca284d9bc 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -41,6 +41,7 @@ template class LLOctreeNode; class LLVolumeFace; class LLVolume; class LLVolumeTriangle; +class LLVolumeOctree; #include "lluuid.h" #include "v4color.h" @@ -913,7 +914,7 @@ public: void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); void destroyOctree(); // Get a reference to the octree, which may be null - const LLOctreeNode* getOctree() const; + const LLVolumeOctree* getOctree() const; enum { @@ -987,7 +988,7 @@ public: LLVector3 mNormalizedScale = LLVector3(1,1,1); private: - LLOctreeNode* mOctree; + LLVolumeOctree* mOctree; LLVolumeTriangle* mOctreeTriangles; BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE); diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index 6894d04d3c..95c7cb0b5c 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -92,15 +92,15 @@ void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode { public: - const LLVolumeFace* mFace; LLVector4a mStart; LLVector4a mDir; LLVector4a mEnd; @@ -121,10 +120,13 @@ public: LLVector4a* mNormal; LLVector4a* mTangent; F32* mClosestT; + LLVolumeFace* mFace; bool mHitFace; + const LLVolumeTriangle* mHitTriangle = nullptr; - LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, - const LLVolumeFace* face, F32* closest_t, + LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + LLVolumeFace* face, + F32* closest_t, LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); void traverse(const LLOctreeNode* node); @@ -137,4 +139,91 @@ class LLVolumeOctreeValidate : public LLOctreeTraveler* branch); }; +class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst +{ +public: + LLVolumeOctreeRebound() + { + } + + virtual void visit(const LLOctreeNode* branch) + { //this is a depth first traversal, so it's safe to assum all children have complete + //bounding data + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*)branch->getListener(0); + + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; + + if (!branch->isEmpty()) + { //node has data, find AABB that binds data set + const LLVolumeTriangle* tri = *(branch->getDataBegin()); + + //initialize min/max to first available vertex + min = *(tri->mV[0]); + max = *(tri->mV[0]); + + for (LLOctreeNode::const_element_iter iter = branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) + { //for each triangle in node + + //stretch by triangles in node + tri = *iter; + + min.setMin(min, *tri->mV[0]); + min.setMin(min, *tri->mV[1]); + min.setMin(min, *tri->mV[2]); + + max.setMax(max, *tri->mV[0]); + max.setMax(max, *tri->mV[1]); + max.setMax(max, *tri->mV[2]); + } + } + else if (branch->getChildCount() > 0) + { //no data, but child nodes exist + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(0)->getListener(0); + + //initialize min/max to extents of first child + min = child->mExtents[0]; + max = child->mExtents[1]; + } + else + { + llassert(!branch->isLeaf()); // Empty leaf + } + + for (S32 i = 0; i < branch->getChildCount(); ++i) + { //stretch by child extents + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*)branch->getChild(i)->getListener(0); + min.setMin(min, child->mExtents[0]); + max.setMax(max, child->mExtents[1]); + } + + node->mBounds[0].setAdd(min, max); + node->mBounds[0].mul(0.5f); + + node->mBounds[1].setSub(max, min); + node->mBounds[1].mul(0.5f); + } +}; + +class LLVolumeOctree : public LLOctreeRoot, public LLRefCount +{ +public: + LLVolumeOctree(const LLVector4a& center, const LLVector4a& size) + : + LLOctreeRoot(center, size, nullptr), + LLRefCount() + { + new LLVolumeOctreeListener(this); + } + + LLVolumeOctree() + : LLOctreeRoot(LLVector4a::getZero(), LLVector4a(1.f,1.f,1.f), nullptr), + LLRefCount() + { + new LLVolumeOctreeListener(this); + } +}; + #endif diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4f5f30d7c2..dda3c1532d 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -657,7 +657,7 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto U16 idx = indicesp[i]; gGL.vertex3fv(pos[idx].getF32ptr()); } -} + } gGL.end(); gGL.flush(); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8494ba5b49..125f5b28ba 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -74,6 +74,9 @@ if (NOT HAVOK_TPV) endif (NOT HAVOK_TPV) set(viewer_SOURCE_FILES + gltfscenemanager.cpp + gltf/asset.cpp + gltf/primitive.cpp groupchatlistener.cpp llaccountingcostmanager.cpp llaisapi.cpp @@ -727,7 +730,10 @@ set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING set(viewer_HEADER_FILES CMakeLists.txt ViewerInstall.cmake + gltfscenemanager.h groupchatlistener.h + gltf/asset.h + gltf/primitive.h llaccountingcost.h llaccountingcostmanager.h llaisapi.h diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp new file mode 100644 index 0000000000..18f814c5b6 --- /dev/null +++ b/indra/newview/gltf/asset.cpp @@ -0,0 +1,209 @@ +/** + * @file asset.cpp + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "asset.h" +#include "llvolumeoctree.h" + +using namespace LL::GLTF; + +void Scene::updateTransforms(Asset& asset) +{ + LLMatrix4a identity; + identity.setIdentity(); + for (auto& nodeIndex : mNodes) + { + Node& node = asset.mNodes[nodeIndex]; + node.updateTransforms(asset, identity); + } +} + +void Scene::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview) +{ + for (auto& nodeIndex : mNodes) + { + Node& node = asset.mNodes[nodeIndex]; + node.updateRenderTransforms(asset, modelview); + } +} + +void Node::updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview) +{ + matMul(mMatrix, modelview, mRenderMatrix); + + for (auto& childIndex : mChildren) + { + Node& child = asset.mNodes[childIndex]; + child.updateRenderTransforms(asset, mRenderMatrix); + } +} + +LLMatrix4a inverse(const LLMatrix4a& mat); + +void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix) +{ + matMul(mMatrix, parentMatrix, mAssetMatrix); + mAssetMatrixInv = inverse(mAssetMatrix); + + for (auto& childIndex : mChildren) + { + Node& child = asset.mNodes[childIndex]; + child.updateTransforms(asset, mAssetMatrix); + } +} + +void Asset::updateTransforms() +{ + for (auto& scene : mScenes) + { + scene.updateTransforms(*this); + } +} + +void Asset::updateRenderTransforms(const LLMatrix4a& modelview) +{ +#if 0 + // traverse hierarchy and update render transforms from scratch + for (auto& scene : mScenes) + { + scene.updateRenderTransforms(*this, modelview); + } +#else + // use mAssetMatrix to update render transforms from node list + for (auto& node : mNodes) + { + if (node.mMesh != INVALID_INDEX) + { + matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); + } + } + +#endif + +} + +S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent, // return the surface tangent at the intersection point + S32* primitive_hitp +) +{ + S32 node_hit = -1; + S32 primitive_hit = -1; + + LLVector4a local_start; + LLVector4a asset_end = end; + LLVector4a local_end; + LLVector4a p; + + + for (auto& node : mNodes) + { + if (node.mMesh != INVALID_INDEX) + { + + bool newHit = false; + + // transform start and end to this node's local space + node.mAssetMatrixInv.affineTransform(start, local_start); + node.mAssetMatrixInv.affineTransform(asset_end, local_end); + + Mesh& mesh = mMeshes[node.mMesh]; + for (auto& primitive : mesh.mPrimitives) + { + const LLVolumeTriangle* tri = primitive.lineSegmentIntersect(local_start, local_end, &p, tex_coord, normal, tangent); + if (tri) + { + newHit = true; + local_end = p; + + // pointer math to get the node index + node_hit = &node - &mNodes[0]; + llassert(&mNodes[node_hit] == &node); + + //pointer math to get the primitive index + primitive_hit = &primitive - &mesh.mPrimitives[0]; + llassert(&mesh.mPrimitives[primitive_hit] == &primitive); + } + } + + if (newHit) + { + // shorten line segment on hit + node.mAssetMatrix.affineTransform(p, asset_end); + + // transform results back to asset space + if (intersection) + { + *intersection = asset_end; + } + + if (normal || tangent) + { + LLMatrix4 normalMatrix(node.mAssetMatrixInv.getF32ptr()); + + normalMatrix.transpose(); + + LLMatrix4a norm_mat; + norm_mat.loadu((F32*)normalMatrix.mMatrix); + + if (normal) + { + LLVector4a n = *normal; + F32 w = n.getF32ptr()[3]; + n.getF32ptr()[3] = 0.0f; + + norm_mat.affineTransform(n, *normal); + normal->getF32ptr()[3] = w; + } + + if (tangent) + { + LLVector4a t = *tangent; + F32 w = t.getF32ptr()[3]; + t.getF32ptr()[3] = 0.0f; + + norm_mat.affineTransform(t, *tangent); + tangent->getF32ptr()[3] = w; + } + } + } + } + } + + if (node_hit != -1) + { + if (primitive_hitp) + { + *primitive_hitp = primitive_hit; + } + } + + return node_hit; +} + + diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h new file mode 100644 index 0000000000..0f1d4e8993 --- /dev/null +++ b/indra/newview/gltf/asset.h @@ -0,0 +1,445 @@ +#pragma once + +/** + * @file asset.h + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "llvertexbuffer.h" +#include "llvolumeoctree.h" +#include "../lltinygltfhelper.h" +#include "primitive.h" + +// LL GLTF Implementation +namespace LL +{ + namespace GLTF + { + constexpr S32 INVALID_INDEX = -1; + + class Asset; + + class Buffer + { + public: + std::vector mData; + std::string mName; + std::string mUri; + + const Buffer& operator=(const tinygltf::Buffer& src) + { + mData = src.data; + mName = src.name; + mUri = src.uri; + return *this; + } + }; + + class BufferView + { + public: + S32 mBuffer = INVALID_INDEX; + S32 mByteLength; + S32 mByteOffset; + S32 mByteStride; + S32 mTarget; + S32 mComponentType; + + std::string mName; + + const BufferView& operator=(const tinygltf::BufferView& src) + { + mBuffer = src.buffer; + mByteLength = src.byteLength; + mByteOffset = src.byteOffset; + mByteStride = src.byteStride; + mTarget = src.target; + mName = src.name; + return *this; + } + }; + + class Accessor + { + public: + S32 mBufferView = INVALID_INDEX; + S32 mByteOffset; + S32 mComponentType; + S32 mCount; + std::vector mMax; + std::vector mMin; + S32 mType; + bool mNormalized; + std::string mName; + + const Accessor& operator=(const tinygltf::Accessor& src) + { + mBufferView = src.bufferView; + mByteOffset = src.byteOffset; + mComponentType = src.componentType; + mCount = src.count; + mType = src.type; + mNormalized = src.normalized; + mName = src.name; + mMax = src.maxValues; + mMin = src.maxValues; + + return *this; + } + }; + + class Material + { + public: + // use LLFetchedGLTFMaterial for now, but eventually we'll want to use + // a more flexible GLTF material implementation instead of the fixed packing + // version we use for sharable GLTF material assets + LLPointer mMaterial; + std::string mName; + + const Material& operator=(const tinygltf::Material& src) + { + mName = src.name; + return *this; + } + + void allocateGLResources(Asset& asset) + { + // allocate material + mMaterial = new LLFetchedGLTFMaterial(); + } + }; + + class Mesh + { + public: + std::vector mPrimitives; + std::vector mWeights; + std::string mName; + + const Mesh& operator=(const tinygltf::Mesh& src) + { + mPrimitives.resize(src.primitives.size()); + for (U32 i = 0; i < src.primitives.size(); ++i) + { + mPrimitives[i] = src.primitives[i]; + } + + mWeights = src.weights; + mName = src.name; + + return *this; + } + + void allocateGLResources(Asset& asset) + { + for (auto& primitive : mPrimitives) + { + primitive.allocateGLResources(asset); + } + } + + }; + + class Node + { + public: + LLMatrix4a mMatrix; //local transform + LLMatrix4a mRenderMatrix; //transform for rendering + LLMatrix4a mAssetMatrix; //transform from local to asset space + LLMatrix4a mAssetMatrixInv; //transform from asset to local space + + std::vector mChildren; + S32 mMesh = INVALID_INDEX; + std::string mName; + + const Node& operator=(const tinygltf::Node& src) + { + F32* dstMatrix = mMatrix.getF32ptr(); + + if (src.matrix.size() != 16) + { + mMatrix.setIdentity(); + } + else + { + for (U32 i = 0; i < 16; ++i) + { + dstMatrix[i] = (F32)src.matrix[i]; + } + } + + mChildren = src.children; + mMesh = src.mesh; + mName = src.name; + + return *this; + } + + // Set mRenderMatrix to a transform that can be used for the current render pass + // modelview -- parent's render matrix + void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); + + // update mAssetMatrix and mAssetMatrixInv + void updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix); + + }; + + class Scene + { + public: + std::vector mNodes; + std::string mName; + + const Scene& operator=(const tinygltf::Scene& src) + { + mNodes = src.nodes; + mName = src.name; + + return *this; + } + + void updateTransforms(Asset& asset); + void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); + + }; + + class Texture + { + public: + S32 mSampler = INVALID_INDEX; + S32 mSource = INVALID_INDEX; + std::string mName; + + const Texture& operator=(const tinygltf::Texture& src) + { + mSampler = src.sampler; + mSource = src.source; + mName = src.name; + + return *this; + } + }; + + class Sampler + { + public: + S32 mMagFilter; + S32 mMinFilter; + S32 mWrapS; + S32 mWrapT; + std::string mName; + + const Sampler& operator=(const tinygltf::Sampler& src) + { + mMagFilter = src.magFilter; + mMinFilter = src.minFilter; + mWrapS = src.wrapS; + mWrapT = src.wrapT; + mName = src.name; + + return *this; + } + }; + + class Image + { + public: + std::string mName; + std::string mUri; + std::string mMimeType; + std::vector mData; + S32 mWidth; + S32 mHeight; + S32 mComponent; + S32 mBits; + LLPointer mTexture; + + const Image& operator=(const tinygltf::Image& src) + { + mName = src.name; + mUri = src.uri; + mMimeType = src.mimeType; + mData = src.image; + mWidth = src.width; + mHeight = src.height; + mComponent = src.component; + mBits = src.bits; + + return *this; + } + + void allocateGLResources() + { + // allocate texture + + } + }; + + // C++ representation of a GLTF Asset + class Asset : public LLRefCount + { + public: + std::vector mScenes; + std::vector mNodes; + std::vector mMeshes; + std::vector mMaterials; + std::vector mBuffers; + std::vector mBufferViews; + std::vector mTextures; + std::vector mSamplers; + std::vector mImages; + std::vector mAccessors; + + void allocateGLResources(const std::string& filename, const tinygltf::Model& model) + { + for (auto& mesh : mMeshes) + { + mesh.allocateGLResources(*this); + } + + for (auto& image : mImages) + { + image.allocateGLResources(); + } + + for (U32 i = 0; i < mMaterials.size(); ++i) + { + mMaterials[i].allocateGLResources(*this); + LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true); + } + } + + // update asset-to-node and node-to-asset transforms + void updateTransforms(); + + // update node render transforms + void updateRenderTransforms(const LLMatrix4a& modelview); + + void renderOpaque() + { + for (auto& node : mNodes) + { + if (node.mMesh != INVALID_INDEX) + { + Mesh& mesh = mMeshes[node.mMesh]; + for (auto& primitive : mesh.mPrimitives) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + if (primitive.mMaterial != INVALID_INDEX) + { + Material& material = mMaterials[primitive.mMaterial]; + material.mMaterial->bind(); + } + primitive.mVertexBuffer->setBuffer(); + if (primitive.mVertexBuffer->getNumIndices() > 0) + { + primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); + } + else + { + primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); + } + } + } + } + } + + // return the index of the node that the line segment intersects with, or -1 if no hit + // input and output values must be in this asset's local coordinate frame + S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + LLVector4a* intersection = nullptr, // return the intersection point + LLVector2* tex_coord = nullptr, // return the texture coordinates of the intersection point + LLVector4a* normal = nullptr, // return the surface normal at the intersection point + LLVector4a* tangent = nullptr, // return the surface tangent at the intersection point + S32* primitive_hitp = nullptr // return the index of the primitive that was hit + ); + + const Asset& operator=(const tinygltf::Model& src) + { + mScenes.resize(src.scenes.size()); + for (U32 i = 0; i < src.scenes.size(); ++i) + { + mScenes[i] = src.scenes[i]; + } + + mNodes.resize(src.nodes.size()); + for (U32 i = 0; i < src.nodes.size(); ++i) + { + mNodes[i] = src.nodes[i]; + } + + mMeshes.resize(src.meshes.size()); + for (U32 i = 0; i < src.meshes.size(); ++i) + { + mMeshes[i] = src.meshes[i]; + } + + mMaterials.resize(src.materials.size()); + for (U32 i = 0; i < src.materials.size(); ++i) + { + mMaterials[i] = src.materials[i]; + } + + mBuffers.resize(src.buffers.size()); + for (U32 i = 0; i < src.buffers.size(); ++i) + { + mBuffers[i] = src.buffers[i]; + } + + mBufferViews.resize(src.bufferViews.size()); + for (U32 i = 0; i < src.bufferViews.size(); ++i) + { + mBufferViews[i] = src.bufferViews[i]; + } + + mTextures.resize(src.textures.size()); + for (U32 i = 0; i < src.textures.size(); ++i) + { + mTextures[i] = src.textures[i]; + } + + mSamplers.resize(src.samplers.size()); + for (U32 i = 0; i < src.samplers.size(); ++i) + { + mSamplers[i] = src.samplers[i]; + } + + mImages.resize(src.images.size()); + for (U32 i = 0; i < src.images.size(); ++i) + { + mImages[i] = src.images[i]; + } + + mAccessors.resize(src.accessors.size()); + for (U32 i = 0; i < src.accessors.size(); ++i) + { + mAccessors[i] = src.accessors[i]; + } + + return *this; + } + }; + } +} diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp new file mode 100644 index 0000000000..dca3ccf706 --- /dev/null +++ b/indra/newview/gltf/primitive.cpp @@ -0,0 +1,480 @@ +/** + * @file primitive.cpp + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "asset.h" +#include "../lltinygltfhelper.h" + +using namespace LL::GLTF; + +#ifndef __PRETTY_FUNCTION__ +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#endif + +// copy one vec3 from src to dst +template +void copyVec2(S* src, T& dst) +{ + LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; +} + +// copy one vec3 from src to dst +template +void copyVec3(S* src, T& dst) +{ + LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; +} + +// copy one vec4 from src to dst +template +void copyVec4(S* src, T& dst) +{ + LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; +} + +template<> +void copyVec2(F32* src, LLVector2& dst) +{ + dst.set(src[0], src[1]); +} + +template<> +void copyVec3(F32* src, LLVector4a& dst) +{ + dst.load3(src); +} + +template<> +void copyVec3(U16* src, LLColor4U& dst) +{ + dst.set(src[0], src[1], src[2], 255); +} + +template<> +void copyVec4(F32* src, LLVector4a& dst) +{ + dst.loadua(src); +} + +// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy +template +void copyVec2(S* src, LLStrider dst, S32 stride, S32 count) +{ + for (S32 i = 0; i < count; ++i) + { + copyVec2(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } +} + +// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy +template +void copyVec3(S* src, LLStrider dst, S32 stride, S32 count) +{ + for (S32 i = 0; i < count; ++i) + { + copyVec3(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } +} + +// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy +template +void copyVec4(S* src, LLStrider dst, S32 stride, S32 count) +{ + for (S32 i = 0; i < count; ++i) + { + copyVec3(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } +} + +template +void copyAttributeArray(Asset& asset, const Accessor& accessor, const S* src, LLStrider& dst, S32 byteStride) +{ + if (accessor.mType == TINYGLTF_TYPE_VEC2) + { + S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride; + copyVec2((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == TINYGLTF_TYPE_VEC3) + { + S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride; + copyVec3((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == TINYGLTF_TYPE_VEC4) + { + S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride; + copyVec4((S*)src, dst, stride, accessor.mCount); + } + else + { + LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; + } +} + +template +void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider& dst) +{ + const Accessor& accessor = asset.mAccessors[accessorIdx]; + const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; + const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; + + if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT) + { + copyAttributeArray(asset, accessor, (const F32*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) + { + copyAttributeArray(asset, accessor, (const U16*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) + { + copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); + } + else + + { + LL_ERRS() << "Unsupported component type" << LL_ENDL; + } +} + +void Primitive::allocateGLResources(Asset& asset) +{ + // allocate vertex buffer + // We diverge from the intent of the GLTF format here to work with our existing render pipeline + // GLTF wants us to copy the buffer views into GPU storage as is and build render commands that source that data. + // For our engine, though, it's better to rearrange the buffers at load time into a layout that's more consistent. + // The GLTF native approach undoubtedly works well if you can count on VAOs, but VAOs perform much worse with our scenes. + + // get the number of vertices + U32 numVertices = 0; + for (auto& it : mAttributes) + { + const Accessor& accessor = asset.mAccessors[it.second]; + numVertices = accessor.mCount; + break; + } + + // get the number of indices + U32 numIndices = 0; + if (mIndices != INVALID_INDEX) + { + const Accessor& accessor = asset.mAccessors[mIndices]; + numIndices = accessor.mCount; + } + + // create vertex buffer + mVertexBuffer = new LLVertexBuffer(ATTRIBUTE_MASK); + mVertexBuffer->allocateBuffer(numVertices, numIndices); + + bool needs_color = true; + bool needs_texcoord = true; + bool needs_normal = true; + bool needs_tangent = true; + + // load vertex data + for (auto& it : mAttributes) + { + const std::string& attribName = it.first; + + // load vertex data + if (attribName == "POSITION") + { + // load position data + LLStrider dst; + mVertexBuffer->getVertexStrider(dst); + + copyAttribute(asset, it.second, dst); + } + else if (attribName == "NORMAL") + { + needs_normal = false; + // load normal data + LLStrider dst; + mVertexBuffer->getNormalStrider(dst); + + copyAttribute(asset, it.second, dst); + } + else if (attribName == "TANGENT") + { + needs_tangent = false; + // load tangent data + + LLStrider dst; + mVertexBuffer->getTangentStrider(dst); + + copyAttribute(asset, it.second, dst); + } + else if (attribName == "COLOR_0") + { + needs_color = false; + // load color data + + LLStrider dst; + mVertexBuffer->getColorStrider(dst); + + copyAttribute(asset, it.second, dst); + } + else if (attribName == "TEXCOORD_0") + { + needs_texcoord = false; + // load texcoord data + LLStrider dst; + mVertexBuffer->getTexCoord0Strider(dst); + + LLStrider tc = dst; + copyAttribute(asset, it.second, dst); + + // convert to OpenGL coordinate space + for (U32 i = 0; i < numVertices; ++i) + { + tc->mV[1] = 1.0f - tc->mV[1];; + tc++; + } + } + } + + // copy index buffer + if (mIndices != INVALID_INDEX) + { + const Accessor& accessor = asset.mAccessors[mIndices]; + const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; + const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + + const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; + + LLStrider dst; + mVertexBuffer->getIndexStrider(dst); + mIndexArray.resize(numIndices); + + if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) + { + for (U32 i = 0; i < numIndices; ++i) + { + *(dst++) = (U16) * (U32*)src; + src += sizeof(U32); + } + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) + { + for (U32 i = 0; i < numIndices; ++i) + { + *(dst++) = *(U16*)src; + src += sizeof(U16); + } + } + else + { + LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL; + } + + U16* idx = (U16*)mVertexBuffer->getMappedIndices(); + for (U32 i = 0; i < numIndices; ++i) + { + mIndexArray[i] = idx[i]; + } + } + + // fill in default values for missing attributes + if (needs_color) + { // set default color + LLStrider dst; + mVertexBuffer->getColorStrider(dst); + for (U32 i = 0; i < numVertices; ++i) + { + *(dst++) = LLColor4U(255, 255, 255, 255); + } + } + + if (needs_texcoord) + { // set default texcoord + LLStrider dst; + mVertexBuffer->getTexCoord0Strider(dst); + for (U32 i = 0; i < numVertices; ++i) + { + *(dst++) = LLVector2(0.0f, 0.0f); + } + } + + if (needs_normal) + { // set default normal + LLStrider dst; + mVertexBuffer->getNormalStrider(dst); + for (U32 i = 0; i < numVertices; ++i) + { + *(dst++) = LLVector4a(0.0f, 0.0f, 1.0f, 0.0f); + } + } + + if (needs_tangent) + { // TODO: generate tangents if needed + LLStrider dst; + mVertexBuffer->getTangentStrider(dst); + for (U32 i = 0; i < numVertices; ++i) + { + *(dst++) = LLVector4a(1.0f, 0.0f, 0.0f, 1.0f); + } + } + + mPositions.resize(numVertices); + mTexCoords.resize(numVertices); + mNormals.resize(numVertices); + mTangents.resize(numVertices); + + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + LLVector2* tc = (LLVector2*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TEXCOORD0)); + LLVector4a* norm = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_NORMAL)); + LLVector4a* tangent = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TANGENT)); + for (U32 i = 0; i < numVertices; ++i) + { + mPositions[i] = pos[i]; + mTexCoords[i] = tc[i]; + mNormals[i] = norm[i]; + mTangents[i] = tangent[i]; + } + createOctree(); + + mVertexBuffer->unmapBuffer(); +} + +void Primitive::createOctree() +{ + // create octree + mOctree = new LLVolumeOctree(); + + if (mMode == TINYGLTF_MODE_TRIANGLES) + { + F32 scaler = 0.25f; + + const U32 num_triangles = mVertexBuffer->getNumIndices() / 3; + // Initialize all the triangles we need + mOctreeTriangles.resize(num_triangles); + + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + U16* indices = (U16*)mVertexBuffer->getMappedIndices(); + + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) + { //for each triangle + const U32 index = triangle_index * 3; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; + const LLVector4a& v0 = pos[indices[index]]; + const LLVector4a& v1 = pos[indices[index + 1]]; + const LLVector4a& v2 = pos[indices[index + 2]]; + + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = indices[index]; + tri->mIndex[1] = indices[index + 1]; + tri->mIndex[2] = indices[index + 2]; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max, min); + + tri->mRadius = size.getLength3().getF32() * scaler; + + //insert + mOctree->insert(tri); + } + } + else + { + LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL; + } + + //remove unneeded octree layers + while (!mOctree->balance()) {} + + //calculate AABB for each node + LLVolumeOctreeRebound rebound; + rebound.traverse(mOctree); +} + +const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out) +{ + if (mOctree.isNull()) + { + return nullptr; + } + + LLVector4a dir; + dir.setSub(end, start); + + F32 closest_t = 2.f; // must be larger than 1 + + //create a proxy LLVolumeFace for the raycast + LLVolumeFace face; + face.mPositions = mPositions.data(); + face.mTexCoords = mTexCoords.data(); + face.mNormals = mNormals.data(); + face.mTangents = mTangents.data(); + face.mIndices = mIndexArray.data(); + + face.mNumIndices = mIndexArray.size(); + face.mNumVertices = mPositions.size(); + + LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); + intersect.traverse(mOctree); + + // null out proxy data so it doesn't get freed + face.mPositions = face.mNormals = face.mTangents = nullptr; + face.mIndices = nullptr; + face.mTexCoords = nullptr; + + return intersect.mHitTriangle; +} + +Primitive::~Primitive() +{ + mOctree = nullptr; +} + diff --git a/indra/newview/gltf/primitive.h b/indra/newview/gltf/primitive.h new file mode 100644 index 0000000000..7c47d9dac5 --- /dev/null +++ b/indra/newview/gltf/primitive.h @@ -0,0 +1,140 @@ +#pragma once + +/** + * @file primitive.h + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "llvertexbuffer.h" +#include "llvolumeoctree.h" + +// LL GLTF Implementation +namespace LL +{ + namespace GLTF + { + class Asset; + + constexpr U32 ATTRIBUTE_MASK = + LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_TANGENT | + LLVertexBuffer::MAP_COLOR; + + class Primitive + { + public: + ~Primitive(); + + // GPU copy of mesh data + LLPointer mVertexBuffer; + + // CPU copy of mesh data + std::vector mTexCoords; + std::vector mNormals; + std::vector mTangents; + std::vector mPositions; + std::vector mIndexArray; + + // raycast acceleration structure + LLPointer mOctree; + std::vector mOctreeTriangles; + + S32 mMaterial = -1; + U32 mMode = TINYGLTF_MODE_TRIANGLES; // default to triangles + U32 mGLMode = LLRender::TRIANGLES; + S32 mIndices = -1; + std::unordered_map mAttributes; + + // copy the attribute in the given BufferView to the given destination + // assumes destination has enough storage for the attribute + template + void copyAttribute(Asset& asset, S32 bufferViewIdx, LLStrider& dst); + + // create octree based on vertex buffer + // must be called before buffer is unmapped and after buffer is populated with good data + void createOctree(); + + //get the LLVolumeTriangle that intersects with the given line segment at the point + //closest to start. Moves end to the point of intersection. Returns nullptr if no intersection. + //Line segment must be in the same coordinate frame as this Primitive + const LLVolumeTriangle* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + const Primitive& operator=(const tinygltf::Primitive& src) + { + // load material + mMaterial = src.material; + + // load mode + mMode = src.mode; + + // load indices + mIndices = src.indices; + + // load attributes + for (auto& it : src.attributes) + { + mAttributes[it.first] = it.second; + } + + switch (mMode) + { + case TINYGLTF_MODE_POINTS: + mGLMode = LLRender::POINTS; + break; + case TINYGLTF_MODE_LINE: + mGLMode = LLRender::LINES; + break; + case TINYGLTF_MODE_LINE_LOOP: + mGLMode = LLRender::LINE_LOOP; + break; + case TINYGLTF_MODE_LINE_STRIP: + mGLMode = LLRender::LINE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLES: + mGLMode = LLRender::TRIANGLES; + break; + case TINYGLTF_MODE_TRIANGLE_STRIP: + mGLMode = LLRender::TRIANGLE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLE_FAN: + mGLMode = LLRender::TRIANGLE_FAN; + break; + default: + mGLMode = GL_TRIANGLES; + } + + return *this; + } + + void allocateGLResources(Asset& asset); + }; + } +} diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp new file mode 100644 index 0000000000..429c9118f8 --- /dev/null +++ b/indra/newview/gltfscenemanager.cpp @@ -0,0 +1,469 @@ +/** + * @file gltfscenemanager.cpp + * @brief Builds menus out of items. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "gltfscenemanager.h" +#include "llviewermenufile.h" +#include "llappviewer.h" +#include "lltinygltfhelper.h" +#include "llvertexbuffer.h" +#include "llselectmgr.h" +#include "llagent.h" +#include "llnotificationsutil.h" +#include "llvoavatarself.h" +#include "llvolumeoctree.h" +#include "gltf/asset.h" +#include "pipeline.h" +#include "llviewershadermgr.h" + + +using namespace LL; + +// temporary location of LL GLTF Implementation +using namespace LL::GLTF; + +void GLTFSceneManager::load() +{ + LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject(); + + if (obj) + { + // Load a scene from disk + LLFilePickerReplyThread::startPicker( + [](const std::vector& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter) + { + if (LLAppViewer::instance()->quitRequested()) + { + return; + } + if (filenames.size() > 0) + { + GLTFSceneManager::instance().load(filenames[0]); + } + }, + LLFilePicker::FFLOAD_GLTF, + true); + } + else + { + LLNotificationsUtil::add("GLTFPreviewSelection"); + } +} + +void GLTFSceneManager::load(const std::string& filename) +{ + tinygltf::Model model; + LLTinyGLTFHelper::loadModel(filename, model); + + LLPointer asset = new Asset(); + *asset = model; + + asset->allocateGLResources(filename, model); + asset->updateTransforms(); + + // hang the asset off the currently selected object, or off of the avatar if no object is selected + LLViewerObject* obj = LLSelectMgr::instance().getSelection()->getFirstRootObject(); + + if (obj) + { // assign to self avatar + obj->mGLTFAsset = asset; + mObjects.push_back(obj); + } +} + +GLTFSceneManager::~GLTFSceneManager() +{ + mObjects.clear(); +} + +LLMatrix4a getAssetToAgentTransform(LLViewerObject* obj) +{ + LLMatrix4 root; + root.initScale(obj->getScale()); + root.rotate(obj->getRenderRotation()); + root.translate(obj->getPositionAgent()); + + LLMatrix4a mat; + mat.loadu((F32*) root.mMatrix); + + return mat; +} + +LLMatrix4a getAgentToAssetTransform(LLViewerObject* obj) +{ + LLMatrix4 root; + LLVector3 scale = obj->getScale(); + scale.mV[0] = 1.f / scale.mV[0]; + scale.mV[1] = 1.f / scale.mV[1]; + scale.mV[2] = 1.f / scale.mV[2]; + + root.translate(-obj->getPositionAgent()); + root.rotate(~obj->getRenderRotation()); + + LLMatrix4 scale_mat; + scale_mat.initScale(scale); + + root *= scale_mat; + + + LLMatrix4a mat; + mat.loadu((F32*) root.mMatrix); + + return mat; +} + +void GLTFSceneManager::renderOpaque() +{ + // for debugging, just render the whole scene as opaque + // by traversing the whole scenegraph + // Assumes camera transform is already set and + // appropriate shader is already bound + + gGL.matrixMode(LLRender::MM_MODELVIEW); + + for (U32 i = 0; i < mObjects.size(); ++i) + { + if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr) + { + mObjects.erase(mObjects.begin() + i); + --i; + continue; + } + + Asset* asset = mObjects[i]->mGLTFAsset; + + gGL.pushMatrix(); + + LLMatrix4a mat = getAssetToAgentTransform(mObjects[i]); + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + + matMul(mat, modelview, modelview); + + asset->updateRenderTransforms(modelview); + asset->renderOpaque(); + + gGL.popMatrix(); + } +} + +LLMatrix4a inverse(const LLMatrix4a& mat) +{ + glh::matrix4f m((F32*)mat.mMatrix); + m = m.inverse(); + LLMatrix4a ret; + ret.loadu(m.m); + return ret; +} + +bool GLTFSceneManager::lineSegmentIntersect(LLVOVolume* obj, Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* node_hit, S32* primitive_hit, + LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + +{ + // line segment intersection test + // start and end should be in agent space + // volume space and asset space should be the same coordinate frame + // results should be transformed back to agent space + + bool ret = false; + + LLVector4a local_start; + LLVector4a local_end; + + LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj); + LLMatrix4a agent_to_asset = inverse(asset_to_agent); + + agent_to_asset.affineTransform(start, local_start); + agent_to_asset.affineTransform(end, local_end); + + LLVector4a p; + LLVector4a n; + LLVector2 tc; + LLVector4a tn; + + if (intersection != NULL) + { + p = *intersection; + } + + if (tex_coord != NULL) + { + tc = *tex_coord; + } + + if (normal != NULL) + { + n = *normal; + } + + if (tangent != NULL) + { + tn = *tangent; + } + + S32 hit_node_index = asset->lineSegmentIntersect(local_start, local_end, &p, &tc, &n, &tn, primitive_hit); + + if (hit_node_index >= 0) + { + local_end = p; + if (node_hit != NULL) + { + *node_hit = hit_node_index; + } + + if (intersection != NULL) + { + asset_to_agent.affineTransform(p, *intersection); + } + + if (normal != NULL) + { + LLVector3 v_n(n.getF32ptr()); + normal->load3(obj->volumeDirectionToAgent(v_n).mV); + (*normal).normalize3fast(); + } + + if (tangent != NULL) + { + LLVector3 v_tn(tn.getF32ptr()); + + LLVector4a trans_tangent; + trans_tangent.load3(obj->volumeDirectionToAgent(v_tn).mV); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + tangent->setSelectWithMask(mask, tn, trans_tangent); + (*tangent).normalize3fast(); + } + + if (tex_coord != NULL) + { + *tex_coord = tc; + } + + ret = true; + } + + return ret; +} + +LLDrawable* GLTFSceneManager::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_unselectable, + BOOL pick_reflection_probe, + S32* node_hit, // return the index of the node that was hit + S32* primitive_hit, // return the index of the primitive that was hit + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent) // return the surface tangent at the intersection point +{ + LLDrawable* drawable = nullptr; + + LLVector4a local_end = end; + LLVector4a position; + + for (U32 i = 0; i < mObjects.size(); ++i) + { + if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr || !mObjects[i]->getVolume()) + { + mObjects.erase(mObjects.begin() + i); + --i; + continue; + } + + // temporary debug -- always double check objects that have GLTF scenes hanging off of them even if the ray doesn't intersect the object bounds + if (lineSegmentIntersect((LLVOVolume*) mObjects[i].get(), mObjects[i]->mGLTFAsset, start, local_end, -1, pick_transparent, pick_rigged, pick_unselectable, node_hit, primitive_hit, &position, tex_coord, normal, tangent)) + { + local_end = position; + if (intersection) + { + *intersection = position; + } + drawable = mObjects[i]->mDrawable; + } + } + + return drawable; +} + +void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size); + +extern LLVector4a gDebugRaycastStart; +extern LLVector4a gDebugRaycastEnd; + +void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree); + +void renderAssetDebug(LLViewerObject* obj, Asset* asset) +{ + // render debug + // assumes appropriate shader is already bound + // assumes modelview matrix is already set + + gGL.pushMatrix(); + + // get raycast in asset space + LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj); + LLMatrix4a agent_to_asset = getAgentToAssetTransform(obj); + + LLVector4a start; + LLVector4a end; + + agent_to_asset.affineTransform(gDebugRaycastStart, start); + agent_to_asset.affineTransform(gDebugRaycastEnd, end); + + + for (auto& node : asset->mNodes) + { + Mesh& mesh = asset->mMeshes[node.mMesh]; + + if (node.mMesh != INVALID_INDEX) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + + // draw bounding box of mesh primitives + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + gGL.color3f(0.f, 1.f, 1.f); + + for (auto& primitive : mesh.mPrimitives) + { + auto* listener = (LLVolumeOctreeListener*) primitive.mOctree->getListener(0); + + LLVector4a center = listener->mBounds[0]; + LLVector4a size = listener->mBounds[1]; + + drawBoxOutline(center, size); + } + } + +#if 0 + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + // convert raycast to node local space + LLVector4a local_start; + LLVector4a local_end; + + node.mAssetMatrixInv.affineTransform(start, local_start); + node.mAssetMatrixInv.affineTransform(end, local_end); + + for (auto& primitive : mesh.mPrimitives) + { + if (primitive.mOctree.notNull()) + { + renderOctreeRaycast(local_start, local_end, primitive.mOctree); + } + } + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } +#endif + } + } + + gGL.popMatrix(); +} + +void GLTFSceneManager::renderDebug() +{ + if (!gPipeline.hasRenderDebugMask( + LLPipeline::RENDER_DEBUG_BBOXES | + LLPipeline::RENDER_DEBUG_RAYCAST)) + { + return; + } + + gDebugProgram.bind(); + + LLGLDisable cullface(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gPipeline.disableLights(); + + for (auto& obj : mObjects) + { + if (obj->isDead() || obj->mGLTFAsset == nullptr) + { + continue; + } + + Asset* asset = obj->mGLTFAsset; + + + LLMatrix4a mat = getAssetToAgentTransform(obj); + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + + matMul(mat, modelview, modelview); + + asset->updateRenderTransforms(modelview); + renderAssetDebug(obj, asset); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + S32 node_hit = -1; + S32 primitive_hit = -1; + LLVector4a intersection; + + LLDrawable* drawable = lineSegmentIntersect(gDebugRaycastStart, gDebugRaycastEnd, TRUE, TRUE, TRUE, TRUE, &node_hit, &primitive_hit, &intersection, nullptr, nullptr, nullptr); + + if (drawable) + { + gGL.pushMatrix(); + Asset* asset = drawable->getVObj()->mGLTFAsset; + Node* node = &asset->mNodes[node_hit]; + Primitive* primitive = &asset->mMeshes[node->mMesh].mPrimitives[primitive_hit]; + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.color3f(1, 0, 1); + drawBoxOutline(intersection, LLVector4a(0.1f, 0.1f, 0.1f, 0.f)); + + gGL.loadMatrix((F32*) node->mRenderMatrix.mMatrix); + + + + auto* listener = (LLVolumeOctreeListener*) primitive->mOctree->getListener(0); + drawBoxOutline(listener->mBounds[0], listener->mBounds[1]); + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.popMatrix(); + } + } + gDebugProgram.unbind(); +} + diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h new file mode 100644 index 0000000000..50e1dd93da --- /dev/null +++ b/indra/newview/gltfscenemanager.h @@ -0,0 +1,64 @@ +#pragma once + +/** + * @file gltfscenemanager.h + * @brief Builds menus out of items. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "llsingleton.h" +#include "llviewerobject.h" + +namespace LL +{ + class GLTFSceneManager : public LLSimpleton + { + public: + ~GLTFSceneManager(); + // load GLTF file from disk + void load(); // open filepicker to choose asset + void load(const std::string& filename); // load asset from filename + void renderOpaque(); + + LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_unselectable, + BOOL pick_reflection_probe, + S32* node_hit, // return the index of the node that was hit + S32* primitive_hit, // return the index of the primitive that was hit + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent); // return the surface tangent at the intersection point + + bool lineSegmentIntersect(LLVOVolume* obj, GLTF::Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* face_hitp, S32* primitive_hitp, + LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); + + void renderDebug(); + + std::vector> mObjects; + }; +} + + diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 31d9804fe3..46b95601af 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -240,6 +240,8 @@ #include "llavatariconctrl.h" #include "llgroupiconctrl.h" #include "llviewerassetstats.h" +#include "gltfscenemanager.h" + #include "workqueue.h" using namespace LL; @@ -1280,6 +1282,8 @@ bool LLAppViewer::init() LLWorld::createInstance(); LLSelectMgr::createInstance(); LLViewerCamera::createInstance(); + LL::GLTFSceneManager::createInstance(); + #if LL_WINDOWS if (!mSecondInstance) @@ -2155,7 +2159,7 @@ bool LLAppViewer::cleanup() ll_close_fail_log(); LLError::LLCallStacks::cleanup(); - + LL::GLTFSceneManager::deleteSingleton(); LLEnvironment::deleteSingleton(); LLSelectMgr::deleteSingleton(); LLViewerEventRecorder::deleteSingleton(); diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp index 86b790e2c5..a32382af92 100644 --- a/indra/newview/lldrawpoolpbropaque.cpp +++ b/indra/newview/lldrawpoolpbropaque.cpp @@ -30,6 +30,7 @@ #include "lldrawpoolpbropaque.h" #include "llviewershadermgr.h" #include "pipeline.h" +#include "gltfscenemanager.h" LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR(U32 type) : LLRenderPass(type) @@ -54,8 +55,11 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass) llassert(!LLPipeline::sRenderingHUDs); gDeferredPBROpaqueProgram.bind(); + + LL::GLTFSceneManager::instance().renderOpaque(); pushGLTFBatches(mRenderType); + gDeferredPBROpaqueProgram.bind(true); pushRiggedGLTFBatches(mRenderType + 1); } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index fec550ae50..f3b5bb0565 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2866,10 +2866,8 @@ void renderLights(LLDrawable* drawablep) class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect { public: - - LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) - : LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL) + : LLOctreeTriangleRayIntersect(start, dir, nullptr, closest_t, NULL, NULL, NULL, NULL) { } @@ -2893,7 +2891,7 @@ public: size.set(vl->mBounds[1].getF32ptr()); } - drawBoxOutline(center, size); + drawBoxOutline(center, size); for (U32 i = 0; i < 2; i++) { @@ -2937,6 +2935,13 @@ public: } }; +void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree) +{ + F32 t = 1.f; + LLRenderOctreeRaycast render(start, end, &t); + render.traverse(octree); +} + void renderRaycast(LLDrawable* drawablep) { if (drawablep->getNumFaces()) @@ -2994,29 +2999,22 @@ void renderRaycast(LLDrawable* drawablep) dir.setSub(end, start); gGL.flush(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); { //render face positions - LLVertexBuffer::unbind(); - gGL.diffuseColor4f(0,1,1,0.5f); - glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions); - gGL.syncMatrices(); - glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); + //gGL.diffuseColor4f(0,1,1,0.5f); + //LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, nullptr, face.mNumIndices, face.mIndices); } if (!volume->isUnique()) { - F32 t = 1.f; - if (!face.getOctree()) { ((LLVolumeFace*) &face)->createOctree(); } - LLRenderOctreeRaycast render(start, dir, &t); - - render.traverse(face.getOctree()); + renderOctreeRaycast(start, end, face.getOctree()); } gGL.popMatrix(); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 5b75db37d0..40e6f285a8 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -147,7 +147,7 @@ const tinygltf::Image * LLTinyGLTFHelper::getImageFromTextureIndex(const tinyglt return nullptr; } -LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name) +LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, std::string & name, bool flip) { const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index); LLImageRaw* rawImage = nullptr; @@ -159,14 +159,17 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny { name = image->name; rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); - rawImage->verticalFlip(); + if (flip) + { + rawImage->verticalFlip(); + } rawImage->optimizeAwayAlpha(); } return rawImage; } -LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index) +LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tinygltf::Model & model, S32 texture_index, bool flip) { const tinygltf::Image* image = getImageFromTextureIndex(model, texture_index); LLImageRaw* rawImage = nullptr; @@ -177,7 +180,10 @@ LLImageRaw * LLTinyGLTFHelper::getTexture(const std::string & folder, const tiny image->component <= 4) { rawImage = new LLImageRaw(&image->image[0], image->width, image->height, image->component); - rawImage->verticalFlip(); + if (flip) + { + rawImage->verticalFlip(); + } rawImage->optimizeAwayAlpha(); } @@ -237,7 +243,8 @@ bool LLTinyGLTFHelper::getMaterialFromModel( const tinygltf::Model& model_in, S32 mat_index, LLFetchedGLTFMaterial* material, - std::string& material_name) + std::string& material_name, + bool flip) { llassert(material); @@ -256,18 +263,18 @@ bool LLTinyGLTFHelper::getMaterialFromModel( material_name = material_in.name; // get base color texture - LLPointer base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index); + LLPointer base_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.baseColorTexture.index, flip); // get normal map - LLPointer normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index); + LLPointer normal_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.normalTexture.index, flip); // get metallic-roughness texture - LLPointer mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index); + LLPointer mr_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.pbrMetallicRoughness.metallicRoughnessTexture.index, flip); // get emissive texture - LLPointer emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index); + LLPointer emissive_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.emissiveTexture.index, flip); // get occlusion map if needed LLPointer occlusion_img; if (material_in.occlusionTexture.index != material_in.pbrMetallicRoughness.metallicRoughnessTexture.index) { - occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index); + occlusion_img = LLTinyGLTFHelper::getTexture(folder, model_in, material_in.occlusionTexture.index, flip); } LLPointer base_color_tex; diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h index 256f6c854f..da505b41e9 100644 --- a/indra/newview/lltinygltfhelper.h +++ b/indra/newview/lltinygltfhelper.h @@ -38,10 +38,8 @@ namespace LLTinyGLTFHelper { LLColor4 getColor(const std::vector& in); const tinygltf::Image* getImageFromTextureIndex(const tinygltf::Model& model, S32 texture_index); - LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name); - LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); - - LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index); + LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name, bool flip = true); + LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, bool flip = true); bool loadModel(const std::string& filename, tinygltf::Model& model_out); @@ -50,7 +48,8 @@ namespace LLTinyGLTFHelper const tinygltf::Model& model, S32 mat_index, LLFetchedGLTFMaterial* material, - std::string& material_name); + std::string& material_name, + bool flip = true); void initFetchedTextures(tinygltf::Material& material, LLPointer& base_color_img, diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 37d02cd911..4cf948f20d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -140,6 +140,7 @@ #include #include "llcleanup.h" #include "llviewershadermgr.h" +#include "gltfscenemanager.h" using namespace LLAvatarAppearanceDefines; @@ -7921,6 +7922,17 @@ class LLAdvancedClickHDRIPreview: public view_listener_t } }; + +class LLAdvancedClickGLTFScenePreview : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + // open personal lighting floater when previewing an HDRI (keeps HDRI from implicitly unloading when opening build tools) + LL::GLTFSceneManager::instance().load(); + return true; + } +}; + // these are used in the gl menus to set control values that require shader recompilation class LLToggleShaderControl : public view_listener_t { @@ -9568,6 +9580,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview"); + view_listener_t::addMenu(new LLAdvancedClickGLTFScenePreview(), "Advanced.ClickGLTFScenePreview"); view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 0c4d958aed..3d6903d177 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -45,6 +45,7 @@ #include "llbbox.h" #include "llrigginginfo.h" #include "llreflectionmap.h" +#include "gltf/asset.h" class LLAgent; // TODO: Get rid of this. class LLAudioSource; @@ -722,6 +723,8 @@ public: F32 mPhysicsDensity; F32 mPhysicsRestitution; + // Associated GLTF Asset + LLPointer mGLTFAsset; // Pipeline classes LLPointer mDrawable; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d4390c46cb..bcecd3a7fe 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4606,7 +4606,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, BOOL pick_unselectable, S32 *face_hitp, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) { if (!mbCanSelect @@ -4814,7 +4814,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& } } } - + return ret; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 85f4ccd86f..37bdcbf88c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -112,6 +112,7 @@ #include "llscenemonitor.h" #include "llprogressview.h" #include "llcleanup.h" +#include "gltfscenemanager.h" #include "llenvironment.h" #include "llsettingsvo.h" @@ -4530,6 +4531,8 @@ void LLPipeline::renderDebug() } } + LL::GLTFSceneManager::instance().renderDebug(); + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { //render visible selected group occlusion geometry gDebugProgram.bind(); @@ -6341,6 +6344,15 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, } } } + + S32 node_hit = -1; + S32 primitive_hit = -1; + LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + local_end = position; + } if (!sPickAvatar) { @@ -6557,6 +6569,11 @@ void LLPipeline::renderGLTFObjects(U32 type, bool texture, bool rigged) gGL.loadMatrix(gGLModelView); gGLLastMatrix = NULL; + + if (!rigged) + { + LL::GLTFSceneManager::instance().renderOpaque(); + } } // Currently only used for shadows -Cosmic,2023-04-19 diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 145276db57..c2f04231fc 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2846,6 +2846,12 @@ function="World.EnvPreset" + + + - + + + You must select an object to act as a handle to the GLTF asset you are previewing. + fail + + + -- cgit v1.2.3 From 720f7d7ef5d06366cdbae51cd67a6883e994880b Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 10 Apr 2024 11:25:07 -0500 Subject: Fix mac build (#1182) * Fix mac build * Mac build take 2 * Mac build take 3 --- indra/newview/gltf/asset.cpp | 2 ++ indra/newview/gltf/primitive.cpp | 16 ++++++++++------ indra/newview/gltfscenemanager.cpp | 3 ++- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 18f814c5b6..092b6e5d4b 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -24,6 +24,8 @@ * $/LicenseInfo$ */ +#include "../llviewerprecompiledheaders.h" + #include "asset.h" #include "llvolumeoctree.h" diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index dca3ccf706..71654dcfdd 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -9,7 +9,7 @@ * 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. + * 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 @@ -24,34 +24,38 @@ * $/LicenseInfo$ */ +#include "../llviewerprecompiledheaders.h" + #include "asset.h" #include "../lltinygltfhelper.h" using namespace LL::GLTF; -#ifndef __PRETTY_FUNCTION__ -#define __PRETTY_FUNCTION__ __FUNCSIG__ +#ifdef _MSC_VER +#define LL_FUNCSIG __FUNCSIG__ +#else +#define LL_FUNCSIG __PRETTY_FUNCTION__ #endif // copy one vec3 from src to dst template void copyVec2(S* src, T& dst) { - LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; } // copy one vec3 from src to dst template void copyVec3(S* src, T& dst) { - LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; } // copy one vec4 from src to dst template void copyVec4(S* src, T& dst) { - LL_ERRS() << "TODO: implement " << __PRETTY_FUNCTION__ << LL_ENDL; + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; } template<> diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 429c9118f8..6c44b83646 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -24,6 +24,8 @@ * $/LicenseInfo$ */ +#include "llviewerprecompiledheaders.h" + #include "gltfscenemanager.h" #include "llviewermenufile.h" #include "llappviewer.h" @@ -329,7 +331,6 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) gGL.pushMatrix(); // get raycast in asset space - LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj); LLMatrix4a agent_to_asset = getAgentToAssetTransform(obj); LLVector4a start; -- cgit v1.2.3 From 7ef2b43802da07b8f30b455448cb84bd1c26320d Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 10 Apr 2024 15:21:59 -0700 Subject: Multiple fixes for mirrors. (#1192) * #1064 Fix for mirror surfaces going black when the roughness is set too high. * #1130 Fix for the user's avatar not appearing in mouselook in a mirror. * #1059 Disable mirrors on low settings per the feature table. * #860 Modify the settings UI to better reflect that we only have two AA modes: off and FXAA. * #1191 Add some settings for mirrors in preferences. * #1185 Add support for runtime mirror resolution changing. Useful for quality settings, and auto-FPS. --- .../shaders/class3/deferred/reflectionProbeF.glsl | 2 +- indra/newview/featuretable.txt | 38 +++++ indra/newview/featuretable_mac.txt | 38 +++++ indra/newview/llheroprobemanager.cpp | 30 +++- indra/newview/llheroprobemanager.h | 3 + indra/newview/llviewercontrol.cpp | 14 ++ indra/newview/llvoavatarself.cpp | 2 +- indra/newview/pipeline.cpp | 7 + .../en/floater_preferences_graphics_advanced.xml | 183 +++++++++++++++------ 9 files changed, 259 insertions(+), 58 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 4f2475b101..90c84cc428 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -717,7 +717,7 @@ void tapHeroProbe(inout vec3 glossenv, vec3 pos, vec3 norm, float glossiness) clipDist = clipDist * 0.95 + 0.05; clipDist = clamp(clipDist * falloffMult, 0, 1); w = clamp(w * falloffMult * clipDist, 0, 1); - + w = mix(0, w, clamp(glossiness - 0.75, 0, 1) * 4); // We only generate a quarter of the mips for the hero probes. Linearly interpolate between normal probes and hero probes based upon glossiness. glossenv = mix(glossenv, textureLod(heroProbes, vec4(env_mat * refnormpersp, 0), (1.0-glossiness)*heroMipCount).xyz, w); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 965391b5cf..3e1e235fcd 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -107,6 +107,11 @@ WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 256 +RenderHeroProbeDistance 1 4 +RenderHeroProbeUpdateRate 1 4 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium Low Graphics Settings @@ -138,6 +143,11 @@ WLSkyDetail 1 96 RenderFSAASamples 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 256 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 3 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium Graphics Settings (standard) @@ -169,6 +179,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 1 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 512 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 3 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium High Graphics Settings @@ -200,6 +215,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 2 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 512 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 2 +RenderHeroProbeConservativeUpdateMultiplier 1 8 // // High Graphics Settings (SSAO + sun shadows) @@ -231,6 +251,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 1024 +RenderHeroProbeDistance 1 8 +RenderHeroProbeUpdateRate 1 2 +RenderHeroProbeConservativeUpdateMultiplier 1 8 // // High Ultra Graphics Settings (deferred + SSAO + all shadows) @@ -262,6 +287,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 1024 +RenderHeroProbeDistance 1 16 +RenderHeroProbeUpdateRate 1 1 +RenderHeroProbeConservativeUpdateMultiplier 1 4 // // Ultra graphics (REALLY PURTY!) @@ -293,6 +323,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 +RenderMirrors 1 1 +RenderHeroProbeResolution 1 2048 +RenderHeroProbeDistance 1 16 +RenderHeroProbeUpdateRate 1 1 +RenderHeroProbeConservativeUpdateMultiplier 1 4 // // Class Unknown Hardware (unknown) @@ -301,6 +336,7 @@ list Unknown RenderShadowDetail 1 0 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 +RenderMirrors 1 0 // // VRAM > 512MB @@ -322,6 +358,7 @@ RenderTransparentWater 1 0 RenderDeferredSSAO 0 0 RenderShadowDetail 0 0 RenderReflectionProbeDetail 0 -1 +RenderMirrors 0 0 list Intel RenderAnisotropic 1 0 @@ -336,6 +373,7 @@ list GL3 RenderFSAASamples 0 0 RenderReflectionsEnabled 0 0 RenderReflectionProbeDetail 0 0 +RenderMirrors 0 0 list TexUnit16orLess RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 61cde82512..2ffefadcc1 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -105,6 +105,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 256 +RenderHeroProbeDistance 1 4 +RenderHeroProbeUpdateRate 1 4 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium Low Graphics Settings @@ -136,6 +141,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 256 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 3 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium Graphics Settings (standard) @@ -167,6 +177,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 512 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 3 +RenderHeroProbeConservativeUpdateMultiplier 1 16 // // Medium High Graphics Settings @@ -198,6 +213,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 0 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 512 +RenderHeroProbeDistance 1 6 +RenderHeroProbeUpdateRate 1 2 +RenderHeroProbeConservativeUpdateMultiplier 1 8 // // High Graphics Settings (SSAO + sun shadows) @@ -229,6 +249,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 1 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 1024 +RenderHeroProbeDistance 1 8 +RenderHeroProbeUpdateRate 1 2 +RenderHeroProbeConservativeUpdateMultiplier 1 8 // // High Ultra Graphics Settings (SSAO + all shadows) @@ -260,6 +285,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 2 +RenderMirrors 1 0 +RenderHeroProbeResolution 1 1024 +RenderHeroProbeDistance 1 16 +RenderHeroProbeUpdateRate 1 1 +RenderHeroProbeConservativeUpdateMultiplier 1 4 // // Ultra graphics (REALLY PURTY!) @@ -291,6 +321,11 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 +RenderMirrors 1 1 +RenderHeroProbeResolution 1 2048 +RenderHeroProbeDistance 1 16 +RenderHeroProbeUpdateRate 1 1 +RenderHeroProbeConservativeUpdateMultiplier 1 4 // // Class Unknown Hardware (unknown) @@ -299,6 +334,7 @@ list Unknown RenderShadowDetail 1 0 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 +RenderMirrors 1 0 // @@ -320,6 +356,7 @@ RenderTerrainDetail 1 0 RenderDeferredSSAO 0 0 RenderUseAdvancedAtmospherics 0 0 RenderShadowDetail 0 0 +RenderMirrors 0 0 list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -338,3 +375,4 @@ list GL3 RenderFSAASamples 0 0 RenderReflectionProbeDetail 0 0 RenderReflectionsEnabled 0 0 +RenderMirrors 0 0 diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 13c12b5e55..dd29b416fb 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -64,6 +64,14 @@ LLHeroProbeManager::LLHeroProbeManager() { } +LLHeroProbeManager::~LLHeroProbeManager() +{ + cleanup(); + + mHeroVOList.clear(); + mNearestHero = nullptr; +} + // helper class to seed octree with probes void LLHeroProbeManager::update() { @@ -84,8 +92,7 @@ void LLHeroProbeManager::update() if (!mRenderTarget.isComplete()) { U32 color_fmt = GL_RGBA16F; - U32 targetRes = mProbeResolution; // super sample - mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); + mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true); } if (mMipChain.empty()) @@ -472,12 +479,19 @@ void LLHeroProbeManager::renderDebug() gDebugProgram.unbind(); } + void LLHeroProbeManager::initReflectionMaps() { U32 count = LL_MAX_HERO_PROBE_COUNT; - if (mTexture.isNull() || mReflectionProbeCount != count || mReset) + if ((mTexture.isNull() || mReflectionProbeCount != count || mReset) && LLPipeline::RenderMirrors) { + + if (mReset) + { + cleanup(); + } + mReset = false; mReflectionProbeCount = count; mProbeResolution = gSavedSettings.getS32("RenderHeroProbeResolution"); @@ -546,9 +560,8 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - - mHeroVOList.clear(); - mNearestHero = nullptr; + /* + */ } void LLHeroProbeManager::doOcclusion() @@ -565,6 +578,11 @@ void LLHeroProbeManager::doOcclusion() } } +void LLHeroProbeManager::reset() +{ + mReset = true; +} + bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) { llassert(drawablep != nullptr); diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 17e75a18d4..d5e720e8e8 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -60,6 +60,7 @@ public: // allocate an environment map of the given resolution LLHeroProbeManager(); + ~LLHeroProbeManager(); // release any GL state void cleanup(); @@ -77,6 +78,8 @@ public: // perform occlusion culling on all active reflection probes void doOcclusion(); + void reset(); + bool registerViewerObject(LLVOVolume *drawablep); void unregisterViewerObject(LLVOVolume* drawablep); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index ba1add9b92..1fc51ac23c 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -437,6 +437,19 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue) gPipeline.createGLBuffers(); LLViewerShaderMgr::instance()->setShaders(); gPipeline.mReflectionMapManager.reset(); + gPipeline.mHeroProbeManager.reset(); + } + return true; +} + +static bool handleHeroProbeResolutionChanged(const LLSD &newvalue) +{ + if (gPipeline.isInit()) + { + LLPipeline::refreshCachedSettings(); + gPipeline.mHeroProbeManager.reset(); + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); } return true; } @@ -752,6 +765,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionProbeDetailChanged); setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged); + setting_setup_signal_listener(gSavedSettings, "RenderHeroProbeResolution", handleHeroProbeResolutionChanged); setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 7b24b9ee02..75a17cebe9 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1062,7 +1062,7 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) switch (camera_mode) { case CAMERA_MODE_MOUSELOOK: - if (LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) + if ((LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) || gPipeline.mHeroProbeManager.isMirrorPass()) { attachment->setAttachmentVisibility(TRUE); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 37bdcbf88c..ea40365c97 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -793,6 +793,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (RenderMirrors) { + mHeroProbeManager.initReflectionMaps(); res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. mRT = &mHeroProbeRT; allocateScreenBuffer(res, res, samples); @@ -1153,6 +1154,12 @@ void LLPipeline::releaseScreenBuffers() mRT->fxaaBuffer.release(); mRT->deferredScreen.release(); mRT->deferredLight.release(); + + mHeroProbeRT.uiScreen.release(); + mHeroProbeRT.screen.release(); + mHeroProbeRT.fxaaBuffer.release(); + mHeroProbeRT.deferredScreen.release(); + mHeroProbeRT.deferredLight.release(); } void LLPipeline::releaseSunShadowTarget(U32 index) 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 a3b18563d0..94c889f4e4 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 @@ -335,42 +335,10 @@ name="FSAADisabled" value="0" /> - - - - - (requires restart) - - - Mesh + Mesh - Low + Low - Low + Low - Low + Low - Low + Low + + (requires restart) + + Shaders @@ -747,6 +734,102 @@ width="260"> + + + + + + + Mirror Resolution: + + + + + + + + + + + Mirror Update Rate: + + + + + + + + + + Date: Wed, 10 Apr 2024 09:59:18 -0700 Subject: viewer#1163: Unboost terrain textures when done to allow deletion --- indra/newview/llvlcomposition.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'indra') diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 234b24e440..6c0691c6a9 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -69,6 +69,11 @@ namespace if (!tex) { return; } tex->setBoostLevel(LLGLTexture::BOOST_NONE); tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); + + if (tex->getTextureState() == LLGLTexture::NO_DELETE) + { + tex->forceActive(); + } } void unboost_minimap_material(LLPointer& mat) @@ -91,6 +96,11 @@ LLTerrainMaterials::LLTerrainMaterials() LLTerrainMaterials::~LLTerrainMaterials() { + for (S32 i = 0; i < ASSET_COUNT; ++i) + { + unboost_minimap_texture(mDetailTextures[i]); + unboost_minimap_material(mDetailMaterials[i]); + } } BOOL LLTerrainMaterials::generateMaterials() @@ -131,6 +141,12 @@ LLPointer fetch_terrain_texture(const LLUUID& id) void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) { + // *NOTE: If there were multiple terrain swatches using the same asset + // ID, the asset still in use will be temporarily unboosted. + // It will be boosted again during terrain rendering. + unboost_minimap_texture(mDetailTextures[asset]); + unboost_minimap_material(mDetailMaterials[asset]); + // This is terrain texture, but we are not setting it as BOOST_TERRAIN // since we will be manipulating it later as needed. mDetailTextures[asset] = fetch_terrain_texture(id); -- cgit v1.2.3 From 47255bf44d04e5ba7b33d44f8cc738da4be9d53a Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 11 Apr 2024 17:26:02 -0700 Subject: secondlife/viewer#1184: Stop making terrain textures undeletable --- indra/llrender/llgltexture.cpp | 3 +- indra/llrender/llgltexture.h | 3 +- indra/newview/lldrawpoolterrain.cpp | 36 +---------------- indra/newview/llvlcomposition.cpp | 79 ++++++++++++++++++++++++++----------- indra/newview/llvlcomposition.h | 3 ++ 5 files changed, 64 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index b616002b49..a590a8e745 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -95,7 +95,8 @@ void LLGLTexture::setBoostLevel(S32 level) mBoostLevel = level ; if(mBoostLevel != LLGLTexture::BOOST_NONE && mBoostLevel != LLGLTexture::BOOST_ICON - && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL) + && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL + && mBoostLevel != LLGLTexture::BOOST_TERRAIN) { setNoDelete() ; } diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 1cc8fbe523..fa6faa2583 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -52,10 +52,11 @@ public: BOOST_AVATAR , BOOST_AVATAR_BAKED , BOOST_SCULPTED , + BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead. BOOST_HIGH = 10, BOOST_BUMP , - BOOST_TERRAIN , // has to be high priority for minimap / low detail + BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug BOOST_SELECTED , BOOST_AVATAR_BAKED_SELF , BOOST_AVATAR_SELF , // needed for baking avatar diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 2d198c5b4b..c5932a6ad9 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -115,41 +115,7 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures() // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - for (S32 i = 0; i < 4; i++) - { - constexpr LLGLTexture::EBoostLevel level = LLGLTexture::BOOST_TERRAIN; - constexpr float stats = 1024.f * 1024.f; - - LLPointer& tex = compp->mDetailTextures[i]; - llassert(tex.notNull()); - tex->setBoostLevel(level); - tex->addTextureStats(stats); - - LLPointer& fetched_material = compp->mDetailMaterials[i]; - if (fetched_material) - { - if (fetched_material->mBaseColorTexture) - { - fetched_material->mBaseColorTexture->setBoostLevel(level); - fetched_material->mBaseColorTexture->addTextureStats(stats); - } - if (fetched_material->mNormalTexture) - { - fetched_material->mNormalTexture->setBoostLevel(level); - fetched_material->mNormalTexture->addTextureStats(stats); - } - if (fetched_material->mMetallicRoughnessTexture) - { - fetched_material->mMetallicRoughnessTexture->setBoostLevel(level); - fetched_material->mMetallicRoughnessTexture->addTextureStats(stats); - } - if (fetched_material->mEmissiveTexture) - { - fetched_material->mEmissiveTexture->setBoostLevel(level); - fetched_material->mEmissiveTexture->addTextureStats(stats); - } - } - } + compp->boost(); } void LLDrawPoolTerrain::beginDeferredPass(S32 pass) diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 6c0691c6a9..6955949571 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -45,6 +45,7 @@ extern LLColor4U MAX_WATER_COLOR; static const U32 BASE_SIZE = 128; +static const F32 TERRAIN_DECODE_PRIORITY = 2048.f * 2048.f; namespace { @@ -64,25 +65,38 @@ namespace return result; } - void unboost_minimap_texture(LLPointer& tex) + void boost_minimap_texture(LLViewerFetchedTexture* tex, F32 virtual_size) + { + llassert(tex); + if (!tex) { return; } + + tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case the raw image is at low detail + tex->addTextureStats(virtual_size); // priority + } + + void boost_minimap_material(LLFetchedGLTFMaterial* mat, F32 virtual_size) + { + if (!mat) { return; } + if (mat->mBaseColorTexture) { boost_minimap_texture(mat->mBaseColorTexture, virtual_size); } + if (mat->mNormalTexture) { boost_minimap_texture(mat->mNormalTexture, virtual_size); } + if (mat->mMetallicRoughnessTexture) { boost_minimap_texture(mat->mMetallicRoughnessTexture, virtual_size); } + if (mat->mEmissiveTexture) { boost_minimap_texture(mat->mEmissiveTexture, virtual_size); } + } + + void unboost_minimap_texture(LLViewerFetchedTexture* tex) { if (!tex) { return; } tex->setBoostLevel(LLGLTexture::BOOST_NONE); tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); - - if (tex->getTextureState() == LLGLTexture::NO_DELETE) - { - tex->forceActive(); - } } - void unboost_minimap_material(LLPointer& mat) + void unboost_minimap_material(LLFetchedGLTFMaterial* mat) { if (!mat) { return; } - unboost_minimap_texture(mat->mBaseColorTexture); - unboost_minimap_texture(mat->mNormalTexture); - unboost_minimap_texture(mat->mMetallicRoughnessTexture); - unboost_minimap_texture(mat->mEmissiveTexture); + if (mat->mBaseColorTexture) { unboost_minimap_texture(mat->mBaseColorTexture); } + if (mat->mNormalTexture) { unboost_minimap_texture(mat->mNormalTexture); } + if (mat->mMetallicRoughnessTexture) { unboost_minimap_texture(mat->mMetallicRoughnessTexture); } + if (mat->mEmissiveTexture) { unboost_minimap_texture(mat->mEmissiveTexture); } } }; @@ -96,11 +110,7 @@ LLTerrainMaterials::LLTerrainMaterials() LLTerrainMaterials::~LLTerrainMaterials() { - for (S32 i = 0; i < ASSET_COUNT; ++i) - { - unboost_minimap_texture(mDetailTextures[i]); - unboost_minimap_material(mDetailMaterials[i]); - } + unboost(); } BOOL LLTerrainMaterials::generateMaterials() @@ -118,6 +128,31 @@ BOOL LLTerrainMaterials::generateMaterials() return FALSE; } +void LLTerrainMaterials::boost() +{ + for (S32 i = 0; i < ASSET_COUNT; ++i) + { + LLPointer& tex = mDetailTextures[i]; + llassert(tex.notNull()); + boost_minimap_texture(tex, TERRAIN_DECODE_PRIORITY); + + LLPointer& mat = mDetailMaterials[i]; + boost_minimap_material(mat, TERRAIN_DECODE_PRIORITY); + } +} + +void LLTerrainMaterials::unboost() +{ + for (S32 i = 0; i < ASSET_COUNT; ++i) + { + LLPointer& tex = mDetailTextures[i]; + unboost_minimap_texture(tex); + + LLPointer& mat = mDetailMaterials[i]; + unboost_minimap_material(mat); + } +} + LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset) { llassert(mDetailTextures[asset] && mDetailMaterials[asset]); @@ -135,7 +170,6 @@ LLPointer fetch_terrain_texture(const LLUUID& id) } LLPointer tex = LLViewerTextureManager::getFetchedTexture(id); - tex->setNoDelete(); return tex; } @@ -240,8 +274,7 @@ bool LLTerrainMaterials::textureReady(LLPointer& tex, bo { if (boost) { - tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail - tex->addTextureStats(BASE_SIZE*BASE_SIZE); + boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE); } return false; } @@ -251,6 +284,8 @@ bool LLTerrainMaterials::textureReady(LLPointer& tex, bo { if (boost) { + boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE); + S32 width = tex->getFullWidth(); S32 height = tex->getFullHeight(); S32 min_dim = llmin(width, height); @@ -260,9 +295,7 @@ bool LLTerrainMaterials::textureReady(LLPointer& tex, bo ddiscard++; min_dim /= 2; } - tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail tex->setMinDiscardLevel(ddiscard); - tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority } return false; } @@ -589,7 +622,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, // Raw image is not ready, will enter here again later. if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage()) { - tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); + boost_minimap_texture(tex, TERRAIN_DECODE_PRIORITY); tex->forceToRefetchTexture(ddiscard); } @@ -606,7 +639,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, // Raw image is not ready, will enter here again later. if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage()) { - tex_emissive->setBoostLevel(LLGLTexture::BOOST_TERRAIN); + boost_minimap_texture(tex_emissive, TERRAIN_DECODE_PRIORITY); tex_emissive->forceToRefetchTexture(ddiscard_emissive); } diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 7397ff1e8d..6a460e3285 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -58,6 +58,8 @@ public: BOOL generateMaterials(); + void boost(); + virtual LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); @@ -67,6 +69,7 @@ public: bool materialsReady(bool boost, bool strict); protected: + void unboost(); static bool textureReady(LLPointer& tex, bool boost); // strict = true -> all materials must be sufficiently loaded // strict = false -> at least one material must be loaded -- cgit v1.2.3 From 7df1bc9e65a6dd7532ac4a22ea6960cc8d8c9ee8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Apr 2024 03:36:23 +0300 Subject: viewer#1081 2K texture apload price arrives as an array #2 --- indra/newview/llagentbenefits.cpp | 80 ++++++++++++++++++++++++++++++--- indra/newview/llagentbenefits.h | 9 +++- indra/newview/llfloaterimagepreview.cpp | 13 +----- indra/newview/llmaterialeditor.cpp | 71 +++++------------------------ indra/newview/llviewermenufile.cpp | 71 ++++------------------------- 5 files changed, 101 insertions(+), 143 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp index 7362082029..29b0a4612f 100644 --- a/indra/newview/llagentbenefits.cpp +++ b/indra/newview/llagentbenefits.cpp @@ -25,6 +25,7 @@ #include "llviewerprecompiledheaders.h" #include "llagentbenefits.h" +#include "llviewertexture.h" LLAgentBenefits::LLAgentBenefits(): m_initalized(false), @@ -34,8 +35,7 @@ LLAgentBenefits::LLAgentBenefits(): m_group_membership_limit(-1), m_picks_limit(-1), m_sound_upload_cost(-1), - m_texture_upload_cost(-1), - m_2k_texture_upload_cost(-1) + m_texture_upload_cost(-1) { } @@ -95,7 +95,26 @@ bool LLAgentBenefits::init(const LLSD& benefits_sd) { return false; } - get_required_S32(benefits_sd, "large_texture_upload_cost", m_2k_texture_upload_cost); + + if (benefits_sd.has("large_texture_upload_cost")) + { + LLSD large_texture_cost = benefits_sd.get("large_texture_upload_cost"); + if (large_texture_cost.isArray()) + { + LLSD::array_const_iterator end = large_texture_cost.endArray(); + LLSD::array_const_iterator it = large_texture_cost.beginArray(); + for (; it != end; ++it) + { + m_2k_texture_upload_cost.push_back(it->asInteger()); + } + std::sort(m_2k_texture_upload_cost.begin(), m_2k_texture_upload_cost.end()); + } + } + + if (m_2k_texture_upload_cost.empty()) + { + m_2k_texture_upload_cost.push_back(m_texture_upload_cost); + } // FIXME PREMIUM - either use this field or get rid of it m_initalized = true; @@ -142,9 +161,60 @@ S32 LLAgentBenefits::getTextureUploadCost() const return m_texture_upload_cost; } -S32 LLAgentBenefits::get2KTextureUploadCost() const +S32 LLAgentBenefits::getTextureUploadCost(const LLViewerTexture* tex) const +{ + if (tex) + { + S32 area = tex->getFullHeight() * tex->getFullWidth(); + if (area >= MIN_2K_TEXTURE_AREA) + { + return get2KTextureUploadCost(area); + } + else + { + return getTextureUploadCost(); + } + } + return getTextureUploadCost(); +} + +S32 LLAgentBenefits::getTextureUploadCost(const LLImageBase* tex) const +{ + if (tex) + { + S32 area = tex->getHeight() * tex->getWidth(); + if (area >= MIN_2K_TEXTURE_AREA) + { + return get2KTextureUploadCost(area); + } + else + { + return getTextureUploadCost(); + } + } + return getTextureUploadCost(); +} + +S32 LLAgentBenefits::get2KTextureUploadCost(S32 area) const { - return m_2k_texture_upload_cost; + if (m_2k_texture_upload_cost.empty()) + { + return m_texture_upload_cost; + } + const S32 TEXTURE_SEGMENTS = 1024; + if (m_2k_texture_upload_cost.size() == TEXTURE_SEGMENTS) + { + S32 index = (S32)llceil(sqrt((F32)area)); + // 1..1024 pixels uses m_texture_upload_cost + // 1025..2048 uses m_2k_texture_upload_cost + // Translate 1025..2048 to 0..1023 of the + // cost array + const S32 PIXELS_TO_2K_ARRAY_TRANLATE = 1025; + index -= PIXELS_TO_2K_ARRAY_TRANLATE; + index = llclamp(index, 0, TEXTURE_SEGMENTS - 1); + return m_2k_texture_upload_cost[index]; + } + return m_2k_texture_upload_cost[0]; } bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h index e48cedd95c..962d0f9371 100644 --- a/indra/newview/llagentbenefits.h +++ b/indra/newview/llagentbenefits.h @@ -30,6 +30,9 @@ #include "llsd.h" #include "llassettype.h" +class LLViewerTexture; +class LLImageBase; + class LLAgentBenefits { public: @@ -49,7 +52,9 @@ public: S32 getPicksLimit() const; S32 getSoundUploadCost() const; S32 getTextureUploadCost() const; - S32 get2KTextureUploadCost() const; + S32 getTextureUploadCost(const LLViewerTexture* tex) const; + S32 getTextureUploadCost(const LLImageBase* tex) const; + S32 get2KTextureUploadCost(S32 area) const; bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const; @@ -62,7 +67,7 @@ private: S32 m_picks_limit; S32 m_sound_upload_cost; S32 m_texture_upload_cost; - S32 m_2k_texture_upload_cost; + std::vector m_2k_texture_upload_cost; bool m_initalized; }; diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 87fe0a4dd6..55516fe168 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -151,18 +151,7 @@ BOOL LLFloaterImagePreview::postBuild() //----------------------------------------------------------------------------- S32 LLFloaterImagePreview::getExpectedUploadCost() const { - if (mRawImagep.notNull()) - { - if (mRawImagep->getWidth() * mRawImagep->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - return LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - } - else - { - return LLAgentBenefitsMgr::current().getTextureUploadCost(); - } - } - return 0; + return LLAgentBenefitsMgr::current().getTextureUploadCost(mRawImagep); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 1783621530..84446b626a 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -489,20 +489,10 @@ BOOL LLMaterialEditor::postBuild() } else { - S32 upload_cost_base = LLAgentBenefitsMgr::current().getTextureUploadCost(); - S32 upload_cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - - bool large_texture = mBaseColorFetched && (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); - getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - - large_texture = mMetallicRoughnessFetched && (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); - getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - - large_texture = mEmissiveFetched && (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); - getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); - - large_texture = mNormalFetched && (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA); - getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", large_texture ? upload_cost_2k : upload_cost_base)); + getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched))); + getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched))); + getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched))); + getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched))); } boost::function changes_callback = [this](LLUICtrl * ctrl, void* userData) @@ -851,60 +841,24 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) setCanSave(false); } - S32 upload_texture_count = 0; - S32 upload_2k_texture_count = 0; + mExpectedUploadCost = 0; if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched) { - if (mBaseColorFetched->getFullHeight() * mBaseColorFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - upload_2k_texture_count++; - } - else - { - upload_texture_count++; - } + mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched); } if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched) { - if (mMetallicRoughnessFetched->getFullHeight() * mMetallicRoughnessFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - upload_2k_texture_count++; - } - else - { - upload_texture_count++; - } + mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched); } if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched) { - if (mEmissiveFetched->getFullHeight() * mEmissiveFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - upload_2k_texture_count++; - } - else - { - upload_texture_count++; - } + mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched); } if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched) { - if (mNormalFetched->getFullHeight() * mNormalFetched->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - upload_2k_texture_count++; - } - else - { - upload_texture_count++; - } + mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched); } - mExpectedUploadCost = upload_texture_count * LLAgentBenefitsMgr::current().getTextureUploadCost(); - S32 cost_2k = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - if (cost_2k < 0) - { - cost_2k = 0; - } - mExpectedUploadCost += upload_2k_texture_count * cost_2k; getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); } @@ -3539,12 +3493,7 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con std::string buffer; buffer.assign((const char*) img->getData(), img->getDataSize()); - U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - if (img->getWidth() * img->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - } - + U32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(img); LLSD key = getKey(); std::function failed_upload([key](LLUUID assetId, LLSD response, std::string reason) { diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 6fe5ef00ab..240c756411 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -556,19 +556,8 @@ void do_bulk_upload(std::vector filenames, const LLSD& notification LLPointer image_frmted = LLImageFormatted::createFromType(codec); if (gDirUtilp->fileExists(filename) && image_frmted->load(filename)) { - if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - expected_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); - if (expected_upload_cost >= 0) - { - resource_upload = true; - } - } - else - { - expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - resource_upload = true; - } + expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(image_frmted); + resource_upload = true; } } else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost)) @@ -617,8 +606,6 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 total_cost = 0; file_count = 0; bvh_count = 0; - S32 texture_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - S32 texture_2k_upload_cost = LLAgentBenefitsMgr::current().get2KTextureUploadCost(); for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) { std::string filename = (*in_iter); @@ -640,19 +627,8 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 LLPointer image_frmted = LLImageFormatted::createFromType(codec); if (gDirUtilp->fileExists(filename) && image_frmted->load(filename)) { - if (image_frmted->getWidth() * image_frmted->getHeight() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - if (texture_2k_upload_cost >= 0) - { - total_cost += texture_2k_upload_cost; - file_count++; - } - } - else - { - total_cost += texture_upload_cost; - file_count++; - } + total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(image_frmted); + file_count++; } } else if (LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost)) @@ -680,53 +656,22 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 { // Todo: make it account for possibility of same texture in different // materials and even in scope of same material - S32 texture_count = 0; - S32 texture_2k_count = 0; if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull() && material->mBaseColorTexture) { - if (material->mBaseColorTexture->getFullHeight() * material->mBaseColorTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - texture_2k_count++; - } - else - { - texture_count++; - } + total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mBaseColorTexture); } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull() && material->mMetallicRoughnessTexture) { - if (material->mMetallicRoughnessTexture->getFullHeight() * material->mMetallicRoughnessTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - texture_2k_count++; - } - else - { - texture_count++; - } + total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mMetallicRoughnessTexture); } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull() && material->mNormalTexture) { - if (material->mNormalTexture->getFullHeight() * material->mNormalTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - texture_2k_count++; - } - else - { - texture_count++; - } + total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mNormalTexture); } if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull() && material->mEmissiveTexture) { - if (material->mEmissiveTexture->getFullHeight() * material->mEmissiveTexture->getFullWidth() >= LLAgentBenefits::MIN_2K_TEXTURE_AREA) - { - texture_2k_count++; - } - else - { - texture_count++; - } + total_cost += LLAgentBenefitsMgr::current().getTextureUploadCost(material->mEmissiveTexture); } - total_cost += texture_count * texture_upload_cost + texture_2k_count * texture_2k_upload_cost; file_count++; } } -- cgit v1.2.3 From 713d443ae89f871761eb305ece18d2cc1c9ac482 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Apr 2024 20:33:38 +0300 Subject: viewer#1081 LLFloaterImagePreview 2048 image upload support --- indra/newview/llfloaterimagepreview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 55516fe168..2a5106f79e 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -388,7 +388,7 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename) return false; } - raw_image->biasedScaleToPowerOfTwo(1024); + raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); mRawImagep = raw_image; return true; -- cgit v1.2.3 From 4053bae85dabf7840c9c2bd2444c0d034d697973 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 12 Apr 2024 20:53:30 +0300 Subject: viewer#1081 Fix XMLPRC not being parced to LLSD correctly which interferred with getting benefits from LLSD array --- indra/newview/llxmlrpclistener.cpp | 94 +++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 46 deletions(-) (limited to 'indra') diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index b816f9a3b5..c4f9be5fcd 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -411,34 +411,20 @@ private: return parseValues(status_string, "", param); } - /** - * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map. - * @param key_pfx Used to describe a given key in log messages. At top - * level, pass "". When parsing an options array, pass the top-level key - * name of the array plus the index of the array entry; to this we'll - * append the subkey of interest. - * @param param XMLRPC_VALUE iterator. At top level, pass - * XMLRPC_RequestGetData(XMLRPC_REQUEST). - */ - LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param) + LLSD parseValue(std::string& status_string, const std::string& key, const std::string& key_pfx, XMLRPC_VALUE param) { - LLSD responses; - for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current; - current = XMLRPC_VectorNext(param)) + LLSD response; + + XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(param); + switch (type) { - std::string key(XMLRPC_GetValueID(current)); - LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL; - XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current); - switch (type) - { case xmlrpc_type_empty: LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL; - responses.insert(key, LLSD()); break; case xmlrpc_type_base64: { - S32 len = XMLRPC_GetValueStringLen(current); - const char* buf = XMLRPC_GetValueBase64(current); + S32 len = XMLRPC_GetValueStringLen(param); + const char* buf = XMLRPC_GetValueBase64(param); if ((len > 0) && buf) { // During implementation this code was not tested @@ -449,49 +435,44 @@ private: LLSD::Binary data; data.resize(len); memcpy((void*)&data[0], (void*)buf, len); - responses.insert(key, data); + response = data; } else { LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key " << key_pfx << key << LL_ENDL; - responses.insert(key, LLSD()); } break; } case xmlrpc_type_boolean: { - LLSD::Boolean val(XMLRPC_GetValueBoolean(current)); - LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; - responses.insert(key, val); + response = LLSD::Boolean(XMLRPC_GetValueBoolean(param)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL; break; } case xmlrpc_type_datetime: { - std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(current)); + std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(param)); LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL; - responses.insert(key, LLSD::Date(iso8601_date)); + response = LLSD::Date(iso8601_date); break; } case xmlrpc_type_double: { - LLSD::Real val(XMLRPC_GetValueDouble(current)); - LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; - responses.insert(key, val); + response = LLSD::Real(XMLRPC_GetValueDouble(param)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL; break; } case xmlrpc_type_int: { - LLSD::Integer val(XMLRPC_GetValueInt(current)); - LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; - responses.insert(key, val); + response = LLSD::Integer(XMLRPC_GetValueInt(param)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL; break; } case xmlrpc_type_string: { - LLSD::String val(XMLRPC_GetValueString(current)); - LL_DEBUGS("LLXMLRPCListener") << "val: " << val << LL_ENDL; - responses.insert(key, val); + response = LLSD::String(XMLRPC_GetValueString(param)); + LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL; break; } case xmlrpc_type_mixed: @@ -501,8 +482,8 @@ private: // recursively parsing each submap and collecting them. LLSD array; int i = 0; // for descriptive purposes - for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row; - row = XMLRPC_VectorNext(current), ++i) + for (XMLRPC_VALUE row = XMLRPC_VectorRewind(param); row; + row = XMLRPC_VectorNext(param), ++i) { // Recursive call. For the lower-level key_pfx, if 'key' // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the @@ -510,21 +491,21 @@ private: // "foo[0]:bar", and so forth. // Parse the scalar subkey/value pairs from this array // entry into a temp submap. Collect such submaps in 'array'. - array.append(parseValues(status_string, + + array.append(parseValue(status_string, "", STRINGIZE(key_pfx << key << '[' << i << "]:"), row)); } // Having collected an 'array' of 'submap's, insert that whole // 'array' as the value of this 'key'. - responses.insert(key, array); + response = array; break; } case xmlrpc_type_struct: { - LLSD submap = parseValues(status_string, + response = parseValues(status_string, STRINGIZE(key_pfx << key << ':'), - current); - responses.insert(key, submap); + param); break; } case xmlrpc_type_none: // Not expected @@ -532,9 +513,30 @@ private: // whoops - unrecognized type LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key " << key_pfx << key << LL_ENDL; - responses.insert(key, STRINGIZE("')); + response = STRINGIZE("'); status_string = "BadType"; - } + } + return response; + } + + /** + * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map. + * @param key_pfx Used to describe a given key in log messages. At top + * level, pass "". When parsing an options array, pass the top-level key + * name of the array plus the index of the array entry; to this we'll + * append the subkey of interest. + * @param param XMLRPC_VALUE iterator. At top level, pass + * XMLRPC_RequestGetData(XMLRPC_REQUEST). + */ + LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param) + { + LLSD responses; + for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current; + current = XMLRPC_VectorNext(param)) + { + std::string key(XMLRPC_GetValueID(current)); + LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL; + responses.insert(key, parseValue(status_string, key, key_pfx, current)); } return responses; } -- cgit v1.2.3 From a6107bceec79b15ebf4cdbdc6a5e32d018b7eb23 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 13 Apr 2024 01:49:09 +0300 Subject: viewer#1081 Add expected price to upload's body --- indra/newview/llviewerassetupload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index e2e321af0d..882e08935c 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -156,9 +156,9 @@ LLSD LLResourceUploadInfo::generatePostBody() body["next_owner_mask"] = LLSD::Integer(mNextOwnerPerms); body["group_mask"] = LLSD::Integer(mGroupPerms); body["everyone_mask"] = LLSD::Integer(mEveryonePerms); + body["expected_upload_cost"] = mExpectedUploadCost; return body; - } void LLResourceUploadInfo::logPreparedUpload() -- cgit v1.2.3 From 64c541f40191dee0fb6b3b0c09d0d9bfacb454a5 Mon Sep 17 00:00:00 2001 From: Beq Date: Sun, 14 Apr 2024 18:33:03 +0100 Subject: Fix/Finish VoCache extras The extras cache was never fully implemented and thus grows forever. This coupled with the server side "bug" that sends innumerable blank overrides leads users to collect 100MB+ SLEC files which in turn cause significant pauses post TP. --- indra/newview/llgltfmateriallist.cpp | 7 +- indra/newview/llviewerregion.cpp | 14 ++- indra/newview/llvocache.cpp | 201 +++++++++++++++++++++++++++-------- indra/newview/llvocache.h | 11 +- 4 files changed, 178 insertions(+), 55 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 92c58a2dbc..a1d77779dd 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -246,7 +246,12 @@ void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::s } } - region->cacheFullUpdateGLTFOverride(cache); + // Workaround for server sending empty overrides. + if(cache.mSides.size() > 0) + { + region->cacheFullUpdateGLTFOverride(cache); + LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL; + } } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index eba7189a82..c4a4e6613c 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -794,8 +794,9 @@ void LLViewerRegion::loadObjectCache() if(LLVOCache::instanceExists()) { LLVOCache & vocache = LLVOCache::instance(); - vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); - vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD); + // Without this a "corrupted" vocache persists until a cache clear or other rewrite. Mark as dirty hereif read fails to force a rewrite. + mCacheDirty = !vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); + vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mImpl->mCacheMap); if (mImpl->mCacheMap.empty()) { @@ -1162,13 +1163,13 @@ void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering) child = entry->getChild(); } } - + // Kill the assocaited overrides + mImpl->mGLTFOverridesLLSD.erase(entry->getLocalID()); //will remove it from the object cache, real deletion entry->setState(LLVOCacheEntry::INACTIVE); entry->removeOctreeEntry(); entry->setValid(FALSE); - // TODO kill extras/material overrides cache too } //physically delete the cache entry @@ -3672,6 +3673,11 @@ void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj) auto iter = mImpl->mGLTFOverridesLLSD.find(local_id); if (iter != mImpl->mGLTFOverridesLLSD.end()) { + // UUID can be inserted null, so backfill the UUID if it was left empty + if (iter->second.mObjectId.isNull()) + { + iter->second.mObjectId = obj->getID(); + } llassert(iter->second.mGLTFMaterial.size() == iter->second.mSides.size()); for (auto& side : iter->second.mGLTFMaterial) diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index dd5b9f9fd5..e0b7a5929a 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -33,7 +33,7 @@ #include "llviewerregion.h" #include "llagentcamera.h" #include "llsdserialize.h" - +#include "llworld.h" // For LLWorld::getInstance() //static variables U32 LLVOCacheEntry::sMinFrameRange = 0; F32 LLVOCacheEntry::sNearRadius = 1.0f; @@ -55,6 +55,10 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) return apr_file->write(src, n_bytes) == n_bytes ; } +// Material Override Cache needs a version label, so we can upgrade this later. +const std::string LLGLTFOverrideCacheEntry::VERSION_LABEL = {"GLTFCacheVer"}; +const int LLGLTFOverrideCacheEntry::VERSION = 1; + bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; @@ -235,6 +239,8 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) } else { + // Improve logging around vocache + LL_WARNS() << "Error loading cache entry for " << mLocalID << ", size " << size << " aborting!" << LL_ENDL; delete[] mBuffer ; mBuffer = NULL ; } @@ -1261,6 +1267,10 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry) { return; } + // Bit more tracking of cache creation/destruction. + std::string filename; + getObjectCacheFilename(entry->mHandle, filename); + LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL; header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); if(iter != mHeaderEntryQueue.end()) @@ -1331,6 +1341,10 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry) std::string filename; getObjectCacheFilename(entry->mHandle, filename); LLAPRFile::remove(filename, mLocalAPRFilePoolp); + // Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry. + // as such this now includes the generic extras + removeGenericExtrasForHandle(entry->mHandle); + entry->mTime = INVALID_TIME ; updateEntry(entry) ; //update the head file. } @@ -1478,12 +1492,14 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; } -void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +// we now return bool to trigger dirty cache +// this in turn forces a rewrite after a partial read due to corruption. +bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) { if(!mEnabled) { LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; - return ; + return true; // no problem we're just read only } llassert_always(mInitialized); @@ -1491,10 +1507,11 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca if(iter == mHandleEntryMap.end()) //no cache { LL_WARNS() << "No handle map entry for " << handle << LL_ENDL; - return ; + return false; // arguably no a problem, but we'll mark this as dirty anyway. } bool success = true ; + S32 num_entries = 0 ; // lifted out of inner loop. { std::string filename; LLUUID cache_id; @@ -1513,7 +1530,6 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca if(success) { - S32 num_entries; // if removal was enabled during write num_entries might be wrong success = check_read(&apr_file, &num_entries, sizeof(S32)) ; if(success) @@ -1542,11 +1558,17 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca } } - return ; + LL_DEBUGS("GLTF", "VOCache") << "Read " << cache_entry_map.size() << " entries from object cache " << filename << ", expected " << num_entries << ", success=" << (success?"True":"False") << LL_ENDL; + return success; } -void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map) +// We now pass in the cache entry map, so that we can remove entries from extras that are no longer in the primary cache. +void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) { + int loaded= 0; + int discarded = 0; + // get ViewerRegion pointer from handle + LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle); if(!mEnabled) { LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; @@ -1568,19 +1590,35 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::getline(in, line); if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); return; } + // file formats need versions, let's add one. legacy cache files will be considered version 0 + // This will make it easier to upgrade/revise later. + int versionNumber=0; + if (line.compare(0, LLGLTFOverrideCacheEntry::VERSION_LABEL.length(), LLGLTFOverrideCacheEntry::VERSION_LABEL) == 0) + { + std::string versionStr = line.substr(LLGLTFOverrideCacheEntry::VERSION_LABEL.length()+1); // skip the version label and ':' + versionNumber = std::stol(versionStr); + std::getline(in, line); // read the next line for the region UUID check + } if(!LLUUID::validate(line)) { LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); return; } LLUUID cache_id(line); if(cache_id != id) { - LL_INFOS() << "Cache ID doesn't match for this region, discarding" << LL_ENDL; + // if the cache id doesn't match the expected region we should just kill the file. + LL_WARNS() << "Cache ID doesn't match for this region, deleting it" << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); return; } @@ -1588,6 +1626,8 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::getline(in, line); if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); return; } try { @@ -1596,10 +1636,12 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac catch(std::logic_error&) // either invalid_argument or out_of_range { LL_WARNS() << "Failed reading extras cache for handle " << handle << ". unreadable num_entries" << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); return; } - LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + LL_DEBUGS("GLTF") << "Beginning reading extras cache for handle " << handle << " from " << getObjectCacheExtrasFilename(handle) << LL_ENDL; LLSD entry_llsd; for (U32 i = 0; i < num_entries && !in.eof(); i++) @@ -1608,46 +1650,63 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size); // check bool(in) this time since eof is not a failure condition here if(!success || !in) { - LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << LL_ENDL; - return; - } + LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << " cache patrtial load only." << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); + break; LLGLTFOverrideCacheEntry entry; entry.fromLLSD(entry_llsd); U32 local_id = entry_llsd["local_id"].asInteger(); - cache_extras_entry_map[local_id] = entry; + // only add entries that exist in the primary cache + // this is a self-healing test that avoids us polluting the cache with entries that are no longer valid based on the main cache. + if(cache_entry_map.find(local_id)!= cache_entry_map.end()) + { + // attempt to backfill a null objectId, though these shouldn't be in the persisted cache really + if(entry.mObjectId.isNull() && pRegion) + { + gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() ); + } + cache_extras_entry_map[local_id] = entry; + loaded++; + } + else + { + discarded++; + } } - - LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + LL_DEBUGS("GLTF") << "Completed reading extras cache for handle " << handle << ", " << loaded << " loaded, " << discarded << " discarded" << LL_ENDL; } void LLVOCache::purgeEntries(U32 size) { + LL_DEBUGS("VOCache","GLTF") << "Purging " << size << " entries from cache" << LL_ENDL; while(mHeaderEntryQueue.size() > size) { header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; - HeaderEntryInfo* entry = *iter ; - mHandleEntryMap.erase(entry->mHandle); + HeaderEntryInfo* entry = *iter ; + mHandleEntryMap.erase(entry->mHandle) ; mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; + removeFromCache(entry) ; // This now handles removing extras cache where appropriate. delete entry; - // TODO also delete extras } mNumEntries = mHandleEntryMap.size() ; } void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled) { + std::string filename; + getObjectCacheFilename(handle, filename); if(!mEnabled) { - LL_WARNS() << "Not writing cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently disabled." << LL_ENDL; return ; } llassert_always(mInitialized); if(mReadOnly) { - LL_WARNS() << "Not writing cache for handle " << handle << "): Cache is currently in read-only mode." << LL_ENDL; + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently in read-only mode." << LL_ENDL; return ; } @@ -1682,13 +1741,13 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: //update cache header if(!updateEntry(entry)) { - LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". handle = " << handle << LL_ENDL; + LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". " << filename << " handle = " << handle << LL_ENDL; return ; //update failed. } if(!dirty_cache) { - LL_WARNS() << "Skipping write to cache for handle " << handle << ": cache not dirty" << LL_ENDL; + LL_WARNS() << "Skipping write to cache for " << filename << " (handle:" << handle << "): cache not dirty" << LL_ENDL; return ; //nothing changed, no need to update. } @@ -1724,6 +1783,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: } else { + LL_WARNS() << "Failed to write cache entry to buffer for " << filename << ", entry number " << iter->second->getLocalID() << LL_ENDL; success = false; break; } @@ -1735,6 +1795,7 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: size_in_buffer = 0; if (!success) { + LL_WARNS() << "Failed to write cache to disk " << filename << LL_ENDL; break; } } @@ -1745,8 +1806,13 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: { // final write success = check_write(&apr_file, (void*)data_buffer, size_in_buffer); + if(!success) + { + LL_WARNS() << "Failed to write cache entry to disk " << filename << LL_ENDL; + } size_in_buffer = 0; } + LL_DEBUGS("VOCache") << "Wrote " << num_entries << " entries to the primary VOCache file " << filename << ". success = " << (success ? "True":"False") << LL_ENDL; } } } @@ -1759,6 +1825,17 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: return ; } +void LLVOCache::removeGenericExtrasForHandle(U64 handle) +{ + if(mReadOnly) + { + LL_WARNS() << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << LL_ENDL; + return ; + } + LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << handle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL; + LLFile::remove(getObjectCacheExtrasFilename(handle)); +} + void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled) { if(!mEnabled) @@ -1774,46 +1851,86 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL return; } - std::string filename(getObjectCacheExtrasFilename(handle)); + // FIRE-33808 - Material Override Cache causes long delays + std::string filename = getObjectCacheExtrasFilename(handle); + // llofstream out(filename, std::ios::out | std::ios::binary); if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); return; - // TODO - clean up broken cache file } + // It is good practice to version file formats so let's add one. + // legacy versions will be treated as version 0. + out << LLGLTFOverrideCacheEntry::VERSION_LABEL << ":" << LLGLTFOverrideCacheEntry::VERSION << '\n'; out << id << '\n'; if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); return; - // TODO - clean up broken cache file } - - U32 num_entries = cache_extras_entry_map.size(); - out << num_entries << '\n'; + // Because we don't write out all the entries we need to record a placeholder and rewrite this later + auto num_entries_placeholder = out.tellp(); + out << std::setw(10) << std::setfill('0') << 0 << '\n'; if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); return; - // TODO - clean up broken cache file } - for (auto const & entry : cache_extras_entry_map) + // get ViewerRegion pointer from handle + LLViewerRegion* pRegion = LLWorld::getInstance()->getRegionFromHandle(handle); + + U32 num_entries = 0; + U32 inmem_entries = 0; + U32 skipped = 0; + inmem_entries = cache_extras_entry_map.size(); + for (auto [local_id, entry] : cache_extras_entry_map) { - S32 local_id = entry.first; - LLSD entry_llsd = entry.second.toLLSD(); - entry_llsd["local_id"] = local_id; - LLSDSerialize::serialize(entry_llsd, out, LLSDSerialize::LLSD_XML); - out << '\n'; - if(!out.good()) + // Only write out GLTFOverrides that we can actually apply again on import. + // worst case we have an extra cache miss. + // Note: A null mObjectId is valid when in memory as we might have a data race between GLTF of the object itself. + // This remains a valid state to persist as it is consistent with the localid checks on import with the main cache. + // the mObjectId will be updated if/when the local object is updated from the gObject list (due to full update) + if(entry.mObjectId.isNull() && pRegion) { - LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; - return; - // TODO - clean up broken cache file + gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() ); } - } - LL_DEBUGS("GLTF") << "Completed writing extras cache for handle " << handle << ", " << num_entries << " entries" << LL_ENDL; + if( entry.mSides.size() > 0 && + entry.mSides.size() == entry.mGLTFMaterial.size() + ) + { + LLSD entry_llsd = entry.toLLSD(); + entry_llsd["local_id"] = (S32)local_id; + LLSDSerialize::serialize(entry_llsd, out, LLSDSerialize::LLSD_XML); + out << '\n'; + if(!out.good()) + { + // We're not in a good place when this happens so we might as well nuke the file. + LL_WARNS() << "Failed writing extras cache for handle " << handle << ". Corrupted cache file " << filename << " removed." << LL_ENDL; + removeGenericExtrasForHandle(handle); + return; + } + num_entries++; + } + else + { + skipped++; + } + } + // Rewrite the placeholder + out.seekp(num_entries_placeholder); + out << std::setw(10) << std::setfill('0') << num_entries << '\n'; + if(!out.good()) + { + LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; + removeGenericExtrasForHandle(handle); + return; + } + LL_DEBUGS("GLTF") << "Completed writing extras cache for handle " << handle << ", " << num_entries << " entries. Total in RAM: " << inmem_entries << " skipped (no persist): " << skipped << LL_ENDL; } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 8525edd121..c24a4accc7 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -96,12 +96,6 @@ public: } }; - struct ExtrasEntry - { - LLSD extras; - std::string extras_raw; - }; - protected: ~LLVOCacheEntry(); public: @@ -289,12 +283,13 @@ public: void initCache(ELLPath location, U32 size, U32 cache_version); void removeCache(ELLPath location, bool started = false) ; - void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map); + bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; + void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map); void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled); void removeEntry(U64 handle) ; + void removeGenericExtrasForHandle(U64 handle); U32 getCacheEntries() { return mNumEntries; } U32 getCacheEntriesMax() { return mCacheSize; } -- cgit v1.2.3 From 614b9739ff208cdfa4f63a3f86e605a66ce5297b Mon Sep 17 00:00:00 2001 From: Beq Date: Mon, 15 Apr 2024 12:23:11 +0100 Subject: lift variable out of loop and fix a missing bracket. --- indra/newview/llvocache.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index e0b7a5929a..d0ae8e9399 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1512,8 +1512,8 @@ bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca bool success = true ; S32 num_entries = 0 ; // lifted out of inner loop. + std::string filename; // lifted out of loop { - std::string filename; LLUUID cache_id; getObjectCacheFilename(handle, filename); LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); @@ -1588,7 +1588,8 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::string line; std::getline(in, line); - if(!in.good()) { + if(!in.good()) + { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; in.close(); removeGenericExtrasForHandle(handle); @@ -1624,13 +1625,15 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac U32 num_entries; // if removal was enabled during write num_entries might be wrong std::getline(in, line); - if(!in.good()) { + if(!in.good()) + { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; in.close(); removeGenericExtrasForHandle(handle); return; } - try { + try + { num_entries = std::stol(line); } catch(std::logic_error&) // either invalid_argument or out_of_range @@ -1649,11 +1652,13 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac static const U32 max_size = 4096; bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size); // check bool(in) this time since eof is not a failure condition here - if(!success || !in) { + if(!success || !in) + { LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << " cache patrtial load only." << LL_ENDL; in.close(); removeGenericExtrasForHandle(handle); break; + } LLGLTFOverrideCacheEntry entry; entry.fromLLSD(entry_llsd); -- cgit v1.2.3 From 291c1ad91b4fb5793cdfd85763df7d3b419a6ac3 Mon Sep 17 00:00:00 2001 From: Beq Date: Mon, 15 Apr 2024 12:28:51 +0100 Subject: Declaring things helps! --- indra/newview/llvocache.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index c24a4accc7..d94e79ce1b 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -43,6 +43,8 @@ class LLCamera; class LLGLTFOverrideCacheEntry { public: + static const std::string VERSION_LABEL; + static const int VERSION; bool fromLLSD(const LLSD& data); LLSD toLLSD() const; -- cgit v1.2.3 From 655b35afffb86bb2bafeecb932f07e3fb40a119a Mon Sep 17 00:00:00 2001 From: Beq Date: Tue, 16 Apr 2024 10:19:56 +0100 Subject: Add some checking around extras cache versionNumber --- indra/newview/llvocache.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index d0ae8e9399..4ba6024166 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1602,8 +1602,18 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac { std::string versionStr = line.substr(LLGLTFOverrideCacheEntry::VERSION_LABEL.length()+1); // skip the version label and ':' versionNumber = std::stol(versionStr); - std::getline(in, line); // read the next line for the region UUID check } + // For future versions we may call a legacy handler here, but realistically we'll just consider this cache out of date. + // The important thing is to make sure it gets removed. + if(versionNumber != LLGLTFOverrideCacheEntry::VERSION && versionNumber != 0) + { + LL_WARNS << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL; + in.close(); + removeGenericExtrasForHandle(handle); + return; + } + + LL_DEBUGS("VOCache") << "Reading extras cache for handle " << handle << ", version " << versionNumber << LL_ENDL; if(!LLUUID::validate(line)) { -- cgit v1.2.3 From ee33a43daee924d32bf5de58c264a6d384ef7451 Mon Sep 17 00:00:00 2001 From: Beq Date: Tue, 16 Apr 2024 16:50:37 +0100 Subject: Too hasty on the push. --- indra/newview/llvocache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 4ba6024166..82ffd1d522 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1607,7 +1607,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac // The important thing is to make sure it gets removed. if(versionNumber != LLGLTFOverrideCacheEntry::VERSION && versionNumber != 0) { - LL_WARNS << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL; + LL_WARNS() << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL; in.close(); removeGenericExtrasForHandle(handle); return; -- cgit v1.2.3 From bc93177ea0788a245554882b6d721eae2e057206 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 17 Apr 2024 16:12:49 -0500 Subject: 1176 integrate llgltfnode with selection manager and llmaniptranslate/rotate (#1258) * #1176 Somewhat working GLTF Node support for translate tool * #1176 Missing file from last commit * #1176 Better translation for rotated nodes. * #1176 Fix for objects snapping back to original position * #1176 GLTF Samples compatibility pass -- attempt at improving rotation manip support, incidental cleanup, GLTF node debug display * #1176 Clean out some unused and not working functions. * #1176 Fix for mac build, incidental cleanup * Mac build fix --- indra/llmath/llmatrix4a.h | 14 +- indra/llrender/llrender.cpp | 24 -- indra/newview/gltf/asset.cpp | 128 +++++++++ indra/newview/gltf/asset.h | 68 +---- indra/newview/gltf/primitive.cpp | 180 ++++++++++--- indra/newview/gltfscenemanager.cpp | 153 ++++++++--- indra/newview/gltfscenemanager.h | 2 + indra/newview/llagentcamera.cpp | 2 +- indra/newview/lldrawpoolalpha.cpp | 7 + indra/newview/llfetchedgltfmaterial.cpp | 3 + indra/newview/llfetchedgltfmaterial.h | 2 + indra/newview/llmanip.cpp | 8 +- indra/newview/llmaniprotate.cpp | 293 +++++++++++---------- indra/newview/llmaniptranslate.cpp | 225 ++++++++-------- indra/newview/llselectmgr.cpp | 118 +++++---- indra/newview/llselectmgr.h | 9 +- indra/newview/lltinygltfhelper.cpp | 30 ++- indra/newview/lltoolselect.cpp | 2 +- indra/newview/llviewermenu.cpp | 4 + indra/newview/llviewerobject.cpp | 162 ++++++++++++ indra/newview/llviewerobject.h | 12 + indra/newview/llviewerwindow.cpp | 18 +- indra/newview/llviewerwindow.h | 4 + indra/newview/pipeline.cpp | 32 ++- indra/newview/pipeline.h | 6 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 10 + 26 files changed, 1043 insertions(+), 473 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index 2cf50e9cd2..12fc6d570a 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -34,8 +34,8 @@ class LLMatrix4a { public: - LL_ALIGN_16(LLVector4a mMatrix[4]); - + LL_ALIGN_16(LLVector4a mMatrix[4]); + LLMatrix4a() { @@ -56,6 +56,16 @@ public: return (F32*)&mMatrix; } + inline LLMatrix4& asMatrix4() + { + return *(LLMatrix4*)this; + } + + inline const LLMatrix4& asMatrix4() const + { + return *(LLMatrix4*)this; + } + inline void clear() { mMatrix[0].clear(); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 4d64dc9e10..358b35f36b 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -2068,10 +2068,6 @@ void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f); } - else - { - glColor3f(r,g,b); - } } void LLRender::diffuseColor3fv(const F32* c) @@ -2083,10 +2079,6 @@ void LLRender::diffuseColor3fv(const F32* c) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f); } - else - { - glColor3fv(c); - } } void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) @@ -2098,10 +2090,6 @@ void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a); } - else - { - glColor4f(r,g,b,a); - } } void LLRender::diffuseColor4fv(const F32* c) @@ -2113,10 +2101,6 @@ void LLRender::diffuseColor4fv(const F32* c) { shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c); } - else - { - glColor4fv(c); - } } void LLRender::diffuseColor4ubv(const U8* c) @@ -2128,10 +2112,6 @@ void LLRender::diffuseColor4ubv(const U8* c) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); } - else - { - glColor4ubv(c); - } } void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) @@ -2143,10 +2123,6 @@ void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) { shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); } - else - { - glColor4ub(r,g,b,a); - } } diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 092b6e5d4b..7181c5fa53 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -69,9 +69,12 @@ void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix) matMul(mMatrix, parentMatrix, mAssetMatrix); mAssetMatrixInv = inverse(mAssetMatrix); + S32 my_index = this - &asset.mNodes[0]; + for (auto& childIndex : mChildren) { Node& child = asset.mNodes[childIndex]; + child.mParent = my_index; child.updateTransforms(asset, mAssetMatrix); } } @@ -208,4 +211,129 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, return node_hit; } +const Node& Node::operator=(const tinygltf::Node& src) +{ + F32* dstMatrix = mMatrix.getF32ptr(); + + if (src.matrix.size() == 16) + { + // Node has a transformation matrix, just copy it + for (U32 i = 0; i < 16; ++i) + { + dstMatrix[i] = (F32)src.matrix[i]; + } + } + else if (!src.rotation.empty() || !src.translation.empty() || !src.scale.empty()) + { + // node has rotation/translation/scale, convert to matrix + glh::quaternionf rotation; + if (src.rotation.size() == 4) + { + rotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); + } + + glh::vec3f translation; + if (src.translation.size() == 3) + { + translation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); + } + + glh::vec3f scale; + if (src.scale.size() == 3) + { + scale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); + } + else + { + scale.set_value(1.f, 1.f, 1.f); + } + + glh::matrix4f rot; + rotation.get_value(rot); + + glh::matrix4f trans; + trans.set_translate(translation); + + glh::matrix4f sc; + sc.set_scale(scale); + + glh::matrix4f t; + //t = sc * rot * trans; + //t = trans * rot * sc; // best so far, still wrong on negative scale + //t = sc * trans * rot; + t = trans * sc * rot; + + mMatrix.loadu(t.m); + } + else + { + // node specifies no transformation, set to identity + mMatrix.setIdentity(); + } + + mChildren = src.children; + mMesh = src.mesh; + mName = src.name; + + return *this; +} + +void Asset::render(bool opaque) +{ + for (auto& node : mNodes) + { + if (node.mMesh != INVALID_INDEX) + { + Mesh& mesh = mMeshes[node.mMesh]; + for (auto& primitive : mesh.mPrimitives) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + bool cull = true; + if (primitive.mMaterial != INVALID_INDEX) + { + Material& material = mMaterials[primitive.mMaterial]; + + if ((material.mMaterial->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND) == opaque) + { + continue; + } + material.mMaterial->bind(); + cull = !material.mMaterial->mDoubleSided; + } + else + { + if (!opaque) + { + continue; + } + LLFetchedGLTFMaterial::sDefault.bind(); + } + + LLGLDisable cull_face(!cull ? GL_CULL_FACE : 0); + + primitive.mVertexBuffer->setBuffer(); + if (primitive.mVertexBuffer->getNumIndices() > 0) + { + primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); + } + else + { + primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); + } + + } + } + } +} + +void Asset::renderOpaque() +{ + render(true); +} + +void Asset::renderTransparent() +{ + render(false); +} + diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 0f1d4e8993..acf9ba77df 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -171,31 +171,12 @@ namespace LL LLMatrix4a mAssetMatrixInv; //transform from asset to local space std::vector mChildren; + S32 mParent = INVALID_INDEX; + S32 mMesh = INVALID_INDEX; std::string mName; - const Node& operator=(const tinygltf::Node& src) - { - F32* dstMatrix = mMatrix.getF32ptr(); - - if (src.matrix.size() != 16) - { - mMatrix.setIdentity(); - } - else - { - for (U32 i = 0; i < 16; ++i) - { - dstMatrix[i] = (F32)src.matrix[i]; - } - } - - mChildren = src.children; - mMesh = src.mesh; - mName = src.name; - - return *this; - } + const Node& operator=(const tinygltf::Node& src); // Set mRenderMatrix to a transform that can be used for the current render pass // modelview -- parent's render matrix @@ -314,21 +295,23 @@ namespace LL void allocateGLResources(const std::string& filename, const tinygltf::Model& model) { - for (auto& mesh : mMeshes) - { - mesh.allocateGLResources(*this); - } - + // do images first as materials may depend on images for (auto& image : mImages) { image.allocateGLResources(); } + // do materials before meshes as meshes may depend on materials for (U32 i = 0; i < mMaterials.size(); ++i) { mMaterials[i].allocateGLResources(*this); LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true); } + + for (auto& mesh : mMeshes) + { + mesh.allocateGLResources(*this); + } } // update asset-to-node and node-to-asset transforms @@ -337,34 +320,9 @@ namespace LL // update node render transforms void updateRenderTransforms(const LLMatrix4a& modelview); - void renderOpaque() - { - for (auto& node : mNodes) - { - if (node.mMesh != INVALID_INDEX) - { - Mesh& mesh = mMeshes[node.mMesh]; - for (auto& primitive : mesh.mPrimitives) - { - gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); - if (primitive.mMaterial != INVALID_INDEX) - { - Material& material = mMaterials[primitive.mMaterial]; - material.mMaterial->bind(); - } - primitive.mVertexBuffer->setBuffer(); - if (primitive.mVertexBuffer->getNumIndices() > 0) - { - primitive.mVertexBuffer->draw(primitive.mGLMode, primitive.mVertexBuffer->getNumIndices(), 0); - } - else - { - primitive.mVertexBuffer->drawArrays(primitive.mGLMode, 0, primitive.mVertexBuffer->getNumVerts()); - } - } - } - } - } + void render(bool opaque); + void renderOpaque(); + void renderTransparent(); // return the index of the node that the line segment intersects with, or -1 if no hit // input and output values must be in this asset's local coordinate frame diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index 71654dcfdd..b5d59e1b24 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -162,10 +162,25 @@ void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider& dst) { copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) + { + copyAttributeArray(asset, accessor, (const U8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT) + { + copyAttributeArray(asset, accessor, (const S16*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE) + { + copyAttributeArray(asset, accessor, (const S8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) + { + copyAttributeArray(asset, accessor, (const F64*)src, dst, bufferView.mByteStride); + } else - { - LL_ERRS() << "Unsupported component type" << LL_ENDL; + LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL; } } @@ -179,11 +194,11 @@ void Primitive::allocateGLResources(Asset& asset) // get the number of vertices U32 numVertices = 0; - for (auto& it : mAttributes) + if (!mAttributes.empty()) { - const Accessor& accessor = asset.mAccessors[it.second]; + auto it = mAttributes.begin(); + const Accessor& accessor = asset.mAccessors[it->second]; numVertices = accessor.mCount; - break; } // get the number of indices @@ -294,6 +309,14 @@ void Primitive::allocateGLResources(Asset& asset) src += sizeof(U16); } } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) + { + for (U32 i = 0; i < numIndices; ++i) + { + *(dst++) = *(U8*)src; + src += sizeof(U8); + } + } else { LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL; @@ -317,6 +340,22 @@ void Primitive::allocateGLResources(Asset& asset) } } + // bake material basecolor into color array + if (mMaterial != INVALID_INDEX) + { + const Material& material = asset.mMaterials[mMaterial]; + LLColor4 baseColor = material.mMaterial->mBaseColor; + LLStrider dst; + mVertexBuffer->getColorStrider(dst); + + for (U32 i = 0; i < numVertices; ++i) + { + LLColor4 col = *dst; + *dst = LLColor4U(baseColor * col); + dst++; + } + } + if (needs_texcoord) { // set default texcoord LLStrider dst; @@ -368,15 +407,51 @@ void Primitive::allocateGLResources(Asset& asset) mVertexBuffer->unmapBuffer(); } +void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) +{ + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = i0; + tri->mIndex[1] = i1; + tri->mIndex[2] = i2; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max, min); + + tri->mRadius = size.getLength3().getF32() * scaler; +} + void Primitive::createOctree() { // create octree mOctree = new LLVolumeOctree(); + F32 scaler = 0.25f; + if (mMode == TINYGLTF_MODE_TRIANGLES) { - F32 scaler = 0.25f; - const U32 num_triangles = mVertexBuffer->getNumIndices() / 3; // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); @@ -388,47 +463,82 @@ void Primitive::createOctree() { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - const LLVector4a& v0 = pos[indices[index]]; - const LLVector4a& v1 = pos[indices[index + 1]]; - const LLVector4a& v2 = pos[indices[index + 2]]; + S32 i0 = indices[index]; + S32 i1 = indices[index + 1]; + S32 i2 = indices[index + 2]; + + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; + + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); + + //insert + mOctree->insert(tri); + } + } + else if (mMode == TINYGLTF_MODE_TRIANGLE_STRIP) + { + const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; + // Initialize all the triangles we need + mOctreeTriangles.resize(num_triangles); - //store pointers to vertex data - tri->mV[0] = &v0; - tri->mV[1] = &v1; - tri->mV[2] = &v2; + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - //store indices - tri->mIndex[0] = indices[index]; - tri->mIndex[1] = indices[index + 1]; - tri->mIndex[2] = indices[index + 2]; + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) + { //for each triangle + const U32 index = triangle_index + 2; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; + S32 i0 = indices[index]; + S32 i1 = indices[index - 1]; + S32 i2 = indices[index - 2]; + + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; - //get minimum point - LLVector4a min = v0; - min.setMin(min, v1); - min.setMin(min, v2); + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); - //get maximum point - LLVector4a max = v0; - max.setMax(max, v1); - max.setMax(max, v2); + //insert + mOctree->insert(tri); + } + } + else if (mMode == TINYGLTF_MODE_TRIANGLE_FAN) + { + const U32 num_triangles = mVertexBuffer->getNumIndices() - 2; + // Initialize all the triangles we need + mOctreeTriangles.resize(num_triangles); - //compute center - LLVector4a center; - center.setAdd(min, max); - center.mul(0.5f); + LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); + U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - tri->mPositionGroup = center; + for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) + { //for each triangle + const U32 index = triangle_index + 2; + LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; + S32 i0 = indices[0]; + S32 i1 = indices[index - 1]; + S32 i2 = indices[index - 2]; - //compute "radius" - LLVector4a size; - size.setSub(max, min); + const LLVector4a& v0 = pos[i0]; + const LLVector4a& v1 = pos[i1]; + const LLVector4a& v2 = pos[i2]; - tri->mRadius = size.getLength3().getF32() * scaler; + initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); //insert mOctree->insert(tri); } } + else if (mMode == TINYGLTF_MODE_POINTS || + mMode == TINYGLTF_MODE_LINE || + mMode == TINYGLTF_MODE_LINE_LOOP || + mMode == TINYGLTF_MODE_LINE_STRIP) + { + // nothing to do, no volume... maybe add some collision geometry around these primitive types? + } + else { LL_ERRS() << "Unsupported Primitive mode" << LL_ENDL; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 6c44b83646..8273c707f9 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -91,7 +91,11 @@ void GLTFSceneManager::load(const std::string& filename) if (obj) { // assign to self avatar obj->mGLTFAsset = asset; - mObjects.push_back(obj); + + if (std::find(mObjects.begin(), mObjects.end(), obj) == mObjects.end()) + { + mObjects.push_back(obj); + } } } @@ -100,43 +104,17 @@ GLTFSceneManager::~GLTFSceneManager() mObjects.clear(); } -LLMatrix4a getAssetToAgentTransform(LLViewerObject* obj) +void GLTFSceneManager::renderOpaque() { - LLMatrix4 root; - root.initScale(obj->getScale()); - root.rotate(obj->getRenderRotation()); - root.translate(obj->getPositionAgent()); - - LLMatrix4a mat; - mat.loadu((F32*) root.mMatrix); - - return mat; + render(true); } -LLMatrix4a getAgentToAssetTransform(LLViewerObject* obj) +void GLTFSceneManager::renderAlpha() { - LLMatrix4 root; - LLVector3 scale = obj->getScale(); - scale.mV[0] = 1.f / scale.mV[0]; - scale.mV[1] = 1.f / scale.mV[1]; - scale.mV[2] = 1.f / scale.mV[2]; - - root.translate(-obj->getPositionAgent()); - root.rotate(~obj->getRenderRotation()); - - LLMatrix4 scale_mat; - scale_mat.initScale(scale); - - root *= scale_mat; - - - LLMatrix4a mat; - mat.loadu((F32*) root.mMatrix); - - return mat; + render(false); } -void GLTFSceneManager::renderOpaque() +void GLTFSceneManager::render(bool opaque) { // for debugging, just render the whole scene as opaque // by traversing the whole scenegraph @@ -158,7 +136,7 @@ void GLTFSceneManager::renderOpaque() gGL.pushMatrix(); - LLMatrix4a mat = getAssetToAgentTransform(mObjects[i]); + LLMatrix4a mat = mObjects[i]->getGLTFAssetToAgentTransform(); LLMatrix4a modelview; modelview.loadu(gGLModelView); @@ -166,7 +144,7 @@ void GLTFSceneManager::renderOpaque() matMul(mat, modelview, modelview); asset->updateRenderTransforms(modelview); - asset->renderOpaque(); + asset->render(opaque); gGL.popMatrix(); } @@ -195,7 +173,7 @@ bool GLTFSceneManager::lineSegmentIntersect(LLVOVolume* obj, Asset* asset, const LLVector4a local_start; LLVector4a local_end; - LLMatrix4a asset_to_agent = getAssetToAgentTransform(obj); + LLMatrix4a asset_to_agent = obj->getGLTFAssetToAgentTransform(); LLMatrix4a agent_to_asset = inverse(asset_to_agent); agent_to_asset.affineTransform(start, local_start); @@ -331,7 +309,7 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) gGL.pushMatrix(); // get raycast in asset space - LLMatrix4a agent_to_asset = getAgentToAssetTransform(obj); + LLMatrix4a agent_to_asset = obj->getAgentToGLTFAssetTransform(); LLVector4a start; LLVector4a end; @@ -399,7 +377,8 @@ void GLTFSceneManager::renderDebug() { if (!gPipeline.hasRenderDebugMask( LLPipeline::RENDER_DEBUG_BBOXES | - LLPipeline::RENDER_DEBUG_RAYCAST)) + LLPipeline::RENDER_DEBUG_RAYCAST | + LLPipeline::RENDER_DEBUG_NODES)) { return; } @@ -412,6 +391,7 @@ void GLTFSceneManager::renderDebug() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gPipeline.disableLights(); + // force update all mRenderMatrix, not just nodes with meshes for (auto& obj : mObjects) { if (obj->isDead() || obj->mGLTFAsset == nullptr) @@ -419,20 +399,115 @@ void GLTFSceneManager::renderDebug() continue; } + LLMatrix4a mat = obj->getGLTFAssetToAgentTransform(); + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + + matMul(mat, modelview, modelview); + Asset* asset = obj->mGLTFAsset; + for (auto& node : asset->mNodes) + { + matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); + } + } + + for (auto& obj : mObjects) + { + if (obj->isDead() || obj->mGLTFAsset == nullptr) + { + continue; + } + + Asset* asset = obj->mGLTFAsset; - LLMatrix4a mat = getAssetToAgentTransform(obj); + LLMatrix4a mat = obj->getGLTFAssetToAgentTransform(); LLMatrix4a modelview; modelview.loadu(gGLModelView); matMul(mat, modelview, modelview); - asset->updateRenderTransforms(modelview); renderAssetDebug(obj, asset); } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NODES)) + { //render node hierarchy + + for (U32 i = 0; i < 2; ++i) + { + LLGLDepthTest depth(GL_TRUE, i == 0 ? GL_FALSE : GL_TRUE, i == 0 ? GL_GREATER : GL_LEQUAL); + LLGLState blend(GL_BLEND, i == 0 ? TRUE : FALSE); + + + gGL.pushMatrix(); + + for (auto& obj : mObjects) + { + if (obj->isDead() || obj->mGLTFAsset == nullptr) + { + continue; + } + + LLMatrix4a mat = obj->getGLTFAssetToAgentTransform(); + + LLMatrix4a modelview; + modelview.loadu(gGLModelView); + + matMul(mat, modelview, modelview); + + Asset* asset = obj->mGLTFAsset; + + for (auto& node : asset->mNodes) + { + // force update all mRenderMatrix, not just nodes with meshes + matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); + + gGL.loadMatrix(node.mRenderMatrix.getF32ptr()); + // render x-axis red, y-axis green, z-axis blue + gGL.color4f(1.f, 0.f, 0.f, 0.5f); + gGL.begin(LLRender::LINES); + gGL.vertex3f(0.f, 0.f, 0.f); + gGL.vertex3f(1.f, 0.f, 0.f); + gGL.end(); + gGL.flush(); + + gGL.color4f(0.f, 1.f, 0.f, 0.5f); + gGL.begin(LLRender::LINES); + gGL.vertex3f(0.f, 0.f, 0.f); + gGL.vertex3f(0.f, 1.f, 0.f); + gGL.end(); + gGL.flush(); + + gGL.begin(LLRender::LINES); + gGL.color4f(0.f, 0.f, 1.f, 0.5f); + gGL.vertex3f(0.f, 0.f, 0.f); + gGL.vertex3f(0.f, 0.f, 1.f); + gGL.end(); + gGL.flush(); + + // render path to child nodes cyan + gGL.color4f(0.f, 1.f, 1.f, 0.5f); + gGL.begin(LLRender::LINES); + for (auto& child_idx : node.mChildren) + { + Node& child = asset->mNodes[child_idx]; + gGL.vertex3f(0.f, 0.f, 0.f); + gGL.vertex3fv(child.mMatrix.getTranslation().getF32ptr()); + } + gGL.end(); + gGL.flush(); + } + } + + gGL.popMatrix(); + } + + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) { S32 node_hit = -1; diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index 50e1dd93da..4e9013834b 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -38,7 +38,9 @@ namespace LL // load GLTF file from disk void load(); // open filepicker to choose asset void load(const std::string& filename); // load asset from filename + void render(bool opaque); void renderOpaque(); + void renderAlpha(); LLDrawable* lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 8977b145d1..7ddf6c4390 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2525,7 +2525,7 @@ void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick) { LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); - if (objectp) + if (objectp && pick.mGLTFNodeIndex == -1) { // focus on object plus designated offset // which may or may not be same as pick.mPosGlobal diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 41dc95a8cb..81014e9d6e 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -49,6 +49,7 @@ #include "llspatialpartition.h" #include "llglcommonfunc.h" #include "llvoavatar.h" +#include "gltfscenemanager.h" #include "llenvironment.h" @@ -260,6 +261,12 @@ void LLDrawPoolAlpha::forwardRender(bool rigged) mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + if (write_depth) + { // draw GLTF scene to depth buffer + gPipeline.bindDeferredShader(gDeferredPBRAlphaProgram); + LL::GLTFSceneManager::instance().renderAlpha(); + } + // If the face is more than 90% transparent, then don't update the Depth buffer for Dof // We don't want the nearly invisible objects to cause of DoF effects renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, false, rigged); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1ca7ffaec1..1dd1dbabbe 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -34,6 +34,9 @@ #include "llshadermgr.h" #include "pipeline.h" +//static +LLFetchedGLTFMaterial LLFetchedGLTFMaterial::sDefault; + LLFetchedGLTFMaterial::LLFetchedGLTFMaterial() : LLGLTFMaterial() , mExpectedFlusTime(0.f) diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 42c835a416..7550c75b45 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -66,6 +66,8 @@ public: std::set mTextureEntires; + // default material for when assets don't have one + static LLFetchedGLTFMaterial sDefault; protected: // Lifetime management diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index feb691520f..8a284686ad 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -355,8 +355,14 @@ LLVector3 LLManip::getSavedPivotPoint() const LLVector3 LLManip::getPivotPoint() { - if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + LLViewerObject* object = mObjectSelection->getFirstObject(); + if (object && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { + LLSelectNode* select_node = mObjectSelection->getFirstNode(); + if (select_node->mSelectedGLTFNode != -1) + { + return object->getGLTFNodePositionAgent(select_node->mSelectedGLTFNode); + } return mObjectSelection->getFirstObject()->getPivotPositionAgent(); } return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 7f37f98568..1ac1992fe0 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -556,6 +556,7 @@ void LLManipRotate::drag( S32 x, S32 y ) BOOL damped = mSmoothRotate; mSmoothRotate = FALSE; + bool gltf_mode = false; for (LLObjectSelection::iterator iter = mObjectSelection->begin(); iter != mObjectSelection->end(); iter++) @@ -569,154 +570,177 @@ void LLManipRotate::drag( S32 x, S32 y ) ((root_object == NULL) || !root_object->isPermanentEnforced()) && (object->isRootEdit() || selectNode->mIndividualSelection)) { - if (!object->isRootEdit()) - { - // child objects should not update if parent is selected - LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); - if (editable_root->isSelected()) - { - // we will be moved properly by our parent, so skip - continue; - } - } - LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; - std::vector& child_positions = object->mUnselectedChildrenPositions ; - std::vector child_rotations; - if (object->isRootEdit() && selectNode->mIndividualSelection) - { - object->saveUnselectedChildrenRotation(child_rotations) ; - object->saveUnselectedChildrenPosition(child_positions) ; - } + if (selectNode->mSelectedGLTFNode != -1) + { + LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; - if (object->getParent() && object->mDrawable.notNull()) - { - LLQuaternion invParentRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); - invParentRotation.transQuat(); + object->setGLTFNodeRotationAgent(selectNode->mSelectedGLTFNode, new_rot); - object->setRotation(new_rot * invParentRotation, damped); - rebuild(object); - } - else - { - object->setRotation(new_rot, damped); - LLVOAvatar* avatar = object->asAvatar(); - if (avatar && avatar->isSelf() - && LLSelectMgr::getInstance()->mAllowSelectAvatar - && !object->getParent()) + gltf_mode = true; + } + else if (!gltf_mode) + { + if (!object->isRootEdit()) { - // Normal avatars use object's orienttion, but self uses - // separate LLCoordFrame - // See LVOAvatar::updateOrientation() - if (gAgentCamera.getFocusOnAvatar()) + // child objects should not update if parent is selected + LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); + if (editable_root->isSelected()) { - //Don't rotate camera with avatar - gAgentCamera.setFocusOnAvatar(false, false, false); + // we will be moved properly by our parent, so skip + continue; } + } - LLVector3 at_axis = mAgentSelfAtAxis; - at_axis *= mRotation; - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis); + LLQuaternion new_rot = selectNode->mSavedRotation * mRotation; + std::vector& child_positions = object->mUnselectedChildrenPositions; + std::vector child_rotations; + if (object->isRootEdit() && selectNode->mIndividualSelection) + { + object->saveUnselectedChildrenRotation(child_rotations); + object->saveUnselectedChildrenPosition(child_positions); } - rebuild(object); - } - // for individually selected roots, we need to counterrotate all the children - if (object->isRootEdit() && selectNode->mIndividualSelection) - { - //RN: must do non-damped updates on these objects so relative rotation appears constant - // instead of having two competing slerps making the child objects appear to "wobble" - object->resetChildrenRotationAndPosition(child_rotations, child_positions) ; - } + if (object->getParent() && object->mDrawable.notNull()) + { + LLQuaternion invParentRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); + invParentRotation.transQuat(); + + object->setRotation(new_rot * invParentRotation, damped); + rebuild(object); + } + else + { + object->setRotation(new_rot, damped); + LLVOAvatar* avatar = object->asAvatar(); + if (avatar && avatar->isSelf() + && LLSelectMgr::getInstance()->mAllowSelectAvatar + && !object->getParent()) + { + // Normal avatars use object's orienttion, but self uses + // separate LLCoordFrame + // See LVOAvatar::updateOrientation() + if (gAgentCamera.getFocusOnAvatar()) + { + //Don't rotate camera with avatar + gAgentCamera.setFocusOnAvatar(false, false, false); + } + + LLVector3 at_axis = mAgentSelfAtAxis; + at_axis *= mRotation; + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis); + } + rebuild(object); + } + + // for individually selected roots, we need to counterrotate all the children + if (object->isRootEdit() && selectNode->mIndividualSelection) + { + //RN: must do non-damped updates on these objects so relative rotation appears constant + // instead of having two competing slerps making the child objects appear to "wobble" + object->resetChildrenRotationAndPosition(child_rotations, child_positions); + } + } } } // update positions - for (LLObjectSelection::iterator iter = mObjectSelection->begin(); - iter != mObjectSelection->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + if (!gltf_mode) + { + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); + iter != mObjectSelection->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); - // to avoid cumulative position changes we calculate the objects new position using its saved position - if (object && object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced())) - { - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - LLVector3 old_position; - LLVector3 new_position; - - if (object->isAttachment() && object->mDrawable.notNull()) - { - // need to work in drawable space to handle selected items from multiple attachments - // (which have no shared frame of reference other than their render positions) - LLXform* parent_xform = object->mDrawable->getXform()->getParent(); - new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); - old_position = (object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();//object->getRenderPosition(); - } - else - { - new_position = gAgent.getPosAgentFromGlobal( selectNode->mSavedPositionGlobal ); - old_position = object->getPositionAgent(); - } - new_position = (new_position - center) * mRotation; // new relative rotated position - new_position += center; - - if (object->isRootEdit() && !object->isAttachment()) - { - LLVector3d new_pos_global = gAgent.getPosGlobalFromAgent(new_position); - new_pos_global = LLWorld::getInstance()->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global); - new_position = gAgent.getPosAgentFromGlobal(new_pos_global); - } + // to avoid cumulative position changes we calculate the objects new position using its saved position + if (object && object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced())) + { + LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter); - // for individually selected child objects - if (!object->isRootEdit() && selectNode->mIndividualSelection) - { - LLViewerObject* parentp = (LLViewerObject*)object->getParent(); - if (!parentp->isSelected()) - { - if (object->isAttachment() && object->mDrawable.notNull()) - { - // find position relative to render position of parent - object->setPosition((new_position - parentp->getRenderPosition()) * ~parentp->getRenderRotation()); - rebuild(object); - } - else - { - object->setPositionParent((new_position - parentp->getPositionAgent()) * ~parentp->getRotationRegion()); - rebuild(object); - } - } - } - else if (object->isRootEdit()) - { - if (object->isAttachment() && object->mDrawable.notNull()) - { - LLXform* parent_xform = object->mDrawable->getXform()->getParent(); - object->setPosition((new_position - parent_xform->getWorldPosition()) * ~parent_xform->getWorldRotation()); - rebuild(object); - } - else - { - object->setPositionAgent(new_position); - rebuild(object); - } - } + LLVector3 old_position; + LLVector3 new_position; - // for individually selected roots, we need to counter-translate all unselected children - if (object->isRootEdit() && selectNode->mIndividualSelection) - { - // only offset by parent's translation as we've already countered parent's rotation - rebuild(object); - object->resetChildrenPosition(old_position - new_position) ; - } - } - } + if (selectNode->mSelectedGLTFNode != -1) + { + + } + else + { + if (object->isAttachment() && object->mDrawable.notNull()) + { + // need to work in drawable space to handle selected items from multiple attachments + // (which have no shared frame of reference other than their render positions) + LLXform* parent_xform = object->mDrawable->getXform()->getParent(); + new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); + old_position = (object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();//object->getRenderPosition(); + } + else + { + new_position = gAgent.getPosAgentFromGlobal(selectNode->mSavedPositionGlobal); + old_position = object->getPositionAgent(); + } + + new_position = (new_position - center) * mRotation; // new relative rotated position + new_position += center; + + if (object->isRootEdit() && !object->isAttachment()) + { + LLVector3d new_pos_global = gAgent.getPosGlobalFromAgent(new_position); + new_pos_global = LLWorld::getInstance()->clipToVisibleRegions(selectNode->mSavedPositionGlobal, new_pos_global); + new_position = gAgent.getPosAgentFromGlobal(new_pos_global); + } + + // for individually selected child objects + if (!object->isRootEdit() && selectNode->mIndividualSelection) + { + LLViewerObject* parentp = (LLViewerObject*)object->getParent(); + if (!parentp->isSelected()) + { + if (object->isAttachment() && object->mDrawable.notNull()) + { + // find position relative to render position of parent + object->setPosition((new_position - parentp->getRenderPosition()) * ~parentp->getRenderRotation()); + rebuild(object); + } + else + { + object->setPositionParent((new_position - parentp->getPositionAgent()) * ~parentp->getRotationRegion()); + rebuild(object); + } + } + } + else if (object->isRootEdit()) + { + if (object->isAttachment() && object->mDrawable.notNull()) + { + LLXform* parent_xform = object->mDrawable->getXform()->getParent(); + object->setPosition((new_position - parent_xform->getWorldPosition()) * ~parent_xform->getWorldRotation()); + rebuild(object); + } + else + { + object->setPositionAgent(new_position); + rebuild(object); + } + } + + // for individually selected roots, we need to counter-translate all unselected children + if (object->isRootEdit() && selectNode->mIndividualSelection) + { + // only offset by parent's translation as we've already countered parent's rotation + rebuild(object); + object->resetChildrenPosition(old_position - new_position); + } + } + } + } + } // store changes to override updates for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); @@ -725,12 +749,13 @@ void LLManipRotate::drag( S32 x, S32 y ) LLSelectNode* selectNode = *iter; LLViewerObject*cur = selectNode->getObject(); LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); - if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && ((root_object == NULL) || !root_object->isPermanentEnforced()) && (!cur->isAvatar() || LLSelectMgr::getInstance()->mAllowSelectAvatar)) { - selectNode->mLastRotation = cur->getRotation(); - selectNode->mLastPositionLocal = cur->getPosition(); + selectNode->mLastRotation = cur->getRotation(); + selectNode->mLastPositionLocal = cur->getPosition(); } } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index cafb3fef67..9fc5ad502c 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -655,114 +655,125 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply - for (LLObjectSelection::iterator iter = mObjectSelection->begin(); - iter != mObjectSelection->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - - // Only apply motion to root objects and objects selected - // as "individual". - if (!object->isRootEdit() && !selectNode->mIndividualSelection) - { - continue; - } - - if (!object->isRootEdit()) - { - // child objects should not update if parent is selected - LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); - if (editable_root->isSelected()) - { - // we will be moved properly by our parent, so skip - continue; - } - } - - LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); - if (object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced())) - { - // handle attachments in local space - if (object->isAttachment() && object->mDrawable.notNull()) - { - // calculate local version of relative move - LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); - objWorldRotation.transQuat(); - - LLVector3 old_position_local = object->getPosition(); - LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); - - //RN: I forget, but we need to do this because of snapping which doesn't often result - // in position changes even when the mouse moves - object->setPosition(new_position_local); - rebuild(object); - gAgentAvatarp->clampAttachmentPositions(); - new_position_local = object->getPosition(); - - if (selectNode->mIndividualSelection) - { - // counter-translate child objects if we are moving the root as an individual - object->resetChildrenPosition(old_position_local - new_position_local, TRUE) ; - } - } - else - { - // compute new position to send to simulators, but don't set it yet. - // We need the old position to know which simulator to send the move message to. - LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; - - // Don't let object centers go too far underground - F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); - if (new_position_global.mdV[VZ] < min_height) - { - new_position_global.mdV[VZ] = min_height; - } - - // For safety, cap heights where objects can be dragged - if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) - { - new_position_global.mdV[VZ] = MAX_OBJECT_Z; - } - - // Grass is always drawn on the ground, so clamp its position to the ground - if (object->getPCode() == LL_PCODE_LEGACY_GRASS) - { - new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; - } - - if (object->isRootEdit()) - { - new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); - } - - // PR: Only update if changed - LLVector3 old_position_agent = object->getPositionAgent(); - LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); - if (object->isRootEdit()) - { - // finally, move parent object after children have calculated new offsets - object->setPositionAgent(new_position_agent); - rebuild(object); - } - else - { - LLViewerObject* root_object = object->getRootEdit(); - new_position_agent -= root_object->getPositionAgent(); - new_position_agent = new_position_agent * ~root_object->getRotation(); - object->setPositionParent(new_position_agent, FALSE); - rebuild(object); - } + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); + iter != mObjectSelection->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + + if (selectNode->mSelectedGLTFNode != -1) + { + // manipulating a GLTF node + clamped_relative_move_f -= selectNode->mLastMoveLocal; + object->moveGLTFNode(selectNode->mSelectedGLTFNode, clamped_relative_move_f); + selectNode->mLastMoveLocal += clamped_relative_move_f; + } + else + { + // Only apply motion to root objects and objects selected + // as "individual". + if (!object->isRootEdit() && !selectNode->mIndividualSelection) + { + continue; + } + + if (!object->isRootEdit()) + { + // child objects should not update if parent is selected + LLViewerObject* editable_root = (LLViewerObject*)object->getParent(); + if (editable_root->isSelected()) + { + // we will be moved properly by our parent, so skip + continue; + } + } + + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced())) + { + // handle attachments in local space + if (object->isAttachment() && object->mDrawable.notNull()) + { + // calculate local version of relative move + LLQuaternion objWorldRotation = object->mDrawable->mXform.getParent()->getWorldRotation(); + objWorldRotation.transQuat(); + + LLVector3 old_position_local = object->getPosition(); + LLVector3 new_position_local = selectNode->mSavedPositionLocal + (clamped_relative_move_f * objWorldRotation); + + //RN: I forget, but we need to do this because of snapping which doesn't often result + // in position changes even when the mouse moves + object->setPosition(new_position_local); + rebuild(object); + gAgentAvatarp->clampAttachmentPositions(); + new_position_local = object->getPosition(); + + if (selectNode->mIndividualSelection) + { + // counter-translate child objects if we are moving the root as an individual + object->resetChildrenPosition(old_position_local - new_position_local, TRUE); + } + } + else + { + // compute new position to send to simulators, but don't set it yet. + // We need the old position to know which simulator to send the move message to. + LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; + + // Don't let object centers go too far underground + F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); + if (new_position_global.mdV[VZ] < min_height) + { + new_position_global.mdV[VZ] = min_height; + } + + // For safety, cap heights where objects can be dragged + if (new_position_global.mdV[VZ] > MAX_OBJECT_Z) + { + new_position_global.mdV[VZ] = MAX_OBJECT_Z; + } + + // Grass is always drawn on the ground, so clamp its position to the ground + if (object->getPCode() == LL_PCODE_LEGACY_GRASS) + { + new_position_global.mdV[VZ] = LLWorld::getInstance()->resolveLandHeightGlobal(new_position_global) + 1.f; + } + + if (object->isRootEdit()) + { + new_position_global = LLWorld::getInstance()->clipToVisibleRegions(object->getPositionGlobal(), new_position_global); + } + + // PR: Only update if changed + LLVector3 old_position_agent = object->getPositionAgent(); + LLVector3 new_position_agent = gAgent.getPosAgentFromGlobal(new_position_global); + if (object->isRootEdit()) + { + // finally, move parent object after children have calculated new offsets + object->setPositionAgent(new_position_agent); + rebuild(object); + } + else + { + LLViewerObject* root_object = object->getRootEdit(); + new_position_agent -= root_object->getPositionAgent(); + new_position_agent = new_position_agent * ~root_object->getRotation(); + object->setPositionParent(new_position_agent, FALSE); + rebuild(object); + } + + if (selectNode->mIndividualSelection) + { + // counter-translate child objects if we are moving the root as an individual + object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE); + } + } + selectNode->mLastPositionLocal = object->getPosition(); + } + } + } - if (selectNode->mIndividualSelection) - { - // counter-translate child objects if we are moving the root as an individual - object->resetChildrenPosition(old_position_agent - new_position_agent, TRUE) ; - } - } - selectNode->mLastPositionLocal = object->getPosition(); - } - } LLSelectMgr::getInstance()->updateSelectionCenter(); gAgentCamera.clearFocusObject(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 471601f16f..20b00974e1 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -456,7 +456,7 @@ void LLSelectMgr::overrideAvatarUpdates() //----------------------------------------------------------------------------- // Select just the object, not any other group members. //----------------------------------------------------------------------------- -LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) +LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face, S32 gltf_node, S32 gltf_primitive) { llassert( object ); @@ -481,7 +481,7 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S3 // Place it in the list and tag it. // This will refresh dialogs. - addAsIndividual(object, face); + addAsIndividual(object, face, TRUE, gltf_node, gltf_primitive); // Stop the object from moving (this anticipates changes on the // simulator in LLTask::userSelect) @@ -1033,7 +1033,7 @@ void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to //----------------------------------------------------------------------------- // addAsIndividual() - a single object, face, etc //----------------------------------------------------------------------------- -void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable) +void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable, S32 gltf_node, S32 gltf_primitive) { // check to see if object is already in list LLSelectNode *nodep = mSelectedObjects->findNode(objectp); @@ -1080,6 +1080,13 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab return; } + // Handle glTF node selection + if (gltf_node >= 0) + { + nodep->selectGLTFNode(gltf_node, gltf_primitive, TRUE); + + } + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); updateSelectionCenter(); dialog_refresh_all(); @@ -5211,46 +5218,57 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) { return true; // skip } - selectNode->mSavedPositionLocal = object->getPosition(); - if (object->isAttachment()) - { - if (object->isRootEdit()) - { - LLXform* parent_xform = object->mDrawable->getXform()->getParent(); - if (parent_xform) - { - selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - } - } - else - { - LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); - LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; - if (parent_xform) - { - LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); - LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); - selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - } - } - selectNode->mSavedRotation = object->getRenderRotation(); - } - else - { - selectNode->mSavedPositionGlobal = object->getPositionGlobal(); - selectNode->mSavedRotation = object->getRotationRegion(); - } - - selectNode->mSavedScale = object->getScale(); - selectNode->saveTextureScaleRatios(mManager->mTextureChannel); + + if (selectNode->mSelectedGLTFNode != -1) + { + // save GLTF node state + object->getGLTFNodeTransformAgent(selectNode->mSelectedGLTFNode, &selectNode->mSavedPositionLocal, &selectNode->mSavedRotation, &selectNode->mSavedScale); + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent(selectNode->mSavedPositionLocal); + selectNode->mLastMoveLocal.setZero(); + } + else + { + selectNode->mSavedPositionLocal = object->getPosition(); + if (object->isAttachment()) + { + if (object->isRootEdit()) + { + LLXform* parent_xform = object->mDrawable->getXform()->getParent(); + if (parent_xform) + { + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + } + } + else + { + LLViewerObject* attachment_root = (LLViewerObject*)object->getParent(); + LLXform* parent_xform = attachment_root ? attachment_root->mDrawable->getXform()->getParent() : NULL; + if (parent_xform) + { + LLVector3 root_pos = (attachment_root->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); + LLQuaternion root_rot = (attachment_root->getRotation() * parent_xform->getWorldRotation()); + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * root_rot) + root_pos); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + } + } + selectNode->mSavedRotation = object->getRenderRotation(); + } + else + { + selectNode->mSavedPositionGlobal = object->getPositionGlobal(); + selectNode->mSavedRotation = object->getRotationRegion(); + } + + selectNode->mSavedScale = object->getScale(); + selectNode->saveTextureScaleRatios(mManager->mTextureChannel); + } return true; } } func(action_type, this); @@ -6682,8 +6700,7 @@ LLSelectNode::~LLSelectNode() } } - - delete mPermissions; + delete mPermissions; mPermissions = NULL; } @@ -6711,6 +6728,17 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected) mLastTESelected = te_index; } +void LLSelectNode::selectGLTFNode(S32 node_index, S32 primitive_index, bool selected) +{ + if (node_index < 0) + { + return; + } + + mSelectedGLTFNode = node_index; + mSelectedGLTFPrimitive = primitive_index; +} + BOOL LLSelectNode::isTESelected(S32 te_index) const { if (te_index < 0 || te_index >= mObject->getNumTEs()) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index f89209b437..66c794af4c 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -175,6 +175,7 @@ public: void selectAllTEs(BOOL b); void selectTE(S32 te_index, BOOL selected); + void selectGLTFNode(S32 node_index, S32 primitive_index, bool selected); BOOL isTESelected(S32 te_index) const; bool hasSelectedTE() const { return TE_SELECT_MASK_ALL & mTESelectMask; } S32 getLastSelectedTE() const; @@ -217,6 +218,7 @@ public: S16 mInventorySerial; LLVector3 mSavedPositionLocal; // for interactively modifying object position LLVector3 mLastPositionLocal; + LLVector3 mLastMoveLocal; LLVector3d mSavedPositionGlobal; // for interactively modifying object position LLVector3 mSavedScale; // for interactively modifying object scale LLVector3 mLastScale; @@ -240,11 +242,14 @@ public: std::vector mSilhouetteVertices; // array of vertices to render silhouette of object std::vector mSilhouetteNormals; // array of normals to render silhouette of object BOOL mSilhouetteExists; // need to generate silhouette? + S32 mSelectedGLTFNode = -1; + S32 mSelectedGLTFPrimitive = -1; protected: LLPointer mObject; S32 mTESelectMask; S32 mLastTESelected; + }; class LLObjectSelection : public LLRefCount @@ -533,7 +538,7 @@ public: LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE, BOOL ignore_select_owned = FALSE); // For when you want just a child object. - LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); + LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES, S32 gltf_node = -1, S32 gltf_primitive = -1); // Same as above, but takes a list of objects. Used by rectangle select. LLObjectSelectionHandle selectObjectAndFamily(const std::vector& object_list, BOOL send_to_sim = TRUE); @@ -833,7 +838,7 @@ public: void remove(std::vector& objects); void remove(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE); void removeAll(); - void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE); + void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE, S32 gltf_node = -1, S32 gltf_primitive = -1); void promoteSelectionToRoot(); void demoteSelectionToIndividuals(); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 40e6f285a8..49c35165e6 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -87,20 +87,30 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material, { strip_alpha_channel(mr_img); - if (occlusion_img && material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) + if (occlusion_img) { - // occlusion is a distinct texture from pbrMetallicRoughness - // pack into mr red channel - int occlusion_idx = material.occlusionTexture.index; - int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; - if (occlusion_idx != mr_idx) + if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != material.occlusionTexture.index) { - //scale occlusion image to match resolution of mr image - occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); - - copy_red_channel(occlusion_img, mr_img); + // occlusion is a distinct texture from pbrMetallicRoughness + // pack into mr red channel + int occlusion_idx = material.occlusionTexture.index; + int mr_idx = material.pbrMetallicRoughness.metallicRoughnessTexture.index; + if (occlusion_idx != mr_idx) + { + //scale occlusion image to match resolution of mr image + occlusion_img->scale(mr_img->getWidth(), mr_img->getHeight()); + + copy_red_channel(occlusion_img, mr_img); + } } } + else + { + // no occlusion, make a white occlusion image + occlusion_img = new LLImageRaw(mr_img->getWidth(), mr_img->getHeight(), 3); + occlusion_img->clear(255, 255, 255); + copy_red_channel(occlusion_img, mr_img); + } } else if (occlusion_img) { diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index f7455c6cb8..907cec4d17 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -173,7 +173,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi if ( ignore_group ) { - LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); + LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES, pick.mGLTFNodeIndex, pick.mGLTFPrimitiveIndex); } else { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4cf948f20d..9f377ae3e7 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -996,6 +996,10 @@ U64 info_display_from_string(std::string info_display) { return LLPipeline::RENDER_DEBUG_OCTREE; } + else if ("nodes" == info_display) + { + return LLPipeline::RENDER_DEBUG_NODES; + } else if ("shadow frusta" == info_display) { return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index cee00db8eb..b66d4b1dab 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4374,6 +4374,168 @@ const LLVector3 &LLViewerObject::getPositionAgent() const return mPositionAgent; } +LLMatrix4a LLViewerObject::getGLTFAssetToAgentTransform() const +{ + LLMatrix4 root; + root.initScale(getScale()); + root.rotate(getRenderRotation()); + root.translate(getPositionAgent()); + + LLMatrix4a mat; + mat.loadu((F32*)root.mMatrix); + + return mat; +} + +LLVector3 LLViewerObject::getGLTFNodePositionAgent(S32 node_index) const +{ + LLVector3 ret; + getGLTFNodeTransformAgent(node_index, &ret, nullptr, nullptr); + return ret; + +} + +LLMatrix4a LLViewerObject::getAgentToGLTFAssetTransform() const +{ + LLMatrix4 root; + LLVector3 scale = getScale(); + scale.mV[0] = 1.f / scale.mV[0]; + scale.mV[1] = 1.f / scale.mV[1]; + scale.mV[2] = 1.f / scale.mV[2]; + + root.translate(-getPositionAgent()); + root.rotate(~getRenderRotation()); + + LLMatrix4 scale_mat; + scale_mat.initScale(scale); + + root *= scale_mat; + LLMatrix4a mat; + mat.loadu((F32*)root.mMatrix); + + return mat; +} + +LLMatrix4a LLViewerObject::getGLTFNodeTransformAgent(S32 node_index) const +{ + LLMatrix4a mat; + + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a asset_to_agent = getGLTFAssetToAgentTransform(); + LLMatrix4a node_to_agent; + matMul(node.mAssetMatrix, asset_to_agent, node_to_agent); + + mat = node_to_agent; + } + else + { + mat.setIdentity(); + } + + return mat; +} +void LLViewerObject::getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const +{ + LLMatrix4a node_to_agent = getGLTFNodeTransformAgent(node_index); + + if (position) + { + LLVector4a p = node_to_agent.getTranslation(); + position->set(p.getF32ptr()); + } + + if (rotation) + { + rotation->set(node_to_agent.asMatrix4()); + } + + if (scale) + { + scale->mV[0] = node_to_agent.mMatrix[0].getLength3().getF32(); + scale->mV[1] = node_to_agent.mMatrix[1].getLength3().getF32(); + scale->mV[2] = node_to_agent.mMatrix[2].getLength3().getF32(); + } +} + +void decomposeMatrix(const LLMatrix4a& mat, LLVector3& position, LLQuaternion& rotation, LLVector3& scale) +{ + LLVector4a p = mat.getTranslation(); + position.set(p.getF32ptr()); + + rotation.set(mat.asMatrix4()); + + scale.mV[0] = mat.mMatrix[0].getLength3().getF32(); + scale.mV[1] = mat.mMatrix[1].getLength3().getF32(); + scale.mV[2] = mat.mMatrix[2].getLength3().getF32(); +} + +void LLViewerObject::setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation) +{ + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); + LLMatrix4a agent_to_node = agent_to_asset; + + if (node.mParent != -1) + { + auto& parent = mGLTFAsset->mNodes[node.mParent]; + matMul(agent_to_asset, parent.mAssetMatrixInv, agent_to_node); + } + + LLQuaternion agent_to_node_rot(agent_to_node.asMatrix4()); + LLQuaternion new_rot; + + new_rot = rotation * agent_to_node_rot; + new_rot.normalize(); + + LLVector3 pos; + LLQuaternion rot; + LLVector3 scale; + decomposeMatrix(node.mMatrix, pos, rot, scale); + + node.mMatrix.asMatrix4().initAll(scale, new_rot, pos); + + mGLTFAsset->updateTransforms(); + } +} + +void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset) +{ + if (mGLTFAsset.notNull() && node_index >= 0 && node_index < mGLTFAsset->mNodes.size()) + { + auto& node = mGLTFAsset->mNodes[node_index]; + + LLMatrix4a agent_to_asset = getAgentToGLTFAssetTransform(); + LLMatrix4a agent_to_node; + matMul(agent_to_asset, node.mAssetMatrixInv, agent_to_node); + + LLVector4a origin = LLVector4a::getZero(); + LLVector4a offset_v; + offset_v.load3(offset.mV); + + + agent_to_node.affineTransform(offset_v, offset_v); + agent_to_node.affineTransform(origin, origin); + + offset_v.sub(origin); + offset_v.getF32ptr()[3] = 1.f; + + LLMatrix4a trans; + trans.setIdentity(); + trans.mMatrix[3] = offset_v; + + matMul(trans, node.mMatrix, node.mMatrix); + + // TODO -- only update transforms for this node and its children (or use a dirty flag) + mGLTFAsset->updateTransforms(); + } +} + const LLVector3 &LLViewerObject::getPositionRegion() const { if (!isRoot()) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 3d6903d177..64c1ee6633 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -315,6 +315,18 @@ public: virtual const LLVector3 &getPositionAgent() const; virtual const LLVector3 getRenderPosition() const; + LLMatrix4a getAgentToGLTFAssetTransform() const; + LLMatrix4a getGLTFAssetToAgentTransform() const; + LLVector3 getGLTFNodePositionAgent(S32 node_index) const; + LLMatrix4a getGLTFNodeTransformAgent(S32 node_index) const; + void getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const; + + // move the node at the given index by the given offset in agent space + void moveGLTFNode(S32 node_index, const LLVector3& offset); + + // set the rotation in agent space of the given node + void setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation); + virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not LLViewerObject* getRootEdit() const; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1459686f10..a0b0fabb66 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -246,6 +246,8 @@ LLVector2 gDebugRaycastTexCoord; LLVector4a gDebugRaycastNormal; LLVector4a gDebugRaycastTangent; S32 gDebugRaycastFaceHit; +S32 gDebugRaycastGLTFNodeHit; +S32 gDebugRaycastGLTFPrimitiveHit; LLVector4a gDebugRaycastStart; LLVector4a gDebugRaycastEnd; @@ -3348,9 +3350,11 @@ void LLViewerWindow::updateUI() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) { - gDebugRaycastFaceHit = -1; + gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1; gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, FALSE, &gDebugRaycastFaceHit, + &gDebugRaycastGLTFNodeHit, + &gDebugRaycastGLTFPrimitiveHit, &gDebugRaycastIntersection, &gDebugRaycastTexCoord, &gDebugRaycastNormal, @@ -4343,6 +4347,8 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de BOOL pick_unselectable, BOOL pick_reflection_probe, S32* face_hit, + S32* gltf_node_hit, + S32* gltf_primitive_hit, LLVector4a *intersection, LLVector2 *uv, LLVector4a *normal, @@ -4436,7 +4442,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, pick_unselectable, pick_reflection_probe, - face_hit, intersection, uv, normal, tangent); + face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent); if (found && !pick_transparent) { gDebugRaycastIntersection = *intersection; @@ -6140,8 +6146,8 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, void LLPickInfo::fetchResults() { - S32 face_hit = -1; + LLVector4a intersection, normal; LLVector4a tangent; @@ -6164,8 +6170,8 @@ void LLPickInfo::fetchResults() } LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, - NULL, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, - &intersection, &uv, &normal, &tangent, &start, &end); + nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, + &intersection, &uv, &normal, &tangent, &start, &end); mPickPt = mMousePt; @@ -6311,6 +6317,8 @@ void LLPickInfo::getSurfaceInfo() if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &mObjectFace, + &mGLTFNodeIndex, + &mGLTFPrimitiveIndex, &intersection, &mSTCoords, &normal, diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad634503ba..2e90c5faeb 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -119,6 +119,8 @@ public: LLUUID mParticleOwnerID; LLUUID mParticleSourceID; S32 mObjectFace; + S32 mGLTFNodeIndex = -1; + S32 mGLTFPrimitiveIndex = -1; LLHUDIcon* mHUDIcon; LLVector3 mIntersection; LLVector2 mUVCoords; @@ -423,6 +425,8 @@ public: BOOL pick_unselectable = TRUE, BOOL pick_reflection_probe = TRUE, S32* face_hit = NULL, + S32* gltf_node_hit = nullptr, + S32* gltf_primitive_hit = nullptr, LLVector4a *intersection = NULL, LLVector2 *uv = NULL, LLVector4a *normal = NULL, diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ea40365c97..3adf2828f8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6309,6 +6309,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, bool pick_unselectable, bool pick_reflection_probe, S32* face_hit, + S32* gltf_node_hit, + S32* gltf_primitive_hit, LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point LLVector4a* normal, // return the surface normal at the intersection point @@ -6352,15 +6354,6 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, } } - S32 node_hit = -1; - S32 primitive_hit = -1; - LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent); - if (hit) - { - drawable = hit; - local_end = position; - } - if (!sPickAvatar) { //save hit info in case we need to restore @@ -6461,6 +6454,25 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, } } + S32 node_hit = -1; + S32 primitive_hit = -1; + LLDrawable* hit = LL::GLTFSceneManager::instance().lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, &node_hit, &primitive_hit, &position, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + local_end = position; + } + + if (gltf_node_hit) + { + *gltf_node_hit = node_hit; + } + + if (gltf_primitive_hit) + { + *gltf_primitive_hit = primitive_hit; + } + if (intersection) { *intersection = position; @@ -7269,7 +7281,7 @@ void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) LLVector4a result; result.clear(); - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, NULL, &result); + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, nullptr, nullptr, nullptr, &result); focus_point.set(result.getF32ptr()); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 817750b4a1..bfa4009a0b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -210,6 +210,8 @@ public: bool pick_unselectable, bool pick_reflection_probe, S32* face_hit, // return the face hit + S32* gltf_node_hit = nullptr, // return the gltf node hit + S32* gltf_primitive_hit = nullptr, // return the gltf primitive hit LLVector4a* intersection = NULL, // return the intersection point LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector4a* normal = NULL, // return the surface normal at the intersection point @@ -615,12 +617,12 @@ public: RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000, RENDER_DEBUG_NORMALS = 0x04000000, RENDER_DEBUG_LOD_INFO = 0x08000000, - RENDER_DEBUG_ATTACHMENT_BYTES = 0x20000000, // not used + RENDER_DEBUG_NODES = 0x20000000, RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, RENDER_DEBUG_IMPOSTORS = 0x100000000, RENDER_DEBUG_REFLECTION_PROBES = 0x200000000, - RENDER_DEBUG_PROBE_UPDATES = 0x400000000 + RENDER_DEBUG_PROBE_UPDATES = 0x400000000, }; public: diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index c2f04231fc..a366e78a2d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2888,6 +2888,16 @@ function="World.EnvPreset" function="Advanced.ToggleInfoDisplay" parameter="octree" /> + + + + -- cgit v1.2.3 From 9b5615647dc5053769af4fcf18b5805ffa89c50b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 19 Apr 2024 01:03:27 +0300 Subject: viewer#1081 removed a 'not finalized' part of 2K benefits This part isn't planned at the moment, at least not this way, remove to not cause issues once server side changes behavior --- indra/newview/llagentbenefits.cpp | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp index 29b0a4612f..0717d92ea7 100644 --- a/indra/newview/llagentbenefits.cpp +++ b/indra/newview/llagentbenefits.cpp @@ -201,19 +201,6 @@ S32 LLAgentBenefits::get2KTextureUploadCost(S32 area) const { return m_texture_upload_cost; } - const S32 TEXTURE_SEGMENTS = 1024; - if (m_2k_texture_upload_cost.size() == TEXTURE_SEGMENTS) - { - S32 index = (S32)llceil(sqrt((F32)area)); - // 1..1024 pixels uses m_texture_upload_cost - // 1025..2048 uses m_2k_texture_upload_cost - // Translate 1025..2048 to 0..1023 of the - // cost array - const S32 PIXELS_TO_2K_ARRAY_TRANLATE = 1025; - index -= PIXELS_TO_2K_ARRAY_TRANLATE; - index = llclamp(index, 0, TEXTURE_SEGMENTS - 1); - return m_2k_texture_upload_cost[index]; - } return m_2k_texture_upload_cost[0]; } -- cgit v1.2.3 From 51c7108650722c39521fc439a07ffe63a173396f Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Fri, 19 Apr 2024 10:55:05 -0400 Subject: Update to use newer mikktspace generation lib changes from Blender for bug/crash fixes --- indra/llmath/llvolume.cpp | 97 ++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 60 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2f25a4359d..4384c732b2 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -53,8 +53,7 @@ #include "lltimer.h" #include "llvolumeoctree.h" -#include "mikktspace/mikktspace.h" -#include "mikktspace/mikktspace.c" // insert mikktspace implementation into llvolume object file +#include "mikktspace/mikktspace.hh" #include "meshoptimizer/meshoptimizer.h" @@ -5436,6 +5435,40 @@ struct MikktData } } } + + uint32_t GetNumFaces() + { + return uint32_t(face->mNumIndices / 3); + } + + uint32_t GetNumVerticesOfFace(const uint32_t face_num) + { + return 3; + } + + mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num) + { + F32* v = p[face_num * 3 + vert_num].mV; + return mikk::float3(v); + } + + mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) + { + F32* uv = tc[face_num * 3 + vert_num].mV; + return mikk::float3(uv[0], uv[1], 1.0f); + } + + mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) + { + F32* normal = n[face_num * 3 + vert_num].mV; + return mikk::float3(normal); + } + + void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation) + { + S32 i = face_num * 3 + vert_num; + t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f); + } }; bool LLVolumeFace::cacheOptimize(bool gen_tangents) @@ -5448,62 +5481,9 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) { // generate mikkt space tangents before cache optimizing since the index buffer may change // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh // and is executed on a background thread - SMikkTSpaceInterface ms; - - ms.m_getNumFaces = [](const SMikkTSpaceContext* pContext) - { - MikktData* data = (MikktData*)pContext->m_pUserData; - LLVolumeFace* face = data->face; - return face->mNumIndices / 3; - }; - - ms.m_getNumVerticesOfFace = [](const SMikkTSpaceContext* pContext, const int iFace) - { - return 3; - }; - - ms.m_getPosition = [](const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert) - { - MikktData* data = (MikktData*)pContext->m_pUserData; - F32* v = data->p[iFace * 3 + iVert].mV; - fvPosOut[0] = v[0]; - fvPosOut[1] = v[1]; - fvPosOut[2] = v[2]; - }; - - ms.m_getNormal = [](const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert) - { - MikktData* data = (MikktData*)pContext->m_pUserData; - F32* n = data->n[iFace * 3 + iVert].mV; - fvNormOut[0] = n[0]; - fvNormOut[1] = n[1]; - fvNormOut[2] = n[2]; - }; - - ms.m_getTexCoord = [](const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert) - { - MikktData* data = (MikktData*)pContext->m_pUserData; - F32* tc = data->tc[iFace * 3 + iVert].mV; - fvTexcOut[0] = tc[0]; - fvTexcOut[1] = tc[1]; - }; - - ms.m_setTSpaceBasic = [](const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) - { - MikktData* data = (MikktData*)pContext->m_pUserData; - S32 i = iFace * 3 + iVert; - - data->t[i].set(fvTangent); - data->t[i].mV[3] = fSign; - }; - - ms.m_setTSpace = nullptr; - MikktData data(this); - - SMikkTSpaceContext ctx = { &ms, &data }; - - genTangSpaceDefault(&ctx); + mikk::Mikktspace ctx(data); + ctx.genTangSpace(); //re-weld meshopt_Stream mos[] = @@ -5524,9 +5504,6 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) if (vert_count < 65535 && vert_count != 0) { - std::vector indices; - indices.resize(mNumIndices); - //copy results back into volume resizeVertices(vert_count); -- cgit v1.2.3 From 2880e5ceeeacbf4024167b2a4e0f1d2ce129eb6f Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 19 Apr 2024 11:59:28 -0500 Subject: #1139 Fix for world going black/white in some scenes (NaNs) (#1273) * #1139 Fix for world going black/white in some scenes (NaNs) NaNs were coming from normal encode/decode. Take advantage of available gbuffer space to send full normal instead of encoding. * #1139 Cleanup remove now unused encodeNormF.glsl * #1139 Remove final reference to encodeNormF * #1139 Fix for getNormalEnvIntensityFlags referencing wrong sampler for env intensity * Mac build fix --- indra/llrender/llglslshader.h | 1 - indra/llrender/llshadermgr.cpp | 8 ---- .../shaders/class1/deferred/avatarF.glsl | 6 +-- .../shaders/class1/deferred/bumpF.glsl | 6 +-- .../shaders/class1/deferred/deferredUtil.glsl | 20 +++------ .../shaders/class1/deferred/diffuseAlphaMaskF.glsl | 4 +- .../class1/deferred/diffuseAlphaMaskIndexedF.glsl | 4 +- .../class1/deferred/diffuseAlphaMaskNoColorF.glsl | 4 +- .../shaders/class1/deferred/diffuseF.glsl | 5 +-- .../shaders/class1/deferred/diffuseIndexedF.glsl | 5 +-- .../shaders/class1/deferred/impostorF.glsl | 3 +- .../shaders/class1/deferred/pbropaqueF.glsl | 3 +- .../shaders/class1/deferred/pbrterrainF.glsl | 3 +- .../shaders/class1/deferred/terrainF.glsl | 3 +- .../shaders/class1/deferred/treeF.glsl | 4 +- .../shaders/class1/environment/encodeNormF.glsl | 34 -------------- .../shaders/class2/deferred/alphaF.glsl | 1 - .../shaders/class3/deferred/materialF.glsl | 14 +++--- .../shaders/class3/deferred/softenLightF.glsl | 5 ++- indra/newview/lldrawpoolbump.cpp | 7 +-- indra/newview/llviewermenu.cpp | 20 +++++++++ indra/newview/llviewershadermgr.cpp | 20 --------- indra/newview/pipeline.cpp | 4 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 52 +++++++++++++++++++++- 24 files changed, 109 insertions(+), 127 deletions(-) delete mode 100644 indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl (limited to 'indra') diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index e8529ebadc..ed0f27d143 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -49,7 +49,6 @@ public: bool hasShadows = false; bool hasAmbientOcclusion = false; bool hasSrgb = false; - bool encodesNormal = false; // include: shaders\class1\environment\encodeNormF.glsl bool isDeferred = false; bool hasScreenSpaceReflections = false; bool disableTextureIndex = false; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 6cfe065355..0b20ff6230 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -264,14 +264,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if (features->encodesNormal) - { - if (!shader->attachFragmentObject("environment/encodeNormF.glsl")) - { - return FALSE; - } - } - if (features->hasAtmospherics || features->isDeferred) { if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index c0607d0149..db7597dd74 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -25,7 +25,7 @@ /*[EXTRA_CODE_HERE]*/ -out vec4 frag_data[3]; +out vec4 frag_data[4]; uniform sampler2D diffuseMap; @@ -35,7 +35,6 @@ in vec3 vary_normal; in vec2 vary_texcoord0; in vec3 vary_position; -vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos); void main() @@ -52,6 +51,7 @@ void main() frag_data[0] = vec4(diff.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index a22c174349..8483f257fa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -39,8 +39,6 @@ in vec4 vertex_color; in vec2 vary_texcoord0; in vec3 vary_position; -vec2 encode_normal(vec3 n); - void mirrorClip(vec3 pos); void main() { @@ -64,6 +62,6 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index f9ebf33b4a..065fcec45a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -50,6 +50,7 @@ SOFTWARE. uniform sampler2D normalMap; uniform sampler2D depthMap; +uniform sampler2D emissiveRect; uniform sampler2D projectionMap; // rgba uniform sampler2D brdfLut; @@ -140,18 +141,9 @@ vec2 getScreenCoordinate(vec2 screenpos) return sc - vec2(1.0, 1.0); } -// See: https://aras-p.info/texts/CompactNormalStorage.html -// Method #4: Spheremap Transform, Lambert Azimuthal Equal-Area projection vec3 getNorm(vec2 screenpos) { - vec2 enc = texture(normalMap, screenpos.xy).xy; - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return n; + return texture(normalMap, screenpos.xy).rgb; } vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags) @@ -170,10 +162,10 @@ vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags) // See: C++: addDeferredAttachments(), GLSL: softenLightF vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity) { - vec4 packedNormalEnvIntensityFlags = texture(normalMap, screenpos.xy); - n = getNormalFromPacked( packedNormalEnvIntensityFlags ); - envIntensity = packedNormalEnvIntensityFlags.z; - return packedNormalEnvIntensityFlags; + n = texture(normalMap, screenpos.xy).rgb; + envIntensity = texture(emissiveRect, screenpos.xy).r; + + return vec4(n, envIntensity); } // get linear depth value given a depth buffer sample d and znear and zfar values diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index e8ead91504..82d5d363d2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -37,8 +37,6 @@ in vec3 vary_normal; in vec4 vertex_color; in vec2 vary_texcoord0; -vec2 encode_normal(vec3 n); - void mirrorClip(vec3 pos); void main() @@ -55,7 +53,7 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index a07c892d8e..788ea633fc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -35,8 +35,6 @@ uniform float minimum_alpha; in vec4 vertex_color; in vec2 vary_texcoord0; -vec2 encode_normal(vec3 n); - void mirrorClip(vec3 pos); void main() @@ -53,6 +51,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 234f096ed5..22e6d60419 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -34,8 +34,6 @@ uniform sampler2D diffuseMap; in vec3 vary_normal; in vec2 vary_texcoord0; -vec2 encode_normal(vec3 n); - void main() { vec4 col = texture(diffuseMap, vary_texcoord0.xy); @@ -48,7 +46,7 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 76776ede2c..799fc62a42 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -34,7 +34,6 @@ in vec4 vertex_color; in vec2 vary_texcoord0; in vec3 vary_position; -vec2 encode_normal(vec3 n); void mirrorClip(vec3 pos); void main() @@ -45,7 +44,7 @@ void main() frag_data[1] = vertex_color.aaaa; // spec //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index b983acf657..3362a180c6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -33,7 +33,6 @@ in vec2 vary_texcoord0; in vec3 vary_position; void mirrorClip(vec3 pos); -vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); void main() @@ -47,6 +46,6 @@ void main() frag_data[0] = vec4(col, 0.0); frag_data[1] = vec4(spec, vertex_color.a); // spec vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, GBUFFER_FLAG_HAS_ATMOS); - frag_data[3] = vec4(0); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index aae595f619..c64f65e32c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -37,7 +37,6 @@ uniform sampler2D specularMap; in vec2 vary_texcoord0; vec3 linear_to_srgb(vec3 c); -vec2 encode_normal (vec3 n); void main() { @@ -53,6 +52,6 @@ void main() frag_data[0] = vec4(col.rgb, 0.0); frag_data[1] = spec; - frag_data[2] = vec4(encode_normal(norm.xyz),0,GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(norm.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index 0683236460..55fc94b7f5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -54,7 +54,6 @@ in vec2 emissive_texcoord; uniform float minimum_alpha; // PBR alphaMode: MASK, See: mAlphaCutoff, setAlphaCutoff() -vec2 encode_normal(vec3 n); vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); @@ -110,7 +109,7 @@ void main() // See: C++: addDeferredAttachments(), GLSL: softenLightF frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(encode_normal(tnorm), vertex_color.a, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags + frag_data[2] = max(vec4(tnorm, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 57c0a6024f..025ecb64df 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -140,7 +140,6 @@ flat in float vary_sign; in vec4 vary_texcoord0; in vec4 vary_texcoord1; -vec2 encode_normal(vec3 n); void mirrorClip(vec3 position); float terrain_mix(TerrainMix tm, vec4 tms4); @@ -342,7 +341,7 @@ void main() #endif frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(encode_normal(tnorm), base_color_factor_alpha, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags + frag_data[2] = max(vec4(tnorm, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 2dba7cb9d9..5f598f84a7 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -38,7 +38,6 @@ in vec3 vary_normal; in vec4 vary_texcoord0; in vec4 vary_texcoord1; -vec2 encode_normal(vec3 n); void mirrorClip(vec3 position); void main() @@ -61,7 +60,7 @@ void main() frag_data[0] = outColor; frag_data[1] = vec4(0.0,0.0,0.0,-1.0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index f108faf283..708acd0194 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -36,8 +36,6 @@ in vec3 vary_position; uniform float minimum_alpha; -vec2 encode_normal(vec3 n); - void mirrorClip(vec3 pos); void main() { @@ -51,6 +49,6 @@ void main() frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); frag_data[1] = vec4(0,0,0,0); vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl deleted file mode 100644 index 6cd2445522..0000000000 --- a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file encodeNormF.glsl - * - * $LicenseInfo:firstyear=2018&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2018, 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$ - */ - -// Lambert Azimuthal Equal-Area projection -// See: https://aras-p.info/texts/CompactNormalStorage.html -// Also see: A_bit_more_deferred_-_CryEngine3.ppt -vec2 encode_normal(vec3 n) -{ - float f = sqrt(8 * n.z + 8); - return n.xy / f + 0.5; -} - diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 4aef22c296..7a1a54a77a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -68,7 +68,6 @@ void waterClip(vec3 pos); vec3 srgb_to_linear(vec3 c); vec3 linear_to_srgb(vec3 c); -vec2 encode_normal (vec3 n); vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 0476b98e10..d49db4b74d 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -216,8 +216,6 @@ in vec3 vary_normal; in vec4 vertex_color; in vec2 vary_texcoord0; -vec2 encode_normal(vec3 n); - // get the transformed normal and apply glossiness component from normal map vec3 getNormal(inout float glossiness) { @@ -306,8 +304,6 @@ void main() float glossiness = specular_color.a; vec3 norm = getNormal(glossiness); - vec2 abnormal = encode_normal(norm.xyz); - float emissive = getEmissive(diffcol); #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) @@ -417,10 +413,12 @@ void main() float flag = GBUFFER_FLAG_HAS_ATMOS; - frag_data[0] = vec4(diffcol.rgb, emissive); // gbuffer is sRGB for legacy materials - frag_data[1] = vec4(spec.rgb, glossiness); // XYZ = Specular color. W = Specular exponent. - frag_data[2] = vec4(encode_normal(norm), env, flag);; // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) - frag_data[3] = vec4(0); + frag_data[0] = max(vec4(diffcol.rgb, emissive), vec4(0)); // gbuffer is sRGB for legacy materials + frag_data[1] = max(vec4(spec.rgb, glossiness), vec4(0)); // XYZ = Specular color. W = Specular exponent. + frag_data[2] = max(vec4(norm, flag), vec4(0)); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) + frag_data[3] = vec4(env, 0, 0, 0); + #endif } + diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 9b9739ba22..f71f8a028f 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -129,7 +129,8 @@ void main() float depth = getDepth(tc.xy); vec4 pos = getPositionWithDepth(tc, depth); vec4 norm = texture(normalMap, tc); - float envIntensity = norm.z; + vec3 colorEmissive = texture(emissiveRect, tc).rgb; + float envIntensity = colorEmissive.r; norm.xyz = getNorm(tc); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; @@ -174,7 +175,7 @@ void main() float metallic = orm.b; float ao = orm.r; - vec3 colorEmissive = texture(emissiveRect, tc).rgb; + // PBR IBL float gloss = 1.0 - perceptualRoughness; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index a0ce0ef6cf..24df11c158 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -701,8 +701,7 @@ void LLBumpImageList::updateImages() { for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) { - bump_image_map_t::iterator curiter = iter++; - LLViewerTexture* image = curiter->second; + LLViewerTexture* image = iter->second; if( image ) { BOOL destroy = TRUE; @@ -721,9 +720,11 @@ void LLBumpImageList::updateImages() if( destroy ) { //LL_INFOS() << "*** Destroying bright " << (void*)image << LL_ENDL; - mBrightnessEntries.erase(curiter); // deletes the image thanks to reference counting + iter = mBrightnessEntries.erase(iter); // deletes the image thanks to reference counting + continue; } } + ++iter; } for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9f377ae3e7..360fc3ea7b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -740,10 +740,30 @@ U32 render_type_from_string(std::string render_type) { return LLPipeline::RENDER_TYPE_SIMPLE; } + if ("materials" == render_type) + { + return LLPipeline::RENDER_TYPE_MATERIALS; + } else if ("alpha" == render_type) { return LLPipeline::RENDER_TYPE_ALPHA; } + else if ("alpha_mask" == render_type) + { + return LLPipeline::RENDER_TYPE_ALPHA_MASK; + } + else if ("fullbright_alpha_mask" == render_type) + { + return LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK; + } + else if ("fullbright" == render_type) + { + return LLPipeline::RENDER_TYPE_FULLBRIGHT; + } + else if ("glow" == render_type) + { + return LLPipeline::RENDER_TYPE_GLOW; + } else if ("tree" == render_type) { return LLPipeline::RENDER_TYPE_TREE; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 65b1fee54b..24064ed6c1 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -720,7 +720,6 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mShaderLevel[SHADER_WATER] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/encodeNormF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/globalF.glsl", 1)); @@ -1040,7 +1039,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; - gDeferredDiffuseProgram.mFeatures.encodesNormal = true; gDeferredDiffuseProgram.mFeatures.hasSrgb = true; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); @@ -1054,7 +1052,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; - gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER)); @@ -1067,7 +1064,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; - gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true; gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); @@ -1079,7 +1075,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask No Color Shader"; - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true; gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear(); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER)); gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER)); @@ -1091,7 +1086,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredBumpProgram.mName = "Deferred Bump Shader"; - gDeferredBumpProgram.mFeatures.encodesNormal = true; gDeferredBumpProgram.mShaderFiles.clear(); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER)); gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER)); @@ -1163,7 +1157,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].mFeatures.hasSrgb = true; - gDeferredMaterialProgram[i].mFeatures.encodesNormal = true; gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true; gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true; gDeferredMaterialProgram[i].mFeatures.hasGamma = true; @@ -1197,7 +1190,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredPBROpaqueProgram.mName = "Deferred PBR Opaque Shader"; - gDeferredPBROpaqueProgram.mFeatures.encodesNormal = true; gDeferredPBROpaqueProgram.mFeatures.hasSrgb = true; gDeferredPBROpaqueProgram.mShaderFiles.clear(); @@ -1258,7 +1250,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() shader->mFeatures.hasLighting = false; shader->mFeatures.isAlphaLighting = true; shader->mFeatures.hasSrgb = true; - shader->mFeatures.encodesNormal = true; shader->mFeatures.calculatesAtmospherics = true; shader->mFeatures.hasAtmospherics = true; shader->mFeatures.hasGamma = true; @@ -1329,7 +1320,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBRTerrainProgram.mName = llformat("Deferred PBR Terrain Shader %d %s", detail, (mapping == 1 ? "flat" : "triplanar")); - gDeferredPBRTerrainProgram.mFeatures.encodesNormal = true; gDeferredPBRTerrainProgram.mFeatures.hasSrgb = true; gDeferredPBRTerrainProgram.mFeatures.isAlphaLighting = true; gDeferredPBRTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels @@ -1353,7 +1343,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredTreeProgram.mName = "Deferred Tree Shader"; gDeferredTreeProgram.mShaderFiles.clear(); - gDeferredTreeProgram.mFeatures.encodesNormal = true; gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER)); gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER)); gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; @@ -1388,8 +1377,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; gDeferredImpostorProgram.mFeatures.hasSrgb = true; - gDeferredImpostorProgram.mFeatures.encodesNormal = true; - //gDeferredImpostorProgram.mFeatures.isDeferred = true; gDeferredImpostorProgram.mShaderFiles.clear(); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER)); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER)); @@ -1551,7 +1538,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() shader->mFeatures.isAlphaLighting = true; shader->mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels shader->mFeatures.hasSrgb = true; - shader->mFeatures.encodesNormal = true; shader->mFeatures.calculatesAtmospherics = true; shader->mFeatures.hasAtmospherics = true; shader->mFeatures.hasGamma = true; @@ -1613,7 +1599,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() shader->mFeatures.hasSrgb = true; shader->mFeatures.isAlphaLighting = true; - shader->mFeatures.encodesNormal = true; shader->mFeatures.hasShadows = use_sun_shadow; shader->mFeatures.hasReflectionProbes = true; shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; @@ -1661,7 +1646,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarEyesProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true; - gDeferredAvatarEyesProgram.mFeatures.encodesNormal = true; gDeferredAvatarEyesProgram.mFeatures.hasShadows = true; gDeferredAvatarEyesProgram.mShaderFiles.clear(); @@ -2059,7 +2043,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { gDeferredTerrainProgram.mName = "Deferred Terrain Shader"; - gDeferredTerrainProgram.mFeatures.encodesNormal = true; gDeferredTerrainProgram.mFeatures.hasSrgb = true; gDeferredTerrainProgram.mFeatures.isAlphaLighting = true; gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels @@ -2079,7 +2062,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredAvatarProgram.mName = "Deferred Avatar Shader"; gDeferredAvatarProgram.mFeatures.hasSkinning = true; - gDeferredAvatarProgram.mFeatures.encodesNormal = true; gDeferredAvatarProgram.mShaderFiles.clear(); gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER)); gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER)); @@ -2097,7 +2079,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true; gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarAlphaProgram.mFeatures.hasSrgb = true; - gDeferredAvatarAlphaProgram.mFeatures.encodesNormal = true; gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; @@ -2431,7 +2412,6 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { gObjectBumpProgram.mName = "Bump Shader"; - gObjectBumpProgram.mFeatures.encodesNormal = true; gObjectBumpProgram.mShaderFiles.clear(); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER)); gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER)); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3adf2828f8..fd8a2e3ffc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -331,8 +331,8 @@ bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false) { bool valid = true && target.addColorAttachment(GL_RGBA) // frag-data[1] specular OR PBR ORM - && target.addColorAttachment(GL_RGBA16F) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight - && target.addColorAttachment(GL_RGB16F); // frag_data[3] PBR emissive + && target.addColorAttachment(GL_RGBA16F) // frag_data[2] normal+fogmask, See: class1\deferred\materialF.glsl & softenlight + && target.addColorAttachment(GL_RGB16F); // frag_data[3] PBR emissive OR material env intensity return valid; } diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a366e78a2d..44300738bb 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2039,7 +2039,57 @@ function="World.EnvPreset" function="Advanced.ToggleRenderType" parameter="simple" /> - + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From da2662478a915828d740b0628083fd9a6e138eda Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Mon, 15 Apr 2024 18:39:23 +0300 Subject: Revert "SL-20140 Setting shape hand size to 36 won't save" This reverts commit 810a3d24c2e3671f926091c062b101bdec6a1517. (secondlife/jira-archive-internal#70482) --- indra/newview/character/avatar_lad.xml | 17 ++++---- indra/newview/llscrollingpanelparam.cpp | 63 ++++++++++++++++++++--------- indra/newview/llscrollingpanelparam.h | 3 ++ indra/newview/llscrollingpanelparambase.cpp | 29 +++++++------ indra/newview/llscrollingpanelparambase.h | 7 +--- 5 files changed, 72 insertions(+), 47 deletions(-) (limited to 'indra') diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml index aef402d4db..2cdd86267e 100644 --- a/indra/newview/character/avatar_lad.xml +++ b/indra/newview/character/avatar_lad.xml @@ -2021,7 +2021,7 @@ value_min="-1" value_max="1"> - + - - @@ -2041,7 +2042,7 @@ name="mFaceEyeAltRight" scale="0 0 0" offset="-.005 0 0" /> - + - @@ -2061,17 +2062,17 @@ name="mFaceEyeLidUpperLeft" scale="0 0.3 0.7" offset=" 0 0 0" /> - + - + - + diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index efd84eaa6d..bfa453a0ae 100644 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -259,15 +259,19 @@ void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint ) // Make sure we're not taking the slider out of bounds // (this is where some simple UI limits are stored) - F32 new_percent = weightToSlider(new_weight); - if (mSlider->getMinValue() < new_percent - && new_percent < mSlider->getMaxValue()) + F32 new_percent = weightToPercent(new_weight); + LLSliderCtrl* slider = getChild("param slider"); + if (slider) { - mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight); - mWearable->writeToAvatar(gAgentAvatarp); - gAgentAvatarp->updateVisualParams(); + if (slider->getMinValue() < new_percent + && new_percent < slider->getMaxValue()) + { + mWearable->setVisualParamWeight( hint->getVisualParam()->getID(), new_weight); + mWearable->writeToAvatar(gAgentAvatarp); + gAgentAvatarp->updateVisualParams(); - mSlider->setValue( weightToSlider( new_weight ) ); + slider->setValue( weightToPercent( new_weight ) ); + } } } } @@ -288,13 +292,17 @@ void LLScrollingPanelParam::onHintMinMouseUp( void* userdata ) F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight(); // step a fraction in the negative directiona F32 new_weight = current_weight - (range / 10.f); - F32 new_percent = self->weightToSlider(new_weight); - if (self->mSlider->getMinValue() < new_percent - && new_percent < self->mSlider->getMaxValue()) + F32 new_percent = self->weightToPercent(new_weight); + LLSliderCtrl* slider = self->getChild("param slider"); + if (slider) { - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); - self->mWearable->writeToAvatar(gAgentAvatarp); - self->mSlider->setValue( self->weightToSlider( new_weight ) ); + if (slider->getMinValue() < new_percent + && new_percent < slider->getMaxValue()) + { + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); + self->mWearable->writeToAvatar(gAgentAvatarp); + slider->setValue( self->weightToPercent( new_weight ) ); + } } } @@ -318,16 +326,33 @@ void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata ) F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight(); // step a fraction in the negative direction F32 new_weight = current_weight + (range / 10.f); - F32 new_percent = self->weightToSlider(new_weight); - if (self->mSlider->getMinValue() < new_percent - && new_percent < self->mSlider->getMaxValue()) + F32 new_percent = self->weightToPercent(new_weight); + LLSliderCtrl* slider = self->getChild("param slider"); + if (slider) { - self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); - self->mWearable->writeToAvatar(gAgentAvatarp); - self->mSlider->setValue( self->weightToSlider( new_weight ) ); + if (slider->getMinValue() < new_percent + && new_percent < slider->getMaxValue()) + { + self->mWearable->setVisualParamWeight(hint->getVisualParam()->getID(), new_weight); + self->mWearable->writeToAvatar(gAgentAvatarp); + slider->setValue( self->weightToPercent( new_weight ) ); + } } } } LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax ); } + + +F32 LLScrollingPanelParam::weightToPercent( F32 weight ) +{ + LLViewerVisualParam* param = mParam; + return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f; +} + +F32 LLScrollingPanelParam::percentToWeight( F32 percent ) +{ + LLViewerVisualParam* param = mParam; + return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight(); +} diff --git a/indra/newview/llscrollingpanelparam.h b/indra/newview/llscrollingpanelparam.h index dc344486fc..c7a47d5c7a 100644 --- a/indra/newview/llscrollingpanelparam.h +++ b/indra/newview/llscrollingpanelparam.h @@ -61,6 +61,9 @@ public: void onHintMouseDown( LLVisualParamHint* hint ); void onHintHeldDown( LLVisualParamHint* hint ); + F32 weightToPercent( F32 weight ); + F32 percentToWeight( F32 percent ); + public: // Constants for LLPanelVisualParam const static F32 PARAM_STEP_TIME_THRESHOLD; diff --git a/indra/newview/llscrollingpanelparambase.cpp b/indra/newview/llscrollingpanelparambase.cpp index 2a6c25235d..fe7a362723 100644 --- a/indra/newview/llscrollingpanelparambase.cpp +++ b/indra/newview/llscrollingpanelparambase.cpp @@ -43,7 +43,6 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify, LLWearable* wearable, LLJoint* jointp, BOOL use_hints) : LLScrollingPanel( panel_params ), mParam(param), - mSlider(nullptr), mAllowModify(allow_modify), mWearable(wearable) { @@ -51,15 +50,13 @@ LLScrollingPanelParamBase::LLScrollingPanelParamBase( const LLPanel::Params& pan buildFromFile( "panel_scrolling_param.xml"); else buildFromFile( "panel_scrolling_param_base.xml"); - - mSlider = getChild("param slider"); - mSlider->setMaxValue(100.f * (mParam->getMaxWeight() - mParam->getMinWeight())); - mSlider->setValue(weightToSlider(param->getWeight())); + + getChild("param slider")->setValue(weightToPercent(param->getWeight())); std::string display_name = LLTrans::getString(param->getDisplayName()); - mSlider->setLabelArg("[DESC]", display_name); - mSlider->setEnabled(mAllowModify); - mSlider->setCommitCallback(boost::bind(LLScrollingPanelParamBase::onSliderMoved, mSlider, this)); + getChild("param slider")->setLabelArg("[DESC]", display_name); + getChildView("param slider")->setEnabled(mAllowModify); + childSetCommitCallback("param slider", LLScrollingPanelParamBase::onSliderMoved, this); setVisible(FALSE); setBorderVisible( FALSE ); @@ -80,9 +77,9 @@ void LLScrollingPanelParamBase::updatePanel(BOOL allow_modify) } F32 current_weight = mWearable->getVisualParamWeight( param->getID() ); - mSlider->setValue(weightToSlider( current_weight ) ); + getChild("param slider")->setValue(weightToPercent( current_weight ) ); mAllowModify = allow_modify; - mSlider->setEnabled(mAllowModify); + getChildView("param slider")->setEnabled(mAllowModify); } // static @@ -93,7 +90,7 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata) LLViewerVisualParam* param = self->mParam; F32 current_weight = self->mWearable->getVisualParamWeight( param->getID() ); - F32 new_weight = self->sliderToWeight( (F32)slider->getValue().asReal() ); + F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() ); if (current_weight != new_weight ) { self->mWearable->setVisualParamWeight( param->getID(), new_weight); @@ -102,12 +99,14 @@ void LLScrollingPanelParamBase::onSliderMoved(LLUICtrl* ctrl, void* userdata) } } -F32 LLScrollingPanelParamBase::weightToSlider(F32 weight) +F32 LLScrollingPanelParamBase::weightToPercent( F32 weight ) { - return (weight - mParam->getMinWeight()) * 100.f; + LLViewerVisualParam* param = mParam; + return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f; } -F32 LLScrollingPanelParamBase::sliderToWeight(F32 slider) +F32 LLScrollingPanelParamBase::percentToWeight( F32 percent ) { - return slider / 100.f + mParam->getMinWeight(); + LLViewerVisualParam* param = mParam; + return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight(); } diff --git a/indra/newview/llscrollingpanelparambase.h b/indra/newview/llscrollingpanelparambase.h index e7f88a21bd..9538826251 100644 --- a/indra/newview/llscrollingpanelparambase.h +++ b/indra/newview/llscrollingpanelparambase.h @@ -36,7 +36,6 @@ class LLViewerVisualParam; class LLWearable; class LLVisualParamHint; class LLViewerVisualParam; -class LLSliderCtrl; class LLJoint; class LLScrollingPanelParamBase : public LLScrollingPanel @@ -50,13 +49,11 @@ public: static void onSliderMoved(LLUICtrl* ctrl, void* userdata); - F32 weightToSlider(F32 weight); - F32 sliderToWeight(F32 slider); + F32 weightToPercent( F32 weight ); + F32 percentToWeight( F32 percent ); public: LLViewerVisualParam* mParam; - LLSliderCtrl* mSlider; - protected: BOOL mAllowModify; LLWearable *mWearable; -- cgit v1.2.3 From e361671018068000a8b63b3cdc2ad87468def9a3 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Fri, 19 Apr 2024 15:39:28 -0400 Subject: Port from OpenEXR to TinyEXR for reduced installer and library size (#1287) --- indra/cmake/CMakeLists.txt | 2 + indra/cmake/Copy3rdPartyLibs.cmake | 6 -- indra/cmake/OpenEXR.cmake | 18 ------ indra/cmake/TinyEXR.cmake | 7 +++ indra/newview/CMakeLists.txt | 9 +-- indra/newview/llreflectionmapmanager.cpp | 96 ++++++++++---------------------- indra/newview/viewer_manifest.py | 8 --- 7 files changed, 38 insertions(+), 108 deletions(-) delete mode 100644 indra/cmake/OpenEXR.cmake create mode 100644 indra/cmake/TinyEXR.cmake (limited to 'indra') diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 05c51c018d..da7e4be464 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -56,6 +56,8 @@ set(cmake_SOURCE_FILES PulseAudio.cmake Python.cmake TemplateCheck.cmake + TinyEXR.cmake + TinyGLTF.cmake Tut.cmake UI.cmake UnixInstall.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 873253b419..9f79c13a97 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -60,12 +60,6 @@ if(WINDOWS) nghttp2.dll libhunspell.dll uriparser.dll - Iex-3_2.dll - IlmThread-3_2.dll - Imath-3_1.dll - OpenEXR-3_2.dll - OpenEXRCore-3_2.dll - OpenEXRUtil-3_2.dll ) # ICU4C (same filenames for 32 and 64 bit builds) diff --git a/indra/cmake/OpenEXR.cmake b/indra/cmake/OpenEXR.cmake deleted file mode 100644 index ee21fac541..0000000000 --- a/indra/cmake/OpenEXR.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# -*- cmake -*- - -include(Prebuilt) - -include_guard() -add_library( ll::openexr INTERFACE IMPORTED ) - -if(USE_CONAN ) - target_link_libraries( ll::openexr INTERFACE CONAN_PKG::openexr ) - return() -endif() - -use_prebuilt_binary(openexr) - -target_link_libraries( ll::openexr INTERFACE Iex-3_2 IlmThread-3_2 Imath-3_1 OpenEXR-3_2 OpenEXRCore-3_2 OpenEXRUtil-3_2) - -target_include_directories( ll::openexr SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/OpenEXR ${LIBS_PREBUILT_DIR}/include/Imath) - diff --git a/indra/cmake/TinyEXR.cmake b/indra/cmake/TinyEXR.cmake new file mode 100644 index 0000000000..e6d142d19d --- /dev/null +++ b/indra/cmake/TinyEXR.cmake @@ -0,0 +1,7 @@ +# -*- cmake -*- +include(Prebuilt) + +use_prebuilt_binary(tinyexr) + +set(TINYEXR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/tinyexr) + diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 011dccb910..ed617ba70e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -34,11 +34,11 @@ include(LLWindow) include(NDOF) include(NVAPI) include(OPENAL) -include(OpenEXR) include(OpenGL) include(OpenSSL) include(PNG) include(TemplateCheck) +include(TinyEXR) include(ThreeJS) include(Tracy) include(UI) @@ -1750,12 +1750,6 @@ if (WINDOWS) media_plugin_cef media_plugin_libvlc media_plugin_example - ${SHARED_LIB_STAGING_DIR}/Iex-3_2.dll - ${SHARED_LIB_STAGING_DIR}/IlmThread-3_2.dll - ${SHARED_LIB_STAGING_DIR}/Imath-3_1.dll - ${SHARED_LIB_STAGING_DIR}/OpenEXR-3_2.dll - ${SHARED_LIB_STAGING_DIR}/OpenEXRCore-3_2.dll - ${SHARED_LIB_STAGING_DIR}/OpenEXRUtil-3_2.dll ) if (ADDRESS_SIZE EQUAL 64) @@ -1949,7 +1943,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ll::bugsplat ll::tracy ll::icu4c - ll::openexr ) if( TARGET ll::intel_memops ) diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 3e4992e4e7..5a8f44f5c2 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -41,14 +41,17 @@ #include "llviewermenufile.h" #include "llnotificationsutil.h" - -// load an OpenEXR image from a file -#define IMATH_HALF_NO_LOOKUP_TABLE 1 -#include -#include -#include -#include -#include +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // compiler complains unreachable code +#endif +#define TINYEXR_USE_MINIZ 0 +#include "zlib.h" +#define TINYEXR_IMPLEMENTATION +#include "tinyexr/tinyexr.h" +#if LL_WINDOWS +#pragma warning (pop) +#endif LLPointer gEXRImage; @@ -58,55 +61,14 @@ void load_exr(const std::string& filename) gPipeline.mReflectionMapManager.reset(); gPipeline.mReflectionMapManager.initReflectionMaps(); - try { - Imf::InputFile file(filename.c_str()); - Imath::Box2i dw = file.header().dataWindow(); - int width = dw.max.x - dw.min.x + 1; - int height = dw.max.y - dw.min.y + 1; - - Imf::Array2D rPixels; - Imf::Array2D gPixels; - Imf::Array2D bPixels; - - rPixels.resizeErase(height, width); - gPixels.resizeErase(height, width); - bPixels.resizeErase(height, width); - - Imf::FrameBuffer frameBuffer; - - frameBuffer.insert("R", // name - Imf::Slice(Imf::HALF, // type - (char*)(&rPixels[0][0] - // base - dw.min.x - - dw.min.y * width), - sizeof(rPixels[0][0]) * 1, // xStride - sizeof(rPixels[0][0]) * width, // yStride - 1, 1, // x/y sampling - 0.0)); // fillValue - - frameBuffer.insert("G", // name - Imf::Slice(Imf::HALF, // type - (char*)(&gPixels[0][0] - // base - dw.min.x - - dw.min.y * width), - sizeof(gPixels[0][0]) * 1, // xStride - sizeof(gPixels[0][0]) * width, // yStride - 1, 1, // x/y sampling - 0.0)); // fillValue - - frameBuffer.insert("B", // name - Imf::Slice(Imf::HALF, // type - (char*)(&bPixels[0][0] - // base - dw.min.x - - dw.min.y * width), - sizeof(bPixels[0][0]) * 1, // xStride - sizeof(bPixels[0][0]) * width, // yStride - 1, 1, // x/y sampling - FLT_MAX)); // fillValue - - file.setFrameBuffer(frameBuffer); - file.readPixels(dw.min.y, dw.max.y); + float* out; // width * height * RGBA + int width; + int height; + const char* err = NULL; // or nullptr in C++11 + int ret = LoadEXRWithLayer(&out, &width, &height, filename.c_str(), /* layername */ nullptr, &err); + if (ret == TINYEXR_SUCCESS) + { U32 texName = 0; LLImageGL::generateTextures(1, &texName); @@ -117,27 +79,25 @@ void load_exr(const std::string& filename) gGL.getTexUnit(0)->bind(gEXRImage); - std::vector data(width * height * 3); - for (int i = 0; i < width * height; ++i) - { - data[i * 3 + 0] = rPixels[i / width][i % width]; - data[i * 3 + 1] = gPixels[i / width][i % width]; - data[i * 3 + 2] = bPixels[i / width][i % width]; - } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGBA, GL_FLOAT, out); + free(out); // release memory of image data - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, data.data()); - glGenerateMipmap(GL_TEXTURE_2D); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } - catch (const std::exception& e) { + else + { LLSD notif_args; notif_args["WHAT"] = filename; - notif_args["REASON"] = e.what(); + notif_args["REASON"] = "Unknown"; + if (err) + { + notif_args["REASON"] = std::string(err); + FreeEXRErrorMessage(err); // release memory of error message. + } LLNotificationsUtil::add("CannotLoad", notif_args); - return; } } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index d51d86aa3c..4de4dc8fc5 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -587,14 +587,6 @@ class Windows_x86_64_Manifest(ViewerManifest): self.path("libcrypto-1_1-x64.dll") self.path("libssl-1_1-x64.dll") - # OpenEXR - self.path("Iex-3_2.dll") - self.path("IlmThread-3_2.dll") - self.path("Imath-3_1.dll") - self.path("OpenEXR-3_2.dll") - self.path("OpenEXRCore-3_2.dll") - self.path("OpenEXRUtil-3_2.dll") - # HTTP/2 self.path("nghttp2.dll") -- cgit v1.2.3 From f1b7e806eb30a343876036eff5caef7c03309aa6 Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Sun, 21 Apr 2024 20:40:13 -0400 Subject: Fix sampling normals from gbuffer and cleanup redundant gbuffer samples (#1294) * Fix sampling normals from gbuffer and cleanup redundant gbuffer samples * Allow negative normals in gbuffer to fix broken material rendering --- .../shaders/class1/deferred/blurLightF.glsl | 4 ++-- .../shaders/class1/deferred/deferredUtil.glsl | 21 +++++---------------- .../shaders/class1/deferred/pbropaqueF.glsl | 2 +- .../shaders/class1/deferred/pbrterrainF.glsl | 2 +- .../shaders/class2/deferred/sunLightF.glsl | 10 +++++----- .../shaders/class2/deferred/sunLightSSAOF.glsl | 12 ++++++------ .../app_settings/shaders/class3/deferred/hazeF.glsl | 5 ++--- .../shaders/class3/deferred/materialF.glsl | 2 +- .../shaders/class3/deferred/multiPointLightF.glsl | 7 +++---- .../shaders/class3/deferred/pointLightF.glsl | 7 +++---- .../class3/deferred/screenSpaceReflPostF.glsl | 9 +++------ .../shaders/class3/deferred/softenLightF.glsl | 13 ++++++------- .../shaders/class3/deferred/spotLightF.glsl | 10 +++++----- .../shaders/class3/deferred/waterHazeF.glsl | 1 - 14 files changed, 43 insertions(+), 62 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 08baf98686..8627ab1852 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -40,12 +40,12 @@ uniform float kern_scale; in vec2 vary_fragcoord; vec4 getPosition(vec2 pos_screen); -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); void main() { vec2 tc = vary_fragcoord.xy; - vec3 norm = getNorm(tc); + vec4 norm = getNorm(tc); vec3 pos = getPosition(tc).xyz; vec4 ccol = texture(lightMap, tc).rgba; diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index 065fcec45a..f6696e270c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -141,31 +141,20 @@ vec2 getScreenCoordinate(vec2 screenpos) return sc - vec2(1.0, 1.0); } -vec3 getNorm(vec2 screenpos) +vec4 getNorm(vec2 screenpos) { - return texture(normalMap, screenpos.xy).rgb; -} - -vec3 getNormalFromPacked(vec4 packedNormalEnvIntensityFlags) -{ - vec2 enc = packedNormalEnvIntensityFlags.xy; - vec2 fenc = enc*4-2; - float f = dot(fenc,fenc); - float g = sqrt(1-f/4); - vec3 n; - n.xy = fenc*g; - n.z = 1-f/2; - return normalize(n); // TODO: Is this normalize redundant? + return texture(normalMap, screenpos.xy); } // return packedNormalEnvIntensityFlags since GBUFFER_FLAG_HAS_PBR needs .w // See: C++: addDeferredAttachments(), GLSL: softenLightF vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity) { - n = texture(normalMap, screenpos.xy).rgb; + vec4 norm = texture(normalMap, screenpos.xy); + n = norm.xyz; envIntensity = texture(emissiveRect, screenpos.xy).r; - return vec4(n, envIntensity); + return norm; } // get linear depth value given a depth buffer sample d and znear and zfar values diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index 55fc94b7f5..1d5f810cf3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -109,7 +109,7 @@ void main() // See: C++: addDeferredAttachments(), GLSL: softenLightF frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(tnorm, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, environment intensity, flags + frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index 025ecb64df..de4745c1c4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -341,7 +341,7 @@ void main() #endif frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse frag_data[1] = max(vec4(orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. - frag_data[2] = max(vec4(tnorm, GBUFFER_FLAG_HAS_PBR), vec4(0)); // normal, flags + frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 1ea57516a4..1bd5f5a718 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -35,7 +35,7 @@ in vec2 vary_fragcoord; uniform vec3 sun_dir; uniform float shadow_bias; -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); vec4 getPosition(vec2 pos_screen); float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); @@ -45,13 +45,13 @@ void main() { vec2 pos_screen = vary_fragcoord.xy; vec4 pos = getPosition(pos_screen); - vec3 norm = getNorm(pos_screen); + vec4 norm = getNorm(pos_screen); vec4 col; - col.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen); + col.r = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen); col.g = 1.0f; - col.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen); - col.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen); + col.b = sampleSpotShadow(pos.xyz, norm.xyz, 0, pos_screen); + col.a = sampleSpotShadow(pos.xyz, norm.xyz, 1, pos_screen); frag_color = clamp(col, vec4(0), vec4(1)); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 0126e09d4c..e0333b6044 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -32,7 +32,7 @@ out vec4 frag_color; in vec2 vary_fragcoord; vec4 getPosition(vec2 pos_screen); -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); float sampleDirectionalShadow(vec3 shadow_pos, vec3 norm, vec2 pos_screen); float sampleSpotShadow(vec3 shadow_pos, vec3 norm, int index, vec2 pos_screen); @@ -42,13 +42,13 @@ void main() { vec2 pos_screen = vary_fragcoord.xy; vec4 pos = getPosition(pos_screen); - vec3 norm = getNorm(pos_screen); + vec4 norm = getNorm(pos_screen); vec4 col; - col.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen); - col.g = calcAmbientOcclusion(pos, norm, pos_screen); - col.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen); - col.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen); + col.r = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen); + col.g = calcAmbientOcclusion(pos, norm.xyz, pos_screen); + col.b = sampleSpotShadow(pos.xyz, norm.xyz, 0, pos_screen); + col.a = sampleSpotShadow(pos.xyz, norm.xyz, 1, pos_screen); frag_color = clamp(col, vec4(0), vec4(1)); } diff --git a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl index 0b154e82ad..4af57e3b80 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/hazeF.glsl @@ -33,7 +33,7 @@ uniform vec3 moon_dir; uniform int sun_up_factor; in vec2 vary_fragcoord; -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); vec4 getPositionWithDepth(vec2 pos_screen, float depth); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); @@ -53,8 +53,7 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = getDepth(tc.xy); vec4 pos = getPositionWithDepth(tc, depth); - vec4 norm = texture(normalMap, tc); - norm.xyz = getNorm(tc); + vec4 norm = getNorm(tc); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; vec3 color = vec3(0); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index d49db4b74d..2a20eb79d2 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -415,7 +415,7 @@ void main() frag_data[0] = max(vec4(diffcol.rgb, emissive), vec4(0)); // gbuffer is sRGB for legacy materials frag_data[1] = max(vec4(spec.rgb, glossiness), vec4(0)); // XYZ = Specular color. W = Specular exponent. - frag_data[2] = max(vec4(norm, flag), vec4(0)); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) + frag_data[2] = vec4(norm, flag); // XY = Normal. Z = Env. intensity. W = 1 skip atmos (mask off fog) frag_data[3] = vec4(env, 0, 0, 0); #endif diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl index ec8168465e..edfd6cbced 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/multiPointLightF.glsl @@ -48,7 +48,7 @@ in vec4 vary_fragcoord; void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); float calcLegacyDistanceAttenuation(float distance, float falloff); vec4 getPosition(vec2 pos_screen); -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); +vec4 getNorm(vec2 screenpos); vec2 getScreenXY(vec4 clip); vec2 getScreenCoord(vec4 clip); vec3 srgb_to_linear(vec3 c); @@ -74,9 +74,8 @@ void main() discard; } - float envIntensity; // not used for this shader - vec3 n; - vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG() + vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG() + vec3 n = norm.xyz; vec4 spec = texture(specularRect, tc); vec3 diffuse = texture(diffuseRect, tc).rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl index 31af1208bd..60be9f4407 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/pointLightF.glsl @@ -52,7 +52,7 @@ uniform vec4 viewport; void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); float calcLegacyDistanceAttenuation(float distance, float falloff); -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); +vec4 getNorm(vec2 screenpos); vec4 getPosition(vec2 pos_screen); vec2 getScreenXY(vec4 clip); vec2 getScreenCoord(vec4 clip); @@ -72,9 +72,8 @@ void main() vec2 tc = getScreenCoord(vary_fragcoord); vec3 pos = getPosition(tc).xyz; - float envIntensity; - vec3 n; - vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG() + vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG() + vec3 n = norm.xyz; vec3 diffuse = texture(diffuseRect, tc).rgb; vec4 spec = texture(specularRect, tc); diff --git a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl index dbf20fe2d8..deb276ef9d 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/screenSpaceReflPostF.glsl @@ -40,14 +40,13 @@ uniform sampler2D specularRect; uniform sampler2D diffuseRect; uniform sampler2D diffuseMap; -vec3 getNorm(vec2 screenpos); +vec4 getNorm(vec2 screenpos); float getDepth(vec2 pos_screen); float linearDepth(float d, float znear, float zfar); float linearDepth01(float d, float znear, float zfar); vec4 getPositionWithDepth(vec2 pos_screen, float depth); vec4 getPosition(vec2 pos_screen); -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); float random (vec2 uv); @@ -57,9 +56,7 @@ void main() { vec2 tc = vary_fragcoord.xy; float depth = linearDepth01(getDepth(tc), zNear, zFar); - float envIntensity; - vec3 n; - vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG() + vec4 norm = getNorm(tc); // need `norm.w` for GET_GBUFFER_FLAG() vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz; vec4 spec = texture(specularRect, tc); vec2 hitpixel; @@ -84,7 +81,7 @@ void main() vec4 collectedColor = vec4(0); - float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap, 0); + float w = tapScreenSpaceReflection(4, tc, pos, norm.xyz, collectedColor, diffuseMap, 0); collectedColor.rgb *= specCol.rgb; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index f71f8a028f..96c32734e4 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -61,7 +61,7 @@ in vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -vec3 getNorm(vec2 pos_screen); +vec4 getNorm(vec2 pos_screen); vec4 getPositionWithDepth(vec2 pos_screen, float depth); void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive); @@ -128,14 +128,13 @@ void main() vec2 tc = vary_fragcoord.xy; float depth = getDepth(tc.xy); vec4 pos = getPositionWithDepth(tc, depth); - vec4 norm = texture(normalMap, tc); + vec4 norm = getNorm(tc); vec3 colorEmissive = texture(emissiveRect, tc).rgb; float envIntensity = colorEmissive.r; - norm.xyz = getNorm(tc); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; vec4 baseColor = texture(diffuseRect, tc); - vec4 spec = texture(specularRect, vary_fragcoord.xy); // NOTE: PBR linear Emissive + vec4 spec = texture(specularRect, tc); // NOTE: PBR linear Emissive #if defined(HAS_SUN_SHADOW) || defined(HAS_SSAO) vec2 scol_ambocc = texture(lightMap, vary_fragcoord.xy).rg; @@ -170,7 +169,7 @@ void main() if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 orm = texture(specularRect, tc).rgb; + vec3 orm = spec.rgb; float perceptualRoughness = orm.g; float metallic = orm.b; float ao = orm.r; @@ -193,12 +192,12 @@ void main() else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_HDRI)) { // actual HDRI sky, just copy color value - color = texture(emissiveRect, tc).rgb; + color = colorEmissive.rgb; } else if (GET_GBUFFER_FLAG(GBUFFER_FLAG_SKIP_ATMOS)) { //should only be true of WL sky, port over base color value and scale for fake HDR - color = texture(emissiveRect, tc).rgb; + color = colorEmissive.rgb; color = srgb_to_linear(color); color *= sky_hdr_scale; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl index d31b37fb60..319fa86148 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl @@ -72,7 +72,7 @@ uniform mat4 inv_proj; void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist); float calcLegacyDistanceAttenuation(float distance, float falloff); bool clipProjectedLightVars(vec3 center, vec3 pos, out float dist, out float l_dist, out vec3 lv, out vec4 proj_tc ); -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity); +vec4 getNorm(vec2 screenpos); vec3 getProjectedLightAmbiance(float amb_da, float attenuation, float lit, float nl, float noise, vec2 projected_uv); vec3 getProjectedLightDiffuseColor(float light_distance, vec2 projected_uv ); vec2 getScreenCoord(vec4 clip); @@ -121,9 +121,8 @@ void main() shadow = clamp(shadow, 0.0, 1.0); } - float envIntensity; - vec3 n; - vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); + vec4 norm = getNorm(tc); + vec3 n = norm.xyz; float dist_atten = calcLegacyDistanceAttenuation(dist, falloff); if (dist_atten <= 0.0) @@ -145,7 +144,6 @@ void main() if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR)) { - vec3 colorEmissive = texture(emissiveRect, tc).rgb; vec3 orm = spec.rgb; float perceptualRoughness = orm.g; float metallic = orm.b; @@ -182,6 +180,8 @@ void main() } else { + float envIntensity = texture(emissiveRect, tc).r; + diffuse = srgb_to_linear(diffuse); spec.rgb = srgb_to_linear(spec.rgb); diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index f6b8299f91..f6bef1e498 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -56,7 +56,6 @@ void main() } vec4 pos = getPositionWithDepth(tc, depth); - vec4 norm = texture(normalMap, tc); vec4 fogged = getWaterFogView(pos.xyz); -- cgit v1.2.3 From cadc1a02cc7289dabd368dd1a1d237c042e9f82e Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 24 Apr 2024 09:51:15 -0500 Subject: 1285 GLTF Animation Prototype --- indra/llcommon/llstrider.h | 2 +- indra/llmath/llvolumeoctree.h | 2 +- indra/llrender/llvertexbuffer.cpp | 43 ++- indra/llrender/llvertexbuffer.h | 8 +- indra/newview/CMakeLists.txt | 5 + indra/newview/gltf/accessor.cpp | 66 +++++ indra/newview/gltf/accessor.h | 95 +++++++ indra/newview/gltf/animation.cpp | 287 ++++++++++++++++++++ indra/newview/gltf/animation.h | 181 +++++++++++++ indra/newview/gltf/asset.cpp | 375 ++++++++++++++++++++++++-- indra/newview/gltf/asset.h | 295 ++++++-------------- indra/newview/gltf/buffer_util.h | 402 ++++++++++++++++++++++++++++ indra/newview/gltf/primitive.cpp | 488 ++++++++++------------------------ indra/newview/gltf/primitive.h | 57 +--- indra/newview/gltfscenemanager.cpp | 23 +- indra/newview/gltfscenemanager.h | 5 +- indra/newview/llappviewer.cpp | 1 + indra/newview/lldrawpoolalpha.cpp | 9 +- indra/newview/lldrawpoolpbropaque.cpp | 1 + indra/newview/pipeline.cpp | 4 + 20 files changed, 1702 insertions(+), 647 deletions(-) create mode 100644 indra/newview/gltf/accessor.cpp create mode 100644 indra/newview/gltf/accessor.h create mode 100644 indra/newview/gltf/animation.cpp create mode 100644 indra/newview/gltf/animation.h create mode 100644 indra/newview/gltf/buffer_util.h (limited to 'indra') diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index ed9284d2c5..e7522484e6 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -37,8 +37,8 @@ template class LLStrider }; U32 mSkip; public: - LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); } + LLStrider(Object* first) { mObjectp = first; mSkip = sizeof(Object); } ~LLStrider() { } const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index d6f536b9ca..0bbb793896 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -62,7 +62,7 @@ public: LL_ALIGN_16(LLVector4a mPositionGroup); const LLVector4a* mV[3]; - U16 mIndex[3]; + U32 mIndex[3]; F32 mRadius; mutable S32 mBinIndex; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index dda3c1532d..1d81c3778b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -741,8 +741,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); gGL.syncMatrices(); - glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, - (GLvoid*) (indices_offset * sizeof(U16))); + glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType, + (GLvoid*) (indices_offset * (size_t) mIndicesStride)); } void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const @@ -1139,7 +1139,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) } // flush the given byte range -// target -- "targret" parameter for glBufferSubData +// target -- "target" parameter for glBufferSubData // start -- first byte to copy // end -- last byte to copy (NOT last byte + 1) // data -- mMappedData or mMappedIndexData @@ -1301,6 +1301,8 @@ bool LLVertexBuffer::getVertexStrider(LLStrider& strider, U32 index, } bool LLVertexBuffer::getIndexStrider(LLStrider& strider, U32 index, S32 count) { + llassert(mIndicesStride == 2); // cannot access 32-bit indices with U16 strider + llassert(mIndicesType == GL_UNSIGNED_SHORT); return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getTexCoord0Strider(LLStrider& strider, U32 index, S32 count) @@ -1507,4 +1509,39 @@ void LLVertexBuffer::setColorData(const LLColor4U* data) flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data); } +void LLVertexBuffer::setNormalData(const LLVector4a* data) +{ + llassert(sGLRenderBuffer == mGLBuffer); + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data); +} + +void LLVertexBuffer::setTangentData(const LLVector4a* data) +{ + llassert(sGLRenderBuffer == mGLBuffer); + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data); +} + +void LLVertexBuffer::setWeight4Data(const LLVector4a* data) +{ + llassert(sGLRenderBuffer == mGLBuffer); + flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data); +} + +void LLVertexBuffer::setIndexData(const U16* data) +{ + llassert(sGLRenderIndices == mGLIndices); + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data); +} + +void LLVertexBuffer::setIndexData(const U32* data) +{ + llassert(sGLRenderIndices == mGLIndices); + if (mIndicesType != GL_UNSIGNED_INT) + { // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices + mIndicesType = GL_UNSIGNED_INT; + mIndicesStride = 4; + mNumIndices /= 2; + } + flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data); +} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index cc59e322ed..669d89aabf 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -190,9 +190,13 @@ public: bool getClothWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); void setPositionData(const LLVector4a* data); + void setNormalData(const LLVector4a* data); + void setTangentData(const LLVector4a* data); + void setWeight4Data(const LLVector4a* data); void setTexCoordData(const LLVector2* data); void setColorData(const LLColor4U* data); - + void setIndexData(const U16* data); + void setIndexData(const U32* data); U32 getNumVerts() const { return mNumVerts; } U32 getNumIndices() const { return mNumIndices; } @@ -224,6 +228,8 @@ protected: U32 mGLIndices = 0; // GL IBO handle U32 mNumVerts = 0; // Number of vertices allocated U32 mNumIndices = 0; // Number of indices allocated + U32 mIndicesType = GL_UNSIGNED_SHORT; // type of indices in index buffer + U32 mIndicesStride = 2; // size of each index in bytes U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ed617ba70e..b15ee235bd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -76,7 +76,9 @@ endif (NOT HAVOK_TPV) set(viewer_SOURCE_FILES gltfscenemanager.cpp gltf/asset.cpp + gltf/accessor.cpp gltf/primitive.cpp + gltf/animation.cpp groupchatlistener.cpp llaccountingcostmanager.cpp llaisapi.cpp @@ -733,7 +735,10 @@ set(viewer_HEADER_FILES gltfscenemanager.h groupchatlistener.h gltf/asset.h + gltf/accessor.h + gltf/buffer_util.h gltf/primitive.h + gltf/animation.h llaccountingcost.h llaccountingcostmanager.h llaisapi.h diff --git a/indra/newview/gltf/accessor.cpp b/indra/newview/gltf/accessor.cpp new file mode 100644 index 0000000000..55d36b7a32 --- /dev/null +++ b/indra/newview/gltf/accessor.cpp @@ -0,0 +1,66 @@ +/** + * @file accessor.cpp + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "../llviewerprecompiledheaders.h" + +#include "asset.h" + +using namespace LL::GLTF; + +const Buffer& Buffer::operator=(const tinygltf::Buffer& src) +{ + mData = src.data; + mName = src.name; + mUri = src.uri; + return *this; +} + +const BufferView& BufferView::operator=(const tinygltf::BufferView& src) +{ + mBuffer = src.buffer; + mByteLength = src.byteLength; + mByteOffset = src.byteOffset; + mByteStride = src.byteStride; + mTarget = src.target; + mName = src.name; + return *this; +} + +const Accessor& Accessor::operator=(const tinygltf::Accessor& src) +{ + mBufferView = src.bufferView; + mByteOffset = src.byteOffset; + mComponentType = src.componentType; + mCount = src.count; + mType = src.type; + mNormalized = src.normalized; + mName = src.name; + mMax = src.maxValues; + mMin = src.minValues; + + return *this; +} + diff --git a/indra/newview/gltf/accessor.h b/indra/newview/gltf/accessor.h new file mode 100644 index 0000000000..9b8265d8da --- /dev/null +++ b/indra/newview/gltf/accessor.h @@ -0,0 +1,95 @@ +#pragma once + +/** + * @file asset.h + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "../lltinygltfhelper.h" +#include "llstrider.h" + +// LL GLTF Implementation +namespace LL +{ + namespace GLTF + { + class Asset; + + constexpr S32 INVALID_INDEX = -1; + + class Buffer + { + public: + std::vector mData; + std::string mName; + std::string mUri; + + const Buffer& operator=(const tinygltf::Buffer& src); + }; + + class BufferView + { + public: + S32 mBuffer = INVALID_INDEX; + S32 mByteLength; + S32 mByteOffset; + S32 mByteStride; + S32 mTarget; + S32 mComponentType; + + std::string mName; + + const BufferView& operator=(const tinygltf::BufferView& src); + + }; + + class Accessor + { + public: + S32 mBufferView = INVALID_INDEX; + S32 mByteOffset; + S32 mComponentType; + S32 mCount; + std::vector mMax; + std::vector mMin; + + enum class Type : S32 + { + SCALAR = TINYGLTF_TYPE_SCALAR, + VEC2 = TINYGLTF_TYPE_VEC2, + VEC3 = TINYGLTF_TYPE_VEC3, + VEC4 = TINYGLTF_TYPE_VEC4, + MAT2 = TINYGLTF_TYPE_MAT2, + MAT3 = TINYGLTF_TYPE_MAT3, + MAT4 = TINYGLTF_TYPE_MAT4 + }; + + S32 mType; + bool mNormalized; + std::string mName; + + const Accessor& operator=(const tinygltf::Accessor& src); + }; + } +} diff --git a/indra/newview/gltf/animation.cpp b/indra/newview/gltf/animation.cpp new file mode 100644 index 0000000000..da6d02b356 --- /dev/null +++ b/indra/newview/gltf/animation.cpp @@ -0,0 +1,287 @@ +/** + * @file animation.cpp + * @brief LL GLTF Animation Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "../llviewerprecompiledheaders.h" + +#include "asset.h" +#include "buffer_util.h" + +using namespace LL::GLTF; + +void Animation::allocateGLResources(Asset& asset) +{ + if (!mSamplers.empty()) + { + mMinTime = FLT_MAX; + mMaxTime = -FLT_MAX; + for (auto& sampler : mSamplers) + { + sampler.allocateGLResources(asset); + mMinTime = llmin(sampler.mMinTime, mMinTime); + mMaxTime = llmax(sampler.mMaxTime, mMaxTime); + } + } + else + { + mMinTime = mMaxTime = 0.f; + } + + for (auto& channel : mRotationChannels) + { + channel.allocateGLResources(asset, mSamplers[channel.mSampler]); + } + + for (auto& channel : mTranslationChannels) + { + channel.allocateGLResources(asset, mSamplers[channel.mSampler]); + } +} + +void Animation::update(Asset& asset, F32 dt) +{ + mTime += dt; + + apply(asset, mTime); +} + +void Animation::apply(Asset& asset, float time) +{ + // convert time to animation loop time + time = fmod(time, mMaxTime - mMinTime) + mMinTime; + + // apply each channel + for (auto& channel : mRotationChannels) + { + channel.apply(asset, mSamplers[channel.mSampler], time); + } + + for (auto& channel : mTranslationChannels) + { + channel.apply(asset, mSamplers[channel.mSampler], time); + } +}; + + +void Animation::Sampler::allocateGLResources(Asset& asset) +{ + Accessor& accessor = asset.mAccessors[mInput]; + mMinTime = accessor.mMin[0]; + mMaxTime = accessor.mMax[0]; + + mFrameTimes.resize(accessor.mCount); + + LLStrider frame_times = mFrameTimes.data(); + copy(asset, accessor, frame_times); +} + +void Animation::Sampler::getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F32& t) +{ + if (time < mMinTime) + { + frameIndex = 0; + t = 0.0f; + return; + } + + if (mFrameTimes.size() > 1) + { + if (time > mMaxTime) + { + frameIndex = mFrameTimes.size() - 2; + t = 1.0f; + return; + } + + frameIndex = mFrameTimes.size() - 2; + t = 1.f; + + for (U32 i = 0; i < mFrameTimes.size() - 1; i++) + { + if (time >= mFrameTimes[i] && time < mFrameTimes[i + 1]) + { + frameIndex = i; + t = (time - mFrameTimes[i]) / (mFrameTimes[i + 1] - mFrameTimes[i]); + return; + } + } + } + else + { + frameIndex = 0; + t = 0.0f; + } +} + +void Animation::RotationChannel::allocateGLResources(Asset& asset, Animation::Sampler& sampler) +{ + Accessor& accessor = asset.mAccessors[sampler.mOutput]; + + copy(asset, accessor, mRotations); +} + +void Animation::RotationChannel::apply(Asset& asset, Sampler& sampler, F32 time) +{ + U32 frameIndex; + F32 t; + + Node& node = asset.mNodes[mTarget.mNode]; + + sampler.getFrameInfo(asset, time, frameIndex, t); + + if (sampler.mFrameTimes.size() == 1) + { + node.setRotation(mRotations[0]); + } + else + { + // interpolate + LLQuaternion q0(mRotations[frameIndex].get_value()); + LLQuaternion q1(mRotations[frameIndex + 1].get_value()); + + LLQuaternion qf = slerp(t, q0, q1); + + qf.normalize(); + node.setRotation(glh::quaternionf(qf.mQ)); + } +} + +void Animation::TranslationChannel::allocateGLResources(Asset& asset, Animation::Sampler& sampler) +{ + Accessor& accessor = asset.mAccessors[sampler.mOutput]; + + copy(asset, accessor, mTranslations); +} + +void Animation::TranslationChannel::apply(Asset& asset, Sampler& sampler, F32 time) +{ + U32 frameIndex; + F32 t; + + Node& node = asset.mNodes[mTarget.mNode]; + + sampler.getFrameInfo(asset, time, frameIndex, t); + + if (sampler.mFrameTimes.size() == 1) + { + node.setTranslation(mTranslations[0]); + } + else + { + // interpolate + const glh::vec3f& v0 = mTranslations[frameIndex]; + const glh::vec3f& v1 = mTranslations[frameIndex + 1]; + + glh::vec3f vf = v0 + t * (v1 - v0); + + node.setTranslation(vf); + } +} + +void Animation::ScaleChannel::allocateGLResources(Asset& asset, Animation::Sampler& sampler) +{ + Accessor& accessor = asset.mAccessors[sampler.mOutput]; + + copy(asset, accessor, mScales); +} + +void Animation::ScaleChannel::apply(Asset& asset, Sampler& sampler, F32 time) +{ + U32 frameIndex; + F32 t; + + Node& node = asset.mNodes[mTarget.mNode]; + + sampler.getFrameInfo(asset, time, frameIndex, t); + + if (sampler.mFrameTimes.size() == 1) + { + node.setScale(mScales[0]); + } + else + { + // interpolate + const glh::vec3f& v0 = mScales[frameIndex]; + const glh::vec3f& v1 = mScales[frameIndex + 1]; + + glh::vec3f vf = v0 + t * (v1 - v0); + + node.setScale(vf); + } +} + +const Animation& Animation::operator=(const tinygltf::Animation& src) +{ + mName = src.name; + + mSamplers.resize(src.samplers.size()); + for (U32 i = 0; i < src.samplers.size(); ++i) + { + mSamplers[i] = src.samplers[i]; + } + + for (U32 i = 0; i < src.channels.size(); ++i) + { + if (src.channels[i].target_path == "rotation") + { + mRotationChannels.push_back(RotationChannel()); + mRotationChannels.back() = src.channels[i]; + } + + if (src.channels[i].target_path == "translation") + { + mTranslationChannels.push_back(TranslationChannel()); + mTranslationChannels.back() = src.channels[i]; + } + + if (src.channels[i].target_path == "scale") + { + mScaleChannels.push_back(ScaleChannel()); + mScaleChannels.back() = src.channels[i]; + } + } + + return *this; +} + +void Skin::allocateGLResources(Asset& asset) +{ + if (mInverseBindMatrices != INVALID_INDEX) + { + Accessor& accessor = asset.mAccessors[mInverseBindMatrices]; + copy(asset, accessor, mInverseBindMatricesData); + } +} + +const Skin& Skin::operator=(const tinygltf::Skin& src) +{ + mName = src.name; + mSkeleton = src.skeleton; + mInverseBindMatrices = src.inverseBindMatrices; + mJoints = src.joints; + + return *this; +} + diff --git a/indra/newview/gltf/animation.h b/indra/newview/gltf/animation.h new file mode 100644 index 0000000000..869eae963a --- /dev/null +++ b/indra/newview/gltf/animation.h @@ -0,0 +1,181 @@ +#pragma once + +/** + * @file animation.h + * @brief LL GLTF Animation Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "accessor.h" + +// LL GLTF Implementation +namespace LL +{ + namespace GLTF + { + class Asset; + + class Animation + { + public: + class Sampler + { + public: + std::vector mFrameTimes; + + F32 mMinTime = -FLT_MAX; + F32 mMaxTime = FLT_MAX; + + S32 mInput = INVALID_INDEX; + S32 mOutput = INVALID_INDEX; + std::string mInterpolation; + + void allocateGLResources(Asset& asset); + + const Sampler& operator=(const tinygltf::AnimationSampler& src) + { + mInput = src.input; + mOutput = src.output; + mInterpolation = src.interpolation; + + return *this; + } + + // get the frame index and time for the specified time + // asset -- the asset to reference for Accessors + // time -- the animation time to get the frame info for + // frameIndex -- index of the closest frame that precedes the specified time + // t - interpolant value between the frameIndex and the next frame + void getFrameInfo(Asset& asset, F32 time, U32& frameIndex, F32& t); + }; + + class Channel + { + public: + class Target + { + public: + S32 mNode = INVALID_INDEX; + std::string mPath; + }; + + S32 mSampler = INVALID_INDEX; + Target mTarget; + std::string mTargetPath; + std::string mName; + + const Channel& operator=(const tinygltf::AnimationChannel& src) + { + mSampler = src.sampler; + + mTarget.mNode = src.target_node; + mTarget.mPath = src.target_path; + + return *this; + } + + }; + + class RotationChannel : public Channel + { + public: + std::vector mRotations; + + const RotationChannel& operator=(const tinygltf::AnimationChannel& src) + { + Channel::operator=(src); + return *this; + } + + // prepare data needed for rendering + // asset -- asset to reference for Accessors + // sampler -- Sampler associated with this channel + void allocateGLResources(Asset& asset, Sampler& sampler); + + void apply(Asset& asset, Sampler& sampler, F32 time); + }; + + class TranslationChannel : public Channel + { + public: + std::vector mTranslations; + + const TranslationChannel& operator=(const tinygltf::AnimationChannel& src) + { + Channel::operator=(src); + return *this; + } + + // prepare data needed for rendering + // asset -- asset to reference for Accessors + // sampler -- Sampler associated with this channel + void allocateGLResources(Asset& asset, Sampler& sampler); + + void apply(Asset& asset, Sampler& sampler, F32 time); + }; + + class ScaleChannel : public Channel + { + public: + std::vector mScales; + + const ScaleChannel& operator=(const tinygltf::AnimationChannel& src) + { + Channel::operator=(src); + return *this; + } + + // prepare data needed for rendering + // asset -- asset to reference for Accessors + // sampler -- Sampler associated with this channel + void allocateGLResources(Asset& asset, Sampler& sampler); + + void apply(Asset& asset, Sampler& sampler, F32 time); + }; + + std::string mName; + std::vector mSamplers; + + // min/max time values for all samplers combined + F32 mMinTime = 0.f; + F32 mMaxTime = 0.f; + + // current time of the animation + F32 mTime = 0.f; + + std::vector mRotationChannels; + std::vector mTranslationChannels; + std::vector mScaleChannels; + + const Animation& operator=(const tinygltf::Animation& src); + + void allocateGLResources(Asset& asset); + + void update(Asset& asset, float dt); + + // apply this animation at the specified time + void apply(Asset& asset, F32 time); + }; + + } +} diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index 7181c5fa53..313e82bf01 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -28,6 +28,8 @@ #include "asset.h" #include "llvolumeoctree.h" +#include "../llviewershadermgr.h" +#include "../llviewercontrol.h" using namespace LL::GLTF; @@ -66,6 +68,7 @@ LLMatrix4a inverse(const LLMatrix4a& mat); void Node::updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix) { + makeMatrixValid(); matMul(mMatrix, parentMatrix, mAssetMatrix); mAssetMatrixInv = inverse(mAssetMatrix); @@ -99,7 +102,7 @@ void Asset::updateRenderTransforms(const LLMatrix4a& modelview) // use mAssetMatrix to update render transforms from node list for (auto& node : mNodes) { - if (node.mMesh != INVALID_INDEX) + //if (node.mMesh != INVALID_INDEX) { matMul(node.mAssetMatrix, modelview, node.mRenderMatrix); } @@ -211,6 +214,67 @@ S32 Asset::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, return node_hit; } + +void Node::makeMatrixValid() +{ + if (!mMatrixValid && mTRSValid) + { + glh::matrix4f rot; + mRotation.get_value(rot); + + glh::matrix4f trans; + trans.set_translate(mTranslation); + + glh::matrix4f sc; + sc.set_scale(mScale); + + glh::matrix4f t; + //t = sc * rot * trans; + //t = trans * rot * sc; // best so far, still wrong on negative scale + //t = sc * trans * rot; + t = trans * sc * rot; + + mMatrix.loadu(t.m); + mMatrixValid = true; + } +} + +void Node::makeTRSValid() +{ + if (!mTRSValid && mMatrixValid) + { + glh::matrix4f t(mMatrix.getF32ptr()); + + glh::vec4f p = t.get_column(3); + mTranslation.set_value(p.v[0], p.v[1], p.v[2]); + + mScale.set_value(t.get_column(0).length(), t.get_column(1).length(), t.get_column(2).length()); + mRotation.set_value(t); + mTRSValid = true; + } +} + +void Node::setRotation(const glh::quaternionf& q) +{ + makeTRSValid(); + mRotation = q; + mMatrixValid = false; +} + +void Node::setTranslation(const glh::vec3f& t) +{ + makeTRSValid(); + mTranslation = t; + mMatrixValid = false; +} + +void Node::setScale(const glh::vec3f& s) +{ + makeTRSValid(); + mScale = s; + mMatrixValid = false; +} + const Node& Node::operator=(const tinygltf::Node& src) { F32* dstMatrix = mMatrix.getF32ptr(); @@ -222,48 +286,33 @@ const Node& Node::operator=(const tinygltf::Node& src) { dstMatrix[i] = (F32)src.matrix[i]; } + + mMatrixValid = true; } else if (!src.rotation.empty() || !src.translation.empty() || !src.scale.empty()) { // node has rotation/translation/scale, convert to matrix - glh::quaternionf rotation; if (src.rotation.size() == 4) { - rotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); + mRotation = glh::quaternionf((F32)src.rotation[0], (F32)src.rotation[1], (F32)src.rotation[2], (F32)src.rotation[3]); } - glh::vec3f translation; if (src.translation.size() == 3) { - translation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); + mTranslation = glh::vec3f((F32)src.translation[0], (F32)src.translation[1], (F32)src.translation[2]); } glh::vec3f scale; if (src.scale.size() == 3) { - scale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); + mScale = glh::vec3f((F32)src.scale[0], (F32)src.scale[1], (F32)src.scale[2]); } else { - scale.set_value(1.f, 1.f, 1.f); + mScale.set_value(1.f, 1.f, 1.f); } - glh::matrix4f rot; - rotation.get_value(rot); - - glh::matrix4f trans; - trans.set_translate(translation); - - glh::matrix4f sc; - sc.set_scale(scale); - - glh::matrix4f t; - //t = sc * rot * trans; - //t = trans * rot * sc; // best so far, still wrong on negative scale - //t = sc * trans * rot; - t = trans * sc * rot; - - mMatrix.loadu(t.m); + mTRSValid = true; } else { @@ -273,21 +322,50 @@ const Node& Node::operator=(const tinygltf::Node& src) mChildren = src.children; mMesh = src.mesh; + mSkin = src.skin; mName = src.name; return *this; } -void Asset::render(bool opaque) +void Asset::render(bool opaque, bool rigged) { + if (rigged) + { + gGL.loadIdentity(); + } + for (auto& node : mNodes) { + if (node.mSkin != INVALID_INDEX) + { + if (rigged) + { + Skin& skin = mSkins[node.mSkin]; + skin.uploadMatrixPalette(*this, node); + } + else + { + //skip static nodes if we're rendering rigged + continue; + } + } + else if (rigged) + { + // skip rigged nodes if we're not rendering rigged + continue; + } + + if (node.mMesh != INVALID_INDEX) { Mesh& mesh = mMeshes[node.mMesh]; for (auto& primitive : mesh.mPrimitives) { - gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + if (!rigged) + { + gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); + } bool cull = true; if (primitive.mMaterial != INVALID_INDEX) { @@ -336,4 +414,251 @@ void Asset::renderTransparent() render(false); } +void Asset::update() +{ + F32 dt = gFrameTimeSeconds - mLastUpdateTime; + + if (dt > 0.f) + { + mLastUpdateTime = gFrameTimeSeconds; + if (mAnimations.size() > 0) + { + static LLCachedControl anim_idx(gSavedSettings, "GLTFAnimationIndex", 0); + static LLCachedControl anim_speed(gSavedSettings, "GLTFAnimationSpeed", 1.f); + + U32 idx = llclamp(anim_idx(), 0U, mAnimations.size() - 1); + mAnimations[idx].update(*this, dt*anim_speed); + } + + updateTransforms(); + } +} + +void Asset::allocateGLResources(const std::string& filename, const tinygltf::Model& model) +{ + // do images first as materials may depend on images + for (auto& image : mImages) + { + image.allocateGLResources(); + } + + // do materials before meshes as meshes may depend on materials + for (U32 i = 0; i < mMaterials.size(); ++i) + { + mMaterials[i].allocateGLResources(*this); + LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true); + } + + for (auto& mesh : mMeshes) + { + mesh.allocateGLResources(*this); + } + + for (auto& animation : mAnimations) + { + animation.allocateGLResources(*this); + } + + for (auto& skin : mSkins) + { + skin.allocateGLResources(*this); + } +} + +const Asset& Asset::operator=(const tinygltf::Model& src) +{ + mScenes.resize(src.scenes.size()); + for (U32 i = 0; i < src.scenes.size(); ++i) + { + mScenes[i] = src.scenes[i]; + } + + mNodes.resize(src.nodes.size()); + for (U32 i = 0; i < src.nodes.size(); ++i) + { + mNodes[i] = src.nodes[i]; + } + + mMeshes.resize(src.meshes.size()); + for (U32 i = 0; i < src.meshes.size(); ++i) + { + mMeshes[i] = src.meshes[i]; + } + + mMaterials.resize(src.materials.size()); + for (U32 i = 0; i < src.materials.size(); ++i) + { + mMaterials[i] = src.materials[i]; + } + + mBuffers.resize(src.buffers.size()); + for (U32 i = 0; i < src.buffers.size(); ++i) + { + mBuffers[i] = src.buffers[i]; + } + + mBufferViews.resize(src.bufferViews.size()); + for (U32 i = 0; i < src.bufferViews.size(); ++i) + { + mBufferViews[i] = src.bufferViews[i]; + } + + mTextures.resize(src.textures.size()); + for (U32 i = 0; i < src.textures.size(); ++i) + { + mTextures[i] = src.textures[i]; + } + + mSamplers.resize(src.samplers.size()); + for (U32 i = 0; i < src.samplers.size(); ++i) + { + mSamplers[i] = src.samplers[i]; + } + + mImages.resize(src.images.size()); + for (U32 i = 0; i < src.images.size(); ++i) + { + mImages[i] = src.images[i]; + } + + mAccessors.resize(src.accessors.size()); + for (U32 i = 0; i < src.accessors.size(); ++i) + { + mAccessors[i] = src.accessors[i]; + } + + mAnimations.resize(src.animations.size()); + for (U32 i = 0; i < src.animations.size(); ++i) + { + mAnimations[i] = src.animations[i]; + } + + mSkins.resize(src.skins.size()); + for (U32 i = 0; i < src.skins.size(); ++i) + { + mSkins[i] = src.skins[i]; + } + + return *this; +} + +const Material& Material::operator=(const tinygltf::Material& src) +{ + mName = src.name; + return *this; +} + +void Material::allocateGLResources(Asset& asset) +{ + // allocate material + mMaterial = new LLFetchedGLTFMaterial(); +} + +const Mesh& Mesh::operator=(const tinygltf::Mesh& src) +{ + mPrimitives.resize(src.primitives.size()); + for (U32 i = 0; i < src.primitives.size(); ++i) + { + mPrimitives[i] = src.primitives[i]; + } + + mWeights = src.weights; + mName = src.name; + + return *this; +} + +void Mesh::allocateGLResources(Asset& asset) +{ + for (auto& primitive : mPrimitives) + { + primitive.allocateGLResources(asset); + } +} + +const Scene& Scene::operator=(const tinygltf::Scene& src) +{ + mNodes = src.nodes; + mName = src.name; + + return *this; +} + +const Texture& Texture::operator=(const tinygltf::Texture& src) +{ + mSampler = src.sampler; + mSource = src.source; + mName = src.name; + + return *this; +} + +const Sampler& Sampler::operator=(const tinygltf::Sampler& src) +{ + mMagFilter = src.magFilter; + mMinFilter = src.minFilter; + mWrapS = src.wrapS; + mWrapT = src.wrapT; + mName = src.name; + + return *this; +} + +void Skin::uploadMatrixPalette(Asset& asset, Node& node) +{ + // prepare matrix palette + + // modelview will be applied by the shader, so assume matrix palette is in asset space + std::vector t_mp; + + t_mp.resize(mJoints.size()); + + for (U32 i = 0; i < mJoints.size(); ++i) + { + Node& joint = asset.mNodes[mJoints[i]]; + + //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + //t_mp[i] = t_mp[i] * mInverseBindMatricesData[i]; + + //t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + //t_mp[i] = mInverseBindMatricesData[i] * t_mp[i]; + + t_mp[i].set_value(joint.mRenderMatrix.getF32ptr()); + t_mp[i] = t_mp[i] * mInverseBindMatricesData[i]; + + } + + std::vector glmp; + + glmp.resize(mJoints.size() * 12); + + F32* mp = glmp.data(); + + for (U32 i = 0; i < mJoints.size(); ++i) + { + F32* m = (F32*)t_mp[i].m; + + U32 idx = i * 12; + + mp[idx + 0] = m[0]; + mp[idx + 1] = m[1]; + mp[idx + 2] = m[2]; + mp[idx + 3] = m[12]; + + mp[idx + 4] = m[4]; + mp[idx + 5] = m[5]; + mp[idx + 6] = m[6]; + mp[idx + 7] = m[13]; + + mp[idx + 8] = m[8]; + mp[idx + 9] = m[9]; + mp[idx + 10] = m[10]; + mp[idx + 11] = m[14]; + } + + LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, + mJoints.size(), + FALSE, + (GLfloat*)glmp.data()); +} diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index acf9ba77df..6e576a1ffe 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -29,86 +29,19 @@ #include "llvertexbuffer.h" #include "llvolumeoctree.h" #include "../lltinygltfhelper.h" +#include "accessor.h" #include "primitive.h" +#include "animation.h" + +extern F32SecondsImplicit gFrameTimeSeconds; // LL GLTF Implementation namespace LL { namespace GLTF { - constexpr S32 INVALID_INDEX = -1; - class Asset; - class Buffer - { - public: - std::vector mData; - std::string mName; - std::string mUri; - - const Buffer& operator=(const tinygltf::Buffer& src) - { - mData = src.data; - mName = src.name; - mUri = src.uri; - return *this; - } - }; - - class BufferView - { - public: - S32 mBuffer = INVALID_INDEX; - S32 mByteLength; - S32 mByteOffset; - S32 mByteStride; - S32 mTarget; - S32 mComponentType; - - std::string mName; - - const BufferView& operator=(const tinygltf::BufferView& src) - { - mBuffer = src.buffer; - mByteLength = src.byteLength; - mByteOffset = src.byteOffset; - mByteStride = src.byteStride; - mTarget = src.target; - mName = src.name; - return *this; - } - }; - - class Accessor - { - public: - S32 mBufferView = INVALID_INDEX; - S32 mByteOffset; - S32 mComponentType; - S32 mCount; - std::vector mMax; - std::vector mMin; - S32 mType; - bool mNormalized; - std::string mName; - - const Accessor& operator=(const tinygltf::Accessor& src) - { - mBufferView = src.bufferView; - mByteOffset = src.byteOffset; - mComponentType = src.componentType; - mCount = src.count; - mType = src.type; - mNormalized = src.normalized; - mName = src.name; - mMax = src.maxValues; - mMin = src.maxValues; - - return *this; - } - }; - class Material { public: @@ -118,17 +51,9 @@ namespace LL LLPointer mMaterial; std::string mName; - const Material& operator=(const tinygltf::Material& src) - { - mName = src.name; - return *this; - } - - void allocateGLResources(Asset& asset) - { - // allocate material - mMaterial = new LLFetchedGLTFMaterial(); - } + const Material& operator=(const tinygltf::Material& src); + + void allocateGLResources(Asset& asset); }; class Mesh @@ -138,28 +63,9 @@ namespace LL std::vector mWeights; std::string mName; - const Mesh& operator=(const tinygltf::Mesh& src) - { - mPrimitives.resize(src.primitives.size()); - for (U32 i = 0; i < src.primitives.size(); ++i) - { - mPrimitives[i] = src.primitives[i]; - } - - mWeights = src.weights; - mName = src.name; - - return *this; - } - - void allocateGLResources(Asset& asset) - { - for (auto& primitive : mPrimitives) - { - primitive.allocateGLResources(asset); - } - } - + const Mesh& operator=(const tinygltf::Mesh& src); + + void allocateGLResources(Asset& asset); }; class Node @@ -170,10 +76,24 @@ namespace LL LLMatrix4a mAssetMatrix; //transform from local to asset space LLMatrix4a mAssetMatrixInv; //transform from asset to local space + glh::vec3f mTranslation; + glh::quaternionf mRotation; + glh::vec3f mScale; + + // if true, mMatrix is valid and up to date + bool mMatrixValid = false; + + // if true, translation/rotation/scale are valid and up to date + bool mTRSValid = false; + + bool mNeedsApplyMatrix = false; + std::vector mChildren; S32 mParent = INVALID_INDEX; S32 mMesh = INVALID_INDEX; + S32 mSkin = INVALID_INDEX; + std::string mName; const Node& operator=(const tinygltf::Node& src); @@ -184,26 +104,51 @@ namespace LL // update mAssetMatrix and mAssetMatrixInv void updateTransforms(Asset& asset, const LLMatrix4a& parentMatrix); - + + // ensure mMatrix is valid -- if mMatrixValid is false and mTRSValid is true, will update mMatrix to match Translation/Rotation/Scale + void makeMatrixValid(); + + // ensure Translation/Rotation/Scale are valid -- if mTRSValid is false and mMatrixValid is true, will update Translation/Rotation/Scale to match mMatrix + void makeTRSValid(); + + // Set rotation of this node + // SIDE EFFECT: invalidates mMatrix + void setRotation(const glh::quaternionf& rotation); + + // Set translation of this node + // SIDE EFFECT: invalidates mMatrix + void setTranslation(const glh::vec3f& translation); + + // Set scale of this node + // SIDE EFFECT: invalidates mMatrix + void setScale(const glh::vec3f& scale); }; - class Scene + class Skin { public: - std::vector mNodes; + S32 mInverseBindMatrices = INVALID_INDEX; + S32 mSkeleton = INVALID_INDEX; + std::vector mJoints; std::string mName; + std::vector mInverseBindMatricesData; - const Scene& operator=(const tinygltf::Scene& src) - { - mNodes = src.nodes; - mName = src.name; + void allocateGLResources(Asset& asset); + void uploadMatrixPalette(Asset& asset, Node& node); - return *this; - } + const Skin& operator=(const tinygltf::Skin& src); + }; + + class Scene + { + public: + std::vector mNodes; + std::string mName; + const Scene& operator=(const tinygltf::Scene& src); + void updateTransforms(Asset& asset); void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); - }; class Texture @@ -213,14 +158,7 @@ namespace LL S32 mSource = INVALID_INDEX; std::string mName; - const Texture& operator=(const tinygltf::Texture& src) - { - mSampler = src.sampler; - mSource = src.source; - mName = src.name; - - return *this; - } + const Texture& operator=(const tinygltf::Texture& src); }; class Sampler @@ -232,16 +170,7 @@ namespace LL S32 mWrapT; std::string mName; - const Sampler& operator=(const tinygltf::Sampler& src) - { - mMagFilter = src.magFilter; - mMinFilter = src.minFilter; - mWrapS = src.wrapS; - mWrapT = src.wrapT; - mName = src.name; - - return *this; - } + const Sampler& operator=(const tinygltf::Sampler& src); }; class Image @@ -292,27 +221,21 @@ namespace LL std::vector mSamplers; std::vector mImages; std::vector mAccessors; + std::vector mAnimations; + std::vector mSkins; - void allocateGLResources(const std::string& filename, const tinygltf::Model& model) - { - // do images first as materials may depend on images - for (auto& image : mImages) - { - image.allocateGLResources(); - } - - // do materials before meshes as meshes may depend on materials - for (U32 i = 0; i < mMaterials.size(); ++i) - { - mMaterials[i].allocateGLResources(*this); - LLTinyGLTFHelper::getMaterialFromModel(filename, model, i, mMaterials[i].mMaterial, mMaterials[i].mName, true); - } - - for (auto& mesh : mMeshes) - { - mesh.allocateGLResources(*this); - } - } + // the last time update() was called according to gFrameTimeSeconds + F32 mLastUpdateTime = gFrameTimeSeconds; + + // prepare the asset for rendering + void allocateGLResources(const std::string& filename, const tinygltf::Model& model); + + // Called periodically (typically once per frame) + // Any ongoing work (such as animations) should be handled here + // NOT guaranteed to be called every frame + // MAY be called more than once per frame + // Upon return, all Node Matrix transforms should be up to date + void update(); // update asset-to-node and node-to-asset transforms void updateTransforms(); @@ -320,7 +243,7 @@ namespace LL // update node render transforms void updateRenderTransforms(const LLMatrix4a& modelview); - void render(bool opaque); + void render(bool opaque, bool rigged = false); void renderOpaque(); void renderTransparent(); @@ -334,70 +257,8 @@ namespace LL S32* primitive_hitp = nullptr // return the index of the primitive that was hit ); - const Asset& operator=(const tinygltf::Model& src) - { - mScenes.resize(src.scenes.size()); - for (U32 i = 0; i < src.scenes.size(); ++i) - { - mScenes[i] = src.scenes[i]; - } - - mNodes.resize(src.nodes.size()); - for (U32 i = 0; i < src.nodes.size(); ++i) - { - mNodes[i] = src.nodes[i]; - } - - mMeshes.resize(src.meshes.size()); - for (U32 i = 0; i < src.meshes.size(); ++i) - { - mMeshes[i] = src.meshes[i]; - } - - mMaterials.resize(src.materials.size()); - for (U32 i = 0; i < src.materials.size(); ++i) - { - mMaterials[i] = src.materials[i]; - } - - mBuffers.resize(src.buffers.size()); - for (U32 i = 0; i < src.buffers.size(); ++i) - { - mBuffers[i] = src.buffers[i]; - } - - mBufferViews.resize(src.bufferViews.size()); - for (U32 i = 0; i < src.bufferViews.size(); ++i) - { - mBufferViews[i] = src.bufferViews[i]; - } - - mTextures.resize(src.textures.size()); - for (U32 i = 0; i < src.textures.size(); ++i) - { - mTextures[i] = src.textures[i]; - } - - mSamplers.resize(src.samplers.size()); - for (U32 i = 0; i < src.samplers.size(); ++i) - { - mSamplers[i] = src.samplers[i]; - } - - mImages.resize(src.images.size()); - for (U32 i = 0; i < src.images.size(); ++i) - { - mImages[i] = src.images[i]; - } - - mAccessors.resize(src.accessors.size()); - for (U32 i = 0; i < src.accessors.size(); ++i) - { - mAccessors[i] = src.accessors[i]; - } - - return *this; - } + const Asset& operator=(const tinygltf::Model& src); + }; } } diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h new file mode 100644 index 0000000000..4e6f5901e7 --- /dev/null +++ b/indra/newview/gltf/buffer_util.h @@ -0,0 +1,402 @@ +#pragma once + +/** + * @file buffer_util.inl + * @brief LL GLTF Implementation + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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$ + */ + +// inline template implementations for copying data out of GLTF buffers +// DO NOT include from header files to avoid the need to rebuild the whole project +// whenever we add support for more types + +#ifdef _MSC_VER +#define LL_FUNCSIG __FUNCSIG__ +#else +#define LL_FUNCSIG __PRETTY_FUNCTION__ +#endif + +namespace LL +{ + namespace GLTF + { + // copy one Scalar from src to dst + template + static void copyScalar(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec2 from src to dst + template + static void copyVec2(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec3 from src to dst + template + static void copyVec3(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec4 from src to dst + template + static void copyVec4(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec2 from src to dst + template + static void copyMat2(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec3 from src to dst + template + static void copyMat3(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + // copy one vec4 from src to dst + template + static void copyMat4(S* src, T& dst) + { + LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; + } + + //========================================================================================================= + // concrete implementations for different types of source and destination + //========================================================================================================= + +// suppress unused function warning -- clang complains here but these specializations are definitely used +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + + template<> + void copyScalar(F32* src, F32& dst) + { + dst = *src; + } + + template<> + void copyScalar(U32* src, U32& dst) + { + dst = *src; + } + + template<> + void copyScalar(U32* src, U16& dst) + { + dst = *src; + } + + template<> + void copyScalar(U16* src, U16& dst) + { + dst = *src; + } + + template<> + void copyScalar(U16* src, U32& dst) + { + dst = *src; + } + + template<> + void copyScalar(U8* src, U16& dst) + { + dst = *src; + } + + template<> + void copyScalar(U8* src, U32& dst) + { + dst = *src; + } + + template<> + void copyVec2(F32* src, LLVector2& dst) + { + dst.set(src[0], src[1]); + } + + template<> + void copyVec3(F32* src, glh::vec3f& dst) + { + dst.set_value(src[0], src[1], src[2]); + } + + template<> + void copyVec3(F32* src, LLVector4a& dst) + { + dst.load3(src); + } + + template<> + void copyVec3(U16* src, LLColor4U& dst) + { + dst.set(src[0], src[1], src[2], 255); + } + + template<> + void copyVec4(U8* src, LLColor4U& dst) + { + dst.set(src[0], src[1], src[2], src[3]); + } + + template<> + void copyVec4(U16* src, LLColor4U& dst) + { + dst.set(src[0], src[1], src[2], src[3]); + } + + template<> + void copyVec4(F32* src, LLColor4U& dst) + { + dst.set(src[0]*255, src[1]*255, src[2]*255, src[3]*255); + } + + template<> + void copyVec4(F32* src, LLVector4a& dst) + { + dst.loadua(src); + } + + template<> + void copyVec4(U16* src, LLVector4a& dst) + { + dst.set(src[0], src[1], src[2], src[3]); + } + + template<> + void copyVec4(U8* src, LLVector4a& dst) + { + dst.set(src[0], src[1], src[2], src[3]); + } + + template<> + void copyVec4(F32* src, glh::quaternionf& dst) + { + dst.set_value(src); + } + + template<> + void copyMat4(F32* src, glh::matrix4f& dst) + { + dst.set_value(src); + } + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif + + //========================================================================================================= + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyScalar(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyScalar(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyVec2(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyVec2(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyVec3(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyVec3(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyVec4(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyVec4(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyMat2(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyMat2(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyMat3(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyMat3(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + // copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy + template + static void copyMat4(S* src, LLStrider dst, S32 stride, S32 count) + { + for (S32 i = 0; i < count; ++i) + { + copyMat4(src, *dst); + dst++; + src = (S*)((U8*)src + stride); + } + } + + template + static void copy(Asset& asset, Accessor& accessor, const S* src, LLStrider& dst, S32 byteStride) + { + if (accessor.mType == (S32)Accessor::Type::SCALAR) + { + S32 stride = byteStride == 0 ? sizeof(S) * 1 : byteStride; + copyScalar((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::VEC2) + { + S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride; + copyVec2((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::VEC3) + { + S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride; + copyVec3((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::VEC4) + { + S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride; + copyVec4((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::MAT2) + { + S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride; + copyMat2((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::MAT3) + { + S32 stride = byteStride == 0 ? sizeof(S) * 9 : byteStride; + copyMat3((S*)src, dst, stride, accessor.mCount); + } + else if (accessor.mType == (S32)Accessor::Type::MAT4) + { + S32 stride = byteStride == 0 ? sizeof(S) * 16 : byteStride; + copyMat4((S*)src, dst, stride, accessor.mCount); + } + else + { + LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; + } + } + + // copy data from accessor to strider + template + static void copy(Asset& asset, Accessor& accessor, LLStrider& dst) + { + const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; + const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; + + if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT) + { + LL::GLTF::copy(asset, accessor, (const F32*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) + { + LL::GLTF::copy(asset, accessor, (const U16*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) + { + LL::GLTF::copy(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) + { + LL::GLTF::copy(asset, accessor, (const U8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT) + { + LL::GLTF::copy(asset, accessor, (const S16*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE) + { + LL::GLTF::copy(asset, accessor, (const S8*)src, dst, bufferView.mByteStride); + } + else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) + { + LL::GLTF::copy(asset, accessor, (const F64*)src, dst, bufferView.mByteStride); + } + else + { + LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL; + } + } + + // copy data from accessor to vector + template + static void copy(Asset& asset, Accessor& accessor, std::vector& dst) + { + dst.resize(accessor.mCount); + LLStrider strider = dst.data(); + copy(asset, accessor, strider); + } + } +} + diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index b5d59e1b24..b57a0af18d 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -27,163 +27,12 @@ #include "../llviewerprecompiledheaders.h" #include "asset.h" +#include "buffer_util.h" + #include "../lltinygltfhelper.h" using namespace LL::GLTF; -#ifdef _MSC_VER -#define LL_FUNCSIG __FUNCSIG__ -#else -#define LL_FUNCSIG __PRETTY_FUNCTION__ -#endif - -// copy one vec3 from src to dst -template -void copyVec2(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -// copy one vec3 from src to dst -template -void copyVec3(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -// copy one vec4 from src to dst -template -void copyVec4(S* src, T& dst) -{ - LL_ERRS() << "TODO: implement " << LL_FUNCSIG << LL_ENDL; -} - -template<> -void copyVec2(F32* src, LLVector2& dst) -{ - dst.set(src[0], src[1]); -} - -template<> -void copyVec3(F32* src, LLVector4a& dst) -{ - dst.load3(src); -} - -template<> -void copyVec3(U16* src, LLColor4U& dst) -{ - dst.set(src[0], src[1], src[2], 255); -} - -template<> -void copyVec4(F32* src, LLVector4a& dst) -{ - dst.loadua(src); -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template -void copyVec2(S* src, LLStrider dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec2(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template -void copyVec3(S* src, LLStrider dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec3(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -// copy from src to dst, stride is the number of bytes between each element in src, count is number of elements to copy -template -void copyVec4(S* src, LLStrider dst, S32 stride, S32 count) -{ - for (S32 i = 0; i < count; ++i) - { - copyVec3(src, *dst); - dst++; - src = (S*)((U8*)src + stride); - } -} - -template -void copyAttributeArray(Asset& asset, const Accessor& accessor, const S* src, LLStrider& dst, S32 byteStride) -{ - if (accessor.mType == TINYGLTF_TYPE_VEC2) - { - S32 stride = byteStride == 0 ? sizeof(S) * 2 : byteStride; - copyVec2((S*)src, dst, stride, accessor.mCount); - } - else if (accessor.mType == TINYGLTF_TYPE_VEC3) - { - S32 stride = byteStride == 0 ? sizeof(S) * 3 : byteStride; - copyVec3((S*)src, dst, stride, accessor.mCount); - } - else if (accessor.mType == TINYGLTF_TYPE_VEC4) - { - S32 stride = byteStride == 0 ? sizeof(S) * 4 : byteStride; - copyVec4((S*)src, dst, stride, accessor.mCount); - } - else - { - LL_ERRS("GLTF") << "Unsupported accessor type" << LL_ENDL; - } -} - -template -void Primitive::copyAttribute(Asset& asset, S32 accessorIdx, LLStrider& dst) -{ - const Accessor& accessor = asset.mAccessors[accessorIdx]; - const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; - const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; - const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; - - if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_FLOAT) - { - copyAttributeArray(asset, accessor, (const F32*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) - { - copyAttributeArray(asset, accessor, (const U16*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) - { - copyAttributeArray(asset, accessor, (const U32*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) - { - copyAttributeArray(asset, accessor, (const U8*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_SHORT) - { - copyAttributeArray(asset, accessor, (const S16*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_BYTE) - { - copyAttributeArray(asset, accessor, (const S8*)src, dst, bufferView.mByteStride); - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_DOUBLE) - { - copyAttributeArray(asset, accessor, (const F64*)src, dst, bufferView.mByteStride); - } - else - { - LL_ERRS("GLTF") << "Unsupported component type" << LL_ENDL; - } -} - void Primitive::allocateGLResources(Asset& asset) { // allocate vertex buffer @@ -192,219 +41,138 @@ void Primitive::allocateGLResources(Asset& asset) // For our engine, though, it's better to rearrange the buffers at load time into a layout that's more consistent. // The GLTF native approach undoubtedly works well if you can count on VAOs, but VAOs perform much worse with our scenes. - // get the number of vertices - U32 numVertices = 0; - if (!mAttributes.empty()) - { - auto it = mAttributes.begin(); - const Accessor& accessor = asset.mAccessors[it->second]; - numVertices = accessor.mCount; - } - - // get the number of indices - U32 numIndices = 0; - if (mIndices != INVALID_INDEX) - { - const Accessor& accessor = asset.mAccessors[mIndices]; - numIndices = accessor.mCount; - } - - // create vertex buffer - mVertexBuffer = new LLVertexBuffer(ATTRIBUTE_MASK); - mVertexBuffer->allocateBuffer(numVertices, numIndices); - - bool needs_color = true; - bool needs_texcoord = true; - bool needs_normal = true; - bool needs_tangent = true; - // load vertex data for (auto& it : mAttributes) { const std::string& attribName = it.first; + Accessor& accessor = asset.mAccessors[it.second]; // load vertex data if (attribName == "POSITION") { - // load position data - LLStrider dst; - mVertexBuffer->getVertexStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mPositions); } else if (attribName == "NORMAL") { - needs_normal = false; - // load normal data - LLStrider dst; - mVertexBuffer->getNormalStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mNormals); } else if (attribName == "TANGENT") { - needs_tangent = false; - // load tangent data - - LLStrider dst; - mVertexBuffer->getTangentStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mTangents); } else if (attribName == "COLOR_0") { - needs_color = false; - // load color data - - LLStrider dst; - mVertexBuffer->getColorStrider(dst); - - copyAttribute(asset, it.second, dst); + copy(asset, accessor, mColors); } else if (attribName == "TEXCOORD_0") { - needs_texcoord = false; - // load texcoord data - LLStrider dst; - mVertexBuffer->getTexCoord0Strider(dst); - - LLStrider tc = dst; - copyAttribute(asset, it.second, dst); - - // convert to OpenGL coordinate space - for (U32 i = 0; i < numVertices; ++i) - { - tc->mV[1] = 1.0f - tc->mV[1];; - tc++; - } + copy(asset, accessor, mTexCoords); + } + else if (attribName == "JOINTS_0") + { + copy(asset, accessor, mJoints); + } + else if (attribName == "WEIGHTS_0") + { + copy(asset, accessor, mWeights); } } // copy index buffer if (mIndices != INVALID_INDEX) { - const Accessor& accessor = asset.mAccessors[mIndices]; - const BufferView& bufferView = asset.mBufferViews[accessor.mBufferView]; - const Buffer& buffer = asset.mBuffers[bufferView.mBuffer]; + Accessor& accessor = asset.mAccessors[mIndices]; + copy(asset, accessor, mIndexArray); + } - const U8* src = buffer.mData.data() + bufferView.mByteOffset + accessor.mByteOffset; + U32 mask = ATTRIBUTE_MASK; + + if (!mWeights.empty()) + { + mask |= LLVertexBuffer::MAP_WEIGHT4; + } - LLStrider dst; - mVertexBuffer->getIndexStrider(dst); - mIndexArray.resize(numIndices); + mVertexBuffer = new LLVertexBuffer(mask); + mVertexBuffer->allocateBuffer(mPositions.size(), mIndexArray.size()*2); // double the size of the index buffer for 32-bit indices - if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = (U16) * (U32*)src; - src += sizeof(U32); - } - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = *(U16*)src; - src += sizeof(U16); - } - } - else if (accessor.mComponentType == TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE) - { - for (U32 i = 0; i < numIndices; ++i) - { - *(dst++) = *(U8*)src; - src += sizeof(U8); - } - } - else - { - LL_ERRS("GLTF") << "Unsupported component type for indices" << LL_ENDL; - } + mVertexBuffer->setBuffer(); + mVertexBuffer->setPositionData(mPositions.data()); - U16* idx = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 i = 0; i < numIndices; ++i) - { - mIndexArray[i] = idx[i]; - } + if (!mIndexArray.empty()) + { + mVertexBuffer->setIndexData(mIndexArray.data()); } - // fill in default values for missing attributes - if (needs_color) - { // set default color - LLStrider dst; - mVertexBuffer->getColorStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLColor4U(255, 255, 255, 255); - } + if (mTexCoords.empty()) + { + mTexCoords.resize(mPositions.size()); + } + + // flip texcoord y, upload, then flip back (keep the off-spec data in vram only) + for (auto& tc : mTexCoords) + { + tc[1] = 1.f - tc[1]; } + mVertexBuffer->setTexCoordData(mTexCoords.data()); + for (auto& tc : mTexCoords) + { + tc[1] = 1.f - tc[1]; + } + + if (mColors.empty()) + { + mColors.resize(mPositions.size(), LLColor4U::white); + } + // bake material basecolor into color array if (mMaterial != INVALID_INDEX) { const Material& material = asset.mMaterials[mMaterial]; LLColor4 baseColor = material.mMaterial->mBaseColor; - LLStrider dst; - mVertexBuffer->getColorStrider(dst); - - for (U32 i = 0; i < numVertices; ++i) + for (auto& dst : mColors) { - LLColor4 col = *dst; - *dst = LLColor4U(baseColor * col); - dst++; + dst = LLColor4U(baseColor * LLColor4(dst)); } } - if (needs_texcoord) - { // set default texcoord - LLStrider dst; - mVertexBuffer->getTexCoord0Strider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector2(0.0f, 0.0f); - } - } + mVertexBuffer->setColorData(mColors.data()); - if (needs_normal) - { // set default normal - LLStrider dst; - mVertexBuffer->getNormalStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector4a(0.0f, 0.0f, 1.0f, 0.0f); - } + if (mNormals.empty()) + { + mNormals.resize(mPositions.size(), LLVector4a(0, 0, 1, 0)); } + + mVertexBuffer->setNormalData(mNormals.data()); - if (needs_tangent) - { // TODO: generate tangents if needed - LLStrider dst; - mVertexBuffer->getTangentStrider(dst); - for (U32 i = 0; i < numVertices; ++i) - { - *(dst++) = LLVector4a(1.0f, 0.0f, 0.0f, 1.0f); - } + if (mTangents.empty()) + { + // TODO: generate tangents if needed + mTangents.resize(mPositions.size(), LLVector4a(1, 0, 0, 1)); } - mPositions.resize(numVertices); - mTexCoords.resize(numVertices); - mNormals.resize(numVertices); - mTangents.resize(numVertices); + mVertexBuffer->setTangentData(mTangents.data()); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - LLVector2* tc = (LLVector2*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TEXCOORD0)); - LLVector4a* norm = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_NORMAL)); - LLVector4a* tangent = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_TANGENT)); - for (U32 i = 0; i < numVertices; ++i) + if (!mWeights.empty()) { - mPositions[i] = pos[i]; - mTexCoords[i] = tc[i]; - mNormals[i] = norm[i]; - mTangents[i] = tangent[i]; + std::vector weight_data; + weight_data.resize(mWeights.size()); + + F32 max_weight = 1.f - FLT_EPSILON*100.f; + LLVector4a maxw(max_weight, max_weight, max_weight, max_weight); + for (U32 i = 0; i < mWeights.size(); ++i) + { + LLVector4a& w = weight_data[i]; + w.setMin(mWeights[i], maxw); + w.add(mJoints[i]); + }; + + mVertexBuffer->setWeight4Data(weight_data.data()); } + createOctree(); - mVertexBuffer->unmapBuffer(); + mVertexBuffer->unbind(); } void initOctreeTriangle(LLVolumeTriangle* tri, F32 scaler, S32 i0, S32 i1, S32 i2, const LLVector4a& v0, const LLVector4a& v1, const LLVector4a& v2) @@ -456,20 +224,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[index]; - S32 i1 = indices[index + 1]; - S32 i2 = indices[index + 2]; + S32 i0 = mIndexArray[index]; + S32 i1 = mIndexArray[index + 1]; + S32 i2 = mIndexArray[index + 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -483,20 +248,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index + 2; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[index]; - S32 i1 = indices[index - 1]; - S32 i2 = indices[index - 2]; + S32 i0 = mIndexArray[index]; + S32 i1 = mIndexArray[index - 1]; + S32 i2 = mIndexArray[index - 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -510,20 +272,17 @@ void Primitive::createOctree() // Initialize all the triangles we need mOctreeTriangles.resize(num_triangles); - LLVector4a* pos = (LLVector4a*)(mVertexBuffer->getMappedData() + mVertexBuffer->getOffset(LLVertexBuffer::TYPE_VERTEX)); - U16* indices = (U16*)mVertexBuffer->getMappedIndices(); - for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) { //for each triangle const U32 index = triangle_index + 2; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - S32 i0 = indices[0]; - S32 i1 = indices[index - 1]; - S32 i2 = indices[index - 2]; + S32 i0 = mIndexArray[0]; + S32 i1 = mIndexArray[index - 1]; + S32 i2 = mIndexArray[index - 2]; - const LLVector4a& v0 = pos[i0]; - const LLVector4a& v1 = pos[i1]; - const LLVector4a& v2 = pos[i2]; + const LLVector4a& v0 = mPositions[i0]; + const LLVector4a& v1 = mPositions[i1]; + const LLVector4a& v2 = mPositions[i2]; initOctreeTriangle(tri, scaler, i0, i1, i2, v0, v1, v2); @@ -571,7 +330,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start, face.mTexCoords = mTexCoords.data(); face.mNormals = mNormals.data(); face.mTangents = mTangents.data(); - face.mIndices = mIndexArray.data(); + face.mIndices = nullptr; // unreferenced face.mNumIndices = mIndexArray.size(); face.mNumVertices = mPositions.size(); @@ -592,3 +351,50 @@ Primitive::~Primitive() mOctree = nullptr; } + +const Primitive& Primitive::operator=(const tinygltf::Primitive& src) +{ + // load material + mMaterial = src.material; + + // load mode + mMode = src.mode; + + // load indices + mIndices = src.indices; + + // load attributes + for (auto& it : src.attributes) + { + mAttributes[it.first] = it.second; + } + + switch (mMode) + { + case TINYGLTF_MODE_POINTS: + mGLMode = LLRender::POINTS; + break; + case TINYGLTF_MODE_LINE: + mGLMode = LLRender::LINES; + break; + case TINYGLTF_MODE_LINE_LOOP: + mGLMode = LLRender::LINE_LOOP; + break; + case TINYGLTF_MODE_LINE_STRIP: + mGLMode = LLRender::LINE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLES: + mGLMode = LLRender::TRIANGLES; + break; + case TINYGLTF_MODE_TRIANGLE_STRIP: + mGLMode = LLRender::TRIANGLE_STRIP; + break; + case TINYGLTF_MODE_TRIANGLE_FAN: + mGLMode = LLRender::TRIANGLE_FAN; + break; + default: + mGLMode = GL_TRIANGLES; + } + + return *this; +} diff --git a/indra/newview/gltf/primitive.h b/indra/newview/gltf/primitive.h index 7c47d9dac5..07e8e7deb2 100644 --- a/indra/newview/gltf/primitive.h +++ b/indra/newview/gltf/primitive.h @@ -56,7 +56,10 @@ namespace LL std::vector mNormals; std::vector mTangents; std::vector mPositions; - std::vector mIndexArray; + std::vector mJoints; + std::vector mWeights; + std::vector mColors; + std::vector mIndexArray; // raycast acceleration structure LLPointer mOctree; @@ -68,11 +71,6 @@ namespace LL S32 mIndices = -1; std::unordered_map mAttributes; - // copy the attribute in the given BufferView to the given destination - // assumes destination has enough storage for the attribute - template - void copyAttribute(Asset& asset, S32 bufferViewIdx, LLStrider& dst); - // create octree based on vertex buffer // must be called before buffer is unmapped and after buffer is populated with good data void createOctree(); @@ -87,52 +85,7 @@ namespace LL LLVector4a* tangent = NULL // return the surface tangent at the intersection point ); - const Primitive& operator=(const tinygltf::Primitive& src) - { - // load material - mMaterial = src.material; - - // load mode - mMode = src.mode; - - // load indices - mIndices = src.indices; - - // load attributes - for (auto& it : src.attributes) - { - mAttributes[it.first] = it.second; - } - - switch (mMode) - { - case TINYGLTF_MODE_POINTS: - mGLMode = LLRender::POINTS; - break; - case TINYGLTF_MODE_LINE: - mGLMode = LLRender::LINES; - break; - case TINYGLTF_MODE_LINE_LOOP: - mGLMode = LLRender::LINE_LOOP; - break; - case TINYGLTF_MODE_LINE_STRIP: - mGLMode = LLRender::LINE_STRIP; - break; - case TINYGLTF_MODE_TRIANGLES: - mGLMode = LLRender::TRIANGLES; - break; - case TINYGLTF_MODE_TRIANGLE_STRIP: - mGLMode = LLRender::TRIANGLE_STRIP; - break; - case TINYGLTF_MODE_TRIANGLE_FAN: - mGLMode = LLRender::TRIANGLE_FAN; - break; - default: - mGLMode = GL_TRIANGLES; - } - - return *this; - } + const Primitive& operator=(const tinygltf::Primitive& src); void allocateGLResources(Asset& asset); }; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 8273c707f9..4e3439ea5c 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -82,6 +82,7 @@ void GLTFSceneManager::load(const std::string& filename) LLPointer asset = new Asset(); *asset = model; + gDebugProgram.bind(); // bind a shader to satisfy LLVertexBuffer assertions asset->allocateGLResources(filename, model); asset->updateTransforms(); @@ -114,7 +115,25 @@ void GLTFSceneManager::renderAlpha() render(false); } -void GLTFSceneManager::render(bool opaque) +void GLTFSceneManager::update() +{ + for (U32 i = 0; i < mObjects.size(); ++i) + { + if (mObjects[i]->isDead() || mObjects[i]->mGLTFAsset == nullptr) + { + mObjects.erase(mObjects.begin() + i); + --i; + continue; + } + + Asset* asset = mObjects[i]->mGLTFAsset; + + asset->update(); + + } +} + +void GLTFSceneManager::render(bool opaque, bool rigged) { // for debugging, just render the whole scene as opaque // by traversing the whole scenegraph @@ -144,7 +163,7 @@ void GLTFSceneManager::render(bool opaque) matMul(mat, modelview, modelview); asset->updateRenderTransforms(modelview); - asset->render(opaque); + asset->render(opaque, rigged); gGL.popMatrix(); } diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index 4e9013834b..d286f335e4 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -36,9 +36,12 @@ namespace LL public: ~GLTFSceneManager(); // load GLTF file from disk + void load(); // open filepicker to choose asset void load(const std::string& filename); // load asset from filename - void render(bool opaque); + + void update(); + void render(bool opaque, bool rigged = false); void renderOpaque(); void renderAlpha(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 46b95601af..c4c7d5675f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4857,6 +4857,7 @@ void LLAppViewer::idle() if (!(logoutRequestSent() && hasSavedFinalSnapshot())) { gObjectList.update(gAgent); + LL::GLTFSceneManager::instance().update(); } } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 81014e9d6e..9418cead76 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -261,10 +261,13 @@ void LLDrawPoolAlpha::forwardRender(bool rigged) mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - if (write_depth) - { // draw GLTF scene to depth buffer + if (rigged) + { // draw GLTF scene to depth buffer before rigged alpha gPipeline.bindDeferredShader(gDeferredPBRAlphaProgram); - LL::GLTFSceneManager::instance().renderAlpha(); + LL::GLTFSceneManager::instance().render(false, false); + + gPipeline.bindDeferredShader(*gDeferredPBRAlphaProgram.mRiggedVariant); + LL::GLTFSceneManager::instance().render(false, true); } // If the face is more than 90% transparent, then don't update the Depth buffer for Dof diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp index a32382af92..a32b6b1687 100644 --- a/indra/newview/lldrawpoolpbropaque.cpp +++ b/indra/newview/lldrawpoolpbropaque.cpp @@ -61,6 +61,7 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass) gDeferredPBROpaqueProgram.bind(true); + LL::GLTFSceneManager::instance().render(true, true); pushRiggedGLTFBatches(mRenderType + 1); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index fd8a2e3ffc..341c9706f8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -6593,6 +6593,10 @@ void LLPipeline::renderGLTFObjects(U32 type, bool texture, bool rigged) { LL::GLTFSceneManager::instance().renderOpaque(); } + else + { + LL::GLTFSceneManager::instance().render(true, true); + } } // Currently only used for shadows -Cosmic,2023-04-19 -- cgit v1.2.3 From aac18ada713aa34cafe477264ab08d5f1ba4e205 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 12 Apr 2024 11:27:24 -0700 Subject: secondlife/viewer#1184: Use more robust/memory-friendly setLoadedCallback for minimap gen. Fix some emissive maps. --- indra/llimage/llimage.cpp | 69 +++++++++++++ indra/llimage/llimage.h | 6 ++ indra/newview/llvlcomposition.cpp | 208 +++++++++++++++++++++++--------------- indra/newview/llvlcomposition.h | 5 + 4 files changed, 207 insertions(+), 81 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 16609b60be..8d35fd140e 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1874,6 +1874,75 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3 } } + +void LLImageRaw::addEmissive(LLImageRaw* src) +{ + LLImageRaw* dst = this; // Just for clarity. + + if (!validateSrcAndDst(__FUNCTION__, src, dst)) + { + return; + } + + llassert((3 == src->getComponents()) || (4 == src->getComponents())); + llassert(3 == dst->getComponents()); + + if( 3 == dst->getComponents() ) + { + if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) + { + addEmissiveUnscaled(src); + } + else + { + addEmissiveScaled(src); + } + } +} + +void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src) +{ + LLImageRaw* dst = this; // Just for clarity. + + llassert((3 == src->getComponents()) || (4 == src->getComponents())); + llassert((3 == dst->getComponents()) || (4 == dst->getComponents())); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + + U8* const src_data = src->getData(); + U8* const dst_data = dst->getData(); + for(S32 y = 0; y < dst->getHeight(); ++y) + { + const S32 src_row_offset = src->getComponents() * src->getWidth() * y; + const S32 dst_row_offset = dst->getComponents() * dst->getWidth() * y; + for (S32 x = 0; x < dst->getWidth(); ++x) + { + const S32 src_offset = src_row_offset + (x * src->getComponents()); + const S32 dst_offset = dst_row_offset + (x * dst->getComponents()); + U8* const src_pixel = src_data + src_offset; + U8* const dst_pixel = dst_data + dst_offset; + dst_pixel[0] = llmin(255, dst_pixel[0] + src_pixel[0]); + dst_pixel[1] = llmin(255, dst_pixel[1] + src_pixel[1]); + dst_pixel[2] = llmin(255, dst_pixel[2] + src_pixel[2]); + } + } +} + +void LLImageRaw::addEmissiveScaled(LLImageRaw* src) +{ + LL_INFOS() << __FUNCTION__ << LL_ENDL; + + LLImageRaw* dst = this; // Just for clarity. + + llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); + + LLImageRaw temp(dst->getWidth(), dst->getHeight(), dst->getComponents()); + llassert_always(temp.getDataSize() > 0); + temp.copyScaled(src); + + dst->addEmissiveUnscaled(&temp); +} + + bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst) { if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid()) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 93b58b2356..c49184e338 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -276,6 +276,12 @@ public: // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); + // Emissive operations used by minimap + // Roughly emulates GLTF emissive texture, but is not GLTF-compliant + // *TODO: Remove in favor of shader + void addEmissive(LLImageRaw* src); + void addEmissiveScaled(LLImageRaw* src); + void addEmissiveUnscaled(LLImageRaw* src); protected: // Create an image from a local file (generally used in tools) //bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 6955949571..b915cce933 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -28,6 +28,8 @@ #include "llvlcomposition.h" +#include + #include "llerror.h" #include "v3math.h" #include "llsurface.h" @@ -513,6 +515,108 @@ BOOL LLVLComposition::generateComposition() return LLTerrainMaterials::generateMaterials(); } +namespace +{ + void prepare_fallback_image(LLImageRaw* raw_image) + { + raw_image->resize(BASE_SIZE, BASE_SIZE, 4); + raw_image->fill(LLColor4U::white); + } + + // Check if the raw image is loaded for this texture at a discard + // level the minimap can use, and if not then try to get it loaded. + bool prepare_raw_image(LLPointer& raw_image, bool emissive, LLViewerFetchedTexture* tex, bool& delete_raw_post) + { + if (!tex) + { + if (!emissive) + { + prepare_fallback_image(raw_image); + } + else + { + llassert(!raw_image); + raw_image = nullptr; + } + return true; + } + if (raw_image) + { + // Callback already initiated + if (raw_image->getDataSize() > 0) + { + // Callback finished + delete_raw_post = true; + return true; + } + else + { + return false; + } + } + + raw_image = new LLImageRaw(); + + S32 ddiscard = 0; + { + S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); + while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) + { + ddiscard++; + min_dim /= 2; + } + } + + struct PendingImage + { + LLImageRaw* mRawImage; + S32 mDesiredDiscard; + LLUUID mTextureId; + PendingImage(LLImageRaw* raw_image, S32 ddiscard, const LLUUID& texture_id) + : mRawImage(raw_image) + , mDesiredDiscard(ddiscard) + , mTextureId(texture_id) + { + mRawImage->ref(); + } + ~PendingImage() + { + mRawImage->unref(); + } + }; + PendingImage* pending_image = new PendingImage(raw_image, ddiscard, tex->getID()); + + loaded_callback_func cb = [](BOOL success, LLViewerFetchedTexture * src_vi, LLImageRaw * src, LLImageRaw * src_aux, S32 discard_level, BOOL is_final, void* userdata) { + PendingImage* pending = (PendingImage*)userdata; + // Owning LLVLComposition still exists + + // Assume mRawImage only used by single LLVLComposition for now + const bool in_use_by_composition = pending->mRawImage->getNumRefs() > 1; + llassert(pending->mRawImage->getNumRefs()); + llassert(pending->mRawImage->getNumRefs() <= 2); + const bool needs_data = !pending->mRawImage->getDataSize(); + if (in_use_by_composition && needs_data) + { + if (success && pending->mDesiredDiscard == discard_level) + { + pending->mRawImage->resize(BASE_SIZE, BASE_SIZE, src->getComponents()); + pending->mRawImage->copyScaled(src); + } + else if (is_final) + { + prepare_fallback_image(pending->mRawImage); + } + } + + if (is_final) { delete userdata; } + }; + tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr); + tex->forceToSaveRawImage(ddiscard); + + return false; + } +}; + BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height) { @@ -580,96 +684,28 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, } if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; } - // tex_emissive can be null, and then will be ignored - - S32 ddiscard = 0; - { - S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight()); - while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) - { - ddiscard++; - min_dim /= 2; - } - } - - S32 ddiscard_emissive = 0; - if (tex_emissive) - { - S32 min_dim_emissive = llmin(tex_emissive->getFullWidth(), tex_emissive->getFullHeight()); - while (min_dim_emissive > BASE_SIZE && ddiscard_emissive < MAX_DISCARD_LEVEL) - { - ddiscard_emissive++; - min_dim_emissive /= 2; - } - } - - // *NOTE: It is probably safe to call destroyRawImage no matter - // what, as LLViewerFetchedTexture::mRawImage is managed by - // LLPointer and not modified with the rare exception of - // icons (see BOOST_ICON). Nevertheless, gate this fix for now, as - // it may have unintended consequences on texture loading. - // We may want to also set the boost level in setDetailAssetID, but - // that is not guaranteed to work if a texture is loaded on an object - // before being loaded as terrain, so we will need this fix - // regardless. - static LLCachedControl sRenderTerrainPBREnabled(gSavedSettings, "RenderTerrainPBREnabled", false); - BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL || sRenderTerrainPBREnabled); - BOOL delete_raw_emissive = (tex_emissive && - (tex_emissive->reloadRawImage(ddiscard_emissive) != NULL || sRenderTerrainPBREnabled)); - - if(tex->getRawImageLevel() != ddiscard) - { - // Raw image is not ready, will enter here again later. - if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage()) - { - boost_minimap_texture(tex, TERRAIN_DECODE_PRIORITY); - tex->forceToRefetchTexture(ddiscard); - } - - if(delete_raw) - { - tex->destroyRawImage() ; - } - return FALSE; - } - if (tex_emissive) - { - if(tex_emissive->getRawImageLevel() != ddiscard_emissive) - { - // Raw image is not ready, will enter here again later. - if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage()) - { - boost_minimap_texture(tex_emissive, TERRAIN_DECODE_PRIORITY); - tex_emissive->forceToRefetchTexture(ddiscard_emissive); - } - if(delete_raw_emissive) - { - tex_emissive->destroyRawImage() ; - } - return FALSE; - } - } + bool delete_raw_post = false; + bool delete_raw_post_emissive = false; + if (!prepare_raw_image(mRawImagesBaseColor[i], false, tex, delete_raw_post)) { return FALSE; } + if (tex_emissive && !prepare_raw_image(mRawImagesEmissive[i], true, tex_emissive, delete_raw_post_emissive)) { return FALSE; } + // tex_emissive can be null, and then will be ignored - mRawImages[i] = tex->getRawImage() ; - if(delete_raw) - { - tex->destroyRawImage() ; - } + // In the simplest case, the minimap image is just the base color. + // This will be replaced if we need to do any tinting/compositing. + mRawImages[i] = mRawImagesBaseColor[i]; // *TODO: This isn't quite right for PBR: // 1) It does not convert the color images from SRGB to linear // before mixing (which will always require copying the image). // 2) It mixes emissive and base color before mixing terrain // materials, but it should be the other way around - // 3) The composite function used to put emissive into base color - // is not an alpha blend. // Long-term, we should consider a method that is more // maintainable. Shaders, perhaps? Bake shaders to textures? LLPointer raw_emissive; if (tex_emissive) { - raw_emissive = tex_emissive->getRawImage(); + raw_emissive = mRawImagesEmissive[i]; if (has_emissive_factor || tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE || tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != BASE_SIZE || @@ -677,7 +713,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { LLPointer newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4); // Copy RGB, leave alpha alone (set to opaque by default) - newraw_emissive->copy(mRawImages[i]); + newraw_emissive->copy(mRawImagesEmissive[i]); if (has_emissive_factor) { newraw_emissive->tint(emissive_factor); @@ -702,7 +738,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, MAX_WATER_COLOR.mV[VZ], 255); } - newraw->composite(mRawImages[i]); + newraw->composite(mRawImagesBaseColor[i]); if (has_base_color_factor) { newraw->tint(base_color_factor); @@ -710,16 +746,24 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, // Apply emissive texture if (raw_emissive) { - newraw->composite(raw_emissive); + newraw->addEmissive(raw_emissive); } mRawImages[i] = newraw; // deletes old } - if (delete_raw_emissive) + if (delete_raw_post) + { + tex->destroyRawImage(); + } + if (delete_raw_post_emissive) { tex_emissive->destroyRawImage(); } + + // Remove intermediary image references + mRawImagesBaseColor[i] = nullptr; + mRawImagesEmissive[i] = nullptr; } st_data[i] = mRawImages[i]->getData(); st_data_size[i] = mRawImages[i]->getDataSize(); @@ -893,6 +937,8 @@ void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id) } LLTerrainMaterials::setDetailAssetID(asset, id); mRawImages[asset] = NULL; + mRawImagesBaseColor[asset] = NULL; + mRawImagesEmissive[asset] = NULL; } void LLVLComposition::setStartHeight(S32 corner, const F32 start_height) diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 6a460e3285..5db832e034 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -130,8 +130,13 @@ protected: BOOL mParamsReady = FALSE; LLSurface *mSurfacep; + // Final minimap raw images LLPointer mRawImages[LLTerrainMaterials::ASSET_COUNT]; + // Only non-null during minimap tile generation + LLPointer mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT]; + LLPointer mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT]; + F32 mStartHeight[CORNER_COUNT]; F32 mHeightRange[CORNER_COUNT]; -- cgit v1.2.3 From df40c005aee360671f1f79d601b1456ca6756aca Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 25 Apr 2024 16:51:14 -0700 Subject: secondlife/viewer#1184: Discourage use of forceToRefetchTexture --- indra/newview/llviewertexture.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 35fb0a2237..52b2f19ada 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -398,7 +398,6 @@ public: BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} BOOL isRawImageValid()const { return mIsRawImageValid ; } void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; - void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override; void destroySavedRawImage() ; LLImageRaw* getSavedRawImage() ; @@ -420,6 +419,7 @@ public: protected: /*virtual*/ void switchToCachedImage() override; S32 getCurrentDiscardLevelForFetching() ; + void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); private: void init(bool firstinit) ; -- cgit v1.2.3 From 19c05046713a2d6b439eee3418baa54a904429f1 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Thu, 25 Apr 2024 17:33:02 -0700 Subject: secondlife/viewer#1184: Fix mac build --- indra/newview/llvlcomposition.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index b915cce933..8d3b5cc8a5 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -608,7 +608,7 @@ namespace } } - if (is_final) { delete userdata; } + if (is_final) { delete pending; } }; tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr); tex->forceToSaveRawImage(ddiscard); -- cgit v1.2.3 From 668c63c2c4e2d9757ccaebbfea5f99264b7352c2 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Fri, 26 Apr 2024 09:25:08 -0700 Subject: secondlife/viewer#1184: Remove logspam --- indra/llimage/llimage.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 8d35fd140e..f6a8735ca1 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1929,8 +1929,6 @@ void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src) void LLImageRaw::addEmissiveScaled(LLImageRaw* src) { - LL_INFOS() << __FUNCTION__ << LL_ENDL; - LLImageRaw* dst = this; // Just for clarity. llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); -- cgit v1.2.3 From 8465a8acb206bbdd839764446ac27e1116c58ee8 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Fri, 26 Apr 2024 13:38:30 -0500 Subject: #1325 Fix for GLTF overrides sometimes not showing up. (#1340) --- indra/newview/llgltfmateriallist.cpp | 8 ++------ indra/newview/llviewerregion.cpp | 14 +++++++++++++- indra/newview/llviewerregion.h | 3 ++- indra/newview/llvocache.cpp | 36 +++++++++++++++++++++++++++++------- 4 files changed, 46 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index e97eb552cf..4c9dc8f7cd 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -244,12 +244,8 @@ void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::s } } - // Workaround for server sending empty overrides. - if(cache.mSides.size() > 0) - { - region->cacheFullUpdateGLTFOverride(cache); - LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL; - } + region->cacheFullUpdateGLTFOverride(cache); + LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL; } } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 160e2f7e5c..fe1291c6f4 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2744,7 +2744,14 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data) { U32 local_id = override_data.mLocalId; - mImpl->mGLTFOverridesLLSD[local_id] = override_data; + if (override_data.mSides.size() > 0) + { // empty override means overrides were removed from this object + mImpl->mGLTFOverridesLLSD[local_id] = override_data; + } + else + { + mImpl->mGLTFOverridesLLSD.erase(local_id); + } } LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id) @@ -2961,6 +2968,11 @@ void LLViewerRegion::dumpCache() // TODO - add overrides cache too } +void LLViewerRegion::clearVOCacheFromMemory() +{ + mImpl->mCacheMap.clear(); +} + void LLViewerRegion::unpackRegionHandshake() { LLMessageSystem *msg = gMessageSystem; diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 1c2ff9bc97..1c89cc4e6d 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -378,7 +378,8 @@ public: LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp); void findOrphans(U32 parent_id); void clearCachedVisibleObjects(); - void dumpCache(); + void dumpCache (); + void clearVOCacheFromMemory(); void unpackRegionHandshake(); diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 82ffd1d522..8dad833eaa 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1272,6 +1272,13 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry) getObjectCacheFilename(entry->mHandle, filename); LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL; + // make sure corresponding LLViewerRegion also clears its in-memory cache + LLViewerRegion* regionp = LLWorld::instance().getRegionFromHandle(entry->mHandle); + if (regionp) + { + regionp->clearVOCacheFromMemory(); + } + header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); if(iter != mHeaderEntryQueue.end()) { @@ -1340,10 +1347,14 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry) std::string filename; getObjectCacheFilename(entry->mHandle, filename); + LL_WARNS("GLTF", "VOCache") << "Removing object cache for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL; LLAPRFile::remove(filename, mLocalAPRFilePoolp); - // Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry. + + // Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry. // as such this now includes the generic extras - removeGenericExtrasForHandle(entry->mHandle); + filename = getObjectCacheExtrasFilename(entry->mHandle); + LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL; + LLFile::remove(filename); entry->mTime = INVALID_TIME ; updateEntry(entry) ; //update the head file. @@ -1358,7 +1369,7 @@ void LLVOCache::readCacheHeader() } //clear stale info. - clearCacheInMemory(); + clearCacheInMemory(); bool success = true ; if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) @@ -1605,7 +1616,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac } // For future versions we may call a legacy handler here, but realistically we'll just consider this cache out of date. // The important thing is to make sure it gets removed. - if(versionNumber != LLGLTFOverrideCacheEntry::VERSION && versionNumber != 0) + if(versionNumber != LLGLTFOverrideCacheEntry::VERSION) { LL_WARNS() << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL; in.close(); @@ -1614,7 +1625,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac } LL_DEBUGS("VOCache") << "Reading extras cache for handle " << handle << ", version " << versionNumber << LL_ENDL; - + std::getline(in, line); if(!LLUUID::validate(line)) { LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL; @@ -1847,8 +1858,19 @@ void LLVOCache::removeGenericExtrasForHandle(U64 handle) LL_WARNS() << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << LL_ENDL; return ; } - LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << handle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL; - LLFile::remove(getObjectCacheExtrasFilename(handle)); + + // NOTE: when removing the extras, we must also remove the objects so the simulator will send us a full upddate with the valid overrides + auto* entry = mHandleEntryMap[handle]; + if (entry) + { + removeEntry(entry); + } + else + { + //shouldn't happen, but if it does, we should remove the extras file since it's orphaned + LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << entry->mHandle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL; + LLFile::remove(getObjectCacheExtrasFilename(entry->mHandle)); + } } void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled) -- cgit v1.2.3 From 66ccc1ed836948aa5d26b1ce0fcc1ae799e792a7 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Mon, 29 Apr 2024 12:40:42 -0500 Subject: #886 Fix for crash in LLBumpImageList when connecting to a simulator with different feature flags (#1345) --- indra/newview/llviewerregion.cpp | 84 ++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 34 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index fe1291c6f4..29dce088f5 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2447,45 +2447,61 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) setSimulatorFeaturesReceived(true); - // if region has MaxTextureResolution, set max_texture_dimension settings, otherwise use default - if (mSimulatorFeatures.has("MaxTextureResolution")) - { - S32 max_texture_resolution = mSimulatorFeatures["MaxTextureResolution"].asInteger(); - gSavedSettings.setS32("max_texture_dimension_X", max_texture_resolution); - gSavedSettings.setS32("max_texture_dimension_Y", max_texture_resolution); - } - else - { - gSavedSettings.setS32("max_texture_dimension_X", 1024); - gSavedSettings.setS32("max_texture_dimension_Y", 1024); - } + // WARNING: this is called from a coroutine, and flipping saved settings has a LOT of side effects, shuttle + // the work below back to the main loop + // + + // copy features to lambda in case the region is deleted before the lambda is executed + LLSD features = mSimulatorFeatures; + + auto work = [=]() + { + // if region has MaxTextureResolution, set max_texture_dimension settings, otherwise use default + if (features.has("MaxTextureResolution")) + { + S32 max_texture_resolution = features["MaxTextureResolution"].asInteger(); + gSavedSettings.setS32("max_texture_dimension_X", max_texture_resolution); + gSavedSettings.setS32("max_texture_dimension_Y", max_texture_resolution); + } + else + { + gSavedSettings.setS32("max_texture_dimension_X", 1024); + gSavedSettings.setS32("max_texture_dimension_Y", 1024); + } - bool mirrors_enabled = false; - if (mSimulatorFeatures.has("MirrorsEnabled")) - { - mirrors_enabled = mSimulatorFeatures["MirrorsEnabled"].asBoolean(); - } + bool mirrors_enabled = false; + if (features.has("MirrorsEnabled")) + { + mirrors_enabled = features["MirrorsEnabled"].asBoolean(); + } - gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); + gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); - if (mSimulatorFeatures.has("PBRTerrainEnabled")) - { - bool enabled = mSimulatorFeatures["PBRTerrainEnabled"]; - gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled); - } - else - { - gSavedSettings.setBOOL("RenderTerrainPBREnabled", false); - } + if (features.has("PBRTerrainEnabled")) + { + bool enabled = features["PBRTerrainEnabled"]; + gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled); + } + else + { + gSavedSettings.setBOOL("RenderTerrainPBREnabled", false); + } - if (mSimulatorFeatures.has("PBRMaterialSwatchEnabled")) - { - bool enabled = mSimulatorFeatures["PBRMaterialSwatchEnabled"]; - gSavedSettings.setBOOL("UIPreviewMaterial", enabled); - } - else + if (features.has("PBRMaterialSwatchEnabled")) + { + bool enabled = features["PBRMaterialSwatchEnabled"]; + gSavedSettings.setBOOL("UIPreviewMaterial", enabled); + } + else + { + gSavedSettings.setBOOL("UIPreviewMaterial", false); + } + }; + + auto workqueue = LL::WorkQueue::getInstance("mainloop"); + if (workqueue) { - gSavedSettings.setBOOL("UIPreviewMaterial", false); + LL::WorkQueue::postMaybe(workqueue, work); } } -- cgit v1.2.3 From 1514edc58a498fde9533136f86bb20a9e5ef9a37 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 30 Apr 2024 18:01:13 -0500 Subject: Fix for black moon. (#1369) --- indra/newview/app_settings/shaders/class1/deferred/moonF.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl index 183354b9bd..6ef556d7e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl @@ -55,7 +55,7 @@ void main() frag_data[0] = vec4(0); frag_data[1] = vec4(0.0); - frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_HAS_ATMOS); + frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); frag_data[3] = vec4(c.rgb, c.a); // Added and commented out for a ground truth. Do not uncomment - Geenz -- cgit v1.2.3 From 9b6979f458b585618fa59887b500a1a7a4a6e02f Mon Sep 17 00:00:00 2001 From: Brad Linden <46733234+brad-linden@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:06:27 -0700 Subject: Fix for SL-20652 shadows on mac breaking alpha blended objects. (#1264) * Fix for SL-20652 shadows on mac breaking alpha blended objects. fix secondlife/jira-archive-internal#71030 * clean up surrounding indentation * Skip unnecessary casting * Clean up LLGLSLShader::sIndexedTextureChannels usage and improve fix for SL-20652 --- indra/llrender/llshadermgr.cpp | 2 +- indra/newview/app_settings/settings.xml | 75 +++++++++++++++++++-------------- indra/newview/lldrawpoolalpha.cpp | 7 +-- indra/newview/llface.cpp | 2 +- indra/newview/llviewershadermgr.cpp | 5 ++- indra/newview/llvovolume.cpp | 14 +----- 6 files changed, 54 insertions(+), 51 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 0b20ff6230..636e13719a 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -328,7 +328,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1); + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels, 1); } } diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e42906e78b..e1eeefa755 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10712,38 +10712,49 @@ 3 RenderReflectionRes - - Comment - Reflection map resolution. - Persist - 1 - Type - S32 - Value - 64 - - RenderResolutionDivisor - - Comment - Divisor for rendering 3D scene at reduced resolution. - Persist - 1 - Type - U32 - Value - 1 - - RenderShaderLightingMaxLevel - - Comment - Max lighting level to use in the shader (class 3 is default, 2 is less lights, 1 is sun/moon only. Works around shader compiler bugs on certain platforms.) - Persist - 1 - Type - S32 - Value - 3 - + + Comment + Reflection map resolution. + Persist + 1 + Type + S32 + Value + 64 + + RenderReservedTextureIndices + + Comment + Count of texture indices to reserve for shadow and reflection maps when using indexed texture rendering. Probably only want to set from the login screen. + Persist + 1 + Type + S32 + Value + 14 + + RenderResolutionDivisor + + Comment + Divisor for rendering 3D scene at reduced resolution. + Persist + 1 + Type + U32 + Value + 1 + + RenderShaderLightingMaxLevel + + Comment + Max lighting level to use in the shader (class 3 is default, 2 is less lights, 1 is sun/moon only. Works around shader compiler bugs on certain platforms.) + Persist + 1 + Type + S32 + Value + 3 + RenderSkyAutoAdjustLegacy Comment diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 9418cead76..fd27010877 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -478,7 +478,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material) } } } - + return tex_setup; } @@ -668,7 +668,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo& params = **k; if ((bool)params.mAvatar != rigged) @@ -814,9 +814,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) current_shader->setMinimumAlpha(0.f); reset_minimum_alpha = true; } - + params.mVertexBuffer->setBuffer(); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + stop_glerror(); if (reset_minimum_alpha) { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 69e43bb458..ccee57cf69 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1855,7 +1855,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, S32* vp = (S32*) &val; *vp = index; - llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); + llassert(index < LLGLSLShader::sIndexedTextureChannels); LLVector4Logical mask; mask.clear(); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 289c0d7567..5144b28ce9 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -423,7 +423,10 @@ void LLViewerShaderMgr::setShaders() static LLCachedControl max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); // when using indexed texture rendering, leave some texture units available for shadow and reflection maps - LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits-12, (S32) max_texture_index), 1); + static LLCachedControl reserved_texture_units(gSavedSettings, "RenderReservedTextureIndices", 14); + + LLGLSLShader::sIndexedTextureChannels = + llclamp(max_texture_index, 1, gGLManager.mNumTextureImageUnits-reserved_texture_units); reentrance = true; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b886b922de..1b816b88fb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -6248,19 +6248,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace LLViewerTexture* last_tex = NULL; - S32 texture_index_channels = 1; - - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { - texture_index_channels = LLGLSLShader::sIndexedTextureChannels-1; //always reserve one for shiny for now just for simplicity; - } - - if (distance_sort) - { - texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; - } - - texture_index_channels = LLGLSLShader::sIndexedTextureChannels; + S32 texture_index_channels = LLGLSLShader::sIndexedTextureChannels; bool flexi = false; -- cgit v1.2.3 From 812e2cda54f14a1a6854dd7b9fdd2951932ba2fa Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Wed, 1 May 2024 14:37:50 -0500 Subject: #1382 Fix for scrubbing occlusion channel of ORM map (#1383) --- indra/newview/lltinygltfhelper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 49c35165e6..4e41f9959a 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -104,9 +104,9 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material, } } } - else + else if (material.occlusionTexture.index == -1) { - // no occlusion, make a white occlusion image + // no occlusion, make sure red channel of ORM is all 255 occlusion_img = new LLImageRaw(mr_img->getWidth(), mr_img->getHeight(), 3); occlusion_img->clear(255, 255, 255); copy_red_channel(occlusion_img, mr_img); -- cgit v1.2.3 From ca5e89d741b3618ab1dc681ecb6f75e5884988d7 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 8 May 2024 11:28:51 -0700 Subject: Even more mirror fixes. (#1429) #1271 Add support for mirrors that do not have avatars in them. It does this based on if the probe is set to dynamic or not. #1370 More optimization work to reduce GPU utilization. #1058 - Removed sim feature flag that was overriding mirrors enabled flags secondlife/viewer-private#128 - Locally cache the mirror probe #679 Add additional options to the build floater for mirror probes, including descriptions. --- indra/newview/featuretable.txt | 7 ++- indra/newview/featuretable_mac.txt | 11 ++-- indra/newview/llheroprobemanager.cpp | 73 +++++++++++++++------- indra/newview/llheroprobemanager.h | 2 +- indra/newview/llpanelvolume.cpp | 26 +++++--- indra/newview/llviewerregion.cpp | 8 --- indra/newview/llvovolume.cpp | 7 +++ .../newview/skins/default/xui/en/floater_tools.xml | 12 ++-- 8 files changed, 91 insertions(+), 55 deletions(-) (limited to 'indra') diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 3e1e235fcd..8950770172 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -75,6 +75,7 @@ RenderGLMultiThreadedTextures 1 0 RenderGLMultiThreadedMedia 1 1 RenderReflectionProbeResolution 1 128 RenderScreenSpaceReflections 1 1 +RenderMirrors 1 1 // @@ -251,8 +252,8 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 -RenderMirrors 1 0 -RenderHeroProbeResolution 1 1024 +RenderMirrors 1 1 +RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 8 RenderHeroProbeUpdateRate 1 2 RenderHeroProbeConservativeUpdateMultiplier 1 8 @@ -287,7 +288,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 -RenderMirrors 1 0 +RenderMirrors 1 1 RenderHeroProbeResolution 1 1024 RenderHeroProbeDistance 1 16 RenderHeroProbeUpdateRate 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 2ffefadcc1..8c71235f37 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -74,6 +74,7 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 2 RenderScreenSpaceReflections 1 1 RenderReflectionProbeLevel 1 3 +RenderMirrors 1 1 // // Low Graphics Settings @@ -249,8 +250,8 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 1 -RenderMirrors 1 0 -RenderHeroProbeResolution 1 1024 +RenderMirrors 1 1 +RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 8 RenderHeroProbeUpdateRate 1 2 RenderHeroProbeConservativeUpdateMultiplier 1 8 @@ -285,8 +286,8 @@ RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 2 -RenderMirrors 1 0 -RenderHeroProbeResolution 1 1024 +RenderMirrors 1 1 +RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 16 RenderHeroProbeUpdateRate 1 1 RenderHeroProbeConservativeUpdateMultiplier 1 4 @@ -322,7 +323,7 @@ RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 RenderReflectionProbeLevel 1 3 RenderMirrors 1 1 -RenderHeroProbeResolution 1 2048 +RenderHeroProbeResolution 1 1024 RenderHeroProbeDistance 1 16 RenderHeroProbeUpdateRate 1 1 RenderHeroProbeConservativeUpdateMultiplier 1 4 diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index dd29b416fb..55539a49d8 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -113,22 +113,40 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; F32 near_clip = 0.1f; + bool probe_present = false; + LLQuaternion cameraOrientation = LLViewerCamera::instance().getQuaternion(); + LLVector3 cameraDirection = LLVector3::z_axis * cameraOrientation; + if (mHeroVOList.size() > 0) { // Find our nearest hero candidate. - float last_distance = 99999.f; - + float camera_center_distance = 99999.f; for (auto vo : mHeroVOList) { if (vo && !vo->isDead() && vo->mDrawable.notNull()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); - if (distance < last_distance) + float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); + + if (distance > LLViewerCamera::instance().getFar()) + continue; + + LLVector4a center; + center.load3(vo->getPositionAgent().mV); + LLVector4a size; + + size.load3(vo->getScale().mV); + + bool visible = LLViewerCamera::instance().AABBInFrustum(center, size); + + if (distance < last_distance && center_distance < camera_center_distance && visible) { - mNearestHero = vo; - last_distance = distance; - } + probe_present = true; + mNearestHero = vo; + last_distance = distance; + camera_center_distance = center_distance; + } } else { @@ -136,6 +154,10 @@ void LLHeroProbeManager::update() } } + // Don't even try to do anything if we didn't find a single mirror present. + if (!probe_present) + return; + if (mNearestHero != nullptr && !mNearestHero->isDead() && mNearestHero->mDrawable.notNull()) { LLVector3 hero_pos = mNearestHero->getPositionAgent(); @@ -152,14 +174,12 @@ void LLHeroProbeManager::update() mCurrentClipPlane.setVec(hero_pos, face_normal); mMirrorPosition = hero_pos; mMirrorNormal = face_normal; - probe_pos.load3(point.mV); - // Collect the list of faces that need updating based upon the camera's rotation. - LLVector3 cam_direction = LLVector3(0, 0, 1) * LLViewerCamera::instance().getQuaternion(); - cam_direction.normalize(); + // Detect visible faces of a cube based on camera direction and distance + // Define the cube faces static LLVector3 cubeFaces[6] = { LLVector3(1, 0, 0), LLVector3(-1, 0, 0), @@ -169,17 +189,21 @@ void LLHeroProbeManager::update() LLVector3(0, 0, -1) }; + // Iterate through each face of the cube for (int i = 0; i < 6; i++) { - float shouldUpdate = fminf(1, (fmaxf(-1, cam_direction * cubeFaces[i]) * 0.5 + 0.5)); - - int updateRate = ceilf((1 - shouldUpdate) * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); - - // Chances are this is a face that's non-visible to the camera when it's being reflected. - // Set it to 0. It will be skipped below. - if (updateRate == gPipeline.RenderHeroProbeConservativeUpdateMultiplier) + float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; + + float updateRate; + if (cube_facing < 0.1f) + { updateRate = 0; - + } + else + { + updateRate = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); + } + mFaceUpdateList[i] = updateRate; } } @@ -199,6 +223,7 @@ void LLHeroProbeManager::update() static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); + if (mNearestHero != nullptr) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. @@ -208,13 +233,16 @@ void LLHeroProbeManager::update() gPipeline.mReflectionMapManager.mRadiancePass = true; mRenderingMirror = true; + + doOcclusion(); + for (U32 j = 0; j < mProbes.size(); j++) { for (U32 i = 0; i < 6; ++i) { if (mFaceUpdateList[i] > 0 && mCurrentProbeUpdateFrame % mFaceUpdateList[i] == 0) { - updateProbeFace(mProbes[j], i, near_clip); + updateProbeFace(mProbes[j], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip); mCurrentProbeUpdateFrame = 0; } } @@ -239,18 +267,17 @@ void LLHeroProbeManager::update() // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. // At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe. // In effect this simulates single-bounce lighting. -void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip) +void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip) { // hacky hot-swap of camera specific render targets gPipeline.mRT = &gPipeline.mHeroProbeRT; - probe->update(mRenderTarget.getWidth(), face, true, near_clip); + probe->update(mRenderTarget.getWidth(), face, is_dynamic, near_clip); gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -371,8 +398,6 @@ void LLHeroProbeManager::generateRadiance(LLReflectionMap* probe) static LLStaticHashedString sSourceIdx("sourceIdx"); { - - // generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map) gHeroRadianceGenProgram.bind(); mVertexBuffer->setBuffer(); diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index d5e720e8e8..5df146f2f1 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -116,7 +116,7 @@ private: // update the specified face of the specified probe - void updateProbeFace(LLReflectionMap* probe, U32 face, F32 near_clip); + void updateProbeFace(LLReflectionMap* probe, U32 face, bool is_dynamic, F32 near_clip); void generateRadiance(LLReflectionMap *probe); // list of active reflection maps diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 8d8263448d..91c33b461f 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -424,19 +424,21 @@ void LLPanelVolume::getState( ) volume_type = "Sphere"; } - std::string update_type; - if (volobjp->getReflectionProbeIsDynamic()) + + std::string update_type = "Static"; + + if (volobjp->getReflectionProbeIsDynamic() && !volobjp->getReflectionProbeIsMirror()) { update_type = "Dynamic"; } - else if (volobjp->getReflectionProbeIsMirror()) + else if (volobjp->getReflectionProbeIsMirror() && !volobjp->getReflectionProbeIsDynamic()) { update_type = "Mirror"; } - else - { - update_type = "Static"; + else if (volobjp->getReflectionProbeIsDynamic() && volobjp->getReflectionProbeIsMirror()) + { + update_type = "Dynamic Mirror"; } getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); @@ -1200,6 +1202,7 @@ void LLPanelVolume::onCopyLight() clipboard["reflection_probe"]["ambiance"] = volobjp->getReflectionProbeAmbiance(); clipboard["reflection_probe"]["near_clip"] = volobjp->getReflectionProbeNearClip(); clipboard["reflection_probe"]["dynamic"] = volobjp->getReflectionProbeIsDynamic(); + clipboard["reflection_probe"]["mirror"] = volobjp->getReflectionProbeIsMirror(); } mClipboardParams["light"] = clipboard; @@ -1257,6 +1260,7 @@ void LLPanelVolume::onPasteLight() volobjp->setReflectionProbeAmbiance((F32)clipboard["reflection_probe"]["ambiance"].asReal()); volobjp->setReflectionProbeNearClip((F32)clipboard["reflection_probe"]["near_clip"].asReal()); volobjp->setReflectionProbeIsDynamic(clipboard["reflection_probe"]["dynamic"].asBoolean()); + volobjp->setReflectionProbeIsMirror(clipboard["reflection_probe"]["mirror"].asBoolean()); } else { @@ -1428,11 +1432,13 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) std::string update_type = self->getChild("Probe Update Type")->getValue().asString(); - volobjp->setReflectionProbeIsDynamic(update_type == "Dynamic"); - volobjp->setReflectionProbeIsMirror(update_type == "Mirror"); + bool is_mirror = update_type.find("Mirror") != std::string::npos; + + volobjp->setReflectionProbeIsDynamic(update_type.find("Dynamic") != std::string::npos); + volobjp->setReflectionProbeIsMirror(is_mirror); - self->getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); - self->getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror"); + self->getChildView("Probe Ambiance")->setEnabled(!is_mirror); + self->getChildView("Probe Near Clip")->setEnabled(!is_mirror); std::string shape_type = self->getChild("Probe Volume Type")->getValue().asString(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 29dce088f5..61ab2791fb 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2469,14 +2469,6 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) gSavedSettings.setS32("max_texture_dimension_Y", 1024); } - bool mirrors_enabled = false; - if (features.has("MirrorsEnabled")) - { - mirrors_enabled = features["MirrorsEnabled"].asBoolean(); - } - - gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled); - if (features.has("PBRTerrainEnabled")) { bool enabled = features["PBRTerrainEnabled"]; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 1b816b88fb..a956814147 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3420,8 +3420,15 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) { if (param_block->getIsMirror() != is_mirror) { + LL_INFOS() << "Setting reflection probe mirror to " << is_mirror << LL_ENDL; param_block->setIsMirror(is_mirror); parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); + + if (!is_mirror) + gPipeline.mHeroProbeManager.unregisterViewerObject(this); + else + gPipeline.mHeroProbeManager.registerViewerObject(this); + return true; } } diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 3ee4a354d4..e43143c8c3 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2549,7 +2549,7 @@ even though the user gets a free copy. follows="left|top" name="Probe Volume Type" tool_tip="Choose the probe influence volume" - width="108"> + width="140"> + tool_tip="Determines how the probe updates. Static updates the slowest and without avatars. Dynamic updates more frequently, with avatars visible in the probes. Mirror (Environment) turns this probe into a realtime planar projected probe that only reflects the environment, but does not calculate ambiance. Mirror (Everything) is similar to Mirror (Environment), but it reflects particles and avatars." + width="140"> + Date: Wed, 8 May 2024 13:40:58 -0700 Subject: Fix for mirrors not functioning properly under water. (#1436) * #1165 Fix for clipping and culling for mirrors under water. --- indra/llimage/tests/llimageworker_test.cpp | 2 +- indra/llprimitive/llgltfmaterial.h | 12 +++++++----- indra/llprimitive/tests/llgltfmaterial_test.cpp | 2 +- indra/newview/pipeline.cpp | 3 ++- 4 files changed, 11 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 0a97b739b0..ffcd7d257f 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -98,7 +98,7 @@ namespace tut done = res; *done = false; } - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32) { *done = true; } diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index d14ae6970b..855cb58832 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -122,9 +122,10 @@ public: F32 mRoughnessFactor = 1.f; F32 mAlphaCutoff = 0.5f; - bool mDoubleSided = false; AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE; + bool mDoubleSided = false; + // override specific flags for state that can't use off-by-epsilon or UUID hack bool mOverrideDoubleSided = false; bool mOverrideAlphaMode = false; @@ -139,6 +140,11 @@ public: // heightmaps cannot currently be described as finite enclosed // volumes. // See also LLPanelRegionTerrainInfo::validateMaterials + // These fields are local to viewer and are a part of local bitmap support + typedef std::map local_tex_map_t; + local_tex_map_t mTrackingIdToLocalTexture; + +public: // get a UUID based on a hash of this LLGLTFMaterial LLUUID getHash() const; @@ -240,10 +246,6 @@ public: virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id); virtual void updateTextureTracking(); - // These fields are local to viewer and are a part of local bitmap support - typedef std::map local_tex_map_t; - local_tex_map_t mTrackingIdToLocalTexture; - protected: static LLVector2 vec2FromJson(const std::map& object, const char* key, const LLVector2& default_value); static F32 floatFromJson(const std::map& object, const char* key, const F32 default_value); diff --git a/indra/llprimitive/tests/llgltfmaterial_test.cpp b/indra/llprimitive/tests/llgltfmaterial_test.cpp index 88b6fae3a7..b56c9ab4f5 100644 --- a/indra/llprimitive/tests/llgltfmaterial_test.cpp +++ b/indra/llprimitive/tests/llgltfmaterial_test.cpp @@ -143,7 +143,7 @@ namespace tut #if LL_WINDOWS // If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial) // This test result will vary between compilers, so only test a single platform - ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 216); + ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 224); #endif #endif ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 341c9706f8..8b1e46343b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2269,7 +2269,8 @@ static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); // static bool LLPipeline::isWaterClip() { - return (!sRenderTransparentWater || gCubeSnapshot) && !sRenderingHUDs; + // We always pretend that we're not clipping water when rendering mirrors. + return (gPipeline.mHeroProbeManager.isMirrorPass()) ? false : (!sRenderTransparentWater || gCubeSnapshot) && !sRenderingHUDs; } void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) -- cgit v1.2.3 From d5378e9cab2024237b4d900057ba59f7f22f4594 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 9 May 2024 01:54:03 +0300 Subject: viewer-private#236 Don't block removal of marketplace folders Marketplace is not visible outside of own floater and that floater will do an extra warning when deleting listings that have additional data. --- indra/newview/llinventoryfunctions.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index c8aa235506..016b0880eb 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -843,12 +843,6 @@ bool get_is_category_and_children_removable(LLInventoryModel* model, const LLUUI return false; } - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) - { - return false; - } - LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; model->collectDescendents( -- cgit v1.2.3 From 82d713782529074b03720833038cb0df2b8bcffd Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 14 May 2024 08:50:04 +0300 Subject: #1457 Fix the tests on mac --- indra/llimage/tests/llimageworker_test.cpp | 3 ++- indra/test/test.cpp | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 49fc1afd82..2568adf89e 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -68,6 +68,7 @@ U8* LLImageRaw::allocateData(S32 size) { return NULL; } U8* LLImageRaw::reallocateData(S32 size) { return NULL; } const U8* LLImageBase::getData() const { return NULL; } U8* LLImageBase::getData() { return NULL; } +const std::string& LLImage::getLastThreadError() { static std::string msg; return msg; } // End Stubbing // ------------------------------------------------------------------------------------------- @@ -98,7 +99,7 @@ namespace tut done = res; *done = false; } - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32) + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { *done = true; } diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 21232e88f5..61a4eb07c5 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -54,12 +54,6 @@ #endif #ifndef LL_WINDOWS - -typedef struct { - void *re_pcre; - size_t re_nsub; - size_t re_erroffset; -} regex_t; #include #include #endif -- cgit v1.2.3 From bb3c36f5cbc0c3b542045fd27255eee24e03da22 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 14 May 2024 21:34:34 -0400 Subject: Increment viewer version to 7.1.8 following promotion of secondlife/viewer #705: Maintenance X --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 2380dcfd47..2fe040f424 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.1.7 +7.1.8 -- cgit v1.2.3 From b06a99f7c76950484972e25d9dbbee8660a6a6c3 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 15 May 2024 12:47:27 +0300 Subject: Post-merge spaces fix --- indra/llcommon/indra_constants.cpp | 56 +- indra/llcommon/indra_constants.h | 338 +- indra/llcommon/llstrider.h | 60 +- indra/llimage/llimage.cpp | 3410 ++--- indra/llimage/llimage.h | 408 +- indra/llinventory/llsettingssky.cpp | 146 +- indra/llmath/llcamera.h | 324 +- indra/llmath/llmatrix4a.h | 218 +- indra/llmath/llvolume.cpp | 12538 ++++++++-------- indra/llmath/llvolume.h | 1688 +-- indra/llmath/llvolumeoctree.cpp | 366 +- indra/llmath/llvolumeoctree.h | 132 +- indra/llplugin/llpluginprocessparent.cpp | 1728 +-- indra/llprimitive/llprimitive.cpp | 2892 ++-- indra/llprimitive/llprimitive.h | 894 +- indra/llprimitive/lltextureentry.cpp | 714 +- indra/llrender/llglslshader.cpp | 62 +- indra/llrender/llglslshader.h | 10 +- indra/llrender/llgltexture.cpp | 328 +- indra/llrender/llgltexture.h | 254 +- indra/llrender/llrender.cpp | 2618 ++-- indra/llrender/llrendertarget.h | 176 +- indra/llrender/llshadermgr.cpp | 1856 +-- indra/llrender/llshadermgr.h | 50 +- indra/llrender/llvertexbuffer.cpp | 634 +- indra/llrender/llvertexbuffer.h | 276 +- .../shaders/class1/deferred/avatarEyesV.glsl | 24 +- .../shaders/class1/deferred/avatarF.glsl | 34 +- .../shaders/class1/deferred/avatarV.glsl | 52 +- .../shaders/class1/deferred/bumpF.glsl | 50 +- .../shaders/class1/deferred/bumpV.glsl | 42 +- .../shaders/class1/deferred/deferredUtil.glsl | 172 +- .../shaders/class1/deferred/diffuseAlphaMaskF.glsl | 34 +- .../class1/deferred/diffuseAlphaMaskIndexedF.glsl | 34 +- .../class1/deferred/diffuseAlphaMaskNoColorF.glsl | 36 +- .../shaders/class1/deferred/diffuseF.glsl | 26 +- .../shaders/class1/deferred/diffuseIndexedF.glsl | 26 +- .../shaders/class1/deferred/diffuseV.glsl | 22 +- .../shaders/class1/deferred/impostorF.glsl | 32 +- .../shaders/class1/deferred/materialV.glsl | 54 +- .../shaders/class1/deferred/pbropaqueV.glsl | 42 +- .../shaders/class1/deferred/pbrterrainV.glsl | 18 +- .../class1/deferred/postDeferredGammaCorrect.glsl | 66 +- .../shaders/class1/deferred/treeF.glsl | 30 +- .../shaders/class1/deferred/treeV.glsl | 22 +- .../shaders/class1/interface/normaldebugF.glsl | 14 +- .../shaders/class1/interface/normaldebugV.glsl | 16 +- .../shaders/class1/interface/radianceGenF.glsl | 146 +- .../app_settings/shaders/class1/objects/bumpF.glsl | 18 +- .../app_settings/shaders/class1/objects/bumpV.glsl | 18 +- .../shaders/class2/deferred/alphaF.glsl | 70 +- .../shaders/class3/deferred/fullbrightShinyF.glsl | 28 +- .../shaders/class3/deferred/materialF.glsl | 24 +- .../shaders/class3/environment/underWaterF.glsl | 36 +- .../shaders/class3/environment/waterF.glsl | 38 +- indra/newview/gltf/asset.h | 18 +- indra/newview/gltfscenemanager.cpp | 20 +- indra/newview/gltfscenemanager.h | 4 +- indra/newview/llagentbenefits.cpp | 224 +- indra/newview/llagentbenefits.h | 74 +- indra/newview/llagentcamera.cpp | 4606 +++--- indra/newview/llappviewer.cpp | 7020 ++++----- indra/newview/lldrawable.h | 502 +- indra/newview/lldrawpool.cpp | 424 +- indra/newview/lldrawpool.h | 370 +- indra/newview/lldrawpoolalpha.cpp | 172 +- indra/newview/lldrawpoolbump.cpp | 1380 +- indra/newview/lldrawpoolterrain.cpp | 1288 +- indra/newview/lldrawpoolterrain.h | 76 +- indra/newview/lldrawpooltree.cpp | 60 +- indra/newview/lldrawpoolwlsky.cpp | 160 +- indra/newview/lldynamictexture.cpp | 286 +- indra/newview/llenvironment.cpp | 90 +- indra/newview/llface.cpp | 3362 ++--- indra/newview/llfeaturemanager.cpp | 976 +- indra/newview/llfilepicker.cpp | 2080 +-- indra/newview/llfilepicker.h | 206 +- indra/newview/llfloaterimagepreview.cpp | 1276 +- indra/newview/llfloaterimagepreview.h | 142 +- indra/newview/llfloaternamedesc.h | 50 +- indra/newview/llfloaterregioninfo.cpp | 5044 +++---- indra/newview/llfloaterregioninfo.h | 596 +- indra/newview/llgltfmaterialpreviewmgr.cpp | 38 +- indra/newview/llheroprobemanager.cpp | 78 +- indra/newview/llmanip.cpp | 864 +- indra/newview/llmaniprotate.cpp | 3292 ++--- indra/newview/llmaniptranslate.cpp | 4082 ++--- indra/newview/llmaterialeditor.cpp | 82 +- indra/newview/llpanelface.cpp | 3930 ++--- indra/newview/llpanelface.h | 808 +- indra/newview/llpanelmaininventory.cpp | 2194 +-- indra/newview/llpanelvolume.cpp | 1520 +- indra/newview/llselectmgr.cpp | 11874 +++++++-------- indra/newview/llselectmgr.h | 1514 +- indra/newview/llsettingsvo.cpp | 82 +- indra/newview/llspatialpartition.cpp | 6024 ++++---- indra/newview/llsurface.cpp | 2018 +-- indra/newview/llsurface.h | 270 +- indra/newview/llsurfacepatch.cpp | 1846 +-- indra/newview/llsurfacepatch.h | 220 +- indra/newview/lltexturectrl.cpp | 2236 +-- indra/newview/lltexturectrl.h | 500 +- indra/newview/lltooldraganddrop.cpp | 4868 +++--- indra/newview/lltoolselect.cpp | 390 +- indra/newview/llviewerassetupload.cpp | 168 +- indra/newview/llviewercamera.cpp | 1364 +- indra/newview/llviewercontrol.cpp | 476 +- indra/newview/llviewerdisplay.cpp | 2442 +-- indra/newview/llviewermenu.cpp | 12128 +++++++-------- indra/newview/llviewermenufile.cpp | 1400 +- indra/newview/llviewerobject.cpp | 10118 ++++++------- indra/newview/llviewerobject.h | 1414 +- indra/newview/llviewerregion.cpp | 4342 +++--- indra/newview/llviewerregion.h | 934 +- indra/newview/llviewershadermgr.cpp | 2694 ++-- indra/newview/llviewershadermgr.h | 356 +- indra/newview/llviewertexture.cpp | 5440 +++---- indra/newview/llviewertexture.h | 1128 +- indra/newview/llviewerwindow.cpp | 8920 +++++------ indra/newview/llviewerwindow.h | 890 +- indra/newview/llvlcomposition.cpp | 596 +- indra/newview/llvlcomposition.h | 100 +- indra/newview/llvoavatar.cpp | 14770 +++++++++---------- indra/newview/llvoavatarself.cpp | 4108 +++--- indra/newview/llvocache.cpp | 2362 +-- indra/newview/llvocache.h | 420 +- indra/newview/llvosurfacepatch.cpp | 1584 +- indra/newview/llvosurfacepatch.h | 168 +- indra/newview/llvovolume.cpp | 8366 +++++------ indra/newview/llvovolume.h | 596 +- indra/newview/llxmlrpclistener.cpp | 68 +- indra/newview/pipeline.cpp | 13108 ++++++++-------- indra/newview/pipeline.h | 1518 +- 133 files changed, 107307 insertions(+), 107307 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp index 39e232e480..329dfcbe37 100644 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp @@ -1,25 +1,25 @@ -/** +/** * @file indra_constants.cpp * @brief some useful short term constants for Indra * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -38,39 +38,39 @@ const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1"); // Maintenance's group id. const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd"); // Grass Images -const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER +const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER -const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER +const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER -const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver -const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver -const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver -const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver -const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver +const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver +const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver +const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver +const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver +const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver -const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver +const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver const LLUUID IMG_WHITE ("5748decc-f629-461c-9a36-a35a221fe21f"); // dataserver -const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver -const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver -const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver -const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver -const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver +const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver +const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver +const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver +const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver +const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver -const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver -const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver +const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver +const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver -const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER -const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER -const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER +const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER +const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER +const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER -const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER -const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER -const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER -const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER +const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER +const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER +const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER +const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER -const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER +const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER const LLUUID DEFAULT_OBJECT_TEXTURE ("89556747-24cb-43ed-920b-47caed15465f"); // On dataserver const LLUUID DEFAULT_OBJECT_SPECULAR ("87e0e8f7-8729-1ea8-cfc9-8915773009db"); // On dataserver diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index a4b2efef98..d2de88ff0a 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -1,25 +1,25 @@ -/** +/** * @file indra_constants.h * @brief some useful short term constants for Indra * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -37,21 +37,21 @@ static const U32 REGION_WIDTH_U32 = 256; const F32 REGION_HEIGHT_METERS = 4096.f; -const F32 DEFAULT_AGENT_DEPTH = 0.45f; -const F32 DEFAULT_AGENT_WIDTH = 0.60f; -const F32 DEFAULT_AGENT_HEIGHT = 1.9f; +const F32 DEFAULT_AGENT_DEPTH = 0.45f; +const F32 DEFAULT_AGENT_WIDTH = 0.60f; +const F32 DEFAULT_AGENT_HEIGHT = 1.9f; enum ETerrainBrushType { - // the valid brush numbers cannot be reordered, because they - // are used in the binary LSL format as arguments to llModifyLand() - E_LANDBRUSH_LEVEL = 0, - E_LANDBRUSH_RAISE = 1, - E_LANDBRUSH_LOWER = 2, - E_LANDBRUSH_SMOOTH = 3, - E_LANDBRUSH_NOISE = 4, - E_LANDBRUSH_REVERT = 5, - E_LANDBRUSH_INVALID = 6 + // the valid brush numbers cannot be reordered, because they + // are used in the binary LSL format as arguments to llModifyLand() + E_LANDBRUSH_LEVEL = 0, + E_LANDBRUSH_RAISE = 1, + E_LANDBRUSH_LOWER = 2, + E_LANDBRUSH_SMOOTH = 3, + E_LANDBRUSH_NOISE = 4, + E_LANDBRUSH_REVERT = 5, + E_LANDBRUSH_INVALID = 6 }; enum EMouseClickType{ @@ -67,101 +67,101 @@ enum EMouseClickType{ // keys // Bit masks for various keyboard modifier keys. -const MASK MASK_NONE = 0x0000; -const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs -const MASK MASK_ALT = 0x0002; -const MASK MASK_SHIFT = 0x0004; +const MASK MASK_NONE = 0x0000; +const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs +const MASK MASK_ALT = 0x0002; +const MASK MASK_SHIFT = 0x0004; const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys -const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows -const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; +const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows +const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL; // Special keys go into >128 -const KEY KEY_SPECIAL = 0x80; // special keys start here -const KEY KEY_RETURN = 0x81; -const KEY KEY_LEFT = 0x82; -const KEY KEY_RIGHT = 0x83; -const KEY KEY_UP = 0x84; -const KEY KEY_DOWN = 0x85; -const KEY KEY_ESCAPE = 0x86; +const KEY KEY_SPECIAL = 0x80; // special keys start here +const KEY KEY_RETURN = 0x81; +const KEY KEY_LEFT = 0x82; +const KEY KEY_RIGHT = 0x83; +const KEY KEY_UP = 0x84; +const KEY KEY_DOWN = 0x85; +const KEY KEY_ESCAPE = 0x86; const KEY KEY_BACKSPACE =0x87; -const KEY KEY_DELETE = 0x88; -const KEY KEY_SHIFT = 0x89; -const KEY KEY_CONTROL = 0x8A; -const KEY KEY_ALT = 0x8B; -const KEY KEY_HOME = 0x8C; -const KEY KEY_END = 0x8D; +const KEY KEY_DELETE = 0x88; +const KEY KEY_SHIFT = 0x89; +const KEY KEY_CONTROL = 0x8A; +const KEY KEY_ALT = 0x8B; +const KEY KEY_HOME = 0x8C; +const KEY KEY_END = 0x8D; const KEY KEY_PAGE_UP = 0x8E; const KEY KEY_PAGE_DOWN = 0x8F; const KEY KEY_HYPHEN = 0x90; const KEY KEY_EQUALS = 0x91; const KEY KEY_INSERT = 0x92; const KEY KEY_CAPSLOCK = 0x93; -const KEY KEY_TAB = 0x94; -const KEY KEY_ADD = 0x95; +const KEY KEY_TAB = 0x94; +const KEY KEY_ADD = 0x95; const KEY KEY_SUBTRACT =0x96; const KEY KEY_MULTIPLY =0x97; -const KEY KEY_DIVIDE = 0x98; -const KEY KEY_F1 = 0xA1; -const KEY KEY_F2 = 0xA2; -const KEY KEY_F3 = 0xA3; -const KEY KEY_F4 = 0xA4; -const KEY KEY_F5 = 0xA5; -const KEY KEY_F6 = 0xA6; -const KEY KEY_F7 = 0xA7; -const KEY KEY_F8 = 0xA8; -const KEY KEY_F9 = 0xA9; -const KEY KEY_F10 = 0xAA; -const KEY KEY_F11 = 0xAB; -const KEY KEY_F12 = 0xAC; - -const KEY KEY_PAD_UP = 0xC0; -const KEY KEY_PAD_DOWN = 0xC1; -const KEY KEY_PAD_LEFT = 0xC2; -const KEY KEY_PAD_RIGHT = 0xC3; -const KEY KEY_PAD_HOME = 0xC4; -const KEY KEY_PAD_END = 0xC5; -const KEY KEY_PAD_PGUP = 0xC6; -const KEY KEY_PAD_PGDN = 0xC7; -const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle -const KEY KEY_PAD_INS = 0xC9; -const KEY KEY_PAD_DEL = 0xCA; -const KEY KEY_PAD_RETURN = 0xCB; -const KEY KEY_PAD_ADD = 0xCC; // not used -const KEY KEY_PAD_SUBTRACT = 0xCD; // not used +const KEY KEY_DIVIDE = 0x98; +const KEY KEY_F1 = 0xA1; +const KEY KEY_F2 = 0xA2; +const KEY KEY_F3 = 0xA3; +const KEY KEY_F4 = 0xA4; +const KEY KEY_F5 = 0xA5; +const KEY KEY_F6 = 0xA6; +const KEY KEY_F7 = 0xA7; +const KEY KEY_F8 = 0xA8; +const KEY KEY_F9 = 0xA9; +const KEY KEY_F10 = 0xAA; +const KEY KEY_F11 = 0xAB; +const KEY KEY_F12 = 0xAC; + +const KEY KEY_PAD_UP = 0xC0; +const KEY KEY_PAD_DOWN = 0xC1; +const KEY KEY_PAD_LEFT = 0xC2; +const KEY KEY_PAD_RIGHT = 0xC3; +const KEY KEY_PAD_HOME = 0xC4; +const KEY KEY_PAD_END = 0xC5; +const KEY KEY_PAD_PGUP = 0xC6; +const KEY KEY_PAD_PGDN = 0xC7; +const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle +const KEY KEY_PAD_INS = 0xC9; +const KEY KEY_PAD_DEL = 0xCA; +const KEY KEY_PAD_RETURN = 0xCB; +const KEY KEY_PAD_ADD = 0xCC; // not used +const KEY KEY_PAD_SUBTRACT = 0xCD; // not used const KEY KEY_PAD_MULTIPLY = 0xCE; // not used -const KEY KEY_PAD_DIVIDE = 0xCF; // not used - -const KEY KEY_BUTTON0 = 0xD0; -const KEY KEY_BUTTON1 = 0xD1; -const KEY KEY_BUTTON2 = 0xD2; -const KEY KEY_BUTTON3 = 0xD3; -const KEY KEY_BUTTON4 = 0xD4; -const KEY KEY_BUTTON5 = 0xD5; -const KEY KEY_BUTTON6 = 0xD6; -const KEY KEY_BUTTON7 = 0xD7; -const KEY KEY_BUTTON8 = 0xD8; -const KEY KEY_BUTTON9 = 0xD9; -const KEY KEY_BUTTON10 = 0xDA; -const KEY KEY_BUTTON11 = 0xDB; -const KEY KEY_BUTTON12 = 0xDC; -const KEY KEY_BUTTON13 = 0xDD; -const KEY KEY_BUTTON14 = 0xDE; -const KEY KEY_BUTTON15 = 0xDF; - -const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. +const KEY KEY_PAD_DIVIDE = 0xCF; // not used + +const KEY KEY_BUTTON0 = 0xD0; +const KEY KEY_BUTTON1 = 0xD1; +const KEY KEY_BUTTON2 = 0xD2; +const KEY KEY_BUTTON3 = 0xD3; +const KEY KEY_BUTTON4 = 0xD4; +const KEY KEY_BUTTON5 = 0xD5; +const KEY KEY_BUTTON6 = 0xD6; +const KEY KEY_BUTTON7 = 0xD7; +const KEY KEY_BUTTON8 = 0xD8; +const KEY KEY_BUTTON9 = 0xD9; +const KEY KEY_BUTTON10 = 0xDA; +const KEY KEY_BUTTON11 = 0xDB; +const KEY KEY_BUTTON12 = 0xDC; +const KEY KEY_BUTTON13 = 0xDD; +const KEY KEY_BUTTON14 = 0xDE; +const KEY KEY_BUTTON15 = 0xDF; + +const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only. const S32 KEY_COUNT = 256; -const F32 DEFAULT_WATER_HEIGHT = 20.0f; +const F32 DEFAULT_WATER_HEIGHT = 20.0f; // Maturity ratings for simulators -const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG -const U8 SIM_ACCESS_PG = 13; -const U8 SIM_ACCESS_MATURE = 21; -const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only -const U8 SIM_ACCESS_DOWN = 254; -const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; +const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG +const U8 SIM_ACCESS_PG = 13; +const U8 SIM_ACCESS_MATURE = 21; +const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only +const U8 SIM_ACCESS_DOWN = 254; +const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; // attachment constants const U8 ATTACHMENT_ADD = 0x80; @@ -260,84 +260,84 @@ const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13; const S32 CHAT_CHANNEL_DEBUG = S32_MAX; // agent constants -const U32 CONTROL_AT_POS_INDEX = 0; -const U32 CONTROL_AT_NEG_INDEX = 1; -const U32 CONTROL_LEFT_POS_INDEX = 2; -const U32 CONTROL_LEFT_NEG_INDEX = 3; -const U32 CONTROL_UP_POS_INDEX = 4; -const U32 CONTROL_UP_NEG_INDEX = 5; -const U32 CONTROL_PITCH_POS_INDEX = 6; -const U32 CONTROL_PITCH_NEG_INDEX = 7; -const U32 CONTROL_YAW_POS_INDEX = 8; -const U32 CONTROL_YAW_NEG_INDEX = 9; -const U32 CONTROL_FAST_AT_INDEX = 10; -const U32 CONTROL_FAST_LEFT_INDEX = 11; -const U32 CONTROL_FAST_UP_INDEX = 12; -const U32 CONTROL_FLY_INDEX = 13; -const U32 CONTROL_STOP_INDEX = 14; -const U32 CONTROL_FINISH_ANIM_INDEX = 15; -const U32 CONTROL_STAND_UP_INDEX = 16; -const U32 CONTROL_SIT_ON_GROUND_INDEX = 17; -const U32 CONTROL_MOUSELOOK_INDEX = 18; -const U32 CONTROL_NUDGE_AT_POS_INDEX = 19; -const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; -const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; -const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; -const U32 CONTROL_NUDGE_UP_POS_INDEX = 23; -const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; -const U32 CONTROL_TURN_LEFT_INDEX = 25; -const U32 CONTROL_TURN_RIGHT_INDEX = 26; -const U32 CONTROL_AWAY_INDEX = 27; -const U32 CONTROL_LBUTTON_DOWN_INDEX = 28; -const U32 CONTROL_LBUTTON_UP_INDEX = 29; -const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; -const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; -const U32 TOTAL_CONTROLS = 32; - -const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 -const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 -const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 -const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 -const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 -const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 -const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 -const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 -const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 -const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 - -const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 -const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 -const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 - -const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 -const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 -const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 -const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 -const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 -const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 - -const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 -const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 -const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 -const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 -const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 -const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 -const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 -const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 - -const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 - -const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 -const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 -const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 -const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 - -// move these up so that we can hide them in "State" for object updates +const U32 CONTROL_AT_POS_INDEX = 0; +const U32 CONTROL_AT_NEG_INDEX = 1; +const U32 CONTROL_LEFT_POS_INDEX = 2; +const U32 CONTROL_LEFT_NEG_INDEX = 3; +const U32 CONTROL_UP_POS_INDEX = 4; +const U32 CONTROL_UP_NEG_INDEX = 5; +const U32 CONTROL_PITCH_POS_INDEX = 6; +const U32 CONTROL_PITCH_NEG_INDEX = 7; +const U32 CONTROL_YAW_POS_INDEX = 8; +const U32 CONTROL_YAW_NEG_INDEX = 9; +const U32 CONTROL_FAST_AT_INDEX = 10; +const U32 CONTROL_FAST_LEFT_INDEX = 11; +const U32 CONTROL_FAST_UP_INDEX = 12; +const U32 CONTROL_FLY_INDEX = 13; +const U32 CONTROL_STOP_INDEX = 14; +const U32 CONTROL_FINISH_ANIM_INDEX = 15; +const U32 CONTROL_STAND_UP_INDEX = 16; +const U32 CONTROL_SIT_ON_GROUND_INDEX = 17; +const U32 CONTROL_MOUSELOOK_INDEX = 18; +const U32 CONTROL_NUDGE_AT_POS_INDEX = 19; +const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20; +const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21; +const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22; +const U32 CONTROL_NUDGE_UP_POS_INDEX = 23; +const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24; +const U32 CONTROL_TURN_LEFT_INDEX = 25; +const U32 CONTROL_TURN_RIGHT_INDEX = 26; +const U32 CONTROL_AWAY_INDEX = 27; +const U32 CONTROL_LBUTTON_DOWN_INDEX = 28; +const U32 CONTROL_LBUTTON_UP_INDEX = 29; +const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30; +const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31; +const U32 TOTAL_CONTROLS = 32; + +const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001 +const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002 +const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004 +const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008 +const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010 +const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020 +const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040 +const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080 +const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100 +const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200 + +const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400 +const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800 +const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000 + +const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000 +const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000 +const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000 +const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000 +const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000 +const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000 + +const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000 +const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000 +const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000 +const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000 +const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000 +const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000 +const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000 +const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000 + +const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000 + +const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000 +const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000 +const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000 +const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000 + +// move these up so that we can hide them in "State" for object updates // (for now) -const U32 AGENT_ATTACH_OFFSET = 4; -const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; +const U32 AGENT_ATTACH_OFFSET = 4; +const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET; -// RN: this method swaps the upper and lower nibbles to maintain backward +// RN: this method swaps the upper and lower nibbles to maintain backward // compatibility with old objects that only used the upper nibble #define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4))) diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index e7522484e6..06cf8d3480 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -1,24 +1,24 @@ -/** +/** * @file llstrider.h * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -30,38 +30,38 @@ template class LLStrider { - union - { - Object* mObjectp; - U8* mBytep; - }; - U32 mSkip; + union + { + Object* mObjectp; + U8* mBytep; + }; + U32 mSkip; public: - LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); } + LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); } LLStrider(Object* first) { mObjectp = first; mSkip = sizeof(Object); } - ~LLStrider() { } + ~LLStrider() { } - const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} - void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} + void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} - LLStrider operator+(const S32& index) - { - LLStrider ret; - ret.mBytep = mBytep + mSkip*index; - ret.mSkip = mSkip; + LLStrider operator+(const S32& index) + { + LLStrider ret; + ret.mBytep = mBytep + mSkip*index; + ret.mSkip = mSkip; - return ret; - } + return ret; + } - void skip(const U32 index) { mBytep += mSkip*index;} - U32 getSkip() const { return mSkip; } - Object* get() { return mObjectp; } - Object* operator->() { return mObjectp; } - Object& operator *() { return *mObjectp; } - Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } - Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } + void skip(const U32 index) { mBytep += mSkip*index;} + U32 getSkip() const { return mSkip; } + Object* get() { return mObjectp; } + Object* operator->() { return mObjectp; } + Object& operator *() { return *mObjectp; } + Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } + Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } - Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } + Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } }; #endif // LL_LLSTRIDER_H diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ed8f36286f..864315d0ff 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llimage.cpp * @brief Base class for images. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -54,40 +54,40 @@ #define _UNROL_GEN_TPL_comma_1 BOOST_PP_COMMA() //.................................................................................. #define _UNROL_GEN_TPL_ARGS_macro(z,n,seq) \ - BOOST_PP_CAT(_UNROL_GEN_TPL_arg_, BOOST_PP_MOD(n, 2))(BOOST_PP_SEQ_ELEM(n, seq)) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) + BOOST_PP_CAT(_UNROL_GEN_TPL_arg_, BOOST_PP_MOD(n, 2))(BOOST_PP_SEQ_ELEM(n, seq)) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) #define _UNROL_GEN_TPL_ARGS(seq) \ - BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_ARGS_macro, seq) + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_ARGS_macro, seq) //.................................................................................. #define _UNROL_GEN_TPL_TYPE_ARGS_macro(z,n,seq) \ - BOOST_PP_SEQ_ELEM(n, seq) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) + BOOST_PP_SEQ_ELEM(n, seq) BOOST_PP_CAT(_UNROL_GEN_TPL_comma_, BOOST_PP_AND(BOOST_PP_MOD(n, 2), BOOST_PP_NOT_EQUAL(BOOST_PP_INC(n), BOOST_PP_SEQ_SIZE(seq)))) #define _UNROL_GEN_TPL_TYPE_ARGS(seq) \ - BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_TYPE_ARGS_macro, seq) + BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(seq), _UNROL_GEN_TPL_TYPE_ARGS_macro, seq) //.................................................................................. #define _UNROLL_GEN_TPL_foreach_ee(z, n, seq) \ - executor(_UNROL_GEN_TPL_ARGS(seq)); + executor(_UNROL_GEN_TPL_ARGS(seq)); #define _UNROLL_GEN_TPL(name, args_seq, operation, spec) \ - template<> struct name { \ - private: \ - template inline void executor(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ - BOOST_PP_SEQ_ENUM(operation) ; \ - } \ - public: \ - inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ - BOOST_PP_REPEAT(spec, _UNROLL_GEN_TPL_foreach_ee, args_seq) \ - } \ + template<> struct name { \ + private: \ + template inline void executor(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ + BOOST_PP_SEQ_ENUM(operation) ; \ + } \ + public: \ + inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { \ + BOOST_PP_REPEAT(spec, _UNROLL_GEN_TPL_foreach_ee, args_seq) \ + } \ }; //.................................................................................. #define _UNROLL_GEN_TPL_foreach_seq_macro(r, data, elem) \ - _UNROLL_GEN_TPL(BOOST_PP_SEQ_ELEM(0, data), BOOST_PP_SEQ_ELEM(1, data), BOOST_PP_SEQ_ELEM(2, data), elem) + _UNROLL_GEN_TPL(BOOST_PP_SEQ_ELEM(0, data), BOOST_PP_SEQ_ELEM(1, data), BOOST_PP_SEQ_ELEM(2, data), elem) #define UNROLL_GEN_TPL(name, args_seq, operation, spec_seq) \ - /*general specialization - should not be implemented!*/ \ - template struct name { inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { /*static_assert(!"Should not be instantiated.");*/ } }; \ - BOOST_PP_SEQ_FOR_EACH(_UNROLL_GEN_TPL_foreach_seq_macro, (name)(args_seq)(operation), spec_seq) + /*general specialization - should not be implemented!*/ \ + template struct name { inline void operator()(_UNROL_GEN_TPL_TYPE_ARGS(args_seq)) { /*static_assert(!"Should not be instantiated.");*/ } }; \ + BOOST_PP_SEQ_FOR_EACH(_UNROLL_GEN_TPL_foreach_seq_macro, (name)(args_seq)(operation), spec_seq) //.................................................................................. //.................................................................................. @@ -123,460 +123,460 @@ UNROLL_GEN_TPL(uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff, (U8 *&)(dptr)(S3 template -struct scale_info +struct scale_info { public: - std::vector xpoints; - std::vector ystrides; - std::vector xapoints, yapoints; - S32 xup_yup; + std::vector xpoints; + std::vector ystrides; + std::vector xapoints, yapoints; + S32 xup_yup; public: - //unrolling loop types declaration - typedef uroll_zeroze_cx_comp uroll_zeroze_cx_comp_t; - typedef uroll_comp_rshftasgn_constval uroll_comp_rshftasgn_constval_t; - typedef uroll_comp_asgn_cx_rshft_cval_all_mul_val uroll_comp_asgn_cx_rshft_cval_all_mul_val_t; - typedef uroll_comp_plusasgn_cx_rshft_cval_all_mul_val uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t; - typedef uroll_inp_plusasgn_pix_mul_val uroll_inp_plusasgn_pix_mul_val_t; - typedef uroll_inp_asgn_pix_mul_val uroll_inp_asgn_pix_mul_val_t; - typedef uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t; - typedef uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t; - typedef uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t; - typedef uroll_uref_dptr_inc_asgn_comp_and_ff uroll_uref_dptr_inc_asgn_comp_and_ff_t; - typedef uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t; - typedef uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t; + //unrolling loop types declaration + typedef uroll_zeroze_cx_comp uroll_zeroze_cx_comp_t; + typedef uroll_comp_rshftasgn_constval uroll_comp_rshftasgn_constval_t; + typedef uroll_comp_asgn_cx_rshft_cval_all_mul_val uroll_comp_asgn_cx_rshft_cval_all_mul_val_t; + typedef uroll_comp_plusasgn_cx_rshft_cval_all_mul_val uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t; + typedef uroll_inp_plusasgn_pix_mul_val uroll_inp_plusasgn_pix_mul_val_t; + typedef uroll_inp_asgn_pix_mul_val uroll_inp_asgn_pix_mul_val_t; + typedef uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t; + typedef uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t; + typedef uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t; + typedef uroll_uref_dptr_inc_asgn_comp_and_ff uroll_uref_dptr_inc_asgn_comp_and_ff_t; + typedef uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t; + typedef uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t; public: - scale_info(const U8 *src, U32 srcW, U32 srcH, U32 dstW, U32 dstH, U32 srcStride) - : xup_yup((dstW >= srcW) + ((dstH >= srcH) << 1)) - { - calc_x_points(srcW, dstW); - calc_y_strides(src, srcStride, srcH, dstH); - calc_aa_points(srcW, dstW, xup_yup&1, xapoints); - calc_aa_points(srcH, dstH, xup_yup&2, yapoints); - } + scale_info(const U8 *src, U32 srcW, U32 srcH, U32 dstW, U32 dstH, U32 srcStride) + : xup_yup((dstW >= srcW) + ((dstH >= srcH) << 1)) + { + calc_x_points(srcW, dstW); + calc_y_strides(src, srcStride, srcH, dstH); + calc_aa_points(srcW, dstW, xup_yup&1, xapoints); + calc_aa_points(srcH, dstH, xup_yup&2, yapoints); + } private: - //........................................................................................... - void calc_x_points(U32 srcW, U32 dstW) - { - xpoints.resize(dstW+1); - - S32 val = dstW >= srcW ? 0x8000 * srcW / dstW - 0x8000 : 0; - S32 inc = (srcW << 16) / dstW; - - for(U32 i = 0, j = 0; i < dstW; ++i, ++j, val += inc) - { - xpoints[j] = llmax(0, val >> 16); - } - } - //........................................................................................... - void calc_y_strides(const U8 *src, U32 srcStride, U32 srcH, U32 dstH) - { - ystrides.resize(dstH+1); - - S32 val = dstH >= srcH ? 0x8000 * srcH / dstH - 0x8000 : 0; - S32 inc = (srcH << 16) / dstH; - - for(U32 i = 0, j = 0; i < dstH; ++i, ++j, val += inc) - { - ystrides[j] = src + llmax(0, val >> 16) * srcStride; - } - } - //........................................................................................... - void calc_aa_points(U32 srcSz, U32 dstSz, bool scale_up, std::vector &vp) - { - vp.resize(dstSz); - - if(scale_up) - { - S32 val = 0x8000 * srcSz / dstSz - 0x8000; - S32 inc = (srcSz << 16) / dstSz; - U32 pos; - - for(U32 i = 0, j = 0; i < dstSz; ++i, ++j, val += inc) - { - pos = val >> 16; - - if (pos >= (srcSz - 1)) - vp[j] = 0; - else - vp[j] = (val >> 8) - ((val >> 8) & 0xffffff00); - } - } - else - { - S32 inc = (srcSz << 16) / dstSz; - S32 Cp = ((dstSz << 14) / srcSz) + 1; - S32 ap; - - for(U32 i = 0, j = 0, val = 0; i < dstSz; ++i, ++j, val += inc) - { - ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; - vp[j] = ap | (Cp << 16); - } - } - } + //........................................................................................... + void calc_x_points(U32 srcW, U32 dstW) + { + xpoints.resize(dstW+1); + + S32 val = dstW >= srcW ? 0x8000 * srcW / dstW - 0x8000 : 0; + S32 inc = (srcW << 16) / dstW; + + for(U32 i = 0, j = 0; i < dstW; ++i, ++j, val += inc) + { + xpoints[j] = llmax(0, val >> 16); + } + } + //........................................................................................... + void calc_y_strides(const U8 *src, U32 srcStride, U32 srcH, U32 dstH) + { + ystrides.resize(dstH+1); + + S32 val = dstH >= srcH ? 0x8000 * srcH / dstH - 0x8000 : 0; + S32 inc = (srcH << 16) / dstH; + + for(U32 i = 0, j = 0; i < dstH; ++i, ++j, val += inc) + { + ystrides[j] = src + llmax(0, val >> 16) * srcStride; + } + } + //........................................................................................... + void calc_aa_points(U32 srcSz, U32 dstSz, bool scale_up, std::vector &vp) + { + vp.resize(dstSz); + + if(scale_up) + { + S32 val = 0x8000 * srcSz / dstSz - 0x8000; + S32 inc = (srcSz << 16) / dstSz; + U32 pos; + + for(U32 i = 0, j = 0; i < dstSz; ++i, ++j, val += inc) + { + pos = val >> 16; + + if (pos >= (srcSz - 1)) + vp[j] = 0; + else + vp[j] = (val >> 8) - ((val >> 8) & 0xffffff00); + } + } + else + { + S32 inc = (srcSz << 16) / dstSz; + S32 Cp = ((dstSz << 14) / srcSz) + 1; + S32 ap; + + for(U32 i = 0, j = 0, val = 0; i < dstSz; ++i, ++j, val += inc) + { + ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8; + vp[j] = ap | (Cp << 16); + } + } + } }; template inline void bilinear_scale( - const U8 *src, U32 srcW, U32 srcH, U32 srcStride - , U8 *dst, U32 dstW, U32 dstH, U32 dstStride - ) -{ - typedef scale_info scale_info_t; - - scale_info_t info(src, srcW, srcH, dstW, dstH, srcStride); - - const U8 *sptr; - U8 *dptr; - U32 x, y; - const U8 *pix; - - S32 cx[ch], comp[ch]; - - - if(3 == info.xup_yup) - { //scale x/y - up - for(y = 0; y < dstH; ++y) - { - dptr = dst + (y * dstStride); - sptr = info.ystrides[y]; - - if(0 < info.yapoints[y]) - { - for(x = 0; x < dstW; ++x) - { - //for(c = 0; c < ch; ++c) cx[c] = comp[c] = 0; - typename scale_info_t::uroll_zeroze_cx_comp_t()(cx, comp); - - if(0 < info.xapoints[x]) - { - pix = info.ystrides[y] + info.xpoints[x] * ch; - - //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.xapoints[x]); - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); - - pix += ch; - - //for(c = 0; c < ch; ++c) comp[c] += pix[c] * info.xapoints[x]; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, info.xapoints[x]); - - pix += srcStride; - - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * info.xapoints[x]; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, info.xapoints[x]); - - pix -= ch; - - //for(c = 0; c < ch; ++c) { - // cx[c] += pix[c] * (256 - info.xapoints[x]); - // comp[c] = ((cx[c] * info.yapoints[y]) + (comp[c] * (256 - info.yapoints[y]))) >> 16; - // *dptr++ = comp[c]&0xff; - //} - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, 256 - info.xapoints[x]); - typename scale_info_t::uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t()(comp, cx, info.yapoints[y]); - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); - } - else - { - pix = info.ystrides[y] + info.xpoints[x] * ch; - - //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.yapoints[y]); - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256-info.yapoints[y]); - - pix += srcStride; - - //for(c = 0; c < ch; ++c) { - // comp[c] = (comp[c] + pix[c] * info.yapoints[y]) >> 8; - // *dptr++ = comp[c]&0xff; - //} - typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.yapoints[y]); - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); - } - } - } - else - { - for(x = 0; x < dstW; ++x) - { - if(0 < info.xapoints[x]) - { - pix = info.ystrides[y] + info.xpoints[x] * ch; - - //for(c = 0; c < ch; ++c) { - // comp[c] = pix[c] * (256 - info.xapoints[x]); - // comp[c] = (comp[c] + pix[c] * info.xapoints[x]) >> 8; - // *dptr++ = comp[c]&0xff; - //} - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); - typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.xapoints[x]); - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); - } - else - { - //for(c = 0; c < ch; ++c) *dptr++ = (sptr[info.xpoints[x]*ch + c])&0xff; - typename scale_info_t::uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t()(dptr, sptr, info.xpoints[x]*ch); - } - } - } - } - } - else if(info.xup_yup == 1) - { //scaling down vertically - S32 Cy, j; - S32 yap; - - for(y = 0; y < dstH; y++) - { - Cy = info.yapoints[y] >> 16; - yap = info.yapoints[y] & 0xffff; - - dptr = dst + (y * dstStride); - - for(x = 0; x < dstW; x++) - { - pix = info.ystrides[y] + info.xpoints[x] * ch; - - //for(c = 0; c < ch; ++c) comp[c] = pix[c] * yap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, yap); - - pix += srcStride; - - for(j = (1 << 14) - yap; j > Cy; j -= Cy, pix += srcStride) - { - //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cy; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cy); - } - - if(j > 0) - { - //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); - } - - if(info.xapoints[x] > 0) - { - pix = info.ystrides[y] + info.xpoints[x]*ch + ch; - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * yap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, yap); - - pix += srcStride; - for(j = (1 << 14) - yap; j > Cy; j -= Cy) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cy; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cy); - pix += srcStride; - } - - if(j > 0) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); - } - - //for(c = 0; c < ch; ++c) comp[c] = ((comp[c]*(256 - info.xapoints[x])) + ((cx[c] * info.xapoints[x]))) >> 12; - typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.xapoints[x], cx); - } - else - { - //for(c = 0; c < ch; ++c) comp[c] >>= 4; - typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); - } - - //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); - } - } - } - else if(info.xup_yup == 2) - { // scaling down horizontally - S32 Cx, j; - S32 xap; - - for(y = 0; y < dstH; y++) - { - dptr = dst + (y * dstStride); - - for(x = 0; x < dstW; x++) - { - Cx = info.xapoints[x] >> 16; - xap = info.xapoints[x] & 0xffff; - - pix = info.ystrides[y] + info.xpoints[x] * ch; - - //for(c = 0; c < ch; ++c) comp[c] = pix[c] * xap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, xap); - - pix+=ch; - for(j = (1 << 14) - xap; j > Cx; j -= Cx) - { - //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cx; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cx); - pix+=ch; - } - - if(j > 0) - { - //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); - } - - if(info.yapoints[y] > 0) - { - pix = info.ystrides[y] + info.xpoints[x]*ch + srcStride; - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); - - pix+=ch; - for(j = (1 << 14) - xap; j > Cx; j -= Cx) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); - pix+=ch; - } - - if(j > 0) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); - } - - //for(c = 0; c < ch; ++c) comp[c] = ((comp[c] * (256 - info.yapoints[y])) + ((cx[c] * info.yapoints[y]))) >> 12; - typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.yapoints[y], cx); - } - else - { - //for(c = 0; c < ch; ++c) comp[c] >>= 4; - typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); - } - - //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); - } - } - } - else - { //scale x/y - down - S32 Cx, Cy, i, j; - S32 xap, yap; - - for(y = 0; y < dstH; y++) - { - Cy = info.yapoints[y] >> 16; - yap = info.yapoints[y] & 0xffff; - - dptr = dst + (y * dstStride); - for(x = 0; x < dstW; x++) - { - Cx = info.xapoints[x] >> 16; - xap = info.xapoints[x] & 0xffff; - - sptr = info.ystrides[y] + info.xpoints[x] * ch; - pix = sptr; - sptr += srcStride; - - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); - - pix+=ch; - for(i = (1 << 14) - xap; i > Cx; i -= Cx) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); - pix+=ch; - } - - if(i > 0) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); - } - - //for(c = 0; c < ch; ++c) comp[c] = (cx[c] >> 5) * yap; - typename scale_info_t::uroll_comp_asgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, yap); - - for(j = (1 << 14) - yap; j > Cy; j -= Cy) - { - pix = sptr; - sptr += srcStride; - - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); - - pix+=ch; - for(i = (1 << 14) - xap; i > Cx; i -= Cx) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); - pix+=ch; - } - - if(i > 0) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); - } - - //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * Cy; - typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, Cy); - } - - if(j > 0) - { - pix = sptr; - sptr += srcStride; - - //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; - typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); - - pix+=ch; - for(i = (1 << 14) - xap; i > Cx; i -= Cx) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); - pix+=ch; - } - - if(i > 0) - { - //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; - typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); - } - - //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * j; - typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, j); - } - - //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>23)&0xff; - typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 23); - } - } - } //else + const U8 *src, U32 srcW, U32 srcH, U32 srcStride + , U8 *dst, U32 dstW, U32 dstH, U32 dstStride + ) +{ + typedef scale_info scale_info_t; + + scale_info_t info(src, srcW, srcH, dstW, dstH, srcStride); + + const U8 *sptr; + U8 *dptr; + U32 x, y; + const U8 *pix; + + S32 cx[ch], comp[ch]; + + + if(3 == info.xup_yup) + { //scale x/y - up + for(y = 0; y < dstH; ++y) + { + dptr = dst + (y * dstStride); + sptr = info.ystrides[y]; + + if(0 < info.yapoints[y]) + { + for(x = 0; x < dstW; ++x) + { + //for(c = 0; c < ch; ++c) cx[c] = comp[c] = 0; + typename scale_info_t::uroll_zeroze_cx_comp_t()(cx, comp); + + if(0 < info.xapoints[x]) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.xapoints[x]); + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); + + pix += ch; + + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * info.xapoints[x]; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, info.xapoints[x]); + + pix += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * info.xapoints[x]; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, info.xapoints[x]); + + pix -= ch; + + //for(c = 0; c < ch; ++c) { + // cx[c] += pix[c] * (256 - info.xapoints[x]); + // comp[c] = ((cx[c] * info.yapoints[y]) + (comp[c] * (256 - info.yapoints[y]))) >> 16; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, 256 - info.xapoints[x]); + typename scale_info_t::uroll_comp_asgn_cx_mul_apoint_plus_comp_mul_inv_apoint_allshifted_16_r_t()(comp, cx, info.yapoints[y]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + else + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * (256 - info.yapoints[y]); + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256-info.yapoints[y]); + + pix += srcStride; + + //for(c = 0; c < ch; ++c) { + // comp[c] = (comp[c] + pix[c] * info.yapoints[y]) >> 8; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.yapoints[y]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + } + } + else + { + for(x = 0; x < dstW; ++x) + { + if(0 < info.xapoints[x]) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) { + // comp[c] = pix[c] * (256 - info.xapoints[x]); + // comp[c] = (comp[c] + pix[c] * info.xapoints[x]) >> 8; + // *dptr++ = comp[c]&0xff; + //} + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, 256 - info.xapoints[x]); + typename scale_info_t::uroll_comp_asgn_comp_plus_pix_mul_apoint_allshifted_8_r_t()(comp, pix, info.xapoints[x]); + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_and_ff_t()(dptr, comp); + } + else + { + //for(c = 0; c < ch; ++c) *dptr++ = (sptr[info.xpoints[x]*ch + c])&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_sptr_apoint_plus_idx_alland_ff_t()(dptr, sptr, info.xpoints[x]*ch); + } + } + } + } + } + else if(info.xup_yup == 1) + { //scaling down vertically + S32 Cy, j; + S32 yap; + + for(y = 0; y < dstH; y++) + { + Cy = info.yapoints[y] >> 16; + yap = info.yapoints[y] & 0xffff; + + dptr = dst + (y * dstStride); + + for(x = 0; x < dstW; x++) + { + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * yap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, yap); + + pix += srcStride; + + for(j = (1 << 14) - yap; j > Cy; j -= Cy, pix += srcStride) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cy; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cy); + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); + } + + if(info.xapoints[x] > 0) + { + pix = info.ystrides[y] + info.xpoints[x]*ch + ch; + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * yap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, yap); + + pix += srcStride; + for(j = (1 << 14) - yap; j > Cy; j -= Cy) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cy; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cy); + pix += srcStride; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); + } + + //for(c = 0; c < ch; ++c) comp[c] = ((comp[c]*(256 - info.xapoints[x])) + ((cx[c] * info.xapoints[x]))) >> 12; + typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.xapoints[x], cx); + } + else + { + //for(c = 0; c < ch; ++c) comp[c] >>= 4; + typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); + } + } + } + else if(info.xup_yup == 2) + { // scaling down horizontally + S32 Cx, j; + S32 xap; + + for(y = 0; y < dstH; y++) + { + dptr = dst + (y * dstStride); + + for(x = 0; x < dstW; x++) + { + Cx = info.xapoints[x] >> 16; + xap = info.xapoints[x] & 0xffff; + + pix = info.ystrides[y] + info.xpoints[x] * ch; + + //for(c = 0; c < ch; ++c) comp[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(comp, pix, xap); + + pix+=ch; + for(j = (1 << 14) - xap; j > Cx; j -= Cx) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, Cx); + pix+=ch; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) comp[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(comp, pix, j); + } + + if(info.yapoints[y] > 0) + { + pix = info.ystrides[y] + info.xpoints[x]*ch + srcStride; + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(j = (1 << 14) - xap; j > Cx; j -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(j > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * j; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, j); + } + + //for(c = 0; c < ch; ++c) comp[c] = ((comp[c] * (256 - info.yapoints[y])) + ((cx[c] * info.yapoints[y]))) >> 12; + typename scale_info_t::uroll_comp_asgn_comp_mul_inv_apoint_plus_cx_mul_apoint_allshifted_12_r_t()(comp, info.yapoints[y], cx); + } + else + { + //for(c = 0; c < ch; ++c) comp[c] >>= 4; + typename scale_info_t::uroll_comp_rshftasgn_constval_t()(comp, 4); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>10)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 10); + } + } + } + else + { //scale x/y - down + S32 Cx, Cy, i, j; + S32 xap, yap; + + for(y = 0; y < dstH; y++) + { + Cy = info.yapoints[y] >> 16; + yap = info.yapoints[y] & 0xffff; + + dptr = dst + (y * dstStride); + for(x = 0; x < dstW; x++) + { + Cx = info.xapoints[x] >> 16; + xap = info.xapoints[x] & 0xffff; + + sptr = info.ystrides[y] + info.xpoints[x] * ch; + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] = (cx[c] >> 5) * yap; + typename scale_info_t::uroll_comp_asgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, yap); + + for(j = (1 << 14) - yap; j > Cy; j -= Cy) + { + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * Cy; + typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, Cy); + } + + if(j > 0) + { + pix = sptr; + sptr += srcStride; + + //for(c = 0; c < ch; ++c) cx[c] = pix[c] * xap; + typename scale_info_t::uroll_inp_asgn_pix_mul_val_t()(cx, pix, xap); + + pix+=ch; + for(i = (1 << 14) - xap; i > Cx; i -= Cx) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * Cx; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, Cx); + pix+=ch; + } + + if(i > 0) + { + //for(c = 0; c < ch; ++c) cx[c] += pix[c] * i; + typename scale_info_t::uroll_inp_plusasgn_pix_mul_val_t()(cx, pix, i); + } + + //for(c = 0; c < ch; ++c) comp[c] += (cx[c] >> 5) * j; + typename scale_info_t::uroll_comp_plusasgn_cx_rshft_cval_all_mul_val_t()(comp, cx, 5, j); + } + + //for(c = 0; c < ch; ++c) *dptr++ = (comp[c]>>23)&0xff; + typename scale_info_t::uroll_uref_dptr_inc_asgn_comp_rshft_cval_and_ff_t()(dptr, comp, 23); + } + } + } //else } //wrapper static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 srcStride, U8 *dst, U32 dstW, U32 dstH, U32 dstCh, U32 dstStride) { - llassert(srcCh == dstCh); + llassert(srcCh == dstCh); - switch(srcCh) - { - case 1: - bilinear_scale<1>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); - break; - case 3: - bilinear_scale<3>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); - break; - case 4: - bilinear_scale<4>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); - break; - default: - llassert(!"Implement if need"); - break; - } + switch(srcCh) + { + case 1: + bilinear_scale<1>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + case 3: + bilinear_scale<3>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + case 4: + bilinear_scale<4>(src, srcW, srcH, srcStride, dst, dstW, dstH, dstStride); + break; + default: + llassert(!"Implement if need"); + break; + } } @@ -593,30 +593,30 @@ S32 LLImage::sMinimalReverseByteRangePercent = 75; //static void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) { - sUseNewByteRange = use_new_byte_range; + sUseNewByteRange = use_new_byte_range; sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; - sMutex = new LLMutex(); + sMutex = new LLMutex(); } //static void LLImage::cleanupClass() { - delete sMutex; - sMutex = NULL; + delete sMutex; + sMutex = NULL; } //static const std::string& LLImage::getLastError() { - static const std::string noerr("No Error"); - return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; + static const std::string noerr("No Error"); + return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; } //static void LLImage::setLastError(const std::string& message) { - LLMutexLock m(sMutex); - sLastErrorMessage = message; + LLMutexLock m(sMutex); + sLastErrorMessage = message; } //--------------------------------------------------------------------------- @@ -624,175 +624,175 @@ void LLImage::setLastError(const std::string& message) //--------------------------------------------------------------------------- LLImageBase::LLImageBase() -: mData(NULL), - mDataSize(0), - mWidth(0), - mHeight(0), - mComponents(0), - mBadBufferAllocation(false), - mAllowOverSize(false) +: mData(NULL), + mDataSize(0), + mWidth(0), + mHeight(0), + mComponents(0), + mBadBufferAllocation(false), + mAllowOverSize(false) {} // virtual LLImageBase::~LLImageBase() { - deleteData(); // virtual + deleteData(); // virtual } // virtual void LLImageBase::dump() { - LL_INFOS() << "LLImageBase mComponents " << mComponents - << " mData " << mData - << " mDataSize " << mDataSize - << " mWidth " << mWidth - << " mHeight " << mHeight - << LL_ENDL; + LL_INFOS() << "LLImageBase mComponents " << mComponents + << " mData " << mData + << " mDataSize " << mDataSize + << " mWidth " << mWidth + << " mHeight " << mHeight + << LL_ENDL; } // virtual void LLImageBase::sanityCheck() { - if (mWidth > MAX_IMAGE_SIZE - || mHeight > MAX_IMAGE_SIZE - || mDataSize > (S32)MAX_IMAGE_DATA_SIZE - || mComponents > (S8)MAX_IMAGE_COMPONENTS - ) - { - LL_ERRS() << "Failed LLImageBase::sanityCheck " - << "width " << mWidth - << "height " << mHeight - << "datasize " << mDataSize - << "components " << mComponents - << "data " << mData - << LL_ENDL; - } + if (mWidth > MAX_IMAGE_SIZE + || mHeight > MAX_IMAGE_SIZE + || mDataSize > (S32)MAX_IMAGE_DATA_SIZE + || mComponents > (S8)MAX_IMAGE_COMPONENTS + ) + { + LL_ERRS() << "Failed LLImageBase::sanityCheck " + << "width " << mWidth + << "height " << mHeight + << "datasize " << mDataSize + << "components " << mComponents + << "data " << mData + << LL_ENDL; + } } // virtual void LLImageBase::deleteData() { - ll_aligned_free_16(mData); - mDataSize = 0; - mData = NULL; + ll_aligned_free_16(mData); + mDataSize = 0; + mData = NULL; } // virtual U8* LLImageBase::allocateData(S32 size) { - //make this function thread-safe. - static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16; //256 MB - mBadBufferAllocation = false; - - if (size < 0) - { - size = mWidth * mHeight * mComponents; - if (size <= 0) - { - LL_WARNS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; - mBadBufferAllocation = true; - } - } - - if (!mBadBufferAllocation && (size < 1 || size > MAX_BUFFER_SIZE)) - { - LL_INFOS() << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << LL_ENDL ; - if(mAllowOverSize) - { - LL_INFOS() << "Oversize: " << size << LL_ENDL ; - } - else - { - LL_WARNS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; - mBadBufferAllocation = true; - } - } - - if (!mBadBufferAllocation && (!mData || size != mDataSize)) - { - deleteData(); // virtual - mData = (U8*)ll_aligned_malloc_16(size); - if (!mData) - { - LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; - mBadBufferAllocation = true; - } - } - - if (mBadBufferAllocation) - { - size = 0; - mWidth = mHeight = 0; - if (mData) - { - deleteData(); // virtual - mData = NULL; - } - } - mDataSize = size; - - return mData; + //make this function thread-safe. + static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16; //256 MB + mBadBufferAllocation = false; + + if (size < 0) + { + size = mWidth * mHeight * mComponents; + if (size <= 0) + { + LL_WARNS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; + mBadBufferAllocation = true; + } + } + + if (!mBadBufferAllocation && (size < 1 || size > MAX_BUFFER_SIZE)) + { + LL_INFOS() << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << LL_ENDL ; + if(mAllowOverSize) + { + LL_INFOS() << "Oversize: " << size << LL_ENDL ; + } + else + { + LL_WARNS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; + mBadBufferAllocation = true; + } + } + + if (!mBadBufferAllocation && (!mData || size != mDataSize)) + { + deleteData(); // virtual + mData = (U8*)ll_aligned_malloc_16(size); + if (!mData) + { + LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; + mBadBufferAllocation = true; + } + } + + if (mBadBufferAllocation) + { + size = 0; + mWidth = mHeight = 0; + if (mData) + { + deleteData(); // virtual + mData = NULL; + } + } + mDataSize = size; + + return mData; } // virtual U8* LLImageBase::reallocateData(S32 size) { - U8 *new_datap = (U8*)ll_aligned_malloc_16(size); - if (!new_datap) - { - LL_WARNS() << "Out of memory in LLImageBase::reallocateData" << LL_ENDL; - return 0; - } - if (mData) - { - S32 bytes = llmin(mDataSize, size); - memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */ - ll_aligned_free_16(mData) ; - } - mData = new_datap; - mDataSize = size; - mBadBufferAllocation = false; - return mData; -} - -const U8* LLImageBase::getData() const -{ - if(mBadBufferAllocation) - { - LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL ; - return NULL; - } - - return mData; + U8 *new_datap = (U8*)ll_aligned_malloc_16(size); + if (!new_datap) + { + LL_WARNS() << "Out of memory in LLImageBase::reallocateData" << LL_ENDL; + return 0; + } + if (mData) + { + S32 bytes = llmin(mDataSize, size); + memcpy(new_datap, mData, bytes); /* Flawfinder: ignore */ + ll_aligned_free_16(mData) ; + } + mData = new_datap; + mDataSize = size; + mBadBufferAllocation = false; + return mData; +} + +const U8* LLImageBase::getData() const +{ + if(mBadBufferAllocation) + { + LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL ; + return NULL; + } + + return mData; } // read only -U8* LLImageBase::getData() -{ - if(mBadBufferAllocation) - { - LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL; - return NULL; - } +U8* LLImageBase::getData() +{ + if(mBadBufferAllocation) + { + LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL; + return NULL; + } - return mData; + return mData; } bool LLImageBase::isBufferInvalid() const { - return mBadBufferAllocation || mData == NULL ; + return mBadBufferAllocation || mData == NULL ; } void LLImageBase::setSize(S32 width, S32 height, S32 ncomponents) { - mWidth = width; - mHeight = height; - mComponents = ncomponents; + mWidth = width; + mHeight = height; + mComponents = ncomponents; } U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size) { - setSize(width, height, ncomponents); - return allocateData(size); // virtual + setSize(width, height, ncomponents); + return allocateData(size); // virtual } //--------------------------------------------------------------------------- @@ -802,17 +802,17 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si S32 LLImageRaw::sRawImageCount = 0; LLImageRaw::LLImageRaw() - : LLImageBase() + : LLImageBase() { - ++sRawImageCount; + ++sRawImageCount; } LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) - : LLImageBase() + : LLImageBase() { - //llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE ); - allocateDataSize(width, height, components); - ++sRawImageCount; + //llassert( S32(width) * S32(height) * S32(components) <= MAX_IMAGE_DATA_SIZE ); + allocateDataSize(width, height, components); + ++sRawImageCount; } LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components) @@ -825,45 +825,45 @@ LLImageRaw::LLImageRaw(const U8* data, U16 width, U16 height, S8 components) } LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy) - : LLImageBase() + : LLImageBase() { - if(no_copy) - { - setDataAndSize(data, width, height, components); - } - else if(allocateDataSize(width, height, components)) - { - memcpy(getData(), data, width*height*components); - } - ++sRawImageCount; + if(no_copy) + { + setDataAndSize(data, width, height, components); + } + else if(allocateDataSize(width, height, components)) + { + memcpy(getData(), data, width*height*components); + } + ++sRawImageCount; } //LLImageRaw::LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only) -// : LLImageBase() +// : LLImageBase() //{ -// createFromFile(filename, j2c_lowest_mip_only); +// createFromFile(filename, j2c_lowest_mip_only); //} LLImageRaw::~LLImageRaw() { - // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData() - // NOT LLImageRaw::deleteData() - deleteData(); - --sRawImageCount; + // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData() + // NOT LLImageRaw::deleteData() + deleteData(); + --sRawImageCount; } // virtual U8* LLImageRaw::allocateData(S32 size) { - U8* res = LLImageBase::allocateData(size); - return res; + U8* res = LLImageBase::allocateData(size); + return res; } // virtual U8* LLImageRaw::reallocateData(S32 size) { - U8* res = LLImageBase::reallocateData(size); - return res; + U8* res = LLImageBase::reallocateData(size); + return res; } void LLImageRaw::releaseData() @@ -875,118 +875,118 @@ void LLImageRaw::releaseData() // virtual void LLImageRaw::deleteData() { - LLImageBase::deleteData(); + LLImageBase::deleteData(); } -void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components) -{ - if(data == getData()) - { - return ; - } +void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components) +{ + if(data == getData()) + { + return ; + } - deleteData(); + deleteData(); - LLImageBase::setSize(width, height, components) ; - LLImageBase::setDataAndSize(data, width * height * components) ; + LLImageBase::setSize(width, height, components) ; + LLImageBase::setDataAndSize(data, width * height * components) ; } bool LLImageRaw::resize(U16 width, U16 height, S8 components) { - if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components) && !isBufferInvalid()) - { - return true; - } - // Reallocate the data buffer. - deleteData(); + if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components) && !isBufferInvalid()) + { + return true; + } + // Reallocate the data buffer. + deleteData(); - allocateDataSize(width,height,components); + allocateDataSize(width,height,components); - return !isBufferInvalid(); + return !isBufferInvalid(); } bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height, - const U8 *data, U32 stride, bool reverse_y) + const U8 *data, U32 stride, bool reverse_y) { - if (!getData()) - { - return false; - } - if (!data) - { - return false; - } + if (!getData()) + { + return false; + } + if (!data) + { + return false; + } - // Should do some simple bounds checking + // Should do some simple bounds checking - U32 i; - for (i = 0; i < height; i++) - { - const U32 row = reverse_y ? height - 1 - i : i; - const U32 from_offset = row * ((stride == 0) ? width*getComponents() : stride); - const U32 to_offset = (y_pos + i)*getWidth() + x_pos; - memcpy(getData() + to_offset*getComponents(), /* Flawfinder: ignore */ - data + from_offset, getComponents()*width); - } + U32 i; + for (i = 0; i < height; i++) + { + const U32 row = reverse_y ? height - 1 - i : i; + const U32 from_offset = row * ((stride == 0) ? width*getComponents() : stride); + const U32 to_offset = (y_pos + i)*getWidth() + x_pos; + memcpy(getData() + to_offset*getComponents(), /* Flawfinder: ignore */ + data + from_offset, getComponents()*width); + } - return true; + return true; } void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) { - llassert( getComponents() <= 4 ); - // This is fairly bogus, but it'll do for now. - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return; - } - - U8 *pos = getData(); - U32 x, y; - for (x = 0; x < getWidth(); x++) - { - for (y = 0; y < getHeight(); y++) - { - *pos = r; - pos++; - if (getComponents() == 1) - { - continue; - } - *pos = g; - pos++; - if (getComponents() == 2) - { - continue; - } - *pos = b; - pos++; - if (getComponents() == 3) - { - continue; - } - *pos = a; - pos++; - } - } + llassert( getComponents() <= 4 ); + // This is fairly bogus, but it'll do for now. + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } + + U8 *pos = getData(); + U32 x, y; + for (x = 0; x < getWidth(); x++) + { + for (y = 0; y < getHeight(); y++) + { + *pos = r; + pos++; + if (getComponents() == 1) + { + continue; + } + *pos = g; + pos++; + if (getComponents() == 2) + { + continue; + } + *pos = b; + pos++; + if (getComponents() == 3) + { + continue; + } + *pos = a; + pos++; + } + } } // Reverses the order of the rows in the image void LLImageRaw::verticalFlip() { - S32 row_bytes = getWidth() * getComponents(); - llassert(row_bytes > 0); - std::vector line_buffer(row_bytes); - S32 mid_row = getHeight() / 2; - for( S32 row = 0; row < mid_row; row++ ) - { - U8* row_a_data = getData() + row * row_bytes; - U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes; - memcpy( &line_buffer[0], row_a_data, row_bytes ); - memcpy( row_a_data, row_b_data, row_bytes ); - memcpy( row_b_data, &line_buffer[0], row_bytes ); - } + S32 row_bytes = getWidth() * getComponents(); + llassert(row_bytes > 0); + std::vector line_buffer(row_bytes); + S32 mid_row = getHeight() / 2; + for( S32 row = 0; row < mid_row; row++ ) + { + U8* row_a_data = getData() + row * row_bytes; + U8* row_b_data = getData() + (getHeight() - 1 - row) * row_bytes; + memcpy( &line_buffer[0], row_a_data, row_bytes ); + memcpy( row_a_data, row_b_data, row_bytes ); + memcpy( row_b_data, &line_buffer[0], row_bytes ); + } } @@ -1079,256 +1079,256 @@ bool LLImageRaw::makeAlpha() void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image) { - // Find new sizes - S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim); - S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim); + // Find new sizes + S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim); + S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim); - scale( new_width, new_height, scale_image ); + scale( new_width, new_height, scale_image ); } void LLImageRaw::contractToPowerOfTwo(S32 max_dim, bool scale_image) { - // Find new sizes - S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE); - S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE); + // Find new sizes + S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE); + S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE); - scale( new_width, new_height, scale_image ); + scale( new_width, new_height, scale_image ); } // static S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim) { - // Strong bias towards rounding down (to save bandwidth) - // No bias would mean THRESHOLD == 1.5f; - const F32 THRESHOLD = 1.75f; - - // Find new sizes - S32 larger_dim = max_dim; // 2^n >= curr_dim - S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim - while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) ) - { - larger_dim = smaller_dim; - smaller_dim >>= 1; - } - return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim; + // Strong bias towards rounding down (to save bandwidth) + // No bias would mean THRESHOLD == 1.5f; + const F32 THRESHOLD = 1.75f; + + // Find new sizes + S32 larger_dim = max_dim; // 2^n >= curr_dim + S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim + while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) ) + { + larger_dim = smaller_dim; + smaller_dim >>= 1; + } + return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim; } // static S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim) { - S32 new_dim = MIN_IMAGE_SIZE; - while( (new_dim < curr_dim) && (new_dim < max_dim) ) - { - new_dim <<= 1; - } + S32 new_dim = MIN_IMAGE_SIZE; + while( (new_dim < curr_dim) && (new_dim < max_dim) ) + { + new_dim <<= 1; + } return new_dim; } // static S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim) { - S32 new_dim = MAX_IMAGE_SIZE; - while( (new_dim > curr_dim) && (new_dim > min_dim) ) - { - new_dim >>= 1; - } + S32 new_dim = MAX_IMAGE_SIZE; + while( (new_dim > curr_dim) && (new_dim > min_dim) ) + { + new_dim >>= 1; + } return new_dim; } void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim) { - // Find new sizes - S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim); - S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim); + // Find new sizes + S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim); + S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim); - scale( new_width, new_height ); + scale( new_width, new_height ); } // Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn! inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b ) { - U32 i = a * b + 128; - return U8((i + (i>>8)) >> 8); + U32 i = a * b + 128; + return U8((i + (i>>8)) >> 8); } void LLImageRaw::composite( LLImageRaw* src ) { - LLImageRaw* dst = this; // Just for clarity. - - if (!validateSrcAndDst("LLImageRaw::composite", src, dst)) - { - return; - } - - llassert((3 == src->getComponents()) || (4 == src->getComponents())); - llassert(3 == dst->getComponents()); - - if( 3 == dst->getComponents() ) - { - if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) - { - // No scaling needed - if( 3 == src->getComponents() ) - { - copyUnscaled( src ); // alpha is one so just copy the data. - } - else - { - compositeUnscaled4onto3( src ); - } - } - else - { - if( 3 == src->getComponents() ) - { - copyScaled( src ); // alpha is one so just copy the data. - } - else - { - compositeScaled4onto3( src ); - } - } - } + LLImageRaw* dst = this; // Just for clarity. + + if (!validateSrcAndDst("LLImageRaw::composite", src, dst)) + { + return; + } + + llassert((3 == src->getComponents()) || (4 == src->getComponents())); + llassert(3 == dst->getComponents()); + + if( 3 == dst->getComponents() ) + { + if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) + { + // No scaling needed + if( 3 == src->getComponents() ) + { + copyUnscaled( src ); // alpha is one so just copy the data. + } + else + { + compositeUnscaled4onto3( src ); + } + } + else + { + if( 3 == src->getComponents() ) + { + copyScaled( src ); // alpha is one so just copy the data. + } + else + { + compositeScaled4onto3( src ); + } + } + } } // Src and dst can be any size. Src has 4 components. Dst has 3 components. void LLImageRaw::compositeScaled4onto3(LLImageRaw* src) { - LL_INFOS() << "compositeScaled4onto3" << LL_ENDL; + LL_INFOS() << "compositeScaled4onto3" << LL_ENDL; - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); + llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); - S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents(); - llassert_always(temp_data_size > 0); - std::vector temp_buffer(temp_data_size); + S32 temp_data_size = src->getWidth() * dst->getHeight() * src->getComponents(); + llassert_always(temp_data_size > 0); + std::vector temp_buffer(temp_data_size); - // Vertical: scale but no composite - for( S32 col = 0; col < src->getWidth(); col++ ) - { - copyLineScaled( src->getData() + (src->getComponents() * col), &temp_buffer[0] + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() ); - } + // Vertical: scale but no composite + for( S32 col = 0; col < src->getWidth(); col++ ) + { + copyLineScaled( src->getData() + (src->getComponents() * col), &temp_buffer[0] + (src->getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() ); + } - // Horizontal: scale and composite - for( S32 row = 0; row < dst->getHeight(); row++ ) - { - compositeRowScaled4onto3( &temp_buffer[0] + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() ); - } + // Horizontal: scale and composite + for( S32 row = 0; row < dst->getHeight(); row++ ) + { + compositeRowScaled4onto3( &temp_buffer[0] + (src->getComponents() * src->getWidth() * row), dst->getData() + (dst->getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth() ); + } } // Src and dst are same size. Src has 4 components. Dst has 3 components. void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src ) { - LLImageRaw* dst = this; // Just for clarity. - - llassert( (3 == src->getComponents()) || (4 == src->getComponents()) ); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); - - U8* src_data = src->getData(); - U8* dst_data = dst->getData(); - S32 pixels = getWidth() * getHeight(); - while( pixels-- ) - { - U8 alpha = src_data[3]; - if( alpha ) - { - if( 255 == alpha ) - { - dst_data[0] = src_data[0]; - dst_data[1] = src_data[1]; - dst_data[2] = src_data[2]; - } - else - { - - U8 transparency = 255 - alpha; - dst_data[0] = fastFractionalMult( dst_data[0], transparency ) + fastFractionalMult( src_data[0], alpha ); - dst_data[1] = fastFractionalMult( dst_data[1], transparency ) + fastFractionalMult( src_data[1], alpha ); - dst_data[2] = fastFractionalMult( dst_data[2], transparency ) + fastFractionalMult( src_data[2], alpha ); - } - } - - src_data += 4; - dst_data += 3; - } + LLImageRaw* dst = this; // Just for clarity. + + llassert( (3 == src->getComponents()) || (4 == src->getComponents()) ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + + U8* src_data = src->getData(); + U8* dst_data = dst->getData(); + S32 pixels = getWidth() * getHeight(); + while( pixels-- ) + { + U8 alpha = src_data[3]; + if( alpha ) + { + if( 255 == alpha ) + { + dst_data[0] = src_data[0]; + dst_data[1] = src_data[1]; + dst_data[2] = src_data[2]; + } + else + { + + U8 transparency = 255 - alpha; + dst_data[0] = fastFractionalMult( dst_data[0], transparency ) + fastFractionalMult( src_data[0], alpha ); + dst_data[1] = fastFractionalMult( dst_data[1], transparency ) + fastFractionalMult( src_data[1], alpha ); + dst_data[2] = fastFractionalMult( dst_data[2], transparency ) + fastFractionalMult( src_data[2], alpha ); + } + } + + src_data += 4; + dst_data += 3; + } } void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst)) - { - return; - } + if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst)) + { + return; + } - llassert( 1 == src->getComponents() ); - llassert( 4 == dst->getComponents() ); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + llassert( 1 == src->getComponents() ); + llassert( 4 == dst->getComponents() ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); - S32 pixels = getWidth() * getHeight(); - U8* src_data = src->getData(); - U8* dst_data = dst->getData(); - for ( S32 i = 0; i < pixels; i++ ) - { - dst_data[0] = fill.mV[0]; - dst_data[1] = fill.mV[1]; - dst_data[2] = fill.mV[2]; - dst_data[3] = src_data[0]; - src_data += 1; - dst_data += 4; - } + S32 pixels = getWidth() * getHeight(); + U8* src_data = src->getData(); + U8* dst_data = dst->getData(); + for ( S32 i = 0; i < pixels; i++ ) + { + dst_data[0] = fill.mV[0]; + dst_data[1] = fill.mV[1]; + dst_data[2] = fill.mV[2]; + dst_data[3] = src_data[0]; + src_data += 1; + dst_data += 4; + } } // Fill the buffer with a constant color void LLImageRaw::fill( const LLColor4U& color ) { - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return; - } - - S32 pixels = getWidth() * getHeight(); - if( 4 == getComponents() ) - { - U32* data = (U32*) getData(); - U32 rgbaColor = color.asRGBA(); - for( S32 i = 0; i < pixels; i++ ) - { - data[ i ] = rgbaColor; - } - } - else - if( 3 == getComponents() ) - { - U8* data = getData(); - for( S32 i = 0; i < pixels; i++ ) - { - data[0] = color.mV[0]; - data[1] = color.mV[1]; - data[2] = color.mV[2]; - data += 3; - } - } -} + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } + + S32 pixels = getWidth() * getHeight(); + if( 4 == getComponents() ) + { + U32* data = (U32*) getData(); + U32 rgbaColor = color.asRGBA(); + for( S32 i = 0; i < pixels; i++ ) + { + data[ i ] = rgbaColor; + } + } + else + if( 3 == getComponents() ) + { + U8* data = getData(); + for( S32 i = 0; i < pixels; i++ ) + { + data[0] = color.mV[0]; + data[1] = color.mV[1]; + data[2] = color.mV[2]; + data += 3; + } + } +} void LLImageRaw::tint( const LLColor3& color ) { - llassert( (3 == getComponents()) || (4 == getComponents()) ); - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return; - } + llassert( (3 == getComponents()) || (4 == getComponents()) ); + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return; + } - S32 pixels = getWidth() * getHeight(); + S32 pixels = getWidth() * getHeight(); const S32 components = getComponents(); U8* data = getData(); for( S32 i = 0; i < pixels; i++ ) @@ -1345,188 +1345,188 @@ void LLImageRaw::tint( const LLColor3& color ) LLPointer LLImageRaw::duplicate() { - if(getNumRefs() < 2) - { - return this; //nobody else refences to this image, no need to duplicate. - } + if(getNumRefs() < 2) + { + return this; //nobody else refences to this image, no need to duplicate. + } - //make a duplicate - LLPointer dup = new LLImageRaw(getData(), getWidth(), getHeight(), getComponents()); - return dup; + //make a duplicate + LLPointer dup = new LLImageRaw(getData(), getWidth(), getHeight(), getComponents()); + return dup; } // Src and dst can be any size. Src and dst can each have 3 or 4 components. void LLImageRaw::copy(LLImageRaw* src) { - LLImageRaw* dst = this; // Just for clarity. - - if (!validateSrcAndDst("LLImageRaw::copy", src, dst)) - { - return; - } - - if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) - { - // No scaling needed - if( src->getComponents() == dst->getComponents() ) - { - copyUnscaled( src ); - } - else - if( 3 == src->getComponents() ) - { - copyUnscaled3onto4( src ); - } - else - { - // 4 == src->getComponents() - copyUnscaled4onto3( src ); - } - } - else - { - // Scaling needed - // No scaling needed - if( src->getComponents() == dst->getComponents() ) - { - copyScaled( src ); - } - else - if( 3 == src->getComponents() ) - { - copyScaled3onto4( src ); - } - else - { - // 4 == src->getComponents() - copyScaled4onto3( src ); - } - } + LLImageRaw* dst = this; // Just for clarity. + + if (!validateSrcAndDst("LLImageRaw::copy", src, dst)) + { + return; + } + + if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) + { + // No scaling needed + if( src->getComponents() == dst->getComponents() ) + { + copyUnscaled( src ); + } + else + if( 3 == src->getComponents() ) + { + copyUnscaled3onto4( src ); + } + else + { + // 4 == src->getComponents() + copyUnscaled4onto3( src ); + } + } + else + { + // Scaling needed + // No scaling needed + if( src->getComponents() == dst->getComponents() ) + { + copyScaled( src ); + } + else + if( 3 == src->getComponents() ) + { + copyScaled3onto4( src ); + } + else + { + // 4 == src->getComponents() + copyScaled4onto3( src ); + } + } } // Src and dst are same size. Src and dst have same number of components. void LLImageRaw::copyUnscaled(LLImageRaw* src) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - llassert( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) ); - llassert( src->getComponents() == dst->getComponents() ); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + llassert( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) ); + llassert( src->getComponents() == dst->getComponents() ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); - memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */ + memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */ } // Src and dst can be any size. Src has 3 components. Dst has 4 components. void LLImageRaw::copyScaled3onto4(LLImageRaw* src) { - llassert( (3 == src->getComponents()) && (4 == getComponents()) ); + llassert( (3 == src->getComponents()) && (4 == getComponents()) ); - // Slow, but simple. Optimize later if needed. - LLImageRaw temp( src->getWidth(), src->getHeight(), 4); - temp.copyUnscaled3onto4( src ); - copyScaled( &temp ); + // Slow, but simple. Optimize later if needed. + LLImageRaw temp( src->getWidth(), src->getHeight(), 4); + temp.copyUnscaled3onto4( src ); + copyScaled( &temp ); } // Src and dst can be any size. Src has 4 components. Dst has 3 components. void LLImageRaw::copyScaled4onto3(LLImageRaw* src) { - llassert( (4 == src->getComponents()) && (3 == getComponents()) ); + llassert( (4 == src->getComponents()) && (3 == getComponents()) ); - // Slow, but simple. Optimize later if needed. - LLImageRaw temp( src->getWidth(), src->getHeight(), 3); - temp.copyUnscaled4onto3( src ); - copyScaled( &temp ); + // Slow, but simple. Optimize later if needed. + LLImageRaw temp( src->getWidth(), src->getHeight(), 3); + temp.copyUnscaled4onto3( src ); + copyScaled( &temp ); } // Src and dst are same size. Src has 4 components. Dst has 3 components. void LLImageRaw::copyUnscaled4onto3( LLImageRaw* src ) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - llassert( (3 == dst->getComponents()) && (4 == src->getComponents()) ); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + llassert( (3 == dst->getComponents()) && (4 == src->getComponents()) ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); - S32 pixels = getWidth() * getHeight(); - U8* src_data = src->getData(); - U8* dst_data = dst->getData(); - for( S32 i=0; igetData(); + U8* dst_data = dst->getData(); + for( S32 i=0; igetComponents() ); - llassert( 4 == dst->getComponents() ); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + LLImageRaw* dst = this; // Just for clarity. + llassert( 3 == src->getComponents() ); + llassert( 4 == dst->getComponents() ); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); - S32 pixels = getWidth() * getHeight(); - U8* src_data = src->getData(); - U8* dst_data = dst->getData(); - for( S32 i=0; igetData(); + U8* dst_data = dst->getData(); + for( S32 i=0; igetComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) ); - llassert_always( src->getComponents() == dst->getComponents() ); + llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) ); + llassert_always( src->getComponents() == dst->getComponents() ); - if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) - { - memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */ - return; - } + if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) + { + memcpy( dst->getData(), src->getData(), getWidth() * getHeight() * getComponents() ); /* Flawfinder: ignore */ + return; + } - bilinear_scale( - src->getData(), src->getWidth(), src->getHeight(), src->getComponents(), src->getWidth()*src->getComponents() - , dst->getData(), dst->getWidth(), dst->getHeight(), dst->getComponents(), dst->getWidth()*dst->getComponents() - ); + bilinear_scale( + src->getData(), src->getWidth(), src->getHeight(), src->getComponents(), src->getWidth()*src->getComponents() + , dst->getData(), dst->getWidth(), dst->getHeight(), dst->getComponents(), dst->getWidth()*dst->getComponents() + ); - /* - S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents(); - llassert_always(temp_data_size > 0); - std::vector temp_buffer(temp_data_size); + /* + S32 temp_data_size = src->getWidth() * dst->getHeight() * getComponents(); + llassert_always(temp_data_size > 0); + std::vector temp_buffer(temp_data_size); - // Vertical - for( S32 col = 0; col < src->getWidth(); col++ ) - { - copyLineScaled( src->getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() ); - } + // Vertical + for( S32 col = 0; col < src->getWidth(); col++ ) + { + copyLineScaled( src->getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), src->getHeight(), dst->getHeight(), src->getWidth(), src->getWidth() ); + } - // Horizontal - for( S32 row = 0; row < dst->getHeight(); row++ ) - { - copyLineScaled( &temp_buffer[0] + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 ); - } - */ + // Horizontal + for( S32 row = 0; row < dst->getHeight(); row++ ) + { + copyLineScaled( &temp_buffer[0] + (getComponents() * src->getWidth() * row), dst->getData() + (getComponents() * dst->getWidth() * row), src->getWidth(), dst->getWidth(), 1, 1 ); + } + */ } @@ -1539,79 +1539,79 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data ) return false; } - if (isBufferInvalid()) - { - LL_WARNS() << "Invalid image buffer" << LL_ENDL; - return false; - } + if (isBufferInvalid()) + { + LL_WARNS() << "Invalid image buffer" << LL_ENDL; + return false; + } - S32 old_width = getWidth(); - S32 old_height = getHeight(); - - if( (old_width == new_width) && (old_height == new_height) ) - { - return true; // Nothing to do. - } + S32 old_width = getWidth(); + S32 old_height = getHeight(); + + if( (old_width == new_width) && (old_height == new_height) ) + { + return true; // Nothing to do. + } - // Reallocate the data buffer. + // Reallocate the data buffer. - if (scale_image_data) - { - S32 new_data_size = new_width * new_height * components; + if (scale_image_data) + { + S32 new_data_size = new_width * new_height * components; - if (new_data_size > 0) + if (new_data_size > 0) { - U8 *new_data = (U8*)ll_aligned_malloc_16(new_data_size); - if(NULL == new_data) + U8 *new_data = (U8*)ll_aligned_malloc_16(new_data_size); + if(NULL == new_data) { - return false; + return false; } bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components); - setDataAndSize(new_data, new_width, new_height, components); - } - } - else try - { - // copy out existing image data - S32 temp_data_size = old_width * old_height * components; - std::vector temp_buffer(temp_data_size); - memcpy(&temp_buffer[0], getData(), temp_data_size); - - // allocate new image data, will delete old data - U8* new_buffer = allocateDataSize(new_width, new_height, components); + setDataAndSize(new_data, new_width, new_height, components); + } + } + else try + { + // copy out existing image data + S32 temp_data_size = old_width * old_height * components; + std::vector temp_buffer(temp_data_size); + memcpy(&temp_buffer[0], getData(), temp_data_size); + + // allocate new image data, will delete old data + U8* new_buffer = allocateDataSize(new_width, new_height, components); if (!new_buffer) { LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL; return false; } - - for( S32 row = 0; row < new_height; row++ ) + + for( S32 row = 0; row < new_height; row++ ) { - if (row < old_height) + if (row < old_height) { - memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width)); - if (old_width < new_width) + memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width)); + if (old_width < new_width) { - // pad out rest of row with black - memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width)); + // pad out rest of row with black + memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width)); } } else { // pad remaining rows with black - memset(new_buffer + (new_width * row * components), 0, new_width * components); + memset(new_buffer + (new_width * row * components), 0, new_width * components); } } - } + } catch (std::bad_alloc&) // for temp_buffer { LL_WARNS() << "Failed to allocate temporary image buffer" << LL_ENDL; return false; } - return true ; + return true ; } LLPointer LLImageRaw::scaled(S32 new_width, S32 new_height) @@ -1665,253 +1665,253 @@ LLPointer LLImageRaw::scaled(S32 new_width, S32 new_height) void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ) { - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new - const F32 norm_factor = 1.f / ratio; - - S32 goff = components >= 2 ? 1 : 0; - S32 boff = components >= 3 ? 2 : 0; - for( S32 x = 0; x < out_pixel_len; x++ ) - { - // Sample input pixels in range from sample0 to sample1. - // Avoid floating point accumulation error... don't just add ratio each time. JC - const F32 sample0 = x * ratio; - const F32 sample1 = (x+1) * ratio; - const S32 index0 = llfloor(sample0); // left integer (floor) - const S32 index1 = llfloor(sample1); // right integer (floor) - const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left - const F32 fract1 = sample1 - F32(index1); // spill-over on right - - if( index0 == index1 ) - { - // Interval is embedded in one input pixel - S32 t0 = x * out_pixel_step * components; - S32 t1 = index0 * in_pixel_step * components; - U8* outp = out + t0; - U8* inp = in + t1; - for (S32 i = 0; i < components; ++i) - { - *outp = *inp; - ++outp; - ++inp; - } - } - else - { - // Left straddle - S32 t1 = index0 * in_pixel_step * components; - F32 r = in[t1 + 0] * fract0; - F32 g = in[t1 + goff] * fract0; - F32 b = in[t1 + boff] * fract0; - F32 a = 0; - if( components == 4) - { - a = in[t1 + 3] * fract0; - } - - // Central interval - if (components < 4) - { - for( S32 u = index0 + 1; u < index1; u++ ) - { - S32 t2 = u * in_pixel_step * components; - r += in[t2 + 0]; - g += in[t2 + goff]; - b += in[t2 + boff]; - } - } - else - { - for( S32 u = index0 + 1; u < index1; u++ ) - { - S32 t2 = u * in_pixel_step * components; - r += in[t2 + 0]; - g += in[t2 + 1]; - b += in[t2 + 2]; - a += in[t2 + 3]; - } - } - - // right straddle - // Watch out for reading off of end of input array. - if( fract1 && index1 < in_pixel_len ) - { - S32 t3 = index1 * in_pixel_step * components; - if (components < 4) - { - U8 in0 = in[t3 + 0]; - U8 in1 = in[t3 + goff]; - U8 in2 = in[t3 + boff]; - r += in0 * fract1; - g += in1 * fract1; - b += in2 * fract1; - } - else - { - U8 in0 = in[t3 + 0]; - U8 in1 = in[t3 + 1]; - U8 in2 = in[t3 + 2]; - U8 in3 = in[t3 + 3]; - r += in0 * fract1; - g += in1 * fract1; - b += in2 * fract1; - a += in3 * fract1; - } - } - - r *= norm_factor; - g *= norm_factor; - b *= norm_factor; - a *= norm_factor; // skip conditional - - S32 t4 = x * out_pixel_step * components; - out[t4 + 0] = U8(ll_round(r)); - if (components >= 2) - out[t4 + 1] = U8(ll_round(g)); - if (components >= 3) - out[t4 + 2] = U8(ll_round(b)); - if( components == 4) - out[t4 + 3] = U8(ll_round(a)); - } - } + const S32 components = getComponents(); + llassert( components >= 1 && components <= 4 ); + + const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new + const F32 norm_factor = 1.f / ratio; + + S32 goff = components >= 2 ? 1 : 0; + S32 boff = components >= 3 ? 2 : 0; + for( S32 x = 0; x < out_pixel_len; x++ ) + { + // Sample input pixels in range from sample0 to sample1. + // Avoid floating point accumulation error... don't just add ratio each time. JC + const F32 sample0 = x * ratio; + const F32 sample1 = (x+1) * ratio; + const S32 index0 = llfloor(sample0); // left integer (floor) + const S32 index1 = llfloor(sample1); // right integer (floor) + const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left + const F32 fract1 = sample1 - F32(index1); // spill-over on right + + if( index0 == index1 ) + { + // Interval is embedded in one input pixel + S32 t0 = x * out_pixel_step * components; + S32 t1 = index0 * in_pixel_step * components; + U8* outp = out + t0; + U8* inp = in + t1; + for (S32 i = 0; i < components; ++i) + { + *outp = *inp; + ++outp; + ++inp; + } + } + else + { + // Left straddle + S32 t1 = index0 * in_pixel_step * components; + F32 r = in[t1 + 0] * fract0; + F32 g = in[t1 + goff] * fract0; + F32 b = in[t1 + boff] * fract0; + F32 a = 0; + if( components == 4) + { + a = in[t1 + 3] * fract0; + } + + // Central interval + if (components < 4) + { + for( S32 u = index0 + 1; u < index1; u++ ) + { + S32 t2 = u * in_pixel_step * components; + r += in[t2 + 0]; + g += in[t2 + goff]; + b += in[t2 + boff]; + } + } + else + { + for( S32 u = index0 + 1; u < index1; u++ ) + { + S32 t2 = u * in_pixel_step * components; + r += in[t2 + 0]; + g += in[t2 + 1]; + b += in[t2 + 2]; + a += in[t2 + 3]; + } + } + + // right straddle + // Watch out for reading off of end of input array. + if( fract1 && index1 < in_pixel_len ) + { + S32 t3 = index1 * in_pixel_step * components; + if (components < 4) + { + U8 in0 = in[t3 + 0]; + U8 in1 = in[t3 + goff]; + U8 in2 = in[t3 + boff]; + r += in0 * fract1; + g += in1 * fract1; + b += in2 * fract1; + } + else + { + U8 in0 = in[t3 + 0]; + U8 in1 = in[t3 + 1]; + U8 in2 = in[t3 + 2]; + U8 in3 = in[t3 + 3]; + r += in0 * fract1; + g += in1 * fract1; + b += in2 * fract1; + a += in3 * fract1; + } + } + + r *= norm_factor; + g *= norm_factor; + b *= norm_factor; + a *= norm_factor; // skip conditional + + S32 t4 = x * out_pixel_step * components; + out[t4 + 0] = U8(ll_round(r)); + if (components >= 2) + out[t4 + 1] = U8(ll_round(g)); + if (components >= 3) + out[t4 + 2] = U8(ll_round(b)); + if( components == 4) + out[t4 + 3] = U8(ll_round(a)); + } + } } void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len ) { - llassert( getComponents() == 3 ); - - const S32 IN_COMPONENTS = 4; - const S32 OUT_COMPONENTS = 3; - - const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new - const F32 norm_factor = 1.f / ratio; - - for( S32 x = 0; x < out_pixel_len; x++ ) - { - // Sample input pixels in range from sample0 to sample1. - // Avoid floating point accumulation error... don't just add ratio each time. JC - const F32 sample0 = x * ratio; - const F32 sample1 = (x+1) * ratio; - const S32 index0 = S32(sample0); // left integer (floor) - const S32 index1 = S32(sample1); // right integer (floor) - const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left - const F32 fract1 = sample1 - F32(index1); // spill-over on right - - U8 in_scaled_r; - U8 in_scaled_g; - U8 in_scaled_b; - U8 in_scaled_a; - - if( index0 == index1 ) - { - // Interval is embedded in one input pixel - S32 t1 = index0 * IN_COMPONENTS; - in_scaled_r = in[t1 + 0]; - in_scaled_g = in[t1 + 0]; - in_scaled_b = in[t1 + 0]; - in_scaled_a = in[t1 + 0]; - } - else - { - // Left straddle - S32 t1 = index0 * IN_COMPONENTS; - F32 r = in[t1 + 0] * fract0; - F32 g = in[t1 + 1] * fract0; - F32 b = in[t1 + 2] * fract0; - F32 a = in[t1 + 3] * fract0; - - // Central interval - for( S32 u = index0 + 1; u < index1; u++ ) - { - S32 t2 = u * IN_COMPONENTS; - r += in[t2 + 0]; - g += in[t2 + 1]; - b += in[t2 + 2]; - a += in[t2 + 3]; - } - - // right straddle - // Watch out for reading off of end of input array. - if( fract1 && index1 < in_pixel_len ) - { - S32 t3 = index1 * IN_COMPONENTS; - r += in[t3 + 0] * fract1; - g += in[t3 + 1] * fract1; - b += in[t3 + 2] * fract1; - a += in[t3 + 3] * fract1; - } - - r *= norm_factor; - g *= norm_factor; - b *= norm_factor; - a *= norm_factor; - - in_scaled_r = U8(ll_round(r)); - in_scaled_g = U8(ll_round(g)); - in_scaled_b = U8(ll_round(b)); - in_scaled_a = U8(ll_round(a)); - } - - if( in_scaled_a ) - { - if( 255 == in_scaled_a ) - { - out[0] = in_scaled_r; - out[1] = in_scaled_g; - out[2] = in_scaled_b; - } - else - { - U8 transparency = 255 - in_scaled_a; - out[0] = fastFractionalMult( out[0], transparency ) + fastFractionalMult( in_scaled_r, in_scaled_a ); - out[1] = fastFractionalMult( out[1], transparency ) + fastFractionalMult( in_scaled_g, in_scaled_a ); - out[2] = fastFractionalMult( out[2], transparency ) + fastFractionalMult( in_scaled_b, in_scaled_a ); - } - } - out += OUT_COMPONENTS; - } + llassert( getComponents() == 3 ); + + const S32 IN_COMPONENTS = 4; + const S32 OUT_COMPONENTS = 3; + + const F32 ratio = F32(in_pixel_len) / out_pixel_len; // ratio of old to new + const F32 norm_factor = 1.f / ratio; + + for( S32 x = 0; x < out_pixel_len; x++ ) + { + // Sample input pixels in range from sample0 to sample1. + // Avoid floating point accumulation error... don't just add ratio each time. JC + const F32 sample0 = x * ratio; + const F32 sample1 = (x+1) * ratio; + const S32 index0 = S32(sample0); // left integer (floor) + const S32 index1 = S32(sample1); // right integer (floor) + const F32 fract0 = 1.f - (sample0 - F32(index0)); // spill over on left + const F32 fract1 = sample1 - F32(index1); // spill-over on right + + U8 in_scaled_r; + U8 in_scaled_g; + U8 in_scaled_b; + U8 in_scaled_a; + + if( index0 == index1 ) + { + // Interval is embedded in one input pixel + S32 t1 = index0 * IN_COMPONENTS; + in_scaled_r = in[t1 + 0]; + in_scaled_g = in[t1 + 0]; + in_scaled_b = in[t1 + 0]; + in_scaled_a = in[t1 + 0]; + } + else + { + // Left straddle + S32 t1 = index0 * IN_COMPONENTS; + F32 r = in[t1 + 0] * fract0; + F32 g = in[t1 + 1] * fract0; + F32 b = in[t1 + 2] * fract0; + F32 a = in[t1 + 3] * fract0; + + // Central interval + for( S32 u = index0 + 1; u < index1; u++ ) + { + S32 t2 = u * IN_COMPONENTS; + r += in[t2 + 0]; + g += in[t2 + 1]; + b += in[t2 + 2]; + a += in[t2 + 3]; + } + + // right straddle + // Watch out for reading off of end of input array. + if( fract1 && index1 < in_pixel_len ) + { + S32 t3 = index1 * IN_COMPONENTS; + r += in[t3 + 0] * fract1; + g += in[t3 + 1] * fract1; + b += in[t3 + 2] * fract1; + a += in[t3 + 3] * fract1; + } + + r *= norm_factor; + g *= norm_factor; + b *= norm_factor; + a *= norm_factor; + + in_scaled_r = U8(ll_round(r)); + in_scaled_g = U8(ll_round(g)); + in_scaled_b = U8(ll_round(b)); + in_scaled_a = U8(ll_round(a)); + } + + if( in_scaled_a ) + { + if( 255 == in_scaled_a ) + { + out[0] = in_scaled_r; + out[1] = in_scaled_g; + out[2] = in_scaled_b; + } + else + { + U8 transparency = 255 - in_scaled_a; + out[0] = fastFractionalMult( out[0], transparency ) + fastFractionalMult( in_scaled_r, in_scaled_a ); + out[1] = fastFractionalMult( out[1], transparency ) + fastFractionalMult( in_scaled_g, in_scaled_a ); + out[2] = fastFractionalMult( out[2], transparency ) + fastFractionalMult( in_scaled_b, in_scaled_a ); + } + } + out += OUT_COMPONENTS; + } } void LLImageRaw::addEmissive(LLImageRaw* src) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - if (!validateSrcAndDst(__FUNCTION__, src, dst)) - { - return; - } + if (!validateSrcAndDst(__FUNCTION__, src, dst)) + { + return; + } - llassert((3 == src->getComponents()) || (4 == src->getComponents())); - llassert(3 == dst->getComponents()); + llassert((3 == src->getComponents()) || (4 == src->getComponents())); + llassert(3 == dst->getComponents()); - if( 3 == dst->getComponents() ) - { - if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) - { + if( 3 == dst->getComponents() ) + { + if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ) + { addEmissiveUnscaled(src); - } - else - { + } + else + { addEmissiveScaled(src); - } - } + } + } } void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - llassert((3 == src->getComponents()) || (4 == src->getComponents())); - llassert((3 == dst->getComponents()) || (4 == dst->getComponents())); - llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); + llassert((3 == src->getComponents()) || (4 == src->getComponents())); + llassert((3 == dst->getComponents()) || (4 == dst->getComponents())); + llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) ); U8* const src_data = src->getData(); U8* const dst_data = dst->getData(); - for(S32 y = 0; y < dst->getHeight(); ++y) - { + for(S32 y = 0; y < dst->getHeight(); ++y) + { const S32 src_row_offset = src->getComponents() * src->getWidth() * y; const S32 dst_row_offset = dst->getComponents() * dst->getWidth() * y; for (S32 x = 0; x < dst->getWidth(); ++x) @@ -1924,17 +1924,17 @@ void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src) dst_pixel[1] = llmin(255, dst_pixel[1] + src_pixel[1]); dst_pixel[2] = llmin(255, dst_pixel[2] + src_pixel[2]); } - } + } } void LLImageRaw::addEmissiveScaled(LLImageRaw* src) { - LLImageRaw* dst = this; // Just for clarity. + LLImageRaw* dst = this; // Just for clarity. - llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); + llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) ); LLImageRaw temp(dst->getWidth(), dst->getHeight(), dst->getComponents()); - llassert_always(temp.getDataSize() > 0); + llassert_always(temp.getDataSize() > 0); temp.copyScaled(src); dst->addEmissiveUnscaled(&temp); @@ -1943,161 +1943,161 @@ void LLImageRaw::addEmissiveScaled(LLImageRaw* src) bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst) { - if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid()) - { - LL_WARNS() << func << ": Source: "; - if (!src) LL_CONT << "Null pointer"; - else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer"; - else LL_CONT << "OK"; + if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid()) + { + LL_WARNS() << func << ": Source: "; + if (!src) LL_CONT << "Null pointer"; + else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer"; + else LL_CONT << "OK"; - LL_CONT << "; Destination: "; - if (!dst) LL_CONT << "Null pointer"; - else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer"; - else LL_CONT << "OK"; - LL_CONT << "." << LL_ENDL; + LL_CONT << "; Destination: "; + if (!dst) LL_CONT << "Null pointer"; + else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer"; + else LL_CONT << "OK"; + LL_CONT << "." << LL_ENDL; - return false; - } - return true; + return false; + } + return true; } //---------------------------------------------------------------------------- static struct { - const char* exten; - EImageCodec codec; + const char* exten; + EImageCodec codec; } file_extensions[] = { - { "bmp", IMG_CODEC_BMP }, - { "tga", IMG_CODEC_TGA }, - { "j2c", IMG_CODEC_J2C }, - { "jp2", IMG_CODEC_J2C }, - { "texture", IMG_CODEC_J2C }, - { "jpg", IMG_CODEC_JPEG }, - { "jpeg", IMG_CODEC_JPEG }, - { "mip", IMG_CODEC_DXT }, - { "dxt", IMG_CODEC_DXT }, - { "png", IMG_CODEC_PNG } + { "bmp", IMG_CODEC_BMP }, + { "tga", IMG_CODEC_TGA }, + { "j2c", IMG_CODEC_J2C }, + { "jp2", IMG_CODEC_J2C }, + { "texture", IMG_CODEC_J2C }, + { "jpg", IMG_CODEC_JPEG }, + { "jpeg", IMG_CODEC_JPEG }, + { "mip", IMG_CODEC_DXT }, + { "dxt", IMG_CODEC_DXT }, + { "png", IMG_CODEC_PNG } }; #define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions) #if 0 static std::string find_file(std::string &name, S8 *codec) { - std::string tname; - for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++) - { - tname = name + "." + std::string(file_extensions[i].exten); - llifstream ifs(tname.c_str(), llifstream::binary); - if (ifs.is_open()) - { - ifs.close(); - if (codec) - *codec = file_extensions[i].codec; - return std::string(file_extensions[i].exten); - } - } - return std::string(""); + std::string tname; + for (int i=0; i<(int)(NUM_FILE_EXTENSIONS); i++) + { + tname = name + "." + std::string(file_extensions[i].exten); + llifstream ifs(tname.c_str(), llifstream::binary); + if (ifs.is_open()) + { + ifs.close(); + if (codec) + *codec = file_extensions[i].codec; + return std::string(file_extensions[i].exten); + } + } + return std::string(""); } #endif EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten) { - if (!exten.empty()) - { - for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++) - { - if (exten == file_extensions[i].exten) - return file_extensions[i].codec; - } - } - return IMG_CODEC_INVALID; + if (!exten.empty()) + { + for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++) + { + if (exten == file_extensions[i].exten) + return file_extensions[i].codec; + } + } + return IMG_CODEC_INVALID; } #if 0 bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only) { - std::string name = filename; - size_t dotidx = name.rfind('.'); - S8 codec = IMG_CODEC_INVALID; - std::string exten; - - deleteData(); // delete any existing data - - if (dotidx != std::string::npos) - { - exten = name.substr(dotidx+1); - LLStringUtil::toLower(exten); - codec = getCodecFromExtension(exten); - } - else - { - exten = find_file(name, &codec); - name = name + "." + exten; - } - if (codec == IMG_CODEC_INVALID) - { - return false; // format not recognized - } - - llifstream ifs(name.c_str(), llifstream::binary); - if (!ifs.is_open()) - { - // SJB: changed from LL_INFOS() to LL_DEBUGS() to reduce spam - LL_DEBUGS() << "Unable to open image file: " << name << LL_ENDL; - return false; - } - - ifs.seekg (0, std::ios::end); - int length = ifs.tellg(); - if (j2c_lowest_mip_only && length > 2048) - { - length = 2048; - } - ifs.seekg (0, std::ios::beg); - - if (!length) - { - LL_INFOS() << "Zero length file file: " << name << LL_ENDL; - return false; - } - - LLPointer image = LLImageFormatted::createFromType(codec); - llassert(image.notNull()); - - U8 *buffer = image->allocateData(length); - ifs.read ((char*)buffer, length); - ifs.close(); - - bool success; - - success = image->updateData(); - if (success) - { - if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) - { - S32 width = image->getWidth(); - S32 height = image->getHeight(); - S32 discard_level = 0; - while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) - { - width >>= 1; - height >>= 1; - discard_level++; - } - ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); - } - success = image->decode(this, 100000.0f); - } - - image = NULL; // deletes image - if (!success) - { - deleteData(); - LL_WARNS() << "Unable to decode image" << name << LL_ENDL; - return false; - } - - return true; + std::string name = filename; + size_t dotidx = name.rfind('.'); + S8 codec = IMG_CODEC_INVALID; + std::string exten; + + deleteData(); // delete any existing data + + if (dotidx != std::string::npos) + { + exten = name.substr(dotidx+1); + LLStringUtil::toLower(exten); + codec = getCodecFromExtension(exten); + } + else + { + exten = find_file(name, &codec); + name = name + "." + exten; + } + if (codec == IMG_CODEC_INVALID) + { + return false; // format not recognized + } + + llifstream ifs(name.c_str(), llifstream::binary); + if (!ifs.is_open()) + { + // SJB: changed from LL_INFOS() to LL_DEBUGS() to reduce spam + LL_DEBUGS() << "Unable to open image file: " << name << LL_ENDL; + return false; + } + + ifs.seekg (0, std::ios::end); + int length = ifs.tellg(); + if (j2c_lowest_mip_only && length > 2048) + { + length = 2048; + } + ifs.seekg (0, std::ios::beg); + + if (!length) + { + LL_INFOS() << "Zero length file file: " << name << LL_ENDL; + return false; + } + + LLPointer image = LLImageFormatted::createFromType(codec); + llassert(image.notNull()); + + U8 *buffer = image->allocateData(length); + ifs.read ((char*)buffer, length); + ifs.close(); + + bool success; + + success = image->updateData(); + if (success) + { + if (j2c_lowest_mip_only && codec == IMG_CODEC_J2C) + { + S32 width = image->getWidth(); + S32 height = image->getHeight(); + S32 discard_level = 0; + while (width > 1 && height > 1 && discard_level < MAX_DISCARD_LEVEL) + { + width >>= 1; + height >>= 1; + discard_level++; + } + ((LLImageJ2C *)((LLImageFormatted*)image))->setDiscardLevel(discard_level); + } + success = image->decode(this, 100000.0f); + } + + image = NULL; // deletes image + if (!success) + { + deleteData(); + LL_WARNS() << "Unable to decode image" << name << LL_ENDL; + return false; + } + + return true; } #endif //--------------------------------------------------------------------------- @@ -2108,21 +2108,21 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip S32 LLImageFormatted::sGlobalFormattedMemory = 0; LLImageFormatted::LLImageFormatted(S8 codec) - : LLImageBase(), - mCodec(codec), - mDecoding(0), - mDecoded(0), - mDiscardLevel(-1), - mLevels(0) + : LLImageBase(), + mCodec(codec), + mDecoding(0), + mDecoded(0), + mDiscardLevel(-1), + mLevels(0) { } // virtual LLImageFormatted::~LLImageFormatted() { - // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData() - // NOT LLImageFormatted::deleteData() - deleteData(); + // NOTE: ~LLimageBase() call to deleteData() calls LLImageBase::deleteData() + // NOT LLImageFormatted::deleteData() + deleteData(); } //---------------------------------------------------------------------------- @@ -2130,16 +2130,16 @@ LLImageFormatted::~LLImageFormatted() //virtual void LLImageFormatted::resetLastError() { - LLImage::setLastError(""); + LLImage::setLastError(""); } //virtual void LLImageFormatted::setLastError(const std::string& message, const std::string& filename) { - std::string error = message; - if (!filename.empty()) - error += std::string(" FILE: ") + filename; - LLImage::setLastError(error); + std::string error = message; + if (!filename.empty()) + error += std::string(" FILE: ") + filename; + LLImage::setLastError(error); } //---------------------------------------------------------------------------- @@ -2147,97 +2147,97 @@ void LLImageFormatted::setLastError(const std::string& message, const std::strin // static LLImageFormatted* LLImageFormatted::createFromType(S8 codec) { - LLImageFormatted* image; - switch(codec) - { - case IMG_CODEC_BMP: - image = new LLImageBMP(); - break; - case IMG_CODEC_TGA: - image = new LLImageTGA(); - break; - case IMG_CODEC_JPEG: - image = new LLImageJPEG(); - break; - case IMG_CODEC_PNG: - image = new LLImagePNG(); - break; - case IMG_CODEC_J2C: - image = new LLImageJ2C(); - break; - case IMG_CODEC_DXT: - image = new LLImageDXT(); - break; - default: - image = NULL; - break; - } - return image; + LLImageFormatted* image; + switch(codec) + { + case IMG_CODEC_BMP: + image = new LLImageBMP(); + break; + case IMG_CODEC_TGA: + image = new LLImageTGA(); + break; + case IMG_CODEC_JPEG: + image = new LLImageJPEG(); + break; + case IMG_CODEC_PNG: + image = new LLImagePNG(); + break; + case IMG_CODEC_J2C: + image = new LLImageJ2C(); + break; + case IMG_CODEC_DXT: + image = new LLImageDXT(); + break; + default: + image = NULL; + break; + } + return image; } // static LLImageFormatted* LLImageFormatted::createFromExtension(const std::string& instring) { - std::string exten; - size_t dotidx = instring.rfind('.'); - if (dotidx != std::string::npos) - { - exten = instring.substr(dotidx+1); - } - else - { - exten = instring; - } - S8 codec = getCodecFromExtension(exten); - return createFromType(codec); + std::string exten; + size_t dotidx = instring.rfind('.'); + if (dotidx != std::string::npos) + { + exten = instring.substr(dotidx+1); + } + else + { + exten = instring; + } + S8 codec = getCodecFromExtension(exten); + return createFromType(codec); } //---------------------------------------------------------------------------- // virtual void LLImageFormatted::dump() { - LLImageBase::dump(); + LLImageBase::dump(); - LL_INFOS() << "LLImageFormatted" - << " mDecoding " << mDecoding - << " mCodec " << S32(mCodec) - << " mDecoded " << mDecoded - << LL_ENDL; + LL_INFOS() << "LLImageFormatted" + << " mDecoding " << mDecoding + << " mCodec " << S32(mCodec) + << " mDecoded " << mDecoded + << LL_ENDL; } //---------------------------------------------------------------------------- S32 LLImageFormatted::calcDataSize(S32 discard_level) { - if (discard_level < 0) - { - discard_level = mDiscardLevel; - } - S32 w = getWidth() >> discard_level; - S32 h = getHeight() >> discard_level; - w = llmax(w, 1); - h = llmax(h, 1); - return w * h * getComponents(); + if (discard_level < 0) + { + discard_level = mDiscardLevel; + } + S32 w = getWidth() >> discard_level; + S32 h = getHeight() >> discard_level; + w = llmax(w, 1); + h = llmax(h, 1); + return w * h * getComponents(); } S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes) { - llassert(bytes >= 0); - S32 discard_level = 0; - while (1) - { - S32 bytes_needed = calcDataSize(discard_level); // virtual - if (bytes_needed <= bytes) - { - break; - } - discard_level++; - if (discard_level > MAX_IMAGE_MIP) - { - return -1; - } - } - return discard_level; + llassert(bytes >= 0); + S32 discard_level = 0; + while (1) + { + S32 bytes_needed = calcDataSize(discard_level); // virtual + if (bytes_needed <= bytes) + { + break; + } + discard_level++; + if (discard_level > MAX_IMAGE_MIP) + { + return -1; + } + } + return discard_level; } @@ -2246,34 +2246,34 @@ S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes) // Subclasses that can handle more than 4 channels should override this function. bool LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel) { - llassert( (first_channel == 0) && (max_channel == 4) ); - return decode( raw_image, decode_time ); // Loads first 4 channels by default. -} + llassert( (first_channel == 0) && (max_channel == 4) ); + return decode( raw_image, decode_time ); // Loads first 4 channels by default. +} //---------------------------------------------------------------------------- // virtual U8* LLImageFormatted::allocateData(S32 size) { - U8* res = LLImageBase::allocateData(size); // calls deleteData() - sGlobalFormattedMemory += getDataSize(); - return res; + U8* res = LLImageBase::allocateData(size); // calls deleteData() + sGlobalFormattedMemory += getDataSize(); + return res; } // virtual U8* LLImageFormatted::reallocateData(S32 size) { - sGlobalFormattedMemory -= getDataSize(); - U8* res = LLImageBase::reallocateData(size); - sGlobalFormattedMemory += getDataSize(); - return res; + sGlobalFormattedMemory -= getDataSize(); + U8* res = LLImageBase::reallocateData(size); + sGlobalFormattedMemory += getDataSize(); + return res; } // virtual void LLImageFormatted::deleteData() { - sGlobalFormattedMemory -= getDataSize(); - LLImageBase::deleteData(); + sGlobalFormattedMemory -= getDataSize(); + LLImageBase::deleteData(); } //---------------------------------------------------------------------------- @@ -2281,196 +2281,196 @@ void LLImageFormatted::deleteData() // virtual void LLImageFormatted::sanityCheck() { - LLImageBase::sanityCheck(); + LLImageBase::sanityCheck(); - if (mCodec >= IMG_CODEC_EOF) - { - LL_ERRS() << "Failed LLImageFormatted::sanityCheck " - << "decoding " << S32(mDecoding) - << "decoded " << S32(mDecoded) - << "codec " << S32(mCodec) - << LL_ENDL; - } + if (mCodec >= IMG_CODEC_EOF) + { + LL_ERRS() << "Failed LLImageFormatted::sanityCheck " + << "decoding " << S32(mDecoding) + << "decoded " << S32(mDecoded) + << "codec " << S32(mCodec) + << LL_ENDL; + } } //---------------------------------------------------------------------------- bool LLImageFormatted::copyData(U8 *data, S32 size) { - if ( data && ((data != getData()) || (size != getDataSize())) ) - { - deleteData(); - allocateData(size); - memcpy(getData(), data, size); /* Flawfinder: ignore */ - } - return true; + if ( data && ((data != getData()) || (size != getDataSize())) ) + { + deleteData(); + allocateData(size); + memcpy(getData(), data, size); /* Flawfinder: ignore */ + } + return true; } // LLImageFormatted becomes the owner of data void LLImageFormatted::setData(U8 *data, S32 size) { - if (data && data != getData()) - { - deleteData(); - setDataAndSize(data, size); // Access private LLImageBase members + if (data && data != getData()) + { + deleteData(); + setDataAndSize(data, size); // Access private LLImageBase members - sGlobalFormattedMemory += getDataSize(); - } + sGlobalFormattedMemory += getDataSize(); + } } void LLImageFormatted::appendData(U8 *data, S32 size) { - if (data) - { - if (!getData()) - { - setData(data, size); - } - else - { - S32 cursize = getDataSize(); - S32 newsize = cursize + size; - reallocateData(newsize); - memcpy(getData() + cursize, data, size); - ll_aligned_free_16(data); - } - } + if (data) + { + if (!getData()) + { + setData(data, size); + } + else + { + S32 cursize = getDataSize(); + S32 newsize = cursize + size; + reallocateData(newsize); + memcpy(getData() + cursize, data, size); + ll_aligned_free_16(data); + } + } } //---------------------------------------------------------------------------- bool LLImageFormatted::load(const std::string &filename, int load_size) { - resetLastError(); - - S32 file_size = 0; - LLAPRFile infile ; - infile.open(filename, LL_APR_RB, NULL, &file_size); - apr_file_t* apr_file = infile.getFileHandle(); - if (!apr_file) - { - setLastError("Unable to open file for reading", filename); - return false; - } - if (file_size == 0) - { - setLastError("File is empty",filename); - return false; - } - - // Constrain the load size to acceptable values - if ((load_size == 0) || (load_size > file_size)) - { - load_size = file_size; - } - bool res; - U8 *data = allocateData(load_size); - if (data) - { - apr_size_t bytes_read = load_size; - apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read - if (s != APR_SUCCESS || (S32) bytes_read != load_size) - { - deleteData(); - setLastError("Unable to read file",filename); - res = false; - } - else - { - res = updateData(); - } - } - else - { - setLastError("Allocation failure", filename); - res = false; - } - - return res; + resetLastError(); + + S32 file_size = 0; + LLAPRFile infile ; + infile.open(filename, LL_APR_RB, NULL, &file_size); + apr_file_t* apr_file = infile.getFileHandle(); + if (!apr_file) + { + setLastError("Unable to open file for reading", filename); + return false; + } + if (file_size == 0) + { + setLastError("File is empty",filename); + return false; + } + + // Constrain the load size to acceptable values + if ((load_size == 0) || (load_size > file_size)) + { + load_size = file_size; + } + bool res; + U8 *data = allocateData(load_size); + if (data) + { + apr_size_t bytes_read = load_size; + apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read + if (s != APR_SUCCESS || (S32) bytes_read != load_size) + { + deleteData(); + setLastError("Unable to read file",filename); + res = false; + } + else + { + res = updateData(); + } + } + else + { + setLastError("Allocation failure", filename); + res = false; + } + + return res; } bool LLImageFormatted::save(const std::string &filename) { - resetLastError(); - - LLAPRFile outfile ; - outfile.open(filename, LL_APR_WB); - if (!outfile.getFileHandle()) - { - setLastError("Unable to open file for writing", filename); - return false; - } - - S32 result = outfile.write(getData(), getDataSize()); - outfile.close() ; + resetLastError(); + + LLAPRFile outfile ; + outfile.open(filename, LL_APR_WB); + if (!outfile.getFileHandle()) + { + setLastError("Unable to open file for writing", filename); + return false; + } + + S32 result = outfile.write(getData(), getDataSize()); + outfile.close() ; return (result != 0); } S8 LLImageFormatted::getCodec() const { - return mCodec; + return mCodec; } static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst) { - dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); - dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); - dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2); - dst[3] = (U8)(((U32)(a[3]) + b[3] + c[3] + d[3])>>2); + dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); + dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); + dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2); + dst[3] = (U8)(((U32)(a[3]) + b[3] + c[3] + d[3])>>2); } static void avg4_colors3(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst) { - dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); - dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); - dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2); + dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); + dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); + dst[2] = (U8)(((U32)(a[2]) + b[2] + c[2] + d[2])>>2); } static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst) { - dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); - dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); + dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); + dst[1] = (U8)(((U32)(a[1]) + b[1] + c[1] + d[1])>>2); } void LLImageBase::setDataAndSize(U8 *data, S32 size) -{ - ll_assert_aligned(data, 16); - mData = data; - mDataSize = size; -} +{ + ll_assert_aligned(data, 16); + mData = data; + mDataSize = size; +} //static void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 height, S32 nchannels) { - llassert(width > 0 && height > 0); - U8* data = mipdata; - S32 in_width = width*2; - for (S32 h=0; h>2); - break; - default: - LL_ERRS() << "generateMmip called with bad num channels" << LL_ENDL; - } - indata += nchannels*2; - data += nchannels; - } - indata += nchannels*in_width; // skip odd lines - } + llassert(width > 0 && height > 0); + U8* data = mipdata; + S32 in_width = width*2; + for (S32 h=0; h>2); + break; + default: + LL_ERRS() << "generateMmip called with bad num channels" << LL_ENDL; + } + indata += nchannels*2; + data += nchannels; + } + indata += nchannels*in_width; // skip odd lines + } } @@ -2479,69 +2479,69 @@ void LLImageBase::generateMip(const U8* indata, U8* mipdata, S32 width, S32 heig //static F32 LLImageBase::calc_download_priority(F32 virtual_size, F32 visible_pixels, S32 bytes_sent) { - F32 w_priority; - - F32 bytes_weight = 1.f; - if (!bytes_sent) - { - bytes_weight = 20.f; - } - else if (bytes_sent < 1000) - { - bytes_weight = 1.f; - } - else if (bytes_sent < 2000) - { - bytes_weight = 1.f/1.5f; - } - else if (bytes_sent < 4000) - { - bytes_weight = 1.f/3.f; - } - else if (bytes_sent < 8000) - { - bytes_weight = 1.f/6.f; - } - else if (bytes_sent < 16000) - { - bytes_weight = 1.f/12.f; - } - else if (bytes_sent < 32000) - { - bytes_weight = 1.f/20.f; - } - else if (bytes_sent < 64000) - { - bytes_weight = 1.f/32.f; - } - else - { - bytes_weight = 1.f/64.f; - } - bytes_weight *= bytes_weight; - - - //LL_INFOS() << "VS: " << virtual_size << LL_ENDL; - F32 virtual_size_factor = virtual_size / (10.f*10.f); - - // The goal is for weighted priority to be <= 0 when we've reached a point where - // we've sent enough data. - //LL_INFOS() << "BytesSent: " << bytes_sent << LL_ENDL; - //LL_INFOS() << "BytesWeight: " << bytes_weight << LL_ENDL; - //LL_INFOS() << "PreLog: " << bytes_weight * virtual_size_factor << LL_ENDL; - w_priority = (F32)log10(bytes_weight * virtual_size_factor); - - //LL_INFOS() << "PreScale: " << w_priority << LL_ENDL; - - // We don't want to affect how MANY bytes we send based on the visible pixels, but the order - // in which they're sent. We post-multiply so we don't change the zero point. - if (w_priority > 0.f) - { - F32 pixel_weight = (F32)log10(visible_pixels + 1)*3.0f; - w_priority *= pixel_weight; - } - - return w_priority; + F32 w_priority; + + F32 bytes_weight = 1.f; + if (!bytes_sent) + { + bytes_weight = 20.f; + } + else if (bytes_sent < 1000) + { + bytes_weight = 1.f; + } + else if (bytes_sent < 2000) + { + bytes_weight = 1.f/1.5f; + } + else if (bytes_sent < 4000) + { + bytes_weight = 1.f/3.f; + } + else if (bytes_sent < 8000) + { + bytes_weight = 1.f/6.f; + } + else if (bytes_sent < 16000) + { + bytes_weight = 1.f/12.f; + } + else if (bytes_sent < 32000) + { + bytes_weight = 1.f/20.f; + } + else if (bytes_sent < 64000) + { + bytes_weight = 1.f/32.f; + } + else + { + bytes_weight = 1.f/64.f; + } + bytes_weight *= bytes_weight; + + + //LL_INFOS() << "VS: " << virtual_size << LL_ENDL; + F32 virtual_size_factor = virtual_size / (10.f*10.f); + + // The goal is for weighted priority to be <= 0 when we've reached a point where + // we've sent enough data. + //LL_INFOS() << "BytesSent: " << bytes_sent << LL_ENDL; + //LL_INFOS() << "BytesWeight: " << bytes_weight << LL_ENDL; + //LL_INFOS() << "PreLog: " << bytes_weight * virtual_size_factor << LL_ENDL; + w_priority = (F32)log10(bytes_weight * virtual_size_factor); + + //LL_INFOS() << "PreScale: " << w_priority << LL_ENDL; + + // We don't want to affect how MANY bytes we send based on the visible pixels, but the order + // in which they're sent. We post-multiply so we don't change the zero point. + if (w_priority > 0.f) + { + F32 pixel_weight = (F32)log10(visible_pixels + 1)*3.0f; + w_priority *= pixel_weight; + } + + return w_priority; } //============================================================================ diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index c49184e338..a5f05d4380 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -1,25 +1,25 @@ -/** +/** * @file llimage.h * @brief Object for managing images and their textures. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -35,21 +35,21 @@ const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 const S32 MAX_IMAGE_MIP = 12; // 4096x4096 -// *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number +// *TODO : Use MAX_IMAGE_MIP as max discard level and modify j2c management so that the number // of levels is read from the header's file, not inferred from its size. const S32 MAX_DISCARD_LEVEL = 5; // JPEG2000 size constraints // Those are declared here as they are germane to other image constraints used in the viewer // and declared right here. Some come from the JPEG2000 spec, some conventions specific to SL. -const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec -const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is) -const S32 MAX_PRECINCT_SIZE = 4096; // No reason to be bigger than MAX_IMAGE_SIZE -const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE -const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks -const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec -const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!! -const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit) +const S32 MAX_DECOMPOSITION_LEVELS = 32; // Number of decomposition levels cannot exceed 32 according to jpeg2000 spec +const S32 MIN_DECOMPOSITION_LEVELS = 5; // the SL viewer will *crash* trying to decode images with fewer than 5 decomposition levels (unless image is small that is) +const S32 MAX_PRECINCT_SIZE = 4096; // No reason to be bigger than MAX_IMAGE_SIZE +const S32 MIN_PRECINCT_SIZE = 4; // Can't be smaller than MIN_BLOCK_SIZE +const S32 MAX_BLOCK_SIZE = 64; // Max total block size is 4096, hence 64x64 when using square blocks +const S32 MIN_BLOCK_SIZE = 4; // Min block dim is 4 according to jpeg2000 spec +const S32 MIN_LAYER_SIZE = 2000; // Size of the first quality layer (after header). Must be > to FIRST_PACKET_SIZE!! +const S32 MAX_NB_LAYERS = 64; // Max number of layers we'll entertain in SL (practical limit) const S32 MIN_IMAGE_SIZE = (1< scaled(S32 new_width, S32 new_height); - - // Fill the buffer with a constant color - void fill( const LLColor4U& color ); + + // Fill the buffer with a constant color + void fill( const LLColor4U& color ); // Multiply this raw image by the given color void tint( const LLColor3& color ); - // Copy operations - - //duplicate this raw image if refCount > 1. - LLPointer duplicate(); + // Copy operations + + //duplicate this raw image if refCount > 1. + LLPointer duplicate(); - // Src and dst can be any size. Src and dst can each have 3 or 4 components. - void copy( LLImageRaw* src ); + // Src and dst can be any size. Src and dst can each have 3 or 4 components. + void copy( LLImageRaw* src ); - // Src and dst are same size. Src and dst have same number of components. - void copyUnscaled( LLImageRaw* src ); - - // Src and dst are same size. Src has 4 components. Dst has 3 components. - void copyUnscaled4onto3( LLImageRaw* src ); + // Src and dst are same size. Src and dst have same number of components. + void copyUnscaled( LLImageRaw* src ); - // Src and dst are same size. Src has 3 components. Dst has 4 components. - void copyUnscaled3onto4( LLImageRaw* src ); + // Src and dst are same size. Src has 4 components. Dst has 3 components. + void copyUnscaled4onto3( LLImageRaw* src ); - // Src and dst are same size. Src has 1 component. Dst has 4 components. - // Alpha component is set to source alpha mask component. - // RGB components are set to fill color. - void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill); + // Src and dst are same size. Src has 3 components. Dst has 4 components. + void copyUnscaled3onto4( LLImageRaw* src ); - // Src and dst can be any size. Src and dst have same number of components. - void copyScaled( LLImageRaw* src ); + // Src and dst are same size. Src has 1 component. Dst has 4 components. + // Alpha component is set to source alpha mask component. + // RGB components are set to fill color. + void copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill); - // Src and dst can be any size. Src has 3 components. Dst has 4 components. - void copyScaled3onto4( LLImageRaw* src ); + // Src and dst can be any size. Src and dst have same number of components. + void copyScaled( LLImageRaw* src ); - // Src and dst can be any size. Src has 4 components. Dst has 3 components. - void copyScaled4onto3( LLImageRaw* src ); + // Src and dst can be any size. Src has 3 components. Dst has 4 components. + void copyScaled3onto4( LLImageRaw* src ); + // Src and dst can be any size. Src has 4 components. Dst has 3 components. + void copyScaled4onto3( LLImageRaw* src ); - // Composite operations - // Src and dst can be any size. Src and dst can each have 3 or 4 components. - void composite( LLImageRaw* src ); + // Composite operations - // Src and dst can be any size. Src has 4 components. Dst has 3 components. - void compositeScaled4onto3( LLImageRaw* src ); + // Src and dst can be any size. Src and dst can each have 3 or 4 components. + void composite( LLImageRaw* src ); - // Src and dst are same size. Src has 4 components. Dst has 3 components. - void compositeUnscaled4onto3( LLImageRaw* src ); + // Src and dst can be any size. Src has 4 components. Dst has 3 components. + void compositeScaled4onto3( LLImageRaw* src ); + + // Src and dst are same size. Src has 4 components. Dst has 3 components. + void compositeUnscaled4onto3( LLImageRaw* src ); // Emissive operations used by minimap // Roughly emulates GLTF emissive texture, but is not GLTF-compliant @@ -283,21 +283,21 @@ public: void addEmissiveScaled(LLImageRaw* src); void addEmissiveUnscaled(LLImageRaw* src); protected: - // Create an image from a local file (generally used in tools) - //bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false); + // Create an image from a local file (generally used in tools) + //bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false); - void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ); - void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len ); + void copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ); + void compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len ); - U8 fastFractionalMult(U8 a,U8 b); + U8 fastFractionalMult(U8 a,U8 b); - void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; + void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static S32 sRawImageCount; + static S32 sRawImageCount; private: - bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst); + bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst); }; // Compressed representation of image. @@ -305,74 +305,74 @@ private: class LLImageFormatted : public LLImageBase { public: - static LLImageFormatted* createFromType(S8 codec); - static LLImageFormatted* createFromExtension(const std::string& instring); + static LLImageFormatted* createFromType(S8 codec); + static LLImageFormatted* createFromExtension(const std::string& instring); protected: - /*virtual*/ ~LLImageFormatted(); - + /*virtual*/ ~LLImageFormatted(); + public: - LLImageFormatted(S8 codec); - - // LLImageBase - /*virtual*/ void deleteData(); - /*virtual*/ U8* allocateData(S32 size = -1); - /*virtual*/ U8* reallocateData(S32 size); - - /*virtual*/ void dump(); - /*virtual*/ void sanityCheck(); - - // New methods - // subclasses must return a prefered file extension (lowercase without a leading dot) - virtual std::string getExtension() = 0; - // calcHeaderSize() returns the maximum size of header; - // 0 indicates we don't have a header and have to read the entire file - virtual S32 calcHeaderSize() { return 0; }; - // calcDataSize() returns how many bytes to read to load discard_level (including header) - virtual S32 calcDataSize(S32 discard_level); - // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes - virtual S32 calcDiscardLevelBytes(S32 bytes); - // getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C) - virtual S8 getRawDiscardLevel() { return mDiscardLevel; } - - bool load(const std::string& filename, int load_size = 0); - bool save(const std::string& filename); - - virtual bool updateData() = 0; // pure virtual - void setData(U8 *data, S32 size); - void appendData(U8 *data, S32 size); - - // Loads first 4 channels. - virtual bool decode(LLImageRaw* raw_image, F32 decode_time) = 0; - // Subclasses that can handle more than 4 channels should override this function. - virtual bool decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel); - - virtual bool encode(const LLImageRaw* raw_image, F32 encode_time) = 0; - - S8 getCodec() const; - bool isDecoding() const { return mDecoding; } - bool isDecoded() const { return mDecoded; } - void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; } - S8 getDiscardLevel() const { return mDiscardLevel; } - S8 getLevels() const { return mLevels; } - void setLevels(S8 nlevels) { mLevels = nlevels; } - - // setLastError needs to be deferred for J2C images since it may be called from a DLL - virtual void resetLastError(); - virtual void setLastError(const std::string& message, const std::string& filename = std::string()); - + LLImageFormatted(S8 codec); + + // LLImageBase + /*virtual*/ void deleteData(); + /*virtual*/ U8* allocateData(S32 size = -1); + /*virtual*/ U8* reallocateData(S32 size); + + /*virtual*/ void dump(); + /*virtual*/ void sanityCheck(); + + // New methods + // subclasses must return a prefered file extension (lowercase without a leading dot) + virtual std::string getExtension() = 0; + // calcHeaderSize() returns the maximum size of header; + // 0 indicates we don't have a header and have to read the entire file + virtual S32 calcHeaderSize() { return 0; }; + // calcDataSize() returns how many bytes to read to load discard_level (including header) + virtual S32 calcDataSize(S32 discard_level); + // calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes + virtual S32 calcDiscardLevelBytes(S32 bytes); + // getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C) + virtual S8 getRawDiscardLevel() { return mDiscardLevel; } + + bool load(const std::string& filename, int load_size = 0); + bool save(const std::string& filename); + + virtual bool updateData() = 0; // pure virtual + void setData(U8 *data, S32 size); + void appendData(U8 *data, S32 size); + + // Loads first 4 channels. + virtual bool decode(LLImageRaw* raw_image, F32 decode_time) = 0; + // Subclasses that can handle more than 4 channels should override this function. + virtual bool decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel); + + virtual bool encode(const LLImageRaw* raw_image, F32 encode_time) = 0; + + S8 getCodec() const; + bool isDecoding() const { return mDecoding; } + bool isDecoded() const { return mDecoded; } + void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; } + S8 getDiscardLevel() const { return mDiscardLevel; } + S8 getLevels() const { return mLevels; } + void setLevels(S8 nlevels) { mLevels = nlevels; } + + // setLastError needs to be deferred for J2C images since it may be called from a DLL + virtual void resetLastError(); + virtual void setLastError(const std::string& message, const std::string& filename = std::string()); + protected: - bool copyData(U8 *data, S32 size); // calls updateData() - + bool copyData(U8 *data, S32 size); // calls updateData() + protected: - S8 mCodec; - S8 mDecoding; - S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC - S8 mDiscardLevel; // Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc... - S8 mLevels; // Number of resolution levels in that image. Min is 1. 0 means unknown. - + S8 mCodec; + S8 mDecoding; + S8 mDecoded; // unused, but changing LLImage layout requires recompiling static Mac/Linux libs. 2009-01-30 JC + S8 mDiscardLevel; // Current resolution level worked on. 0 = full res, 1 = half res, 2 = quarter res, etc... + S8 mLevels; // Number of resolution levels in that image. Min is 1. 0 means unknown. + public: - static S32 sGlobalFormattedMemory; + static S32 sGlobalFormattedMemory; }; #endif diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 6688dadd3a..1e332e0154 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -51,9 +51,9 @@ namespace { F32 cosPhi = cos(altitude); LLVector3 dir; - // +x right, +z up, +y at... + // +x right, +z up, +y at... dir.mV[0] = cosTheta * cosPhi; - dir.mV[1] = sinTheta * cosPhi; + dir.mV[1] = sinTheta * cosPhi; dir.mV[2] = sinPhi; LLVector3 axis = LLVector3::x_axis % dir; @@ -156,23 +156,23 @@ LLSettingsSky::validation_list_t legacyHazeValidationList() static LLSettingsBase::validation_list_t legacyHazeValidation; if (legacyHazeValidation.empty()) { - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray, boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(3.0f, 3.0f, 3.0f, "*")))); - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray, boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(3.0f, 3.0f, 3.0f, "*")))); - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray, boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(3.0f, 3.0f, 3.0f, "*")))); - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 5.0f)))); - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 5.0f)))); - legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal, + legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0001f, 2.0f)))); legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0001f, 1000.0f)))); @@ -185,19 +185,19 @@ LLSettingsSky::validation_list_t rayleighValidationList() static LLSettingsBase::validation_list_t rayleighValidation; if (rayleighValidation.empty()) { - rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f)))); - rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - - rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f)))); - rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); } return rayleighValidation; @@ -208,19 +208,19 @@ LLSettingsSky::validation_list_t absorptionValidationList() static LLSettingsBase::validation_list_t absorptionValidation; if (absorptionValidation.empty()) { - absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f)))); - absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - - absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f)))); - absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); } return absorptionValidation; @@ -231,22 +231,22 @@ LLSettingsSky::validation_list_t mieValidationList() static LLSettingsBase::validation_list_t mieValidation; if (mieValidation.empty()) { - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 32768.0f)))); - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, + + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(-1.0f, 1.0f)))); - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 2.0f)))); - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); - mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal, + mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal, boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); } return mieValidation; @@ -296,7 +296,7 @@ bool validateRayleighLayers(LLSD &value, U32 flags) } } return allGood; - } + } llassert(value.type() == LLSD::TypeMap); LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations, flags); if (result["errors"].size() > 0) @@ -317,7 +317,7 @@ bool validateAbsorptionLayers(LLSD &value, U32 flags) LLSettingsBase::validation_list_t absorptionValidations = absorptionValidationList(); if (value.isArray()) { - bool allGood = true; + bool allGood = true; for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf) { LLSD& layerConfig = (*itf); @@ -443,7 +443,7 @@ void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother) mNextHaloTextureId = pother->mNextHaloTextureId; } -void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) +void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) { LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT; llassert(getSettingsType() == end->getSettingsType()); @@ -529,8 +529,8 @@ LLSettingsSky::stringset_t LLSettingsSky::getSkipInterpolateKeys() const return skipSet; } -LLSettingsSky::stringset_t LLSettingsSky::getSlerpKeys() const -{ +LLSettingsSky::stringset_t LLSettingsSky::getSlerpKeys() const +{ static stringset_t slepSet; if (slepSet.empty()) @@ -557,53 +557,53 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList() validation.push_back(Validator(SETTING_RAINBOW_TEXTUREID, false, LLSD::TypeUUID)); validation.push_back(Validator(SETTING_HALO_TEXTUREID, false, LLSD::TypeUUID)); - validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(1.0f, 1.0f, 1.0f, "*")))); - validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(1.0f, 1.0f, 3.0f, "*")))); - validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(1.0f, 1.0f, 1.0f, "*")))); - validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.001f, 3.0f)))); - validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(-50.0f, -50.0f), llsd::array(50.0f, 50.0f)))); - validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); validation.push_back(Validator(SETTING_CLOUD_TEXTUREID, false, LLSD::TypeUUID)); - validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); - validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); - validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 2000.0f)))); - validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 20.0f)))); - validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(0.2f, "*", -10.0f, "*"), llsd::array(40.0f, "*", 10.0f, "*")))); - - validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal, + + validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 10000.0f)))); validation.push_back(Validator(SETTING_MOON_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal)); validation.push_back(Validator(SETTING_MOON_SCALE, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.25f, 20.0f)), LLSD::Real(1.0))); validation.push_back(Validator(SETTING_MOON_TEXTUREID, false, LLSD::TypeUUID)); - validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); - validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 500.0f)))); - validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray, + validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray, boost::bind(&Validator::verifyVectorMinMax, _1, _2, llsd::array(0.0f, 0.0f, 0.0f, "*"), llsd::array(3.0f, 3.0f, 3.0f, "*")))); @@ -612,25 +612,25 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList() boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.25f, 20.0f)), LLSD::Real(1.0))); validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID)); - validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f)))); - validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f)))); - validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(1000.0f, 32768.0f)))); - validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 0.1f)))); - validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); - validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(5.0f, 1000.0f)))); - validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal, + validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(0.0f, 1.0f)))); validation.push_back(Validator(SETTING_REFLECTION_PROBE_AMBIANCE, false, LLSD::TypeReal, @@ -720,7 +720,7 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position) sunquat = convert_azimuth_and_altitude_to_quat(altitude, azimuth); moonquat = convert_azimuth_and_altitude_to_quat(altitude + (F_PI * 0.125f), azimuth + (F_PI * 0.125f)); - // Magic constants copied form dfltsetting.xml + // Magic constants copied form dfltsetting.xml dfltsetting[SETTING_CLOUD_COLOR] = LLColor4(0.4099, 0.4099, 0.4099, 0.0).getValue(); dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue(); dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue(); @@ -733,7 +733,7 @@ LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position) dfltsetting[SETTING_DOME_RADIUS] = LLSD::Real(15000.f); dfltsetting[SETTING_GAMMA] = LLSD::Real(1.0); dfltsetting[SETTING_GLOW] = LLColor4(5.000, 0.0010, -0.4799, 1.0).getValue(); - + dfltsetting[SETTING_MAX_Y] = LLSD::Real(1605); dfltsetting[SETTING_MOON_ROTATION] = moonquat.getValue(); dfltsetting[SETTING_MOON_BRIGHTNESS] = LLSD::Real(0.5f); @@ -777,7 +777,7 @@ LLSD LLSettingsSky::translateLegacyHazeSettings(const LLSD& legacy) // AdvancedAtmospherics TODO // These need to be translated into density profile info in the new settings format... -// LEGACY_ATMOSPHERICS +// LEGACY_ATMOSPHERICS if (legacy.has(SETTING_AMBIENT)) { legacyhazesettings[SETTING_AMBIENT] = LLColor3(legacy[SETTING_AMBIENT]).getValue(); @@ -867,7 +867,7 @@ LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy) newsettings[SETTING_CLOUD_SHADOW] = LLSD::Real(legacy[SETTING_CLOUD_SHADOW][0].asReal()); converted_something |= true; } - + if (legacy.has(SETTING_GAMMA)) { @@ -925,7 +925,7 @@ LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy) // get counter-clockwise radian angle from clockwise legacy WL east angle... F32 azimuth = -legacy[SETTING_LEGACY_EAST_ANGLE].asReal(); F32 altitude = legacy[SETTING_LEGACY_SUN_ANGLE].asReal(); - + LLQuaternion sunquat = convert_azimuth_and_altitude_to_quat(azimuth, altitude); // original WL moon dir was diametrically opposed to the sun dir LLQuaternion moonquat = convert_azimuth_and_altitude_to_quat(azimuth + F_PI, -altitude); @@ -1240,9 +1240,9 @@ LLColor3 LLSettingsSky::gammaCorrect(const LLColor3& in,const F32 &gamma) const } LLColor3 color = in * 2.0f; - color = smear(1.f) - componentSaturate(color); // clamping after mul seems wrong, but prevents negative colors... - componentPow(color, gamma); - color = smear(1.f) - color; + color = smear(1.f) - componentSaturate(color); // clamping after mul seems wrong, but prevents negative colors... + componentPow(color, gamma); + color = smear(1.f) - color; return color; } @@ -1352,7 +1352,7 @@ void LLSettingsSky::calculateLightSettings() const mSunAmbient = tmpAmbient; F32 haze_horizon = getHazeHorizon(); - + sunlight *= 1.0 - cloud_shadow; sunlight += tmpAmbient; @@ -1462,7 +1462,7 @@ F32 LLSettingsSky::getMieAnisotropy() const { return getMieConfig()[SETTING_MIE_ANISOTROPY_FACTOR].asReal(); } - + LLSD LLSettingsSky::getRayleighConfig() const { LLSD copy = *(mSettings[SETTING_RAYLEIGH_CONFIG].beginArray()); @@ -1480,7 +1480,7 @@ LLSD LLSettingsSky::getAbsorptionConfig() const LLSD copy = *(mSettings[SETTING_ABSORPTION_CONFIG].beginArray()); return copy; } - + LLSD LLSettingsSky::getRayleighConfigs() const { return mSettings[SETTING_RAYLEIGH_CONFIG]; @@ -1622,13 +1622,13 @@ void LLSettingsSky::setCloudVariance(F32 val) F32 LLSettingsSky::getDomeOffset() const { //return mSettings[SETTING_DOME_OFFSET].asReal(); - return DOME_OFFSET; + return DOME_OFFSET; } F32 LLSettingsSky::getDomeRadius() const { //return mSettings[SETTING_DOME_RADIUS].asReal(); - return DOME_RADIUS; + return DOME_RADIUS; } F32 LLSettingsSky::getGamma() const @@ -1657,7 +1657,7 @@ F32 LLSettingsSky::getMaxY() const return mSettings[SETTING_MAX_Y].asReal(); } -void LLSettingsSky::setMaxY(F32 val) +void LLSettingsSky::setMaxY(F32 val) { setValue(SETTING_MAX_Y, val); } @@ -1741,7 +1741,7 @@ LLQuaternion LLSettingsSky::getSunRotation() const return LLQuaternion(mSettings[SETTING_SUN_ROTATION]); } -void LLSettingsSky::setSunRotation(const LLQuaternion &val) +void LLSettingsSky::setSunRotation(const LLQuaternion &val) { setValue(SETTING_SUN_ROTATION, val); } @@ -1762,7 +1762,7 @@ LLUUID LLSettingsSky::getSunTextureId() const return mSettings[SETTING_SUN_TEXTUREID].asUUID(); } -void LLSettingsSky::setSunTextureId(LLUUID id) +void LLSettingsSky::setSunTextureId(LLUUID id) { setValue(SETTING_SUN_TEXTUREID, id); } @@ -1788,7 +1788,7 @@ LLUUID LLSettingsSky::getNextBloomTextureId() const } // if true, this sky is a candidate for auto-adjustment -bool LLSettingsSky::canAutoAdjust() const -{ +bool LLSettingsSky::canAutoAdjust() const +{ return !mSettings.has(SETTING_REFLECTION_PROBE_AMBIANCE); } diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index e1d3536f66..b6e0e4a2be 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -1,25 +1,25 @@ -/** +/** * @file llcamera.h * @brief Header file for the LLCamera class. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -33,26 +33,26 @@ #include "llplane.h" #include "llvector4a.h" -const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; -const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; -const F32 DEFAULT_NEAR_PLANE = 0.25f; -const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions +const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; +const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; +const F32 DEFAULT_NEAR_PLANE = 0.25f; +const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions -const F32 MAX_ASPECT_RATIO = 50.0f; -const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends -const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. -const F32 MAX_FAR_CLIP = 512.0f; +const F32 MAX_ASPECT_RATIO = 50.0f; +const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends +const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though. +const F32 MAX_FAR_CLIP = 512.0f; -const F32 MIN_ASPECT_RATIO = 0.02f; -const F32 MIN_NEAR_PLANE = 0.1f; -const F32 MIN_FAR_PLANE = 0.2f; +const F32 MIN_ASPECT_RATIO = 0.02f; +const F32 MIN_NEAR_PLANE = 0.1f; +const F32 MIN_FAR_PLANE = 0.2f; // Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio. static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD; static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; // An LLCamera is an LLCoorFrame with a view frustum. -// This means that it has several methods for moving it around +// This means that it has several methods for moving it around // that are inherited from the LLCoordFrame() class : // // setOrigin(), setAxes() @@ -62,162 +62,162 @@ static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD; LL_ALIGN_PREFIX(16) class LLCamera -: public LLCoordFrame +: public LLCoordFrame { public: - LLCamera(const LLCamera& rhs) - { - *this = rhs; - } - - enum { - PLANE_LEFT = 0, - PLANE_RIGHT = 1, - PLANE_BOTTOM = 2, - PLANE_TOP = 3, - PLANE_NUM = 4, - PLANE_MASK_NONE = 0xff // Disable this plane - }; - enum { - PLANE_LEFT_MASK = (1<size[i] + fAWdU[i]) return false; - } + for (U32 i = 0; i < 3; i++) + { + dir[i] = 0.5f * (end[i] - start[i]); + diff[i] = (0.5f * (end[i] + start[i])) - center[i]; + fAWdU[i] = fabsf(dir[i]); + if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; + } - float f; - f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; - f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; - f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; - - return true; + float f; + f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; + f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; + f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; + + return true; } // Finds tangent vec based on three vertices with texture coordinates. // Fills in dummy values if the triangle has degenerate texture coordinates. void calc_tangent_from_triangle( - LLVector4a& normal, - LLVector4a& tangent_out, - const LLVector4a& v1, - const LLVector2& w1, - const LLVector4a& v2, - const LLVector2& w2, - const LLVector4a& v3, - const LLVector2& w3) -{ - const F32* v1ptr = v1.getF32ptr(); - const F32* v2ptr = v2.getF32ptr(); - const F32* v3ptr = v3.getF32ptr(); + LLVector4a& normal, + LLVector4a& tangent_out, + const LLVector4a& v1, + const LLVector2& w1, + const LLVector4a& v2, + const LLVector2& w2, + const LLVector4a& v3, + const LLVector2& w3) +{ + const F32* v1ptr = v1.getF32ptr(); + const F32* v2ptr = v2.getF32ptr(); + const F32* v3ptr = v3.getF32ptr(); + + float x1 = v2ptr[0] - v1ptr[0]; + float x2 = v3ptr[0] - v1ptr[0]; + float y1 = v2ptr[1] - v1ptr[1]; + float y2 = v3ptr[1] - v1ptr[1]; + float z1 = v2ptr[2] - v1ptr[2]; + float z2 = v3ptr[2] - v1ptr[2]; + + float s1 = w2.mV[0] - w1.mV[0]; + float s2 = w3.mV[0] - w1.mV[0]; + float t1 = w2.mV[1] - w1.mV[1]; + float t2 = w3.mV[1] - w1.mV[1]; + + F32 rd = s1*t2-s2*t1; + + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero + + llassert(llfinite(r)); + llassert(!llisnan(r)); + + LLVector4a sdir( + (t2 * x1 - t1 * x2) * r, + (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + + LLVector4a tdir( + (s1 * x2 - s2 * x1) * r, + (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + + LLVector4a n = normal; + LLVector4a t = sdir; + + LLVector4a ncrosst; + ncrosst.setCross3(n,t); + + // Gram-Schmidt orthogonalize + n.mul(n.dot3(t).getF32()); + + LLVector4a tsubn; + tsubn.setSub(t,n); + + if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) + { + tsubn.normalize3fast_checked(); - float x1 = v2ptr[0] - v1ptr[0]; - float x2 = v3ptr[0] - v1ptr[0]; - float y1 = v2ptr[1] - v1ptr[1]; - float y2 = v3ptr[1] - v1ptr[1]; - float z1 = v2ptr[2] - v1ptr[2]; - float z2 = v3ptr[2] - v1ptr[2]; + // Calculate handedness + F32 handedness = ncrosst.dot3(tdir).getF32() < 0.f ? -1.f : 1.f; - float s1 = w2.mV[0] - w1.mV[0]; - float s2 = w3.mV[0] - w1.mV[0]; - float t1 = w2.mV[1] - w1.mV[1]; - float t2 = w3.mV[1] - w1.mV[1]; + tsubn.getF32ptr()[3] = handedness; - F32 rd = s1*t2-s2*t1; + tangent_out = tsubn; + } + else + { + // degenerate, make up a value + // + tangent_out.set(0,0,1,1); + } - float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) - : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero +} - llassert(llfinite(r)); - llassert(!llisnan(r)); - LLVector4a sdir( - (t2 * x1 - t1 * x2) * r, - (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); +// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. +// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, +// and returns the intersection point along dir in intersection_t. - LLVector4a tdir( - (s1 * x2 - s2 * x1) * r, - (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); +// Moller-Trumbore algorithm +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ - LLVector4a n = normal; - LLVector4a t = sdir; + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); - LLVector4a ncrosst; - ncrosst.setCross3(n,t); + LLVector4a edge2; + edge2.setSub(vert2, vert0); - // Gram-Schmidt orthogonalize - n.mul(n.dot3(t).getF32()); + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); - LLVector4a tsubn; - tsubn.setSub(t,n); + /* if determinant is near zero, ray lies in plane of triangle */ + LLVector4a det; + det.setAllDot3(edge1, pvec); - if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) - { - tsubn.normalize3fast_checked(); + if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) + { + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); - // Calculate handedness - F32 handedness = ncrosst.dot3(tdir).getF32() < 0.f ? -1.f : 1.f; + /* calculate U parameter and test bounds */ + LLVector4a u; + u.setAllDot3(tvec,pvec); - tsubn.getF32ptr()[3] = handedness; + if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && + (u.lessEqual(det).getGatheredBits() & 0x7)) + { + /* prepare to test V parameter */ + LLVector4a qvec; + qvec.setCross3(tvec, edge1); - tangent_out = tsubn; - } - else - { - // degenerate, make up a value - // - tangent_out.set(0,0,1,1); - } + /* calculate V parameter and test bounds */ + LLVector4a v; + v.setAllDot3(dir, qvec); -} + //if (!(v < 0.f || u + v > det)) -// intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. -// returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, -// and returns the intersection point along dir in intersection_t. + LLVector4a sum_uv; + sum_uv.setAdd(u, v); -// Moller-Trumbore algorithm -BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - LLVector4a det; - det.setAllDot3(edge1, pvec); - - if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) - { - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - LLVector4a u; - u.setAllDot3(tvec,pvec); - - if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && - (u.lessEqual(det).getGatheredBits() & 0x7)) - { - /* prepare to test V parameter */ - LLVector4a qvec; - qvec.setCross3(tvec, edge1); - - /* calculate V parameter and test bounds */ - LLVector4a v; - v.setAllDot3(dir, qvec); - - - //if (!(v < 0.f || u + v > det)) - - LLVector4a sum_uv; - sum_uv.setAdd(u, v); - - S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; - S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; - - if (v_gequal && sum_lequal) - { - /* calculate t, scale parameters, ray intersects triangle */ - LLVector4a t; - t.setAllDot3(edge2,qvec); - - t.div(det); - u.div(det); - v.div(det); - - intersection_a = u[0]; - intersection_b = v[0]; - intersection_t = t[0]; - return TRUE; - } - } - } - - return FALSE; -} + S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; + S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; + + if (v_gequal && sum_lequal) + { + /* calculate t, scale parameters, ray intersects triangle */ + LLVector4a t; + t.setAllDot3(edge2,qvec); + + t.div(det); + u.div(det); + v.div(det); + + intersection_a = u[0]; + intersection_b = v[0]; + intersection_t = t[0]; + return TRUE; + } + } + } + + return FALSE; +} BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t) -{ - F32 u, v, t; - - /* find vectors for two edges sharing vert0 */ - LLVector4a edge1; - edge1.setSub(vert1, vert0); - - - LLVector4a edge2; - edge2.setSub(vert2, vert0); - - /* begin calculating determinant - also used to calculate U parameter */ - LLVector4a pvec; - pvec.setCross3(dir, edge2); - - /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1.dot3(pvec).getF32(); - - - if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) - { - return FALSE; - } - - F32 inv_det = 1.f / det; - - /* calculate distance from vert0 to ray origin */ - LLVector4a tvec; - tvec.setSub(orig, vert0); - - /* calculate U parameter and test bounds */ - u = (tvec.dot3(pvec).getF32()) * inv_det; - if (u < 0.f || u > 1.f) - { - return FALSE; - } - - /* prepare to test V parameter */ - tvec.sub(edge1); - - /* calculate V parameter and test bounds */ - v = (dir.dot3(tvec).getF32()) * inv_det; - - if (v < 0.f || u + v > 1.f) - { - return FALSE; - } - - /* calculate t, ray intersects triangle */ - t = (edge2.dot3(tvec).getF32()) * inv_det; - - intersection_a = u; - intersection_b = v; - intersection_t = t; - - - return TRUE; -} + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ + F32 u, v, t; + + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); + + + LLVector4a edge2; + edge2.setSub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + F32 det = edge1.dot3(pvec).getF32(); + + + if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) + { + return FALSE; + } + + F32 inv_det = 1.f / det; + + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); + + /* calculate U parameter and test bounds */ + u = (tvec.dot3(pvec).getF32()) * inv_det; + if (u < 0.f || u > 1.f) + { + return FALSE; + } + + /* prepare to test V parameter */ + tvec.sub(edge1); + + /* calculate V parameter and test bounds */ + v = (dir.dot3(tvec).getF32()) * inv_det; + + if (v < 0.f || u + v > 1.f) + { + return FALSE; + } + + /* calculate t, ray intersects triangle */ + t = (edge2.dot3(tvec).getF32()) * inv_det; + + intersection_a = u; + intersection_b = v; + intersection_t = t; + + + return TRUE; +} //helper for non-aligned vectors BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided) -{ - LLVector4a vert0a, vert1a, vert2a, origa, dira; - vert0a.load3(vert0.mV); - vert1a.load3(vert1.mV); - vert2a.load3(vert2.mV); - origa.load3(orig.mV); - dira.load3(dir.mV); - - if (two_sided) - { - return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira, - intersection_a, intersection_b, intersection_t); - } - else - { - return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira, - intersection_a, intersection_b, intersection_t); - } + F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided) +{ + LLVector4a vert0a, vert1a, vert2a, origa, dira; + vert0a.load3(vert0.mV); + vert1a.load3(vert1.mV); + vert2a.load3(vert2.mV); + origa.load3(orig.mV); + dira.load3(dir.mV); + + if (two_sided) + { + return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } + else + { + return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } } //------------------------------------------------------------------- @@ -385,5141 +385,5141 @@ BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, cons LLProfile::Face* LLProfile::addCap(S16 faceID) { - Face *face = vector_append(mFaces, 1); - - face->mIndex = 0; - face->mCount = mTotal; - face->mScaleU= 1.0f; - face->mCap = TRUE; - face->mFaceID = faceID; - return face; + Face *face = vector_append(mFaces, 1); + + face->mIndex = 0; + face->mCount = mTotal; + face->mScaleU= 1.0f; + face->mCap = TRUE; + face->mFaceID = faceID; + return face; } LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BOOL flat) { - Face *face = vector_append(mFaces, 1); - - face->mIndex = i; - face->mCount = count; - face->mScaleU= scaleU; + Face *face = vector_append(mFaces, 1); - face->mFlat = flat; - face->mCap = FALSE; - face->mFaceID = faceID; - return face; + face->mIndex = i; + face->mCount = count; + face->mScaleU= scaleU; + + face->mFlat = flat; + face->mCap = FALSE; + face->mFaceID = faceID; + return face; } //static S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) { // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points - S32 np = 0; - - // Generate an n-sided "circular" path. - // 0 is (1,0), and we go counter-clockwise along a circular path from there. - F32 t, t_step, t_first, t_fraction; - - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - - t_step = 1.0f / sides; - - t_first = floor(begin * sides) / (F32)sides; - - // pt1 is the first point on the fractional face. - // Starting t and ang values for the first face - t = t_first; - - // Increment to the next point. - // pt2 is the end point on the fractional face - t += t_step; - - t_fraction = (begin - t_first)*sides; - - // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.9999f) - { - np++; - } - - // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 - while (t < end) - { - // Iterate through all the integer steps of t. - np++; - - t += t_step; - } - - t_fraction = (end - (t - t_step))*sides; - - // Find the fraction that we need to add to the end point. - t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.0001f) - { - np++; - } - - // If we're sliced, the profile is open. - if ((end - begin)*ang_scale < 0.99f) - { - if (params.getHollow() <= 0) - { - // put center point if not hollow. - np++; - } - } - - return np; -} - -// What is the bevel parameter used for? - DJS 04/05/02 -// Bevel parameter is currently unused but presumedly would support -// filleted and chamfered corners -void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) -{ - // Generate an n-sided "circular" path. - // 0 is (1,0), and we go counter-clockwise along a circular path from there. - static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - F32 scale = 0.5f; - F32 t, t_step, t_first, t_fraction, ang, ang_step; - LLVector4a pt1,pt2; - - F32 begin = params.getBegin(); - F32 end = params.getEnd(); - - t_step = 1.0f / sides; - ang_step = 2.0f*F_PI*t_step*ang_scale; - - // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. - - S32 total_sides = ll_round(sides / ang_scale); // Total number of sides all around - - if (total_sides < 8) - { - scale = tableScale[total_sides]; - } - - t_first = floor(begin * sides) / (F32)sides; - - // pt1 is the first point on the fractional face. - // Starting t and ang values for the first face - t = t_first; - ang = 2.0f*F_PI*(t*ang_scale + offset); - pt1.set(cos(ang)*scale,sin(ang)*scale, t); - - // Increment to the next point. - // pt2 is the end point on the fractional face - t += t_step; - ang += ang_step; - pt2.set(cos(ang)*scale,sin(ang)*scale,t); - - t_fraction = (begin - t_first)*sides; - - // Only use if it's not almost exactly on an edge. - if (t_fraction < 0.9999f) - { - LLVector4a new_pt; - new_pt.setLerp(pt1, pt2, t_fraction); - mProfile.push_back(new_pt); - } - - // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 - while (t < end) - { - // Iterate through all the integer steps of t. - pt1.set(cos(ang)*scale,sin(ang)*scale,t); - - if (mProfile.size() > 0) { - LLVector4a p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - //mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); - LLVector4a new_pt; - new_pt.setSub(pt1, p); - new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); - new_pt.add(p); - mProfile.push_back(new_pt); - } - } - mProfile.push_back(pt1); - - t += t_step; - ang += ang_step; - } - - t_fraction = (end - (t - t_step))*sides; - - // pt1 is the first point on the fractional face - // pt2 is the end point on the fractional face - pt2.set(cos(ang)*scale,sin(ang)*scale,t); - - // Find the fraction that we need to add to the end point. - t_fraction = (end - (t - t_step))*sides; - if (t_fraction > 0.0001f) - { - LLVector4a new_pt; - new_pt.setLerp(pt1, pt2, t_fraction); - - if (mProfile.size() > 0) { - LLVector4a p = mProfile[mProfile.size()-1]; - for (S32 i = 0; i < split && mProfile.size() > 0; i++) { - //mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); - - LLVector4a pt1; - pt1.setSub(new_pt, p); - pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); - pt1.add(p); - mProfile.push_back(pt1); - } - } - mProfile.push_back(new_pt); - } - - // If we're sliced, the profile is open. - if ((end - begin)*ang_scale < 0.99f) - { - if ((end - begin)*ang_scale > 0.5f) - { - mConcave = TRUE; - } - else - { - mConcave = FALSE; - } - mOpen = TRUE; - if (params.getHollow() <= 0) - { - // put center point if not hollow. - mProfile.push_back(LLVector4a(0,0,0)); - } - } - else - { - // The profile isn't open. - mOpen = FALSE; - mConcave = FALSE; - } - - mTotal = mProfile.size(); -} - -// Hollow is percent of the original bounding box, not of this particular -// profile's geometry. Thus, a swept triangle needs lower hollow values than -// a swept square. -LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split) -{ - // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. + S32 np = 0; - // Total add has number of vertices on outside. - mTotalOut = mTotal; + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + F32 t, t_step, t_first, t_fraction; - // Why is the "bevel" parameter -1? DJS 04/05/02 - genNGon(params, llfloor(sides),offset,-1, ang_scale, split); + F32 begin = params.getBegin(); + F32 end = params.getEnd(); - Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); + t_step = 1.0f / sides; - static thread_local LLAlignedArray pt; - pt.resize(mTotal) ; + t_first = floor(begin * sides) / (F32)sides; - for (S32 i=mTotalOut;i end - 0.01f) - { - LL_WARNS() << "LLProfile::generate() assertion failed (begin >= end)" << LL_ENDL; - return FALSE; - } - - S32 face_num = 0; - - switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_SQUARE: - { - genNGon(params, 4,-0.375, 0, 1, split); - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); - } - - LLVector4a scale(1,1,4,1); - - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 4 to generate proper tex coords. - mProfile[i].mul(scale); - llassert(mProfile[i].isFinite3()); - } - - if (hollow) - { - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_TRIANGLE: - // This offset is not correct, but we can't change it now... DK 11/17/04 - addHole(params, TRUE, 3, -0.375f, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - // TODO: Compute actual detail levels for cubes - addHole(params, FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_SQUARE: - default: - addHole(params, TRUE, 4, -0.375f, hollow, 1.f, split); - break; - } - } - - if (path_open) { - mFaces[0].mCount = mTotal; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - case LL_PCODE_PROFILE_EQUALTRI: - { - genNGon(params, 3,0, 0, 1, split); - LLVector4a scale(1,1,3,1); - for (i = 0; i <(S32) mProfile.size(); i++) - { - // Scale by 3 to generate proper tex coords. - mProfile[i].mul(scale); - llassert(mProfile[i].isFinite3()); - } - - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - - for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) - { - addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); - } - if (hollow) - { - // Swept triangles need smaller hollowness values, - // because the triangle doesn't fill the bounding box. - F32 triangle_hollow = hollow / 2.f; - - switch (params.getCurveType() & LL_PCODE_HOLE_MASK) - { - case LL_PCODE_HOLE_CIRCLE: - // TODO: Actually generate level of detail for triangles - addHole(params, FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); - break; - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 4, 0, triangle_hollow, 1.f, split); - break; - case LL_PCODE_HOLE_SAME: - case LL_PCODE_HOLE_TRIANGLE: - default: - addHole(params, TRUE, 3, 0, triangle_hollow, 1.f, split); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - F32 circle_detail = MIN_DETAIL_FACES * detail; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides, - // so that corners line up. - circle_detail = llceil(circle_detail / 4.0f) * 4.0f; - } - } - - S32 sides = (S32)circle_detail; - - if (is_sculpted) - sides = sculpt_size; - - genNGon(params, sides); - - if (path_open) - { - addCap (LL_FACE_PATH_BEGIN); - } - - if (mOpen && !hollow) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 4, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, TRUE, 3, 0, hollow, 1.f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, FALSE, circle_detail, 0, hollow, 1.f); - break; - } - } - } - break; - case LL_PCODE_PROFILE_CIRCLE_HALF: - { - // If this has a square hollow, we should adjust the - // number of faces a bit so that the geometry lines up. - U8 hole_type=0; - // Number of faces is cut in half because it's only a half-circle. - F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; - if (hollow) - { - hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; - if (hole_type == LL_PCODE_HOLE_SQUARE) - { - // Snap to the next multiple of four sides (div 2), - // so that corners line up. - circle_detail = llceil(circle_detail / 2.0f) * 2.0f; - } - } - genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); - if (path_open) - { - addCap(LL_FACE_PATH_BEGIN); - } - if (mOpen && !params.getHollow()) - { - addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - else - { - addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); - } - - if (hollow) - { - switch (hole_type) - { - case LL_PCODE_HOLE_SQUARE: - addHole(params, TRUE, 2, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_TRIANGLE: - addHole(params, TRUE, 3, 0.5f, hollow, 0.5f, split); - break; - case LL_PCODE_HOLE_CIRCLE: - case LL_PCODE_HOLE_SAME: - default: - addHole(params, FALSE, circle_detail, 0.5f, hollow, 0.5f); - break; - } - } - - // Special case for openness of sphere - if ((params.getEnd() - params.getBegin()) < 1.f) - { - mOpen = TRUE; - } - else if (!hollow) - { - mOpen = FALSE; - mProfile.push_back(mProfile[0]); - mTotal++; - } - } - break; - default: - LL_ERRS() << "Unknown profile: getCurveType()=" << params.getCurveType() << LL_ENDL; - break; - }; - - if (path_open) - { - addCap(LL_FACE_PATH_END); // bottom - } - - if ( mOpen) // interior edge caps - { - addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, TRUE); - - if (hollow) - { - addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, TRUE); - } - else - { - addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE); - } - } - - return TRUE; -} + t_fraction = (end - (t - t_step))*sides; + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + np++; + } + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if (params.getHollow() <= 0) + { + // put center point if not hollow. + np++; + } + } -BOOL LLProfileParams::importFile(LLFILE *fp) -{ - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; - } - } - - return TRUE; + return np; } - -BOOL LLProfileParams::exportFile(LLFILE *fp) const +// What is the bevel parameter used for? - DJS 04/05/02 +// Bevel parameter is currently unused but presumedly would support +// filleted and chamfered corners +void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) { - fprintf(fp,"\t\tprofile 0\n"); - fprintf(fp,"\t\t{\n"); - fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); - fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); - fprintf(fp,"\t\t\tend\t%g\n", getEnd()); - fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); - fprintf(fp, "\t\t}\n"); - return TRUE; -} + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + F32 scale = 0.5f; + F32 t, t_step, t_first, t_fraction, ang, ang_step; + LLVector4a pt1,pt2; + F32 begin = params.getBegin(); + F32 end = params.getEnd(); -BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) -{ - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of these buffers will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - valuestr[0] = 0; - F32 tempF32; - U32 tempU32; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, - valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("curve", keyword)) - { - sscanf(valuestr,"%d",&tempU32); - setCurveType((U8) tempU32); - } - else if (!strcmp("begin",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setBegin(tempF32); - } - else if (!strcmp("end",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setEnd(tempF32); - } - else if (!strcmp("hollow",keyword)) - { - sscanf(valuestr,"%g",&tempF32); - setHollow(tempF32); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; - } - } - - return TRUE; -} + t_step = 1.0f / sides; + ang_step = 2.0f*F_PI*t_step*ang_scale; + // Scale to have size "match" scale. Compensates to get object to generally fill bounding box. -BOOL LLProfileParams::exportLegacyStream(std::ostream& output_stream) const -{ - output_stream <<"\t\tprofile 0\n"; - output_stream <<"\t\t{\n"; - output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; - output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; - output_stream <<"\t\t\tend\t" << getEnd() << "\n"; - output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; - output_stream << "\t\t}\n"; - return TRUE; -} + S32 total_sides = ll_round(sides / ang_scale); // Total number of sides all around -LLSD LLProfileParams::asLLSD() const -{ - LLSD sd; + if (total_sides < 8) + { + scale = tableScale[total_sides]; + } - sd["curve"] = getCurveType(); - sd["begin"] = getBegin(); - sd["end"] = getEnd(); - sd["hollow"] = getHollow(); - return sd; -} + t_first = floor(begin * sides) / (F32)sides; -bool LLProfileParams::fromLLSD(LLSD& sd) -{ - setCurveType(sd["curve"].asInteger()); - setBegin((F32)sd["begin"].asReal()); - setEnd((F32)sd["end"].asReal()); - setHollow((F32)sd["hollow"].asReal()); - return true; -} + // pt1 is the first point on the fractional face. + // Starting t and ang values for the first face + t = t_first; + ang = 2.0f*F_PI*(t*ang_scale + offset); + pt1.set(cos(ang)*scale,sin(ang)*scale, t); -void LLProfileParams::copyParams(const LLProfileParams ¶ms) -{ - setCurveType(params.getCurveType()); - setBegin(params.getBegin()); - setEnd(params.getEnd()); - setHollow(params.getHollow()); -} + // Increment to the next point. + // pt2 is the end point on the fractional face + t += t_step; + ang += ang_step; + pt2.set(cos(ang)*scale,sin(ang)*scale,t); + t_fraction = (begin - t_first)*sides; -LLPath::~LLPath() -{ -} + // Only use if it's not almost exactly on an edge. + if (t_fraction < 0.9999f) + { + LLVector4a new_pt; + new_pt.setLerp(pt1, pt2, t_fraction); + mProfile.push_back(new_pt); + } -S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) -{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added - S32 ret = 0; + // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 + while (t < end) + { + // Iterate through all the integer steps of t. + pt1.set(cos(ang)*scale,sin(ang)*scale,t); + + if (mProfile.size() > 0) { + LLVector4a p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + //mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); + LLVector4a new_pt; + new_pt.setSub(pt1, p); + new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); + new_pt.add(p); + mProfile.push_back(new_pt); + } + } + mProfile.push_back(pt1); - F32 step= 1.0f / sides; - F32 t = params.getBegin(); - ret = 1; - - t+=step; + t += t_step; + ang += ang_step; + } - // Snap to a quantized parameter, so that cut does not - // affect most sample points. - t = ((S32)(t * sides)) / (F32)sides; + t_fraction = (end - (t - t_step))*sides; - // Run through the non-cut dependent points. - while (t < params.getEnd()) - { - ret++; - t+=step; - } + // pt1 is the first point on the fractional face + // pt2 is the end point on the fractional face + pt2.set(cos(ang)*scale,sin(ang)*scale,t); - ret++; + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + LLVector4a new_pt; + new_pt.setLerp(pt1, pt2, t_fraction); + + if (mProfile.size() > 0) { + LLVector4a p = mProfile[mProfile.size()-1]; + for (S32 i = 0; i < split && mProfile.size() > 0; i++) { + //mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); + + LLVector4a pt1; + pt1.setSub(new_pt, p); + pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); + pt1.add(p); + mProfile.push_back(pt1); + } + } + mProfile.push_back(new_pt); + } - return ret; -} + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if ((end - begin)*ang_scale > 0.5f) + { + mConcave = TRUE; + } + else + { + mConcave = FALSE; + } + mOpen = TRUE; + if (params.getHollow() <= 0) + { + // put center point if not hollow. + mProfile.push_back(LLVector4a(0,0,0)); + } + } + else + { + // The profile isn't open. + mOpen = FALSE; + mConcave = FALSE; + } -void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. - static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; - - F32 revolutions = params.getRevolutions(); - F32 skew = params.getSkew(); - F32 skew_mag = fabs(skew); - F32 hole_x = params.getScaleX() * (1.0f - skew_mag); - F32 hole_y = params.getScaleY(); - - // Calculate taper begin/end for x,y (Negative means taper the beginning) - F32 taper_x_begin = 1.0f; - F32 taper_x_end = 1.0f - params.getTaperX(); - F32 taper_y_begin = 1.0f; - F32 taper_y_end = 1.0f - params.getTaperY(); - - if ( taper_x_end > 1.0f ) - { - // Flip tapering. - taper_x_begin = 2.0f - taper_x_end; - taper_x_end = 1.0f; - } - if ( taper_y_end > 1.0f ) - { - // Flip tapering. - taper_y_begin = 2.0f - taper_y_end; - taper_y_end = 1.0f; - } - - // For spheres, the radius is usually zero. - F32 radius_start = 0.5f; - if (sides < 8) - { - radius_start = tableScale[sides]; - } - - // Scale the radius to take the hole size into account. - radius_start *= 1.0f - hole_y; - - // Now check the radius offset to calculate the start,end radius. (Negative means - // decrease the start radius instead). - F32 radius_end = radius_start; - F32 radius_offset = params.getRadiusOffset(); - if (radius_offset < 0.f) - { - radius_start *= 1.f + radius_offset; - } - else - { - radius_end *= 1.f - radius_offset; - } - - // Is the path NOT a closed loop? - mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || - (skew_mag > 0.001f) || - (fabs(taper_x_end - taper_x_begin) > 0.001f) || - (fabs(taper_y_end - taper_y_begin) > 0.001f) || - (fabs(radius_end - radius_start) > 0.001f) ); - - F32 ang, c, s; - LLQuaternion twist, qang; - PathPt *pt; - LLVector3 path_axis (1.f, 0.f, 0.f); - //LLVector3 twist_axis(0.f, 0.f, 1.f); - F32 twist_begin = params.getTwistBegin() * twist_scale; - F32 twist_end = params.getTwist() * twist_scale; - - // We run through this once before the main loop, to make sure - // the path begins at the correct cut. - F32 step= 1.0f / sides; - F32 t = params.getBegin(); - pt = mPath.append(1); - ang = 2.0f*F_PI*revolutions * t; - s = sin(ang)*lerp(radius_start, radius_end, t); - c = cos(ang)*lerp(radius_start, radius_end, t); - - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - - LLMatrix3 rot(twist * qang); - - pt->mRot.loadu(rot); - - t+=step; - - // Snap to a quantized parameter, so that cut does not - // affect most sample points. - t = ((S32)(t * sides)) / (F32)sides; - - // Run through the non-cut dependent points. - while (t < params.getEnd()) - { - pt = mPath.append(1); - - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - LLMatrix3 tmp(twist*qang); - pt->mRot.loadu(tmp); - - t+=step; - } - - // Make one final pass for the end cut. - t = params.getEnd(); - pt = mPath.append(1); - ang = 2.0f*F_PI*revolutions * t; - c = cos(ang)*lerp(radius_start, radius_end, t); - s = sin(ang)*lerp(radius_start, radius_end, t); - - pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) - + lerp(-skew ,skew, t) * 0.5f, - c + lerp(0,params.getShear().mV[1],s), - s); - pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), - hole_y * lerp(taper_y_begin, taper_y_end, t), - 0,1); - pt->mTexT = t; - - // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 - twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); - // Rotate the point around the circle's center. - qang.setQuat (ang,path_axis); - LLMatrix3 tmp(twist*qang); - pt->mRot.loadu(tmp); - - mTotal = mPath.size(); + mTotal = mProfile.size(); } -const LLVector2 LLPathParams::getBeginScale() const +// Hollow is percent of the original bounding box, not of this particular +// profile's geometry. Thus, a swept triangle needs lower hollow values than +// a swept square. +LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split) { - LLVector2 begin_scale(1.f, 1.f); - if (getScaleX() > 1) - { - begin_scale.mV[0] = 2-getScaleX(); - } - if (getScaleY() > 1) - { - begin_scale.mV[1] = 2-getScaleY(); - } - return begin_scale; -} + // Note that addHole will NOT work for non-"circular" profiles, if we ever decide to use them. -const LLVector2 LLPathParams::getEndScale() const -{ - LLVector2 end_scale(1.f, 1.f); - if (getScaleX() < 1) - { - end_scale.mV[0] = getScaleX(); - } - if (getScaleY() < 1) - { - end_scale.mV[1] = getScaleY(); - } - return end_scale; -} + // Total add has number of vertices on outside. + mTotalOut = mTotal; -S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail) -{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points - if (detail < MIN_LOD) - { - detail = MIN_LOD; - } + // Why is the "bevel" parameter -1? DJS 04/05/02 + genNGon(params, llfloor(sides),offset,-1, ang_scale, split); - S32 np = 2; // hardcode for line + Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); - // Is this 0xf0 mask really necessary? DK 03/02/05 + static thread_local LLAlignedArray pt; + pt.resize(mTotal) ; - switch (params.getCurveType() & 0xf0) - { - default: - case LL_PCODE_PATH_LINE: - { - // Take the begin/end twist into account for detail. - np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; - } - break; + for (S32 i=mTotalOut;i= 0.99f && - params.getScaleX() >= .99f) - { - mOpen = FALSE; - } - - //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); - genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); - - F32 toggle = 0.5f; - for (S32 i=0;i<(S32)mPath.size();i++) - { - mPath[i].mPos.getF32ptr()[0] = toggle; - if (toggle == 0.5f) - toggle = -0.5f; - else - toggle = 0.5f; - } - } - - break; - - case LL_PCODE_PATH_TEST: - - np = 5; - mStep = 1.0f / (np-1); - - mPath.resize(np); - - for (S32 i=0;i end - 0.01f) + { + LL_WARNS() << "LLProfile::generate() assertion failed (begin >= end)" << LL_ENDL; + return FALSE; + } -S32 LLVolume::sNumMeshPoints = 0; + S32 face_num = 0; -LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) - : mParams(params) -{ - mUnique = is_unique; - mFaceMask = 0x0; - mDetail = detail; - mSculptLevel = -2; - mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims - mIsMeshAssetLoaded = false; - mIsMeshAssetUnavaliable = false; - mLODScaleBias.setVec(1,1,1); - mHullPoints = NULL; - mHullIndices = NULL; - mNumHullPoints = 0; - mNumHullIndices = 0; - - // set defaults - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) - { - mPathp = new LLDynamicPath(); - } - else - { - mPathp = new LLPath(); - } - mProfilep = new LLProfile(); - - mGenerateSingleFace = generate_single_face; - - generate(); - - if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) - { - createVolumeFaces(); - } -} + switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_SQUARE: + { + genNGon(params, 4,-0.375, 0, 1, split); + if (path_open) + { + addCap (LL_FACE_PATH_BEGIN); + } -void LLVolume::resizePath(S32 length) -{ - mPathp->resizePath(length); - mVolumeFaces.clear(); - setDirty(); -} + for (i = llfloor(begin * 4.f); i < llfloor(end * 4.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); + } -void LLVolume::regen() -{ - generate(); - createVolumeFaces(); -} + LLVector4a scale(1,1,4,1); -void LLVolume::genTangents(S32 face) -{ - // generate legacy tangents for the specified face - llassert(!isMeshAssetLoaded() || mVolumeFaces[face].mTangents != nullptr); // if this is a complete mesh asset, we should already have tangents - mVolumeFaces[face].createTangents(); -} + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 4 to generate proper tex coords. + mProfile[i].mul(scale); + llassert(mProfile[i].isFinite3()); + } -LLVolume::~LLVolume() -{ - sNumMeshPoints -= mMesh.size(); - delete mPathp; + if (hollow) + { + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_TRIANGLE: + // This offset is not correct, but we can't change it now... DK 11/17/04 + addHole(params, TRUE, 3, -0.375f, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + // TODO: Compute actual detail levels for cubes + addHole(params, FALSE, MIN_DETAIL_FACES * detail, -0.375f, hollow, 1.f); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_SQUARE: + default: + addHole(params, TRUE, 4, -0.375f, hollow, 1.f, split); + break; + } + } + + if (path_open) { + mFaces[0].mCount = mTotal; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + case LL_PCODE_PROFILE_EQUALTRI: + { + genNGon(params, 3,0, 0, 1, split); + LLVector4a scale(1,1,3,1); + for (i = 0; i <(S32) mProfile.size(); i++) + { + // Scale by 3 to generate proper tex coords. + mProfile[i].mul(scale); + llassert(mProfile[i].isFinite3()); + } - delete mProfilep; + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } - mPathp = NULL; - mProfilep = NULL; - mVolumeFaces.clear(); + for (i = llfloor(begin * 3.f); i < llfloor(end * 3.f + .999f); i++) + { + addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE); + } + if (hollow) + { + // Swept triangles need smaller hollowness values, + // because the triangle doesn't fill the bounding box. + F32 triangle_hollow = hollow / 2.f; - ll_aligned_free_16(mHullPoints); - mHullPoints = NULL; - ll_aligned_free_16(mHullIndices); - mHullIndices = NULL; -} + switch (params.getCurveType() & LL_PCODE_HOLE_MASK) + { + case LL_PCODE_HOLE_CIRCLE: + // TODO: Actually generate level of detail for triangles + addHole(params, FALSE, MIN_DETAIL_FACES * detail, 0, triangle_hollow, 1.f); + break; + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 4, 0, triangle_hollow, 1.f, split); + break; + case LL_PCODE_HOLE_SAME: + case LL_PCODE_HOLE_TRIANGLE: + default: + addHole(params, TRUE, 3, 0, triangle_hollow, 1.f, split); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + F32 circle_detail = MIN_DETAIL_FACES * detail; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides, + // so that corners line up. + circle_detail = llceil(circle_detail / 4.0f) * 4.0f; + } + } -BOOL LLVolume::generate() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - LL_CHECK_MEMORY - llassert_always(mProfilep); - - //Added 10.03.05 Dave Parks - // Split is a parameter to LLProfile::generate that tesselates edges on the profile - // to prevent lighting and texture interpolation errors on triangles that are - // stretched due to twisting or scaling on the path. - S32 split = (S32) ((mDetail)*0.66f); - - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && - (mParams.getPathParams().getScale().mV[0] != 1.0f || - mParams.getPathParams().getScale().mV[1] != 1.0f) && - (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || - mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) - { - split = 0; - } - - mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); - - F32 profile_detail = mDetail; - F32 path_detail = mDetail; - - if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) - { - U8 path_type = mParams.getPathParams().getCurveType(); - U8 profile_type = mParams.getProfileParams().getCurveType(); - if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) - { - //cylinders don't care about Z-Axis - mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); - } - else if (path_type == LL_PCODE_PATH_CIRCLE) - { - mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); - } - } - - BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); - BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); - - if (regenPath || regenProf ) - { - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeT * sizeS); - sNumMeshPoints += mMesh.size(); - - //generate vertex positions - - // Run along the path. - LLVector4a* dst = mMesh.mArray; - - for (S32 s = 0; s < sizeS; ++s) - { - F32* scale = mPathp->mPath[s].mScale.getF32ptr(); - - F32 sc [] = - { scale[0], 0, 0, 0, - 0, scale[1], 0, 0, - 0, 0, scale[2], 0, - 0, 0, 0, 1 }; - - LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); - LLMatrix4 scale_mat(sc); - - scale_mat *= rot; - - LLMatrix4a rot_mat; - rot_mat.loadu(scale_mat); - - LLVector4a* profile = mProfilep->mProfile.mArray; - LLVector4a* end_profile = profile+sizeT; - LLVector4a offset = mPathp->mPath[s].mPos; + S32 sides = (S32)circle_detail; - // hack to work around MAINT-5660 for debug until we can suss out - // what is wrong with the path generated that inserts NaNs... - if (!offset.isFinite3()) + if (is_sculpted) + sides = sculpt_size; + + genNGon(params, sides); + + if (path_open) { - offset.clear(); + addCap (LL_FACE_PATH_BEGIN); + } + + if (mOpen && !hollow) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 4, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, TRUE, 3, 0, hollow, 1.f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, FALSE, circle_detail, 0, hollow, 1.f); + break; + } + } + } + break; + case LL_PCODE_PROFILE_CIRCLE_HALF: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + // Number of faces is cut in half because it's only a half-circle. + F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides (div 2), + // so that corners line up. + circle_detail = llceil(circle_detail / 2.0f) * 2.0f; + } + } + genNGon(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); + if (path_open) + { + addCap(LL_FACE_PATH_BEGIN); + } + if (mOpen && !params.getHollow()) + { + addFace(0,mTotal-1,0,LL_FACE_OUTER_SIDE_0, FALSE); + } + else + { + addFace(0,mTotal,0,LL_FACE_OUTER_SIDE_0, FALSE); } - LLVector4a tmp; + if (hollow) + { + switch (hole_type) + { + case LL_PCODE_HOLE_SQUARE: + addHole(params, TRUE, 2, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_TRIANGLE: + addHole(params, TRUE, 3, 0.5f, hollow, 0.5f, split); + break; + case LL_PCODE_HOLE_CIRCLE: + case LL_PCODE_HOLE_SAME: + default: + addHole(params, FALSE, circle_detail, 0.5f, hollow, 0.5f); + break; + } + } - // Run along the profile. - while (profile < end_profile) - { - rot_mat.rotate(*profile++, tmp); - dst->setAdd(tmp,offset); - ++dst; - } - } + // Special case for openness of sphere + if ((params.getEnd() - params.getBegin()) < 1.f) + { + mOpen = TRUE; + } + else if (!hollow) + { + mOpen = FALSE; + mProfile.push_back(mProfile[0]); + mTotal++; + } + } + break; + default: + LL_ERRS() << "Unknown profile: getCurveType()=" << params.getCurveType() << LL_ENDL; + break; + }; - for (std::vector::iterator iter = mProfilep->mFaces.begin(); - iter != mProfilep->mFaces.end(); ++iter) - { - LLFaceID id = iter->mFaceID; - mFaceMask |= id; - } - LL_CHECK_MEMORY - return TRUE; - } + if (path_open) + { + addCap(LL_FACE_PATH_END); // bottom + } - LL_CHECK_MEMORY - return FALSE; -} + if ( mOpen) // interior edge caps + { + addFace(mTotal-1, 2,0.5,LL_FACE_PROFILE_BEGIN, TRUE); -void LLVolumeFace::VertexData::init() -{ - if (!mData) - { - mData = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*2); - } -} + if (hollow) + { + addFace(mTotalOut-1, 2,0.5,LL_FACE_PROFILE_END, TRUE); + } + else + { + addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE); + } + } -LLVolumeFace::VertexData::VertexData() -{ - mData = NULL; - init(); + return TRUE; } - -LLVolumeFace::VertexData::VertexData(const VertexData& rhs) + + + +BOOL LLProfileParams::importFile(LLFILE *fp) { - mData = NULL; - *this = rhs; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; + } + } + + return TRUE; } -const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) + +BOOL LLProfileParams::exportFile(LLFILE *fp) const { - if (this != &rhs) - { - init(); - LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); - mTexCoord = rhs.mTexCoord; - } - return *this; + fprintf(fp,"\t\tprofile 0\n"); + fprintf(fp,"\t\t{\n"); + fprintf(fp,"\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp,"\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp,"\t\t\tend\t%g\n", getEnd()); + fprintf(fp,"\t\t\thollow\t%g\n", getHollow()); + fprintf(fp, "\t\t}\n"); + return TRUE; } -LLVolumeFace::VertexData::~VertexData() + +BOOL LLProfileParams::importLegacyStream(std::istream& input_stream) { - ll_aligned_free_16(mData); - mData = NULL; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + F32 tempF32; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, + valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("hollow",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setHollow(tempF32); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in profile import" << LL_ENDL; + } + } + + return TRUE; } -LLVector4a& LLVolumeFace::VertexData::getPosition() + +BOOL LLProfileParams::exportLegacyStream(std::ostream& output_stream) const { - return mData[POSITION]; + output_stream <<"\t\tprofile 0\n"; + output_stream <<"\t\t{\n"; + output_stream <<"\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream <<"\t\t\tbegin\t" << getBegin() << "\n"; + output_stream <<"\t\t\tend\t" << getEnd() << "\n"; + output_stream <<"\t\t\thollow\t" << getHollow() << "\n"; + output_stream << "\t\t}\n"; + return TRUE; } -LLVector4a& LLVolumeFace::VertexData::getNormal() +LLSD LLProfileParams::asLLSD() const { - return mData[NORMAL]; + LLSD sd; + + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["hollow"] = getHollow(); + return sd; } -const LLVector4a& LLVolumeFace::VertexData::getPosition() const +bool LLProfileParams::fromLLSD(LLSD& sd) { - return mData[POSITION]; + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setHollow((F32)sd["hollow"].asReal()); + return true; } -const LLVector4a& LLVolumeFace::VertexData::getNormal() const +void LLProfileParams::copyParams(const LLProfileParams ¶ms) { - return mData[NORMAL]; + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setHollow(params.getHollow()); } -void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) +LLPath::~LLPath() { - mData[POSITION] = pos; } -void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) -{ - mData[NORMAL] = norm; +S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) +{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added + S32 ret = 0; + + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + ret = 1; + + t+=step; + + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; + + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + ret++; + t+=step; + } + + ret++; + + return ret; } -bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { - const F32* lp = this->getPosition().getF32ptr(); - const F32* rp = rhs.getPosition().getF32ptr(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } + // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. + static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; + + F32 revolutions = params.getRevolutions(); + F32 skew = params.getSkew(); + F32 skew_mag = fabs(skew); + F32 hole_x = params.getScaleX() * (1.0f - skew_mag); + F32 hole_y = params.getScaleY(); + + // Calculate taper begin/end for x,y (Negative means taper the beginning) + F32 taper_x_begin = 1.0f; + F32 taper_x_end = 1.0f - params.getTaperX(); + F32 taper_y_begin = 1.0f; + F32 taper_y_end = 1.0f - params.getTaperY(); + + if ( taper_x_end > 1.0f ) + { + // Flip tapering. + taper_x_begin = 2.0f - taper_x_end; + taper_x_end = 1.0f; + } + if ( taper_y_end > 1.0f ) + { + // Flip tapering. + taper_y_begin = 2.0f - taper_y_end; + taper_y_end = 1.0f; + } - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } + // For spheres, the radius is usually zero. + F32 radius_start = 0.5f; + if (sides < 8) + { + radius_start = tableScale[sides]; + } - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } + // Scale the radius to take the hole size into account. + radius_start *= 1.0f - hole_y; - lp = getNormal().getF32ptr(); - rp = rhs.getNormal().getF32ptr(); + // Now check the radius offset to calculate the start,end radius. (Negative means + // decrease the start radius instead). + F32 radius_end = radius_start; + F32 radius_offset = params.getRadiusOffset(); + if (radius_offset < 0.f) + { + radius_start *= 1.f + radius_offset; + } + else + { + radius_end *= 1.f - radius_offset; + } - if (lp[0] != rp[0]) - { - return lp[0] < rp[0]; - } + // Is the path NOT a closed loop? + mOpen = ( (params.getEnd()*end_scale - params.getBegin() < 1.0f) || + (skew_mag > 0.001f) || + (fabs(taper_x_end - taper_x_begin) > 0.001f) || + (fabs(taper_y_end - taper_y_begin) > 0.001f) || + (fabs(radius_end - radius_start) > 0.001f) ); + + F32 ang, c, s; + LLQuaternion twist, qang; + PathPt *pt; + LLVector3 path_axis (1.f, 0.f, 0.f); + //LLVector3 twist_axis(0.f, 0.f, 1.f); + F32 twist_begin = params.getTwistBegin() * twist_scale; + F32 twist_end = params.getTwist() * twist_scale; + + // We run through this once before the main loop, to make sure + // the path begins at the correct cut. + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + pt = mPath.append(1); + ang = 2.0f*F_PI*revolutions * t; + s = sin(ang)*lerp(radius_start, radius_end, t); + c = cos(ang)*lerp(radius_start, radius_end, t); + + + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + + LLMatrix3 rot(twist * qang); + + pt->mRot.loadu(rot); + + t+=step; + + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; + + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + pt = mPath.append(1); + + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); + + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; + + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + LLMatrix3 tmp(twist*qang); + pt->mRot.loadu(tmp); + + t+=step; + } - if (rp[1] != lp[1]) - { - return lp[1] < rp[1]; - } + // Make one final pass for the end cut. + t = params.getEnd(); + pt = mPath.append(1); + ang = 2.0f*F_PI*revolutions * t; + c = cos(ang)*lerp(radius_start, radius_end, t); + s = sin(ang)*lerp(radius_start, radius_end, t); - if (rp[2] != lp[2]) - { - return lp[2] < rp[2]; - } + pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s) + + lerp(-skew ,skew, t) * 0.5f, + c + lerp(0,params.getShear().mV[1],s), + s); + pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), + hole_y * lerp(taper_y_begin, taper_y_end, t), + 0,1); + pt->mTexT = t; - if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) - { - return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; - } + // Twist rotates the path along the x,y plane (I think) - DJS 04/05/02 + twist.setQuat (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1); + // Rotate the point around the circle's center. + qang.setQuat (ang,path_axis); + LLMatrix3 tmp(twist*qang); + pt->mRot.loadu(tmp); - return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; + mTotal = mPath.size(); } -bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +const LLVector2 LLPathParams::getBeginScale() const { - return mData[POSITION].equals3(rhs.getPosition()) && - mData[NORMAL].equals3(rhs.getNormal()) && - mTexCoord == rhs.mTexCoord; + LLVector2 begin_scale(1.f, 1.f); + if (getScaleX() > 1) + { + begin_scale.mV[0] = 2-getScaleX(); + } + if (getScaleY() > 1) + { + begin_scale.mV[1] = 2-getScaleY(); + } + return begin_scale; } -bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +const LLVector2 LLPathParams::getEndScale() const { - bool retval = false; + LLVector2 end_scale(1.f, 1.f); + if (getScaleX() < 1) + { + end_scale.mV[0] = getScaleX(); + } + if (getScaleY() < 1) + { + end_scale.mV[1] = getScaleY(); + } + return end_scale; +} - const F32 epsilon = 0.00001f; +S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail) +{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points + if (detail < MIN_LOD) + { + detail = MIN_LOD; + } - if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && - fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && - fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) - { - if (angle_cutoff > 1.f) - { - retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); - } - else - { - F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); - retval = cur_angle > angle_cutoff; - } - } + S32 np = 2; // hardcode for line - return retval; -} + // Is this 0xf0 mask really necessary? DK 03/02/05 -bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + } + break; - //input stream is now pointing at a zlib compressed block of LLSD - //decompress block - LLSD mdl; - U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, is, size); - if (uzip_result != LLUZipHelper::ZR_OK) - { - LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; - return false; - } - return unpackVolumeFacesInternal(mdl); -} + case LL_PCODE_PATH_CIRCLE: + { + // Increase the detail as the revolutions and twist increase. + F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); -bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) -{ - //input data is now pointing at a zlib compressed block of LLSD - //decompress block - LLSD mdl; - U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); - if (uzip_result != LLUZipHelper::ZR_OK) - { - LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; - return false; - } - return unpackVolumeFacesInternal(mdl); + S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); + + np = sides; + } + break; + + case LL_PCODE_PATH_CIRCLE2: + { + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail)); + } + break; + + case LL_PCODE_PATH_TEST: + + np = 5; + break; + }; + + return np; } -bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) +BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) { - { - U32 face_count = mdl.size(); - - if (face_count == 0) - { //no faces unpacked, treat as failed decode - LL_WARNS() << "found no faces!" << LL_ENDL; - return false; - } - - mVolumeFaces.resize(face_count); - - for (size_t i = 0; i < face_count; ++i) - { - LLVolumeFace& face = mVolumeFaces[i]; - - if (mdl[i].has("NoGeometry")) - { //face has no geometry, continue - face.resizeIndices(3); - face.resizeVertices(1); - face.mPositions->clear(); - face.mNormals->clear(); - face.mTexCoords->setZero(); - memset(face.mIndices, 0, sizeof(U16)*3); - continue; - } - - LLSD::Binary pos = mdl[i]["Position"]; - LLSD::Binary norm = mdl[i]["Normal"]; - LLSD::Binary tangent = mdl[i]["Tangent"]; - LLSD::Binary tc = mdl[i]["TexCoord0"]; - LLSD::Binary idx = mdl[i]["TriangleList"]; + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - //copy out indices - S32 num_indices = idx.size() / 2; - const S32 indices_to_discard = num_indices % 3; - if (indices_to_discard > 0) - { - // Invalid number of triangle indices - LL_WARNS() << "Incomplete triangle discarded from face! Indices count " << num_indices << " was not divisible by 3. face index: " << i << " Total: " << face_count << LL_ENDL; - num_indices -= indices_to_discard; - } - face.resizeIndices(num_indices); + if ((!mDirty) && (!is_sculpted)) + { + return FALSE; + } - if (num_indices > 2 && !face.mIndices) + if (detail < MIN_LOD) + { + LL_INFOS() << "Generating path with LOD < MIN! Clamping to 1" << LL_ENDL; + detail = MIN_LOD; + } + + mDirty = FALSE; + S32 np = 2; // hardcode for line + + mPath.resize(0); + mOpen = TRUE; + + // Is this 0xf0 mask really necessary? DK 03/02/05 + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + if (np < split+2) { - LL_WARNS() << "Failed to allocate " << num_indices << " indices for face index: " << i << " Total: " << face_count << LL_ENDL; - continue; + np = split+2; } - - if (idx.empty() || face.mNumIndices < 3) - { //why is there an empty index list? - LL_WARNS() << "Empty face present! Face index: " << i << " Total: " << face_count << LL_ENDL; - continue; - } - - U16* indices = (U16*) &(idx[0]); - for (U32 j = 0; j < num_indices; ++j) - { - face.mIndices[j] = indices[j]; - } - //copy out vertices - U32 num_verts = pos.size()/(3*2); - face.resizeVertices(num_verts); + mStep = 1.0f / (np-1); - if (num_verts > 0 && !face.mPositions) + mPath.resize(np); + + LLVector2 start_scale = params.getBeginScale(); + LLVector2 end_scale = params.getEndScale(); + + for (S32 i=0;iset((F32) v[0], (F32) v[1], (F32) v[2]); - pos_out->div(65535.f); - pos_out->mul(pos_range); - pos_out->add(min_pos); - pos_out++; - v += 3; - } - - } - - { - if (!norm.empty()) - { - U16* n = (U16*) &(norm[0]); - for (U32 j = 0; j < num_verts; ++j) - { - norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); - norm_out->div(65535.f); - norm_out->mul(2.f); - norm_out->sub(1.f); - norm_out++; - n += 3; - } - } - else - { - for (U32 j = 0; j < num_verts; ++j) - { - norm_out->clear(); - norm_out++; // or just norm_out[j].clear(); - } - } - } + if (is_sculpted) + sides = llmax(sculpt_size, 1); -#if 0 // keep this code for now in case we decide to add support for on-the-wire tangents + if (0 < sides) + genNGon(params, sides); + } + break; + + case LL_PCODE_PATH_CIRCLE2: + { + if (params.getEnd() - params.getBegin() >= 0.99f && + params.getScaleX() >= .99f) { - if (!tangent.empty()) - { - face.allocateTangents(face.mNumVertices); - U16* t = (U16*)&(tangent[0]); + mOpen = FALSE; + } - // NOTE: tangents coming from the asset may not be mikkt space, but they should always be used by the GLTF shaders to - // maintain compliance with the GLTF spec - LLVector4a* t_out = face.mTangents; + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + genNGon(params, llfloor(MIN_DETAIL_FACES * detail)); - for (U32 j = 0; j < num_verts; ++j) - { - t_out->set((F32)t[0], (F32)t[1], (F32)t[2], (F32) t[3]); - t_out->div(65535.f); - t_out->mul(2.f); - t_out->sub(1.f); + F32 toggle = 0.5f; + for (S32 i=0;i<(S32)mPath.size();i++) + { + mPath[i].mPos.getF32ptr()[0] = toggle; + if (toggle == 0.5f) + toggle = -0.5f; + else + toggle = 0.5f; + } + } - F32* tp = t_out->getF32ptr(); - tp[3] = tp[3] < 0.f ? -1.f : 1.f; + break; - t_out++; - t += 4; - } - } - } -#endif + case LL_PCODE_PATH_TEST: - { - if (!tc.empty()) - { - U16* t = (U16*) &(tc[0]); - for (U32 j = 0; j < num_verts; j+=2) - { - if (j < num_verts-1) - { - tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); - } - else - { - tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); - } - - t += 4; - - tc_out->div(65535.f); - tc_out->mul(tc_range); - tc_out->add(min_tc4); - - tc_out++; - } - } - else - { - for (U32 j = 0; j < num_verts; j += 2) - { - tc_out->clear(); - tc_out++; - } - } - } - - if (mdl[i].has("Weights")) - { - face.allocateWeights(num_verts); - if (!face.mWeights && num_verts) - { - LL_WARNS() << "Failed to allocate " << num_verts << " weights for face index: " << i << " Total: " << face_count << LL_ENDL; - face.resizeIndices(0); - face.resizeVertices(0); - continue; - } + np = 5; + mStep = 1.0f / (np-1); - LLSD::Binary weights = mdl[i]["Weights"]; + mPath.resize(np); - U32 idx = 0; + for (S32 i=0;i= 4) - { - joint = END_INFLUENCES; - } - else - { - joint = weights[idx++]; - } - } - F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; - if (wsum <= 0.f) - { - wght = LLVector4(0.999f,0.f,0.f,0.f); - } - for (U32 k=0; k<4; k++) - { - F32 f_combined = (F32) joints[k] + wght[k]; - joints_with_weights[k] = f_combined; - // Any weights we added above should wind up non-zero and applied to a specific bone. - // A failure here would indicate a floating point precision error in the math. - llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); - } - face.mWeights[cur_vertex].loadua(joints_with_weights.mV); - - cur_vertex++; - } - - if (cur_vertex != num_verts || idx != weights.size()) - { - LL_WARNS() << "Vertex weight count does not match vertex count!" << LL_ENDL; - } - - } - - // modifier flags? - bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); - bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); - - - // translate to actions: - bool do_reflect_x = false; - bool do_reverse_triangles = false; - bool do_invert_normals = false; - - if (do_mirror) - { - do_reflect_x = true; - do_reverse_triangles = !do_reverse_triangles; - } - - if (do_invert) - { - do_invert_normals = true; - do_reverse_triangles = !do_reverse_triangles; - } - - // now do the work - - if (do_reflect_x) - { - LLVector4a* p = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - p[i].mul(-1.0f); - n[i].mul(-1.0f); - } - } - - if (do_invert_normals) - { - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (S32 i = 0; i < face.mNumVertices; i++) - { - n[i].mul(-1.0f); - } - } - - if (do_reverse_triangles) - { - for (U32 j = 0; j < face.mNumIndices; j += 3) - { - // swap the 2nd and 3rd index - S32 swap = face.mIndices[j+1]; - face.mIndices[j+1] = face.mIndices[j+2]; - face.mIndices[j+2] = swap; - } - } - - //calculate bounding box - // VFExtents change - LLVector4a& min = face.mExtents[0]; - LLVector4a& max = face.mExtents[1]; - - if (face.mNumVertices < 3) - { //empty face, use a dummy 1cm (at 1m scale) bounding box - min.splat(-0.005f); - max.splat(0.005f); - } - else - { - min = max = face.mPositions[0]; - - for (S32 i = 1; i < face.mNumVertices; ++i) - { - min.setMin(min, face.mPositions[i]); - max.setMax(max, face.mPositions[i]); - } - - if (face.mTexCoords) - { - LLVector2& min_tc = face.mTexCoordExtents[0]; - LLVector2& max_tc = face.mTexCoordExtents[1]; - - min_tc = face.mTexCoords[0]; - max_tc = face.mTexCoords[0]; - - for (U32 j = 1; j < face.mNumVertices; ++j) - { - update_min_max(min_tc, max_tc, face.mTexCoords[j]); - } - } - else - { - face.mTexCoordExtents[0].set(0,0); - face.mTexCoordExtents[1].set(1,1); - } - } - } - } - - if (!cacheOptimize(true)) - { - // Out of memory? - LL_WARNS() << "Failed to optimize!" << LL_ENDL; - mVolumeFaces.clear(); - return false; - } - - mSculptLevel = 0; // success! - - return true; -} + if (params.getTwist() != params.getTwistBegin()) mOpen = TRUE; + //if ((int(fabsf(params.getTwist() - params.getTwistBegin())*100))%100 != 0) { + // mOpen = TRUE; + //} -bool LLVolume::isMeshAssetLoaded() -{ - return mIsMeshAssetLoaded; + return TRUE; } -void LLVolume::setMeshAssetLoaded(bool loaded) +BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) { - mIsMeshAssetLoaded = loaded; - if (loaded) + mOpen = TRUE; // Draw end caps + if (getPathLength() == 0) { - mIsMeshAssetUnavaliable = false; + // Path hasn't been generated yet. + // Some algorithms later assume at least TWO path points. + resizePath(2); + LLQuaternion quat; + quat.setQuat(0,0,0); + LLMatrix3 tmp(quat); + + for (U32 i = 0; i < 2; i++) + { + mPath[i].mPos.set(0, 0, 0); + mPath[i].mRot.loadu(tmp); + mPath[i].mScale.set(1, 1, 0, 1); + mPath[i].mTexT = 0; + } } + + return TRUE; } -void LLVolume::setMeshAssetUnavaliable(bool unavaliable) + +BOOL LLPathParams::importFile(LLFILE *fp) { - // Don't set it if at least one lod loaded - if (!mIsMeshAssetLoaded) + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (!feof(fp)) { - mIsMeshAssetUnavaliable = unavaliable; + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; + } } + return TRUE; } -bool LLVolume::isMeshAssetUnavaliable() + +BOOL LLPathParams::exportFile(LLFILE *fp) const { - return mIsMeshAssetUnavaliable; + fprintf(fp, "\t\tpath 0\n"); + fprintf(fp, "\t\t{\n"); + fprintf(fp, "\t\t\tcurve\t%d\n", getCurveType()); + fprintf(fp, "\t\t\tbegin\t%g\n", getBegin()); + fprintf(fp, "\t\t\tend\t%g\n", getEnd()); + fprintf(fp, "\t\t\tscale_x\t%g\n", getScaleX() ); + fprintf(fp, "\t\t\tscale_y\t%g\n", getScaleY() ); + fprintf(fp, "\t\t\tshear_x\t%g\n", getShearX() ); + fprintf(fp, "\t\t\tshear_y\t%g\n", getShearY() ); + fprintf(fp,"\t\t\ttwist\t%g\n", getTwist()); + + fprintf(fp,"\t\t\ttwist_begin\t%g\n", getTwistBegin()); + fprintf(fp,"\t\t\tradius_offset\t%g\n", getRadiusOffset()); + fprintf(fp,"\t\t\ttaper_x\t%g\n", getTaperX()); + fprintf(fp,"\t\t\ttaper_y\t%g\n", getTaperY()); + fprintf(fp,"\t\t\trevolutions\t%g\n", getRevolutions()); + fprintf(fp,"\t\t\tskew\t%g\n", getSkew()); + + fprintf(fp, "\t\t}\n"); + return TRUE; } -void LLVolume::copyFacesTo(std::vector &faces) const + +BOOL LLPathParams::importLegacyStream(std::istream& input_stream) { - faces = mVolumeFaces; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + char valuestr[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + valuestr[0] = 0; + + F32 tempF32; + F32 x, y; + U32 tempU32; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf( /* Flawfinder: ignore */ + buffer, + " %255s %255s", + keyword, valuestr); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("curve", keyword)) + { + sscanf(valuestr,"%d",&tempU32); + setCurveType((U8) tempU32); + } + else if (!strcmp("begin",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setBegin(tempF32); + } + else if (!strcmp("end",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setEnd(tempF32); + } + else if (!strcmp("scale",keyword)) + { + // Legacy for one dimensional scale per path + sscanf(valuestr,"%g",&tempF32); + setScale(tempF32, tempF32); + } + else if (!strcmp("scale_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setScaleX(x); + } + else if (!strcmp("scale_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setScaleY(y); + } + else if (!strcmp("shear_x", keyword)) + { + sscanf(valuestr, "%g", &x); + setShearX(x); + } + else if (!strcmp("shear_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setShearY(y); + } + else if (!strcmp("twist",keyword)) + { + sscanf(valuestr,"%g",&tempF32); + setTwist(tempF32); + } + else if (!strcmp("twist_begin", keyword)) + { + sscanf(valuestr, "%g", &y); + setTwistBegin(y); + } + else if (!strcmp("radius_offset", keyword)) + { + sscanf(valuestr, "%g", &y); + setRadiusOffset(y); + } + else if (!strcmp("taper_x", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperX(y); + } + else if (!strcmp("taper_y", keyword)) + { + sscanf(valuestr, "%g", &y); + setTaperY(y); + } + else if (!strcmp("revolutions", keyword)) + { + sscanf(valuestr, "%g", &y); + setRevolutions(y); + } + else if (!strcmp("skew", keyword)) + { + sscanf(valuestr, "%g", &y); + setSkew(y); + } + else + { + LL_WARNS() << "unknown keyword " << " in path import" << LL_ENDL; + } + } + return TRUE; } -void LLVolume::copyFacesFrom(const std::vector &faces) + +BOOL LLPathParams::exportLegacyStream(std::ostream& output_stream) const { - mVolumeFaces = faces; - mSculptLevel = 0; + output_stream << "\t\tpath 0\n"; + output_stream << "\t\t{\n"; + output_stream << "\t\t\tcurve\t" << (S32) getCurveType() << "\n"; + output_stream << "\t\t\tbegin\t" << getBegin() << "\n"; + output_stream << "\t\t\tend\t" << getEnd() << "\n"; + output_stream << "\t\t\tscale_x\t" << getScaleX() << "\n"; + output_stream << "\t\t\tscale_y\t" << getScaleY() << "\n"; + output_stream << "\t\t\tshear_x\t" << getShearX() << "\n"; + output_stream << "\t\t\tshear_y\t" << getShearY() << "\n"; + output_stream <<"\t\t\ttwist\t" << getTwist() << "\n"; + + output_stream <<"\t\t\ttwist_begin\t" << getTwistBegin() << "\n"; + output_stream <<"\t\t\tradius_offset\t" << getRadiusOffset() << "\n"; + output_stream <<"\t\t\ttaper_x\t" << getTaperX() << "\n"; + output_stream <<"\t\t\ttaper_y\t" << getTaperY() << "\n"; + output_stream <<"\t\t\trevolutions\t" << getRevolutions() << "\n"; + output_stream <<"\t\t\tskew\t" << getSkew() << "\n"; + + output_stream << "\t\t}\n"; + return TRUE; } -void LLVolume::copyVolumeFaces(const LLVolume* volume) +LLSD LLPathParams::asLLSD() const { - mVolumeFaces = volume->mVolumeFaces; - mSculptLevel = 0; + LLSD sd = LLSD(); + sd["curve"] = getCurveType(); + sd["begin"] = getBegin(); + sd["end"] = getEnd(); + sd["scale_x"] = getScaleX(); + sd["scale_y"] = getScaleY(); + sd["shear_x"] = getShearX(); + sd["shear_y"] = getShearY(); + sd["twist"] = getTwist(); + sd["twist_begin"] = getTwistBegin(); + sd["radius_offset"] = getRadiusOffset(); + sd["taper_x"] = getTaperX(); + sd["taper_y"] = getTaperY(); + sd["revolutions"] = getRevolutions(); + sd["skew"] = getSkew(); + + return sd; } -bool LLVolume::cacheOptimize(bool gen_tangents) +bool LLPathParams::fromLLSD(LLSD& sd) { - for (S32 i = 0; i < mVolumeFaces.size(); ++i) - { - if (!mVolumeFaces[i].cacheOptimize(gen_tangents)) - { - return false; - } - } - return true; + setCurveType(sd["curve"].asInteger()); + setBegin((F32)sd["begin"].asReal()); + setEnd((F32)sd["end"].asReal()); + setScaleX((F32)sd["scale_x"].asReal()); + setScaleY((F32)sd["scale_y"].asReal()); + setShearX((F32)sd["shear_x"].asReal()); + setShearY((F32)sd["shear_y"].asReal()); + setTwist((F32)sd["twist"].asReal()); + setTwistBegin((F32)sd["twist_begin"].asReal()); + setRadiusOffset((F32)sd["radius_offset"].asReal()); + setTaperX((F32)sd["taper_x"].asReal()); + setTaperY((F32)sd["taper_y"].asReal()); + setRevolutions((F32)sd["revolutions"].asReal()); + setSkew((F32)sd["skew"].asReal()); + return true; } - -S32 LLVolume::getNumFaces() const +void LLPathParams::copyParams(const LLPathParams ¶ms) { - return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size(); + setCurveType(params.getCurveType()); + setBegin(params.getBegin()); + setEnd(params.getEnd()); + setScale(params.getScaleX(), params.getScaleY() ); + setShear(params.getShearX(), params.getShearY() ); + setTwist(params.getTwist()); + setTwistBegin(params.getTwistBegin()); + setRadiusOffset(params.getRadiusOffset()); + setTaper( params.getTaperX(), params.getTaperY() ); + setRevolutions(params.getRevolutions()); + setSkew(params.getSkew()); } - -void LLVolume::createVolumeFaces() +LLProfile::~LLProfile() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - if (mGenerateSingleFace) - { - // do nothing - } - else - { - S32 num_faces = getNumFaces(); - BOOL partial_build = TRUE; - if (num_faces != mVolumeFaces.size()) - { - partial_build = FALSE; - mVolumeFaces.resize(num_faces); - } - // Initialize volume faces with parameter data - for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) - { - LLVolumeFace& vf = mVolumeFaces[i]; - LLProfile::Face& face = mProfilep->mFaces[i]; - vf.mBeginS = face.mIndex; - vf.mNumS = face.mCount; - if (vf.mNumS < 0) - { - LL_ERRS() << "Volume face corruption detected." << LL_ENDL; - } - - vf.mBeginT = 0; - vf.mNumT= getPath().mPath.size(); - vf.mID = i; - - // Set the type mask bits correctly - if (mParams.getProfileParams().getHollow() > 0) - { - vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; - } - if (mProfilep->isOpen()) - { - vf.mTypeMask |= LLVolumeFace::OPEN_MASK; - } - if (face.mCap) - { - vf.mTypeMask |= LLVolumeFace::CAP_MASK; - if (face.mFaceID == LL_FACE_PATH_BEGIN) - { - vf.mTypeMask |= LLVolumeFace::TOP_MASK; - } - else - { - llassert(face.mFaceID == LL_FACE_PATH_END); - vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; - } - } - else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; - } - else - { - vf.mTypeMask |= LLVolumeFace::SIDE_MASK; - if (face.mFlat) - { - vf.mTypeMask |= LLVolumeFace::FLAT_MASK; - } - if (face.mFaceID & LL_FACE_INNER_SIDE) - { - vf.mTypeMask |= LLVolumeFace::INNER_MASK; - if (face.mFlat && vf.mNumS > 2) - { //flat inner faces have to copy vert normals - vf.mNumS = vf.mNumS*2; - if (vf.mNumS < 0) - { - LL_ERRS() << "Volume face corruption detected." << LL_ENDL; - } - } - } - else - { - vf.mTypeMask |= LLVolumeFace::OUTER_MASK; - } - } - } - - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - (*iter).create(this, partial_build); - } - } } -inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b) -{ - // maps RGB values to vector values [0..255] -> [-0.5..0.5] - LLVector4a value; - LLVector4a sub(0.5f, 0.5f, 0.5f); +S32 LLVolume::sNumMeshPoints = 0; + +LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face, const BOOL is_unique) + : mParams(params) +{ + mUnique = is_unique; + mFaceMask = 0x0; + mDetail = detail; + mSculptLevel = -2; + mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims + mIsMeshAssetLoaded = false; + mIsMeshAssetUnavaliable = false; + mLODScaleBias.setVec(1,1,1); + mHullPoints = NULL; + mHullIndices = NULL; + mNumHullPoints = 0; + mNumHullIndices = 0; + + // set defaults + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) + { + mPathp = new LLDynamicPath(); + } + else + { + mPathp = new LLPath(); + } + mProfilep = new LLProfile(); + + mGenerateSingleFace = generate_single_face; - value.set(r,g,b); - value.mul(1.f/255.f); - value.sub(sub); + generate(); - return value; + if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + { + createVolumeFaces(); + } } -inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) +void LLVolume::resizePath(S32 length) { - U32 index = (x + y * sculpt_width) * sculpt_components; - return index; + mPathp->resizePath(length); + mVolumeFaces.clear(); + setDirty(); } - -inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) +void LLVolume::regen() { - U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); - U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); - - return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + generate(); + createVolumeFaces(); } - -inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data) +void LLVolume::genTangents(S32 face) { - LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); - - return v; + // generate legacy tangents for the specified face + llassert(!isMeshAssetLoaded() || mVolumeFaces[face].mTangents != nullptr); // if this is a complete mesh asset, we should already have tangents + mVolumeFaces[face].createTangents(); } -inline LLVector4a sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +LLVolume::~LLVolume() { - U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); + sNumMeshPoints -= mMesh.size(); + delete mPathp; - return sculpt_index_to_vector(index, sculpt_data); -} + delete mProfilep; -inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) -{ - U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + mPathp = NULL; + mProfilep = NULL; + mVolumeFaces.clear(); - return sculpt_index_to_vector(index, sculpt_data); + ll_aligned_free_16(mHullPoints); + mHullPoints = NULL; + ll_aligned_free_16(mHullIndices); + mHullIndices = NULL; } - -F32 LLVolume::sculptGetSurfaceArea() +BOOL LLVolume::generate() { - // test to see if image has enough variation to create non-degenerate geometry + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LL_CHECK_MEMORY + llassert_always(mProfilep); - F32 area = 0; + //Added 10.03.05 Dave Parks + // Split is a parameter to LLProfile::generate that tesselates edges on the profile + // to prevent lighting and texture interpolation errors on triangles that are + // stretched due to twisting or scaling on the path. + S32 split = (S32) ((mDetail)*0.66f); - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - for (S32 s = 0; s < sizeS-1; s++) - { - for (S32 t = 0; t < sizeT-1; t++) - { - // get four corners of quad - LLVector4a& p1 = mMesh[(s )*sizeT + (t )]; - LLVector4a& p2 = mMesh[(s+1)*sizeT + (t )]; - LLVector4a& p3 = mMesh[(s )*sizeT + (t+1)]; - LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)]; + if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_LINE && + (mParams.getPathParams().getScale().mV[0] != 1.0f || + mParams.getPathParams().getScale().mV[1] != 1.0f) && + (mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_SQUARE || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_ISOTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_EQUALTRI || + mParams.getProfileParams().getCurveType() == LL_PCODE_PROFILE_RIGHTTRI)) + { + split = 0; + } - // compute the area of the quad by taking the length of the cross product of the two triangles - LLVector4a v0,v1,v2,v3; - v0.setSub(p1,p2); - v1.setSub(p1,p3); - v2.setSub(p4,p2); - v3.setSub(p4,p3); + mLODScaleBias.setVec(0.5f, 0.5f, 0.5f); - LLVector4a cross1, cross2; - cross1.setCross3(v0,v1); - cross2.setCross3(v2,v3); + F32 profile_detail = mDetail; + F32 path_detail = mDetail; - //LLVector3 cross1 = (p1 - p2) % (p1 - p3); - //LLVector3 cross2 = (p4 - p2) % (p4 - p3); - - area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f; - } - } + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) + { + U8 path_type = mParams.getPathParams().getCurveType(); + U8 profile_type = mParams.getProfileParams().getCurveType(); + if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE) + { + //cylinders don't care about Z-Axis + mLODScaleBias.setVec(0.6f, 0.6f, 0.0f); + } + else if (path_type == LL_PCODE_PATH_CIRCLE) + { + mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); + } + } - return area; -} + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); + BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); -// create empty placeholder shape -void LLVolume::sculptGenerateEmptyPlaceholder() -{ - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); + if (regenPath || regenProf ) + { + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); - S32 line = 0; + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeT * sizeS); + sNumMeshPoints += mMesh.size(); - for (S32 s = 0; s < sizeS; s++) - { - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; - - F32* p = pt.getF32ptr(); + //generate vertex positions - p[0] = 0; - p[1] = 0; - p[2] = 0; + // Run along the path. + LLVector4a* dst = mMesh.mArray; - llassert(pt.isFinite3()); - } - line += sizeT; - } -} + for (S32 s = 0; s < sizeS; ++s) + { + F32* scale = mPathp->mPath[s].mScale.getF32ptr(); -// create sphere placeholder shape -void LLVolume::sculptGenerateSpherePlaceholder() -{ - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); + F32 sc [] = + { scale[0], 0, 0, 0, + 0, scale[1], 0, 0, + 0, 0, scale[2], 0, + 0, 0, 0, 1 }; - S32 line = 0; + LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); + LLMatrix4 scale_mat(sc); - for (S32 s = 0; s < sizeS; s++) - { - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; + scale_mat *= rot; + LLMatrix4a rot_mat; + rot_mat.loadu(scale_mat); - F32 u = (F32)s / (sizeS - 1); - F32 v = (F32)t / (sizeT - 1); + LLVector4a* profile = mProfilep->mProfile.mArray; + LLVector4a* end_profile = profile+sizeT; + LLVector4a offset = mPathp->mPath[s].mPos; + + // hack to work around MAINT-5660 for debug until we can suss out + // what is wrong with the path generated that inserts NaNs... + if (!offset.isFinite3()) + { + offset.clear(); + } - const F32 RADIUS = (F32) 0.3; + LLVector4a tmp; - F32* p = pt.getF32ptr(); + // Run along the profile. + while (profile < end_profile) + { + rot_mat.rotate(*profile++, tmp); + dst->setAdd(tmp,offset); + ++dst; + } + } - p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); - p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); - p[2] = (F32)(cos(F_PI * v) * RADIUS); + for (std::vector::iterator iter = mProfilep->mFaces.begin(); + iter != mProfilep->mFaces.end(); ++iter) + { + LLFaceID id = iter->mFaceID; + mFaceMask |= id; + } + LL_CHECK_MEMORY + return TRUE; + } - llassert(pt.isFinite3()); - } - line += sizeT; - } + LL_CHECK_MEMORY + return FALSE; } -// create the vertices from the map -void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) -{ - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - S32 sizeS = mPathp->mPath.size(); - S32 sizeT = mProfilep->mProfile.size(); - - S32 line = 0; - for (S32 s = 0; s < sizeS; s++) - { - // Run along the profile. - for (S32 t = 0; t < sizeT; t++) - { - S32 i = t + line; - LLVector4a& pt = mMesh[i]; - - S32 reversed_t = t; - - if (reverse_horizontal) - { - reversed_t = sizeT - t - 1; - } - - U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); - U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); - - - if (y == 0) // top row stitching - { - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (y == sculpt_height) // bottom row stitching - { - // wrap? - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - { - y = 0; - } - else - { - y = sculpt_height - 1; - } - - // pinch? - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - { - x = sculpt_width / 2; - } - } - - if (x == sculpt_width) // side stitching - { - // wrap? - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - { - x = 0; - } - - else - { - x = sculpt_width - 1; - } - } - - pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); - - if (sculpt_mirror) - { - LLVector4a scale(-1.f,1,1,1); - pt.mul(scale); - } - - llassert(pt.isFinite3()); - } - - line += sizeT; - } -} - - -const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square -const S32 SCULPT_REZ_2 = 8; -const S32 SCULPT_REZ_3 = 16; -const S32 SCULPT_REZ_4 = 32; - -S32 sculpt_sides(F32 detail) -{ - - // detail is usually one of: 1, 1.5, 2.5, 4.0. - - if (detail <= 1.0) - { - return SCULPT_REZ_1; - } - if (detail <= 2.0) - { - return SCULPT_REZ_2; - } - if (detail <= 3.0) - { - return SCULPT_REZ_3; - } - else - { - return SCULPT_REZ_4; - } -} - - - -// determine the number of vertices in both s and t direction for this sculpt -void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) +void LLVolumeFace::VertexData::init() { - // this code has the following properties: - // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map - // while still using all available verts - // 2) the mesh cannot have more verts than is allowed by LOD - // 3) the mesh cannot have more verts than is allowed by the map - - S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); - S32 max_vertices_map = width * height / 4; - - S32 vertices; - if (max_vertices_map > 0) - vertices = llmin(max_vertices_lod, max_vertices_map); - else - vertices = max_vertices_lod; - - - F32 ratio; - if ((width == 0) || (height == 0)) - ratio = 1.f; - else - ratio = (F32) width / (F32) height; - - - s = (S32)(F32) sqrt(((F32)vertices / ratio)); - - s = llmax(s, 4); // no degenerate sizes, please - t = vertices / s; - - t = llmax(t, 4); // no degenerate sizes, please - s = vertices / t; + if (!mData) + { + mData = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*2); + } } -// sculpt replaces generate() for sculpted surfaces -void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) +LLVolumeFace::VertexData::VertexData() { - U8 sculpt_type = mParams.getSculptType(); - - BOOL data_is_empty = FALSE; - - if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) - { - sculpt_level = -1; - data_is_empty = TRUE; - } - - S32 requested_sizeS = 0; - S32 requested_sizeT = 0; - - sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); - - mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); - mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); - - S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got - S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got - - // weird crash bug - DEV-11158 - trying to collect more data: - if ((sizeS == 0) || (sizeT == 0)) - { - LL_WARNS() << "sculpt bad mesh size " << sizeS << " " << sizeT << LL_ENDL; - } - - sNumMeshPoints -= mMesh.size(); - mMesh.resize(sizeS * sizeT); - sNumMeshPoints += mMesh.size(); - - //generate vertex positions - if (!data_is_empty) - { - sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); - - // don't test lowest LOD to support legacy content DEV-33670 - if (mDetail > SCULPT_MIN_AREA_DETAIL) - { - F32 area = sculptGetSurfaceArea(); - - mSurfaceArea = area; - - const F32 SCULPT_MAX_AREA = 384.f; - - if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) - { - data_is_empty = TRUE; - visible_placeholder = true; - } - } - } - - if (data_is_empty) - { - if (visible_placeholder) - { - // Object should be visible since there will be nothing else to display - sculptGenerateSpherePlaceholder(); - } - else - { - sculptGenerateEmptyPlaceholder(); - } - } - - - - for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) - { - mFaceMask |= mProfilep->mFaces[i].mFaceID; - } - - mSculptLevel = sculpt_level; - - // Delete any existing faces so that they get regenerated - mVolumeFaces.clear(); - - createVolumeFaces(); + mData = NULL; + init(); } - - - -BOOL LLVolume::isCap(S32 face) +LLVolumeFace::VertexData::VertexData(const VertexData& rhs) { - return mProfilep->mFaces[face].mCap; + mData = NULL; + *this = rhs; } -BOOL LLVolume::isFlat(S32 face) +const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) { - return mProfilep->mFaces[face].mFlat; + if (this != &rhs) + { + init(); + LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); + mTexCoord = rhs.mTexCoord; + } + return *this; } - -bool LLVolumeParams::isSculpt() const +LLVolumeFace::VertexData::~VertexData() { - return (mSculptType & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_NONE; + ll_aligned_free_16(mData); + mData = NULL; } -bool LLVolumeParams::isMeshSculpt() const +LLVector4a& LLVolumeFace::VertexData::getPosition() { - return (mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH; + return mData[POSITION]; } -bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const +LLVector4a& LLVolumeFace::VertexData::getNormal() { - return ( (getPathParams() == params.getPathParams()) && - (getProfileParams() == params.getProfileParams()) && - (mSculptID == params.mSculptID) && - (mSculptType == params.mSculptType) ); + return mData[NORMAL]; } -bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const +const LLVector4a& LLVolumeFace::VertexData::getPosition() const { - return ( (getPathParams() != params.getPathParams()) || - (getProfileParams() != params.getProfileParams()) || - (mSculptID != params.mSculptID) || - (mSculptType != params.mSculptType) ); + return mData[POSITION]; } -bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const +const LLVector4a& LLVolumeFace::VertexData::getNormal() const { - if( getPathParams() != params.getPathParams() ) - { - return getPathParams() < params.getPathParams(); - } - - if (getProfileParams() != params.getProfileParams()) - { - return getProfileParams() < params.getProfileParams(); - } - - if (mSculptID != params.mSculptID) - { - return mSculptID < params.mSculptID; - } - - return mSculptType < params.mSculptType; - - + return mData[NORMAL]; } -void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) -{ - mProfileParams.copyParams(params.mProfileParams); - mPathParams.copyParams(params.mPathParams); - mSculptID = params.getSculptID(); - mSculptType = params.getSculptType(); -} -// Less restricitve approx 0 for volumes -const F32 APPROXIMATELY_ZERO = 0.001f; -bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO) +void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) { - return (f >= -tolerance) && (f <= tolerance); + mData[POSITION] = pos; } -// return true if in range (or nearly so) -static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO) +void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) { - F32 min_delta = v - min; - if (min_delta < 0.f) - { - v = min; - if (!approx_zero(min_delta, tolerance)) - return false; - } - F32 max_delta = max - v; - if (max_delta < 0.f) - { - v = max; - if (!approx_zero(max_delta, tolerance)) - return false; - } - return true; + mData[NORMAL] = norm; } -bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e) +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const { - bool valid = true; - - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); - - F32 end = e; - if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + const F32* lp = this->getPosition().getF32ptr(); + const F32* rp = rhs.getPosition().getF32ptr(); - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); - - // Now set them. - mProfileParams.setBegin(begin); - mProfileParams.setEnd(end); - - return valid; -} - -bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e) -{ - bool valid = true; + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } - // First, clamp to valid ranges. - F32 begin = b; - valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } - F32 end = e; - valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } - valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + lp = getNormal().getF32ptr(); + rp = rhs.getNormal().getF32ptr(); - // Now set them. - mPathParams.setBegin(begin); - mPathParams.setEnd(end); + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } - return valid; -} + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } -bool LLVolumeParams::setHollow(const F32 h) -{ - // Validate the hollow based on path and profile. - U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; - - F32 max_hollow = HOLLOW_MAX; - - // Only square holes have trouble. - if (LL_PCODE_HOLE_SQUARE == hole_type) - { - switch(profile) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - case LL_PCODE_PROFILE_EQUALTRI: - max_hollow = HOLLOW_MAX_SQUARE; - } - } - - F32 hollow = h; - bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); - mProfileParams.setHollow(hollow); - - return valid; -} + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } -bool LLVolumeParams::setTwistBegin(const F32 b) -{ - F32 twist_begin = b; - bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistBegin(twist_begin); - return valid; -} + if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) + { + return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; + } -bool LLVolumeParams::setTwistEnd(const F32 e) -{ - F32 twist_end = e; - bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); - mPathParams.setTwistEnd(twist_end); - return valid; + return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; } -bool LLVolumeParams::setRatio(const F32 x, const F32 y) +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const { - F32 min_x = RATIO_MIN; - F32 max_x = RATIO_MAX; - F32 min_y = RATIO_MIN; - F32 max_y = RATIO_MAX; - // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PATH_CIRCLE == path_type && - LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) - { - // Holes are more restricted... - min_x = HOLE_X_MIN; - max_x = HOLE_X_MAX; - min_y = HOLE_Y_MIN; - max_y = HOLE_Y_MAX; - } - - F32 ratio_x = x; - bool valid = limit_range(ratio_x, min_x, max_x); - F32 ratio_y = y; - valid &= limit_range(ratio_y, min_y, max_y); - - mPathParams.setScale(ratio_x, ratio_y); - - return valid; + return mData[POSITION].equals3(rhs.getPosition()) && + mData[NORMAL].equals3(rhs.getNormal()) && + mTexCoord == rhs.mTexCoord; } -bool LLVolumeParams::setShear(const F32 x, const F32 y) +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const { - F32 shear_x = x; - bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); - F32 shear_y = y; - valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); - mPathParams.setShear(shear_x, shear_y); - return valid; -} + bool retval = false; -bool LLVolumeParams::setTaperX(const F32 v) -{ - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperX(taper); - return valid; -} + const F32 epsilon = 0.00001f; -bool LLVolumeParams::setTaperY(const F32 v) -{ - F32 taper = v; - bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); - mPathParams.setTaperY(taper); - return valid; -} + if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && + fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && + fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) + { + if (angle_cutoff > 1.f) + { + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); + } + else + { + F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); + retval = cur_angle > angle_cutoff; + } + } -bool LLVolumeParams::setRevolutions(const F32 r) -{ - F32 revolutions = r; - bool valid = limit_range(revolutions, REV_MIN, REV_MAX); - mPathParams.setRevolutions(revolutions); - return valid; + return retval; } -bool LLVolumeParams::setRadiusOffset(const F32 offset) +bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { - bool valid = true; - - // If this is a sphere, just set it to 0 and get out. - U8 path_type = mPathParams.getCurveType(); - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || - LL_PCODE_PATH_CIRCLE != path_type ) - { - mPathParams.setRadiusOffset(0.f); - return true; - } - - // Limit radius offset, based on taper and hole size y. - F32 radius_offset = offset; - F32 taper_y = getTaperY(); - F32 radius_mag = fabs(radius_offset); - F32 hole_y_mag = fabs(getRatioY()); - F32 taper_y_mag = fabs(taper_y); - // Check to see if the taper effects us. - if ( (radius_offset > 0.f && taper_y < 0.f) || - (radius_offset < 0.f && taper_y > 0.f) ) - { - // The taper does not help increase the radius offset range. - taper_y_mag = 0.f; - } - F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); - - // Enforce the maximum magnitude. - F32 delta = max_radius_mag - radius_mag; - if (delta < 0.f) - { - // Check radius offset sign. - if (radius_offset < 0.f) - { - radius_offset = -max_radius_mag; - } - else - { - radius_offset = max_radius_mag; - } - valid = approx_zero(delta, .1f); - } - - mPathParams.setRadiusOffset(radius_offset); - return valid; -} + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME -bool LLVolumeParams::setSkew(const F32 skew_value) -{ - bool valid = true; - - // Check the skew value against the revolutions. - F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); - F32 skew_mag = fabs(skew); - F32 revolutions = getRevolutions(); - F32 scale_x = getRatioX(); - F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); - // Discontinuity; A revolution of 1 allows skews below 0.5. - if ( fabs(revolutions - 1.0f) < 0.001) - min_skew_mag = 0.0f; - - // Clip skew. - F32 delta = skew_mag - min_skew_mag; - if (delta < 0.f) - { - // Check skew sign. - if (skew < 0.0f) - { - skew = -min_skew_mag; - } - else - { - skew = min_skew_mag; - } - valid = approx_zero(delta, .01f); - } - - mPathParams.setSkew(skew); - return valid; + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, is, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); } -bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type) +bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) { - mSculptID = sculpt_id; - mSculptType = sculpt_type; - return true; + //input data is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); + if (uzip_result != LLUZipHelper::ZR_OK) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; + return false; + } + return unpackVolumeFacesInternal(mdl); } -bool LLVolumeParams::setType(U8 profile, U8 path) +bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) { - bool result = true; - // First, check profile and path for validity. - U8 profile_type = profile & LL_PCODE_PROFILE_MASK; - U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; - U8 path_type = path >> 4; - - if (profile_type > LL_PCODE_PROFILE_MAX) - { - // Bad profile. Make it square. - profile = LL_PCODE_PROFILE_SQUARE; - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad profile type (" << profile_type - << ") to be LL_PCODE_PROFILE_SQUARE" << LL_ENDL; - } - else if (hole_type > LL_PCODE_HOLE_MAX) - { - // Bad hole. Make it the same. - profile = profile_type; - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad hole type (" << hole_type - << ") to be LL_PCODE_HOLE_SAME" << LL_ENDL; - } - - if (path_type < LL_PCODE_PATH_MIN || - path_type > LL_PCODE_PATH_MAX) - { - // Bad path. Make it linear. - result = false; - LL_WARNS() << "LLVolumeParams::setType changing bad path (" << path - << ") to be LL_PCODE_PATH_LINE" << LL_ENDL; - path = LL_PCODE_PATH_LINE; - } - - mProfileParams.setCurveType(profile); - mPathParams.setCurveType(path); - return result; -} - -// static -bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, - U8 path_curve, F32 path_begin, F32 path_end, - F32 scx, F32 scy, F32 shx, F32 shy, - F32 twistend, F32 twistbegin, F32 radiusoffset, - F32 tx, F32 ty, F32 revolutions, F32 skew) -{ - LLVolumeParams test_params; - if (!test_params.setType (prof_curve, path_curve)) - { - return false; - } - if (!test_params.setBeginAndEndS (prof_begin, prof_end)) - { - return false; - } - if (!test_params.setBeginAndEndT (path_begin, path_end)) - { - return false; - } - if (!test_params.setHollow (hollow)) - { - return false; - } - if (!test_params.setTwistBegin (twistbegin)) - { - return false; - } - if (!test_params.setTwistEnd (twistend)) - { - return false; - } - if (!test_params.setRatio (scx, scy)) - { - return false; - } - if (!test_params.setShear (shx, shy)) - { - return false; - } - if (!test_params.setTaper (tx, ty)) - { - return false; - } - if (!test_params.setRevolutions (revolutions)) - { - return false; - } - if (!test_params.setRadiusOffset (radiusoffset)) - { - return false; - } - if (!test_params.setSkew (skew)) - { - return false; - } - return true; -} + { + U32 face_count = mdl.size(); -void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts) -{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the - //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - F32 detail[] = {1.f, 1.5f, 2.5f, 4.f}; - for (S32 i = 0; i < 4; i++) - { - S32 count = 0; - S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]); - S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]); + if (face_count == 0) + { //no faces unpacked, treat as failed decode + LL_WARNS() << "found no faces!" << LL_ENDL; + return false; + } - count = (profile_points-1)*2*(path_points-1); - count += profile_points*2; + mVolumeFaces.resize(face_count); - counts[i] = count; - } -} + for (size_t i = 0; i < face_count; ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + if (mdl[i].has("NoGeometry")) + { //face has no geometry, continue + face.resizeIndices(3); + face.resizeVertices(1); + face.mPositions->clear(); + face.mNormals->clear(); + face.mTexCoords->setZero(); + memset(face.mIndices, 0, sizeof(U16)*3); + continue; + } + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tangent = mdl[i]["Tangent"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; -S32 LLVolume::getNumTriangles(S32* vcount) const -{ - U32 triangle_count = 0; - U32 vertex_count = 0; + //copy out indices + S32 num_indices = idx.size() / 2; + const S32 indices_to_discard = num_indices % 3; + if (indices_to_discard > 0) + { + // Invalid number of triangle indices + LL_WARNS() << "Incomplete triangle discarded from face! Indices count " << num_indices << " was not divisible by 3. face index: " << i << " Total: " << face_count << LL_ENDL; + num_indices -= indices_to_discard; + } + face.resizeIndices(num_indices); - for (S32 i = 0; i < getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = getVolumeFace(i); - triangle_count += face.mNumIndices/3; + if (num_indices > 2 && !face.mIndices) + { + LL_WARNS() << "Failed to allocate " << num_indices << " indices for face index: " << i << " Total: " << face_count << LL_ENDL; + continue; + } - vertex_count += face.mNumVertices; - } + if (idx.empty() || face.mNumIndices < 3) + { //why is there an empty index list? + LL_WARNS() << "Empty face present! Face index: " << i << " Total: " << face_count << LL_ENDL; + continue; + } + U16* indices = (U16*) &(idx[0]); + for (U32 j = 0; j < num_indices; ++j) + { + face.mIndices[j] = indices[j]; + } - if (vcount) - { - *vcount = vertex_count; - } - - return triangle_count; -} + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.resizeVertices(num_verts); + if (num_verts > 0 && !face.mPositions) + { + LL_WARNS() << "Failed to allocate " << num_verts << " vertices for face index: " << i << " Total: " << face_count << LL_ENDL; + face.resizeIndices(0); + continue; + } -//----------------------------------------------------------------------------- -// generateSilhouetteVertices() -//----------------------------------------------------------------------------- -void LLVolume::generateSilhouetteVertices(std::vector &vertices, - std::vector &normals, - const LLVector3& obj_cam_vec_in, - const LLMatrix4& mat_in, - const LLMatrix3& norm_mat_in, - S32 face_mask) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - - LLMatrix4a mat; - mat.loadu(mat_in); - - LLMatrix4a norm_mat; - norm_mat.loadu(norm_mat_in); - - LLVector4a obj_cam_vec; - obj_cam_vec.load3(obj_cam_vec_in.mV); - - vertices.clear(); - normals.clear(); - - if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - return; - } - - S32 cur_index = 0; - //for each face - for (face_list_t::iterator iter = mVolumeFaces.begin(); - iter != mVolumeFaces.end(); ++iter) - { - LLVolumeFace& face = *iter; - - if (!(face_mask & (0x1 << cur_index++)) || - face.mNumIndices == 0 || face.mEdge.empty()) - { - continue; - } - - if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) - { - LLVector4a* v = (LLVector4a*)face.mPositions; - LLVector4a* n = (LLVector4a*)face.mNormals; - - for (U32 j = 0; j < face.mNumIndices / 3; j++) - { - for (S32 k = 0; k < 3; k++) - { - S32 index = face.mEdge[j * 3 + k]; - - if (index == -1) - { - // silhouette edge, currently only cubes, so no other conditions - - S32 v1 = face.mIndices[j * 3 + k]; - S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)]; - - LLVector4a t; - mat.affineTransform(v[v1], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v1], t); - - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - - mat.affineTransform(v[v2], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v2], t); - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - } - } - } - - } - else - { - - //============================================== - //DEBUG draw edge map instead of silhouette edge - //============================================== + LLVector3 minp; + LLVector3 maxp; + LLVector2 min_tc; + LLVector2 max_tc; -#if DEBUG_SILHOUETTE_EDGE_MAP + minp.setValue(mdl[i]["PositionDomain"]["Min"]); + maxp.setValue(mdl[i]["PositionDomain"]["Max"]); + LLVector4a min_pos, max_pos; + min_pos.load3(minp.mV); + max_pos.load3(maxp.mV); - //for each triangle - U32 tri_count = face.mNumIndices / 3; - for (U32 j = 0; j < tri_count; j++) { - //get vertices - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - //get current face center - LLVector3 cCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //for each edge - for (S32 k = 0; k < 3; k++) { - S32 nIndex = face.mEdge[j*3+k]; - if (nIndex <= -1) { - continue; - } + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); - if (nIndex >= (S32)tri_count) { - continue; - } - //get neighbor vertices - v1 = face.mIndices[nIndex*3+0]; - v2 = face.mIndices[nIndex*3+1]; - v3 = face.mIndices[nIndex*3+2]; - - //get neighbor face center - LLVector3 nCenter = (face.mVertices[v1].getPosition() + - face.mVertices[v2].getPosition() + - face.mVertices[v3].getPosition()) / 3.0f; - - //draw line - vertices.push_back(cCenter); - vertices.push_back(nCenter); - normals.push_back(LLVector3(1,1,1)); - normals.push_back(LLVector3(1,1,1)); - segments.push_back(vertices.size()); - } - } - - continue; - - //============================================== - //DEBUG - //============================================== - - //============================================== - //DEBUG draw normals instead of silhouette edge - //============================================== -#elif DEBUG_SILHOUETTE_NORMALS + //unpack normalized scale/translation + if (mdl[i].has("NormalizedScale")) + { + face.mNormalizedScale.setValue(mdl[i]["NormalizedScale"]); + } + else + { + face.mNormalizedScale.set(1, 1, 1); + } - //for each vertex - for (U32 j = 0; j < face.mNumVertices; j++) { - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); -#if DEBUG_SILHOUETTE_BINORMALS - vertices.push_back(face.mVertices[j].getPosition()); - vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mTangent*0.1f); - normals.push_back(LLVector3(0,0,1)); - normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); -#endif - } - - continue; -#else - //============================================== - //DEBUG - //============================================== - - static const U8 AWAY = 0x01, - TOWARDS = 0x02; - - //for each triangle - std::vector fFacing; - vector_append(fFacing, face.mNumIndices/3); - - LLVector4a* v = (LLVector4a*) face.mPositions; - LLVector4a* n = (LLVector4a*) face.mNormals; - - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - //approximate normal - S32 v1 = face.mIndices[j*3+0]; - S32 v2 = face.mIndices[j*3+1]; - S32 v3 = face.mIndices[j*3+2]; - - LLVector4a c1,c2; - c1.setSub(v[v1], v[v2]); - c2.setSub(v[v2], v[v3]); - - LLVector4a norm; - - norm.setCross3(c1, c2); - - if (norm.dot3(norm) < 0.00000001f) - { - fFacing[j] = AWAY | TOWARDS; - } - else - { - //get view vector - LLVector4a view; - view.setSub(obj_cam_vec, v[v1]); - bool away = view.dot3(norm) > 0.0f; - if (away) - { - fFacing[j] = AWAY; - } - else - { - fFacing[j] = TOWARDS; - } - } - } - - //for each triangle - for (U32 j = 0; j < face.mNumIndices/3; j++) - { - if (fFacing[j] == (AWAY | TOWARDS)) - { //this is a degenerate triangle - //take neighbor facing (degenerate faces get facing of one of their neighbors) - // *FIX IF NEEDED: this does not deal with neighboring degenerate faces - for (S32 k = 0; k < 3; k++) - { - S32 index = face.mEdge[j*3+k]; - if (index != -1) - { - fFacing[j] = fFacing[index]; - break; - } - } - continue; //skip degenerate face - } - - //for each edge - for (S32 k = 0; k < 3; k++) { - S32 index = face.mEdge[j*3+k]; - if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { - //our neighbor is degenerate, make him face our direction - fFacing[face.mEdge[j*3+k]] = fFacing[j]; - continue; - } - - if (index == -1 || //edge has no neighbor, MUST be a silhouette edge - (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge - - S32 v1 = face.mIndices[j*3+k]; - S32 v2 = face.mIndices[j*3+((k+1)%3)]; - - LLVector4a t; - mat.affineTransform(v[v1], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v1], t); - - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - - mat.affineTransform(v[v2], t); - vertices.push_back(LLVector3(t[0], t[1], t[2])); - - norm_mat.rotate(n[v2], t); - t.normalize3fast(); - normals.push_back(LLVector3(t[0], t[1], t[2])); - } - } - } -#endif - } - } -} - -S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out) -{ - S32 hit_face = -1; - - S32 start_face; - S32 end_face; - - if (face == -1) // ALL_SIDES - { - start_face = 0; - end_face = getNumVolumeFaces() - 1; - } - else - { - start_face = face; - end_face = face; - } - - LLVector4a dir; - dir.setSub(end, start); - - F32 closest_t = 2.f; // must be larger than 1 - - end_face = llmin(end_face, getNumVolumeFaces()-1); - - for (S32 i = start_face; i <= end_face; i++) - { - LLVolumeFace &face = mVolumeFaces[i]; - - LLVector4a box_center; - box_center.setAdd(face.mExtents[0], face.mExtents[1]); - box_center.mul(0.5f); - - LLVector4a box_size; - box_size.setSub(face.mExtents[1], face.mExtents[0]); + LLVector4a pos_range; + pos_range.setSub(max_pos, min_pos); + LLVector2 tc_range2 = max_tc - min_tc; - if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) - { - if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them - { - genTangents(i); - } - - if (isUnique()) - { //don't bother with an octree for flexi volumes - U32 tri_count = face.mNumIndices/3; - - for (U32 j = 0; j < tri_count; ++j) - { - U16 idx0 = face.mIndices[j*3+0]; - U16 idx1 = face.mIndices[j*3+1]; - U16 idx2 = face.mIndices[j*3+2]; - - const LLVector4a& v0 = face.mPositions[idx0]; - const LLVector4a& v1 = face.mPositions[idx1]; - const LLVector4a& v2 = face.mPositions[idx2]; - - F32 a,b,t; - - if (LLTriangleRayIntersect(v0, v1, v2, - start, dir, a, b, t)) - { - if ((t >= 0.f) && // if hit is after start - (t <= 1.f) && // and before end - (t < closest_t)) // and this hit is closer - { - closest_t = t; - hit_face = i; - - if (intersection != NULL) - { - LLVector4a intersect = dir; - intersect.mul(closest_t); - intersect.add(start); - *intersection = intersect; - } - - - if (tex_coord != NULL) - { - LLVector2* tc = (LLVector2*) face.mTexCoords; - *tex_coord = ((1.f - a - b) * tc[idx0] + - a * tc[idx1] + - b * tc[idx2]); - - } - - if (normal!= NULL) - { - LLVector4a* norm = face.mNormals; - - LLVector4a n1,n2,n3; - n1 = norm[idx0]; - n1.mul(1.f-a-b); - - n2 = norm[idx1]; - n2.mul(a); - - n3 = norm[idx2]; - n3.mul(b); - - n1.add(n2); - n1.add(n3); - - *normal = n1; - } - - if (tangent_out != NULL) - { - LLVector4a* tangents = face.mTangents; - - LLVector4a t1,t2,t3; - t1 = tangents[idx0]; - t1.mul(1.f-a-b); - - t2 = tangents[idx1]; - t2.mul(a); - - t3 = tangents[idx2]; - t3.mul(b); - - t1.add(t2); - t1.add(t3); - - *tangent_out = t1; - } - } - } - } - } - else - { - if (!face.getOctree()) - { - face.createOctree(); - } - - LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); - intersect.traverse(face.getOctree()); - if (intersect.mHitFace) - { - hit_face = i; - } - } - } - } - - - return hit_face; -} + LLVector4a tc_range; + tc_range.set(tc_range2[0], tc_range2[1], tc_range2[0], tc_range2[1]); + LLVector4a min_tc4(min_tc[0], min_tc[1], min_tc[0], min_tc[1]); -class LLVertexIndexPair -{ -public: - LLVertexIndexPair(const LLVector3 &vertex, const S32 index); + LLVector4a* pos_out = face.mPositions; + LLVector4a* norm_out = face.mNormals; + LLVector4a* tc_out = (LLVector4a*) face.mTexCoords; - LLVector3 mVertex; - S32 mIndex; -}; + { + U16* v = (U16*) &(pos[0]); + for (U32 j = 0; j < num_verts; ++j) + { + pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); + pos_out->div(65535.f); + pos_out->mul(pos_range); + pos_out->add(min_pos); + pos_out++; + v += 3; + } -LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index) -{ - mVertex = vertex; - mIndex = index; -} + } -const F32 VERTEX_SLOP = 0.00001f; + { + if (!norm.empty()) + { + U16* n = (U16*) &(norm[0]); + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + n += 3; + } + } + else + { + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->clear(); + norm_out++; // or just norm_out[j].clear(); + } + } + } -struct lessVertex -{ - bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) - { - const F32 slop = VERTEX_SLOP; - - if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) - { - return TRUE; - } - else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) - { - return FALSE; - } - - if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) - { - return TRUE; - } - else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) - { - return FALSE; - } - - if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) - { - return TRUE; - } - else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) - { - return FALSE; - } - - return FALSE; - } -}; +#if 0 // keep this code for now in case we decide to add support for on-the-wire tangents + { + if (!tangent.empty()) + { + face.allocateTangents(face.mNumVertices); + U16* t = (U16*)&(tangent[0]); -struct lessTriangle -{ - bool operator()(const S32 *a, const S32 *b) - { - if (*a < *b) - { - return TRUE; - } - else if (*a > *b) - { - return FALSE; - } - - if (*(a+1) < *(b+1)) - { - return TRUE; - } - else if (*(a+1) > *(b+1)) - { - return FALSE; - } - - if (*(a+2) < *(b+2)) - { - return TRUE; - } - else if (*(a+2) > *(b+2)) - { - return FALSE; - } - - return FALSE; - } -}; + // NOTE: tangents coming from the asset may not be mikkt space, but they should always be used by the GLTF shaders to + // maintain compliance with the GLTF spec + LLVector4a* t_out = face.mTangents; -BOOL equalTriangle(const S32 *a, const S32 *b) -{ - if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) - { - return TRUE; - } - return FALSE; -} + for (U32 j = 0; j < num_verts; ++j) + { + t_out->set((F32)t[0], (F32)t[1], (F32)t[2], (F32) t[3]); + t_out->div(65535.f); + t_out->mul(2.f); + t_out->sub(1.f); -BOOL LLVolumeParams::importFile(LLFILE *fp) -{ - //LL_INFOS() << "importing volume" << LL_ENDL; - const S32 BUFSIZE = 16384; - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importFile(fp); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importFile(fp); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; - } - } - - return TRUE; -} + F32* tp = t_out->getF32ptr(); + tp[3] = tp[3] < 0.f ? -1.f : 1.f; -BOOL LLVolumeParams::exportFile(LLFILE *fp) const -{ - fprintf(fp,"\tshape 0\n"); - fprintf(fp,"\t{\n"); - mPathParams.exportFile(fp); - mProfileParams.exportFile(fp); - fprintf(fp, "\t}\n"); - return TRUE; + t_out++; + t += 4; + } + } + } +#endif + + { + if (!tc.empty()) + { + U16* t = (U16*) &(tc[0]); + for (U32 j = 0; j < num_verts; j+=2) + { + if (j < num_verts-1) + { + tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); + } + else + { + tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); + } + + t += 4; + + tc_out->div(65535.f); + tc_out->mul(tc_range); + tc_out->add(min_tc4); + + tc_out++; + } + } + else + { + for (U32 j = 0; j < num_verts; j += 2) + { + tc_out->clear(); + tc_out++; + } + } + } + + if (mdl[i].has("Weights")) + { + face.allocateWeights(num_verts); + if (!face.mWeights && num_verts) + { + LL_WARNS() << "Failed to allocate " << num_verts << " weights for face index: " << i << " Total: " << face_count << LL_ENDL; + face.resizeIndices(0); + face.resizeVertices(0); + continue; + } + + LLSD::Binary weights = mdl[i]["Weights"]; + + U32 idx = 0; + + U32 cur_vertex = 0; + while (idx < weights.size() && cur_vertex < num_verts) + { + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; + + U32 cur_influence = 0; + LLVector4 wght(0,0,0,0); + U32 joints[4] = {0,0,0,0}; + LLVector4 joints_with_weights(0,0,0,0); + + while (joint != END_INFLUENCES && idx < weights.size()) + { + U16 influence = weights[idx++]; + influence |= ((U16) weights[idx++] << 8); + + F32 w = llclamp((F32) influence / 65535.f, 0.001f, 0.999f); + wght.mV[cur_influence] = w; + joints[cur_influence] = joint; + cur_influence++; + + if (cur_influence >= 4) + { + joint = END_INFLUENCES; + } + else + { + joint = weights[idx++]; + } + } + F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW]; + if (wsum <= 0.f) + { + wght = LLVector4(0.999f,0.f,0.f,0.f); + } + for (U32 k=0; k<4; k++) + { + F32 f_combined = (F32) joints[k] + wght[k]; + joints_with_weights[k] = f_combined; + // Any weights we added above should wind up non-zero and applied to a specific bone. + // A failure here would indicate a floating point precision error in the math. + llassert((k >= cur_influence) || (f_combined - S32(f_combined) > 0.0f)); + } + face.mWeights[cur_vertex].loadua(joints_with_weights.mV); + + cur_vertex++; + } + + if (cur_vertex != num_verts || idx != weights.size()) + { + LL_WARNS() << "Vertex weight count does not match vertex count!" << LL_ENDL; + } + + } + + // modifier flags? + bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + + + // translate to actions: + bool do_reflect_x = false; + bool do_reverse_triangles = false; + bool do_invert_normals = false; + + if (do_mirror) + { + do_reflect_x = true; + do_reverse_triangles = !do_reverse_triangles; + } + + if (do_invert) + { + do_invert_normals = true; + do_reverse_triangles = !do_reverse_triangles; + } + + // now do the work + + if (do_reflect_x) + { + LLVector4a* p = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + p[i].mul(-1.0f); + n[i].mul(-1.0f); + } + } + + if (do_invert_normals) + { + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + n[i].mul(-1.0f); + } + } + + if (do_reverse_triangles) + { + for (U32 j = 0; j < face.mNumIndices; j += 3) + { + // swap the 2nd and 3rd index + S32 swap = face.mIndices[j+1]; + face.mIndices[j+1] = face.mIndices[j+2]; + face.mIndices[j+2] = swap; + } + } + + //calculate bounding box + // VFExtents change + LLVector4a& min = face.mExtents[0]; + LLVector4a& max = face.mExtents[1]; + + if (face.mNumVertices < 3) + { //empty face, use a dummy 1cm (at 1m scale) bounding box + min.splat(-0.005f); + max.splat(0.005f); + } + else + { + min = max = face.mPositions[0]; + + for (S32 i = 1; i < face.mNumVertices; ++i) + { + min.setMin(min, face.mPositions[i]); + max.setMax(max, face.mPositions[i]); + } + + if (face.mTexCoords) + { + LLVector2& min_tc = face.mTexCoordExtents[0]; + LLVector2& max_tc = face.mTexCoordExtents[1]; + + min_tc = face.mTexCoords[0]; + max_tc = face.mTexCoords[0]; + + for (U32 j = 1; j < face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, face.mTexCoords[j]); + } + } + else + { + face.mTexCoordExtents[0].set(0,0); + face.mTexCoordExtents[1].set(1,1); + } + } + } + } + + if (!cacheOptimize(true)) + { + // Out of memory? + LL_WARNS() << "Failed to optimize!" << LL_ENDL; + mVolumeFaces.clear(); + return false; + } + + mSculptLevel = 0; // success! + + return true; } -BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) +bool LLVolume::isMeshAssetLoaded() { - //LL_INFOS() << "importing volume" << LL_ENDL; - const S32 BUFSIZE = 16384; - // *NOTE: changing the size or type of this buffer will require - // changing the sscanf below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[256]; /* Flawfinder: ignore */ - keyword[0] = 0; - - while (input_stream.good()) - { - input_stream.getline(buffer, BUFSIZE); - sscanf(buffer, " %255s", keyword); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("profile", keyword)) - { - mProfileParams.importLegacyStream(input_stream); - } - else if (!strcmp("path",keyword)) - { - mPathParams.importLegacyStream(input_stream); - } - else - { - LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; - } - } - - return TRUE; + return mIsMeshAssetLoaded; } -BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const +void LLVolume::setMeshAssetLoaded(bool loaded) { - output_stream <<"\tshape 0\n"; - output_stream <<"\t{\n"; - mPathParams.exportLegacyStream(output_stream); - mProfileParams.exportLegacyStream(output_stream); - output_stream << "\t}\n"; - return TRUE; + mIsMeshAssetLoaded = loaded; + if (loaded) + { + mIsMeshAssetUnavaliable = false; + } } -LLSD LLVolumeParams::sculptAsLLSD() const +void LLVolume::setMeshAssetUnavaliable(bool unavaliable) { - LLSD sd = LLSD(); - sd["id"] = getSculptID(); - sd["type"] = getSculptType(); - - return sd; + // Don't set it if at least one lod loaded + if (!mIsMeshAssetLoaded) + { + mIsMeshAssetUnavaliable = unavaliable; + } } -bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +bool LLVolume::isMeshAssetUnavaliable() { - setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); - return true; + return mIsMeshAssetUnavaliable; } -LLSD LLVolumeParams::asLLSD() const +void LLVolume::copyFacesTo(std::vector &faces) const { - LLSD sd = LLSD(); - sd["path"] = mPathParams; - sd["profile"] = mProfileParams; - sd["sculpt"] = sculptAsLLSD(); - - return sd; + faces = mVolumeFaces; } -bool LLVolumeParams::fromLLSD(LLSD& sd) +void LLVolume::copyFacesFrom(const std::vector &faces) { - mPathParams.fromLLSD(sd["path"]); - mProfileParams.fromLLSD(sd["profile"]); - sculptFromLLSD(sd["sculpt"]); - - return true; + mVolumeFaces = faces; + mSculptLevel = 0; } -void LLVolumeParams::reduceS(F32 begin, F32 end) +void LLVolume::copyVolumeFaces(const LLVolume* volume) { - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mProfileParams.getBegin(); - F32 b = mProfileParams.getEnd(); - mProfileParams.setBegin(a + begin * (b - a)); - mProfileParams.setEnd(a + end * (b - a)); + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; } -void LLVolumeParams::reduceT(F32 begin, F32 end) +bool LLVolume::cacheOptimize(bool gen_tangents) { - begin = llclampf(begin); - end = llclampf(end); - if (begin > end) - { - F32 temp = begin; - begin = end; - end = temp; - } - F32 a = mPathParams.getBegin(); - F32 b = mPathParams.getEnd(); - mPathParams.setBegin(a + begin * (b - a)); - mPathParams.setEnd(a + end * (b - a)); + for (S32 i = 0; i < mVolumeFaces.size(); ++i) + { + if (!mVolumeFaces[i].cacheOptimize(gen_tangents)) + { + return false; + } + } + return true; } -const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity -const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity -// returns TRUE if the shape can be approximated with a convex shape -// for collison purposes -BOOL LLVolumeParams::isConvex() const +S32 LLVolume::getNumFaces() const { - if (!getSculptID().isNull()) - { - // can't determine, be safe and say no: - return FALSE; - } - - F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); - F32 hollow = mProfileParams.getHollow(); - - U8 path_type = mPathParams.getCurveType(); - if ( path_length > MIN_CONCAVE_PATH_WEDGE - && ( mPathParams.getTwist() != mPathParams.getTwistBegin() - || (hollow > 0.f - && LL_PCODE_PATH_LINE != path_type) ) ) - { - // twist along a "not too short" path is concave - return FALSE; - } - - F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); - BOOL same_hole = hollow == 0.f - || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; - - F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; - U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // it is a sphere and spheres get twice the minimum profile wedge - min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; - } - - BOOL convex_profile = ( ( profile_length == 1.f - || profile_length <= 0.5f ) - && hollow == 0.f ) // trivially convex - || ( profile_length <= min_profile_wedge - && same_hole ); // effectvely convex (even when hollow) - - if (!convex_profile) - { - // profile is concave - return FALSE; - } - - if ( LL_PCODE_PATH_LINE == path_type ) - { - // straight paths with convex profile - return TRUE; - } - - BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); - if (concave_path) - { - return FALSE; - } - - // we're left with spheres, toroids and tubes - if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) - { - // at this stage all spheres must be convex - return TRUE; - } - - // it's a toroid or tube - if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) - { - // effectively convex - return TRUE; - } - - return FALSE; + return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size(); } -// debug -void LLVolumeParams::setCube() + +void LLVolume::createVolumeFaces() { - mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); - mProfileParams.setBegin(0.f); - mProfileParams.setEnd(1.f); - mProfileParams.setHollow(0.f); + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME - mPathParams.setBegin(0.f); - mPathParams.setEnd(1.f); - mPathParams.setScale(1.f, 1.f); - mPathParams.setShear(0.f, 0.f); - mPathParams.setCurveType(LL_PCODE_PATH_LINE); - mPathParams.setTwistBegin(0.f); - mPathParams.setTwistEnd(0.f); - mPathParams.setRadiusOffset(0.f); - mPathParams.setTaper(0.f, 0.f); - mPathParams.setRevolutions(0.f); - mPathParams.setSkew(0.f); -} + if (mGenerateSingleFace) + { + // do nothing + } + else + { + S32 num_faces = getNumFaces(); + BOOL partial_build = TRUE; + if (num_faces != mVolumeFaces.size()) + { + partial_build = FALSE; + mVolumeFaces.resize(num_faces); + } + // Initialize volume faces with parameter data + for (S32 i = 0; i < (S32)mVolumeFaces.size(); i++) + { + LLVolumeFace& vf = mVolumeFaces[i]; + LLProfile::Face& face = mProfilep->mFaces[i]; + vf.mBeginS = face.mIndex; + vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + LL_ERRS() << "Volume face corruption detected." << LL_ENDL; + } -LLFaceID LLVolume::generateFaceMask() -{ - LLFaceID new_mask = 0x0000; - - switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) - { - case LL_PCODE_PROFILE_CIRCLE: - case LL_PCODE_PROFILE_CIRCLE_HALF: - new_mask |= LL_FACE_OUTER_SIDE_0; - break; - case LL_PCODE_PROFILE_SQUARE: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - case LL_PCODE_PROFILE_ISOTRI: - case LL_PCODE_PROFILE_EQUALTRI: - case LL_PCODE_PROFILE_RIGHTTRI: - { - for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) - { - new_mask |= LL_FACE_OUTER_SIDE_0 << side; - } - } - break; - default: - LL_ERRS() << "Unknown profile!" << LL_ENDL; - break; - } - - // handle hollow objects - if (mParams.getProfileParams().getHollow() > 0) - { - new_mask |= LL_FACE_INNER_SIDE; - } - - // handle open profile curves - if (mProfilep->isOpen()) - { - new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; - } - - // handle open path curves - if (mPathp->isOpen()) - { - new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; - } - - return new_mask; -} + vf.mBeginT = 0; + vf.mNumT= getPath().mPath.size(); + vf.mID = i; -BOOL LLVolume::isFaceMaskValid(LLFaceID face_mask) -{ - LLFaceID test_mask = 0; - for(S32 i = 0; i < getNumFaces(); i++) - { - test_mask |= mProfilep->mFaces[i].mFaceID; - } + // Set the type mask bits correctly + if (mParams.getProfileParams().getHollow() > 0) + { + vf.mTypeMask |= LLVolumeFace::HOLLOW_MASK; + } + if (mProfilep->isOpen()) + { + vf.mTypeMask |= LLVolumeFace::OPEN_MASK; + } + if (face.mCap) + { + vf.mTypeMask |= LLVolumeFace::CAP_MASK; + if (face.mFaceID == LL_FACE_PATH_BEGIN) + { + vf.mTypeMask |= LLVolumeFace::TOP_MASK; + } + else + { + llassert(face.mFaceID == LL_FACE_PATH_END); + vf.mTypeMask |= LLVolumeFace::BOTTOM_MASK; + } + } + else if (face.mFaceID & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK | LLVolumeFace::END_MASK; + } + else + { + vf.mTypeMask |= LLVolumeFace::SIDE_MASK; + if (face.mFlat) + { + vf.mTypeMask |= LLVolumeFace::FLAT_MASK; + } + if (face.mFaceID & LL_FACE_INNER_SIDE) + { + vf.mTypeMask |= LLVolumeFace::INNER_MASK; + if (face.mFlat && vf.mNumS > 2) + { //flat inner faces have to copy vert normals + vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + LL_ERRS() << "Volume face corruption detected." << LL_ENDL; + } + } + } + else + { + vf.mTypeMask |= LLVolumeFace::OUTER_MASK; + } + } + } - return test_mask == face_mask; + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + (*iter).create(this, partial_build); + } + } } -BOOL LLVolume::isConvex() const + +inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b) { - // mParams.isConvex() may return FALSE even though the final - // geometry is actually convex due to LOD approximations. - // TODO -- provide LLPath and LLProfile with isConvex() methods - // that correctly determine convexity. -- Leviathan - return mParams.isConvex(); -} + // maps RGB values to vector values [0..255] -> [-0.5..0.5] + LLVector4a value; + LLVector4a sub(0.5f, 0.5f, 0.5f); + value.set(r,g,b); + value.mul(1.f/255.f); + value.sub(sub); -std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params) -{ - s << "{type=" << (U32) profile_params.mCurveType; - s << ", begin=" << profile_params.mBegin; - s << ", end=" << profile_params.mEnd; - s << ", hollow=" << profile_params.mHollow; - s << "}"; - return s; + return value; } - -std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params) +inline U32 sculpt_xy_to_index(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) { - s << "{type=" << (U32) path_params.mCurveType; - s << ", begin=" << path_params.mBegin; - s << ", end=" << path_params.mEnd; - s << ", twist=" << path_params.mTwistEnd; - s << ", scale=" << path_params.mScale; - s << ", shear=" << path_params.mShear; - s << ", twist_begin=" << path_params.mTwistBegin; - s << ", radius_offset=" << path_params.mRadiusOffset; - s << ", taper=" << path_params.mTaper; - s << ", revolutions=" << path_params.mRevolutions; - s << ", skew=" << path_params.mSkew; - s << "}"; - return s; + U32 index = (x + y * sculpt_width) * sculpt_components; + return index; } -std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params) +inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components) { - s << "{profileparams = " << volume_params.mProfileParams; - s << ", pathparams = " << volume_params.mPathParams; - s << "}"; - return s; + U32 x = (U32) ((F32)s/(size_s) * (F32) sculpt_width); + U32 y = (U32) ((F32)t/(size_t) * (F32) sculpt_height); + + return sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); } -std::ostream& operator<<(std::ostream &s, const LLProfile &profile) +inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data) { - s << " {open=" << (U32) profile.mOpen; - s << ", dirty=" << profile.mDirty; - s << ", totalout=" << profile.mTotalOut; - s << ", total=" << profile.mTotal; - s << "}"; - return s; -} + LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); + return v; +} -std::ostream& operator<<(std::ostream &s, const LLPath &path) +inline LLVector4a sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) { - s << "{open=" << (U32) path.mOpen; - s << ", dirty=" << path.mDirty; - s << ", step=" << path.mStep; - s << ", total=" << path.mTotal; - s << "}"; - return s; + U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components); + + return sculpt_index_to_vector(index, sculpt_data); } -std::ostream& operator<<(std::ostream &s, const LLVolume &volume) +inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) { - s << "{params = " << volume.getParams(); - s << ", path = " << *volume.mPathp; - s << ", profile = " << *volume.mProfilep; - s << "}"; - return s; + U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); + + return sculpt_index_to_vector(index, sculpt_data); } -std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) -{ - s << "{params = " << volumep->getParams(); - s << ", path = " << *(volumep->mPathp); - s << ", profile = " << *(volumep->mProfilep); - s << "}"; - return s; -} - -LLVolumeFace::LLVolumeFace() : - mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumAllocatedVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mTangents(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - mJustWeights(NULL), - mJointIndices(NULL), -#endif - mWeightsScrubbed(FALSE), - mOctree(NULL), - mOctreeTriangles(NULL), - mOptimized(FALSE) +F32 LLVolume::sculptGetSurfaceArea() { - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mExtents[0].splat(-0.5f); - mExtents[1].splat(0.5f); - mCenter = mExtents+2; -} + // test to see if image has enough variation to create non-degenerate geometry -LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) -: mID(0), - mTypeMask(0), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0), - mNumVertices(0), - mNumAllocatedVertices(0), - mNumIndices(0), - mPositions(NULL), - mNormals(NULL), - mTangents(NULL), - mTexCoords(NULL), - mIndices(NULL), - mWeights(NULL), -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - mJustWeights(NULL), - mJointIndices(NULL), -#endif - mWeightsScrubbed(FALSE), - mOctree(NULL), - mOctreeTriangles(NULL) -{ - mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); - mCenter = mExtents+2; - *this = src; -} + F32 area = 0; -LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) -{ - if (&src == this) - { //self assignment, do nothing - return *this; - } - - mID = src.mID; - mTypeMask = src.mTypeMask; - mBeginS = src.mBeginS; - mBeginT = src.mBeginT; - mNumS = src.mNumS; - mNumT = src.mNumT; - - mExtents[0] = src.mExtents[0]; - mExtents[1] = src.mExtents[1]; - *mCenter = *src.mCenter; - - mNumVertices = 0; - mNumIndices = 0; - - freeData(); - - resizeVertices(src.mNumVertices); - resizeIndices(src.mNumIndices); - - if (mNumVertices) - { - S32 vert_size = mNumVertices*sizeof(LLVector4a); - S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); - - if (src.mNormals) - { - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); - } - - if(src.mTexCoords) - { - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); - } - - if (src.mTangents) - { - allocateTangents(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size); - } - else - { - ll_aligned_free_16(mTangents); - mTangents = NULL; - } - - if (src.mWeights) - { - llassert(!mWeights); // don't orphan an old alloc here accidentally - allocateWeights(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); - mWeightsScrubbed = src.mWeightsScrubbed; - } - else - { - ll_aligned_free_16(mWeights); - mWeights = NULL; - mWeightsScrubbed = FALSE; - } + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); - #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - if (src.mJointIndices) + for (S32 s = 0; s < sizeS-1; s++) + { + for (S32 t = 0; t < sizeT-1; t++) { - llassert(!mJointIndices); // don't orphan an old alloc here accidentally - allocateJointIndices(src.mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4); + // get four corners of quad + LLVector4a& p1 = mMesh[(s )*sizeT + (t )]; + LLVector4a& p2 = mMesh[(s+1)*sizeT + (t )]; + LLVector4a& p3 = mMesh[(s )*sizeT + (t+1)]; + LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)]; + + // compute the area of the quad by taking the length of the cross product of the two triangles + LLVector4a v0,v1,v2,v3; + v0.setSub(p1,p2); + v1.setSub(p1,p3); + v2.setSub(p4,p2); + v3.setSub(p4,p3); + + LLVector4a cross1, cross2; + cross1.setCross3(v0,v1); + cross2.setCross3(v2,v3); + + //LLVector3 cross1 = (p1 - p2) % (p1 - p3); + //LLVector3 cross2 = (p4 - p2) % (p4 - p3); + + area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f; } - else*/ - { - ll_aligned_free_16(mJointIndices); - mJointIndices = NULL; - } - #endif - - } - - if (mNumIndices) - { - S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; - - LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); - } - else - { - ll_aligned_free_16(mIndices); - mIndices = NULL; } - mOptimized = src.mOptimized; - mNormalizedScale = src.mNormalizedScale; - - //delete - return *this; + return area; } -LLVolumeFace::~LLVolumeFace() +// create empty placeholder shape +void LLVolume::sculptGenerateEmptyPlaceholder() { - ll_aligned_free_16(mExtents); - mExtents = NULL; - mCenter = NULL; + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); + + S32 line = 0; + + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; + + F32* p = pt.getF32ptr(); - freeData(); + p[0] = 0; + p[1] = 0; + p[2] = 0; + + llassert(pt.isFinite3()); + } + line += sizeT; + } } -void LLVolumeFace::freeData() +// create sphere placeholder shape +void LLVolume::sculptGenerateSpherePlaceholder() { - ll_aligned_free<64>(mPositions); - mPositions = NULL; + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); - //normals and texture coordinates are part of the same buffer as mPositions, do not free them separately - mNormals = NULL; - mTexCoords = NULL; + S32 line = 0; - ll_aligned_free_16(mIndices); - mIndices = NULL; - ll_aligned_free_16(mTangents); - mTangents = NULL; - ll_aligned_free_16(mWeights); - mWeights = NULL; + for (S32 s = 0; s < sizeS; s++) + { + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; -#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS - ll_aligned_free_16(mJointIndices); - mJointIndices = NULL; - ll_aligned_free_16(mJustWeights); - mJustWeights = NULL; -#endif - destroyOctree(); -} + F32 u = (F32)s / (sizeS - 1); + F32 v = (F32)t / (sizeT - 1); -BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + const F32 RADIUS = (F32) 0.3; - //tree for this face is no longer valid - destroyOctree(); + F32* p = pt.getF32ptr(); - LL_CHECK_MEMORY - BOOL ret = FALSE ; - if (mTypeMask & CAP_MASK) - { - ret = createCap(volume, partial_build); - LL_CHECK_MEMORY - } - else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) - { - ret = createSide(volume, partial_build); - LL_CHECK_MEMORY - } - else - { - LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL; - } - - return ret ; -} + p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); + p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); + p[2] = (F32)(cos(F_PI * v) * RADIUS); -void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) -{ - cv.setPosition(mPositions[index]); - if (mNormals) - { - cv.setNormal(mNormals[index]); - } - else - { - cv.getNormal().clear(); - } - - if (mTexCoords) - { - cv.mTexCoord = mTexCoords[index]; - } - else - { - cv.mTexCoord.clear(); - } + llassert(pt.isFinite3()); + } + line += sizeT; + } } -bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const +// create the vertices from the map +void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type) { - return getPosition().equals3(rhs.getPosition()) && - mTexCoord == rhs.mTexCoord && - getNormal().equals3(rhs.getNormal()); -} + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + BOOL reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR -bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const -{ - if (a.mV[0] != b.mV[0]) - { - return a.mV[0] < b.mV[0]; - } - - if (a.mV[1] != b.mV[1]) - { - return a.mV[1] < b.mV[1]; - } - - return a.mV[2] < b.mV[2]; -} + S32 sizeS = mPathp->mPath.size(); + S32 sizeT = mProfilep->mProfile.size(); -void LLVolumeFace::remap() -{ - // Generate a remap buffer - std::vector remap(mNumVertices); - S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], - mIndices, - mNumIndices, - mPositions, - mNormals, - mTexCoords, - mNumVertices); + S32 line = 0; + for (S32 s = 0; s < sizeS; s++) + { + // Run along the profile. + for (S32 t = 0; t < sizeT; t++) + { + S32 i = t + line; + LLVector4a& pt = mMesh[i]; - // Allocate new buffers - S32 size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF; - U16* remap_indices = (U16*)ll_aligned_malloc_16(size); + S32 reversed_t = t; - S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF; - LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size); - LLVector4a* remap_normals = remap_positions + remap_vertices_count; - LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count); + if (reverse_horizontal) + { + reversed_t = sizeT - t - 1; + } - // Fill the buffers - LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]); - LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]); - LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]); - LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]); + U32 x = (U32) ((F32)reversed_t/(sizeT-1) * (F32) sculpt_width); + U32 y = (U32) ((F32)s/(sizeS-1) * (F32) sculpt_height); - // Free unused buffers - ll_aligned_free_16(mIndices); - ll_aligned_free<64>(mPositions); - // Tangets are now invalid - ll_aligned_free_16(mTangents); - mTangents = NULL; + if (y == 0) // top row stitching + { + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } - // Assign new values - mIndices = remap_indices; - mPositions = remap_positions; - mNormals = remap_normals; - mTexCoords = remap_tex_coords; - mNumVertices = remap_vertices_count; - mNumAllocatedVertices = remap_vertices_count; -} + if (y == sculpt_height) // bottom row stitching + { + // wrap? + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + { + y = 0; + } + else + { + y = sculpt_height - 1; + } -void LLVolumeFace::optimize(F32 angle_cutoff) -{ - LLVolumeFace new_face; + // pinch? + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + { + x = sculpt_width / 2; + } + } - //map of points to vector of vertices at that point - std::map > point_map; + if (x == sculpt_width) // side stitching + { + // wrap? + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + { + x = 0; + } - LLVector4a range; - range.setSub(mExtents[1],mExtents[0]); + else + { + x = sculpt_width - 1; + } + } - //remove redundant vertices - for (U32 i = 0; i < mNumIndices; ++i) - { - U16 index = mIndices[i]; + pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); - if (index >= mNumVertices) - { - // invalid index - // replace with a valid index to avoid crashes - index = mNumVertices - 1; - mIndices[i] = index; + if (sculpt_mirror) + { + LLVector4a scale(-1.f,1,1,1); + pt.mul(scale); + } - // Needs better logging - LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; + llassert(pt.isFinite3()); } - LLVolumeFace::VertexData cv; - getVertexData(index, cv); - - BOOL found = FALSE; - - LLVector4a pos; - pos.setSub(mPositions[index], mExtents[0]); - pos.div(range); - - U64 pos64 = 0; - - pos64 = (U16) (pos[0]*65535); - pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); - pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); - - std::map >::iterator point_iter = point_map.find(pos64); - - if (point_iter != point_map.end()) - { //duplicate point might exist - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - LLVolumeFace::VertexData& tv = (point_iter->second)[j]; - if (tv.compareNormal(cv, angle_cutoff)) - { - found = TRUE; - new_face.pushIndex((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - new_face.pushVertex(cv); - U16 index = (U16) new_face.mNumVertices-1; - new_face.pushIndex(index); - - VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[pos64].push_back(d); - } - } - } - - - if (angle_cutoff > 1.f && !mNormals) - { - // Now alloc'd with positions - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!mTexCoords) - { - // Now alloc'd with positions - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - // Only swap data if we've actually optimized the mesh - // - if (new_face.mNumVertices <= mNumVertices) - { - llassert(new_face.mNumIndices == mNumIndices); - swapData(new_face); - } - + line += sizeT; + } } -class LLVCacheTriangleData; -class LLVCacheVertexData -{ -public: - S32 mIdx; - S32 mCacheTag; - F64 mScore; - U32 mActiveTriangles; - std::vector mTriangles; - - LLVCacheVertexData() - { - mCacheTag = -1; - mScore = 0.0; - mActiveTriangles = 0; - mIdx = -1; - } -}; +const S32 SCULPT_REZ_1 = 6; // changed from 4 to 6 - 6 looks round whereas 4 looks square +const S32 SCULPT_REZ_2 = 8; +const S32 SCULPT_REZ_3 = 16; +const S32 SCULPT_REZ_4 = 32; -class LLVCacheTriangleData +S32 sculpt_sides(F32 detail) { -public: - bool mActive; - F64 mScore; - LLVCacheVertexData* mVertex[3]; - - LLVCacheTriangleData() - { - mActive = true; - mScore = 0.0; - mVertex[0] = mVertex[1] = mVertex[2] = NULL; - } - - void complete() - { - mActive = false; - for (S32 i = 0; i < 3; ++i) - { - if (mVertex[i]) - { - llassert(mVertex[i]->mActiveTriangles > 0); - mVertex[i]->mActiveTriangles--; - } - } - } - - bool operator<(const LLVCacheTriangleData& rhs) const - { //highest score first - return rhs.mScore < mScore; - } -}; -const F64 FindVertexScore_CacheDecayPower = 1.5; -const F64 FindVertexScore_LastTriScore = 0.75; -const F64 FindVertexScore_ValenceBoostScale = 2.0; -const F64 FindVertexScore_ValenceBoostPower = 0.5; -const U32 MaxSizeVertexCache = 32; -const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3); + // detail is usually one of: 1, 1.5, 2.5, 4.0. -F64 find_vertex_score(LLVCacheVertexData& data) + if (detail <= 1.0) + { + return SCULPT_REZ_1; + } + if (detail <= 2.0) + { + return SCULPT_REZ_2; + } + if (detail <= 3.0) + { + return SCULPT_REZ_3; + } + else + { + return SCULPT_REZ_4; + } +} + + + +// determine the number of vertices in both s and t direction for this sculpt +void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) { - F64 score = -1.0; + // this code has the following properties: + // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map + // while still using all available verts + // 2) the mesh cannot have more verts than is allowed by LOD + // 3) the mesh cannot have more verts than is allowed by the map - score = 0.0; + S32 max_vertices_lod = (S32)pow((double)sculpt_sides(detail), 2.0); + S32 max_vertices_map = width * height / 4; - S32 cache_idx = data.mCacheTag; + S32 vertices; + if (max_vertices_map > 0) + vertices = llmin(max_vertices_lod, max_vertices_map); + else + vertices = max_vertices_lod; - if (cache_idx < 0) - { - //not in cache - } - else - { - if (cache_idx < 3) - { //vertex was in the last triangle - score = FindVertexScore_LastTriScore; - } - else - { //more points for being higher in the cache - score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); - score = pow(score, FindVertexScore_CacheDecayPower); - } - } - //bonus points for having low valence - F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); - score += FindVertexScore_ValenceBoostScale * valence_boost; + F32 ratio; + if ((width == 0) || (height == 0)) + ratio = 1.f; + else + ratio = (F32) width / (F32) height; - return score; -} -class LLVCacheFIFO -{ -public: - LLVCacheVertexData* mCache[MaxSizeVertexCache]; - U32 mMisses; - - LLVCacheFIFO() - { - mMisses = 0; - for (U32 i = 0; i < MaxSizeVertexCache; ++i) - { - mCache[i] = NULL; - } - } - - void addVertex(LLVCacheVertexData* data) - { - if (data->mCacheTag == -1) - { - mMisses++; - - S32 end = MaxSizeVertexCache-1; - - if (mCache[end]) - { - mCache[end]->mCacheTag = -1; - } - - for (S32 i = end; i > 0; --i) - { - mCache[i] = mCache[i-1]; - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - data->mCacheTag = 0; - } - } -}; + s = (S32)(F32) sqrt(((F32)vertices / ratio)); -class LLVCacheLRU -{ -public: - LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; - - LLVCacheTriangleData* mBestTriangle; - - U32 mMisses; - - LLVCacheLRU() - { - for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) - { - mCache[i] = NULL; - } - - mBestTriangle = NULL; - mMisses = 0; - } - - void addVertex(LLVCacheVertexData* data) - { - S32 end = MaxSizeVertexCache+2; - if (data->mCacheTag != -1) - { //just moving a vertex to the front of the cache - end = data->mCacheTag; - } - else - { - mMisses++; - if (mCache[end]) - { //adding a new vertex, vertex at end of cache falls off - mCache[end]->mCacheTag = -1; - } - } - - for (S32 i = end; i > 0; --i) - { //adjust cache pointers and tags - mCache[i] = mCache[i-1]; - - if (mCache[i]) - { - mCache[i]->mCacheTag = i; - } - } - - mCache[0] = data; - mCache[0]->mCacheTag = 0; - } - - void addTriangle(LLVCacheTriangleData* data) - { - addVertex(data->mVertex[0]); - addVertex(data->mVertex[1]); - addVertex(data->mVertex[2]); - } - - void updateScores() - { - LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache; - LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3; - - while(data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter++; - //trailing 3 vertices aren't actually in the cache for scoring purposes - if (data) - { - data->mCacheTag = -1; - } - } - - data_iter = mCache; - end_data = mCache+MaxSizeVertexCache; - - while (data_iter != end_data) - { //update scores of vertices in cache - LLVCacheVertexData* data = *data_iter++; - if (data) - { - data->mScore = find_vertex_score(*data); - } - } - - mBestTriangle = NULL; - //update triangle scores - data_iter = mCache; - end_data = mCache+MaxSizeVertexCache+3; - - while (data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter++; - if (data) - { - for (std::vector::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter) - { - LLVCacheTriangleData* tri = *iter; - if (tri->mActive) - { - tri->mScore = tri->mVertex[0] ? tri->mVertex[0]->mScore : 0; - tri->mScore += tri->mVertex[1] ? tri->mVertex[1]->mScore : 0; - tri->mScore += tri->mVertex[2] ? tri->mVertex[2]->mScore : 0; - - if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) - { - mBestTriangle = tri; - } - } - } - } - } - - //knock trailing 3 vertices off the cache - data_iter = mCache+MaxSizeVertexCache; - end_data = mCache+MaxSizeVertexCache+3; - while (data_iter != end_data) - { - LLVCacheVertexData* data = *data_iter; - if (data) - { - llassert(data->mCacheTag == -1); - *data_iter = NULL; - } - ++data_iter; - } - } -}; + s = llmax(s, 4); // no degenerate sizes, please + t = vertices / s; -// data structures for tangent generation + t = llmax(t, 4); // no degenerate sizes, please + s = vertices / t; +} -struct MikktData +// sculpt replaces generate() for sculpted surfaces +void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) { - LLVolumeFace* face; - std::vector p; - std::vector n; - std::vector tc; - std::vector w; - std::vector t; + U8 sculpt_type = mParams.getSculptType(); - MikktData(LLVolumeFace* f) - : face(f) + BOOL data_is_empty = FALSE; + + if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) { - U32 count = face->mNumIndices; + sculpt_level = -1; + data_is_empty = TRUE; + } - p.resize(count); - n.resize(count); - tc.resize(count); - t.resize(count); + S32 requested_sizeS = 0; + S32 requested_sizeT = 0; - if (face->mWeights) - { - w.resize(count); - } + sculpt_calc_mesh_resolution(sculpt_width, sculpt_height, sculpt_type, mDetail, requested_sizeS, requested_sizeT); + mPathp->generate(mParams.getPathParams(), mDetail, 0, TRUE, requested_sizeS); + mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(), mDetail, 0, TRUE, requested_sizeT); - LLVector3 inv_scale(1.f / face->mNormalizedScale.mV[0], 1.f / face->mNormalizedScale.mV[1], 1.f / face->mNormalizedScale.mV[2]); - + S32 sizeS = mPathp->mPath.size(); // we requested a specific size, now see what we really got + S32 sizeT = mProfilep->mProfile.size(); // we requested a specific size, now see what we really got - for (int i = 0; i < face->mNumIndices; ++i) - { - U32 idx = face->mIndices[i]; + // weird crash bug - DEV-11158 - trying to collect more data: + if ((sizeS == 0) || (sizeT == 0)) + { + LL_WARNS() << "sculpt bad mesh size " << sizeS << " " << sizeT << LL_ENDL; + } - p[i].set(face->mPositions[idx].getF32ptr()); - p[i].scaleVec(face->mNormalizedScale); //put mesh in original coordinate frame when reconstructing tangents - n[i].set(face->mNormals[idx].getF32ptr()); - n[i].scaleVec(inv_scale); - n[i].normalize(); - tc[i].set(face->mTexCoords[idx]); + sNumMeshPoints -= mMesh.size(); + mMesh.resize(sizeS * sizeT); + sNumMeshPoints += mMesh.size(); - if (idx >= face->mNumVertices) - { - // invalid index - // replace with a valid index to avoid crashes - idx = face->mNumVertices - 1; - face->mIndices[i] = idx; + //generate vertex positions + if (!data_is_empty) + { + sculptGenerateMapVertices(sculpt_width, sculpt_height, sculpt_components, sculpt_data, sculpt_type); - // Needs better logging - LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; - } + // don't test lowest LOD to support legacy content DEV-33670 + if (mDetail > SCULPT_MIN_AREA_DETAIL) + { + F32 area = sculptGetSurfaceArea(); - if (face->mWeights) + mSurfaceArea = area; + + const F32 SCULPT_MAX_AREA = 384.f; + + if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) { - w[i].set(face->mWeights[idx].getF32ptr()); + data_is_empty = TRUE; + visible_placeholder = true; } } } - uint32_t GetNumFaces() - { - return uint32_t(face->mNumIndices / 3); - } - - uint32_t GetNumVerticesOfFace(const uint32_t face_num) - { - return 3; - } - - mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num) - { - F32* v = p[face_num * 3 + vert_num].mV; - return mikk::float3(v); - } - - mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) - { - F32* uv = tc[face_num * 3 + vert_num].mV; - return mikk::float3(uv[0], uv[1], 1.0f); - } - - mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) - { - F32* normal = n[face_num * 3 + vert_num].mV; - return mikk::float3(normal); - } - - void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation) - { - S32 i = face_num * 3 + vert_num; - t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f); - } -}; + if (data_is_empty) + { + if (visible_placeholder) + { + // Object should be visible since there will be nothing else to display + sculptGenerateSpherePlaceholder(); + } + else + { + sculptGenerateEmptyPlaceholder(); + } + } -bool LLVolumeFace::cacheOptimize(bool gen_tangents) -{ //optimize for vertex cache according to Forsyth method: - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - llassert(!mOptimized); - mOptimized = TRUE; - if (gen_tangents && mNormals && mTexCoords) - { // generate mikkt space tangents before cache optimizing since the index buffer may change - // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh - // and is executed on a background thread - MikktData data(this); - mikk::Mikktspace ctx(data); - ctx.genTangSpace(); - //re-weld - meshopt_Stream mos[] = - { - { &data.p[0], sizeof(LLVector3), sizeof(LLVector3) }, - { &data.n[0], sizeof(LLVector3), sizeof(LLVector3) }, - { &data.t[0], sizeof(LLVector4), sizeof(LLVector4) }, - { &data.tc[0], sizeof(LLVector2), sizeof(LLVector2) }, - { data.w.empty() ? nullptr : &data.w[0], sizeof(LLVector4), sizeof(LLVector4) } - }; + for (S32 i = 0; i < (S32)mProfilep->mFaces.size(); i++) + { + mFaceMask |= mProfilep->mFaces[i].mFaceID; + } - std::vector remap; - remap.resize(data.p.size()); + mSculptLevel = sculpt_level; - U32 stream_count = data.w.empty() ? 4 : 5; + // Delete any existing faces so that they get regenerated + mVolumeFaces.clear(); - size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count); + createVolumeFaces(); +} - if (vert_count < 65535 && vert_count != 0) - { - //copy results back into volume - resizeVertices(vert_count); - if (!data.w.empty()) - { - allocateWeights(vert_count); - } - allocateTangents(mNumVertices); - for (int i = 0; i < mNumIndices; ++i) - { - U32 src_idx = i; - U32 dst_idx = remap[i]; - if (dst_idx >= mNumVertices) - { +BOOL LLVolume::isCap(S32 face) +{ + return mProfilep->mFaces[face].mCap; +} + +BOOL LLVolume::isFlat(S32 face) +{ + return mProfilep->mFaces[face].mFlat; +} + + +bool LLVolumeParams::isSculpt() const +{ + return (mSculptType & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_NONE; +} + +bool LLVolumeParams::isMeshSculpt() const +{ + return (mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH; +} + +bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const +{ + return ( (getPathParams() == params.getPathParams()) && + (getProfileParams() == params.getProfileParams()) && + (mSculptID == params.mSculptID) && + (mSculptType == params.mSculptType) ); +} + +bool LLVolumeParams::operator!=(const LLVolumeParams ¶ms) const +{ + return ( (getPathParams() != params.getPathParams()) || + (getProfileParams() != params.getProfileParams()) || + (mSculptID != params.mSculptID) || + (mSculptType != params.mSculptType) ); +} + +bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const +{ + if( getPathParams() != params.getPathParams() ) + { + return getPathParams() < params.getPathParams(); + } + + if (getProfileParams() != params.getProfileParams()) + { + return getProfileParams() < params.getProfileParams(); + } + + if (mSculptID != params.mSculptID) + { + return mSculptID < params.mSculptID; + } + + return mSculptType < params.mSculptType; + + +} + +void LLVolumeParams::copyParams(const LLVolumeParams ¶ms) +{ + mProfileParams.copyParams(params.mProfileParams); + mPathParams.copyParams(params.mPathParams); + mSculptID = params.getSculptID(); + mSculptType = params.getSculptType(); +} + +// Less restricitve approx 0 for volumes +const F32 APPROXIMATELY_ZERO = 0.001f; +bool approx_zero( F32 f, F32 tolerance = APPROXIMATELY_ZERO) +{ + return (f >= -tolerance) && (f <= tolerance); +} + +// return true if in range (or nearly so) +static bool limit_range(F32& v, F32 min, F32 max, F32 tolerance = APPROXIMATELY_ZERO) +{ + F32 min_delta = v - min; + if (min_delta < 0.f) + { + v = min; + if (!approx_zero(min_delta, tolerance)) + return false; + } + F32 max_delta = max - v; + if (max_delta < 0.f) + { + v = max; + if (!approx_zero(max_delta, tolerance)) + return false; + } + return true; +} + +bool LLVolumeParams::setBeginAndEndS(const F32 b, const F32 e) +{ + bool valid = true; + + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + + F32 end = e; + if (end >= .0149f && end < MIN_CUT_DELTA) end = MIN_CUT_DELTA; // eliminate warning for common rounding error + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + + // Now set them. + mProfileParams.setBegin(begin); + mProfileParams.setEnd(end); + + return valid; +} + +bool LLVolumeParams::setBeginAndEndT(const F32 b, const F32 e) +{ + bool valid = true; + + // First, clamp to valid ranges. + F32 begin = b; + valid &= limit_range(begin, 0.f, 1.f - MIN_CUT_DELTA); + + F32 end = e; + valid &= limit_range(end, MIN_CUT_DELTA, 1.f); + + valid &= limit_range(begin, 0.f, end - MIN_CUT_DELTA, .01f); + + // Now set them. + mPathParams.setBegin(begin); + mPathParams.setEnd(end); + + return valid; +} + +bool LLVolumeParams::setHollow(const F32 h) +{ + // Validate the hollow based on path and profile. + U8 profile = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + U8 hole_type = mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK; + + F32 max_hollow = HOLLOW_MAX; + + // Only square holes have trouble. + if (LL_PCODE_HOLE_SQUARE == hole_type) + { + switch(profile) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + case LL_PCODE_PROFILE_EQUALTRI: + max_hollow = HOLLOW_MAX_SQUARE; + } + } + + F32 hollow = h; + bool valid = limit_range(hollow, HOLLOW_MIN, max_hollow); + mProfileParams.setHollow(hollow); + + return valid; +} + +bool LLVolumeParams::setTwistBegin(const F32 b) +{ + F32 twist_begin = b; + bool valid = limit_range(twist_begin, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistBegin(twist_begin); + return valid; +} + +bool LLVolumeParams::setTwistEnd(const F32 e) +{ + F32 twist_end = e; + bool valid = limit_range(twist_end, TWIST_MIN, TWIST_MAX); + mPathParams.setTwistEnd(twist_end); + return valid; +} + +bool LLVolumeParams::setRatio(const F32 x, const F32 y) +{ + F32 min_x = RATIO_MIN; + F32 max_x = RATIO_MAX; + F32 min_y = RATIO_MIN; + F32 max_y = RATIO_MAX; + // If this is a circular path (and not a sphere) then 'ratio' is actually hole size. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PATH_CIRCLE == path_type && + LL_PCODE_PROFILE_CIRCLE_HALF != profile_type) + { + // Holes are more restricted... + min_x = HOLE_X_MIN; + max_x = HOLE_X_MAX; + min_y = HOLE_Y_MIN; + max_y = HOLE_Y_MAX; + } + + F32 ratio_x = x; + bool valid = limit_range(ratio_x, min_x, max_x); + F32 ratio_y = y; + valid &= limit_range(ratio_y, min_y, max_y); + + mPathParams.setScale(ratio_x, ratio_y); + + return valid; +} + +bool LLVolumeParams::setShear(const F32 x, const F32 y) +{ + F32 shear_x = x; + bool valid = limit_range(shear_x, SHEAR_MIN, SHEAR_MAX); + F32 shear_y = y; + valid &= limit_range(shear_y, SHEAR_MIN, SHEAR_MAX); + mPathParams.setShear(shear_x, shear_y); + return valid; +} + +bool LLVolumeParams::setTaperX(const F32 v) +{ + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperX(taper); + return valid; +} + +bool LLVolumeParams::setTaperY(const F32 v) +{ + F32 taper = v; + bool valid = limit_range(taper, TAPER_MIN, TAPER_MAX); + mPathParams.setTaperY(taper); + return valid; +} + +bool LLVolumeParams::setRevolutions(const F32 r) +{ + F32 revolutions = r; + bool valid = limit_range(revolutions, REV_MIN, REV_MAX); + mPathParams.setRevolutions(revolutions); + return valid; +} + +bool LLVolumeParams::setRadiusOffset(const F32 offset) +{ + bool valid = true; + + // If this is a sphere, just set it to 0 and get out. + U8 path_type = mPathParams.getCurveType(); + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type || + LL_PCODE_PATH_CIRCLE != path_type ) + { + mPathParams.setRadiusOffset(0.f); + return true; + } + + // Limit radius offset, based on taper and hole size y. + F32 radius_offset = offset; + F32 taper_y = getTaperY(); + F32 radius_mag = fabs(radius_offset); + F32 hole_y_mag = fabs(getRatioY()); + F32 taper_y_mag = fabs(taper_y); + // Check to see if the taper effects us. + if ( (radius_offset > 0.f && taper_y < 0.f) || + (radius_offset < 0.f && taper_y > 0.f) ) + { + // The taper does not help increase the radius offset range. + taper_y_mag = 0.f; + } + F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); + + // Enforce the maximum magnitude. + F32 delta = max_radius_mag - radius_mag; + if (delta < 0.f) + { + // Check radius offset sign. + if (radius_offset < 0.f) + { + radius_offset = -max_radius_mag; + } + else + { + radius_offset = max_radius_mag; + } + valid = approx_zero(delta, .1f); + } + + mPathParams.setRadiusOffset(radius_offset); + return valid; +} + +bool LLVolumeParams::setSkew(const F32 skew_value) +{ + bool valid = true; + + // Check the skew value against the revolutions. + F32 skew = llclamp(skew_value, SKEW_MIN, SKEW_MAX); + F32 skew_mag = fabs(skew); + F32 revolutions = getRevolutions(); + F32 scale_x = getRatioX(); + F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); + // Discontinuity; A revolution of 1 allows skews below 0.5. + if ( fabs(revolutions - 1.0f) < 0.001) + min_skew_mag = 0.0f; + + // Clip skew. + F32 delta = skew_mag - min_skew_mag; + if (delta < 0.f) + { + // Check skew sign. + if (skew < 0.0f) + { + skew = -min_skew_mag; + } + else + { + skew = min_skew_mag; + } + valid = approx_zero(delta, .01f); + } + + mPathParams.setSkew(skew); + return valid; +} + +bool LLVolumeParams::setSculptID(const LLUUID sculpt_id, U8 sculpt_type) +{ + mSculptID = sculpt_id; + mSculptType = sculpt_type; + return true; +} + +bool LLVolumeParams::setType(U8 profile, U8 path) +{ + bool result = true; + // First, check profile and path for validity. + U8 profile_type = profile & LL_PCODE_PROFILE_MASK; + U8 hole_type = (profile & LL_PCODE_HOLE_MASK) >> 4; + U8 path_type = path >> 4; + + if (profile_type > LL_PCODE_PROFILE_MAX) + { + // Bad profile. Make it square. + profile = LL_PCODE_PROFILE_SQUARE; + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad profile type (" << profile_type + << ") to be LL_PCODE_PROFILE_SQUARE" << LL_ENDL; + } + else if (hole_type > LL_PCODE_HOLE_MAX) + { + // Bad hole. Make it the same. + profile = profile_type; + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad hole type (" << hole_type + << ") to be LL_PCODE_HOLE_SAME" << LL_ENDL; + } + + if (path_type < LL_PCODE_PATH_MIN || + path_type > LL_PCODE_PATH_MAX) + { + // Bad path. Make it linear. + result = false; + LL_WARNS() << "LLVolumeParams::setType changing bad path (" << path + << ") to be LL_PCODE_PATH_LINE" << LL_ENDL; + path = LL_PCODE_PATH_LINE; + } + + mProfileParams.setCurveType(profile); + mPathParams.setCurveType(path); + return result; +} + +// static +bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, + U8 path_curve, F32 path_begin, F32 path_end, + F32 scx, F32 scy, F32 shx, F32 shy, + F32 twistend, F32 twistbegin, F32 radiusoffset, + F32 tx, F32 ty, F32 revolutions, F32 skew) +{ + LLVolumeParams test_params; + if (!test_params.setType (prof_curve, path_curve)) + { + return false; + } + if (!test_params.setBeginAndEndS (prof_begin, prof_end)) + { + return false; + } + if (!test_params.setBeginAndEndT (path_begin, path_end)) + { + return false; + } + if (!test_params.setHollow (hollow)) + { + return false; + } + if (!test_params.setTwistBegin (twistbegin)) + { + return false; + } + if (!test_params.setTwistEnd (twistend)) + { + return false; + } + if (!test_params.setRatio (scx, scy)) + { + return false; + } + if (!test_params.setShear (shx, shy)) + { + return false; + } + if (!test_params.setTaper (tx, ty)) + { + return false; + } + if (!test_params.setRevolutions (revolutions)) + { + return false; + } + if (!test_params.setRadiusOffset (radiusoffset)) + { + return false; + } + if (!test_params.setSkew (skew)) + { + return false; + } + return true; +} + +void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts) +{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the + //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + F32 detail[] = {1.f, 1.5f, 2.5f, 4.f}; + for (S32 i = 0; i < 4; i++) + { + S32 count = 0; + S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]); + S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]); + + count = (profile_points-1)*2*(path_points-1); + count += profile_points*2; + + counts[i] = count; + } +} + + +S32 LLVolume::getNumTriangles(S32* vcount) const +{ + U32 triangle_count = 0; + U32 vertex_count = 0; + + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = getVolumeFace(i); + triangle_count += face.mNumIndices/3; + + vertex_count += face.mNumVertices; + } + + + if (vcount) + { + *vcount = vertex_count; + } + + return triangle_count; +} + + +//----------------------------------------------------------------------------- +// generateSilhouetteVertices() +//----------------------------------------------------------------------------- +void LLVolume::generateSilhouetteVertices(std::vector &vertices, + std::vector &normals, + const LLVector3& obj_cam_vec_in, + const LLMatrix4& mat_in, + const LLMatrix3& norm_mat_in, + S32 face_mask) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LLMatrix4a mat; + mat.loadu(mat_in); + + LLMatrix4a norm_mat; + norm_mat.loadu(norm_mat_in); + + LLVector4a obj_cam_vec; + obj_cam_vec.load3(obj_cam_vec_in.mV); + + vertices.clear(); + normals.clear(); + + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + return; + } + + S32 cur_index = 0; + //for each face + for (face_list_t::iterator iter = mVolumeFaces.begin(); + iter != mVolumeFaces.end(); ++iter) + { + LLVolumeFace& face = *iter; + + if (!(face_mask & (0x1 << cur_index++)) || + face.mNumIndices == 0 || face.mEdge.empty()) + { + continue; + } + + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) + { + LLVector4a* v = (LLVector4a*)face.mPositions; + LLVector4a* n = (LLVector4a*)face.mNormals; + + for (U32 j = 0; j < face.mNumIndices / 3; j++) + { + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j * 3 + k]; + + if (index == -1) + { + // silhouette edge, currently only cubes, so no other conditions + + S32 v1 = face.mIndices[j * 3 + k]; + S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } + + } + else + { + + //============================================== + //DEBUG draw edge map instead of silhouette edge + //============================================== + +#if DEBUG_SILHOUETTE_EDGE_MAP + + //for each triangle + U32 tri_count = face.mNumIndices / 3; + for (U32 j = 0; j < tri_count; j++) { + //get vertices + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + //get current face center + LLVector3 cCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //for each edge + for (S32 k = 0; k < 3; k++) { + S32 nIndex = face.mEdge[j*3+k]; + if (nIndex <= -1) { + continue; + } + + if (nIndex >= (S32)tri_count) { + continue; + } + //get neighbor vertices + v1 = face.mIndices[nIndex*3+0]; + v2 = face.mIndices[nIndex*3+1]; + v3 = face.mIndices[nIndex*3+2]; + + //get neighbor face center + LLVector3 nCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; + + //draw line + vertices.push_back(cCenter); + vertices.push_back(nCenter); + normals.push_back(LLVector3(1,1,1)); + normals.push_back(LLVector3(1,1,1)); + segments.push_back(vertices.size()); + } + } + + continue; + + //============================================== + //DEBUG + //============================================== + + //============================================== + //DEBUG draw normals instead of silhouette edge + //============================================== +#elif DEBUG_SILHOUETTE_NORMALS + + //for each vertex + for (U32 j = 0; j < face.mNumVertices; j++) { + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); +#if DEBUG_SILHOUETTE_BINORMALS + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mTangent*0.1f); + normals.push_back(LLVector3(0,0,1)); + normals.push_back(LLVector3(0,0,1)); + segments.push_back(vertices.size()); +#endif + } + + continue; +#else + //============================================== + //DEBUG + //============================================== + + static const U8 AWAY = 0x01, + TOWARDS = 0x02; + + //for each triangle + std::vector fFacing; + vector_append(fFacing, face.mNumIndices/3); + + LLVector4a* v = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + //approximate normal + S32 v1 = face.mIndices[j*3+0]; + S32 v2 = face.mIndices[j*3+1]; + S32 v3 = face.mIndices[j*3+2]; + + LLVector4a c1,c2; + c1.setSub(v[v1], v[v2]); + c2.setSub(v[v2], v[v3]); + + LLVector4a norm; + + norm.setCross3(c1, c2); + + if (norm.dot3(norm) < 0.00000001f) + { + fFacing[j] = AWAY | TOWARDS; + } + else + { + //get view vector + LLVector4a view; + view.setSub(obj_cam_vec, v[v1]); + bool away = view.dot3(norm) > 0.0f; + if (away) + { + fFacing[j] = AWAY; + } + else + { + fFacing[j] = TOWARDS; + } + } + } + + //for each triangle + for (U32 j = 0; j < face.mNumIndices/3; j++) + { + if (fFacing[j] == (AWAY | TOWARDS)) + { //this is a degenerate triangle + //take neighbor facing (degenerate faces get facing of one of their neighbors) + // *FIX IF NEEDED: this does not deal with neighboring degenerate faces + for (S32 k = 0; k < 3; k++) + { + S32 index = face.mEdge[j*3+k]; + if (index != -1) + { + fFacing[j] = fFacing[index]; + break; + } + } + continue; //skip degenerate face + } + + //for each edge + for (S32 k = 0; k < 3; k++) { + S32 index = face.mEdge[j*3+k]; + if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) { + //our neighbor is degenerate, make him face our direction + fFacing[face.mEdge[j*3+k]] = fFacing[j]; + continue; + } + + if (index == -1 || //edge has no neighbor, MUST be a silhouette edge + (fFacing[index] & fFacing[j]) == 0) { //we found a silhouette edge + + S32 v1 = face.mIndices[j*3+k]; + S32 v2 = face.mIndices[j*3+((k+1)%3)]; + + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v1], t); + + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + } + } + } +#endif + } + } +} + +S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent_out) +{ + S32 hit_face = -1; + + S32 start_face; + S32 end_face; + + if (face == -1) // ALL_SIDES + { + start_face = 0; + end_face = getNumVolumeFaces() - 1; + } + else + { + start_face = face; + end_face = face; + } + + LLVector4a dir; + dir.setSub(end, start); + + F32 closest_t = 2.f; // must be larger than 1 + + end_face = llmin(end_face, getNumVolumeFaces()-1); + + for (S32 i = start_face; i <= end_face; i++) + { + LLVolumeFace &face = mVolumeFaces[i]; + + LLVector4a box_center; + box_center.setAdd(face.mExtents[0], face.mExtents[1]); + box_center.mul(0.5f); + + LLVector4a box_size; + box_size.setSub(face.mExtents[1], face.mExtents[0]); + + if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) + { + if (tangent_out != NULL) // if the caller wants tangents, we may need to generate them + { + genTangents(i); + } + + if (isUnique()) + { //don't bother with an octree for flexi volumes + U32 tri_count = face.mNumIndices/3; + + for (U32 j = 0; j < tri_count; ++j) + { + U16 idx0 = face.mIndices[j*3+0]; + U16 idx1 = face.mIndices[j*3+1]; + U16 idx2 = face.mIndices[j*3+2]; + + const LLVector4a& v0 = face.mPositions[idx0]; + const LLVector4a& v1 = face.mPositions[idx1]; + const LLVector4a& v2 = face.mPositions[idx2]; + + F32 a,b,t; + + if (LLTriangleRayIntersect(v0, v1, v2, + start, dir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < closest_t)) // and this hit is closer + { + closest_t = t; + hit_face = i; + + if (intersection != NULL) + { + LLVector4a intersect = dir; + intersect.mul(closest_t); + intersect.add(start); + *intersection = intersect; + } + + + if (tex_coord != NULL) + { + LLVector2* tc = (LLVector2*) face.mTexCoords; + *tex_coord = ((1.f - a - b) * tc[idx0] + + a * tc[idx1] + + b * tc[idx2]); + + } + + if (normal!= NULL) + { + LLVector4a* norm = face.mNormals; + + LLVector4a n1,n2,n3; + n1 = norm[idx0]; + n1.mul(1.f-a-b); + + n2 = norm[idx1]; + n2.mul(a); + + n3 = norm[idx2]; + n3.mul(b); + + n1.add(n2); + n1.add(n3); + + *normal = n1; + } + + if (tangent_out != NULL) + { + LLVector4a* tangents = face.mTangents; + + LLVector4a t1,t2,t3; + t1 = tangents[idx0]; + t1.mul(1.f-a-b); + + t2 = tangents[idx1]; + t2.mul(a); + + t3 = tangents[idx2]; + t3.mul(b); + + t1.add(t2); + t1.add(t3); + + *tangent_out = t1; + } + } + } + } + } + else + { + if (!face.getOctree()) + { + face.createOctree(); + } + + LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, tangent_out); + intersect.traverse(face.getOctree()); + if (intersect.mHitFace) + { + hit_face = i; + } + } + } + } + + + return hit_face; +} + +class LLVertexIndexPair +{ +public: + LLVertexIndexPair(const LLVector3 &vertex, const S32 index); + + LLVector3 mVertex; + S32 mIndex; +}; + +LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index) +{ + mVertex = vertex; + mIndex = index; +} + +const F32 VERTEX_SLOP = 0.00001f; + +struct lessVertex +{ + bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b) + { + const F32 slop = VERTEX_SLOP; + + if (a->mVertex.mV[0] + slop < b->mVertex.mV[0]) + { + return TRUE; + } + else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0]) + { + return FALSE; + } + + if (a->mVertex.mV[1] + slop < b->mVertex.mV[1]) + { + return TRUE; + } + else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1]) + { + return FALSE; + } + + if (a->mVertex.mV[2] + slop < b->mVertex.mV[2]) + { + return TRUE; + } + else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2]) + { + return FALSE; + } + + return FALSE; + } +}; + +struct lessTriangle +{ + bool operator()(const S32 *a, const S32 *b) + { + if (*a < *b) + { + return TRUE; + } + else if (*a > *b) + { + return FALSE; + } + + if (*(a+1) < *(b+1)) + { + return TRUE; + } + else if (*(a+1) > *(b+1)) + { + return FALSE; + } + + if (*(a+2) < *(b+2)) + { + return TRUE; + } + else if (*(a+2) > *(b+2)) + { + return FALSE; + } + + return FALSE; + } +}; + +BOOL equalTriangle(const S32 *a, const S32 *b) +{ + if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2))) + { + return TRUE; + } + return FALSE; +} + +BOOL LLVolumeParams::importFile(LLFILE *fp) +{ + //LL_INFOS() << "importing volume" << LL_ENDL; + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */ + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importFile(fp); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importFile(fp); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; + } + } + + return TRUE; +} + +BOOL LLVolumeParams::exportFile(LLFILE *fp) const +{ + fprintf(fp,"\tshape 0\n"); + fprintf(fp,"\t{\n"); + mPathParams.exportFile(fp); + mProfileParams.exportFile(fp); + fprintf(fp, "\t}\n"); + return TRUE; +} + + +BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream) +{ + //LL_INFOS() << "importing volume" << LL_ENDL; + const S32 BUFSIZE = 16384; + // *NOTE: changing the size or type of this buffer will require + // changing the sscanf below. + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[256]; /* Flawfinder: ignore */ + keyword[0] = 0; + + while (input_stream.good()) + { + input_stream.getline(buffer, BUFSIZE); + sscanf(buffer, " %255s", keyword); + if (!strcmp("{", keyword)) + { + continue; + } + if (!strcmp("}",keyword)) + { + break; + } + else if (!strcmp("profile", keyword)) + { + mProfileParams.importLegacyStream(input_stream); + } + else if (!strcmp("path",keyword)) + { + mPathParams.importLegacyStream(input_stream); + } + else + { + LL_WARNS() << "unknown keyword " << keyword << " in volume import" << LL_ENDL; + } + } + + return TRUE; +} + +BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const +{ + output_stream <<"\tshape 0\n"; + output_stream <<"\t{\n"; + mPathParams.exportLegacyStream(output_stream); + mProfileParams.exportLegacyStream(output_stream); + output_stream << "\t}\n"; + return TRUE; +} + +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; +} + +LLSD LLVolumeParams::asLLSD() const +{ + LLSD sd = LLSD(); + sd["path"] = mPathParams; + sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + + return sd; +} + +bool LLVolumeParams::fromLLSD(LLSD& sd) +{ + mPathParams.fromLLSD(sd["path"]); + mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + + return true; +} + +void LLVolumeParams::reduceS(F32 begin, F32 end) +{ + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mProfileParams.getBegin(); + F32 b = mProfileParams.getEnd(); + mProfileParams.setBegin(a + begin * (b - a)); + mProfileParams.setEnd(a + end * (b - a)); +} + +void LLVolumeParams::reduceT(F32 begin, F32 end) +{ + begin = llclampf(begin); + end = llclampf(end); + if (begin > end) + { + F32 temp = begin; + begin = end; + end = temp; + } + F32 a = mPathParams.getBegin(); + F32 b = mPathParams.getEnd(); + mPathParams.setBegin(a + begin * (b - a)); + mPathParams.setEnd(a + end * (b - a)); +} + +const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity +const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity + +// returns TRUE if the shape can be approximated with a convex shape +// for collison purposes +BOOL LLVolumeParams::isConvex() const +{ + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return FALSE; + } + + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); + F32 hollow = mProfileParams.getHollow(); + + U8 path_type = mPathParams.getCurveType(); + if ( path_length > MIN_CONCAVE_PATH_WEDGE + && ( mPathParams.getTwist() != mPathParams.getTwistBegin() + || (hollow > 0.f + && LL_PCODE_PATH_LINE != path_type) ) ) + { + // twist along a "not too short" path is concave + return FALSE; + } + + F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin(); + BOOL same_hole = hollow == 0.f + || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME; + + F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE; + U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK; + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // it is a sphere and spheres get twice the minimum profile wedge + min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE; + } + + BOOL convex_profile = ( ( profile_length == 1.f + || profile_length <= 0.5f ) + && hollow == 0.f ) // trivially convex + || ( profile_length <= min_profile_wedge + && same_hole ); // effectvely convex (even when hollow) + + if (!convex_profile) + { + // profile is concave + return FALSE; + } + + if ( LL_PCODE_PATH_LINE == path_type ) + { + // straight paths with convex profile + return TRUE; + } + + BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f); + if (concave_path) + { + return FALSE; + } + + // we're left with spheres, toroids and tubes + if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type ) + { + // at this stage all spheres must be convex + return TRUE; + } + + // it's a toroid or tube + if ( path_length <= MIN_CONCAVE_PATH_WEDGE ) + { + // effectively convex + return TRUE; + } + + return FALSE; +} + +// debug +void LLVolumeParams::setCube() +{ + mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE); + mProfileParams.setBegin(0.f); + mProfileParams.setEnd(1.f); + mProfileParams.setHollow(0.f); + + mPathParams.setBegin(0.f); + mPathParams.setEnd(1.f); + mPathParams.setScale(1.f, 1.f); + mPathParams.setShear(0.f, 0.f); + mPathParams.setCurveType(LL_PCODE_PATH_LINE); + mPathParams.setTwistBegin(0.f); + mPathParams.setTwistEnd(0.f); + mPathParams.setRadiusOffset(0.f); + mPathParams.setTaper(0.f, 0.f); + mPathParams.setRevolutions(0.f); + mPathParams.setSkew(0.f); +} + +LLFaceID LLVolume::generateFaceMask() +{ + LLFaceID new_mask = 0x0000; + + switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_CIRCLE: + case LL_PCODE_PROFILE_CIRCLE_HALF: + new_mask |= LL_FACE_OUTER_SIDE_0; + break; + case LL_PCODE_PROFILE_SQUARE: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_EQUALTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + { + for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++) + { + new_mask |= LL_FACE_OUTER_SIDE_0 << side; + } + } + break; + default: + LL_ERRS() << "Unknown profile!" << LL_ENDL; + break; + } + + // handle hollow objects + if (mParams.getProfileParams().getHollow() > 0) + { + new_mask |= LL_FACE_INNER_SIDE; + } + + // handle open profile curves + if (mProfilep->isOpen()) + { + new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END; + } + + // handle open path curves + if (mPathp->isOpen()) + { + new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END; + } + + return new_mask; +} + +BOOL LLVolume::isFaceMaskValid(LLFaceID face_mask) +{ + LLFaceID test_mask = 0; + for(S32 i = 0; i < getNumFaces(); i++) + { + test_mask |= mProfilep->mFaces[i].mFaceID; + } + + return test_mask == face_mask; +} + +BOOL LLVolume::isConvex() const +{ + // mParams.isConvex() may return FALSE even though the final + // geometry is actually convex due to LOD approximations. + // TODO -- provide LLPath and LLProfile with isConvex() methods + // that correctly determine convexity. -- Leviathan + return mParams.isConvex(); +} + + +std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params) +{ + s << "{type=" << (U32) profile_params.mCurveType; + s << ", begin=" << profile_params.mBegin; + s << ", end=" << profile_params.mEnd; + s << ", hollow=" << profile_params.mHollow; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params) +{ + s << "{type=" << (U32) path_params.mCurveType; + s << ", begin=" << path_params.mBegin; + s << ", end=" << path_params.mEnd; + s << ", twist=" << path_params.mTwistEnd; + s << ", scale=" << path_params.mScale; + s << ", shear=" << path_params.mShear; + s << ", twist_begin=" << path_params.mTwistBegin; + s << ", radius_offset=" << path_params.mRadiusOffset; + s << ", taper=" << path_params.mTaper; + s << ", revolutions=" << path_params.mRevolutions; + s << ", skew=" << path_params.mSkew; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params) +{ + s << "{profileparams = " << volume_params.mProfileParams; + s << ", pathparams = " << volume_params.mPathParams; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLProfile &profile) +{ + s << " {open=" << (U32) profile.mOpen; + s << ", dirty=" << profile.mDirty; + s << ", totalout=" << profile.mTotalOut; + s << ", total=" << profile.mTotal; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLPath &path) +{ + s << "{open=" << (U32) path.mOpen; + s << ", dirty=" << path.mDirty; + s << ", step=" << path.mStep; + s << ", total=" << path.mTotal; + s << "}"; + return s; +} + +std::ostream& operator<<(std::ostream &s, const LLVolume &volume) +{ + s << "{params = " << volume.getParams(); + s << ", path = " << *volume.mPathp; + s << ", profile = " << *volume.mProfilep; + s << "}"; + return s; +} + + +std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) +{ + s << "{params = " << volumep->getParams(); + s << ", path = " << *(volumep->mPathp); + s << ", profile = " << *(volumep->mProfilep); + s << "}"; + return s; +} + +LLVolumeFace::LLVolumeFace() : + mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumAllocatedVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mTangents(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), + mJointIndices(NULL), +#endif + mWeightsScrubbed(FALSE), + mOctree(NULL), + mOctreeTriangles(NULL), + mOptimized(FALSE) +{ + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mExtents[0].splat(-0.5f); + mExtents[1].splat(0.5f); + mCenter = mExtents+2; +} + +LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) +: mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumAllocatedVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mTangents(NULL), + mTexCoords(NULL), + mIndices(NULL), + mWeights(NULL), +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + mJustWeights(NULL), + mJointIndices(NULL), +#endif + mWeightsScrubbed(FALSE), + mOctree(NULL), + mOctreeTriangles(NULL) +{ + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mCenter = mExtents+2; + *this = src; +} + +LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) +{ + if (&src == this) + { //self assignment, do nothing + return *this; + } + + mID = src.mID; + mTypeMask = src.mTypeMask; + mBeginS = src.mBeginS; + mBeginT = src.mBeginT; + mNumS = src.mNumS; + mNumT = src.mNumT; + + mExtents[0] = src.mExtents[0]; + mExtents[1] = src.mExtents[1]; + *mCenter = *src.mCenter; + + mNumVertices = 0; + mNumIndices = 0; + + freeData(); + + resizeVertices(src.mNumVertices); + resizeIndices(src.mNumIndices); + + if (mNumVertices) + { + S32 vert_size = mNumVertices*sizeof(LLVector4a); + S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); + + if (src.mNormals) + { + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); + } + + if(src.mTexCoords) + { + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + } + + if (src.mTangents) + { + allocateTangents(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size); + } + else + { + ll_aligned_free_16(mTangents); + mTangents = NULL; + } + + if (src.mWeights) + { + llassert(!mWeights); // don't orphan an old alloc here accidentally + allocateWeights(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); + mWeightsScrubbed = src.mWeightsScrubbed; + } + else + { + ll_aligned_free_16(mWeights); + mWeights = NULL; + mWeightsScrubbed = FALSE; + } + + #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + if (src.mJointIndices) + { + llassert(!mJointIndices); // don't orphan an old alloc here accidentally + allocateJointIndices(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4); + } + else*/ + { + ll_aligned_free_16(mJointIndices); + mJointIndices = NULL; + } + #endif + + } + + if (mNumIndices) + { + S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); + } + else + { + ll_aligned_free_16(mIndices); + mIndices = NULL; + } + + mOptimized = src.mOptimized; + mNormalizedScale = src.mNormalizedScale; + + //delete + return *this; +} + +LLVolumeFace::~LLVolumeFace() +{ + ll_aligned_free_16(mExtents); + mExtents = NULL; + mCenter = NULL; + + freeData(); +} + +void LLVolumeFace::freeData() +{ + ll_aligned_free<64>(mPositions); + mPositions = NULL; + + //normals and texture coordinates are part of the same buffer as mPositions, do not free them separately + mNormals = NULL; + mTexCoords = NULL; + + ll_aligned_free_16(mIndices); + mIndices = NULL; + ll_aligned_free_16(mTangents); + mTangents = NULL; + ll_aligned_free_16(mWeights); + mWeights = NULL; + +#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS + ll_aligned_free_16(mJointIndices); + mJointIndices = NULL; + ll_aligned_free_16(mJustWeights); + mJustWeights = NULL; +#endif + + destroyOctree(); +} + +BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + //tree for this face is no longer valid + destroyOctree(); + + LL_CHECK_MEMORY + BOOL ret = FALSE ; + if (mTypeMask & CAP_MASK) + { + ret = createCap(volume, partial_build); + LL_CHECK_MEMORY + } + else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK)) + { + ret = createSide(volume, partial_build); + LL_CHECK_MEMORY + } + else + { + LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL; + } + + return ret ; +} + +void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) +{ + cv.setPosition(mPositions[index]); + if (mNormals) + { + cv.setNormal(mNormals[index]); + } + else + { + cv.getNormal().clear(); + } + + if (mTexCoords) + { + cv.mTexCoord = mTexCoords[index]; + } + else + { + cv.mTexCoord.clear(); + } +} + +bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const +{ + return getPosition().equals3(rhs.getPosition()) && + mTexCoord == rhs.mTexCoord && + getNormal().equals3(rhs.getNormal()); +} + +bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const +{ + if (a.mV[0] != b.mV[0]) + { + return a.mV[0] < b.mV[0]; + } + + if (a.mV[1] != b.mV[1]) + { + return a.mV[1] < b.mV[1]; + } + + return a.mV[2] < b.mV[2]; +} + +void LLVolumeFace::remap() +{ + // Generate a remap buffer + std::vector remap(mNumVertices); + S32 remap_vertices_count = LLMeshOptimizer::generateRemapMultiU16(&remap[0], + mIndices, + mNumIndices, + mPositions, + mNormals, + mTexCoords, + mNumVertices); + + // Allocate new buffers + S32 size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF; + U16* remap_indices = (U16*)ll_aligned_malloc_16(size); + + S32 tc_bytes_size = ((remap_vertices_count * sizeof(LLVector2)) + 0xF) & ~0xF; + LLVector4a* remap_positions = (LLVector4a*)ll_aligned_malloc<64>(sizeof(LLVector4a) * 2 * remap_vertices_count + tc_bytes_size); + LLVector4a* remap_normals = remap_positions + remap_vertices_count; + LLVector2* remap_tex_coords = (LLVector2*)(remap_normals + remap_vertices_count); + + // Fill the buffers + LLMeshOptimizer::remapIndexBufferU16(remap_indices, mIndices, mNumIndices, &remap[0]); + LLMeshOptimizer::remapPositionsBuffer(remap_positions, mPositions, mNumVertices, &remap[0]); + LLMeshOptimizer::remapNormalsBuffer(remap_normals, mNormals, mNumVertices, &remap[0]); + LLMeshOptimizer::remapUVBuffer(remap_tex_coords, mTexCoords, mNumVertices, &remap[0]); + + // Free unused buffers + ll_aligned_free_16(mIndices); + ll_aligned_free<64>(mPositions); + + // Tangets are now invalid + ll_aligned_free_16(mTangents); + mTangents = NULL; + + // Assign new values + mIndices = remap_indices; + mPositions = remap_positions; + mNormals = remap_normals; + mTexCoords = remap_tex_coords; + mNumVertices = remap_vertices_count; + mNumAllocatedVertices = remap_vertices_count; +} + +void LLVolumeFace::optimize(F32 angle_cutoff) +{ + LLVolumeFace new_face; + + //map of points to vector of vertices at that point + std::map > point_map; + + LLVector4a range; + range.setSub(mExtents[1],mExtents[0]); + + //remove redundant vertices + for (U32 i = 0; i < mNumIndices; ++i) + { + U16 index = mIndices[i]; + + if (index >= mNumVertices) + { + // invalid index + // replace with a valid index to avoid crashes + index = mNumVertices - 1; + mIndices[i] = index; + + // Needs better logging + LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; + } + + LLVolumeFace::VertexData cv; + getVertexData(index, cv); + + BOOL found = FALSE; + + LLVector4a pos; + pos.setSub(mPositions[index], mExtents[0]); + pos.div(range); + + U64 pos64 = 0; + + pos64 = (U16) (pos[0]*65535); + pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); + pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); + + std::map >::iterator point_iter = point_map.find(pos64); + + if (point_iter != point_map.end()) + { //duplicate point might exist + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + LLVolumeFace::VertexData& tv = (point_iter->second)[j]; + if (tv.compareNormal(cv, angle_cutoff)) + { + found = TRUE; + new_face.pushIndex((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + new_face.pushVertex(cv); + U16 index = (U16) new_face.mNumVertices-1; + new_face.pushIndex(index); + + VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos64].push_back(d); + } + } + } + + + if (angle_cutoff > 1.f && !mNormals) + { + // Now alloc'd with positions + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!mTexCoords) + { + // Now alloc'd with positions + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + // Only swap data if we've actually optimized the mesh + // + if (new_face.mNumVertices <= mNumVertices) + { + llassert(new_face.mNumIndices == mNumIndices); + swapData(new_face); + } + +} + +class LLVCacheTriangleData; + +class LLVCacheVertexData +{ +public: + S32 mIdx; + S32 mCacheTag; + F64 mScore; + U32 mActiveTriangles; + std::vector mTriangles; + + LLVCacheVertexData() + { + mCacheTag = -1; + mScore = 0.0; + mActiveTriangles = 0; + mIdx = -1; + } +}; + +class LLVCacheTriangleData +{ +public: + bool mActive; + F64 mScore; + LLVCacheVertexData* mVertex[3]; + + LLVCacheTriangleData() + { + mActive = true; + mScore = 0.0; + mVertex[0] = mVertex[1] = mVertex[2] = NULL; + } + + void complete() + { + mActive = false; + for (S32 i = 0; i < 3; ++i) + { + if (mVertex[i]) + { + llassert(mVertex[i]->mActiveTriangles > 0); + mVertex[i]->mActiveTriangles--; + } + } + } + + bool operator<(const LLVCacheTriangleData& rhs) const + { //highest score first + return rhs.mScore < mScore; + } +}; + +const F64 FindVertexScore_CacheDecayPower = 1.5; +const F64 FindVertexScore_LastTriScore = 0.75; +const F64 FindVertexScore_ValenceBoostScale = 2.0; +const F64 FindVertexScore_ValenceBoostPower = 0.5; +const U32 MaxSizeVertexCache = 32; +const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3); + +F64 find_vertex_score(LLVCacheVertexData& data) +{ + F64 score = -1.0; + + score = 0.0; + + S32 cache_idx = data.mCacheTag; + + if (cache_idx < 0) + { + //not in cache + } + else + { + if (cache_idx < 3) + { //vertex was in the last triangle + score = FindVertexScore_LastTriScore; + } + else + { //more points for being higher in the cache + score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); + score = pow(score, FindVertexScore_CacheDecayPower); + } + } + + //bonus points for having low valence + F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + score += FindVertexScore_ValenceBoostScale * valence_boost; + + return score; +} + +class LLVCacheFIFO +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache]; + U32 mMisses; + + LLVCacheFIFO() + { + mMisses = 0; + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { + mCache[i] = NULL; + } + } + + void addVertex(LLVCacheVertexData* data) + { + if (data->mCacheTag == -1) + { + mMisses++; + + S32 end = MaxSizeVertexCache-1; + + if (mCache[end]) + { + mCache[end]->mCacheTag = -1; + } + + for (S32 i = end; i > 0; --i) + { + mCache[i] = mCache[i-1]; + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + data->mCacheTag = 0; + } + } +}; + +class LLVCacheLRU +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; + + LLVCacheTriangleData* mBestTriangle; + + U32 mMisses; + + LLVCacheLRU() + { + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + mCache[i] = NULL; + } + + mBestTriangle = NULL; + mMisses = 0; + } + + void addVertex(LLVCacheVertexData* data) + { + S32 end = MaxSizeVertexCache+2; + if (data->mCacheTag != -1) + { //just moving a vertex to the front of the cache + end = data->mCacheTag; + } + else + { + mMisses++; + if (mCache[end]) + { //adding a new vertex, vertex at end of cache falls off + mCache[end]->mCacheTag = -1; + } + } + + for (S32 i = end; i > 0; --i) + { //adjust cache pointers and tags + mCache[i] = mCache[i-1]; + + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + mCache[0]->mCacheTag = 0; + } + + void addTriangle(LLVCacheTriangleData* data) + { + addVertex(data->mVertex[0]); + addVertex(data->mVertex[1]); + addVertex(data->mVertex[2]); + } + + void updateScores() + { + LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache; + LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3; + + while(data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter++; + //trailing 3 vertices aren't actually in the cache for scoring purposes + if (data) + { + data->mCacheTag = -1; + } + } + + data_iter = mCache; + end_data = mCache+MaxSizeVertexCache; + + while (data_iter != end_data) + { //update scores of vertices in cache + LLVCacheVertexData* data = *data_iter++; + if (data) + { + data->mScore = find_vertex_score(*data); + } + } + + mBestTriangle = NULL; + //update triangle scores + data_iter = mCache; + end_data = mCache+MaxSizeVertexCache+3; + + while (data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter++; + if (data) + { + for (std::vector::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter) + { + LLVCacheTriangleData* tri = *iter; + if (tri->mActive) + { + tri->mScore = tri->mVertex[0] ? tri->mVertex[0]->mScore : 0; + tri->mScore += tri->mVertex[1] ? tri->mVertex[1]->mScore : 0; + tri->mScore += tri->mVertex[2] ? tri->mVertex[2]->mScore : 0; + + if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) + { + mBestTriangle = tri; + } + } + } + } + } + + //knock trailing 3 vertices off the cache + data_iter = mCache+MaxSizeVertexCache; + end_data = mCache+MaxSizeVertexCache+3; + while (data_iter != end_data) + { + LLVCacheVertexData* data = *data_iter; + if (data) + { + llassert(data->mCacheTag == -1); + *data_iter = NULL; + } + ++data_iter; + } + } +}; + +// data structures for tangent generation + +struct MikktData +{ + LLVolumeFace* face; + std::vector p; + std::vector n; + std::vector tc; + std::vector w; + std::vector t; + + MikktData(LLVolumeFace* f) + : face(f) + { + U32 count = face->mNumIndices; + + p.resize(count); + n.resize(count); + tc.resize(count); + t.resize(count); + + if (face->mWeights) + { + w.resize(count); + } + + + LLVector3 inv_scale(1.f / face->mNormalizedScale.mV[0], 1.f / face->mNormalizedScale.mV[1], 1.f / face->mNormalizedScale.mV[2]); + + + for (int i = 0; i < face->mNumIndices; ++i) + { + U32 idx = face->mIndices[i]; + + p[i].set(face->mPositions[idx].getF32ptr()); + p[i].scaleVec(face->mNormalizedScale); //put mesh in original coordinate frame when reconstructing tangents + n[i].set(face->mNormals[idx].getF32ptr()); + n[i].scaleVec(inv_scale); + n[i].normalize(); + tc[i].set(face->mTexCoords[idx]); + + if (idx >= face->mNumVertices) + { + // invalid index + // replace with a valid index to avoid crashes + idx = face->mNumVertices - 1; + face->mIndices[i] = idx; + + // Needs better logging + LL_DEBUGS_ONCE("LLVOLUME") << "Invalid index, substituting" << LL_ENDL; + } + + if (face->mWeights) + { + w[i].set(face->mWeights[idx].getF32ptr()); + } + } + } + + uint32_t GetNumFaces() + { + return uint32_t(face->mNumIndices / 3); + } + + uint32_t GetNumVerticesOfFace(const uint32_t face_num) + { + return 3; + } + + mikk::float3 GetPosition(const uint32_t face_num, const uint32_t vert_num) + { + F32* v = p[face_num * 3 + vert_num].mV; + return mikk::float3(v); + } + + mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num) + { + F32* uv = tc[face_num * 3 + vert_num].mV; + return mikk::float3(uv[0], uv[1], 1.0f); + } + + mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num) + { + F32* normal = n[face_num * 3 + vert_num].mV; + return mikk::float3(normal); + } + + void SetTangentSpace(const uint32_t face_num, const uint32_t vert_num, mikk::float3 T, bool orientation) + { + S32 i = face_num * 3 + vert_num; + t[i].set(T.x, T.y, T.z, orientation ? 1.0f : -1.0f); + } +}; + +bool LLVolumeFace::cacheOptimize(bool gen_tangents) +{ //optimize for vertex cache according to Forsyth method: + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + llassert(!mOptimized); + mOptimized = TRUE; + + if (gen_tangents && mNormals && mTexCoords) + { // generate mikkt space tangents before cache optimizing since the index buffer may change + // a bit of a hack to do this here, but this function gets called exactly once for the lifetime of a mesh + // and is executed on a background thread + MikktData data(this); + mikk::Mikktspace ctx(data); + ctx.genTangSpace(); + + //re-weld + meshopt_Stream mos[] = + { + { &data.p[0], sizeof(LLVector3), sizeof(LLVector3) }, + { &data.n[0], sizeof(LLVector3), sizeof(LLVector3) }, + { &data.t[0], sizeof(LLVector4), sizeof(LLVector4) }, + { &data.tc[0], sizeof(LLVector2), sizeof(LLVector2) }, + { data.w.empty() ? nullptr : &data.w[0], sizeof(LLVector4), sizeof(LLVector4) } + }; + + std::vector remap; + remap.resize(data.p.size()); + + U32 stream_count = data.w.empty() ? 4 : 5; + + size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count); + + if (vert_count < 65535 && vert_count != 0) + { + //copy results back into volume + resizeVertices(vert_count); + + if (!data.w.empty()) + { + allocateWeights(vert_count); + } + + allocateTangents(mNumVertices); + + for (int i = 0; i < mNumIndices; ++i) + { + U32 src_idx = i; + U32 dst_idx = remap[i]; + if (dst_idx >= mNumVertices) + { dst_idx = mNumVertices - 1; // Shouldn't happen, figure out what gets returned in remap and why. llassert(false); @@ -5575,20 +5575,20 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) resizeIndices(mNumIndices); meshopt_optimizeVertexCache(mIndices, src_indices, mNumIndices, mNumVertices); - + ll_aligned_free_16(src_indices); - return true; + return true; } void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME if (getOctree()) - { - return; - } + { + return; + } llassert(mNumIndices % 3 == 0); @@ -5598,63 +5598,63 @@ void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVe mOctreeTriangles = new LLVolumeTriangle[num_triangles]; for (U32 triangle_index = 0; triangle_index < num_triangles; ++triangle_index) - { //for each triangle + { //for each triangle const U32 index = triangle_index * 3; LLVolumeTriangle* tri = &mOctreeTriangles[triangle_index]; - - const LLVector4a& v0 = mPositions[mIndices[index]]; - const LLVector4a& v1 = mPositions[mIndices[index + 1]]; - const LLVector4a& v2 = mPositions[mIndices[index + 2]]; - - //store pointers to vertex data - tri->mV[0] = &v0; - tri->mV[1] = &v1; - tri->mV[2] = &v2; - - //store indices - tri->mIndex[0] = mIndices[index]; - tri->mIndex[1] = mIndices[index + 1]; - tri->mIndex[2] = mIndices[index + 2]; - - //get minimum point - LLVector4a min = v0; - min.setMin(min, v1); - min.setMin(min, v2); - - //get maximum point - LLVector4a max = v0; - max.setMax(max, v1); - max.setMax(max, v2); - - //compute center - LLVector4a center; - center.setAdd(min, max); - center.mul(0.5f); - - tri->mPositionGroup = center; - - //compute "radius" - LLVector4a size; - size.setSub(max,min); - - tri->mRadius = size.getLength3().getF32() * scaler; - - //insert - mOctree->insert(tri); - } - - //remove unneeded octree layers - while (!mOctree->balance()) { } - - //calculate AABB for each node - LLVolumeOctreeRebound rebound; - rebound.traverse(mOctree); - - if (gDebugGL) - { - LLVolumeOctreeValidate validate; - validate.traverse(mOctree); - } + + const LLVector4a& v0 = mPositions[mIndices[index]]; + const LLVector4a& v1 = mPositions[mIndices[index + 1]]; + const LLVector4a& v2 = mPositions[mIndices[index + 2]]; + + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = mIndices[index]; + tri->mIndex[1] = mIndices[index + 1]; + tri->mIndex[2] = mIndices[index + 2]; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max,min); + + tri->mRadius = size.getLength3().getF32() * scaler; + + //insert + mOctree->insert(tri); + } + + //remove unneeded octree layers + while (!mOctree->balance()) { } + + //calculate AABB for each node + LLVolumeOctreeRebound rebound; + rebound.traverse(mOctree); + + if (gDebugGL) + { + LLVolumeOctreeValidate validate; + validate.traverse(mOctree); + } } void LLVolumeFace::destroyOctree() @@ -5673,145 +5673,145 @@ const LLVolumeOctree* LLVolumeFace::getOctree() const void LLVolumeFace::swapData(LLVolumeFace& rhs) { - llswap(rhs.mPositions, mPositions); - llswap(rhs.mNormals, mNormals); - llswap(rhs.mTangents, mTangents); - llswap(rhs.mTexCoords, mTexCoords); - llswap(rhs.mIndices,mIndices); - llswap(rhs.mNumVertices, mNumVertices); - llswap(rhs.mNumIndices, mNumIndices); + llswap(rhs.mPositions, mPositions); + llswap(rhs.mNormals, mNormals); + llswap(rhs.mTangents, mTangents); + llswap(rhs.mTexCoords, mTexCoords); + llswap(rhs.mIndices,mIndices); + llswap(rhs.mNumVertices, mNumVertices); + llswap(rhs.mNumIndices, mNumIndices); } -void LerpPlanarVertex(LLVolumeFace::VertexData& v0, - LLVolumeFace::VertexData& v1, - LLVolumeFace::VertexData& v2, - LLVolumeFace::VertexData& vout, - F32 coef01, - F32 coef02) +void LerpPlanarVertex(LLVolumeFace::VertexData& v0, + LLVolumeFace::VertexData& v1, + LLVolumeFace::VertexData& v2, + LLVolumeFace::VertexData& vout, + F32 coef01, + F32 coef02) { - LLVector4a lhs; - lhs.setSub(v1.getPosition(), v0.getPosition()); - lhs.mul(coef01); - LLVector4a rhs; - rhs.setSub(v2.getPosition(), v0.getPosition()); - rhs.mul(coef02); + LLVector4a lhs; + lhs.setSub(v1.getPosition(), v0.getPosition()); + lhs.mul(coef01); + LLVector4a rhs; + rhs.setSub(v2.getPosition(), v0.getPosition()); + rhs.mul(coef02); - rhs.add(lhs); - rhs.add(v0.getPosition()); + rhs.add(lhs); + rhs.add(v0.getPosition()); - vout.setPosition(rhs); - - vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); - vout.setNormal(v0.getNormal()); + vout.setPosition(rhs); + + vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); + vout.setNormal(v0.getNormal()); } BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) { - LL_CHECK_MEMORY - - const LLAlignedArray& mesh = volume->getMesh(); - const LLAlignedArray& profile = volume->getProfile().mProfile; - S32 max_s = volume->getProfile().getTotal(); - S32 max_t = volume->getPath().mPath.size(); - - // S32 i; - S32 grid_size = (profile.size()-1)/4; - // VFExtents change - LLVector4a& min = mExtents[0]; - LLVector4a& max = mExtents[1]; - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - { - VertexData corners[4]; - VertexData baseVert; - for(S32 t = 0; t < 4; t++) - { - corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); - corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; - corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1]; - } - - { - LLVector4a lhs; - lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); - LLVector4a rhs; - rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); - baseVert.getNormal().setCross3(lhs, rhs); - baseVert.getNormal().normalize3fast(); - } - - if(!(mTypeMask & TOP_MASK)) - { - baseVert.getNormal().mul(-1.0f); - } - else - { - //Swap the UVs on the U(X) axis for top face - LLVector2 swap; - swap = corners[0].mTexCoord; - corners[0].mTexCoord=corners[3].mTexCoord; - corners[3].mTexCoord=swap; - swap = corners[1].mTexCoord; - corners[1].mTexCoord=corners[2].mTexCoord; - corners[2].mTexCoord=swap; - } - - S32 size = (grid_size+1)*(grid_size+1); - resizeVertices(size); - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - LLVector2* tc = (LLVector2*) mTexCoords; - - for(int gx = 0;gxsetAdd(min, max); - mCenter->mul(0.5f); - } - - if (!partial_build) - { - resizeIndices(grid_size*grid_size*6); - if (!volume->isMeshAssetLoaded()) - { + LL_CHECK_MEMORY + + const LLAlignedArray& mesh = volume->getMesh(); + const LLAlignedArray& profile = volume->getProfile().mProfile; + S32 max_s = volume->getProfile().getTotal(); + S32 max_t = volume->getPath().mPath.size(); + + // S32 i; + S32 grid_size = (profile.size()-1)/4; + // VFExtents change + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + { + VertexData corners[4]; + VertexData baseVert; + for(S32 t = 0; t < 4; t++) + { + corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); + corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; + corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1]; + } + + { + LLVector4a lhs; + lhs.setSub(corners[1].getPosition(), corners[0].getPosition()); + LLVector4a rhs; + rhs.setSub(corners[2].getPosition(), corners[1].getPosition()); + baseVert.getNormal().setCross3(lhs, rhs); + baseVert.getNormal().normalize3fast(); + } + + if(!(mTypeMask & TOP_MASK)) + { + baseVert.getNormal().mul(-1.0f); + } + else + { + //Swap the UVs on the U(X) axis for top face + LLVector2 swap; + swap = corners[0].mTexCoord; + corners[0].mTexCoord=corners[3].mTexCoord; + corners[3].mTexCoord=swap; + swap = corners[1].mTexCoord; + corners[1].mTexCoord=corners[2].mTexCoord; + corners[2].mTexCoord=swap; + } + + S32 size = (grid_size+1)*(grid_size+1); + resizeVertices(size); + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector2* tc = (LLVector2*) mTexCoords; + + for(int gx = 0;gxsetAdd(min, max); + mCenter->mul(0.5f); + } + + if (!partial_build) + { + resizeIndices(grid_size*grid_size*6); + if (!volume->isMeshAssetLoaded()) + { S32 size = grid_size * grid_size * 6; try { @@ -5822,562 +5822,562 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL; return false; } - } - - U16* out = mIndices; - - S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; - - int cur_edge = 0; - - for(S32 gx = 0;gx=0;i--) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; // Mark face to higlight it - } - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - } - else - { - for(S32 i=0;i<6;i++) - { - *out++ = ((gy*(grid_size+1))+gx+idxs[i]); - } - - S32 edge_value = grid_size * 2 * gy + gx * 2; - - if (gy > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - - if (gy < grid_size - 1) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - if (gx > 0) - { - mEdge[cur_edge++] = edge_value; - } - else - { - mEdge[cur_edge++] = -1; - } - - mEdge[cur_edge++] = edge_value; - } - } - } - } - - LL_CHECK_MEMORY - return TRUE; + } + + U16* out = mIndices; + + S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; + + int cur_edge = 0; + + for(S32 gx = 0;gx=0;i--) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; // Mark face to higlight it + } + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + } + else + { + for(S32 i=0;i<6;i++) + { + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } + + S32 edge_value = grid_size * 2 * gy + gx * 2; + + if (gy > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + + if (gy < grid_size - 1) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + if (gx > 0) + { + mEdge[cur_edge++] = edge_value; + } + else + { + mEdge[cur_edge++] = -1; + } + + mEdge[cur_edge++] = edge_value; + } + } + } + } + + LL_CHECK_MEMORY + return TRUE; } -BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) -{ - if (!(mTypeMask & HOLLOW_MASK) && - !(mTypeMask & OPEN_MASK) && - ((volume->getParams().getPathParams().getBegin()==0.0f)&& - (volume->getParams().getPathParams().getEnd()==1.0f))&& - (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && - volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) - ){ - return createUnCutCubeCap(volume, partial_build); - } - - S32 num_vertices = 0, num_indices = 0; - - const LLAlignedArray& mesh = volume->getMesh(); - const LLAlignedArray& profile = volume->getProfile().mProfile; - - // All types of caps have the same number of vertices and indices - num_vertices = profile.size(); - num_indices = (profile.size() - 2)*3; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - resizeVertices(num_vertices+1); - - //if (!partial_build) - { - resizeIndices(num_indices+3); - } - } - else - { - resizeVertices(num_vertices); - //if (!partial_build) - { - resizeIndices(num_indices); - } - } - - LL_CHECK_MEMORY; - - S32 max_s = volume->getProfile().getTotal(); - S32 max_t = volume->getPath().mPath.size(); - - mCenter->clear(); - - S32 offset = 0; - if (mTypeMask & TOP_MASK) - { - offset = (max_t-1) * max_s; - } - else - { - offset = mBeginS; - } - - // Figure out the normal, assume all caps are flat faces. - // Cross product to get normals. - - LLVector2 cuv; - LLVector2 min_uv, max_uv; - // VFExtents change - LLVector4a& min = mExtents[0]; - LLVector4a& max = mExtents[1]; - - LLVector2* tc = (LLVector2*) mTexCoords; - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector4a* norm = (LLVector4a*) mNormals; - - // Copy the vertices into the array - - const LLVector4a* src = mesh.mArray+offset; - const LLVector4a* end = src+num_vertices; - - min = *src; - max = min; - - - const LLVector4a* p = profile.mArray; - - if (mTypeMask & TOP_MASK) - { - min_uv.set((*p)[0]+0.5f, - (*p)[1]+0.5f); - - max_uv = min_uv; - - while(src < end) - { - tc->mV[0] = (*p)[0]+0.5f; - tc->mV[1] = (*p)[1]+0.5f; - - llassert(src->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds - update_min_max(min,max,*src); - update_min_max(min_uv, max_uv, *tc); - - *pos = *src; - - llassert(pos->isFinite3()); - - ++p; - ++tc; - ++src; - ++pos; - } - } - else - { - - min_uv.set((*p)[0]+0.5f, - 0.5f - (*p)[1]); - max_uv = min_uv; - - while(src < end) - { - // Mirror for underside. - tc->mV[0] = (*p)[0]+0.5f; - tc->mV[1] = 0.5f - (*p)[1]; - - llassert(src->isFinite3()); - update_min_max(min,max,*src); - update_min_max(min_uv, max_uv, *tc); - - *pos = *src; - - llassert(pos->isFinite3()); - - ++p; - ++tc; - ++src; - ++pos; - } - } - - LL_CHECK_MEMORY - - mCenter->setAdd(min, max); - mCenter->mul(0.5f); - - cuv = (min_uv + max_uv)*0.5f; - - - VertexData vd; - vd.setPosition(*mCenter); - vd.mTexCoord = cuv; - - if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) - { - *pos++ = *mCenter; - *tc++ = cuv; - num_vertices++; - } - - LL_CHECK_MEMORY - - //if (partial_build) - //{ - // return TRUE; - //} - - if (mTypeMask & HOLLOW_MASK) - { - if (mTypeMask & TOP_MASK) - { - // HOLLOW TOP - // Does it matter if it's open or closed? - djs - - S32 pt1 = 0, pt2 = num_vertices - 1; - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - const LLVector4a& p1 = profile[pt1]; - const LLVector4a& p2 = profile[pt2]; - const LLVector4a& pa = profile[pt1+1]; - const LLVector4a& pb = profile[pt2-1]; - - const F32* p1V = p1.getF32ptr(); - const F32* p2V = p2.getF32ptr(); - const F32* paV = pa.getF32ptr(); - const F32* pbV = pb.getF32ptr(); - - //p1.mV[VZ] = 0.f; - //p2.mV[VZ] = 0.f; - //pa.mV[VZ] = 0.f; - //pb.mV[VZ] = 0.f; - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + - (paV[0]*p2V[1] - p2V[0]*paV[1]) + - (p2V[0]*p1V[1] - p1V[0]*p2V[1]); - - area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*paV[1] - paV[0]*pbV[1]) + - (paV[0]*p1V[1] - p1V[0]*paV[1]); - - area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + - (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + - (paV[0]*pbV[1] - pbV[0]*paV[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector4a d1; - d1.setSub(p1, pa); - - LLVector4a d2; - d2.setSub(p2, pb); - - if (d1.dot3(d1) < d2.dot3(d2)) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt1 + 1; - mIndices[i++] = pt2; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2 - 1; - mIndices[i++] = pt2; - pt2--; - } - } - } - else - { - // HOLLOW BOTTOM - // Does it matter if it's open or closed? - djs - - llassert(mTypeMask & BOTTOM_MASK); - S32 pt1 = 0, pt2 = num_vertices - 1; - - S32 i = 0; - while (pt2 - pt1 > 1) - { - // Use the profile points instead of the mesh, since you want - // the un-transformed profile distances. - const LLVector4a& p1 = profile[pt1]; - const LLVector4a& p2 = profile[pt2]; - const LLVector4a& pa = profile[pt1+1]; - const LLVector4a& pb = profile[pt2-1]; - - const F32* p1V = p1.getF32ptr(); - const F32* p2V = p2.getF32ptr(); - const F32* paV = pa.getF32ptr(); - const F32* pbV = pb.getF32ptr(); - - // Use area of triangle to determine backfacing - F32 area_1a2, area_1ba, area_21b, area_2ab; - area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + - (paV[0]*p2V[1] - p2V[0]*paV[1]) + - (p2V[0]*p1V[1] - p1V[0]*p2V[1]); - - area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*paV[1] - paV[0]*pbV[1]) + - (paV[0]*p1V[1] - p1V[0]*paV[1]); - - area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + - (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + - (paV[0]*pbV[1] - pbV[0]*paV[1]) + - (pbV[0]*p2V[1] - p2V[0]*pbV[1]); - - BOOL use_tri1a2 = TRUE; - BOOL tri_1a2 = TRUE; - BOOL tri_21b = TRUE; - - if (area_1a2 < 0) - { - tri_1a2 = FALSE; - } - if (area_2ab < 0) - { - // Can't use, because it contains point b - tri_1a2 = FALSE; - } - if (area_21b < 0) - { - tri_21b = FALSE; - } - if (area_1ba < 0) - { - // Can't use, because it contains point b - tri_21b = FALSE; - } - - if (!tri_1a2) - { - use_tri1a2 = FALSE; - } - else if (!tri_21b) - { - use_tri1a2 = TRUE; - } - else - { - LLVector4a d1; - d1.setSub(p1,pa); - LLVector4a d2; - d2.setSub(p2,pb); - - if (d1.dot3(d1) < d2.dot3(d2)) - { - use_tri1a2 = TRUE; - } - else - { - use_tri1a2 = FALSE; - } - } - - // Flipped backfacing from top - if (use_tri1a2) - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt1 + 1; - pt1++; - } - else - { - mIndices[i++] = pt1; - mIndices[i++] = pt2; - mIndices[i++] = pt2 - 1; - pt2--; - } - } - } - } - else - { - // Not hollow, generate the triangle fan. - U16 v1 = 2; - U16 v2 = 1; - - if (mTypeMask & TOP_MASK) - { - v1 = 1; - v2 = 2; - } - - for (S32 i = 0; i < (num_vertices - 2); i++) - { - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+v1] = i; - mIndices[3*i+v2] = i + 1; - } - - - } - - LLVector4a d0,d1; - LL_CHECK_MEMORY - - - d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]); - d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]); - - LLVector4a normal; - normal.setCross3(d0,d1); - - if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO) - { - normal.normalize3fast(); - } - else - { //degenerate, make up a value - if(normal.getF32ptr()[2] >= 0) - normal.set(0.f,0.f,1.f); - else - normal.set(0.f,0.f,-1.f); - } - - llassert(llfinite(normal.getF32ptr()[0])); - llassert(llfinite(normal.getF32ptr()[1])); - llassert(llfinite(normal.getF32ptr()[2])); - - llassert(!llisnan(normal.getF32ptr()[0])); - llassert(!llisnan(normal.getF32ptr()[1])); - llassert(!llisnan(normal.getF32ptr()[2])); - - for (S32 i = 0; i < num_vertices; i++) - { - norm[i].load4a(normal.getF32ptr()); - } - - return TRUE; +BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) +{ + if (!(mTypeMask & HOLLOW_MASK) && + !(mTypeMask & OPEN_MASK) && + ((volume->getParams().getPathParams().getBegin()==0.0f)&& + (volume->getParams().getPathParams().getEnd()==1.0f))&& + (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE && + volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE) + ){ + return createUnCutCubeCap(volume, partial_build); + } + + S32 num_vertices = 0, num_indices = 0; + + const LLAlignedArray& mesh = volume->getMesh(); + const LLAlignedArray& profile = volume->getProfile().mProfile; + + // All types of caps have the same number of vertices and indices + num_vertices = profile.size(); + num_indices = (profile.size() - 2)*3; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + resizeVertices(num_vertices+1); + + //if (!partial_build) + { + resizeIndices(num_indices+3); + } + } + else + { + resizeVertices(num_vertices); + //if (!partial_build) + { + resizeIndices(num_indices); + } + } + + LL_CHECK_MEMORY; + + S32 max_s = volume->getProfile().getTotal(); + S32 max_t = volume->getPath().mPath.size(); + + mCenter->clear(); + + S32 offset = 0; + if (mTypeMask & TOP_MASK) + { + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; + } + + // Figure out the normal, assume all caps are flat faces. + // Cross product to get normals. + + LLVector2 cuv; + LLVector2 min_uv, max_uv; + // VFExtents change + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + + // Copy the vertices into the array + + const LLVector4a* src = mesh.mArray+offset; + const LLVector4a* end = src+num_vertices; + + min = *src; + max = min; + + + const LLVector4a* p = profile.mArray; + + if (mTypeMask & TOP_MASK) + { + min_uv.set((*p)[0]+0.5f, + (*p)[1]+0.5f); + + max_uv = min_uv; + + while(src < end) + { + tc->mV[0] = (*p)[0]+0.5f; + tc->mV[1] = (*p)[1]+0.5f; + + llassert(src->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds + update_min_max(min,max,*src); + update_min_max(min_uv, max_uv, *tc); + + *pos = *src; + + llassert(pos->isFinite3()); + + ++p; + ++tc; + ++src; + ++pos; + } + } + else + { + + min_uv.set((*p)[0]+0.5f, + 0.5f - (*p)[1]); + max_uv = min_uv; + + while(src < end) + { + // Mirror for underside. + tc->mV[0] = (*p)[0]+0.5f; + tc->mV[1] = 0.5f - (*p)[1]; + + llassert(src->isFinite3()); + update_min_max(min,max,*src); + update_min_max(min_uv, max_uv, *tc); + + *pos = *src; + + llassert(pos->isFinite3()); + + ++p; + ++tc; + ++src; + ++pos; + } + } + + LL_CHECK_MEMORY + + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + + cuv = (min_uv + max_uv)*0.5f; + + + VertexData vd; + vd.setPosition(*mCenter); + vd.mTexCoord = cuv; + + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) + { + *pos++ = *mCenter; + *tc++ = cuv; + num_vertices++; + } + + LL_CHECK_MEMORY + + //if (partial_build) + //{ + // return TRUE; + //} + + if (mTypeMask & HOLLOW_MASK) + { + if (mTypeMask & TOP_MASK) + { + // HOLLOW TOP + // Does it matter if it's open or closed? - djs + + S32 pt1 = 0, pt2 = num_vertices - 1; + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + const LLVector4a& p1 = profile[pt1]; + const LLVector4a& p2 = profile[pt2]; + const LLVector4a& pa = profile[pt1+1]; + const LLVector4a& pb = profile[pt2-1]; + + const F32* p1V = p1.getF32ptr(); + const F32* p2V = p2.getF32ptr(); + const F32* paV = pa.getF32ptr(); + const F32* pbV = pb.getF32ptr(); + + //p1.mV[VZ] = 0.f; + //p2.mV[VZ] = 0.f; + //pa.mV[VZ] = 0.f; + //pb.mV[VZ] = 0.f; + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + + (paV[0]*p2V[1] - p2V[0]*paV[1]) + + (p2V[0]*p1V[1] - p1V[0]*p2V[1]); + + area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*paV[1] - paV[0]*pbV[1]) + + (paV[0]*p1V[1] - p1V[0]*paV[1]); + + area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + + (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + + (paV[0]*pbV[1] - pbV[0]*paV[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector4a d1; + d1.setSub(p1, pa); + + LLVector4a d2; + d2.setSub(p2, pb); + + if (d1.dot3(d1) < d2.dot3(d2)) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt1 + 1; + mIndices[i++] = pt2; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2 - 1; + mIndices[i++] = pt2; + pt2--; + } + } + } + else + { + // HOLLOW BOTTOM + // Does it matter if it's open or closed? - djs + + llassert(mTypeMask & BOTTOM_MASK); + S32 pt1 = 0, pt2 = num_vertices - 1; + + S32 i = 0; + while (pt2 - pt1 > 1) + { + // Use the profile points instead of the mesh, since you want + // the un-transformed profile distances. + const LLVector4a& p1 = profile[pt1]; + const LLVector4a& p2 = profile[pt2]; + const LLVector4a& pa = profile[pt1+1]; + const LLVector4a& pb = profile[pt2-1]; + + const F32* p1V = p1.getF32ptr(); + const F32* p2V = p2.getF32ptr(); + const F32* paV = pa.getF32ptr(); + const F32* pbV = pb.getF32ptr(); + + // Use area of triangle to determine backfacing + F32 area_1a2, area_1ba, area_21b, area_2ab; + area_1a2 = (p1V[0]*paV[1] - paV[0]*p1V[1]) + + (paV[0]*p2V[1] - p2V[0]*paV[1]) + + (p2V[0]*p1V[1] - p1V[0]*p2V[1]); + + area_1ba = (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*paV[1] - paV[0]*pbV[1]) + + (paV[0]*p1V[1] - p1V[0]*paV[1]); + + area_21b = (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + + (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + area_2ab = (p2V[0]*paV[1] - paV[0]*p2V[1]) + + (paV[0]*pbV[1] - pbV[0]*paV[1]) + + (pbV[0]*p2V[1] - p2V[0]*pbV[1]); + + BOOL use_tri1a2 = TRUE; + BOOL tri_1a2 = TRUE; + BOOL tri_21b = TRUE; + + if (area_1a2 < 0) + { + tri_1a2 = FALSE; + } + if (area_2ab < 0) + { + // Can't use, because it contains point b + tri_1a2 = FALSE; + } + if (area_21b < 0) + { + tri_21b = FALSE; + } + if (area_1ba < 0) + { + // Can't use, because it contains point b + tri_21b = FALSE; + } + + if (!tri_1a2) + { + use_tri1a2 = FALSE; + } + else if (!tri_21b) + { + use_tri1a2 = TRUE; + } + else + { + LLVector4a d1; + d1.setSub(p1,pa); + LLVector4a d2; + d2.setSub(p2,pb); + + if (d1.dot3(d1) < d2.dot3(d2)) + { + use_tri1a2 = TRUE; + } + else + { + use_tri1a2 = FALSE; + } + } + + // Flipped backfacing from top + if (use_tri1a2) + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt1 + 1; + pt1++; + } + else + { + mIndices[i++] = pt1; + mIndices[i++] = pt2; + mIndices[i++] = pt2 - 1; + pt2--; + } + } + } + } + else + { + // Not hollow, generate the triangle fan. + U16 v1 = 2; + U16 v2 = 1; + + if (mTypeMask & TOP_MASK) + { + v1 = 1; + v2 = 2; + } + + for (S32 i = 0; i < (num_vertices - 2); i++) + { + mIndices[3*i] = num_vertices - 1; + mIndices[3*i+v1] = i; + mIndices[3*i+v2] = i + 1; + } + + + } + + LLVector4a d0,d1; + LL_CHECK_MEMORY + + + d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]); + d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]); + + LLVector4a normal; + normal.setCross3(d0,d1); + + if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO) + { + normal.normalize3fast(); + } + else + { //degenerate, make up a value + if(normal.getF32ptr()[2] >= 0) + normal.set(0.f,0.f,1.f); + else + normal.set(0.f,0.f,-1.f); + } + + llassert(llfinite(normal.getF32ptr()[0])); + llassert(llfinite(normal.getF32ptr()[1])); + llassert(llfinite(normal.getF32ptr()[2])); + + llassert(!llisnan(normal.getF32ptr()[0])); + llassert(!llisnan(normal.getF32ptr()[1])); + llassert(!llisnan(normal.getF32ptr()[2])); + + for (S32 i = 0; i < num_vertices; i++) + { + norm[i].load4a(normal.getF32ptr()); + } + + return TRUE; } void LLVolumeFace::createTangents() @@ -6387,7 +6387,7 @@ void LLVolumeFace::createTangents() if (!mTangents) { allocateTangents(mNumVertices); - + //generate tangents LLVector4a* ptr = (LLVector4a*)mTangents; @@ -6411,29 +6411,29 @@ void LLVolumeFace::createTangents() void LLVolumeFace::resizeVertices(S32 num_verts) { - ll_aligned_free<64>(mPositions); - //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer - ll_aligned_free_16(mTangents); + ll_aligned_free<64>(mPositions); + //DO NOT free mNormals and mTexCoords as they are part of mPositions buffer + ll_aligned_free_16(mTangents); - mTangents = NULL; + mTangents = NULL; - if (num_verts) - { - //pad texture coordinate block end to allow for QWORD reads - S32 tc_size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + if (num_verts) + { + //pad texture coordinate block end to allow for QWORD reads + S32 tc_size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; - mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+tc_size); - mNormals = mPositions+num_verts; - mTexCoords = (LLVector2*) (mNormals+num_verts); + mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+tc_size); + mNormals = mPositions+num_verts; + mTexCoords = (LLVector2*) (mNormals+num_verts); - ll_assert_aligned(mPositions, 64); - } - else - { - mPositions = NULL; - mNormals = NULL; - mTexCoords = NULL; - } + ll_assert_aligned(mPositions, 64); + } + else + { + mPositions = NULL; + mNormals = NULL; + mTexCoords = NULL; + } if (mPositions) @@ -6454,70 +6454,70 @@ void LLVolumeFace::resizeVertices(S32 num_verts) void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) { - pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); + pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); } void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc) { - S32 new_verts = mNumVertices+1; + S32 new_verts = mNumVertices+1; + + if (new_verts > mNumAllocatedVertices) + { + // double buffer size on expansion + new_verts *= 2; - if (new_verts > mNumAllocatedVertices) - { - // double buffer size on expansion - new_verts *= 2; + S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; + S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; - S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; - S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; + S32 old_vsize = mNumVertices*16; - S32 old_vsize = mNumVertices*16; - - S32 new_size = new_verts*16*2+new_tc_size; + S32 new_size = new_verts*16*2+new_tc_size; - LLVector4a* old_buf = mPositions; + LLVector4a* old_buf = mPositions; - mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size); - mNormals = mPositions+new_verts; - mTexCoords = (LLVector2*) (mNormals+new_verts); + mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size); + mNormals = mPositions+new_verts; + mTexCoords = (LLVector2*) (mNormals+new_verts); - if (old_buf != NULL) - { - // copy old positions into new buffer - LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); + if (old_buf != NULL) + { + // copy old positions into new buffer + LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize); - // normals - LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize); + // normals + LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_vsize); - // tex coords - LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size); - } + // tex coords + LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tc_size); + } - // just clear tangents - ll_aligned_free_16(mTangents); - mTangents = NULL; - ll_aligned_free<64>(old_buf); + // just clear tangents + ll_aligned_free_16(mTangents); + mTangents = NULL; + ll_aligned_free<64>(old_buf); - mNumAllocatedVertices = new_verts; + mNumAllocatedVertices = new_verts; - } + } - mPositions[mNumVertices] = pos; - mNormals[mNumVertices] = norm; - mTexCoords[mNumVertices] = tc; + mPositions[mNumVertices] = pos; + mNormals[mNumVertices] = norm; + mTexCoords[mNumVertices] = tc; - mNumVertices++; + mNumVertices++; } void LLVolumeFace::allocateTangents(S32 num_verts) { - ll_aligned_free_16(mTangents); - mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + ll_aligned_free_16(mTangents); + mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); } void LLVolumeFace::allocateWeights(S32 num_verts) { - ll_aligned_free_16(mWeights); - mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); - + ll_aligned_free_16(mWeights); + mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } void LLVolumeFace::allocateJointIndices(S32 num_verts) @@ -6526,27 +6526,27 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts) ll_aligned_free_16(mJointIndices); ll_aligned_free_16(mJustWeights); - mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); - mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); + mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts); + mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts); #endif } void LLVolumeFace::resizeIndices(S32 num_indices) { - ll_aligned_free_16(mIndices); + ll_aligned_free_16(mIndices); llassert(num_indices % 3 == 0); - - if (num_indices) - { - //pad index block end to allow for QWORD reads - S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; - - mIndices = (U16*) ll_aligned_malloc_16(size); - } - else - { - mIndices = NULL; - } + + if (num_indices) + { + //pad index block end to allow for QWORD reads + S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; + + mIndices = (U16*) ll_aligned_malloc_16(size); + } + else + { + mIndices = NULL; + } if (mIndices) { @@ -6561,73 +6561,73 @@ void LLVolumeFace::resizeIndices(S32 num_indices) void LLVolumeFace::pushIndex(const U16& idx) { - S32 new_count = mNumIndices + 1; - S32 new_size = ((new_count*2)+0xF) & ~0xF; + S32 new_count = mNumIndices + 1; + S32 new_size = ((new_count*2)+0xF) & ~0xF; + + S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; + if (new_size != old_size) + { + mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); + ll_assert_aligned(mIndices,16); + } - S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; - if (new_size != old_size) - { - mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size); - ll_assert_aligned(mIndices,16); - } - - mIndices[mNumIndices++] = idx; + mIndices[mNumIndices++] = idx; } void LLVolumeFace::fillFromLegacyData(std::vector& v, std::vector& idx) { - resizeVertices(v.size()); - resizeIndices(idx.size()); + resizeVertices(v.size()); + resizeIndices(idx.size()); - for (U32 i = 0; i < v.size(); ++i) - { - mPositions[i] = v[i].getPosition(); - mNormals[i] = v[i].getNormal(); - mTexCoords[i] = v[i].mTexCoord; - } + for (U32 i = 0; i < v.size(); ++i) + { + mPositions[i] = v[i].getPosition(); + mNormals[i] = v[i].getNormal(); + mTexCoords[i] = v[i].mTexCoord; + } - for (U32 i = 0; i < idx.size(); ++i) - { - mIndices[i] = idx[i]; - } + for (U32 i = 0; i < idx.size(); ++i) + { + mIndices[i] = idx[i]; + } } BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + + LL_CHECK_MEMORY + BOOL flat = mTypeMask & FLAT_MASK; - LL_CHECK_MEMORY - BOOL flat = mTypeMask & FLAT_MASK; + U8 sculpt_type = volume->getParams().getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - U8 sculpt_type = volume->getParams().getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror); // XOR - - S32 num_vertices, num_indices; + S32 num_vertices, num_indices; - const LLAlignedArray& mesh = volume->getMesh(); - const LLAlignedArray& profile = volume->getProfile().mProfile; - const LLAlignedArray& path_data = volume->getPath().mPath; + const LLAlignedArray& mesh = volume->getMesh(); + const LLAlignedArray& profile = volume->getProfile().mProfile; + const LLAlignedArray& path_data = volume->getPath().mPath; - S32 max_s = volume->getProfile().getTotal(); + S32 max_s = volume->getProfile().getTotal(); - S32 s, t, i; - F32 ss, tt; + S32 s, t, i; + F32 ss, tt; - num_vertices = mNumS*mNumT; - num_indices = (mNumS-1)*(mNumT-1)*6; + num_vertices = mNumS*mNumT; + num_indices = (mNumS-1)*(mNumT-1)*6; - partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? FALSE : partial_build; + partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? FALSE : partial_build; - if (!partial_build) - { - resizeVertices(num_vertices); - resizeIndices(num_indices); + if (!partial_build) + { + resizeVertices(num_vertices); + resizeIndices(num_indices); - if (!volume->isMeshAssetLoaded()) - { + if (!volume->isMeshAssetLoaded()) + { try { mEdge.resize(num_indices); @@ -6637,237 +6637,237 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL; return false; } - } - } - - LL_CHECK_MEMORY - - LLVector4a* pos = (LLVector4a*) mPositions; - LLVector2* tc = (LLVector2*) mTexCoords; - F32 begin_stex = floorf(profile[mBeginS][2]); - S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; - - S32 cur_vertex = 0; - S32 end_t = mBeginT+mNumT; - bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; - - // Copy the vertices into the array - for (t = mBeginT; t < end_t; t++) - { - tt = path_data[t].mTexT; - for (s = 0; s < num_s; s++) - { - if (mTypeMask & END_MASK) - { - if (s) - { - ss = 1.f; - } - else - { - ss = 0.f; - } - } - else - { - // Get s value for tex-coord. + } + } + + LL_CHECK_MEMORY + + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector2* tc = (LLVector2*) mTexCoords; + F32 begin_stex = floorf(profile[mBeginS][2]); + S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; + + S32 cur_vertex = 0; + S32 end_t = mBeginT+mNumT; + bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; + + // Copy the vertices into the array + for (t = mBeginT; t < end_t; t++) + { + tt = path_data[t].mTexT; + for (s = 0; s < num_s; s++) + { + if (mTypeMask & END_MASK) + { + if (s) + { + ss = 1.f; + } + else + { + ss = 0.f; + } + } + else + { + // Get s value for tex-coord. S32 index = mBeginS + s; if (index >= profile.size()) { // edge? ss = flat ? 1.f - begin_stex : 1.f; } - else if (!flat) - { - ss = profile[index][2]; - } - else - { - ss = profile[index][2] - begin_stex; - } - } - - if (sculpt_reverse_horizontal) - { - ss = 1.f - ss; - } - - // Check to see if this triangle wraps around the array. - if (mBeginS + s >= max_s) - { - // We're wrapping - i = mBeginS + s + max_s*(t-1); - } - else - { - i = mBeginS + s + max_s*t; - } - - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - - cur_vertex++; - - if (test && s > 0) - { - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - cur_vertex++; - } - } - - if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) - { - if (mTypeMask & OPEN_MASK) - { - s = num_s-1; - } - else - { - s = 0; - } - - i = mBeginS + s + max_s*t; - ss = profile[mBeginS + s][2] - begin_stex; - - mesh[i].store4a((F32*)(pos+cur_vertex)); - tc[cur_vertex].set(ss,tt); - - cur_vertex++; - } - } - LL_CHECK_MEMORY - - mCenter->clear(); - - LLVector4a* cur_pos = pos; - LLVector4a* end_pos = pos + mNumVertices; - - //get bounding box for this side - LLVector4a face_min; - LLVector4a face_max; - - face_min = face_max = *cur_pos++; - - while (cur_pos < end_pos) - { - update_min_max(face_min, face_max, *cur_pos++); - } - // VFExtents change - mExtents[0] = face_min; - mExtents[1] = face_max; - - U32 tc_count = mNumVertices; - if (tc_count%2 == 1) - { //odd number of texture coordinates, duplicate last entry to padded end of array - tc_count++; - mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; - } - - LLVector4a* cur_tc = (LLVector4a*) mTexCoords; - LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); - - LLVector4a tc_min; - LLVector4a tc_max; - - tc_min = tc_max = *cur_tc++; - - while (cur_tc < end_tc) - { - update_min_max(tc_min, tc_max, *cur_tc++); - } - - F32* minp = tc_min.getF32ptr(); - F32* maxp = tc_max.getF32ptr(); - - mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); - mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); - mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); - mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); - - mCenter->setAdd(face_min, face_max); - mCenter->mul(0.5f); - - S32 cur_index = 0; - S32 cur_edge = 0; - BOOL flat_face = mTypeMask & FLAT_MASK; - - if (!partial_build) - { - // Now we generate the indices. - for (t = 0; t < (mNumT-1); t++) - { - for (s = 0; s < (mNumS-1); s++) - { - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - mIndices[cur_index++] = s + mNumS*(t+1); //top left - mIndices[cur_index++] = s + mNumS*t; //bottom left - mIndices[cur_index++] = s+1 + mNumS*t; //bottom right - mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right - - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face - if (t < mNumT-2) { //top right/top left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; - } - else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on T - mEdge[cur_edge++] = s*2+1; - } - if (s > 0) { //top left/bottom left neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; - } - else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; - } - - if (t > 0) { //bottom left/bottom right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; - } - else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on T - mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; - } - if (s < mNumS-2) { //bottom right/top right neighbor face - mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; - } - else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor - mEdge[cur_edge++] = -1; - } - else { //wrap on S - mEdge[cur_edge++] = (mNumS-1)*2*t; - } - mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face - } - } - } - - LL_CHECK_MEMORY - - //clear normals - F32* dst = (F32*) mNormals; - F32* end = (F32*) (mNormals+mNumVertices); - LLVector4a zero = LLVector4a::getZero(); - - while (dst < end) - { - zero.store4a(dst); - dst += 4; - } - - LL_CHECK_MEMORY - - //generate normals - U32 count = mNumIndices/3; - - LLVector4a* norm = mNormals; + else if (!flat) + { + ss = profile[index][2]; + } + else + { + ss = profile[index][2] - begin_stex; + } + } + + if (sculpt_reverse_horizontal) + { + ss = 1.f - ss; + } + + // Check to see if this triangle wraps around the array. + if (mBeginS + s >= max_s) + { + // We're wrapping + i = mBeginS + s + max_s*(t-1); + } + else + { + i = mBeginS + s + max_s*t; + } + + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + + cur_vertex++; + + if (test && s > 0) + { + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + cur_vertex++; + } + } + + if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) + { + if (mTypeMask & OPEN_MASK) + { + s = num_s-1; + } + else + { + s = 0; + } + + i = mBeginS + s + max_s*t; + ss = profile[mBeginS + s][2] - begin_stex; + + mesh[i].store4a((F32*)(pos+cur_vertex)); + tc[cur_vertex].set(ss,tt); + + cur_vertex++; + } + } + LL_CHECK_MEMORY + + mCenter->clear(); + + LLVector4a* cur_pos = pos; + LLVector4a* end_pos = pos + mNumVertices; + + //get bounding box for this side + LLVector4a face_min; + LLVector4a face_max; + + face_min = face_max = *cur_pos++; + + while (cur_pos < end_pos) + { + update_min_max(face_min, face_max, *cur_pos++); + } + // VFExtents change + mExtents[0] = face_min; + mExtents[1] = face_max; + + U32 tc_count = mNumVertices; + if (tc_count%2 == 1) + { //odd number of texture coordinates, duplicate last entry to padded end of array + tc_count++; + mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; + } + + LLVector4a* cur_tc = (LLVector4a*) mTexCoords; + LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); + + LLVector4a tc_min; + LLVector4a tc_max; + + tc_min = tc_max = *cur_tc++; + + while (cur_tc < end_tc) + { + update_min_max(tc_min, tc_max, *cur_tc++); + } + + F32* minp = tc_min.getF32ptr(); + F32* maxp = tc_max.getF32ptr(); + + mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); + mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); + mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); + mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); + + mCenter->setAdd(face_min, face_max); + mCenter->mul(0.5f); + + S32 cur_index = 0; + S32 cur_edge = 0; + BOOL flat_face = mTypeMask & FLAT_MASK; + + if (!partial_build) + { + // Now we generate the indices. + for (t = 0; t < (mNumT-1); t++) + { + for (s = 0; s < (mNumS-1); s++) + { + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + mIndices[cur_index++] = s + mNumS*(t+1); //top left + mIndices[cur_index++] = s + mNumS*t; //bottom left + mIndices[cur_index++] = s+1 + mNumS*t; //bottom right + mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face + if (t < mNumT-2) { //top right/top left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; + } + else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on T + mEdge[cur_edge++] = s*2+1; + } + if (s > 0) { //top left/bottom left neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1; + } + else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1; + } + + if (t > 0) { //bottom left/bottom right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2; + } + else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on T + mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2; + } + if (s < mNumS-2) { //bottom right/top right neighbor face + mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2; + } + else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor + mEdge[cur_edge++] = -1; + } + else { //wrap on S + mEdge[cur_edge++] = (mNumS-1)*2*t; + } + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face + } + } + } + + LL_CHECK_MEMORY + + //clear normals + F32* dst = (F32*) mNormals; + F32* end = (F32*) (mNormals+mNumVertices); + LLVector4a zero = LLVector4a::getZero(); + + while (dst < end) + { + zero.store4a(dst); + dst += 4; + } + + LL_CHECK_MEMORY + + //generate normals + U32 count = mNumIndices/3; + + LLVector4a* norm = mNormals; static thread_local LLAlignedArray triangle_normals; try @@ -6879,242 +6879,242 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) LL_WARNS("LLVOLUME") << "Resize of triangle_normals to " << count << " failed" << LL_ENDL; return false; } - LLVector4a* output = triangle_normals.mArray; - LLVector4a* end_output = output+count; - - U16* idx = mIndices; - - while (output < end_output) - { - LLVector4a b,v1,v2; - b.load4a((F32*) (pos+idx[0])); - v1.load4a((F32*) (pos+idx[1])); - v2.load4a((F32*) (pos+idx[2])); - - //calculate triangle normal - LLVector4a a; - - a.setSub(b, v1); - b.sub(v2); - - - LLQuad& vector1 = *((LLQuad*) &v1); - LLQuad& vector2 = *((LLQuad*) &v2); - - LLQuad& amQ = *((LLQuad*) &a); - LLQuad& bmQ = *((LLQuad*) &b); - - //v1.setCross3(t,v0); - //setCross3(const LLVector4a& a, const LLVector4a& b) - // Vectors are stored in memory in w, z, y, x order from high to low - // Set vector1 = { a[W], a[X], a[Z], a[Y] } - vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // Set vector2 = { b[W], b[Y], b[X], b[Z] } - vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } - vector2 = _mm_mul_ps( vector1, vector2 ); - // vector3 = { a[W], a[Y], a[X], a[Z] } - amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); - // vector4 = { b[W], b[X], b[Z], b[Y] } - bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); - // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } - vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); - - llassert(v1.isFinite3()); - - v1.store4a((F32*) output); - - - output++; - idx += 3; - } - - idx = mIndices; - - LLVector4a* src = triangle_normals.mArray; - - for (U32 i = 0; i < count; i++) //for each triangle - { - LLVector4a c; - c.load4a((F32*) (src++)); - - LLVector4a* n0p = norm+idx[0]; - LLVector4a* n1p = norm+idx[1]; - LLVector4a* n2p = norm+idx[2]; - - idx += 3; - - LLVector4a n0,n1,n2; - n0.load4a((F32*) n0p); - n1.load4a((F32*) n1p); - n2.load4a((F32*) n2p); - - n0.add(c); - n1.add(c); - n2.add(c); - - llassert(c.isFinite3()); - - //even out quad contributions - switch (i%2+1) - { - case 0: n0.add(c); break; - case 1: n1.add(c); break; - case 2: n2.add(c); break; - }; - - n0.store4a((F32*) n0p); - n1.store4a((F32*) n1p); - n2.store4a((F32*) n2p); - } - - LL_CHECK_MEMORY - - // adjust normals based on wrapping and stitching - - LLVector4a top; - top.setSub(pos[0], pos[mNumS*(mNumT-2)]); - BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); - - top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); - BOOL s_top_converges = (top.dot3(top) < 0.000001f); - - if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes - { - if (volume->getPath().isOpen() == FALSE) - { //wrap normals on T - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges)) - { //wrap normals on S - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && - ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) - { - if (s_bottom_converges) - { //all lower S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i].set(1,0,0); - } - } - - if (s_top_converges) - { //all upper S have same normal - for (S32 i = 0; i < mNumT; i++) - { - norm[mNumS*i+mNumS-1].set(-1,0,0); - } - } - } - } - else // logic for sculpt volumes - { - BOOL average_poles = FALSE; - BOOL wrap_s = FALSE; - BOOL wrap_t = FALSE; - - if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) - average_poles = TRUE; - - if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || - (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || - (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) - wrap_s = TRUE; - - if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) - wrap_t = TRUE; - - - if (average_poles) - { - // average normals for north pole - - LLVector4a average; - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i] = average; - } - - // average normals for south pole - - average.clear(); - - for (S32 i = 0; i < mNumS; i++) - { - average.add(norm[i + mNumS * (mNumT - 1)]); - } - - // set average - for (S32 i = 0; i < mNumS; i++) - { - norm[i + mNumS * (mNumT - 1)] = average; - } - - } - - - if (wrap_s) - { - for (S32 i = 0; i < mNumT; i++) - { - LLVector4a n; - n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); - norm[mNumS * i] = n; - norm[mNumS * i+mNumS-1] = n; - } - } - - if (wrap_t) - { - for (S32 i = 0; i < mNumS; i++) - { - LLVector4a n; - n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); - norm[i] = n; - norm[mNumS*(mNumT-1)+i] = n; - } - } - - } - - LL_CHECK_MEMORY - - return TRUE; + LLVector4a* output = triangle_normals.mArray; + LLVector4a* end_output = output+count; + + U16* idx = mIndices; + + while (output < end_output) + { + LLVector4a b,v1,v2; + b.load4a((F32*) (pos+idx[0])); + v1.load4a((F32*) (pos+idx[1])); + v2.load4a((F32*) (pos+idx[2])); + + //calculate triangle normal + LLVector4a a; + + a.setSub(b, v1); + b.sub(v2); + + + LLQuad& vector1 = *((LLQuad*) &v1); + LLQuad& vector2 = *((LLQuad*) &v2); + + LLQuad& amQ = *((LLQuad*) &a); + LLQuad& bmQ = *((LLQuad*) &b); + + //v1.setCross3(t,v0); + //setCross3(const LLVector4a& a, const LLVector4a& b) + // Vectors are stored in memory in w, z, y, x order from high to low + // Set vector1 = { a[W], a[X], a[Z], a[Y] } + vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // Set vector2 = { b[W], b[Y], b[X], b[Z] } + vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } + vector2 = _mm_mul_ps( vector1, vector2 ); + // vector3 = { a[W], a[Y], a[X], a[Z] } + amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // vector4 = { b[W], b[X], b[Z], b[Y] } + bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } + vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); + + llassert(v1.isFinite3()); + + v1.store4a((F32*) output); + + + output++; + idx += 3; + } + + idx = mIndices; + + LLVector4a* src = triangle_normals.mArray; + + for (U32 i = 0; i < count; i++) //for each triangle + { + LLVector4a c; + c.load4a((F32*) (src++)); + + LLVector4a* n0p = norm+idx[0]; + LLVector4a* n1p = norm+idx[1]; + LLVector4a* n2p = norm+idx[2]; + + idx += 3; + + LLVector4a n0,n1,n2; + n0.load4a((F32*) n0p); + n1.load4a((F32*) n1p); + n2.load4a((F32*) n2p); + + n0.add(c); + n1.add(c); + n2.add(c); + + llassert(c.isFinite3()); + + //even out quad contributions + switch (i%2+1) + { + case 0: n0.add(c); break; + case 1: n1.add(c); break; + case 2: n2.add(c); break; + }; + + n0.store4a((F32*) n0p); + n1.store4a((F32*) n1p); + n2.store4a((F32*) n2p); + } + + LL_CHECK_MEMORY + + // adjust normals based on wrapping and stitching + + LLVector4a top; + top.setSub(pos[0], pos[mNumS*(mNumT-2)]); + BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); + + top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); + BOOL s_top_converges = (top.dot3(top) < 0.000001f); + + if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes + { + if (volume->getPath().isOpen() == FALSE) + { //wrap normals on T + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges)) + { //wrap normals on S + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (volume->getPathType() == LL_PCODE_PATH_CIRCLE && + ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF)) + { + if (s_bottom_converges) + { //all lower S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i].set(1,0,0); + } + } + + if (s_top_converges) + { //all upper S have same normal + for (S32 i = 0; i < mNumT; i++) + { + norm[mNumS*i+mNumS-1].set(-1,0,0); + } + } + } + } + else // logic for sculpt volumes + { + BOOL average_poles = FALSE; + BOOL wrap_s = FALSE; + BOOL wrap_t = FALSE; + + if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE) + average_poles = TRUE; + + if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) || + (sculpt_stitching == LL_SCULPT_TYPE_TORUS) || + (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER)) + wrap_s = TRUE; + + if (sculpt_stitching == LL_SCULPT_TYPE_TORUS) + wrap_t = TRUE; + + + if (average_poles) + { + // average normals for north pole + + LLVector4a average; + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i] = average; + } + + // average normals for south pole + + average.clear(); + + for (S32 i = 0; i < mNumS; i++) + { + average.add(norm[i + mNumS * (mNumT - 1)]); + } + + // set average + for (S32 i = 0; i < mNumS; i++) + { + norm[i + mNumS * (mNumT - 1)] = average; + } + + } + + + if (wrap_s) + { + for (S32 i = 0; i < mNumT; i++) + { + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; + } + } + + if (wrap_t) + { + for (S32 i = 0; i < mNumS; i++) + { + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; + } + } + + } + + LL_CHECK_MEMORY + + return TRUE; } //adapted from Lengyel, Eric. "Computing Tangent Space Basis Vectors for an Arbitrary Mesh". Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal, const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME //LLVector4a *tan1 = new LLVector4a[vertexCount * 2]; - LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); - // new(tan1) LLVector4a; + LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a)); + // new(tan1) LLVector4a; LLVector4a* tan2 = tan1 + vertexCount; @@ -7129,86 +7129,86 @@ void LLCalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LL U32 i1 = *index_array++; U32 i2 = *index_array++; U32 i3 = *index_array++; - + const LLVector4a& v1 = vertex[i1]; const LLVector4a& v2 = vertex[i2]; const LLVector4a& v3 = vertex[i3]; - + const LLVector2& w1 = texcoord[i1]; const LLVector2& w2 = texcoord[i2]; const LLVector2& w3 = texcoord[i3]; - - const F32* v1ptr = v1.getF32ptr(); - const F32* v2ptr = v2.getF32ptr(); - const F32* v3ptr = v3.getF32ptr(); - + + const F32* v1ptr = v1.getF32ptr(); + const F32* v2ptr = v2.getF32ptr(); + const F32* v3ptr = v3.getF32ptr(); + float x1 = v2ptr[0] - v1ptr[0]; float x2 = v3ptr[0] - v1ptr[0]; float y1 = v2ptr[1] - v1ptr[1]; float y2 = v3ptr[1] - v1ptr[1]; float z1 = v2ptr[2] - v1ptr[2]; float z2 = v3ptr[2] - v1ptr[2]; - + float s1 = w2.mV[0] - w1.mV[0]; float s2 = w3.mV[0] - w1.mV[0]; float t1 = w2.mV[1] - w1.mV[1]; float t2 = w3.mV[1] - w1.mV[1]; - - F32 rd = s1*t2-s2*t1; - - float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) - : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero - - llassert(llfinite(r)); - llassert(!llisnan(r)); - - LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - LLVector4a tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - - tan1[i1].add(sdir); - tan1[i2].add(sdir); - tan1[i3].add(sdir); - - tan2[i1].add(tdir); - tan2[i2].add(tdir); - tan2[i3].add(tdir); - } - + + F32 rd = s1*t2-s2*t1; + + float r = ((rd*rd) > FLT_EPSILON) ? (1.0f / rd) + : ((rd > 0.0f) ? 1024.f : -1024.f); //some made up large ratio for division by zero + + llassert(llfinite(r)); + llassert(!llisnan(r)); + + LLVector4a sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + LLVector4a tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + + tan1[i1].add(sdir); + tan1[i2].add(sdir); + tan1[i3].add(sdir); + + tan2[i1].add(tdir); + tan2[i2].add(tdir); + tan2[i3].add(tdir); + } + for (U32 a = 0; a < vertexCount; a++) { LLVector4a n = normal[a]; - const LLVector4a& t = tan1[a]; + const LLVector4a& t = tan1[a]; - LLVector4a ncrosst; - ncrosst.setCross3(n,t); + LLVector4a ncrosst; + ncrosst.setCross3(n,t); // Gram-Schmidt orthogonalize n.mul(n.dot3(t).getF32()); - LLVector4a tsubn; - tsubn.setSub(t,n); - - if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) - { - tsubn.normalize3fast(); - - // Calculate handedness - F32 handedness = ncrosst.dot3(tan2[a]).getF32() < 0.f ? -1.f : 1.f; - - tsubn.getF32ptr()[3] = handedness; - - tangent[a] = tsubn; - } - else - { //degenerate, make up a value - tangent[a].set(0,0,1,1); - } - } - - ll_aligned_free_16(tan1); + LLVector4a tsubn; + tsubn.setSub(t,n); + + if (tsubn.dot3(tsubn).getF32() > F_APPROXIMATELY_ZERO) + { + tsubn.normalize3fast(); + + // Calculate handedness + F32 handedness = ncrosst.dot3(tan2[a]).getF32() < 0.f ? -1.f : 1.f; + + tsubn.getF32ptr()[3] = handedness; + + tangent[a] = tsubn; + } + else + { //degenerate, make up a value + tangent[a].set(0,0,1,1); + } + } + + ll_aligned_free_16(tan1); } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index ccc0671315..d53ca2a4b3 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1,25 +1,25 @@ -/** +/** * @file llvolume.h * @brief LLVolume base class. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -70,8 +70,8 @@ const S32 MAX_LOD = 3; // These are defined here but are not enforced at this level, // rather they are here for the convenience of code that uses // the LLVolume class. -const F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; -const F32 MIN_VOLUME_PATH_WIDTH = 0.05f; +const F32 MIN_VOLUME_PROFILE_WIDTH = 0.05f; +const F32 MIN_VOLUME_PATH_WIDTH = 0.05f; const F32 CUT_QUANTA = 0.00002f; const F32 SCALE_QUANTA = 0.01f; @@ -85,100 +85,100 @@ const S32 MAX_VOLUME_TRIANGLE_INDICES = 10000; //============================================================================ // useful masks -const LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness -const LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle) -const LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles) -const LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum -const LLPCode LL_PCODE_BASE_MASK = 0x0F; - - // primitive shapes -const LLPCode LL_PCODE_CUBE = 1; -const LLPCode LL_PCODE_PRISM = 2; -const LLPCode LL_PCODE_TETRAHEDRON = 3; -const LLPCode LL_PCODE_PYRAMID = 4; -const LLPCode LL_PCODE_CYLINDER = 5; -const LLPCode LL_PCODE_CONE = 6; -const LLPCode LL_PCODE_SPHERE = 7; -const LLPCode LL_PCODE_TORUS = 8; -const LLPCode LL_PCODE_VOLUME = 9; - - // surfaces -//const LLPCode LL_PCODE_SURFACE_TRIANGLE = 10; -//const LLPCode LL_PCODE_SURFACE_SQUARE = 11; -//const LLPCode LL_PCODE_SURFACE_DISC = 12; - -const LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects) -const LLPCode LL_PCODE_LEGACY = 15; +const LLPCode LL_PCODE_HOLLOW_MASK = 0x80; // has a thickness +const LLPCode LL_PCODE_SEGMENT_MASK = 0x40; // segments (1 angle) +const LLPCode LL_PCODE_PATCH_MASK = 0x20; // segmented segments (2 angles) +const LLPCode LL_PCODE_HEMI_MASK = 0x10; // half-primitives get their own type per PR's dictum +const LLPCode LL_PCODE_BASE_MASK = 0x0F; + + // primitive shapes +const LLPCode LL_PCODE_CUBE = 1; +const LLPCode LL_PCODE_PRISM = 2; +const LLPCode LL_PCODE_TETRAHEDRON = 3; +const LLPCode LL_PCODE_PYRAMID = 4; +const LLPCode LL_PCODE_CYLINDER = 5; +const LLPCode LL_PCODE_CONE = 6; +const LLPCode LL_PCODE_SPHERE = 7; +const LLPCode LL_PCODE_TORUS = 8; +const LLPCode LL_PCODE_VOLUME = 9; + + // surfaces +//const LLPCode LL_PCODE_SURFACE_TRIANGLE = 10; +//const LLPCode LL_PCODE_SURFACE_SQUARE = 11; +//const LLPCode LL_PCODE_SURFACE_DISC = 12; + +const LLPCode LL_PCODE_APP = 14; // App specific pcode (for viewer/sim side only objects) +const LLPCode LL_PCODE_LEGACY = 15; // Pcodes for legacy objects -//const LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR -const LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER -//const LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD -//const LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON -const LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS -const LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees -//const LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE -const LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS -const LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK -//const LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT -//const LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY; -//const LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE -//const LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK -const LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE -const LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE - - // hemis -const LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK; -const LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK; -const LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK; -const LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK; +//const LLPCode LL_PCODE_LEGACY_ATOR = 0x10 | LL_PCODE_LEGACY; // ATOR +const LLPCode LL_PCODE_LEGACY_AVATAR = 0x20 | LL_PCODE_LEGACY; // PLAYER +//const LLPCode LL_PCODE_LEGACY_BIRD = 0x30 | LL_PCODE_LEGACY; // BIRD +//const LLPCode LL_PCODE_LEGACY_DEMON = 0x40 | LL_PCODE_LEGACY; // DEMON +const LLPCode LL_PCODE_LEGACY_GRASS = 0x50 | LL_PCODE_LEGACY; // GRASS +const LLPCode LL_PCODE_TREE_NEW = 0x60 | LL_PCODE_LEGACY; // new trees +//const LLPCode LL_PCODE_LEGACY_ORACLE = 0x70 | LL_PCODE_LEGACY; // ORACLE +const LLPCode LL_PCODE_LEGACY_PART_SYS = 0x80 | LL_PCODE_LEGACY; // PART_SYS +const LLPCode LL_PCODE_LEGACY_ROCK = 0x90 | LL_PCODE_LEGACY; // ROCK +//const LLPCode LL_PCODE_LEGACY_SHOT = 0xA0 | LL_PCODE_LEGACY; // BASIC_SHOT +//const LLPCode LL_PCODE_LEGACY_SHOT_BIG = 0xB0 | LL_PCODE_LEGACY; +//const LLPCode LL_PCODE_LEGACY_SMOKE = 0xC0 | LL_PCODE_LEGACY; // SMOKE +//const LLPCode LL_PCODE_LEGACY_SPARK = 0xD0 | LL_PCODE_LEGACY;// SPARK +const LLPCode LL_PCODE_LEGACY_TEXT_BUBBLE = 0xE0 | LL_PCODE_LEGACY; // TEXTBUBBLE +const LLPCode LL_PCODE_LEGACY_TREE = 0xF0 | LL_PCODE_LEGACY; // TREE + + // hemis +const LLPCode LL_PCODE_CYLINDER_HEMI = LL_PCODE_CYLINDER | LL_PCODE_HEMI_MASK; +const LLPCode LL_PCODE_CONE_HEMI = LL_PCODE_CONE | LL_PCODE_HEMI_MASK; +const LLPCode LL_PCODE_SPHERE_HEMI = LL_PCODE_SPHERE | LL_PCODE_HEMI_MASK; +const LLPCode LL_PCODE_TORUS_HEMI = LL_PCODE_TORUS | LL_PCODE_HEMI_MASK; // Volumes consist of a profile at the base that is swept around // a path to make a volume. // The profile code -const U8 LL_PCODE_PROFILE_MASK = 0x0f; -const U8 LL_PCODE_PROFILE_MIN = 0x00; -const U8 LL_PCODE_PROFILE_CIRCLE = 0x00; -const U8 LL_PCODE_PROFILE_SQUARE = 0x01; -const U8 LL_PCODE_PROFILE_ISOTRI = 0x02; -const U8 LL_PCODE_PROFILE_EQUALTRI = 0x03; -const U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04; -const U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05; -const U8 LL_PCODE_PROFILE_MAX = 0x05; +const U8 LL_PCODE_PROFILE_MASK = 0x0f; +const U8 LL_PCODE_PROFILE_MIN = 0x00; +const U8 LL_PCODE_PROFILE_CIRCLE = 0x00; +const U8 LL_PCODE_PROFILE_SQUARE = 0x01; +const U8 LL_PCODE_PROFILE_ISOTRI = 0x02; +const U8 LL_PCODE_PROFILE_EQUALTRI = 0x03; +const U8 LL_PCODE_PROFILE_RIGHTTRI = 0x04; +const U8 LL_PCODE_PROFILE_CIRCLE_HALF = 0x05; +const U8 LL_PCODE_PROFILE_MAX = 0x05; // Stored in the profile byte -const U8 LL_PCODE_HOLE_MASK = 0xf0; -const U8 LL_PCODE_HOLE_MIN = 0x00; -const U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile -const U8 LL_PCODE_HOLE_CIRCLE = 0x10; -const U8 LL_PCODE_HOLE_SQUARE = 0x20; -const U8 LL_PCODE_HOLE_TRIANGLE = 0x30; -const U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max +const U8 LL_PCODE_HOLE_MASK = 0xf0; +const U8 LL_PCODE_HOLE_MIN = 0x00; +const U8 LL_PCODE_HOLE_SAME = 0x00; // same as outside profile +const U8 LL_PCODE_HOLE_CIRCLE = 0x10; +const U8 LL_PCODE_HOLE_SQUARE = 0x20; +const U8 LL_PCODE_HOLE_TRIANGLE = 0x30; +const U8 LL_PCODE_HOLE_MAX = 0x03; // min/max needs to be >> 4 of real min/max const U8 LL_PCODE_PATH_IGNORE = 0x00; -const U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max +const U8 LL_PCODE_PATH_MIN = 0x01; // min/max needs to be >> 4 of real min/max const U8 LL_PCODE_PATH_LINE = 0x10; const U8 LL_PCODE_PATH_CIRCLE = 0x20; const U8 LL_PCODE_PATH_CIRCLE2 = 0x30; const U8 LL_PCODE_PATH_TEST = 0x40; const U8 LL_PCODE_PATH_FLEXIBLE = 0x80; -const U8 LL_PCODE_PATH_MAX = 0x08; +const U8 LL_PCODE_PATH_MAX = 0x08; //============================================================================ // face identifiers typedef U16 LLFaceID; -const LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0; -const LLFaceID LL_FACE_PATH_END = 0x1 << 1; -const LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2; -const LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3; -const LLFaceID LL_FACE_PROFILE_END = 0x1 << 4; -const LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5; -const LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6; -const LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7; -const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; +const LLFaceID LL_FACE_PATH_BEGIN = 0x1 << 0; +const LLFaceID LL_FACE_PATH_END = 0x1 << 1; +const LLFaceID LL_FACE_INNER_SIDE = 0x1 << 2; +const LLFaceID LL_FACE_PROFILE_BEGIN = 0x1 << 3; +const LLFaceID LL_FACE_PROFILE_END = 0x1 << 4; +const LLFaceID LL_FACE_OUTER_SIDE_0 = 0x1 << 5; +const LLFaceID LL_FACE_OUTER_SIDE_1 = 0x1 << 6; +const LLFaceID LL_FACE_OUTER_SIDE_2 = 0x1 << 7; +const LLFaceID LL_FACE_OUTER_SIDE_3 = 0x1 << 8; //============================================================================ @@ -191,7 +191,7 @@ const U8 LL_SCULPT_TYPE_PLANE = 3; const U8 LL_SCULPT_TYPE_CYLINDER = 4; const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | - LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; + LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; // for value checks, assign new value after adding new types const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH; @@ -207,125 +207,125 @@ extern BOOL gDebugGL; class LLProfileParams { public: - LLProfileParams() - : mCurveType(LL_PCODE_PROFILE_SQUARE), - mBegin(0.f), - mEnd(1.f), - mHollow(0.f), - mCRC(0) - { - } - - LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) - : mCurveType(curve), - mBegin(begin), - mEnd(end), - mHollow(hollow), - mCRC(0) - { - } - - LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow) - { - mCurveType = curve; - F32 temp_f32 = begin * CUT_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mBegin = temp_f32; - temp_f32 = end * CUT_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mEnd = 1.f - temp_f32; - temp_f32 = hollow * HOLLOW_QUANTA; - if (temp_f32 > 1.f) - { - temp_f32 = 1.f; - } - mHollow = temp_f32; - mCRC = 0; - } - - bool operator==(const LLProfileParams ¶ms) const; - bool operator!=(const LLProfileParams ¶ms) const; - bool operator<(const LLProfileParams ¶ms) const; - - void copyParams(const LLProfileParams ¶ms); - - BOOL importFile(LLFILE *fp); - BOOL exportFile(LLFILE *fp) const; - - BOOL importLegacyStream(std::istream& input_stream); - BOOL exportLegacyStream(std::ostream& output_stream) const; - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - const F32& getBegin () const { return mBegin; } - const F32& getEnd () const { return mEnd; } - const F32& getHollow() const { return mHollow; } - const U8& getCurveType () const { return mCurveType; } - - void setCurveType(const U32 type) { mCurveType = type;} - void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;} - void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;} - void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;} - - friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); + LLProfileParams() + : mCurveType(LL_PCODE_PROFILE_SQUARE), + mBegin(0.f), + mEnd(1.f), + mHollow(0.f), + mCRC(0) + { + } + + LLProfileParams(U8 curve, F32 begin, F32 end, F32 hollow) + : mCurveType(curve), + mBegin(begin), + mEnd(end), + mHollow(hollow), + mCRC(0) + { + } + + LLProfileParams(U8 curve, U16 begin, U16 end, U16 hollow) + { + mCurveType = curve; + F32 temp_f32 = begin * CUT_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mBegin = temp_f32; + temp_f32 = end * CUT_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mEnd = 1.f - temp_f32; + temp_f32 = hollow * HOLLOW_QUANTA; + if (temp_f32 > 1.f) + { + temp_f32 = 1.f; + } + mHollow = temp_f32; + mCRC = 0; + } + + bool operator==(const LLProfileParams ¶ms) const; + bool operator!=(const LLProfileParams ¶ms) const; + bool operator<(const LLProfileParams ¶ms) const; + + void copyParams(const LLProfileParams ¶ms); + + BOOL importFile(LLFILE *fp); + BOOL exportFile(LLFILE *fp) const; + + BOOL importLegacyStream(std::istream& input_stream); + BOOL exportLegacyStream(std::ostream& output_stream) const; + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + const F32& getBegin () const { return mBegin; } + const F32& getEnd () const { return mEnd; } + const F32& getHollow() const { return mHollow; } + const U8& getCurveType () const { return mCurveType; } + + void setCurveType(const U32 type) { mCurveType = type;} + void setBegin(const F32 begin) { mBegin = (begin >= 1.0f) ? 0.0f : ((int) (begin * 100000))/100000.0f;} + void setEnd(const F32 end) { mEnd = (end <= 0.0f) ? 1.0f : ((int) (end * 100000))/100000.0f;} + void setHollow(const F32 hollow) { mHollow = ((int) (hollow * 100000))/100000.0f;} + + friend std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params); protected: - // Profile params - U8 mCurveType; - F32 mBegin; - F32 mEnd; - F32 mHollow; + // Profile params + U8 mCurveType; + F32 mBegin; + F32 mEnd; + F32 mHollow; - U32 mCRC; + U32 mCRC; }; inline bool LLProfileParams::operator==(const LLProfileParams ¶ms) const { - return - (getCurveType() == params.getCurveType()) && - (getBegin() == params.getBegin()) && - (getEnd() == params.getEnd()) && - (getHollow() == params.getHollow()); + return + (getCurveType() == params.getCurveType()) && + (getBegin() == params.getBegin()) && + (getEnd() == params.getEnd()) && + (getHollow() == params.getHollow()); } inline bool LLProfileParams::operator!=(const LLProfileParams ¶ms) const { - return - (getCurveType() != params.getCurveType()) || - (getBegin() != params.getBegin()) || - (getEnd() != params.getEnd()) || - (getHollow() != params.getHollow()); + return + (getCurveType() != params.getCurveType()) || + (getBegin() != params.getBegin()) || + (getEnd() != params.getEnd()) || + (getHollow() != params.getHollow()); } inline bool LLProfileParams::operator<(const LLProfileParams ¶ms) const { - if (getCurveType() != params.getCurveType()) - { - return getCurveType() < params.getCurveType(); - } - else - if (getBegin() != params.getBegin()) - { - return getBegin() < params.getBegin(); - } - else - if (getEnd() != params.getEnd()) - { - return getEnd() < params.getEnd(); - } - else - { - return getHollow() < params.getHollow(); - } + if (getCurveType() != params.getCurveType()) + { + return getCurveType() < params.getCurveType(); + } + else + if (getBegin() != params.getBegin()) + { + return getBegin() < params.getBegin(); + } + else + if (getEnd() != params.getEnd()) + { + return getEnd() < params.getEnd(); + } + else + { + return getHollow() < params.getHollow(); + } } #define U8_TO_F32(x) (F32)(*((S8 *)&x)) @@ -333,225 +333,225 @@ inline bool LLProfileParams::operator<(const LLProfileParams ¶ms) const class LLPathParams { public: - LLPathParams() - : - mCurveType(LL_PCODE_PATH_LINE), - mBegin(0.f), - mEnd(1.f), - mScale(1.f,1.f), - mShear(0.f,0.f), - mTwistBegin(0.f), - mTwistEnd(0.f), - mRadiusOffset(0.f), - mTaper(0.f,0.f), - mRevolutions(1.f), - mSkew(0.f), - mCRC(0) - { - } - - LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) - : mCurveType(curve), - mBegin(begin), - mEnd(end), - mScale(scx,scy), - mShear(shx,shy), - mTwistBegin(twistbegin), - mTwistEnd(twistend), - mRadiusOffset(radiusoffset), - mTaper(tx,ty), - mRevolutions(revolutions), - mSkew(skew), - mCRC(0) - { - } - - LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) - { - mCurveType = curve; - mBegin = (F32)(begin * CUT_QUANTA); - mEnd = (F32)(100.f - end) * CUT_QUANTA; - if (mEnd > 1.f) - mEnd = 1.f; - mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); - mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA); - mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA; - mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA; - mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA; - mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA); - mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f; - mSkew = U8_TO_F32(skew) * SCALE_QUANTA; - - mCRC = 0; - } - - bool operator==(const LLPathParams ¶ms) const; - bool operator!=(const LLPathParams ¶ms) const; - bool operator<(const LLPathParams ¶ms) const; - - void copyParams(const LLPathParams ¶ms); - - BOOL importFile(LLFILE *fp); - BOOL exportFile(LLFILE *fp) const; - - BOOL importLegacyStream(std::istream& input_stream); - BOOL exportLegacyStream(std::ostream& output_stream) const; - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - const F32& getBegin() const { return mBegin; } - const F32& getEnd() const { return mEnd; } - const LLVector2 &getScale() const { return mScale; } - const F32& getScaleX() const { return mScale.mV[0]; } - const F32& getScaleY() const { return mScale.mV[1]; } - const LLVector2 getBeginScale() const; - const LLVector2 getEndScale() const; - const LLVector2 &getShear() const { return mShear; } - const F32& getShearX() const { return mShear.mV[0]; } - const F32& getShearY() const { return mShear.mV[1]; } - const U8& getCurveType () const { return mCurveType; } - - const F32& getTwistBegin() const { return mTwistBegin; } - const F32& getTwistEnd() const { return mTwistEnd; } - const F32& getTwist() const { return mTwistEnd; } // deprecated - const F32& getRadiusOffset() const { return mRadiusOffset; } - const LLVector2 &getTaper() const { return mTaper; } - const F32& getTaperX() const { return mTaper.mV[0]; } - const F32& getTaperY() const { return mTaper.mV[1]; } - const F32& getRevolutions() const { return mRevolutions; } - const F32& getSkew() const { return mSkew; } - - void setCurveType(const U8 type) { mCurveType = type; } - void setBegin(const F32 begin) { mBegin = begin; } - void setEnd(const F32 end) { mEnd = end; } - - void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); } - void setScaleX(const F32 v) { mScale.mV[VX] = v; } - void setScaleY(const F32 v) { mScale.mV[VY] = v; } - void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); } - void setShearX(const F32 v) { mShear.mV[VX] = v; } - void setShearY(const F32 v) { mShear.mV[VY] = v; } - - void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; } - void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; } - void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated - void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; } - void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); } - void setTaperX(const F32 v) { mTaper.mV[VX] = v; } - void setTaperY(const F32 v) { mTaper.mV[VY] = v; } - void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; } - void setSkew(const F32 skew) { mSkew = skew; } - - friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params); + LLPathParams() + : + mCurveType(LL_PCODE_PATH_LINE), + mBegin(0.f), + mEnd(1.f), + mScale(1.f,1.f), + mShear(0.f,0.f), + mTwistBegin(0.f), + mTwistEnd(0.f), + mRadiusOffset(0.f), + mTaper(0.f,0.f), + mRevolutions(1.f), + mSkew(0.f), + mCRC(0) + { + } + + LLPathParams(U8 curve, F32 begin, F32 end, F32 scx, F32 scy, F32 shx, F32 shy, F32 twistend, F32 twistbegin, F32 radiusoffset, F32 tx, F32 ty, F32 revolutions, F32 skew) + : mCurveType(curve), + mBegin(begin), + mEnd(end), + mScale(scx,scy), + mShear(shx,shy), + mTwistBegin(twistbegin), + mTwistEnd(twistend), + mRadiusOffset(radiusoffset), + mTaper(tx,ty), + mRevolutions(revolutions), + mSkew(skew), + mCRC(0) + { + } + + LLPathParams(U8 curve, U16 begin, U16 end, U8 scx, U8 scy, U8 shx, U8 shy, U8 twistend, U8 twistbegin, U8 radiusoffset, U8 tx, U8 ty, U8 revolutions, U8 skew) + { + mCurveType = curve; + mBegin = (F32)(begin * CUT_QUANTA); + mEnd = (F32)(100.f - end) * CUT_QUANTA; + if (mEnd > 1.f) + mEnd = 1.f; + mScale.setVec((F32) (200 - scx) * SCALE_QUANTA,(F32) (200 - scy) * SCALE_QUANTA); + mShear.setVec(U8_TO_F32(shx) * SHEAR_QUANTA,U8_TO_F32(shy) * SHEAR_QUANTA); + mTwistBegin = U8_TO_F32(twistbegin) * SCALE_QUANTA; + mTwistEnd = U8_TO_F32(twistend) * SCALE_QUANTA; + mRadiusOffset = U8_TO_F32(radiusoffset) * SCALE_QUANTA; + mTaper.setVec(U8_TO_F32(tx) * TAPER_QUANTA,U8_TO_F32(ty) * TAPER_QUANTA); + mRevolutions = ((F32)revolutions) * REV_QUANTA + 1.0f; + mSkew = U8_TO_F32(skew) * SCALE_QUANTA; + + mCRC = 0; + } + + bool operator==(const LLPathParams ¶ms) const; + bool operator!=(const LLPathParams ¶ms) const; + bool operator<(const LLPathParams ¶ms) const; + + void copyParams(const LLPathParams ¶ms); + + BOOL importFile(LLFILE *fp); + BOOL exportFile(LLFILE *fp) const; + + BOOL importLegacyStream(std::istream& input_stream); + BOOL exportLegacyStream(std::ostream& output_stream) const; + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + const F32& getBegin() const { return mBegin; } + const F32& getEnd() const { return mEnd; } + const LLVector2 &getScale() const { return mScale; } + const F32& getScaleX() const { return mScale.mV[0]; } + const F32& getScaleY() const { return mScale.mV[1]; } + const LLVector2 getBeginScale() const; + const LLVector2 getEndScale() const; + const LLVector2 &getShear() const { return mShear; } + const F32& getShearX() const { return mShear.mV[0]; } + const F32& getShearY() const { return mShear.mV[1]; } + const U8& getCurveType () const { return mCurveType; } + + const F32& getTwistBegin() const { return mTwistBegin; } + const F32& getTwistEnd() const { return mTwistEnd; } + const F32& getTwist() const { return mTwistEnd; } // deprecated + const F32& getRadiusOffset() const { return mRadiusOffset; } + const LLVector2 &getTaper() const { return mTaper; } + const F32& getTaperX() const { return mTaper.mV[0]; } + const F32& getTaperY() const { return mTaper.mV[1]; } + const F32& getRevolutions() const { return mRevolutions; } + const F32& getSkew() const { return mSkew; } + + void setCurveType(const U8 type) { mCurveType = type; } + void setBegin(const F32 begin) { mBegin = begin; } + void setEnd(const F32 end) { mEnd = end; } + + void setScale(const F32 x, const F32 y) { mScale.setVec(x,y); } + void setScaleX(const F32 v) { mScale.mV[VX] = v; } + void setScaleY(const F32 v) { mScale.mV[VY] = v; } + void setShear(const F32 x, const F32 y) { mShear.setVec(x,y); } + void setShearX(const F32 v) { mShear.mV[VX] = v; } + void setShearY(const F32 v) { mShear.mV[VY] = v; } + + void setTwistBegin(const F32 twist_begin) { mTwistBegin = twist_begin; } + void setTwistEnd(const F32 twist_end) { mTwistEnd = twist_end; } + void setTwist(const F32 twist) { setTwistEnd(twist); } // deprecated + void setRadiusOffset(const F32 radius_offset){ mRadiusOffset = radius_offset; } + void setTaper(const F32 x, const F32 y) { mTaper.setVec(x,y); } + void setTaperX(const F32 v) { mTaper.mV[VX] = v; } + void setTaperY(const F32 v) { mTaper.mV[VY] = v; } + void setRevolutions(const F32 revolutions) { mRevolutions = revolutions; } + void setSkew(const F32 skew) { mSkew = skew; } + + friend std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params); protected: - // Path params - U8 mCurveType; - F32 mBegin; - F32 mEnd; - LLVector2 mScale; - LLVector2 mShear; - - F32 mTwistBegin; - F32 mTwistEnd; - F32 mRadiusOffset; - LLVector2 mTaper; - F32 mRevolutions; - F32 mSkew; - - U32 mCRC; + // Path params + U8 mCurveType; + F32 mBegin; + F32 mEnd; + LLVector2 mScale; + LLVector2 mShear; + + F32 mTwistBegin; + F32 mTwistEnd; + F32 mRadiusOffset; + LLVector2 mTaper; + F32 mRevolutions; + F32 mSkew; + + U32 mCRC; }; inline bool LLPathParams::operator==(const LLPathParams ¶ms) const { - return - (getCurveType() == params.getCurveType()) && - (getScale() == params.getScale()) && - (getBegin() == params.getBegin()) && - (getEnd() == params.getEnd()) && - (getShear() == params.getShear()) && - (getTwist() == params.getTwist()) && - (getTwistBegin() == params.getTwistBegin()) && - (getRadiusOffset() == params.getRadiusOffset()) && - (getTaper() == params.getTaper()) && - (getRevolutions() == params.getRevolutions()) && - (getSkew() == params.getSkew()); + return + (getCurveType() == params.getCurveType()) && + (getScale() == params.getScale()) && + (getBegin() == params.getBegin()) && + (getEnd() == params.getEnd()) && + (getShear() == params.getShear()) && + (getTwist() == params.getTwist()) && + (getTwistBegin() == params.getTwistBegin()) && + (getRadiusOffset() == params.getRadiusOffset()) && + (getTaper() == params.getTaper()) && + (getRevolutions() == params.getRevolutions()) && + (getSkew() == params.getSkew()); } inline bool LLPathParams::operator!=(const LLPathParams ¶ms) const { - return - (getCurveType() != params.getCurveType()) || - (getScale() != params.getScale()) || - (getBegin() != params.getBegin()) || - (getEnd() != params.getEnd()) || - (getShear() != params.getShear()) || - (getTwist() != params.getTwist()) || - (getTwistBegin() !=params.getTwistBegin()) || - (getRadiusOffset() != params.getRadiusOffset()) || - (getTaper() != params.getTaper()) || - (getRevolutions() != params.getRevolutions()) || - (getSkew() != params.getSkew()); + return + (getCurveType() != params.getCurveType()) || + (getScale() != params.getScale()) || + (getBegin() != params.getBegin()) || + (getEnd() != params.getEnd()) || + (getShear() != params.getShear()) || + (getTwist() != params.getTwist()) || + (getTwistBegin() !=params.getTwistBegin()) || + (getRadiusOffset() != params.getRadiusOffset()) || + (getTaper() != params.getTaper()) || + (getRevolutions() != params.getRevolutions()) || + (getSkew() != params.getSkew()); } inline bool LLPathParams::operator<(const LLPathParams ¶ms) const { - if( getCurveType() != params.getCurveType()) - { - return getCurveType() < params.getCurveType(); - } - else - if( getScale() != params.getScale()) - { - return getScale() < params.getScale(); - } - else - if( getBegin() != params.getBegin()) - { - return getBegin() < params.getBegin(); - } - else - if( getEnd() != params.getEnd()) - { - return getEnd() < params.getEnd(); - } - else - if( getShear() != params.getShear()) - { - return getShear() < params.getShear(); - } - else - if( getTwist() != params.getTwist()) - { - return getTwist() < params.getTwist(); - } - else - if( getTwistBegin() != params.getTwistBegin()) - { - return getTwistBegin() < params.getTwistBegin(); - } - else - if( getRadiusOffset() != params.getRadiusOffset()) - { - return getRadiusOffset() < params.getRadiusOffset(); - } - else - if( getTaper() != params.getTaper()) - { - return getTaper() < params.getTaper(); - } - else - if( getRevolutions() != params.getRevolutions()) - { - return getRevolutions() < params.getRevolutions(); - } - else - { - return getSkew() < params.getSkew(); - } + if( getCurveType() != params.getCurveType()) + { + return getCurveType() < params.getCurveType(); + } + else + if( getScale() != params.getScale()) + { + return getScale() < params.getScale(); + } + else + if( getBegin() != params.getBegin()) + { + return getBegin() < params.getBegin(); + } + else + if( getEnd() != params.getEnd()) + { + return getEnd() < params.getEnd(); + } + else + if( getShear() != params.getShear()) + { + return getShear() < params.getShear(); + } + else + if( getTwist() != params.getTwist()) + { + return getTwist() < params.getTwist(); + } + else + if( getTwistBegin() != params.getTwistBegin()) + { + return getTwistBegin() < params.getTwistBegin(); + } + else + if( getRadiusOffset() != params.getRadiusOffset()) + { + return getRadiusOffset() < params.getRadiusOffset(); + } + else + if( getTaper() != params.getTaper()) + { + return getTaper() < params.getTaper(); + } + else + if( getRevolutions() != params.getRevolutions()) + { + return getRevolutions() < params.getRevolutions(); + } + else + { + return getSkew() < params.getSkew(); + } } typedef LLVolumeParams* LLVolumeParamsPtr; @@ -560,190 +560,190 @@ typedef const LLVolumeParams* const_LLVolumeParamsPtr; class LLVolumeParams { public: - LLVolumeParams() - : mSculptType(LL_SCULPT_TYPE_NONE) - { - } - - LLVolumeParams(LLProfileParams &profile, LLPathParams &path, - LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE) - : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type) - { - } - - bool operator==(const LLVolumeParams ¶ms) const; - bool operator!=(const LLVolumeParams ¶ms) const; - bool operator<(const LLVolumeParams ¶ms) const; - - - void copyParams(const LLVolumeParams ¶ms); - - const LLProfileParams &getProfileParams() const {return mProfileParams;} - LLProfileParams &getProfileParams() {return mProfileParams;} - const LLPathParams &getPathParams() const {return mPathParams;} - LLPathParams &getPathParams() {return mPathParams;} - - BOOL importFile(LLFILE *fp); - BOOL exportFile(LLFILE *fp) const; - - BOOL importLegacyStream(std::istream& input_stream); - BOOL exportLegacyStream(std::ostream& output_stream) const; - - LLSD sculptAsLLSD() const; - bool sculptFromLLSD(LLSD& sd); - - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - bool setType(U8 profile, U8 path); - - //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1 - //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1 - //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin - //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin - - bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end - bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end - - bool setHollow(const F32 hollow); // range 0 to 1 - bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base - bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement, - bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base - bool setShear(const F32 x, const F32 y); // 0 = no movement - - bool setTwistBegin(const F32 twist_begin); // range -1 to 1 - bool setTwistEnd(const F32 twist_end); // range -1 to 1 - bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated - bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; } - bool setTaperX(const F32 v); // -1 to 1 - bool setTaperY(const F32 v); // -1 to 1 - bool setRevolutions(const F32 revolutions); // 1 to 4 - bool setRadiusOffset(const F32 radius_offset); - bool setSkew(const F32 skew); - bool setSculptID(const LLUUID sculpt_id, U8 sculpt_type); - - static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, - U8 path_curve, F32 path_begin, F32 path_end, - F32 scx, F32 scy, F32 shx, F32 shy, - F32 twistend, F32 twistbegin, F32 radiusoffset, - F32 tx, F32 ty, F32 revolutions, F32 skew); - - const F32& getBeginS() const { return mProfileParams.getBegin(); } - const F32& getBeginT() const { return mPathParams.getBegin(); } - const F32& getEndS() const { return mProfileParams.getEnd(); } - const F32& getEndT() const { return mPathParams.getEnd(); } - - const F32& getHollow() const { return mProfileParams.getHollow(); } - const F32& getTwist() const { return mPathParams.getTwist(); } - const F32& getRatio() const { return mPathParams.getScaleX(); } - const F32& getRatioX() const { return mPathParams.getScaleX(); } - const F32& getRatioY() const { return mPathParams.getScaleY(); } - const F32& getShearX() const { return mPathParams.getShearX(); } - const F32& getShearY() const { return mPathParams.getShearY(); } - - const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); } - const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); } - const F32& getTaper() const { return mPathParams.getTaperX(); } - const F32& getTaperX() const { return mPathParams.getTaperX(); } - const F32& getTaperY() const { return mPathParams.getTaperY(); } - const F32& getRevolutions() const { return mPathParams.getRevolutions(); } - const F32& getSkew() const { return mPathParams.getSkew(); } - const LLUUID& getSculptID() const { return mSculptID; } - const U8& getSculptType() const { return mSculptType; } - bool isSculpt() const; - bool isMeshSculpt() const; - BOOL isConvex() const; - - // 'begin' and 'end' should be in range [0, 1] (they will be clamped) - // (begin, end) = (0, 1) will not change the volume - // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T) - void reduceS(F32 begin, F32 end); - void reduceT(F32 begin, F32 end); - - struct compare - { - bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const - { - return (*first < *second); - } - }; - - friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); - - // debug helper functions - void setCube(); + LLVolumeParams() + : mSculptType(LL_SCULPT_TYPE_NONE) + { + } + + LLVolumeParams(LLProfileParams &profile, LLPathParams &path, + LLUUID sculpt_id = LLUUID::null, U8 sculpt_type = LL_SCULPT_TYPE_NONE) + : mProfileParams(profile), mPathParams(path), mSculptID(sculpt_id), mSculptType(sculpt_type) + { + } + + bool operator==(const LLVolumeParams ¶ms) const; + bool operator!=(const LLVolumeParams ¶ms) const; + bool operator<(const LLVolumeParams ¶ms) const; + + + void copyParams(const LLVolumeParams ¶ms); + + const LLProfileParams &getProfileParams() const {return mProfileParams;} + LLProfileParams &getProfileParams() {return mProfileParams;} + const LLPathParams &getPathParams() const {return mPathParams;} + LLPathParams &getPathParams() {return mPathParams;} + + BOOL importFile(LLFILE *fp); + BOOL exportFile(LLFILE *fp) const; + + BOOL importLegacyStream(std::istream& input_stream); + BOOL exportLegacyStream(std::ostream& output_stream) const; + + LLSD sculptAsLLSD() const; + bool sculptFromLLSD(LLSD& sd); + + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + bool setType(U8 profile, U8 path); + + //void setBeginS(const F32 beginS) { mProfileParams.setBegin(beginS); } // range 0 to 1 + //void setBeginT(const F32 beginT) { mPathParams.setBegin(beginT); } // range 0 to 1 + //void setEndS(const F32 endS) { mProfileParams.setEnd(endS); } // range 0 to 1, must be greater than begin + //void setEndT(const F32 endT) { mPathParams.setEnd(endT); } // range 0 to 1, must be greater than begin + + bool setBeginAndEndS(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end + bool setBeginAndEndT(const F32 begin, const F32 end); // both range from 0 to 1, begin must be less than end + + bool setHollow(const F32 hollow); // range 0 to 1 + bool setRatio(const F32 x) { return setRatio(x,x); } // 0 = point, 1 = same as base + bool setShear(const F32 x) { return setShear(x,x); } // 0 = no movement, + bool setRatio(const F32 x, const F32 y); // 0 = point, 1 = same as base + bool setShear(const F32 x, const F32 y); // 0 = no movement + + bool setTwistBegin(const F32 twist_begin); // range -1 to 1 + bool setTwistEnd(const F32 twist_end); // range -1 to 1 + bool setTwist(const F32 twist) { return setTwistEnd(twist); } // deprecated + bool setTaper(const F32 x, const F32 y) { bool pass_x = setTaperX(x); bool pass_y = setTaperY(y); return pass_x && pass_y; } + bool setTaperX(const F32 v); // -1 to 1 + bool setTaperY(const F32 v); // -1 to 1 + bool setRevolutions(const F32 revolutions); // 1 to 4 + bool setRadiusOffset(const F32 radius_offset); + bool setSkew(const F32 skew); + bool setSculptID(const LLUUID sculpt_id, U8 sculpt_type); + + static bool validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 hollow, + U8 path_curve, F32 path_begin, F32 path_end, + F32 scx, F32 scy, F32 shx, F32 shy, + F32 twistend, F32 twistbegin, F32 radiusoffset, + F32 tx, F32 ty, F32 revolutions, F32 skew); + + const F32& getBeginS() const { return mProfileParams.getBegin(); } + const F32& getBeginT() const { return mPathParams.getBegin(); } + const F32& getEndS() const { return mProfileParams.getEnd(); } + const F32& getEndT() const { return mPathParams.getEnd(); } + + const F32& getHollow() const { return mProfileParams.getHollow(); } + const F32& getTwist() const { return mPathParams.getTwist(); } + const F32& getRatio() const { return mPathParams.getScaleX(); } + const F32& getRatioX() const { return mPathParams.getScaleX(); } + const F32& getRatioY() const { return mPathParams.getScaleY(); } + const F32& getShearX() const { return mPathParams.getShearX(); } + const F32& getShearY() const { return mPathParams.getShearY(); } + + const F32& getTwistBegin()const { return mPathParams.getTwistBegin(); } + const F32& getRadiusOffset() const { return mPathParams.getRadiusOffset(); } + const F32& getTaper() const { return mPathParams.getTaperX(); } + const F32& getTaperX() const { return mPathParams.getTaperX(); } + const F32& getTaperY() const { return mPathParams.getTaperY(); } + const F32& getRevolutions() const { return mPathParams.getRevolutions(); } + const F32& getSkew() const { return mPathParams.getSkew(); } + const LLUUID& getSculptID() const { return mSculptID; } + const U8& getSculptType() const { return mSculptType; } + bool isSculpt() const; + bool isMeshSculpt() const; + BOOL isConvex() const; + + // 'begin' and 'end' should be in range [0, 1] (they will be clamped) + // (begin, end) = (0, 1) will not change the volume + // (begin, end) = (0, 0.5) will reduce the volume to the first half of its profile/path (S/T) + void reduceS(F32 begin, F32 end); + void reduceT(F32 begin, F32 end); + + struct compare + { + bool operator()( const const_LLVolumeParamsPtr& first, const const_LLVolumeParamsPtr& second) const + { + return (*first < *second); + } + }; + + friend std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); + + // debug helper functions + void setCube(); protected: - LLProfileParams mProfileParams; - LLPathParams mPathParams; - LLUUID mSculptID; - U8 mSculptType; + LLProfileParams mProfileParams; + LLPathParams mPathParams; + LLUUID mSculptID; + U8 mSculptType; }; class LLProfile { - friend class LLVolume; + friend class LLVolume; public: - LLProfile() - : mOpen(FALSE), - mConcave(FALSE), - mDirty(TRUE), - mTotalOut(0), - mTotal(2) - { - } - - S32 getTotal() const { return mTotal; } - S32 getTotalOut() const { return mTotalOut; } // Total number of outside points - BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } - BOOL isOpen() const { return mOpen; } - void setDirty() { mDirty = TRUE; } - - static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, - BOOL is_sculpted = FALSE, S32 sculpt_size = 0); - BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, - BOOL is_sculpted = FALSE, S32 sculpt_size = 0); - BOOL isConcave() const { return mConcave; } + LLProfile() + : mOpen(FALSE), + mConcave(FALSE), + mDirty(TRUE), + mTotalOut(0), + mTotal(2) + { + } + + S32 getTotal() const { return mTotal; } + S32 getTotalOut() const { return mTotalOut; } // Total number of outside points + BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } + BOOL isOpen() const { return mOpen; } + void setDirty() { mDirty = TRUE; } + + static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, + BOOL is_sculpted = FALSE, S32 sculpt_size = 0); + BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, + BOOL is_sculpted = FALSE, S32 sculpt_size = 0); + BOOL isConcave() const { return mConcave; } public: - struct Face - { - S32 mIndex; - S32 mCount; - F32 mScaleU; - BOOL mCap; - BOOL mFlat; - LLFaceID mFaceID; - }; - - LLAlignedArray mProfile; - //LLAlignedArray mNormals; - std::vector mFaces; - - //LLAlignedArray mEdgeNormals; - //LLAlignedArray mEdgeCenters; - - friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile); + struct Face + { + S32 mIndex; + S32 mCount; + F32 mScaleU; + BOOL mCap; + BOOL mFlat; + LLFaceID mFaceID; + }; + + LLAlignedArray mProfile; + //LLAlignedArray mNormals; + std::vector mFaces; + + //LLAlignedArray mEdgeNormals; + //LLAlignedArray mEdgeCenters; + + friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile); protected: - ~LLProfile(); + ~LLProfile(); - static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); - void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); + static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); + void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); - Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); - Face* addCap (S16 faceID); - Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat); + Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); + Face* addCap (S16 faceID); + Face* addFace(S32 index, S32 count, F32 scaleU, S16 faceID, BOOL flat); protected: - BOOL mOpen; - BOOL mConcave; - BOOL mDirty; + BOOL mOpen; + BOOL mConcave; + BOOL mDirty; - S32 mTotalOut; - S32 mTotal; + S32 mTotalOut; + S32 mTotal; }; //------------------------------------------------------------------- @@ -753,220 +753,220 @@ protected: class LLPath { public: - class PathPt - { - public: - LLMatrix4a mRot; - LLVector4a mPos; - - LLVector4a mScale; - F32 mTexT; - F32 pad[3]; //for alignment - PathPt() - { - mPos.clear(); - mTexT = 0; - mScale.clear(); - mRot.setRows(LLVector4a(1,0,0,0), - LLVector4a(0,1,0,0), - LLVector4a(0,0,1,0)); - - //distinguished data in the pad for debugging - pad[0] = 3.14159f; - pad[1] = -3.14159f; - pad[2] = 0.585f; - } - }; + class PathPt + { + public: + LLMatrix4a mRot; + LLVector4a mPos; + + LLVector4a mScale; + F32 mTexT; + F32 pad[3]; //for alignment + PathPt() + { + mPos.clear(); + mTexT = 0; + mScale.clear(); + mRot.setRows(LLVector4a(1,0,0,0), + LLVector4a(0,1,0,0), + LLVector4a(0,0,1,0)); + + //distinguished data in the pad for debugging + pad[0] = 3.14159f; + pad[1] = -3.14159f; + pad[2] = 0.585f; + } + }; public: - LLPath() - : mOpen(FALSE), - mTotal(0), - mDirty(TRUE), - mStep(1) - { - } + LLPath() + : mOpen(FALSE), + mTotal(0), + mDirty(TRUE), + mStep(1) + { + } - virtual ~LLPath(); + virtual ~LLPath(); - static S32 getNumPoints(const LLPathParams& params, F32 detail); - static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); + static S32 getNumPoints(const LLPathParams& params, F32 detail); + static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); - void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); - virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, - BOOL is_sculpted = FALSE, S32 sculpt_size = 0); + void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); + virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, + BOOL is_sculpted = FALSE, S32 sculpt_size = 0); - BOOL isOpen() const { return mOpen; } - F32 getStep() const { return mStep; } - void setDirty() { mDirty = TRUE; } + BOOL isOpen() const { return mOpen; } + F32 getStep() const { return mStep; } + void setDirty() { mDirty = TRUE; } - S32 getPathLength() const { return (S32)mPath.size(); } + S32 getPathLength() const { return (S32)mPath.size(); } - void resizePath(S32 length) { mPath.resize(length); } + void resizePath(S32 length) { mPath.resize(length); } - friend std::ostream& operator<<(std::ostream &s, const LLPath &path); + friend std::ostream& operator<<(std::ostream &s, const LLPath &path); public: - LLAlignedArray mPath; + LLAlignedArray mPath; protected: - BOOL mOpen; - S32 mTotal; - BOOL mDirty; - F32 mStep; + BOOL mOpen; + S32 mTotal; + BOOL mDirty; + F32 mStep; }; class LLDynamicPath : public LLPath { public: - LLDynamicPath() : LLPath() { } - /*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, - BOOL is_sculpted = FALSE, S32 sculpt_size = 0); + LLDynamicPath() : LLPath() { } + /*virtual*/ BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, + BOOL is_sculpted = FALSE, S32 sculpt_size = 0); }; // Yet another "face" class - caches volume-specific, but not instance-specific data for faces) class LLVolumeFace { public: - class VertexData - { - enum - { - POSITION = 0, - NORMAL = 1 - }; - - private: - void init(); - public: - VertexData(); - VertexData(const VertexData& rhs); - const VertexData& operator=(const VertexData& rhs); - - ~VertexData(); - LLVector4a& getPosition(); - LLVector4a& getNormal(); - const LLVector4a& getPosition() const; - const LLVector4a& getNormal() const; - void setPosition(const LLVector4a& pos); - void setNormal(const LLVector4a& norm); - - - LLVector2 mTexCoord; - - bool operator<(const VertexData& rhs) const; - bool operator==(const VertexData& rhs) const; - bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; - - private: - LLVector4a* mData; - }; - - LLVolumeFace(); - LLVolumeFace(const LLVolumeFace& src); - LLVolumeFace& operator=(const LLVolumeFace& rhs); - - ~LLVolumeFace(); + class VertexData + { + enum + { + POSITION = 0, + NORMAL = 1 + }; + + private: + void init(); + public: + VertexData(); + VertexData(const VertexData& rhs); + const VertexData& operator=(const VertexData& rhs); + + ~VertexData(); + LLVector4a& getPosition(); + LLVector4a& getNormal(); + const LLVector4a& getPosition() const; + const LLVector4a& getNormal() const; + void setPosition(const LLVector4a& pos); + void setNormal(const LLVector4a& norm); + + + LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; + + private: + LLVector4a* mData; + }; + + LLVolumeFace(); + LLVolumeFace(const LLVolumeFace& src); + LLVolumeFace& operator=(const LLVolumeFace& rhs); + + ~LLVolumeFace(); private: - void freeData(); + void freeData(); public: - BOOL create(LLVolume* volume, BOOL partial_build = FALSE); - void createTangents(); - - void resizeVertices(S32 num_verts); - void allocateTangents(S32 num_verts); - void allocateWeights(S32 num_verts); + BOOL create(LLVolume* volume, BOOL partial_build = FALSE); + void createTangents(); + + void resizeVertices(S32 num_verts); + void allocateTangents(S32 num_verts); + void allocateWeights(S32 num_verts); void allocateJointIndices(S32 num_verts); - void resizeIndices(S32 num_indices); - void fillFromLegacyData(std::vector& v, std::vector& idx); + void resizeIndices(S32 num_indices); + void fillFromLegacyData(std::vector& v, std::vector& idx); - void pushVertex(const VertexData& cv); - void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc); - void pushIndex(const U16& idx); + void pushVertex(const VertexData& cv); + void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc); + void pushIndex(const U16& idx); - void swapData(LLVolumeFace& rhs); + void swapData(LLVolumeFace& rhs); - void getVertexData(U16 indx, LLVolumeFace::VertexData& cv); + void getVertexData(U16 indx, LLVolumeFace::VertexData& cv); - class VertexMapData : public LLVolumeFace::VertexData - { - public: - U16 mIndex; + class VertexMapData : public LLVolumeFace::VertexData + { + public: + U16 mIndex; - bool operator==(const LLVolumeFace::VertexData& rhs) const; + bool operator==(const LLVolumeFace::VertexData& rhs) const; - struct ComparePosition - { - bool operator()(const LLVector3& a, const LLVector3& b) const; - }; + struct ComparePosition + { + bool operator()(const LLVector3& a, const LLVector3& b) const; + }; - typedef std::map, VertexMapData::ComparePosition > PointMap; - }; + typedef std::map, VertexMapData::ComparePosition > PointMap; + }; // Eliminates non unique triangles, takes positions, // normals and texture coordinates into account. void remap(); - void optimize(F32 angle_cutoff = 2.f); - bool cacheOptimize(bool gen_tangents = false); + void optimize(F32 angle_cutoff = 2.f); + bool cacheOptimize(bool gen_tangents = false); - void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); + void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); void destroyOctree(); // Get a reference to the octree, which may be null const LLVolumeOctree* getOctree() const; - enum - { - SINGLE_MASK = 0x0001, - CAP_MASK = 0x0002, - END_MASK = 0x0004, - SIDE_MASK = 0x0008, - INNER_MASK = 0x0010, - OUTER_MASK = 0x0020, - HOLLOW_MASK = 0x0040, - OPEN_MASK = 0x0080, - FLAT_MASK = 0x0100, - TOP_MASK = 0x0200, - BOTTOM_MASK = 0x0400 - }; - + enum + { + SINGLE_MASK = 0x0001, + CAP_MASK = 0x0002, + END_MASK = 0x0004, + SIDE_MASK = 0x0008, + INNER_MASK = 0x0010, + OUTER_MASK = 0x0020, + HOLLOW_MASK = 0x0040, + OPEN_MASK = 0x0080, + FLAT_MASK = 0x0100, + TOP_MASK = 0x0200, + BOTTOM_MASK = 0x0400 + }; + public: - S32 mID; - U32 mTypeMask; - - // Only used for INNER/OUTER faces - S32 mBeginS; - S32 mBeginT; - S32 mNumS; - S32 mNumT; - - LLVector4a* mExtents; //minimum and maximum point of face - LLVector4a* mCenter; - LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. - - S32 mNumVertices; // num vertices == num normals == num texcoords - S32 mNumAllocatedVertices; - S32 mNumIndices; - - LLVector4a* mPositions; // Contains vertices, nortmals and texcoords - LLVector4a* mNormals; // pointer into mPositions - LLVector4a* mTangents; - LLVector2* mTexCoords; // pointer into mPositions - - // mIndices contains mNumIndices amount of elements. - // It contains triangles, each 3 indices describe one triangle. + S32 mID; + U32 mTypeMask; + + // Only used for INNER/OUTER faces + S32 mBeginS; + S32 mBeginT; + S32 mNumS; + S32 mNumT; + + LLVector4a* mExtents; //minimum and maximum point of face + LLVector4a* mCenter; + LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. + + S32 mNumVertices; // num vertices == num normals == num texcoords + S32 mNumAllocatedVertices; + S32 mNumIndices; + + LLVector4a* mPositions; // Contains vertices, nortmals and texcoords + LLVector4a* mNormals; // pointer into mPositions + LLVector4a* mTangents; + LLVector2* mTexCoords; // pointer into mPositions + + // mIndices contains mNumIndices amount of elements. + // It contains triangles, each 3 indices describe one triangle. // If mIndices contains {0, 2, 3, 1, 2, 4}, it means there // are two triangles {0, 2, 3} and {1, 2, 4} with values being // indexes for mPositions/mNormals/mTexCoords - U16* mIndices; + U16* mIndices; - std::vector mEdge; + std::vector mEdge; - //list of skin weights for rigged volumes - // format is mWeights[vertex_index].mV[influence] = . - // mWeights.size() should be empty or match mVertices.size() - LLVector4a* mWeights; + //list of skin weights for rigged volumes + // format is mWeights[vertex_index].mV[influence] = . + // mWeights.size() should be empty or match mVertices.size() + LLVector4a* mWeights; #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS LLVector4a* mJustWeights; @@ -979,8 +979,8 @@ public: // vertices per joint. LLJointRiggingInfoTab mJointRiggingInfoTab; - //whether or not face has been cache optimized - BOOL mOptimized; + //whether or not face has been cache optimized + BOOL mOptimized; // if this is a mesh asset, scale and translation that were applied // when encoding the source mesh into a unit cube @@ -991,154 +991,154 @@ private: LLVolumeOctree* mOctree; LLVolumeTriangle* mOctreeTriangles; - BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE); - BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); - BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE); + BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE); + BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); + BOOL createSide(LLVolume* volume, BOOL partial_build = FALSE); }; class LLVolume : public LLRefCount { - friend class LLVolumeLODGroup; + friend class LLVolumeLODGroup; protected: - virtual ~LLVolume(); // use unref + virtual ~LLVolume(); // use unref public: - typedef std::vector face_list_t; - - struct FaceParams - { - LLFaceID mFaceID; - S32 mBeginS; - S32 mCountS; - S32 mBeginT; - S32 mCountT; - }; - - LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE); - - U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } - U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const; - S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } - F32 getDetail() const { return mDetail; } - F32 getSurfaceArea() const { return mSurfaceArea; } - const LLVolumeParams& getParams() const { return mParams; } - LLVolumeParams getCopyOfParams() const { return mParams; } - const LLProfile& getProfile() const { return *mProfilep; } - LLPath& getPath() const { return *mPathp; } - void resizePath(S32 length); - const LLAlignedArray& getMesh() const { return mMesh; } - const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; } - - - void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } - - void regen(); + typedef std::vector face_list_t; + + struct FaceParams + { + LLFaceID mFaceID; + S32 mBeginS; + S32 mCountS; + S32 mBeginT; + S32 mCountT; + }; + + LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL generate_single_face = FALSE, const BOOL is_unique = FALSE); + + U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } + U8 getPathType() const { return mParams.getPathParams().getCurveType(); } + S32 getNumFaces() const; + S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } + F32 getDetail() const { return mDetail; } + F32 getSurfaceArea() const { return mSurfaceArea; } + const LLVolumeParams& getParams() const { return mParams; } + LLVolumeParams getCopyOfParams() const { return mParams; } + const LLProfile& getProfile() const { return *mProfilep; } + LLPath& getPath() const { return *mPathp; } + void resizePath(S32 length); + const LLAlignedArray& getMesh() const { return mMesh; } + const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; } + + + void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } + + void regen(); void genTangents(S32 face); - BOOL isConvex() const; - BOOL isCap(S32 face); - BOOL isFlat(S32 face); - BOOL isUnique() const { return mUnique; } - - S32 getSculptLevel() const { return mSculptLevel; } - void setSculptLevel(S32 level) { mSculptLevel = level; } - - - static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); - - S32 getNumTriangles(S32* vcount = NULL) const; - - void generateSilhouetteVertices(std::vector &vertices, - std::vector &normals, - const LLVector3& view_vec, - const LLMatrix4& mat, - const LLMatrix3& norm_mat, - S32 face_index); - - //get the face index of the face that intersects with the given line segment at the point - //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. - //Line segment must be in volume space. - S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - LLVector4a* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); - - LLFaceID generateFaceMask(); - - BOOL isFaceMaskValid(LLFaceID face_mask); - static S32 sNumMeshPoints; - - friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); - friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over - // conversion if *(LLVolume*) to LLVolume& - const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE - - LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE - - face_list_t& getVolumeFaces() { return mVolumeFaces; } - - U32 mFaceMask; // bit array of which faces exist in this volume - LLVector3 mLODScaleBias; // vector for biasing LOD based on scale - - void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); - void copyVolumeFaces(const LLVolume* volume); - void copyFacesTo(std::vector &faces) const; - void copyFacesFrom(const std::vector &faces); + BOOL isConvex() const; + BOOL isCap(S32 face); + BOOL isFlat(S32 face); + BOOL isUnique() const { return mUnique; } + + S32 getSculptLevel() const { return mSculptLevel; } + void setSculptLevel(S32 level) { mSculptLevel = level; } + + + static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); + + S32 getNumTriangles(S32* vcount = NULL) const; + + void generateSilhouetteVertices(std::vector &vertices, + std::vector &normals, + const LLVector3& view_vec, + const LLMatrix4& mat, + const LLMatrix3& norm_mat, + S32 face_index); + + //get the face index of the face that intersects with the given line segment at the point + //closest to start. Moves end to the point of intersection. Returns -1 if no intersection. + //Line segment must be in volume space. + S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + LLFaceID generateFaceMask(); + + BOOL isFaceMaskValid(LLFaceID face_mask); + static S32 sNumMeshPoints; + + friend std::ostream& operator<<(std::ostream &s, const LLVolume &volume); + friend std::ostream& operator<<(std::ostream &s, const LLVolume *volumep); // HACK to bypass Windoze confusion over + // conversion if *(LLVolume*) to LLVolume& + const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE + + face_list_t& getVolumeFaces() { return mVolumeFaces; } + + U32 mFaceMask; // bit array of which faces exist in this volume + LLVector3 mLODScaleBias; // vector for biasing LOD based on scale + + void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); + void copyVolumeFaces(const LLVolume* volume); + void copyFacesTo(std::vector &faces) const; + void copyFacesFrom(const std::vector &faces); // use meshoptimizer to optimize index buffer for vertex shader cache // gen_tangents - if true, generate MikkTSpace tangents if needed before optimizing index buffer - bool cacheOptimize(bool gen_tangents = false); + bool cacheOptimize(bool gen_tangents = false); private: - void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); - F32 sculptGetSurfaceArea(); - void sculptGenerateEmptyPlaceholder(); - void sculptGenerateSpherePlaceholder(); - void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t); + void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); + F32 sculptGetSurfaceArea(); + void sculptGenerateEmptyPlaceholder(); + void sculptGenerateSpherePlaceholder(); + void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t); + - protected: - BOOL generate(); - void createVolumeFaces(); + BOOL generate(); + void createVolumeFaces(); public: - bool unpackVolumeFaces(std::istream& is, S32 size); - bool unpackVolumeFaces(U8* in_data, S32 size); + bool unpackVolumeFaces(std::istream& is, S32 size); + bool unpackVolumeFaces(U8* in_data, S32 size); private: - bool unpackVolumeFacesInternal(const LLSD& mdl); + bool unpackVolumeFacesInternal(const LLSD& mdl); public: - virtual void setMeshAssetLoaded(bool loaded); - virtual bool isMeshAssetLoaded(); + virtual void setMeshAssetLoaded(bool loaded); + virtual bool isMeshAssetLoaded(); virtual void setMeshAssetUnavaliable(bool unavaliable); virtual bool isMeshAssetUnavaliable(); protected: - BOOL mUnique; - F32 mDetail; - S32 mSculptLevel; - F32 mSurfaceArea; //unscaled surface area - bool mIsMeshAssetLoaded; + BOOL mUnique; + F32 mDetail; + S32 mSculptLevel; + F32 mSurfaceArea; //unscaled surface area + bool mIsMeshAssetLoaded; bool mIsMeshAssetUnavaliable; - - const LLVolumeParams mParams; - LLPath *mPathp; - LLProfile *mProfilep; - LLAlignedArray mMesh; - - - BOOL mGenerateSingleFace; - face_list_t mVolumeFaces; + + const LLVolumeParams mParams; + LLPath *mPathp; + LLProfile *mProfilep; + LLAlignedArray mMesh; + + + BOOL mGenerateSingleFace; + face_list_t mVolumeFaces; public: - LLVector4a* mHullPoints; - U16* mHullIndices; - S32 mNumHullPoints; - S32 mNumHullIndices; + LLVector4a* mHullPoints; + U16* mHullIndices; + S32 mNumHullPoints; + S32 mNumHullIndices; }; std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); @@ -1150,13 +1150,13 @@ BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, con BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); //BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, -// F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided); +// F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided); BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t); + F32& intersection_a, F32& intersection_b, F32& intersection_t); BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, - F32& intersection_a, F32& intersection_b, F32& intersection_t); - - + F32& intersection_a, F32& intersection_b, F32& intersection_t); + + #endif diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index 95c7cb0b5c..341b9a6465 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvolumeoctree.cpp * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -29,190 +29,190 @@ BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size) { - LLVector4a fAWdU; - LLVector4a dir; - LLVector4a diff; + LLVector4a fAWdU; + LLVector4a dir; + LLVector4a diff; + + dir.setSub(end, start); + dir.mul(0.5f); + + diff.setAdd(end,start); + diff.mul(0.5f); + diff.sub(center); + fAWdU.setAbs(dir); - dir.setSub(end, start); - dir.mul(0.5f); + LLVector4a rhs; + rhs.setAdd(size, fAWdU); - diff.setAdd(end,start); - diff.mul(0.5f); - diff.sub(center); - fAWdU.setAbs(dir); + LLVector4a lhs; + lhs.setAbs(diff); - LLVector4a rhs; - rhs.setAdd(size, fAWdU); + U32 grt = lhs.greaterThan(rhs).getGatheredBits(); - LLVector4a lhs; - lhs.setAbs(diff); + if (grt & 0x7) + { + return false; + } - U32 grt = lhs.greaterThan(rhs).getGatheredBits(); + LLVector4a f; + f.setCross3(dir, diff); + f.setAbs(f); - if (grt & 0x7) - { - return false; - } - - LLVector4a f; - f.setCross3(dir, diff); - f.setAbs(f); + LLVector4a v0, v1; - LLVector4a v0, v1; + v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); + lhs.setMul(v0, v1); - v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); - v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); - lhs.setMul(v0, v1); + v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); + rhs.setMul(v0, v1); + rhs.add(lhs); - v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); - v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); - rhs.setMul(v0, v1); - rhs.add(lhs); - - grt = f.greaterThan(rhs).getGatheredBits(); + grt = f.greaterThan(rhs).getGatheredBits(); - return (grt & 0x7) ? false : true; + return (grt & 0x7) ? false : true; } LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode* node) { - node->addListener(this); + node->addListener(this); } LLVolumeOctreeListener::~LLVolumeOctreeListener() { } - -void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode* parent, + +void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode* parent, LLOctreeNode* child) { - new LLVolumeOctreeListener(child); + new LLVolumeOctreeListener(child); } -LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, +LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLVolumeFace* face, F32* closest_t, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) : mStart(start), - mDir(dir), - mIntersection(intersection), - mTexCoord(tex_coord), - mNormal(normal), - mTangent(tangent), + mDir(dir), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mTangent(tangent), mFace(face), - mClosestT(closest_t), - mHitFace(false) + mClosestT(closest_t), + mHitFace(false) { - mEnd.setAdd(mStart, mDir); + mEnd.setAdd(mStart, mDir); } void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode* node) { - LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); - - if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) - { - node->accept(this); - for (S32 i = 0; i < node->getChildCount(); ++i) - { - traverse(node->getChild(i)); - } - } + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); + + if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) + { + node->accept(this); + for (S32 i = 0; i < node->getChildCount(); ++i) + { + traverse(node->getChild(i)); + } + } } void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode* node) { for (typename LLOctreeNode::const_element_iter iter = - node->getDataBegin(); iter != node->getDataEnd(); ++iter) - { - const LLVolumeTriangle* tri = *iter; - - F32 a, b, t; - - if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], - mStart, mDir, a, b, t)) - { - if ((t >= 0.f) && // if hit is after start - (t <= 1.f) && // and before end - (t < *mClosestT)) // and this hit is closer - { - *mClosestT = t; - mHitFace = true; + node->getDataBegin(); iter != node->getDataEnd(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + F32 a, b, t; + + if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], + mStart, mDir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < *mClosestT)) // and this hit is closer + { + *mClosestT = t; + mHitFace = true; mHitTriangle = tri; - if (mIntersection != NULL) - { - LLVector4a intersect = mDir; - intersect.mul(*mClosestT); - intersect.add(mStart); - *mIntersection = intersect; - } - - U32 idx0 = tri->mIndex[0]; - U32 idx1 = tri->mIndex[1]; - U32 idx2 = tri->mIndex[2]; - - if (mTexCoord != NULL) - { - LLVector2* tc = (LLVector2*) mFace->mTexCoords; - *mTexCoord = ((1.f - a - b) * tc[idx0] + - a * tc[idx1] + - b * tc[idx2]); - - } - - if (mNormal != NULL) - { - LLVector4a* norm = mFace->mNormals; - - LLVector4a n1,n2,n3; - n1 = norm[idx0]; - n1.mul(1.f-a-b); - - n2 = norm[idx1]; - n2.mul(a); - - n3 = norm[idx2]; - n3.mul(b); - - n1.add(n2); - n1.add(n3); - - *mNormal = n1; - } - - if (mTangent != NULL) - { - LLVector4a* tangents = mFace->mTangents; - - LLVector4a t1,t2,t3; - t1 = tangents[idx0]; - t1.mul(1.f-a-b); - - t2 = tangents[idx1]; - t2.mul(a); - - t3 = tangents[idx2]; - t3.mul(b); - - t1.add(t2); - t1.add(t3); - - *mTangent = t1; - } - } - } - } + if (mIntersection != NULL) + { + LLVector4a intersect = mDir; + intersect.mul(*mClosestT); + intersect.add(mStart); + *mIntersection = intersect; + } + + U32 idx0 = tri->mIndex[0]; + U32 idx1 = tri->mIndex[1]; + U32 idx2 = tri->mIndex[2]; + + if (mTexCoord != NULL) + { + LLVector2* tc = (LLVector2*) mFace->mTexCoords; + *mTexCoord = ((1.f - a - b) * tc[idx0] + + a * tc[idx1] + + b * tc[idx2]); + + } + + if (mNormal != NULL) + { + LLVector4a* norm = mFace->mNormals; + + LLVector4a n1,n2,n3; + n1 = norm[idx0]; + n1.mul(1.f-a-b); + + n2 = norm[idx1]; + n2.mul(a); + + n3 = norm[idx2]; + n3.mul(b); + + n1.add(n2); + n1.add(n3); + + *mNormal = n1; + } + + if (mTangent != NULL) + { + LLVector4a* tangents = mFace->mTangents; + + LLVector4a t1,t2,t3; + t1 = tangents[idx0]; + t1.mul(1.f-a-b); + + t2 = tangents[idx1]; + t2.mul(a); + + t3 = tangents[idx2]; + t3.mul(b); + + t1.add(t2); + t1.add(t3); + + *mTangent = t1; + } + } + } + } } const LLVector4a& LLVolumeTriangle::getPositionGroup() const { - return mPositionGroup; + return mPositionGroup; } const F32& LLVolumeTriangle::getBinRadius() const { - return mRadius; + return mRadius; } @@ -220,55 +220,55 @@ const F32& LLVolumeTriangle::getBinRadius() const void LLVolumeOctreeValidate::visit(const LLOctreeNode* branch) { - LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); - //make sure bounds matches extents - LLVector4a& min = node->mExtents[0]; - LLVector4a& max = node->mExtents[1]; + //make sure bounds matches extents + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; - LLVector4a& center = node->mBounds[0]; - LLVector4a& size = node->mBounds[1]; + LLVector4a& center = node->mBounds[0]; + LLVector4a& size = node->mBounds[1]; - LLVector4a test_min, test_max; - test_min.setSub(center, size); - test_max.setAdd(center, size); + LLVector4a test_min, test_max; + test_min.setSub(center, size); + test_max.setAdd(center, size); - if (!test_min.equals3(min, 0.001f) || - !test_max.equals3(max, 0.001f)) - { - LL_ERRS() << "Bad bounding box data found." << LL_ENDL; - } + if (!test_min.equals3(min, 0.001f) || + !test_max.equals3(max, 0.001f)) + { + LL_ERRS() << "Bad bounding box data found." << LL_ENDL; + } - test_min.sub(LLVector4a(0.001f)); - test_max.add(LLVector4a(0.001f)); + test_min.sub(LLVector4a(0.001f)); + test_max.add(LLVector4a(0.001f)); - for (U32 i = 0; i < branch->getChildCount(); ++i) - { - LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + for (U32 i = 0; i < branch->getChildCount(); ++i) + { + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); - //make sure all children fit inside this node - if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || - child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) - { - LL_ERRS() << "Child protrudes from bounding box." << LL_ENDL; - } - } + //make sure all children fit inside this node + if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || + child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) + { + LL_ERRS() << "Child protrudes from bounding box." << LL_ENDL; + } + } - //children fit, check data + //children fit, check data for (typename LLOctreeNode::const_element_iter iter = branch->getDataBegin(); - iter != branch->getDataEnd(); ++iter) - { - const LLVolumeTriangle* tri = *iter; - - //validate triangle - for (U32 i = 0; i < 3; i++) - { - if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || - tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) - { - LL_ERRS() << "Triangle protrudes from node." << LL_ENDL; - } - } - } + iter != branch->getDataEnd(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + //validate triangle + for (U32 i = 0; i < 3; i++) + { + if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || + tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) + { + LL_ERRS() << "Triangle protrudes from node." << LL_ENDL; + } + } + } } diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 0bbb793896..cf176b5afe 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -1,25 +1,25 @@ -/** +/** * @file llvolumeoctree.h * @brief LLVolume octree classes. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -38,41 +38,41 @@ class alignas(16) LLVolumeTriangle : public LLRefCount { LL_ALIGN_NEW public: - LLVolumeTriangle() - { - mBinIndex = -1; - } + LLVolumeTriangle() + { + mBinIndex = -1; + } - LLVolumeTriangle(const LLVolumeTriangle& rhs) - { - *this = rhs; - } + LLVolumeTriangle(const LLVolumeTriangle& rhs) + { + *this = rhs; + } - const LLVolumeTriangle& operator=(const LLVolumeTriangle& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } + const LLVolumeTriangle& operator=(const LLVolumeTriangle& rhs) + { + LL_ERRS() << "Illegal operation!" << LL_ENDL; + return *this; + } - ~LLVolumeTriangle() - { - - } + ~LLVolumeTriangle() + { - LL_ALIGN_16(LLVector4a mPositionGroup); + } - const LLVector4a* mV[3]; - U32 mIndex[3]; + LL_ALIGN_16(LLVector4a mPositionGroup); - F32 mRadius; - mutable S32 mBinIndex; + const LLVector4a* mV[3]; + U32 mIndex[3]; + F32 mRadius; + mutable S32 mBinIndex; - virtual const LLVector4a& getPositionGroup() const; - virtual const F32& getBinRadius() const; - - S32 getBinIndex() const { return mBinIndex; } - void setBinIndex(S32 idx) const { mBinIndex = idx; } + + virtual const LLVector4a& getPositionGroup() const; + virtual const F32& getBinRadius() const; + + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 idx) const { mBinIndex = idx; } }; @@ -82,52 +82,52 @@ class alignas(16) LLVolumeOctreeListener : public LLOctreeListener* node); - ~LLVolumeOctreeListener(); - - LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) - { - *this = rhs; - } - - const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } - - //LISTENER FUNCTIONS + ~LLVolumeOctreeListener(); + + LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) + { + *this = rhs; + } + + const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) + { + LL_ERRS() << "Illegal operation!" << LL_ENDL; + return *this; + } + + //LISTENER FUNCTIONS virtual void handleChildAddition(const LLOctreeNode* parent, LLOctreeNode* child); - virtual void handleStateChange(const LLTreeNode* node) { } + virtual void handleStateChange(const LLTreeNode* node) { } virtual void handleChildRemoval(const LLOctreeNode* parent, const LLOctreeNode* child) { } - virtual void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) { } - virtual void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) { } - virtual void handleDestruction(const LLTreeNode* node) { } - + virtual void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleDestruction(const LLTreeNode* node) { } + public: - LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) - LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children }; class LLOctreeTriangleRayIntersect : public LLOctreeTraveler { public: - LLVector4a mStart; - LLVector4a mDir; - LLVector4a mEnd; - LLVector4a* mIntersection; - LLVector2* mTexCoord; - LLVector4a* mNormal; - LLVector4a* mTangent; - F32* mClosestT; + LLVector4a mStart; + LLVector4a mDir; + LLVector4a mEnd; + LLVector4a* mIntersection; + LLVector2* mTexCoord; + LLVector4a* mNormal; + LLVector4a* mTangent; + F32* mClosestT; LLVolumeFace* mFace; - bool mHitFace; + bool mHitFace; const LLVolumeTriangle* mHitTriangle = nullptr; - LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, LLVolumeFace* face, - F32* closest_t, - LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); + F32* closest_t, + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); void traverse(const LLOctreeNode* node); @@ -217,7 +217,7 @@ public: { new LLVolumeOctreeListener(this); } - + LLVolumeOctree() : LLOctreeRoot(LLVector4a::getZero(), LLVector4a(1.f,1.f,1.f), nullptr), LLRefCount() diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index f5966b71de..6537733ddf 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llpluginprocessparent.cpp * @brief LLPluginProcessParent handles the parent side of the external-process plugin API. * @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ * @endcond @@ -37,10 +37,10 @@ #include "llapr.h" -//virtual +//virtual LLPluginProcessParentOwner::~LLPluginProcessParentOwner() { - + } bool LLPluginProcessParent::sUseReadThread = false; @@ -54,29 +54,29 @@ LLThread *LLPluginProcessParent::sReadThread = NULL; class LLPluginProcessParentPollThread: public LLThread { public: - LLPluginProcessParentPollThread() : - LLThread("LLPluginProcessParentPollThread", gAPRPoolp) - { - } + LLPluginProcessParentPollThread() : + LLThread("LLPluginProcessParentPollThread", gAPRPoolp) + { + } protected: - // Inherited from LLThread - /*virtual*/ void run(void) - { - while(!isQuitting() && LLPluginProcessParent::getUseReadThread()) - { - LLPluginProcessParent::poll(0.1f); - checkPause(); - } - - // Final poll to clean up the pollset, etc. - LLPluginProcessParent::poll(0.0f); - } - - // Inherited from LLThread - /*virtual*/ bool runCondition(void) - { - return(LLPluginProcessParent::canPollThreadRun()); - } + // Inherited from LLThread + /*virtual*/ void run(void) + { + while(!isQuitting() && LLPluginProcessParent::getUseReadThread()) + { + LLPluginProcessParent::poll(0.1f); + checkPause(); + } + + // Final poll to clean up the pollset, etc. + LLPluginProcessParent::poll(0.0f); + } + + // Inherited from LLThread + /*virtual*/ bool runCondition(void) + { + return(LLPluginProcessParent::canPollThreadRun()); + } }; @@ -104,33 +104,33 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner): mIncomingQueueMutex(), pProcessCreationThread(NULL) { - if(!sInstancesMutex) - { - sInstancesMutex = new LLMutex(); - } - - mOwner = owner; - mBoundPort = 0; - mState = STATE_UNINITIALIZED; - mSleepTime = 0.0; - mCPUUsage = 0.0; - mDisableTimeout = false; - mDebug = false; - mBlocked = false; - mPolledInput = false; - mPollFD.client_data = NULL; - - mPluginLaunchTimeout = 60.0f; - mPluginLockupTimeout = 15.0f; - - // Don't start the timer here -- start it when we actually launch the plugin process. - mHeartbeat.stop(); - + if(!sInstancesMutex) + { + sInstancesMutex = new LLMutex(); + } + + mOwner = owner; + mBoundPort = 0; + mState = STATE_UNINITIALIZED; + mSleepTime = 0.0; + mCPUUsage = 0.0; + mDisableTimeout = false; + mDebug = false; + mBlocked = false; + mPolledInput = false; + mPollFD.client_data = NULL; + + mPluginLaunchTimeout = 60.0f; + mPluginLockupTimeout = 15.0f; + + // Don't start the timer here -- start it when we actually launch the plugin process. + mHeartbeat.stop(); + } LLPluginProcessParent::~LLPluginProcessParent() { - LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; + LL_DEBUGS("Plugin") << "destructor" << LL_ENDL; if (pProcessCreationThread) { if (!pProcessCreationThread->isStopped()) @@ -144,20 +144,20 @@ LLPluginProcessParent::~LLPluginProcessParent() pProcessCreationThread = NULL; } - // Destroy any remaining shared memory regions - sharedMemoryRegionsType::iterator iter; - while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end()) - { - // destroy the shared memory region - iter->second->destroy(); - delete iter->second; - iter->second = NULL; - - // and remove it from our map - mSharedMemoryRegions.erase(iter); - } - - LLProcess::kill(mProcess); + // Destroy any remaining shared memory regions + sharedMemoryRegionsType::iterator iter; + while((iter = mSharedMemoryRegions.begin()) != mSharedMemoryRegions.end()) + { + // destroy the shared memory region + iter->second->destroy(); + delete iter->second; + iter->second = NULL; + + // and remove it from our map + mSharedMemoryRegions.erase(iter); + } + + LLProcess::kill(mProcess); if (!LLApp::isQuitting()) { // If we are quitting, the network sockets will already have been destroyed. killSockets(); @@ -227,7 +227,7 @@ void LLPluginProcessParent::requestShutdown() namestream << "LLPluginProcessParentListener" << ++count; //*HACK!*// - // After requestShutdown has been called our previous owner will no longer call + // After requestShutdown has been called our previous owner will no longer call // our idle() method. Tie into the event loop here to do that until we are good // and finished. LL_DEBUGS("LLPluginProcessParent") << "listening on \"mainloop\"" << LL_ENDL; @@ -279,78 +279,78 @@ bool LLPluginProcessParent::wantsPolling() const void LLPluginProcessParent::killSockets(void) { - { - LLMutexLock lock(&mIncomingQueueMutex); - killMessagePipe(); - } + { + LLMutexLock lock(&mIncomingQueueMutex); + killMessagePipe(); + } - mListenSocket.reset(); - mSocket.reset(); + mListenSocket.reset(); + mSocket.reset(); } void LLPluginProcessParent::errorState(void) { - if(mState < STATE_RUNNING) - setState(STATE_LAUNCH_FAILURE); - else - setState(STATE_ERROR); + if(mState < STATE_RUNNING) + setState(STATE_LAUNCH_FAILURE); + else + setState(STATE_ERROR); } void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug) -{ - mProcessParams.executable = launcher_filename; - mProcessParams.cwd = plugin_dir; - mPluginFile = plugin_filename; - mPluginDir = plugin_dir; - mCPUUsage = 0.0f; - mDebug = debug; - setState(STATE_INITIALIZED); +{ + mProcessParams.executable = launcher_filename; + mProcessParams.cwd = plugin_dir; + mPluginFile = plugin_filename; + mPluginDir = plugin_dir; + mCPUUsage = 0.0f; + mDebug = debug; + setState(STATE_INITIALIZED); } bool LLPluginProcessParent::accept() { - bool result = false; - - apr_status_t status = APR_EGENERAL; - apr_socket_t *new_socket = NULL; - - status = apr_socket_accept( - &new_socket, - mListenSocket->getSocket(), - gAPRPoolp); - - - if(status == APR_SUCCESS) - { -// LL_INFOS() << "SUCCESS" << LL_ENDL; - // Success. Create a message pipe on the new socket - - // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor! - apr_pool_t* new_pool = NULL; - status = apr_pool_create(&new_pool, gAPRPoolp); - - mSocket = LLSocket::create(new_socket, new_pool); - new LLPluginMessagePipe(this, mSocket); - - result = true; - } - else if(APR_STATUS_IS_EAGAIN(status)) - { -// LL_INFOS() << "EAGAIN" << LL_ENDL; - - // No incoming connections. This is not an error. - status = APR_SUCCESS; - } - else - { -// LL_INFOS() << "Error:" << LL_ENDL; - ll_apr_warn_status(status); - - // Some other error. - errorState(); - } - - return result; + bool result = false; + + apr_status_t status = APR_EGENERAL; + apr_socket_t *new_socket = NULL; + + status = apr_socket_accept( + &new_socket, + mListenSocket->getSocket(), + gAPRPoolp); + + + if(status == APR_SUCCESS) + { +// LL_INFOS() << "SUCCESS" << LL_ENDL; + // Success. Create a message pipe on the new socket + + // we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor! + apr_pool_t* new_pool = NULL; + status = apr_pool_create(&new_pool, gAPRPoolp); + + mSocket = LLSocket::create(new_socket, new_pool); + new LLPluginMessagePipe(this, mSocket); + + result = true; + } + else if(APR_STATUS_IS_EAGAIN(status)) + { +// LL_INFOS() << "EAGAIN" << LL_ENDL; + + // No incoming connections. This is not an error. + status = APR_SUCCESS; + } + else + { +// LL_INFOS() << "Error:" << LL_ENDL; + ll_apr_warn_status(status); + + // Some other error. + errorState(); + } + + return result; } bool LLPluginProcessParent::createPluginProcess() @@ -384,166 +384,166 @@ void LLPluginProcessParent::clearProcessCreationThread() void LLPluginProcessParent::idle(void) { - bool idle_again; + bool idle_again; - do - { - // process queued messages + do + { + // process queued messages // Inside main thread, it is preferable not to block it on mutex. - bool locked = mIncomingQueueMutex.trylock(); - while(locked && !mIncomingQueue.empty()) - { - LLPluginMessage message = mIncomingQueue.front(); - mIncomingQueue.pop(); - mIncomingQueueMutex.unlock(); - - receiveMessage(message); - - locked = mIncomingQueueMutex.trylock(); - } + bool locked = mIncomingQueueMutex.trylock(); + while(locked && !mIncomingQueue.empty()) + { + LLPluginMessage message = mIncomingQueue.front(); + mIncomingQueue.pop(); + mIncomingQueueMutex.unlock(); + + receiveMessage(message); + + locked = mIncomingQueueMutex.trylock(); + } if (locked) { mIncomingQueueMutex.unlock(); } - - // Give time to network processing - if(mMessagePipe) - { - // Drain any queued outgoing messages - mMessagePipe->pumpOutput(); - - // Only do input processing here if this instance isn't in a pollset. - // If viewer and plugin are both shutting down, don't process further - // input, viewer won't be able to handle it. - if(!mPolledInput - && !(mState >= STATE_GOODBYE && LLApp::isExiting())) - { - mMessagePipe->pumpInput(); - } - } - - if(mState <= STATE_RUNNING) - { - if(APR_STATUS_IS_EOF(mSocketError)) - { - // Plugin socket was closed. This covers both normal plugin termination and plugin crashes. - errorState(); - } - else if(mSocketError != APR_SUCCESS) - { - // The socket is in an error state -- the plugin is gone. - LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; - errorState(); - } - } - - // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). - // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. - // When in doubt, don't do it. - idle_again = false; - switch(mState) - { - case STATE_UNINITIALIZED: - break; - - case STATE_INITIALIZED: - { - - apr_status_t status = APR_SUCCESS; - apr_sockaddr_t* addr = NULL; - mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); - mBoundPort = 0; - - // This code is based on parts of LLSocket::create() in lliosocket.cpp. - - status = apr_sockaddr_info_get( - &addr, - "127.0.0.1", - APR_INET, - 0, // port 0 = ephemeral ("find me a port") - 0, - gAPRPoolp); - - if(ll_apr_warn_status(status)) - { - killSockets(); - errorState(); - break; - } - - // This allows us to reuse the address on quick down/up. This is unlikely to create problems. - ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1)); - - status = apr_socket_bind(mListenSocket->getSocket(), addr); - if(ll_apr_warn_status(status)) - { - killSockets(); - errorState(); - break; - } - - // Get the actual port the socket was bound to - { - apr_sockaddr_t* bound_addr = NULL; - if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket()))) - { - killSockets(); - errorState(); - break; - } - mBoundPort = bound_addr->port; - - if(mBoundPort == 0) - { - LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; - - killSockets(); - errorState(); - break; - } - } - - LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL; - - // Make the listen socket non-blocking - status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1); - if(ll_apr_warn_status(status)) - { - killSockets(); - errorState(); - break; - } - - apr_socket_timeout_set(mListenSocket->getSocket(), 0); - if(ll_apr_warn_status(status)) - { - killSockets(); - errorState(); - break; - } - - // If it's a stream based socket, we need to tell the OS - // to keep a queue of incoming connections for ACCEPT. - status = apr_socket_listen( - mListenSocket->getSocket(), - 10); // FIXME: Magic number for queue size - - if(ll_apr_warn_status(status)) - { - killSockets(); - errorState(); - break; - } - - // If we got here, we're listening. - setState(STATE_LISTENING); - } - break; - - case STATE_LISTENING: - { - // Launch the plugin process. + + // Give time to network processing + if(mMessagePipe) + { + // Drain any queued outgoing messages + mMessagePipe->pumpOutput(); + + // Only do input processing here if this instance isn't in a pollset. + // If viewer and plugin are both shutting down, don't process further + // input, viewer won't be able to handle it. + if(!mPolledInput + && !(mState >= STATE_GOODBYE && LLApp::isExiting())) + { + mMessagePipe->pumpInput(); + } + } + + if(mState <= STATE_RUNNING) + { + if(APR_STATUS_IS_EOF(mSocketError)) + { + // Plugin socket was closed. This covers both normal plugin termination and plugin crashes. + errorState(); + } + else if(mSocketError != APR_SUCCESS) + { + // The socket is in an error state -- the plugin is gone. + LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL; + errorState(); + } + } + + // If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState(). + // USE THIS CAREFULLY, since it can starve other code. Specifically make sure there's no way to get into a closed cycle and never return. + // When in doubt, don't do it. + idle_again = false; + switch(mState) + { + case STATE_UNINITIALIZED: + break; + + case STATE_INITIALIZED: + { + + apr_status_t status = APR_SUCCESS; + apr_sockaddr_t* addr = NULL; + mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); + mBoundPort = 0; + + // This code is based on parts of LLSocket::create() in lliosocket.cpp. + + status = apr_sockaddr_info_get( + &addr, + "127.0.0.1", + APR_INET, + 0, // port 0 = ephemeral ("find me a port") + 0, + gAPRPoolp); + + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // This allows us to reuse the address on quick down/up. This is unlikely to create problems. + ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1)); + + status = apr_socket_bind(mListenSocket->getSocket(), addr); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // Get the actual port the socket was bound to + { + apr_sockaddr_t* bound_addr = NULL; + if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket()))) + { + killSockets(); + errorState(); + break; + } + mBoundPort = bound_addr->port; + + if(mBoundPort == 0) + { + LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL; + + killSockets(); + errorState(); + break; + } + } + + LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL; + + // Make the listen socket non-blocking + status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + apr_socket_timeout_set(mListenSocket->getSocket(), 0); + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // If it's a stream based socket, we need to tell the OS + // to keep a queue of incoming connections for ACCEPT. + status = apr_socket_listen( + mListenSocket->getSocket(), + 10); // FIXME: Magic number for queue size + + if(ll_apr_warn_status(status)) + { + killSockets(); + errorState(); + break; + } + + // If we got here, we're listening. + setState(STATE_LISTENING); + } + break; + + case STATE_LISTENING: + { + // Launch the plugin process. if (mDebug && !pProcessCreationThread) { createPluginProcess(); @@ -566,36 +566,36 @@ void LLPluginProcessParent::idle(void) errorState(); } - - if (mProcess) - { - if(mDebug) - { + + if (mProcess) + { + if(mDebug) + { #if LL_DARWIN - // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue. - - // The command we're constructing would look like this on the command line: - // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' - - LLProcess::Params params; - params.executable = "/usr/bin/osascript"; - params.args.add("-e"); - params.args.add("tell application \"Terminal\""); - params.args.add("-e"); - params.args.add(STRINGIZE("set win to do script \"lldb -pid " - << mProcess->getProcessID() << "\"")); - params.args.add("-e"); - params.args.add("do script \"continue\" in win"); - params.args.add("-e"); - params.args.add("end tell"); - mDebugger = LLProcess::create(params); + // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue. + + // The command we're constructing would look like this on the command line: + // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' + + LLProcess::Params params; + params.executable = "/usr/bin/osascript"; + params.args.add("-e"); + params.args.add("tell application \"Terminal\""); + params.args.add("-e"); + params.args.add(STRINGIZE("set win to do script \"lldb -pid " + << mProcess->getProcessID() << "\"")); + params.args.add("-e"); + params.args.add("do script \"continue\" in win"); + params.args.add("-e"); + params.args.add("end tell"); + mDebugger = LLProcess::create(params); #endif - } - - // This will allow us to time out if the process never starts. - mHeartbeat.start(); - mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout); + } + + // This will allow us to time out if the process never starts. + mHeartbeat.start(); + mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout); // pProcessCreationThread should have stopped by this point, // but check just in case it paused on statistics sync @@ -605,67 +605,67 @@ void LLPluginProcessParent::idle(void) pProcessCreationThread = NULL; } - setState(STATE_LAUNCHED); - } - } - break; - - case STATE_LAUNCHED: - // waiting for the plugin to connect - if(pluginLockedUpOrQuit()) - { - errorState(); - } - else - { - // Check for the incoming connection. - if(accept()) - { - // Stop listening on the server port - mListenSocket.reset(); - setState(STATE_CONNECTED); - } - } - break; - - case STATE_CONNECTED: - // waiting for hello message from the plugin - - if(pluginLockedUpOrQuit()) - { - errorState(); - } - break; - - case STATE_HELLO: - LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL; - - // Send the message to load the plugin - { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); - message.setValue("file", mPluginFile); - message.setValue("dir", mPluginDir); - sendMessage(message); - } - - setState(STATE_LOADING); - break; - - case STATE_LOADING: - // The load_plugin_response message will kick us from here into STATE_RUNNING - if(pluginLockedUpOrQuit()) - { - errorState(); - } - break; - - case STATE_RUNNING: - if(pluginLockedUpOrQuit()) - { - errorState(); - } - break; - + setState(STATE_LAUNCHED); + } + } + break; + + case STATE_LAUNCHED: + // waiting for the plugin to connect + if(pluginLockedUpOrQuit()) + { + errorState(); + } + else + { + // Check for the incoming connection. + if(accept()) + { + // Stop listening on the server port + mListenSocket.reset(); + setState(STATE_CONNECTED); + } + } + break; + + case STATE_CONNECTED: + // waiting for hello message from the plugin + + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + + case STATE_HELLO: + LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL; + + // Send the message to load the plugin + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); + message.setValue("file", mPluginFile); + message.setValue("dir", mPluginDir); + sendMessage(message); + } + + setState(STATE_LOADING); + break; + + case STATE_LOADING: + // The load_plugin_response message will kick us from here into STATE_RUNNING + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + + case STATE_RUNNING: + if(pluginLockedUpOrQuit()) + { + errorState(); + } + break; + case STATE_GOODBYE: { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shutdown_plugin"); @@ -674,292 +674,292 @@ void LLPluginProcessParent::idle(void) setState(STATE_EXITING); break; - case STATE_EXITING: - if (! LLProcess::isRunning(mProcess)) - { - setState(STATE_CLEANUP); - } - else if(pluginLockedUp()) - { - LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL; - errorState(); - } - break; - - case STATE_LAUNCH_FAILURE: - if(mOwner != NULL) - { - mOwner->pluginLaunchFailed(); - } - setState(STATE_CLEANUP); - break; - - case STATE_ERROR: - if(mOwner != NULL) - { - mOwner->pluginDied(); - } - setState(STATE_CLEANUP); - break; - - case STATE_CLEANUP: - LLProcess::kill(mProcess); - killSockets(); - setState(STATE_DONE); + case STATE_EXITING: + if (! LLProcess::isRunning(mProcess)) + { + setState(STATE_CLEANUP); + } + else if(pluginLockedUp()) + { + LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL; + errorState(); + } + break; + + case STATE_LAUNCH_FAILURE: + if(mOwner != NULL) + { + mOwner->pluginLaunchFailed(); + } + setState(STATE_CLEANUP); + break; + + case STATE_ERROR: + if(mOwner != NULL) + { + mOwner->pluginDied(); + } + setState(STATE_CLEANUP); + break; + + case STATE_CLEANUP: + LLProcess::kill(mProcess); + killSockets(); + setState(STATE_DONE); dirtyPollSet(); clearProcessCreationThread(); - break; - - case STATE_DONE: - // just sit here. - break; - } - - } while (idle_again); + break; + + case STATE_DONE: + // just sit here. + break; + } + + } while (idle_again); } bool LLPluginProcessParent::isLoading(void) { - bool result = false; - - if(mState <= STATE_LOADING) - result = true; - - return result; + bool result = false; + + if(mState <= STATE_LOADING) + result = true; + + return result; } bool LLPluginProcessParent::isRunning(void) { - bool result = false; - - if(mState == STATE_RUNNING) - result = true; - - return result; + bool result = false; + + if(mState == STATE_RUNNING) + result = true; + + return result; } bool LLPluginProcessParent::isDone(void) { - bool result = false; - - if(mState == STATE_DONE) - result = true; - - return result; + bool result = false; + + if(mState == STATE_DONE) + result = true; + + return result; } void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send) { - if(force_send || (sleep_time != mSleepTime)) - { - // Cache the time locally - mSleepTime = sleep_time; - - if(canSendMessage()) - { - // and send to the plugin. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time"); - message.setValueReal("time", mSleepTime); - sendMessage(message); - } - else - { - // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later. - } - } + if(force_send || (sleep_time != mSleepTime)) + { + // Cache the time locally + mSleepTime = sleep_time; + + if(canSendMessage()) + { + // and send to the plugin. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "sleep_time"); + message.setValueReal("time", mSleepTime); + sendMessage(message); + } + else + { + // Too early to send -- the load_plugin_response message will trigger us to send mSleepTime later. + } + } } void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { - if(message.hasValue("blocking_response")) - { - mBlocked = false; - - // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. - mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); - } - - std::string buffer = message.generate(); - LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; - writeMessageRaw(buffer); - - // Try to send message immediately. - if(mMessagePipe) - { - mMessagePipe->pumpOutput(); - } + if(message.hasValue("blocking_response")) + { + mBlocked = false; + + // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + } + + std::string buffer = message.generate(); + LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; + writeMessageRaw(buffer); + + // Try to send message immediately. + if(mMessagePipe) + { + mMessagePipe->pumpOutput(); + } } -//virtual +//virtual void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) { - bool update_pollset = false; - - if(mMessagePipe) - { - // Unsetting an existing message pipe -- remove from the pollset - mPollFD.client_data = NULL; - - // pollset needs an update - update_pollset = true; - } - if(message_pipe != NULL) - { - // Set up the apr_pollfd_t - mPollFD.p = gAPRPoolp; - mPollFD.desc_type = APR_POLL_SOCKET; - mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; - mPollFD.rtnevents = 0; - mPollFD.desc.s = mSocket->getSocket(); - mPollFD.client_data = (void*)this; - - // pollset needs an update - update_pollset = true; - } - - mMessagePipe = message_pipe; - - if(update_pollset) - { - dirtyPollSet(); - } + bool update_pollset = false; + + if(mMessagePipe) + { + // Unsetting an existing message pipe -- remove from the pollset + mPollFD.client_data = NULL; + + // pollset needs an update + update_pollset = true; + } + if(message_pipe != NULL) + { + // Set up the apr_pollfd_t + mPollFD.p = gAPRPoolp; + mPollFD.desc_type = APR_POLL_SOCKET; + mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP; + mPollFD.rtnevents = 0; + mPollFD.desc.s = mSocket->getSocket(); + mPollFD.client_data = (void*)this; + + // pollset needs an update + update_pollset = true; + } + + mMessagePipe = message_pipe; + + if(update_pollset) + { + dirtyPollSet(); + } } -//static +//static void LLPluginProcessParent::dirtyPollSet() { - sPollsetNeedsRebuild = true; - - if(sReadThread) - { - LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL; - sReadThread->unpause(); - } + sPollsetNeedsRebuild = true; + + if(sReadThread) + { + LL_DEBUGS("PluginPoll") << "unpausing read thread " << LL_ENDL; + sReadThread->unpause(); + } } void LLPluginProcessParent::updatePollset() { - if(!sInstancesMutex) - { - // No instances have been created yet. There's no work to do. - return; - } - - LLMutexLock lock(sInstancesMutex); - - if(sPollSet) - { - LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL; - // delete the existing pollset. - apr_pollset_destroy(sPollSet); - sPollSet = NULL; - } - + if(!sInstancesMutex) + { + // No instances have been created yet. There's no work to do. + return; + } + + LLMutexLock lock(sInstancesMutex); + + if(sPollSet) + { + LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL; + // delete the existing pollset. + apr_pollset_destroy(sPollSet); + sPollSet = NULL; + } + mapInstances_t::iterator iter; - int count = 0; - - // Count the number of instances that want to be in the pollset - for(iter = sInstances.begin(); iter != sInstances.end(); iter++) - { - (*iter).second->mPolledInput = false; + int count = 0; + + // Count the number of instances that want to be in the pollset + for(iter = sInstances.begin(); iter != sInstances.end(); iter++) + { + (*iter).second->mPolledInput = false; if ((*iter).second->wantsPolling()) - { - // This instance has a socket that needs to be polled. - ++count; - } - } - - if(sUseReadThread && sReadThread && !sReadThread->isQuitting()) - { - if(!sPollSet && (count > 0)) - { + { + // This instance has a socket that needs to be polled. + ++count; + } + } + + if(sUseReadThread && sReadThread && !sReadThread->isQuitting()) + { + if(!sPollSet && (count > 0)) + { #ifdef APR_POLLSET_NOCOPY - // The pollset doesn't exist yet. Create it now. - apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); - if(status != APR_SUCCESS) - { + // The pollset doesn't exist yet. Create it now. + apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY); + if(status != APR_SUCCESS) + { #endif // APR_POLLSET_NOCOPY - LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; - sPollSet = NULL; + LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL; + sPollSet = NULL; #ifdef APR_POLLSET_NOCOPY - } - else - { - LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL; - - // Pollset was created, add all instances to it. - for(iter = sInstances.begin(); iter != sInstances.end(); iter++) - { + } + else + { + LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL; + + // Pollset was created, add all instances to it. + for(iter = sInstances.begin(); iter != sInstances.end(); iter++) + { if ((*iter).second->wantsPolling()) - { - status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD)); - if(status == APR_SUCCESS) - { - (*iter).second->mPolledInput = true; - } - else - { - LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL; - } - } - } - } + { + status = apr_pollset_add(sPollSet, &((*iter).second->mPollFD)); + if(status == APR_SUCCESS) + { + (*iter).second->mPolledInput = true; + } + else + { + LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL; + } + } + } + } #endif // APR_POLLSET_NOCOPY - } - } + } + } } void LLPluginProcessParent::setUseReadThread(bool use_read_thread) { - if(sUseReadThread != use_read_thread) - { - sUseReadThread = use_read_thread; - - if(sUseReadThread) - { - if(!sReadThread) - { - // start up the read thread - LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL; - - // make sure the pollset gets rebuilt. - sPollsetNeedsRebuild = true; - - sReadThread = new LLPluginProcessParentPollThread; - sReadThread->start(); - } - } - else - { - if(sReadThread) - { - // shut down the read thread - LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL; - delete sReadThread; - sReadThread = NULL; - } - } - - } + if(sUseReadThread != use_read_thread) + { + sUseReadThread = use_read_thread; + + if(sUseReadThread) + { + if(!sReadThread) + { + // start up the read thread + LL_INFOS("PluginPoll") << "creating read thread " << LL_ENDL; + + // make sure the pollset gets rebuilt. + sPollsetNeedsRebuild = true; + + sReadThread = new LLPluginProcessParentPollThread; + sReadThread->start(); + } + } + else + { + if(sReadThread) + { + // shut down the read thread + LL_INFOS("PluginPoll") << "destroying read thread " << LL_ENDL; + delete sReadThread; + sReadThread = NULL; + } + } + + } } void LLPluginProcessParent::poll(F64 timeout) { - if(sPollsetNeedsRebuild || !sUseReadThread) - { - sPollsetNeedsRebuild = false; - updatePollset(); - } - - if(sPollSet) - { - apr_status_t status; - apr_int32_t count; - const apr_pollfd_t *descriptors; - status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors); - if(status == APR_SUCCESS) - { - // One or more of the descriptors signalled. Call them. + if(sPollsetNeedsRebuild || !sUseReadThread) + { + sPollsetNeedsRebuild = false; + updatePollset(); + } + + if(sPollSet) + { + apr_status_t status; + apr_int32_t count; + const apr_pollfd_t *descriptors; + status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors); + if(status == APR_SUCCESS) + { + // One or more of the descriptors signalled. Call them. for (int i = 0; i < count; i++) { void *thatId = descriptors[i].client_data; @@ -981,23 +981,23 @@ void LLPluginProcessParent::poll(F64 timeout) that->mIncomingQueueMutex.unlock(); } - } - } - else if(APR_STATUS_IS_TIMEUP(status)) - { - // timed out with no incoming data. Just return. - } - else if(status == EBADF) - { - // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. - // The pollset has been or will be recreated, so just return. - LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; - } - else if(status != APR_SUCCESS) - { - LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; - } - } + } + } + else if(APR_STATUS_IS_TIMEUP(status)) + { + // timed out with no incoming data. Just return. + } + else if(status == EBADF) + { + // This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed. + // The pollset has been or will be recreated, so just return. + LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL; + } + else if(status != APR_SUCCESS) + { + LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL; + } + } // Remove instances in the done state from the sInstances map. mapInstances_t::iterator itClean = sInstances.begin(); @@ -1012,293 +1012,293 @@ void LLPluginProcessParent::poll(F64 timeout) void LLPluginProcessParent::servicePoll() { - bool result = true; - - // poll signalled on this object's socket. Try to process incoming messages. - if(mMessagePipe) - { - result = mMessagePipe->pumpInput(0.0f); - } - - if(!result) - { - // If we got a read error on input, remove this pipe from the pollset - apr_pollset_remove(sPollSet, &mPollFD); - - // and tell the code not to re-add it - mPollFD.client_data = NULL; - } + bool result = true; + + // poll signalled on this object's socket. Try to process incoming messages. + if(mMessagePipe) + { + result = mMessagePipe->pumpInput(0.0f); + } + + if(!result) + { + // If we got a read error on input, remove this pipe from the pollset + apr_pollset_remove(sPollSet, &mPollFD); + + // and tell the code not to re-add it + mPollFD.client_data = NULL; + } } void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { - LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; - - LLPluginMessage parsed; - if(LLSDParser::PARSE_FAILURE != parsed.parse(message)) - { - if(parsed.hasValue("blocking_request")) - { - mBlocked = true; - } - - if(mPolledInput) - { - // This is being called on the polling thread -- only do minimal processing/queueing. - receiveMessageEarly(parsed); - } - else - { - // This is not being called on the polling thread -- do full message processing at this time. - receiveMessage(parsed); - } - } + LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; + + LLPluginMessage parsed; + if(LLSDParser::PARSE_FAILURE != parsed.parse(message)) + { + if(parsed.hasValue("blocking_request")) + { + mBlocked = true; + } + + if(mPolledInput) + { + // This is being called on the polling thread -- only do minimal processing/queueing. + receiveMessageEarly(parsed); + } + else + { + // This is not being called on the polling thread -- do full message processing at this time. + receiveMessage(parsed); + } + } } void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) { - // NOTE: this function will be called from the polling thread. It will be called with mIncomingQueueMutex _already locked_. - - bool handled = false; - - std::string message_class = message.getClass(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) - { - // no internal messages need to be handled early. - } - else - { - // Call out to the owner and see if they to reply - // TODO: Should this only happen when blocked? - if(mOwner != NULL) - { - handled = mOwner->receivePluginMessageEarly(message); - } - } - - if(!handled) - { - // any message that wasn't handled early needs to be queued. - mIncomingQueue.push(message); - } + // NOTE: this function will be called from the polling thread. It will be called with mIncomingQueueMutex _already locked_. + + bool handled = false; + + std::string message_class = message.getClass(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + // no internal messages need to be handled early. + } + else + { + // Call out to the owner and see if they to reply + // TODO: Should this only happen when blocked? + if(mOwner != NULL) + { + handled = mOwner->receivePluginMessageEarly(message); + } + } + + if(!handled) + { + // any message that wasn't handled early needs to be queued. + mIncomingQueue.push(message); + } } void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) { - std::string message_class = message.getClass(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) - { - // internal messages should be handled here - std::string message_name = message.getName(); - if(message_name == "hello") - { - if(mState == STATE_CONNECTED) - { - // Plugin host has launched. Tell it which plugin to load. - setState(STATE_HELLO); - } - else - { - LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL; - errorState(); - } - - } - else if(message_name == "load_plugin_response") - { - if(mState == STATE_LOADING) - { - // Plugin has been loaded. - - mPluginVersionString = message.getValue("plugin_version"); - LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL; - - // Check which message classes/versions the plugin supports. - // TODO: check against current versions - // TODO: kill plugin on major mismatches? - mMessageClassVersions = message.getValueLLSD("versions"); - LLSD::map_iterator iter; - for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++) - { - LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL; - } - - // Send initial sleep time - llassert_always(mSleepTime != 0.f); - setSleepTime(mSleepTime, true); - - setState(STATE_RUNNING); - } - else - { - LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL; - errorState(); - } - } - else if(message_name == "heartbeat") - { - // this resets our timer. - mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); - - mCPUUsage = message.getValueReal("cpu_usage"); - - LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; - - } - else if(message_name == "shm_add_response") - { - // Nothing to do here. - } - else if(message_name == "shm_remove_response") - { - std::string name = message.getValue("name"); - sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - - if(iter != mSharedMemoryRegions.end()) - { - // destroy the shared memory region - iter->second->destroy(); - delete iter->second; - iter->second = NULL; - - // and remove it from our map - mSharedMemoryRegions.erase(iter); - } - } - else - { - LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL; - } - } - else - { - if(mOwner != NULL) - { - mOwner->receivePluginMessage(message); - } - } + std::string message_class = message.getClass(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + // internal messages should be handled here + std::string message_name = message.getName(); + if(message_name == "hello") + { + if(mState == STATE_CONNECTED) + { + // Plugin host has launched. Tell it which plugin to load. + setState(STATE_HELLO); + } + else + { + LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL; + errorState(); + } + + } + else if(message_name == "load_plugin_response") + { + if(mState == STATE_LOADING) + { + // Plugin has been loaded. + + mPluginVersionString = message.getValue("plugin_version"); + LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL; + + // Check which message classes/versions the plugin supports. + // TODO: check against current versions + // TODO: kill plugin on major mismatches? + mMessageClassVersions = message.getValueLLSD("versions"); + LLSD::map_iterator iter; + for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++) + { + LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL; + } + + // Send initial sleep time + llassert_always(mSleepTime != 0.f); + setSleepTime(mSleepTime, true); + + setState(STATE_RUNNING); + } + else + { + LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL; + errorState(); + } + } + else if(message_name == "heartbeat") + { + // this resets our timer. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + + mCPUUsage = message.getValueReal("cpu_usage"); + + LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; + + } + else if(message_name == "shm_add_response") + { + // Nothing to do here. + } + else if(message_name == "shm_remove_response") + { + std::string name = message.getValue("name"); + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + + if(iter != mSharedMemoryRegions.end()) + { + // destroy the shared memory region + iter->second->destroy(); + delete iter->second; + iter->second = NULL; + + // and remove it from our map + mSharedMemoryRegions.erase(iter); + } + } + else + { + LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL; + } + } + else + { + if(mOwner != NULL) + { + mOwner->receivePluginMessage(message); + } + } } std::string LLPluginProcessParent::addSharedMemory(size_t size) { - std::string name; - - LLPluginSharedMemory *region = new LLPluginSharedMemory; - - // This is a new region - if(region->create(size)) - { - name = region->getName(); - - mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add"); - message.setValue("name", name); - message.setValueS32("size", (S32)size); - sendMessage(message); - } - else - { - LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; - - // Don't leak - delete region; - } - - return name; + std::string name; + + LLPluginSharedMemory *region = new LLPluginSharedMemory; + + // This is a new region + if(region->create(size)) + { + name = region->getName(); + + mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region)); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add"); + message.setValue("name", name); + message.setValueS32("size", (S32)size); + sendMessage(message); + } + else + { + LL_WARNS("Plugin") << "Couldn't create a shared memory segment!" << LL_ENDL; + + // Don't leak + delete region; + } + + return name; } void LLPluginProcessParent::removeSharedMemory(const std::string &name) { - sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - - if(iter != mSharedMemoryRegions.end()) - { - // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove"); - message.setValue("name", name); - sendMessage(message); - } - else - { - LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL; - } + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + + if(iter != mSharedMemoryRegions.end()) + { + // This segment exists. Send the message to the child to unmap it. The response will cause the parent to unmap our end. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove"); + message.setValue("name", name); + sendMessage(message); + } + else + { + LL_WARNS("Plugin") << "Request to remove an unknown shared memory segment." << LL_ENDL; + } } size_t LLPluginProcessParent::getSharedMemorySize(const std::string &name) { - size_t result = 0; - - sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - if(iter != mSharedMemoryRegions.end()) - { - result = iter->second->getSize(); - } - - return result; + size_t result = 0; + + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + result = iter->second->getSize(); + } + + return result; } void *LLPluginProcessParent::getSharedMemoryAddress(const std::string &name) { - void *result = NULL; - - sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); - if(iter != mSharedMemoryRegions.end()) - { - result = iter->second->getMappedAddress(); - } - - return result; + void *result = NULL; + + sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name); + if(iter != mSharedMemoryRegions.end()) + { + result = iter->second->getMappedAddress(); + } + + return result; } std::string LLPluginProcessParent::getMessageClassVersion(const std::string &message_class) { - std::string result; - - if(mMessageClassVersions.has(message_class)) - { - result = mMessageClassVersions[message_class].asString(); - } - - return result; + std::string result; + + if(mMessageClassVersions.has(message_class)) + { + result = mMessageClassVersions[message_class].asString(); + } + + return result; } std::string LLPluginProcessParent::getPluginVersion(void) { - return mPluginVersionString; + return mPluginVersionString; } void LLPluginProcessParent::setState(EState state) { - LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; - mState = state; + LL_DEBUGS("Plugin") << "setting state to " << state << LL_ENDL; + mState = state; }; bool LLPluginProcessParent::pluginLockedUpOrQuit() { - bool result = false; - - if (! LLProcess::isRunning(mProcess)) - { - LL_WARNS("Plugin") << "child exited" << LL_ENDL; - result = true; - } - else if(pluginLockedUp()) - { - LL_WARNS("Plugin") << "timeout" << LL_ENDL; - result = true; - } - - return result; + bool result = false; + + if (! LLProcess::isRunning(mProcess)) + { + LL_WARNS("Plugin") << "child exited" << LL_ENDL; + result = true; + } + else if(pluginLockedUp()) + { + LL_WARNS("Plugin") << "timeout" << LL_ENDL; + result = true; + } + + return result; } bool LLPluginProcessParent::pluginLockedUp() { - if(mDisableTimeout || mDebug || mBlocked) - { - // Never time out a plugin process in these cases. - return false; - } - - // If the timer is running and has expired, the plugin has locked up. - return (mHeartbeat.getStarted() && mHeartbeat.hasExpired()); + if(mDisableTimeout || mDebug || mBlocked) + { + // Never time out a plugin process in these cases. + return false; + } + + // If the timer is running and has expired, the plugin has locked up. + return (mHeartbeat.getStarted() && mHeartbeat.hasExpired()); } diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 53d09df618..088d3d1339 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llprimitive.cpp * @brief LLPrimitive base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -57,9 +57,9 @@ const F32 OBJECT_TWIST_INC = 18.f; // This is used for linear paths, // since twist is used in a slightly different manner. -const F32 OBJECT_TWIST_LINEAR_MIN = -180.f; -const F32 OBJECT_TWIST_LINEAR_MAX = 180.f; -const F32 OBJECT_TWIST_LINEAR_INC = 9.f; +const F32 OBJECT_TWIST_LINEAR_MIN = -180.f; +const F32 OBJECT_TWIST_LINEAR_MAX = 180.f; +const F32 OBJECT_TWIST_LINEAR_INC = 9.f; const F32 OBJECT_MIN_HOLE_SIZE = 0.05f; const F32 OBJECT_MAX_HOLE_SIZE_X = 1.0f; @@ -94,7 +94,7 @@ 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; -const F32 FLEXIBLE_OBJECT_MAX_TENSION = 10.0f; +const F32 FLEXIBLE_OBJECT_MAX_TENSION = 10.0f; // "Drag" => [0,10], increments of 0.1 const F32 FLEXIBLE_OBJECT_MIN_AIR_FRICTION = 0.0f; @@ -112,7 +112,7 @@ const F32 FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY = 0.0f; const F32 FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY = 10.0f; // I'll explain later... -const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE = 0.99f; +const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE = 0.99f; const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f; const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE; @@ -121,9 +121,9 @@ const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e"; // Texture rotations are sent over the wire as a S16. This is used to scale the actual float -// value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it +// value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it // can't be divided by 2. See DEV-19108 -const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000); +const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000); struct material_id_type // originally from llrendermaterialtable { @@ -154,7 +154,7 @@ struct material_id_type // originally from llrendermaterialtable const U8 material_id_type::s_null_id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -//static +//static // LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global // TODO -- eliminate this global from the codebase! LLVolumeMgr* LLPrimitive::sVolumeManager = NULL; @@ -162,61 +162,61 @@ LLVolumeMgr* LLPrimitive::sVolumeManager = NULL; // static void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager ) { - if ( !volume_manager || sVolumeManager ) - { - LL_ERRS() << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << LL_ENDL; - } - sVolumeManager = volume_manager; + if ( !volume_manager || sVolumeManager ) + { + LL_ERRS() << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << LL_ENDL; + } + sVolumeManager = volume_manager; } // static bool LLPrimitive::cleanupVolumeManager() { - BOOL res = FALSE; - if (sVolumeManager) - { - res = sVolumeManager->cleanup(); - delete sVolumeManager; - sVolumeManager = NULL; - } - return res; + BOOL res = FALSE; + if (sVolumeManager) + { + res = sVolumeManager->cleanup(); + delete sVolumeManager; + sVolumeManager = NULL; + } + return res; } //=============================================================== LLPrimitive::LLPrimitive() -: mTextureList(), - mNumTEs(0), - mMiscFlags(0), - mNumBumpmapTEs(0) +: mTextureList(), + mNumTEs(0), + mMiscFlags(0), + mNumBumpmapTEs(0) { - mPrimitiveCode = 0; + mPrimitiveCode = 0; - mMaterial = LL_MCODE_STONE; - mVolumep = NULL; + mMaterial = LL_MCODE_STONE; + mVolumep = NULL; - mChanged = UNCHANGED; + mChanged = UNCHANGED; - mPosition.setVec(0.f,0.f,0.f); - mVelocity.setVec(0.f,0.f,0.f); - mAcceleration.setVec(0.f,0.f,0.f); + mPosition.setVec(0.f,0.f,0.f); + mVelocity.setVec(0.f,0.f,0.f); + mAcceleration.setVec(0.f,0.f,0.f); - mRotation.loadIdentity(); - mAngularVelocity.setVec(0.f,0.f,0.f); - - mScale.setVec(1.f,1.f,1.f); + mRotation.loadIdentity(); + mAngularVelocity.setVec(0.f,0.f,0.f); + + mScale.setVec(1.f,1.f,1.f); } //=============================================================== LLPrimitive::~LLPrimitive() { - clearTextureList(); - // Cleanup handled by volume manager - if (mVolumep && sVolumeManager) - { - sVolumeManager->unrefVolume(mVolumep); - } - mVolumep = NULL; + clearTextureList(); + // Cleanup handled by volume manager + if (mVolumep && sVolumeManager) + { + sVolumeManager->unrefVolume(mVolumep); + } + mVolumep = NULL; } void LLPrimitive::clearTextureList() @@ -227,83 +227,83 @@ void LLPrimitive::clearTextureList() // static LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code) { - LLPrimitive *retval = new LLPrimitive(); - - if (retval) - { - retval->init_primitive(p_code); - } - else - { - LL_ERRS() << "primitive allocation failed" << LL_ENDL; - } + LLPrimitive *retval = new LLPrimitive(); - return retval; + if (retval) + { + retval->init_primitive(p_code); + } + else + { + LL_ERRS() << "primitive allocation failed" << LL_ENDL; + } + + return retval; } //=============================================================== void LLPrimitive::init_primitive(LLPCode p_code) { - clearTextureList(); - mPrimitiveCode = p_code; + clearTextureList(); + mPrimitiveCode = p_code; } void LLPrimitive::setPCode(const U8 p_code) { - mPrimitiveCode = p_code; + mPrimitiveCode = p_code; } //=============================================================== LLTextureEntry* LLPrimitive::getTE(const U8 index) const { - return mTextureList.getTexture(index); + return mTextureList.getTexture(index); } //=============================================================== void LLPrimitive::setNumTEs(const U8 num_tes) { - mTextureList.setSize(num_tes); + mTextureList.setSize(num_tes); } //=============================================================== void LLPrimitive::setAllTETextures(const LLUUID &tex_id) { - mTextureList.setAllIDs(tex_id); + mTextureList.setAllIDs(tex_id); } //=============================================================== void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te) { - if(mTextureList.copyTexture(index, te) != TEM_CHANGE_NONE && te.getBumpmap() > 0) - { - mNumBumpmapTEs++; - } + if(mTextureList.copyTexture(index, te) != TEM_CHANGE_NONE && te.getBumpmap() > 0) + { + mNumBumpmapTEs++; + } } S32 LLPrimitive::setTETexture(const U8 index, const LLUUID &id) { - return mTextureList.setID(index, id); + return mTextureList.setID(index, id); } S32 LLPrimitive::setTEColor(const U8 index, const LLColor4 &color) { - return mTextureList.setColor(index, color); + return mTextureList.setColor(index, color); } S32 LLPrimitive::setTEColor(const U8 index, const LLColor3 &color) { - return mTextureList.setColor(index, color); + return mTextureList.setColor(index, color); } S32 LLPrimitive::setTEAlpha(const U8 index, const F32 alpha) { - return mTextureList.setAlpha(index, alpha); + return mTextureList.setAlpha(index, alpha); } //=============================================================== S32 LLPrimitive::setTEScale(const U8 index, const F32 s, const F32 t) { - return mTextureList.setScale(index, s, t); + return mTextureList.setScale(index, s, t); } @@ -311,7 +311,7 @@ S32 LLPrimitive::setTEScale(const U8 index, const F32 s, const F32 t) // voodoo related to texture coords S32 LLPrimitive::setTEScaleS(const U8 index, const F32 s) { - return mTextureList.setScaleS(index, s); + return mTextureList.setScaleS(index, s); } @@ -319,14 +319,14 @@ S32 LLPrimitive::setTEScaleS(const U8 index, const F32 s) // voodoo related to texture coords S32 LLPrimitive::setTEScaleT(const U8 index, const F32 t) { - return mTextureList.setScaleT(index, t); + return mTextureList.setScaleT(index, t); } //=============================================================== S32 LLPrimitive::setTEOffset(const U8 index, const F32 s, const F32 t) { - return mTextureList.setOffset(index, s, t); + return mTextureList.setOffset(index, s, t); } @@ -334,7 +334,7 @@ S32 LLPrimitive::setTEOffset(const U8 index, const F32 s, const F32 t) // voodoo related to texture coords S32 LLPrimitive::setTEOffsetS(const U8 index, const F32 s) { - return mTextureList.setOffsetS(index, s); + return mTextureList.setOffsetS(index, s); } @@ -342,289 +342,289 @@ S32 LLPrimitive::setTEOffsetS(const U8 index, const F32 s) // voodoo related to texture coords S32 LLPrimitive::setTEOffsetT(const U8 index, const F32 t) { - return mTextureList.setOffsetT(index, t); + return mTextureList.setOffsetT(index, t); } //=============================================================== S32 LLPrimitive::setTERotation(const U8 index, const F32 r) { - return mTextureList.setRotation(index, r); + return mTextureList.setRotation(index, r); } S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID) { - return mTextureList.setMaterialID(index, pMaterialID); + return mTextureList.setMaterialID(index, pMaterialID); } S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams) { - return mTextureList.setMaterialParams(index, pMaterialParams); + return mTextureList.setMaterialParams(index, pMaterialParams); } LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index) { - return mTextureList.getMaterialParams(index); + return mTextureList.getMaterialParams(index); } //=============================================================== S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump) { - updateNumBumpmap(index, bump); - return mTextureList.setBumpShinyFullbright(index, bump); + updateNumBumpmap(index, bump); + return mTextureList.setBumpShinyFullbright(index, bump); } S32 LLPrimitive::setTEMediaTexGen(const U8 index, const U8 media) { - return mTextureList.setMediaTexGen(index, media); + return mTextureList.setMediaTexGen(index, media); } S32 LLPrimitive::setTEBumpmap(const U8 index, const U8 bump) { - updateNumBumpmap(index, bump); - return mTextureList.setBumpMap(index, bump); + updateNumBumpmap(index, bump); + return mTextureList.setBumpMap(index, bump); } S32 LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny) { - updateNumBumpmap(index, bump_shiny); - return mTextureList.setBumpShiny(index, bump_shiny); + updateNumBumpmap(index, bump_shiny); + return mTextureList.setBumpShiny(index, bump_shiny); } S32 LLPrimitive::setTETexGen(const U8 index, const U8 texgen) { - return mTextureList.setTexGen(index, texgen); + return mTextureList.setTexGen(index, texgen); } S32 LLPrimitive::setTEShiny(const U8 index, const U8 shiny) { - return mTextureList.setShiny(index, shiny); + return mTextureList.setShiny(index, shiny); } S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright) { - return mTextureList.setFullbright(index, fullbright); + return mTextureList.setFullbright(index, fullbright); } S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags) { - return mTextureList.setMediaFlags(index, media_flags); + return mTextureList.setMediaFlags(index, media_flags); } S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow) { - return mTextureList.setGlow(index, glow); + return mTextureList.setGlow(index, glow); } void LLPrimitive::setAllTESelected(bool sel) { - for (int i = 0, cnt = getNumTEs(); i < cnt; i++) - { - setTESelected(i, sel); - } + for (int i = 0, cnt = getNumTEs(); i < cnt; i++) + { + setTESelected(i, sel); + } } - + void LLPrimitive::setTESelected(const U8 te, bool sel) { - LLTextureEntry* tep = getTE(te); - if ( (tep) && (tep->setSelected(sel)) && (!sel) && (tep->hasPendingMaterialUpdate()) ) - { - LLMaterialID material_id = tep->getMaterialID(); - setTEMaterialID(te, material_id); - } + LLTextureEntry* tep = getTE(te); + if ( (tep) && (tep->setSelected(sel)) && (!sel) && (tep->hasPendingMaterialUpdate()) ) + { + LLMaterialID material_id = tep->getMaterialID(); + setTEMaterialID(te, material_id); + } } LLPCode LLPrimitive::legacyToPCode(const U8 legacy) { - // TODO: Should this default to something valid? - // Maybe volume? - LLPCode pcode = 0; - - switch (legacy) - { - /* - case BOX: - pcode = LL_PCODE_CUBE; - break; - case CYLINDER: - pcode = LL_PCODE_CYLINDER; - break; - case CONE: - pcode = LL_PCODE_CONE; - break; - case HALF_CONE: - pcode = LL_PCODE_CONE_HEMI; - break; - case HALF_CYLINDER: - pcode = LL_PCODE_CYLINDER_HEMI; - break; - case HALF_SPHERE: - pcode = LL_PCODE_SPHERE_HEMI; - break; - case PRISM: - pcode = LL_PCODE_PRISM; - break; - case PYRAMID: - pcode = LL_PCODE_PYRAMID; - break; - case SPHERE: - pcode = LL_PCODE_SPHERE; - break; - case TETRAHEDRON: - pcode = LL_PCODE_TETRAHEDRON; - break; - case DEMON: - pcode = LL_PCODE_LEGACY_DEMON; - break; - case LSL_TEST: - pcode = LL_PCODE_LEGACY_LSL_TEST; - break; - case ORACLE: - pcode = LL_PCODE_LEGACY_ORACLE; - break; - case TEXTBUBBLE: - pcode = LL_PCODE_LEGACY_TEXT_BUBBLE; - break; - case ATOR: - pcode = LL_PCODE_LEGACY_ATOR; - break; - case BASIC_SHOT: - pcode = LL_PCODE_LEGACY_SHOT; - break; - case BIG_SHOT: - pcode = LL_PCODE_LEGACY_SHOT_BIG; - break; - case BIRD: - pcode = LL_PCODE_LEGACY_BIRD; - break; - case ROCK: - pcode = LL_PCODE_LEGACY_ROCK; - break; - case SMOKE: - pcode = LL_PCODE_LEGACY_SMOKE; - break; - case SPARK: - pcode = LL_PCODE_LEGACY_SPARK; - break; - */ - case PRIMITIVE_VOLUME: - pcode = LL_PCODE_VOLUME; - break; - case GRASS: - pcode = LL_PCODE_LEGACY_GRASS; - break; - case PART_SYS: - pcode = LL_PCODE_LEGACY_PART_SYS; - break; - case PLAYER: - pcode = LL_PCODE_LEGACY_AVATAR; - break; - case TREE: - pcode = LL_PCODE_LEGACY_TREE; - break; - case TREE_NEW: - pcode = LL_PCODE_TREE_NEW; - break; - default: - LL_WARNS() << "Unknown legacy code " << legacy << " [" << (S32)legacy << "]!" << LL_ENDL; - } - - return pcode; + // TODO: Should this default to something valid? + // Maybe volume? + LLPCode pcode = 0; + + switch (legacy) + { + /* + case BOX: + pcode = LL_PCODE_CUBE; + break; + case CYLINDER: + pcode = LL_PCODE_CYLINDER; + break; + case CONE: + pcode = LL_PCODE_CONE; + break; + case HALF_CONE: + pcode = LL_PCODE_CONE_HEMI; + break; + case HALF_CYLINDER: + pcode = LL_PCODE_CYLINDER_HEMI; + break; + case HALF_SPHERE: + pcode = LL_PCODE_SPHERE_HEMI; + break; + case PRISM: + pcode = LL_PCODE_PRISM; + break; + case PYRAMID: + pcode = LL_PCODE_PYRAMID; + break; + case SPHERE: + pcode = LL_PCODE_SPHERE; + break; + case TETRAHEDRON: + pcode = LL_PCODE_TETRAHEDRON; + break; + case DEMON: + pcode = LL_PCODE_LEGACY_DEMON; + break; + case LSL_TEST: + pcode = LL_PCODE_LEGACY_LSL_TEST; + break; + case ORACLE: + pcode = LL_PCODE_LEGACY_ORACLE; + break; + case TEXTBUBBLE: + pcode = LL_PCODE_LEGACY_TEXT_BUBBLE; + break; + case ATOR: + pcode = LL_PCODE_LEGACY_ATOR; + break; + case BASIC_SHOT: + pcode = LL_PCODE_LEGACY_SHOT; + break; + case BIG_SHOT: + pcode = LL_PCODE_LEGACY_SHOT_BIG; + break; + case BIRD: + pcode = LL_PCODE_LEGACY_BIRD; + break; + case ROCK: + pcode = LL_PCODE_LEGACY_ROCK; + break; + case SMOKE: + pcode = LL_PCODE_LEGACY_SMOKE; + break; + case SPARK: + pcode = LL_PCODE_LEGACY_SPARK; + break; + */ + case PRIMITIVE_VOLUME: + pcode = LL_PCODE_VOLUME; + break; + case GRASS: + pcode = LL_PCODE_LEGACY_GRASS; + break; + case PART_SYS: + pcode = LL_PCODE_LEGACY_PART_SYS; + break; + case PLAYER: + pcode = LL_PCODE_LEGACY_AVATAR; + break; + case TREE: + pcode = LL_PCODE_LEGACY_TREE; + break; + case TREE_NEW: + pcode = LL_PCODE_TREE_NEW; + break; + default: + LL_WARNS() << "Unknown legacy code " << legacy << " [" << (S32)legacy << "]!" << LL_ENDL; + } + + return pcode; } U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode) { - U8 legacy; - switch (pcode) - { + U8 legacy; + switch (pcode) + { /* - case LL_PCODE_CUBE: - legacy = BOX; - break; - case LL_PCODE_CYLINDER: - legacy = CYLINDER; - break; - case LL_PCODE_CONE: - legacy = CONE; - break; - case LL_PCODE_CONE_HEMI: - legacy = HALF_CONE; - break; - case LL_PCODE_CYLINDER_HEMI: - legacy = HALF_CYLINDER; - break; - case LL_PCODE_SPHERE_HEMI: - legacy = HALF_SPHERE; - break; - case LL_PCODE_PRISM: - legacy = PRISM; - break; - case LL_PCODE_PYRAMID: - legacy = PYRAMID; - break; - case LL_PCODE_SPHERE: - legacy = SPHERE; - break; - case LL_PCODE_TETRAHEDRON: - legacy = TETRAHEDRON; - break; - case LL_PCODE_LEGACY_ATOR: - legacy = ATOR; - break; - case LL_PCODE_LEGACY_SHOT: - legacy = BASIC_SHOT; - break; - case LL_PCODE_LEGACY_SHOT_BIG: - legacy = BIG_SHOT; - break; - case LL_PCODE_LEGACY_BIRD: - legacy = BIRD; - break; - case LL_PCODE_LEGACY_DEMON: - legacy = DEMON; - break; - case LL_PCODE_LEGACY_LSL_TEST: - legacy = LSL_TEST; - break; - case LL_PCODE_LEGACY_ORACLE: - legacy = ORACLE; - break; - case LL_PCODE_LEGACY_ROCK: - legacy = ROCK; - break; - case LL_PCODE_LEGACY_TEXT_BUBBLE: - legacy = TEXTBUBBLE; - break; - case LL_PCODE_LEGACY_SMOKE: - legacy = SMOKE; - break; - case LL_PCODE_LEGACY_SPARK: - legacy = SPARK; - break; + case LL_PCODE_CUBE: + legacy = BOX; + break; + case LL_PCODE_CYLINDER: + legacy = CYLINDER; + break; + case LL_PCODE_CONE: + legacy = CONE; + break; + case LL_PCODE_CONE_HEMI: + legacy = HALF_CONE; + break; + case LL_PCODE_CYLINDER_HEMI: + legacy = HALF_CYLINDER; + break; + case LL_PCODE_SPHERE_HEMI: + legacy = HALF_SPHERE; + break; + case LL_PCODE_PRISM: + legacy = PRISM; + break; + case LL_PCODE_PYRAMID: + legacy = PYRAMID; + break; + case LL_PCODE_SPHERE: + legacy = SPHERE; + break; + case LL_PCODE_TETRAHEDRON: + legacy = TETRAHEDRON; + break; + case LL_PCODE_LEGACY_ATOR: + legacy = ATOR; + break; + case LL_PCODE_LEGACY_SHOT: + legacy = BASIC_SHOT; + break; + case LL_PCODE_LEGACY_SHOT_BIG: + legacy = BIG_SHOT; + break; + case LL_PCODE_LEGACY_BIRD: + legacy = BIRD; + break; + case LL_PCODE_LEGACY_DEMON: + legacy = DEMON; + break; + case LL_PCODE_LEGACY_LSL_TEST: + legacy = LSL_TEST; + break; + case LL_PCODE_LEGACY_ORACLE: + legacy = ORACLE; + break; + case LL_PCODE_LEGACY_ROCK: + legacy = ROCK; + break; + case LL_PCODE_LEGACY_TEXT_BUBBLE: + legacy = TEXTBUBBLE; + break; + case LL_PCODE_LEGACY_SMOKE: + legacy = SMOKE; + break; + case LL_PCODE_LEGACY_SPARK: + legacy = SPARK; + break; */ - case LL_PCODE_VOLUME: - legacy = PRIMITIVE_VOLUME; - break; - case LL_PCODE_LEGACY_GRASS: - legacy = GRASS; - break; - case LL_PCODE_LEGACY_PART_SYS: - legacy = PART_SYS; - break; - case LL_PCODE_LEGACY_AVATAR: - legacy = PLAYER; - break; - case LL_PCODE_LEGACY_TREE: - legacy = TREE; - break; - case LL_PCODE_TREE_NEW: - legacy = TREE_NEW; - break; - default: - LL_WARNS() << "Unknown pcode " << (S32)pcode << ":" << pcode << "!" << LL_ENDL; - return 0; - } - return legacy; + case LL_PCODE_VOLUME: + legacy = PRIMITIVE_VOLUME; + break; + case LL_PCODE_LEGACY_GRASS: + legacy = GRASS; + break; + case LL_PCODE_LEGACY_PART_SYS: + legacy = PART_SYS; + break; + case LL_PCODE_LEGACY_AVATAR: + legacy = PLAYER; + break; + case LL_PCODE_LEGACY_TREE: + legacy = TREE; + break; + case LL_PCODE_TREE_NEW: + legacy = TREE_NEW; + break; + default: + LL_WARNS() << "Unknown pcode " << (S32)pcode << ":" << pcode << "!" << LL_ENDL; + return 0; + } + return legacy; } @@ -632,491 +632,491 @@ U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode) // Don't crash or LL_ERRS() here! This function is used for debug strings. std::string LLPrimitive::pCodeToString(const LLPCode pcode) { - std::string pcode_string; - - U8 base_code = pcode & LL_PCODE_BASE_MASK; - if (!pcode) - { - pcode_string = "null"; - } - else if ((base_code) == LL_PCODE_LEGACY) - { - // It's a legacy object - switch (pcode) - { - case LL_PCODE_LEGACY_GRASS: - pcode_string = "grass"; - break; - case LL_PCODE_LEGACY_PART_SYS: - pcode_string = "particle system"; - break; - case LL_PCODE_LEGACY_AVATAR: - pcode_string = "avatar"; - break; - case LL_PCODE_LEGACY_TEXT_BUBBLE: - pcode_string = "text bubble"; - break; - case LL_PCODE_LEGACY_TREE: - pcode_string = "tree"; - break; - case LL_PCODE_TREE_NEW: - pcode_string = "tree_new"; - break; - default: - pcode_string = llformat( "unknown legacy pcode %i",(U32)pcode); - } - } - else - { - std::string shape; - std::string mask; - if (base_code == LL_PCODE_CUBE) - { - shape = "cube"; - } - else if (base_code == LL_PCODE_CYLINDER) - { - shape = "cylinder"; - } - else if (base_code == LL_PCODE_CONE) - { - shape = "cone"; - } - else if (base_code == LL_PCODE_PRISM) - { - shape = "prism"; - } - else if (base_code == LL_PCODE_PYRAMID) - { - shape = "pyramid"; - } - else if (base_code == LL_PCODE_SPHERE) - { - shape = "sphere"; - } - else if (base_code == LL_PCODE_TETRAHEDRON) - { - shape = "tetrahedron"; - } - else if (base_code == LL_PCODE_VOLUME) - { - shape = "volume"; - } - else if (base_code == LL_PCODE_APP) - { - shape = "app"; - } - else - { - LL_WARNS() << "Unknown base mask for pcode: " << base_code << LL_ENDL; - } - - U8 mask_code = pcode & (~LL_PCODE_BASE_MASK); - if (base_code == LL_PCODE_APP) - { - mask = llformat( "%x", mask_code); - } - else if (mask_code & LL_PCODE_HEMI_MASK) - { - mask = "hemi"; - } - else - { - mask = llformat( "%x", mask_code); - } - - if (mask[0]) - { - pcode_string = llformat( "%s-%s", shape.c_str(), mask.c_str()); - } - else - { - pcode_string = llformat( "%s", shape.c_str()); - } - } - - return pcode_string; + std::string pcode_string; + + U8 base_code = pcode & LL_PCODE_BASE_MASK; + if (!pcode) + { + pcode_string = "null"; + } + else if ((base_code) == LL_PCODE_LEGACY) + { + // It's a legacy object + switch (pcode) + { + case LL_PCODE_LEGACY_GRASS: + pcode_string = "grass"; + break; + case LL_PCODE_LEGACY_PART_SYS: + pcode_string = "particle system"; + break; + case LL_PCODE_LEGACY_AVATAR: + pcode_string = "avatar"; + break; + case LL_PCODE_LEGACY_TEXT_BUBBLE: + pcode_string = "text bubble"; + break; + case LL_PCODE_LEGACY_TREE: + pcode_string = "tree"; + break; + case LL_PCODE_TREE_NEW: + pcode_string = "tree_new"; + break; + default: + pcode_string = llformat( "unknown legacy pcode %i",(U32)pcode); + } + } + else + { + std::string shape; + std::string mask; + if (base_code == LL_PCODE_CUBE) + { + shape = "cube"; + } + else if (base_code == LL_PCODE_CYLINDER) + { + shape = "cylinder"; + } + else if (base_code == LL_PCODE_CONE) + { + shape = "cone"; + } + else if (base_code == LL_PCODE_PRISM) + { + shape = "prism"; + } + else if (base_code == LL_PCODE_PYRAMID) + { + shape = "pyramid"; + } + else if (base_code == LL_PCODE_SPHERE) + { + shape = "sphere"; + } + else if (base_code == LL_PCODE_TETRAHEDRON) + { + shape = "tetrahedron"; + } + else if (base_code == LL_PCODE_VOLUME) + { + shape = "volume"; + } + else if (base_code == LL_PCODE_APP) + { + shape = "app"; + } + else + { + LL_WARNS() << "Unknown base mask for pcode: " << base_code << LL_ENDL; + } + + U8 mask_code = pcode & (~LL_PCODE_BASE_MASK); + if (base_code == LL_PCODE_APP) + { + mask = llformat( "%x", mask_code); + } + else if (mask_code & LL_PCODE_HEMI_MASK) + { + mask = "hemi"; + } + else + { + mask = llformat( "%x", mask_code); + } + + if (mask[0]) + { + pcode_string = llformat( "%s-%s", shape.c_str(), mask.c_str()); + } + else + { + pcode_string = llformat( "%s", shape.c_str()); + } + } + + return pcode_string; } void LLPrimitive::copyTEs(const LLPrimitive *primitivep) { - U32 i; - if (primitivep->getExpectedNumTEs() != getExpectedNumTEs()) - { - LL_WARNS() << "Primitives don't have same expected number of TE's" << LL_ENDL; - } - U32 num_tes = llmin(primitivep->getExpectedNumTEs(), getExpectedNumTEs()); - if (mTextureList.size() < getExpectedNumTEs()) - { - mTextureList.setSize(getExpectedNumTEs()); - } - for (i = 0; i < num_tes; i++) - { - mTextureList.copyTexture(i, *(primitivep->getTE(i))); - } -} - -S32 face_index_from_id(LLFaceID face_ID, const std::vector& faceArray) -{ - S32 i; - for (i = 0; i < (S32)faceArray.size(); i++) - { - if (faceArray[i].mFaceID == face_ID) - { - return i; - } - } - return -1; + U32 i; + if (primitivep->getExpectedNumTEs() != getExpectedNumTEs()) + { + LL_WARNS() << "Primitives don't have same expected number of TE's" << LL_ENDL; + } + U32 num_tes = llmin(primitivep->getExpectedNumTEs(), getExpectedNumTEs()); + if (mTextureList.size() < getExpectedNumTEs()) + { + mTextureList.setSize(getExpectedNumTEs()); + } + for (i = 0; i < num_tes; i++) + { + mTextureList.copyTexture(i, *(primitivep->getTE(i))); + } +} + +S32 face_index_from_id(LLFaceID face_ID, const std::vector& faceArray) +{ + S32 i; + for (i = 0; i < (S32)faceArray.size(); i++) + { + if (faceArray[i].mFaceID == face_ID) + { + return i; + } + } + return -1; } BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) { - if (NO_LOD == detail) - { - // build the new object - setChanged(GEOMETRY); - sVolumeManager->unrefVolume(mVolumep); - mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE); - setNumTEs(mVolumep->getNumFaces()); - return FALSE; - } - - LLVolume *volumep; - if (unique_volume) - { - F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); - if (mVolumep.notNull() && volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) - { - return FALSE; - } - volumep = new LLVolume(volume_params, volume_detail, FALSE, TRUE); - } - else - { - if (mVolumep.notNull()) - { - F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); - if (volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) - { - return FALSE; - } - } - - volumep = sVolumeManager->refVolume(volume_params, detail); - if (volumep == mVolumep) - { - sVolumeManager->unrefVolume( volumep ); // LLVolumeMgr::refVolume() creates a reference, but we don't need a second one. - return TRUE; - } - } - - setChanged(GEOMETRY); - - - if (!mVolumep) - { - mVolumep = volumep; - //mFaceMask = mVolumep->generateFaceMask(); - setNumTEs(mVolumep->getNumFaces()); - return TRUE; - } - -#if 0 - // #if 0'd out by davep - // this is a lot of cruft to set texture entry values that just stay the same for LOD switch - // or immediately get overridden by an object update message, also crashes occasionally - U32 old_face_mask = mVolumep->mFaceMask; - - S32 face_bit = 0; - S32 cur_mask = 0; - - // Grab copies of the old faces from the original shape, ordered by type. - // We will use these to figure out what old texture info gets mapped to new - // faces in the new shape. - std::vector old_faces; - for (S32 face = 0; face < mVolumep->getNumFaces(); face++) - { - old_faces.push_back(mVolumep->getProfile().mFaces[face]); - } - - // Copy the old texture info off to the side, but not in the order in which - // they live in the mTextureList, rather in order of ther "face id" which - // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex. - // - // Hence, some elements of old_tes::mEntryList will be invalid. It is - // initialized to a size of 9 (max number of possible faces on a volume?) - // and only the ones with valid types are filled in. - LLPrimTextureList old_tes; - old_tes.setSize(9); - for (face_bit = 0; face_bit < 9; face_bit++) - { - cur_mask = 0x1 << face_bit; - if (old_face_mask & cur_mask) - { - S32 te_index = face_index_from_id(cur_mask, old_faces); - old_tes.copyTexture(face_bit, *(getTE(te_index))); - //LL_INFOS() << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << LL_ENDL; - } - } - - - // build the new object - sVolumeManager->unrefVolume(mVolumep); - mVolumep = volumep; - - U32 new_face_mask = mVolumep->mFaceMask; - S32 i; - - if (old_face_mask == new_face_mask) - { - // nothing to do - return TRUE; - } - - if (mVolumep->getNumFaces() == 0 && new_face_mask != 0) - { - LL_WARNS() << "Object with 0 faces found...INCORRECT!" << LL_ENDL; - setNumTEs(mVolumep->getNumFaces()); - return TRUE; - } - - // initialize face_mapping - S32 face_mapping[9]; - for (face_bit = 0; face_bit < 9; face_bit++) - { - face_mapping[face_bit] = face_bit; - } - - // The new shape may have more faces than the original, but we can't just - // add them to the end -- the ordering matters and it may be that we must - // insert the new faces in the middle of the list. When we add a face it - // will pick up the texture/color info of one of the old faces an so we - // now figure out which old face info gets mapped to each new face, and - // store in the face_mapping lookup table. - for (face_bit = 0; face_bit < 9; face_bit++) - { - cur_mask = 0x1 << face_bit; - if (!(new_face_mask & cur_mask)) - { - // Face doesn't exist in new map. - face_mapping[face_bit] = -1; - continue; - } - else if (old_face_mask & cur_mask) - { - // Face exists in new and old map. - face_mapping[face_bit] = face_bit; - continue; - } - - // OK, how we've got a mismatch, where we have to fill a new face with one from - // the old face. - if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE)) - { - // It's a top/bottom/hollow interior face. - if (old_face_mask & LL_FACE_PATH_END) - { - face_mapping[face_bit] = 1; - continue; - } - else - { - S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; - for (i = 0; i < 4; i++) - { - if (old_face_mask & cur_outer_mask) - { - face_mapping[face_bit] = 5 + i; - break; - } - cur_outer_mask <<= 1; - } - if (i == 4) - { - LL_WARNS() << "No path end or outer face in volume!" << LL_ENDL; - } - continue; - } - } - - if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) - { - // A cut slice. Use the hollow interior if we have it. - if (old_face_mask & LL_FACE_INNER_SIDE) - { - face_mapping[face_bit] = 2; - continue; - } - - // No interior, use the bottom face. - // Could figure out which of the outer faces was nearest, but that would be harder. - if (old_face_mask & LL_FACE_PATH_END) - { - face_mapping[face_bit] = 1; - continue; - } - else - { - S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; - for (i = 0; i < 4; i++) - { - if (old_face_mask & cur_outer_mask) - { - face_mapping[face_bit] = 5 + i; - break; - } - cur_outer_mask <<= 1; - } - if (i == 4) - { - LL_WARNS() << "No path end or outer face in volume!" << LL_ENDL; - } - continue; - } - } - - // OK, the face that's missing is an outer face... - // Pull from the nearest adjacent outer face (there's always guaranteed to be one... - S32 cur_outer = face_bit - 5; - S32 min_dist = 5; - S32 min_outer_bit = -1; - S32 i; - for (i = 0; i < 4; i++) - { - if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i)) - { - S32 dist = abs(i - cur_outer); - if (dist < min_dist) - { - min_dist = dist; - min_outer_bit = i + 5; - } - } - } - if (-1 == min_outer_bit) - { - LL_INFOS() << (LLVolume *)mVolumep << LL_ENDL; - LL_WARNS() << "Bad! No outer faces, impossible!" << LL_ENDL; - } - face_mapping[face_bit] = min_outer_bit; - } - - - setNumTEs(mVolumep->getNumFaces()); - for (face_bit = 0; face_bit < 9; face_bit++) - { - // For each possible face type on the new shape we check to see if that - // face exists and if it does we create a texture entry that is a copy - // of one of the originals. Since the originals might not have a - // matching face, we use the face_mapping lookup table to figure out - // which face information to copy. - cur_mask = 0x1 << face_bit; - if (new_face_mask & cur_mask) - { - if (-1 == face_mapping[face_bit]) - { - LL_WARNS() << "No mapping from old face to new face!" << LL_ENDL; - } - - S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces); - setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); - } - } + if (NO_LOD == detail) + { + // build the new object + setChanged(GEOMETRY); + sVolumeManager->unrefVolume(mVolumep); + mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE); + setNumTEs(mVolumep->getNumFaces()); + return FALSE; + } + + LLVolume *volumep; + if (unique_volume) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + if (mVolumep.notNull() && volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) + { + return FALSE; + } + volumep = new LLVolume(volume_params, volume_detail, FALSE, TRUE); + } + else + { + if (mVolumep.notNull()) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + if (volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail())) + { + return FALSE; + } + } + + volumep = sVolumeManager->refVolume(volume_params, detail); + if (volumep == mVolumep) + { + sVolumeManager->unrefVolume( volumep ); // LLVolumeMgr::refVolume() creates a reference, but we don't need a second one. + return TRUE; + } + } + + setChanged(GEOMETRY); + + + if (!mVolumep) + { + mVolumep = volumep; + //mFaceMask = mVolumep->generateFaceMask(); + setNumTEs(mVolumep->getNumFaces()); + return TRUE; + } + +#if 0 + // #if 0'd out by davep + // this is a lot of cruft to set texture entry values that just stay the same for LOD switch + // or immediately get overridden by an object update message, also crashes occasionally + U32 old_face_mask = mVolumep->mFaceMask; + + S32 face_bit = 0; + S32 cur_mask = 0; + + // Grab copies of the old faces from the original shape, ordered by type. + // We will use these to figure out what old texture info gets mapped to new + // faces in the new shape. + std::vector old_faces; + for (S32 face = 0; face < mVolumep->getNumFaces(); face++) + { + old_faces.push_back(mVolumep->getProfile().mFaces[face]); + } + + // Copy the old texture info off to the side, but not in the order in which + // they live in the mTextureList, rather in order of ther "face id" which + // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex. + // + // Hence, some elements of old_tes::mEntryList will be invalid. It is + // initialized to a size of 9 (max number of possible faces on a volume?) + // and only the ones with valid types are filled in. + LLPrimTextureList old_tes; + old_tes.setSize(9); + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (old_face_mask & cur_mask) + { + S32 te_index = face_index_from_id(cur_mask, old_faces); + old_tes.copyTexture(face_bit, *(getTE(te_index))); + //LL_INFOS() << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << LL_ENDL; + } + } + + + // build the new object + sVolumeManager->unrefVolume(mVolumep); + mVolumep = volumep; + + U32 new_face_mask = mVolumep->mFaceMask; + S32 i; + + if (old_face_mask == new_face_mask) + { + // nothing to do + return TRUE; + } + + if (mVolumep->getNumFaces() == 0 && new_face_mask != 0) + { + LL_WARNS() << "Object with 0 faces found...INCORRECT!" << LL_ENDL; + setNumTEs(mVolumep->getNumFaces()); + return TRUE; + } + + // initialize face_mapping + S32 face_mapping[9]; + for (face_bit = 0; face_bit < 9; face_bit++) + { + face_mapping[face_bit] = face_bit; + } + + // The new shape may have more faces than the original, but we can't just + // add them to the end -- the ordering matters and it may be that we must + // insert the new faces in the middle of the list. When we add a face it + // will pick up the texture/color info of one of the old faces an so we + // now figure out which old face info gets mapped to each new face, and + // store in the face_mapping lookup table. + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (!(new_face_mask & cur_mask)) + { + // Face doesn't exist in new map. + face_mapping[face_bit] = -1; + continue; + } + else if (old_face_mask & cur_mask) + { + // Face exists in new and old map. + face_mapping[face_bit] = face_bit; + continue; + } + + // OK, how we've got a mismatch, where we have to fill a new face with one from + // the old face. + if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE)) + { + // It's a top/bottom/hollow interior face. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + LL_WARNS() << "No path end or outer face in volume!" << LL_ENDL; + } + continue; + } + } + + if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + // A cut slice. Use the hollow interior if we have it. + if (old_face_mask & LL_FACE_INNER_SIDE) + { + face_mapping[face_bit] = 2; + continue; + } + + // No interior, use the bottom face. + // Could figure out which of the outer faces was nearest, but that would be harder. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + LL_WARNS() << "No path end or outer face in volume!" << LL_ENDL; + } + continue; + } + } + + // OK, the face that's missing is an outer face... + // Pull from the nearest adjacent outer face (there's always guaranteed to be one... + S32 cur_outer = face_bit - 5; + S32 min_dist = 5; + S32 min_outer_bit = -1; + S32 i; + for (i = 0; i < 4; i++) + { + if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i)) + { + S32 dist = abs(i - cur_outer); + if (dist < min_dist) + { + min_dist = dist; + min_outer_bit = i + 5; + } + } + } + if (-1 == min_outer_bit) + { + LL_INFOS() << (LLVolume *)mVolumep << LL_ENDL; + LL_WARNS() << "Bad! No outer faces, impossible!" << LL_ENDL; + } + face_mapping[face_bit] = min_outer_bit; + } + + + setNumTEs(mVolumep->getNumFaces()); + for (face_bit = 0; face_bit < 9; face_bit++) + { + // For each possible face type on the new shape we check to see if that + // face exists and if it does we create a texture entry that is a copy + // of one of the originals. Since the originals might not have a + // matching face, we use the face_mapping lookup table to figure out + // which face information to copy. + cur_mask = 0x1 << face_bit; + if (new_face_mask & cur_mask) + { + if (-1 == face_mapping[face_bit]) + { + LL_WARNS() << "No mapping from old face to new face!" << LL_ENDL; + } + + S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces); + setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); + } + } #else - // build the new object - sVolumeManager->unrefVolume(mVolumep); - mVolumep = volumep; + // build the new object + sVolumeManager->unrefVolume(mVolumep); + mVolumep = volumep; - setNumTEs(mVolumep->getNumFaces()); + setNumTEs(mVolumep->getNumFaces()); #endif - return TRUE; + return TRUE; } BOOL LLPrimitive::setMaterial(U8 material) { - if (material != mMaterial) - { - mMaterial = material; - return TRUE; - } - else - { - return FALSE; - } + if (material != mMaterial) + { + mMaterial = material; + return TRUE; + } + else + { + return FALSE; + } } S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const { - S32 face_index; - S32 i; - U64 exception_faces; - U8 *start_loc = cur_ptr; - - htolememcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size); - cur_ptr += data_size; - - for (face_index = last_face_index-1; face_index >= 0; face_index--) - { - BOOL already_sent = FALSE; - for (i = face_index+1; i <= last_face_index; i++) - { - if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) - { - already_sent = TRUE; - break; - } - } - - if (!already_sent) - { - exception_faces = 0; - for (i = face_index; i >= 0; i--) - { - if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) - { - exception_faces |= ((U64)1 << i); - } - } - - //assign exception faces to cur_ptr - if (exception_faces >= ((U64)0x1 << 7)) - { - if (exception_faces >= ((U64)0x1 << 14)) - { - if (exception_faces >= ((U64)0x1 << 21)) - { - if (exception_faces >= ((U64)0x1 << 28)) - { - if (exception_faces >= ((U64)0x1 << 35)) - { - if (exception_faces >= ((U64)0x1 << 42)) - { - if (exception_faces >= ((U64)0x1 << 49)) - { - *cur_ptr++ = (U8)(((exception_faces >> 49) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 42) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 35) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 28) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 21) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 14) & 0x7F) | 0x80); - } - *cur_ptr++ = (U8)(((exception_faces >> 7) & 0x7F) | 0x80); - } - - - *cur_ptr++ = (U8)(exception_faces & 0x7F); - - htolememcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size); - cur_ptr += data_size; - } - } - return (S32)(cur_ptr - start_loc); + S32 face_index; + S32 i; + U64 exception_faces; + U8 *start_loc = cur_ptr; + + htolememcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size); + cur_ptr += data_size; + + for (face_index = last_face_index-1; face_index >= 0; face_index--) + { + BOOL already_sent = FALSE; + for (i = face_index+1; i <= last_face_index; i++) + { + if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) + { + already_sent = TRUE; + break; + } + } + + if (!already_sent) + { + exception_faces = 0; + for (i = face_index; i >= 0; i--) + { + if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size)) + { + exception_faces |= ((U64)1 << i); + } + } + + //assign exception faces to cur_ptr + if (exception_faces >= ((U64)0x1 << 7)) + { + if (exception_faces >= ((U64)0x1 << 14)) + { + if (exception_faces >= ((U64)0x1 << 21)) + { + if (exception_faces >= ((U64)0x1 << 28)) + { + if (exception_faces >= ((U64)0x1 << 35)) + { + if (exception_faces >= ((U64)0x1 << 42)) + { + if (exception_faces >= ((U64)0x1 << 49)) + { + *cur_ptr++ = (U8)(((exception_faces >> 49) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 42) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 35) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 28) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 21) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 14) & 0x7F) | 0x80); + } + *cur_ptr++ = (U8)(((exception_faces >> 7) & 0x7F) | 0x80); + } + + + *cur_ptr++ = (U8)(exception_faces & 0x7F); + + htolememcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size); + cur_ptr += data_size; + } + } + return (S32)(cur_ptr - start_loc); } namespace @@ -1136,7 +1136,7 @@ namespace return false; } - // Extract the default value and fill the array. + // Extract the default value and fill the array. htolememcpy(dest, source, type, size); source += size; for (S32 idx = 1; idx < dest_count; ++idx) @@ -1149,7 +1149,7 @@ namespace U64 index_flags(0); U8 sbit(0); - // Unpack the variable length bitfield. Each bit represents whether the following + // Unpack the variable length bitfield. Each bit represents whether the following // value will be placed at the corresponding array index. do { @@ -1203,194 +1203,194 @@ namespace // Includes information about image ID, color, scale S,T, offset S,T and rotation BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const { - const U32 MAX_TES = 45; - - U8 image_ids[MAX_TES*16]; - U8 colors[MAX_TES*4]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; + const U32 MAX_TES = 45; + + U8 image_ids[MAX_TES*16]; + U8 colors[MAX_TES*4]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; U8 glow[MAX_TES]; - U8 material_data[MAX_TES*16]; - - const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; - U8 *cur_ptr = packed_buffer; - - S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1; - - if (last_face_index > -1) - { - // ...if we hit the front, send one image id - S8 face_index; - LLColor4U coloru; - for (face_index = 0; face_index <= last_face_index; face_index++) - { - // Directly sending image_ids is not safe! - memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ - - // Cast LLColor4 to LLColor4U - coloru.setVec( getTE(face_index)->getColor() ); - - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) - // as all zeros. However, the subtraction and addition must be done in unsigned - // byte space, not in float space, otherwise off-by-one errors occur. JC - colors[4*face_index] = 255 - coloru.mV[0]; - colors[4*face_index + 1] = 255 - coloru.mV[1]; - colors[4*face_index + 2] = 255 - coloru.mV[2]; - colors[4*face_index + 3] = 255 - coloru.mV[3]; - - const LLTextureEntry* te = getTE(face_index); - scale_s[face_index] = (F32) te->mScaleS; - scale_t[face_index] = (F32) te->mScaleT; - offset_s[face_index] = (S16) ll_round((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; - offset_t[face_index] = (S16) ll_round((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; - image_rot[face_index] = (S16) ll_round(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); - bump[face_index] = te->getBumpShinyFullbright(); - media_flags[face_index] = te->getMediaTexGen(); - glow[face_index] = (U8) ll_round((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF)); - - // Directly sending material_ids is not safe! - memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */ - } - - cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID); - } - mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer)); - - return FALSE; + U8 material_data[MAX_TES*16]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1; + + if (last_face_index > -1) + { + // ...if we hit the front, send one image id + S8 face_index; + LLColor4U coloru; + for (face_index = 0; face_index <= last_face_index; face_index++) + { + // Directly sending image_ids is not safe! + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + + // Cast LLColor4 to LLColor4U + coloru.setVec( getTE(face_index)->getColor() ); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + colors[4*face_index] = 255 - coloru.mV[0]; + colors[4*face_index + 1] = 255 - coloru.mV[1]; + colors[4*face_index + 2] = 255 - coloru.mV[2]; + colors[4*face_index + 3] = 255 - coloru.mV[3]; + + const LLTextureEntry* te = getTE(face_index); + scale_s[face_index] = (F32) te->mScaleS; + scale_t[face_index] = (F32) te->mScaleT; + offset_s[face_index] = (S16) ll_round((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; + offset_t[face_index] = (S16) ll_round((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; + image_rot[face_index] = (S16) ll_round(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); + bump[face_index] = te->getBumpShinyFullbright(); + media_flags[face_index] = te->getMediaTexGen(); + glow[face_index] = (U8) ll_round((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF)); + + // Directly sending material_ids is not safe! + memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */ + } + + cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID); + } + mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer)); + + return FALSE; } BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const { - const U32 MAX_TES = 45; - - U8 image_ids[MAX_TES*16]; - U8 colors[MAX_TES*4]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; + const U32 MAX_TES = 45; + + U8 image_ids[MAX_TES*16]; + U8 colors[MAX_TES*4]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; U8 glow[MAX_TES]; - U8 material_data[MAX_TES*16]; - - const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; - U8 *cur_ptr = packed_buffer; - - S32 last_face_index = getNumTEs() - 1; - - if (last_face_index > -1) - { - // ...if we hit the front, send one image id - S8 face_index; - LLColor4U coloru; - for (face_index = 0; face_index <= last_face_index; face_index++) - { - // Directly sending image_ids is not safe! - memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ - - // Cast LLColor4 to LLColor4U - coloru.setVec( getTE(face_index)->getColor() ); - - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) - // as all zeros. However, the subtraction and addition must be done in unsigned - // byte space, not in float space, otherwise off-by-one errors occur. JC - colors[4*face_index] = 255 - coloru.mV[0]; - colors[4*face_index + 1] = 255 - coloru.mV[1]; - colors[4*face_index + 2] = 255 - coloru.mV[2]; - colors[4*face_index + 3] = 255 - coloru.mV[3]; - - const LLTextureEntry* te = getTE(face_index); - scale_s[face_index] = (F32) te->mScaleS; - scale_t[face_index] = (F32) te->mScaleT; - offset_s[face_index] = (S16) ll_round((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; - offset_t[face_index] = (S16) ll_round((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; - image_rot[face_index] = (S16) ll_round(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); - bump[face_index] = te->getBumpShinyFullbright(); - media_flags[face_index] = te->getMediaTexGen(); + U8 material_data[MAX_TES*16]; + + const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; + U8 *cur_ptr = packed_buffer; + + S32 last_face_index = getNumTEs() - 1; + + if (last_face_index > -1) + { + // ...if we hit the front, send one image id + S8 face_index; + LLColor4U coloru; + for (face_index = 0; face_index <= last_face_index; face_index++) + { + // Directly sending image_ids is not safe! + memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */ + + // Cast LLColor4 to LLColor4U + coloru.setVec( getTE(face_index)->getColor() ); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + colors[4*face_index] = 255 - coloru.mV[0]; + colors[4*face_index + 1] = 255 - coloru.mV[1]; + colors[4*face_index + 2] = 255 - coloru.mV[2]; + colors[4*face_index + 3] = 255 - coloru.mV[3]; + + const LLTextureEntry* te = getTE(face_index); + scale_s[face_index] = (F32) te->mScaleS; + scale_t[face_index] = (F32) te->mScaleT; + offset_s[face_index] = (S16) ll_round((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ; + offset_t[face_index] = (S16) ll_round((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ; + image_rot[face_index] = (S16) ll_round(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR)); + bump[face_index] = te->getBumpShinyFullbright(); + media_flags[face_index] = te->getMediaTexGen(); glow[face_index] = (U8) ll_round((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF)); - // Directly sending material_ids is not safe! - memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */ - } - - cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8); - *cur_ptr++ = 0; - cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID); - } - - dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry"); - return FALSE; + // Directly sending material_ids is not safe! + memcpy(&material_data[face_index*16],getTE(face_index)->getMaterialID().get(),16); /* Flawfinder: ignore */ + } + + cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8); + *cur_ptr++ = 0; + cur_ptr += packTEField(cur_ptr, (U8 *)material_data, 16, last_face_index, MVT_LLUUID); + } + + dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry"); + return FALSE; } S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec) { - S32 retval = 0; + S32 retval = 0; // temp buffer for material ID processing - // data will end up in tec.material_id[] + // data will end up in tec.material_id[] material_id_type material_data[LLTEContents::MAX_TES]; - if (block_num < 0) - { - tec.size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); - } - else - { - tec.size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); - } - - if (tec.size == 0) - { - tec.face_count = 0; - return retval; - } + if (block_num < 0) + { + tec.size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry); + } + else + { + tec.size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry); + } + + if (tec.size == 0) + { + tec.face_count = 0; + return retval; + } else if (tec.size >= LLTEContents::MAX_TE_BUFFER) { LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; @@ -1400,14 +1400,14 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name // if block_num < 0 ask for block 0 mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, std::max(block_num, 0), LLTEContents::MAX_TE_BUFFER - 1); - // The last field is not zero terminated. + // The last field is not zero terminated. // Rather than special case the upack functions. Just make it 0x00 terminated. tec.packed_buffer[tec.size] = 0x00; ++tec.size; - tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES); + tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES); - U8 *cur_ptr = tec.packed_buffer; + U8 *cur_ptr = tec.packed_buffer; LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffere sized: " << tec.size << LL_ENDL; U8 *buffer_end = tec.packed_buffer + tec.size; @@ -1426,68 +1426,68 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name return 0; } - if (cur_ptr >= buffer_end || !unpack_TEField(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID)) - { - memset((void*)material_data, 0, sizeof(material_data)); - } - - for (U32 i = 0; i < tec.face_count; i++) - { - tec.material_ids[i].set(&(material_data[i])); - } - - retval = 1; - return retval; - } - + if (cur_ptr >= buffer_end || !unpack_TEField(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID)) + { + memset((void*)material_data, 0, sizeof(material_data)); + } + + for (U32 i = 0; i < tec.face_count; i++) + { + tec.material_ids[i].set(&(material_data[i])); + } + + retval = 1; + return retval; + } + S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec) { - S32 retval = 0; - - LLColor4 color; - for (U32 i = 0; i < tec.face_count; i++) - { - LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; - retval |= setTETexture(i, req_id); - retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]); - retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); - retval |= setTEBumpShinyFullbright(i, tec.bump[i]); - retval |= setTEMediaTexGen(i, tec.media_flags[i]); - retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF); - retval |= setTEMaterialID(i, tec.material_ids[i]); - - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) - // as all zeros. However, the subtraction and addition must be done in unsigned - // byte space, not in float space, otherwise off-by-one errors occur. JC - color.mV[VRED] = F32(255 - tec.colors[i].mV[VRED]) / 255.f; - color.mV[VGREEN] = F32(255 - tec.colors[i].mV[VGREEN]) / 255.f; - color.mV[VBLUE] = F32(255 - tec.colors[i].mV[VBLUE]) / 255.f; - color.mV[VALPHA] = F32(255 - tec.colors[i].mV[VALPHA]) / 255.f; - - retval |= setTEColor(i, color); - } - - return retval; + S32 retval = 0; + + LLColor4 color; + for (U32 i = 0; i < tec.face_count; i++) + { + LLUUID& req_id = ((LLUUID*)tec.image_data)[i]; + retval |= setTETexture(i, req_id); + retval |= setTEScale(i, tec.scale_s[i], tec.scale_t[i]); + retval |= setTEOffset(i, (F32)tec.offset_s[i] / (F32)0x7FFF, (F32) tec.offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)tec.image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, tec.bump[i]); + retval |= setTEMediaTexGen(i, tec.media_flags[i]); + retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF); + retval |= setTEMaterialID(i, tec.material_ids[i]); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + color.mV[VRED] = F32(255 - tec.colors[i].mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - tec.colors[i].mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - tec.colors[i].mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - tec.colors[i].mV[VALPHA]) / 255.f; + + retval |= setTEColor(i, color); + } + + return retval; } S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num) { - LLTEContents tec; - S32 retval = parseTEMessage(mesgsys, block_name, block_num, tec); - if (!retval) - return retval; - return applyParsedTEMessage(tec); + LLTEContents tec; + S32 retval = parseTEMessage(mesgsys, block_name, block_num, tec); + if (!retval) + return retval; + return applyParsedTEMessage(tec); } S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) { - // use a negative block_num to indicate a single-block read (a non-variable block) - S32 retval = 0; - const U32 MAX_TES = 45; + // use a negative block_num to indicate a single-block read (a non-variable block) + S32 retval = 0; + const U32 MAX_TES = 45; - // Avoid construction of 32 UUIDs per call - static LLMaterialID material_ids[MAX_TES]; + // Avoid construction of 32 UUIDs per call + static LLMaterialID material_ids[MAX_TES]; const U32 MAX_TE_BUFFER = 4096; U8 packed_buffer[MAX_TE_BUFFER]; @@ -1504,7 +1504,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) U8 media_flags[MAX_TES]; U8 glow[MAX_TES]; material_id_type material_data[MAX_TES]; - + memset((void*)scale_s, 0, sizeof(scale_s)); memset((void*)scale_t, 0, sizeof(scale_t)); memset((void*)offset_s, 0, sizeof(offset_s)); @@ -1514,32 +1514,32 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) memset((void*)media_flags, 0, sizeof(media_flags)); memset((void*)glow, 0, sizeof(glow)); - S32 size; - U32 face_count = 0; + S32 size; + U32 face_count = 0; - if (!dp.unpackBinaryData(packed_buffer, size, "TextureEntry")) - { - retval = TEM_INVALID; - LL_WARNS() << "Bad texture entry block! Abort!" << LL_ENDL; - return retval; - } + if (!dp.unpackBinaryData(packed_buffer, size, "TextureEntry")) + { + retval = TEM_INVALID; + LL_WARNS() << "Bad texture entry block! Abort!" << LL_ENDL; + return retval; + } - if (size == 0) - { - return retval; - } + if (size == 0) + { + return retval; + } else if (size >= MAX_TE_BUFFER) { LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL; size = MAX_TE_BUFFER - 1; } - // The last field is not zero terminated. + // The last field is not zero terminated. // Rather than special case the upack functions. Just make it 0x00 terminated. packed_buffer[size] = 0x00; ++size; - face_count = llmin((U32) getNumTEs(), MAX_TES); - U32 i; + face_count = llmin((U32) getNumTEs(), MAX_TES); + U32 i; U8 *cur_ptr = packed_buffer; LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffer sized: " << size << LL_ENDL; @@ -1560,81 +1560,81 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp) return 0; } - if (cur_ptr >= buffer_end || !unpack_TEField(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID)) - { - memset((void*)material_data, 0, sizeof(material_data)); - } - - for (i = 0; i < face_count; i++) - { - material_ids[i].set(&(material_data[i])); - } - - LLColor4 color; - for (i = 0; i < face_count; i++) - { - retval |= setTETexture(i, ((LLUUID*)image_data)[i]); - retval |= setTEScale(i, scale_s[i], scale_t[i]); - retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); - retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); - retval |= setTEBumpShinyFullbright(i, bump[i]); - retval |= setTEMediaTexGen(i, media_flags[i]); - retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); - retval |= setTEMaterialID(i, material_ids[i]); + if (cur_ptr >= buffer_end || !unpack_TEField(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID)) + { + memset((void*)material_data, 0, sizeof(material_data)); + } - // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) - // as all zeros. However, the subtraction and addition must be done in unsigned - // byte space, not in float space, otherwise off-by-one errors occur. JC - color.mV[VRED] = F32(255 - colors[i].mV[VRED]) / 255.f; - color.mV[VGREEN] = F32(255 - colors[i].mV[VGREEN]) / 255.f; - color.mV[VBLUE] = F32(255 - colors[i].mV[VBLUE]) / 255.f; - color.mV[VALPHA] = F32(255 - colors[i].mV[VALPHA]) / 255.f; + for (i = 0; i < face_count; i++) + { + material_ids[i].set(&(material_data[i])); + } - retval |= setTEColor(i, color); - } + LLColor4 color; + for (i = 0; i < face_count; i++) + { + retval |= setTETexture(i, ((LLUUID*)image_data)[i]); + retval |= setTEScale(i, scale_s[i], scale_t[i]); + retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF); + retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI); + retval |= setTEBumpShinyFullbright(i, bump[i]); + retval |= setTEMediaTexGen(i, media_flags[i]); + retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF); + retval |= setTEMaterialID(i, material_ids[i]); + + // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f) + // as all zeros. However, the subtraction and addition must be done in unsigned + // byte space, not in float space, otherwise off-by-one errors occur. JC + color.mV[VRED] = F32(255 - colors[i].mV[VRED]) / 255.f; + color.mV[VGREEN] = F32(255 - colors[i].mV[VGREEN]) / 255.f; + color.mV[VBLUE] = F32(255 - colors[i].mV[VBLUE]) / 255.f; + color.mV[VALPHA] = F32(255 - colors[i].mV[VALPHA]) / 255.f; + + retval |= setTEColor(i, color); + } - return retval; + return retval; } -U8 LLPrimitive::getExpectedNumTEs() const +U8 LLPrimitive::getExpectedNumTEs() const { - U8 expected_face_count = 0; - if (mVolumep) - { - expected_face_count = mVolumep->getNumFaces(); - } - return expected_face_count; + U8 expected_face_count = 0; + if (mVolumep) + { + expected_face_count = mVolumep->getNumFaces(); + } + return expected_face_count; } void LLPrimitive::copyTextureList(const LLPrimTextureList& other_list) { - mTextureList.copy(other_list); + mTextureList.copy(other_list); } void LLPrimitive::takeTextureList(LLPrimTextureList& other_list) { - mTextureList.take(other_list); + mTextureList.take(other_list); } void LLPrimitive::updateNumBumpmap(const U8 index, const U8 bump) { - LLTextureEntry* te = getTE(index); - if(!te) - { - return; - } + LLTextureEntry* te = getTE(index); + if(!te) + { + return; + } - U8 old_bump = te->getBumpmap(); - if(old_bump > 0) - { - mNumBumpmapTEs--; - } - if((bump & TEM_BUMP_MASK) > 0) - { - mNumBumpmapTEs++; - } + U8 old_bump = te->getBumpmap(); + if(old_bump > 0) + { + mNumBumpmapTEs--; + } + if((bump & TEM_BUMP_MASK) > 0) + { + mNumBumpmapTEs++; + } - return; + return; } //============================================================================ @@ -1645,180 +1645,180 @@ void LLPrimitive::updateNumBumpmap(const U8 index, const U8 bump) // static bool LLPrimitive::getTESTAxes(const U8 face, U32* s_axis, U32* t_axis) { - if (face == 0) - { - *s_axis = VX; *t_axis = VY; - return true; - } - else if (face == 1) - { - *s_axis = VX; *t_axis = VZ; - return true; - } - else if (face == 2) - { - *s_axis = VY; *t_axis = VZ; - return true; - } - else if (face == 3) - { - *s_axis = VX; *t_axis = VZ; - return true; - } - else if (face == 4) - { - *s_axis = VY; *t_axis = VZ; - return true; - } - else if (face >= 5) - { - *s_axis = VX; *t_axis = VY; - return true; - } - else - { - // unknown face - return false; - } + if (face == 0) + { + *s_axis = VX; *t_axis = VY; + return true; + } + else if (face == 1) + { + *s_axis = VX; *t_axis = VZ; + return true; + } + else if (face == 2) + { + *s_axis = VY; *t_axis = VZ; + return true; + } + else if (face == 3) + { + *s_axis = VX; *t_axis = VZ; + return true; + } + else if (face == 4) + { + *s_axis = VY; *t_axis = VZ; + return true; + } + else if (face >= 5) + { + *s_axis = VX; *t_axis = VY; + return true; + } + else + { + // unknown face + return false; + } } //============================================================================ -//static +//static BOOL LLNetworkData::isValid(U16 param_type, U32 size) { - // ew - better mechanism needed - - switch(param_type) - { - case PARAMS_FLEXIBLE: - return (size == 16); - case PARAMS_LIGHT: - return (size == 16); - case PARAMS_SCULPT: - return (size == 17); - case PARAMS_LIGHT_IMAGE: - return (size == 28); + // ew - better mechanism needed + + switch(param_type) + { + case PARAMS_FLEXIBLE: + return (size == 16); + case PARAMS_LIGHT: + return (size == 16); + case PARAMS_SCULPT: + return (size == 17); + case PARAMS_LIGHT_IMAGE: + return (size == 28); case PARAMS_EXTENDED_MESH: return (size == 4); case PARAMS_RENDER_MATERIAL: return (size > 1); case PARAMS_REFLECTION_PROBE: return (size == 9); - } - - return FALSE; + } + + return FALSE; } //============================================================================ LLLightParams::LLLightParams() { - mColor.setToWhite(); - mRadius = 10.f; - mCutoff = 0.0f; - mFalloff = 0.75f; + mColor.setToWhite(); + mRadius = 10.f; + mCutoff = 0.0f; + mFalloff = 0.75f; - mType = PARAMS_LIGHT; + mType = PARAMS_LIGHT; } BOOL LLLightParams::pack(LLDataPacker &dp) const { - LLColor4U color4u(mColor); - dp.packColor4U(color4u, "color"); - dp.packF32(mRadius, "radius"); - dp.packF32(mCutoff, "cutoff"); - dp.packF32(mFalloff, "falloff"); - return TRUE; + LLColor4U color4u(mColor); + dp.packColor4U(color4u, "color"); + dp.packF32(mRadius, "radius"); + dp.packF32(mCutoff, "cutoff"); + dp.packF32(mFalloff, "falloff"); + return TRUE; } BOOL LLLightParams::unpack(LLDataPacker &dp) { - LLColor4U color; - dp.unpackColor4U(color, "color"); - setLinearColor(LLColor4(color)); + LLColor4U color; + dp.unpackColor4U(color, "color"); + setLinearColor(LLColor4(color)); - F32 radius; - dp.unpackF32(radius, "radius"); - setRadius(radius); + F32 radius; + dp.unpackF32(radius, "radius"); + setRadius(radius); - F32 cutoff; - dp.unpackF32(cutoff, "cutoff"); - setCutoff(cutoff); + F32 cutoff; + dp.unpackF32(cutoff, "cutoff"); + setCutoff(cutoff); - F32 falloff; - dp.unpackF32(falloff, "falloff"); - setFalloff(falloff); - - return TRUE; + F32 falloff; + dp.unpackF32(falloff, "falloff"); + setFalloff(falloff); + + return TRUE; } bool LLLightParams::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_LIGHT) - { - return false; - } - const LLLightParams *param = (const LLLightParams*)&data; - if (param->mColor != mColor || - param->mRadius != mRadius || - param->mCutoff != mCutoff || - param->mFalloff != mFalloff) - { - return false; - } - return true; + if (data.mType != PARAMS_LIGHT) + { + return false; + } + const LLLightParams *param = (const LLLightParams*)&data; + if (param->mColor != mColor || + param->mRadius != mRadius || + param->mCutoff != mCutoff || + param->mFalloff != mFalloff) + { + return false; + } + return true; } void LLLightParams::copy(const LLNetworkData& data) { - const LLLightParams *param = (LLLightParams*)&data; - mType = param->mType; - mColor = param->mColor; - mRadius = param->mRadius; - mCutoff = param->mCutoff; - mFalloff = param->mFalloff; + const LLLightParams *param = (LLLightParams*)&data; + mType = param->mType; + mColor = param->mColor; + mRadius = param->mRadius; + mCutoff = param->mCutoff; + mFalloff = param->mFalloff; } LLSD LLLightParams::asLLSD() const { - LLSD sd; - - sd["color"] = ll_sd_from_color4(getLinearColor()); - sd["radius"] = getRadius(); - sd["falloff"] = getFalloff(); - sd["cutoff"] = getCutoff(); - - return sd; + LLSD sd; + + sd["color"] = ll_sd_from_color4(getLinearColor()); + sd["radius"] = getRadius(); + sd["falloff"] = getFalloff(); + sd["cutoff"] = getCutoff(); + + return sd; } bool LLLightParams::fromLLSD(LLSD& sd) { - const char *w; - w = "color"; - if (sd.has(w)) - { - setLinearColor( ll_color4_from_sd(sd["color"]) ); - } else goto fail; - w = "radius"; - if (sd.has(w)) - { - setRadius( (F32)sd[w].asReal() ); - } else goto fail; - w = "falloff"; - if (sd.has(w)) - { - setFalloff( (F32)sd[w].asReal() ); - } else goto fail; - w = "cutoff"; - if (sd.has(w)) - { - setCutoff( (F32)sd[w].asReal() ); - } else goto fail; - - return true; + const char *w; + w = "color"; + if (sd.has(w)) + { + setLinearColor( ll_color4_from_sd(sd["color"]) ); + } else goto fail; + w = "radius"; + if (sd.has(w)) + { + setRadius( (F32)sd[w].asReal() ); + } else goto fail; + w = "falloff"; + if (sd.has(w)) + { + setFalloff( (F32)sd[w].asReal() ); + } else goto fail; + w = "cutoff"; + if (sd.has(w)) + { + setCutoff( (F32)sd[w].asReal() ); + } else goto fail; + + return true; fail: - return false; + return false; } //============================================================================ @@ -1832,39 +1832,39 @@ LLReflectionProbeParams::LLReflectionProbeParams() BOOL LLReflectionProbeParams::pack(LLDataPacker &dp) const { - dp.packF32(mAmbiance, "ambiance"); + dp.packF32(mAmbiance, "ambiance"); dp.packF32(mClipDistance, "clip_distance"); dp.packU8(mFlags, "flags"); - return TRUE; + return TRUE; } BOOL LLReflectionProbeParams::unpack(LLDataPacker &dp) { - F32 ambiance; + F32 ambiance; F32 clip_distance; - dp.unpackF32(ambiance, "ambiance"); - setAmbiance(ambiance); - + dp.unpackF32(ambiance, "ambiance"); + setAmbiance(ambiance); + dp.unpackF32(clip_distance, "clip_distance"); - setClipDistance(clip_distance); - + setClipDistance(clip_distance); + dp.unpackU8(mFlags, "flags"); - - return TRUE; + + 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; @@ -1873,25 +1873,25 @@ bool LLReflectionProbeParams::operator==(const LLNetworkData& data) const { 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; mFlags = param->mFlags; } LLSD LLReflectionProbeParams::asLLSD() const { - LLSD sd; - sd["ambiance"] = getAmbiance(); + LLSD sd; + sd["ambiance"] = getAmbiance(); sd["clip_distance"] = getClipDistance(); sd["flags"] = mFlags; - return sd; + return sd; } bool LLReflectionProbeParams::fromLLSD(LLSD& sd) @@ -1903,10 +1903,10 @@ bool LLReflectionProbeParams::fromLLSD(LLSD& sd) return false; } - setAmbiance((F32)sd["ambiance"].asReal()); + setAmbiance((F32)sd["ambiance"].asReal()); setClipDistance((F32)sd["clip_distance"].asReal()); mFlags = (U8) sd["flags"].asInteger(); - + return true; } @@ -1950,312 +1950,312 @@ void LLReflectionProbeParams::setIsMirror(bool is_mirror) //============================================================================ LLFlexibleObjectData::LLFlexibleObjectData() { - mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS; - mGravity = FLEXIBLE_OBJECT_DEFAULT_GRAVITY; - mAirFriction = FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION; - mWindSensitivity = FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY; - mTension = FLEXIBLE_OBJECT_DEFAULT_TENSION; - //mUsingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE; - //mRenderingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE; - mUserForce = LLVector3(0.f, 0.f, 0.f); + mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS; + mGravity = FLEXIBLE_OBJECT_DEFAULT_GRAVITY; + mAirFriction = FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION; + mWindSensitivity = FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY; + mTension = FLEXIBLE_OBJECT_DEFAULT_TENSION; + //mUsingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE; + //mRenderingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE; + mUserForce = LLVector3(0.f, 0.f, 0.f); - mType = PARAMS_FLEXIBLE; + mType = PARAMS_FLEXIBLE; } BOOL LLFlexibleObjectData::pack(LLDataPacker &dp) const { - // Custom, uber-svelte pack "softness" in upper bits of tension & drag - U8 bit1 = (mSimulateLOD & 2) << 6; - U8 bit2 = (mSimulateLOD & 1) << 7; - dp.packU8((U8)(mTension*10.01f) + bit1, "tension"); - dp.packU8((U8)(mAirFriction*10.01f) + bit2, "drag"); - dp.packU8((U8)((mGravity+10.f)*10.01f), "gravity"); - dp.packU8((U8)(mWindSensitivity*10.01f), "wind"); - dp.packVector3(mUserForce, "userforce"); - return TRUE; + // Custom, uber-svelte pack "softness" in upper bits of tension & drag + U8 bit1 = (mSimulateLOD & 2) << 6; + U8 bit2 = (mSimulateLOD & 1) << 7; + dp.packU8((U8)(mTension*10.01f) + bit1, "tension"); + dp.packU8((U8)(mAirFriction*10.01f) + bit2, "drag"); + dp.packU8((U8)((mGravity+10.f)*10.01f), "gravity"); + dp.packU8((U8)(mWindSensitivity*10.01f), "wind"); + dp.packVector3(mUserForce, "userforce"); + return TRUE; } BOOL LLFlexibleObjectData::unpack(LLDataPacker &dp) { - U8 tension, friction, gravity, wind; - U8 bit1, bit2; - dp.unpackU8(tension, "tension"); bit1 = (tension >> 6) & 2; - mTension = ((F32)(tension&0x7f))/10.f; - dp.unpackU8(friction, "drag"); bit2 = (friction >> 7) & 1; - mAirFriction = ((F32)(friction&0x7f))/10.f; - mSimulateLOD = bit1 | bit2; - dp.unpackU8(gravity, "gravity"); mGravity = ((F32)gravity)/10.f - 10.f; - dp.unpackU8(wind, "wind"); mWindSensitivity = ((F32)wind)/10.f; - if (dp.hasNext()) - { - dp.unpackVector3(mUserForce, "userforce"); - } - else - { - mUserForce.setVec(0.f, 0.f, 0.f); - } - return TRUE; + U8 tension, friction, gravity, wind; + U8 bit1, bit2; + dp.unpackU8(tension, "tension"); bit1 = (tension >> 6) & 2; + mTension = ((F32)(tension&0x7f))/10.f; + dp.unpackU8(friction, "drag"); bit2 = (friction >> 7) & 1; + mAirFriction = ((F32)(friction&0x7f))/10.f; + mSimulateLOD = bit1 | bit2; + dp.unpackU8(gravity, "gravity"); mGravity = ((F32)gravity)/10.f - 10.f; + dp.unpackU8(wind, "wind"); mWindSensitivity = ((F32)wind)/10.f; + if (dp.hasNext()) + { + dp.unpackVector3(mUserForce, "userforce"); + } + else + { + mUserForce.setVec(0.f, 0.f, 0.f); + } + return TRUE; } bool LLFlexibleObjectData::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_FLEXIBLE) - { - return false; - } - LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; - return (mSimulateLOD == flex_data->mSimulateLOD && - mGravity == flex_data->mGravity && - mAirFriction == flex_data->mAirFriction && - mWindSensitivity == flex_data->mWindSensitivity && - mTension == flex_data->mTension && - mUserForce == flex_data->mUserForce); - //mUsingCollisionSphere == flex_data->mUsingCollisionSphere && - //mRenderingCollisionSphere == flex_data->mRenderingCollisionSphere + if (data.mType != PARAMS_FLEXIBLE) + { + return false; + } + LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; + return (mSimulateLOD == flex_data->mSimulateLOD && + mGravity == flex_data->mGravity && + mAirFriction == flex_data->mAirFriction && + mWindSensitivity == flex_data->mWindSensitivity && + mTension == flex_data->mTension && + mUserForce == flex_data->mUserForce); + //mUsingCollisionSphere == flex_data->mUsingCollisionSphere && + //mRenderingCollisionSphere == flex_data->mRenderingCollisionSphere } void LLFlexibleObjectData::copy(const LLNetworkData& data) { - const LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; - mSimulateLOD = flex_data->mSimulateLOD; - mGravity = flex_data->mGravity; - mAirFriction = flex_data->mAirFriction; - mWindSensitivity = flex_data->mWindSensitivity; - mTension = flex_data->mTension; - mUserForce = flex_data->mUserForce; - //mUsingCollisionSphere = flex_data->mUsingCollisionSphere; - //mRenderingCollisionSphere = flex_data->mRenderingCollisionSphere; + const LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data; + mSimulateLOD = flex_data->mSimulateLOD; + mGravity = flex_data->mGravity; + mAirFriction = flex_data->mAirFriction; + mWindSensitivity = flex_data->mWindSensitivity; + mTension = flex_data->mTension; + mUserForce = flex_data->mUserForce; + //mUsingCollisionSphere = flex_data->mUsingCollisionSphere; + //mRenderingCollisionSphere = flex_data->mRenderingCollisionSphere; } LLSD LLFlexibleObjectData::asLLSD() const { - LLSD sd; + LLSD sd; - sd["air_friction"] = getAirFriction(); - sd["gravity"] = getGravity(); - sd["simulate_lod"] = getSimulateLOD(); - sd["tension"] = getTension(); - sd["user_force"] = getUserForce().getValue(); - sd["wind_sensitivity"] = getWindSensitivity(); - - return sd; + sd["air_friction"] = getAirFriction(); + sd["gravity"] = getGravity(); + sd["simulate_lod"] = getSimulateLOD(); + sd["tension"] = getTension(); + sd["user_force"] = getUserForce().getValue(); + sd["wind_sensitivity"] = getWindSensitivity(); + + return sd; } bool LLFlexibleObjectData::fromLLSD(LLSD& sd) { - const char *w; - w = "air_friction"; - if (sd.has(w)) - { - setAirFriction( (F32)sd[w].asReal() ); - } else goto fail; - w = "gravity"; - if (sd.has(w)) - { - setGravity( (F32)sd[w].asReal() ); - } else goto fail; - w = "simulate_lod"; - if (sd.has(w)) - { - setSimulateLOD( sd[w].asInteger() ); - } else goto fail; - w = "tension"; - if (sd.has(w)) - { - setTension( (F32)sd[w].asReal() ); - } else goto fail; - w = "user_force"; - if (sd.has(w)) - { - LLVector3 user_force = ll_vector3_from_sd(sd[w], 0); - setUserForce( user_force ); - } else goto fail; - w = "wind_sensitivity"; - if (sd.has(w)) - { - setWindSensitivity( (F32)sd[w].asReal() ); - } else goto fail; - - return true; + const char *w; + w = "air_friction"; + if (sd.has(w)) + { + setAirFriction( (F32)sd[w].asReal() ); + } else goto fail; + w = "gravity"; + if (sd.has(w)) + { + setGravity( (F32)sd[w].asReal() ); + } else goto fail; + w = "simulate_lod"; + if (sd.has(w)) + { + setSimulateLOD( sd[w].asInteger() ); + } else goto fail; + w = "tension"; + if (sd.has(w)) + { + setTension( (F32)sd[w].asReal() ); + } else goto fail; + w = "user_force"; + if (sd.has(w)) + { + LLVector3 user_force = ll_vector3_from_sd(sd[w], 0); + setUserForce( user_force ); + } else goto fail; + w = "wind_sensitivity"; + if (sd.has(w)) + { + setWindSensitivity( (F32)sd[w].asReal() ); + } else goto fail; + + return true; fail: - return false; + return false; } //============================================================================ LLSculptParams::LLSculptParams() { - mType = PARAMS_SCULPT; - mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); - mSculptType = LL_SCULPT_TYPE_SPHERE; + mType = PARAMS_SCULPT; + mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptType = LL_SCULPT_TYPE_SPHERE; } BOOL LLSculptParams::pack(LLDataPacker &dp) const { - dp.packUUID(mSculptTexture, "texture"); - dp.packU8(mSculptType, "type"); - - return TRUE; + dp.packUUID(mSculptTexture, "texture"); + dp.packU8(mSculptType, "type"); + + return TRUE; } BOOL LLSculptParams::unpack(LLDataPacker &dp) { - U8 type; - LLUUID id; - dp.unpackUUID(id, "texture"); - dp.unpackU8(type, "type"); + U8 type; + LLUUID id; + dp.unpackUUID(id, "texture"); + dp.unpackU8(type, "type"); - setSculptTexture(id, type); - return TRUE; + setSculptTexture(id, type); + return TRUE; } bool LLSculptParams::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_SCULPT) - { - return false; - } - - const LLSculptParams *param = (const LLSculptParams*)&data; - if ( (param->mSculptTexture != mSculptTexture) || - (param->mSculptType != mSculptType) ) - - { - return false; - } - - return true; + if (data.mType != PARAMS_SCULPT) + { + return false; + } + + const LLSculptParams *param = (const LLSculptParams*)&data; + if ( (param->mSculptTexture != mSculptTexture) || + (param->mSculptType != mSculptType) ) + + { + return false; + } + + return true; } void LLSculptParams::copy(const LLNetworkData& data) { - const LLSculptParams *param = (LLSculptParams*)&data; - setSculptTexture(param->mSculptTexture, param->mSculptType); + const LLSculptParams *param = (LLSculptParams*)&data; + setSculptTexture(param->mSculptTexture, param->mSculptType); } LLSD LLSculptParams::asLLSD() const { - LLSD sd; - - sd["texture"] = mSculptTexture; - sd["type"] = mSculptType; - - return sd; + LLSD sd; + + sd["texture"] = mSculptTexture; + sd["type"] = mSculptType; + + return sd; } bool LLSculptParams::fromLLSD(LLSD& sd) { - const char *w; - U8 type; - w = "type"; - if (sd.has(w)) - { - type = sd[w].asInteger(); - } - else return false; + const char *w; + U8 type; + w = "type"; + if (sd.has(w)) + { + type = sd[w].asInteger(); + } + else return false; - w = "texture"; - if (sd.has(w)) - { - setSculptTexture(sd[w], type); - } - else return false; + w = "texture"; + if (sd.has(w)) + { + setSculptTexture(sd[w], type); + } + else return false; - return true; + return true; } void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) { - U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; - U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; - if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) - { - mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); - mSculptType = LL_SCULPT_TYPE_SPHERE; - } - else - { - mSculptTexture = texture_id; - mSculptType = sculpt_type; - } + U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; + U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; + if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) + { + mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptType = LL_SCULPT_TYPE_SPHERE; + } + else + { + mSculptTexture = texture_id; + mSculptType = sculpt_type; + } } //============================================================================ LLLightImageParams::LLLightImageParams() { - mType = PARAMS_LIGHT_IMAGE; - mParams.setVec(F_PI*0.5f, 0.f, 0.f); + mType = PARAMS_LIGHT_IMAGE; + mParams.setVec(F_PI*0.5f, 0.f, 0.f); } BOOL LLLightImageParams::pack(LLDataPacker &dp) const { - dp.packUUID(mLightTexture, "texture"); - dp.packVector3(mParams, "params"); + dp.packUUID(mLightTexture, "texture"); + dp.packVector3(mParams, "params"); - return TRUE; + return TRUE; } BOOL LLLightImageParams::unpack(LLDataPacker &dp) { - dp.unpackUUID(mLightTexture, "texture"); - dp.unpackVector3(mParams, "params"); - - return TRUE; + dp.unpackUUID(mLightTexture, "texture"); + dp.unpackVector3(mParams, "params"); + + return TRUE; } bool LLLightImageParams::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_LIGHT_IMAGE) - { - return false; - } - - const LLLightImageParams *param = (const LLLightImageParams*)&data; - if ( (param->mLightTexture != mLightTexture) ) - { - return false; - } - - if ( (param->mParams != mParams ) ) - { - return false; - } - - return true; + if (data.mType != PARAMS_LIGHT_IMAGE) + { + return false; + } + + const LLLightImageParams *param = (const LLLightImageParams*)&data; + if ( (param->mLightTexture != mLightTexture) ) + { + return false; + } + + if ( (param->mParams != mParams ) ) + { + return false; + } + + return true; } void LLLightImageParams::copy(const LLNetworkData& data) { - const LLLightImageParams *param = (LLLightImageParams*)&data; - mLightTexture = param->mLightTexture; - mParams = param->mParams; + const LLLightImageParams *param = (LLLightImageParams*)&data; + mLightTexture = param->mLightTexture; + mParams = param->mParams; } LLSD LLLightImageParams::asLLSD() const { - LLSD sd; - - sd["texture"] = mLightTexture; - sd["params"] = mParams.getValue(); - - return sd; + LLSD sd; + + sd["texture"] = mLightTexture; + sd["params"] = mParams.getValue(); + + return sd; } bool LLLightImageParams::fromLLSD(LLSD& sd) { - if (sd.has("texture")) - { - setLightTexture( sd["texture"] ); - setParams( LLVector3( sd["params"] ) ); - return true; - } - - return false; + if (sd.has("texture")) + { + setLightTexture( sd["texture"] ); + setParams( LLVector3( sd["params"] ) ); + return true; + } + + return false; } //============================================================================ @@ -2263,63 +2263,63 @@ bool LLLightImageParams::fromLLSD(LLSD& sd) LLExtendedMeshParams::LLExtendedMeshParams() { mType = PARAMS_EXTENDED_MESH; - mFlags = 0; + mFlags = 0; } BOOL LLExtendedMeshParams::pack(LLDataPacker &dp) const { - dp.packU32(mFlags, "flags"); + dp.packU32(mFlags, "flags"); - return TRUE; + return TRUE; } BOOL LLExtendedMeshParams::unpack(LLDataPacker &dp) { - dp.unpackU32(mFlags, "flags"); - - return TRUE; + dp.unpackU32(mFlags, "flags"); + + return TRUE; } bool LLExtendedMeshParams::operator==(const LLNetworkData& data) const { - if (data.mType != PARAMS_EXTENDED_MESH) - { - return false; - } - - const LLExtendedMeshParams *param = (const LLExtendedMeshParams*)&data; - if ( (param->mFlags != mFlags) ) - { - return false; - } + if (data.mType != PARAMS_EXTENDED_MESH) + { + return false; + } - return true; + const LLExtendedMeshParams *param = (const LLExtendedMeshParams*)&data; + if ( (param->mFlags != mFlags) ) + { + return false; + } + + return true; } void LLExtendedMeshParams::copy(const LLNetworkData& data) { - const LLExtendedMeshParams *param = (LLExtendedMeshParams*)&data; - mFlags = param->mFlags; + const LLExtendedMeshParams *param = (LLExtendedMeshParams*)&data; + mFlags = param->mFlags; } LLSD LLExtendedMeshParams::asLLSD() const { - LLSD sd; - - sd["flags"] = LLSD::Integer(mFlags); - - return sd; + LLSD sd; + + sd["flags"] = LLSD::Integer(mFlags); + + return sd; } bool LLExtendedMeshParams::fromLLSD(LLSD& sd) { - if (sd.has("flags")) - { - setFlags( sd["flags"].asInteger()); - return true; - } - - return false; + if (sd.has("flags")) + { + setFlags( sd["flags"].asInteger()); + return true; + } + + return false; } //============================================================================ diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 5622483861..6078abf67e 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -1,25 +1,25 @@ -/** +/** * @file llprimitive.h * @brief LLPrimitive base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -49,14 +49,14 @@ class LLVolumeMgr; enum LLGeomType // NOTE: same vals as GL Ids { - LLInvalid = 0, - LLLineLoop = 2, - LLLineStrip = 3, - LLTriangles = 4, - LLTriStrip = 5, - LLTriFan = 6, - LLQuads = 7, - LLQuadStrip = 8 + LLInvalid = 0, + LLLineLoop = 2, + LLLineStrip = 3, + LLTriangles = 4, + LLTriStrip = 5, + LLTriFan = 6, + LLQuads = 7, + LLQuadStrip = 8 }; class LLVolume; @@ -97,28 +97,28 @@ extern const char *SCULPT_DEFAULT_TEXTURE; class LLNetworkData { public: - // Extra parameter IDs - enum - { - PARAMS_FLEXIBLE = 0x10, - PARAMS_LIGHT = 0x20, - PARAMS_SCULPT = 0x30, - PARAMS_LIGHT_IMAGE = 0x40, - PARAMS_RESERVED = 0x50, // Used on server-side - PARAMS_MESH = 0x60, + // Extra parameter IDs + enum + { + PARAMS_FLEXIBLE = 0x10, + PARAMS_LIGHT = 0x20, + PARAMS_SCULPT = 0x30, + PARAMS_LIGHT_IMAGE = 0x40, + PARAMS_RESERVED = 0x50, // Used on server-side + PARAMS_MESH = 0x60, PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, - }; - + }; + public: - U16 mType; - virtual ~LLNetworkData() {}; - virtual BOOL pack(LLDataPacker &dp) const = 0; - virtual BOOL unpack(LLDataPacker &dp) = 0; - virtual bool operator==(const LLNetworkData& data) const = 0; - virtual void copy(const LLNetworkData& data) = 0; - static BOOL isValid(U16 param_type, U32 size); + U16 mType; + virtual ~LLNetworkData() {}; + virtual BOOL pack(LLDataPacker &dp) const = 0; + virtual BOOL unpack(LLDataPacker &dp) = 0; + virtual bool operator==(const LLNetworkData& data) const = 0; + virtual void copy(const LLNetworkData& data) = 0; + static BOOL isValid(U16 param_type, U32 size); }; extern const F32 LIGHT_MIN_RADIUS; @@ -134,22 +134,22 @@ extern const F32 LIGHT_MAX_CUTOFF; class LLLightParams : public LLNetworkData { private: - LLColor4 mColor; // linear color (not gamma corrected), alpha = intensity - F32 mRadius; - F32 mFalloff; - F32 mCutoff; + LLColor4 mColor; // linear color (not gamma corrected), alpha = intensity + F32 mRadius; + F32 mFalloff; + F32 mCutoff; public: - LLLightParams(); - /*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); + LLLightParams(); + /*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); // set the color by gamma corrected color value // color - gamma corrected color value (directly taken from an on-screen color swatch) @@ -157,19 +157,19 @@ public: // set the color by linear color value // color - linear color value (value as it appears in shaders) - void setLinearColor(const LLColor4& color) { mColor = color; mColor.clamp(); } - void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } - void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } - void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } + void setLinearColor(const LLColor4& color) { mColor = color; mColor.clamp(); } + void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); } + void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); } + void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); } // get the linear space color of this light. This value can be fed directly to shaders - LLColor4 getLinearColor() const { return mColor; } + LLColor4 getLinearColor() const { return mColor; } // get the sRGB (gamma corrected) color of this light, this is the value that should be displayed in the UI - LLColor4 getSRGBColor() const { return srgbColor4(mColor); } - - F32 getRadius() const { return mRadius; } - F32 getFalloff() const { return mFalloff; } - F32 getCutoff() const { return mCutoff; } + LLColor4 getSRGBColor() const { return srgbColor4(mColor); } + + F32 getRadius() const { return mRadius; } + F32 getFalloff() const { return mFalloff; } + F32 getCutoff() const { return mCutoff; } }; extern const F32 REFLECTION_PROBE_MIN_AMBIANCE; @@ -186,7 +186,7 @@ public: { FLAG_BOX_VOLUME = 0x01, // use a box influence volume FLAG_DYNAMIC = 0x02, // render dynamic objects (avatars) into this Reflection Probe - FLAG_MIRROR = 0x04, // This probe is used for reflections on realtime mirrors. + FLAG_MIRROR = 0x04, // This probe is used for reflections on realtime mirrors. }; protected: @@ -220,7 +220,7 @@ public: }; //------------------------------------------------- -// This structure is also used in the part of the +// This structure is also used in the part of the // code that creates new flexible objects. //------------------------------------------------- @@ -228,11 +228,11 @@ public: // array bounds. enum EFlexibleObjectConst { - // "Softness" => [0,3], increments of 1 - // Represents powers of 2: 0 -> 1, 3 -> 8 - FLEXIBLE_OBJECT_MIN_SECTIONS = 0, - FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS = 2, - FLEXIBLE_OBJECT_MAX_SECTIONS = 3 + // "Softness" => [0,3], increments of 1 + // Represents powers of 2: 0 -> 1, 3 -> 8 + FLEXIBLE_OBJECT_MIN_SECTIONS = 0, + FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS = 2, + FLEXIBLE_OBJECT_MAX_SECTIONS = 3 }; // "Tension" => [0,10], increments of 0.1 @@ -265,39 +265,39 @@ extern const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE; class LLFlexibleObjectData : public LLNetworkData { protected: - S32 mSimulateLOD; // 2^n = number of simulated sections - F32 mGravity; - F32 mAirFriction; // higher is more stable, but too much looks like it's underwater - F32 mWindSensitivity; // interacts with tension, air friction, and gravity - F32 mTension; //interacts in complex ways with other parameters - LLVector3 mUserForce; // custom user-defined force vector - //BOOL mUsingCollisionSphere; - //BOOL mRenderingCollisionSphere; + S32 mSimulateLOD; // 2^n = number of simulated sections + F32 mGravity; + F32 mAirFriction; // higher is more stable, but too much looks like it's underwater + F32 mWindSensitivity; // interacts with tension, air friction, and gravity + F32 mTension; //interacts in complex ways with other parameters + LLVector3 mUserForce; // custom user-defined force vector + //BOOL mUsingCollisionSphere; + //BOOL mRenderingCollisionSphere; public: - void setSimulateLOD(S32 lod) { mSimulateLOD = llclamp(lod, (S32)FLEXIBLE_OBJECT_MIN_SECTIONS, (S32)FLEXIBLE_OBJECT_MAX_SECTIONS); } - void setGravity(F32 gravity) { mGravity = llclamp(gravity, FLEXIBLE_OBJECT_MIN_GRAVITY, FLEXIBLE_OBJECT_MAX_GRAVITY); } - void setAirFriction(F32 friction) { mAirFriction = llclamp(friction, FLEXIBLE_OBJECT_MIN_AIR_FRICTION, FLEXIBLE_OBJECT_MAX_AIR_FRICTION); } - void setWindSensitivity(F32 wind) { mWindSensitivity = llclamp(wind, FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY, FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY); } - void setTension(F32 tension) { mTension = llclamp(tension, FLEXIBLE_OBJECT_MIN_TENSION, FLEXIBLE_OBJECT_MAX_TENSION); } - void setUserForce(LLVector3 &force) { mUserForce = force; } - - S32 getSimulateLOD() const { return mSimulateLOD; } - F32 getGravity() const { return mGravity; } - F32 getAirFriction() const { return mAirFriction; } - F32 getWindSensitivity() const { return mWindSensitivity; } - F32 getTension() const { return mTension; } - LLVector3 getUserForce() const { return mUserForce; } - - //------ the constructor for the structure ------------ - LLFlexibleObjectData(); - BOOL pack(LLDataPacker &dp) const; - BOOL unpack(LLDataPacker &dp); - bool operator==(const LLNetworkData& data) const; - void copy(const LLNetworkData& data); - LLSD asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); + void setSimulateLOD(S32 lod) { mSimulateLOD = llclamp(lod, (S32)FLEXIBLE_OBJECT_MIN_SECTIONS, (S32)FLEXIBLE_OBJECT_MAX_SECTIONS); } + void setGravity(F32 gravity) { mGravity = llclamp(gravity, FLEXIBLE_OBJECT_MIN_GRAVITY, FLEXIBLE_OBJECT_MAX_GRAVITY); } + void setAirFriction(F32 friction) { mAirFriction = llclamp(friction, FLEXIBLE_OBJECT_MIN_AIR_FRICTION, FLEXIBLE_OBJECT_MAX_AIR_FRICTION); } + void setWindSensitivity(F32 wind) { mWindSensitivity = llclamp(wind, FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY, FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY); } + void setTension(F32 tension) { mTension = llclamp(tension, FLEXIBLE_OBJECT_MIN_TENSION, FLEXIBLE_OBJECT_MAX_TENSION); } + void setUserForce(LLVector3 &force) { mUserForce = force; } + + S32 getSimulateLOD() const { return mSimulateLOD; } + F32 getGravity() const { return mGravity; } + F32 getAirFriction() const { return mAirFriction; } + F32 getWindSensitivity() const { return mWindSensitivity; } + F32 getTension() const { return mTension; } + LLVector3 getUserForce() const { return mUserForce; } + + //------ the constructor for the structure ------------ + LLFlexibleObjectData(); + BOOL pack(LLDataPacker &dp) const; + BOOL unpack(LLDataPacker &dp); + bool operator==(const LLNetworkData& data) const; + void copy(const LLNetworkData& data); + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); };// end of attributes structure @@ -305,68 +305,68 @@ public: class LLSculptParams : public LLNetworkData { protected: - LLUUID mSculptTexture; - U8 mSculptType; - + LLUUID mSculptTexture; + U8 mSculptType; + public: - LLSculptParams(); - /*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 asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); - LLUUID getSculptTexture() const { return mSculptTexture; } - U8 getSculptType() const { return mSculptType; } + LLSculptParams(); + /*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 asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); + LLUUID getSculptTexture() const { return mSculptTexture; } + U8 getSculptType() const { return mSculptType; } }; class LLLightImageParams : public LLNetworkData { protected: - LLUUID mLightTexture; - LLVector3 mParams; - + LLUUID mLightTexture; + LLVector3 mParams; + public: - LLLightImageParams(); - /*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 asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - void setLightTexture(const LLUUID& id) { mLightTexture = id; } - LLUUID getLightTexture() const { return mLightTexture; } - bool isLightSpotlight() const { return mLightTexture.notNull(); } - void setParams(const LLVector3& params) { mParams = params; } - LLVector3 getParams() const { return mParams; } - + LLLightImageParams(); + /*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 asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setLightTexture(const LLUUID& id) { mLightTexture = id; } + LLUUID getLightTexture() const { return mLightTexture; } + bool isLightSpotlight() const { return mLightTexture.notNull(); } + void setParams(const LLVector3& params) { mParams = params; } + LLVector3 getParams() const { return mParams; } + }; class LLExtendedMeshParams : public LLNetworkData { protected: - U32 mFlags; - + U32 mFlags; + public: - static const U32 ANIMATED_MESH_ENABLED_FLAG = 0x1 << 0; - - LLExtendedMeshParams(); - /*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 asLLSD() const; - operator LLSD() const { return asLLSD(); } - bool fromLLSD(LLSD& sd); - - void setFlags(const U32& flags) { mFlags = flags; } + static const U32 ANIMATED_MESH_ENABLED_FLAG = 0x1 << 0; + + LLExtendedMeshParams(); + /*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 asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setFlags(const U32& flags) { mFlags = flags; } U32 getFlags() const { return mFlags; } - + }; class LLRenderMaterialParams : public LLNetworkData @@ -385,7 +385,7 @@ public: BOOL unpack(LLDataPacker& dp) override; bool operator==(const LLNetworkData& data) const override; void copy(const LLNetworkData& data) override; - + void setMaterial(U8 te_idx, const LLUUID& id); const LLUUID& getMaterial(U8 te_idx) const; @@ -395,249 +395,249 @@ public: // This code is not naming-standards compliant. Leaving it like this for // now to make the connection to code in -// BOOL packTEMessage(LLDataPacker &dp) const; +// BOOL packTEMessage(LLDataPacker &dp) const; // more obvious. This should be refactored to remove the duplication, at which // point we can fix the names as well. // - Vir struct LLTEContents { - static const U32 MAX_TES = 45; + static const U32 MAX_TES = 45; LLUUID image_data[MAX_TES]; LLColor4U colors[MAX_TES]; - F32 scale_s[MAX_TES]; - F32 scale_t[MAX_TES]; - S16 offset_s[MAX_TES]; - S16 offset_t[MAX_TES]; - S16 image_rot[MAX_TES]; - U8 bump[MAX_TES]; - U8 media_flags[MAX_TES]; + F32 scale_s[MAX_TES]; + F32 scale_t[MAX_TES]; + S16 offset_s[MAX_TES]; + S16 offset_t[MAX_TES]; + S16 image_rot[MAX_TES]; + U8 bump[MAX_TES]; + U8 media_flags[MAX_TES]; U8 glow[MAX_TES]; - LLMaterialID material_ids[MAX_TES]; + LLMaterialID material_ids[MAX_TES]; - static const U32 MAX_TE_BUFFER = 4096; - U8 packed_buffer[MAX_TE_BUFFER]; + static const U32 MAX_TE_BUFFER = 4096; + U8 packed_buffer[MAX_TE_BUFFER]; - U32 size; - U32 face_count; + U32 size; + U32 face_count; }; class LLPrimitive : public LLXform { public: - // HACK for removing LLPrimitive's dependency on gVolumeMgr global. - // If a different LLVolumeManager is instantiated and set early enough - // then the LLPrimitive class will use it instead of gVolumeMgr. - static LLVolumeMgr* getVolumeManager() { return sVolumeManager; } - static void setVolumeManager( LLVolumeMgr* volume_manager); - static bool cleanupVolumeManager(); - - // these flags influence how the RigidBody representation is built - static const U32 PRIM_FLAG_PHANTOM = 0x1 << 0; - static const U32 PRIM_FLAG_VOLUME_DETECT = 0x1 << 1; - static const U32 PRIM_FLAG_DYNAMIC = 0x1 << 2; - static const U32 PRIM_FLAG_AVATAR = 0x1 << 3; - static const U32 PRIM_FLAG_SCULPT = 0x1 << 4; - // not used yet, but soon - static const U32 PRIM_FLAG_COLLISION_CALLBACK = 0x1 << 5; - static const U32 PRIM_FLAG_CONVEX = 0x1 << 6; - static const U32 PRIM_FLAG_DEFAULT_VOLUME = 0x1 << 7; - static const U32 PRIM_FLAG_SITTING = 0x1 << 8; - static const U32 PRIM_FLAG_SITTING_ON_GROUND = 0x1 << 9; // Set along with PRIM_FLAG_SITTING - - LLPrimitive(); - virtual ~LLPrimitive(); - - void clearTextureList(); - - static LLPrimitive *createPrimitive(LLPCode p_code); - void init_primitive(LLPCode p_code); - - void setPCode(const LLPCode pcode); - const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume - LLVolume *getVolume() const { return mVolumep; } - virtual BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); - - // Modify texture entry properties - inline BOOL validTE(const U8 te_num) const; - LLTextureEntry* getTE(const U8 te_num) const; - - virtual void setNumTEs(const U8 num_tes); - virtual void setAllTESelected(bool sel); - virtual void setAllTETextures(const LLUUID &tex_id); - virtual void setTE(const U8 index, const LLTextureEntry& te); - virtual S32 setTEColor(const U8 te, const LLColor4 &color); - virtual S32 setTEColor(const U8 te, const LLColor3 &color); - virtual S32 setTEAlpha(const U8 te, const F32 alpha); - virtual S32 setTETexture(const U8 te, const LLUUID &tex_id); - virtual S32 setTEScale (const U8 te, const F32 s, const F32 t); - virtual S32 setTEScaleS(const U8 te, const F32 s); - virtual S32 setTEScaleT(const U8 te, const F32 t); - virtual S32 setTEOffset (const U8 te, const F32 s, const F32 t); - virtual S32 setTEOffsetS(const U8 te, const F32 s); - virtual S32 setTEOffsetT(const U8 te, const F32 t); - virtual S32 setTERotation(const U8 te, const F32 r); - virtual S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); - virtual S32 setTEBumpShiny(const U8 te, const U8 bump); - virtual S32 setTEMediaTexGen(const U8 te, const U8 media); - virtual S32 setTEBumpmap(const U8 te, const U8 bump); - virtual S32 setTETexGen(const U8 te, const U8 texgen); - virtual S32 setTEShiny(const U8 te, const U8 shiny); - virtual S32 setTEFullbright(const U8 te, const U8 fullbright); - virtual S32 setTEMediaFlags(const U8 te, const U8 flags); - virtual S32 setTEGlow(const U8 te, const F32 glow); - virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); + // HACK for removing LLPrimitive's dependency on gVolumeMgr global. + // If a different LLVolumeManager is instantiated and set early enough + // then the LLPrimitive class will use it instead of gVolumeMgr. + static LLVolumeMgr* getVolumeManager() { return sVolumeManager; } + static void setVolumeManager( LLVolumeMgr* volume_manager); + static bool cleanupVolumeManager(); + + // these flags influence how the RigidBody representation is built + static const U32 PRIM_FLAG_PHANTOM = 0x1 << 0; + static const U32 PRIM_FLAG_VOLUME_DETECT = 0x1 << 1; + static const U32 PRIM_FLAG_DYNAMIC = 0x1 << 2; + static const U32 PRIM_FLAG_AVATAR = 0x1 << 3; + static const U32 PRIM_FLAG_SCULPT = 0x1 << 4; + // not used yet, but soon + static const U32 PRIM_FLAG_COLLISION_CALLBACK = 0x1 << 5; + static const U32 PRIM_FLAG_CONVEX = 0x1 << 6; + static const U32 PRIM_FLAG_DEFAULT_VOLUME = 0x1 << 7; + static const U32 PRIM_FLAG_SITTING = 0x1 << 8; + static const U32 PRIM_FLAG_SITTING_ON_GROUND = 0x1 << 9; // Set along with PRIM_FLAG_SITTING + + LLPrimitive(); + virtual ~LLPrimitive(); + + void clearTextureList(); + + static LLPrimitive *createPrimitive(LLPCode p_code); + void init_primitive(LLPCode p_code); + + void setPCode(const LLPCode pcode); + const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume + LLVolume *getVolume() const { return mVolumep; } + virtual BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); + + // Modify texture entry properties + inline BOOL validTE(const U8 te_num) const; + LLTextureEntry* getTE(const U8 te_num) const; + + virtual void setNumTEs(const U8 num_tes); + virtual void setAllTESelected(bool sel); + virtual void setAllTETextures(const LLUUID &tex_id); + virtual void setTE(const U8 index, const LLTextureEntry& te); + virtual S32 setTEColor(const U8 te, const LLColor4 &color); + virtual S32 setTEColor(const U8 te, const LLColor3 &color); + virtual S32 setTEAlpha(const U8 te, const F32 alpha); + virtual S32 setTETexture(const U8 te, const LLUUID &tex_id); + virtual S32 setTEScale (const U8 te, const F32 s, const F32 t); + virtual S32 setTEScaleS(const U8 te, const F32 s); + virtual S32 setTEScaleT(const U8 te, const F32 t); + virtual S32 setTEOffset (const U8 te, const F32 s, const F32 t); + virtual S32 setTEOffsetS(const U8 te, const F32 s); + virtual S32 setTEOffsetT(const U8 te, const F32 t); + virtual S32 setTERotation(const U8 te, const F32 r); + virtual S32 setTEBumpShinyFullbright(const U8 te, const U8 bump); + virtual S32 setTEBumpShiny(const U8 te, const U8 bump); + virtual S32 setTEMediaTexGen(const U8 te, const U8 media); + virtual S32 setTEBumpmap(const U8 te, const U8 bump); + virtual S32 setTETexGen(const U8 te, const U8 texgen); + virtual S32 setTEShiny(const U8 te, const U8 shiny); + virtual S32 setTEFullbright(const U8 te, const U8 fullbright); + virtual S32 setTEMediaFlags(const U8 te, const U8 flags); + virtual S32 setTEGlow(const U8 te, const F32 glow); + virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); - virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed - virtual void setTESelected(const U8 te, bool sel); - - LLMaterialPtr getTEMaterialParams(const U8 index); - - void copyTEs(const LLPrimitive *primitive); - S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; - BOOL packTEMessage(LLMessageSystem *mesgsys) const; - BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks - BOOL unpackTEMessage(LLDataPacker &dp); - S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec); - S32 applyParsedTEMessage(LLTEContents& tec); - + virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed + virtual void setTESelected(const U8 te, bool sel); + + LLMaterialPtr getTEMaterialParams(const U8 index); + + void copyTEs(const LLPrimitive *primitive); + S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; + BOOL packTEMessage(LLMessageSystem *mesgsys) const; + BOOL packTEMessage(LLDataPacker &dp) const; + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks + BOOL unpackTEMessage(LLDataPacker &dp); + S32 parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec); + S32 applyParsedTEMessage(LLTEContents& tec); + #ifdef CHECK_FOR_FINITE - inline void setPosition(const LLVector3& pos); - inline void setPosition(const F32 x, const F32 y, const F32 z); - inline void addPosition(const LLVector3& pos); - - inline void setAngularVelocity(const LLVector3& avel); - inline void setAngularVelocity(const F32 x, const F32 y, const F32 z); - inline void setVelocity(const LLVector3& vel); - inline void setVelocity(const F32 x, const F32 y, const F32 z); - inline void setVelocityX(const F32 x); - inline void setVelocityY(const F32 y); - inline void setVelocityZ(const F32 z); - inline void addVelocity(const LLVector3& vel); - inline void setAcceleration(const LLVector3& accel); - inline void setAcceleration(const F32 x, const F32 y, const F32 z); + inline void setPosition(const LLVector3& pos); + inline void setPosition(const F32 x, const F32 y, const F32 z); + inline void addPosition(const LLVector3& pos); + + inline void setAngularVelocity(const LLVector3& avel); + inline void setAngularVelocity(const F32 x, const F32 y, const F32 z); + inline void setVelocity(const LLVector3& vel); + inline void setVelocity(const F32 x, const F32 y, const F32 z); + inline void setVelocityX(const F32 x); + inline void setVelocityY(const F32 y); + inline void setVelocityZ(const F32 z); + inline void addVelocity(const LLVector3& vel); + inline void setAcceleration(const LLVector3& accel); + inline void setAcceleration(const F32 x, const F32 y, const F32 z); #else - // Don't override the base LLXForm operators. - // Special case for setPosition. If not check-for-finite, fall through to LLXform method. - // void setPosition(F32 x, F32 y, F32 z) - // void setPosition(LLVector3) - - void setAngularVelocity(const LLVector3& avel) { mAngularVelocity = avel; } - void setAngularVelocity(const F32 x, const F32 y, const F32 z) { mAngularVelocity.setVec(x,y,z); } - void setVelocity(const LLVector3& vel) { mVelocity = vel; } - void setVelocity(const F32 x, const F32 y, const F32 z) { mVelocity.setVec(x,y,z); } - void setVelocityX(const F32 x) { mVelocity.mV[VX] = x; } - void setVelocityY(const F32 y) { mVelocity.mV[VY] = y; } - void setVelocityZ(const F32 z) { mVelocity.mV[VZ] = z; } - void addVelocity(const LLVector3& vel) { mVelocity += vel; } - void setAcceleration(const LLVector3& accel) { mAcceleration = accel; } - void setAcceleration(const F32 x, const F32 y, const F32 z) { mAcceleration.setVec(x,y,z); } + // Don't override the base LLXForm operators. + // Special case for setPosition. If not check-for-finite, fall through to LLXform method. + // void setPosition(F32 x, F32 y, F32 z) + // void setPosition(LLVector3) + + void setAngularVelocity(const LLVector3& avel) { mAngularVelocity = avel; } + void setAngularVelocity(const F32 x, const F32 y, const F32 z) { mAngularVelocity.setVec(x,y,z); } + void setVelocity(const LLVector3& vel) { mVelocity = vel; } + void setVelocity(const F32 x, const F32 y, const F32 z) { mVelocity.setVec(x,y,z); } + void setVelocityX(const F32 x) { mVelocity.mV[VX] = x; } + void setVelocityY(const F32 y) { mVelocity.mV[VY] = y; } + void setVelocityZ(const F32 z) { mVelocity.mV[VZ] = z; } + void addVelocity(const LLVector3& vel) { mVelocity += vel; } + void setAcceleration(const LLVector3& accel) { mAcceleration = accel; } + void setAcceleration(const F32 x, const F32 y, const F32 z) { mAcceleration.setVec(x,y,z); } #endif - - LLPCode getPCode() const { return mPrimitiveCode; } - std::string getPCodeString() const { return pCodeToString(mPrimitiveCode); } - const LLVector3& getAngularVelocity() const { return mAngularVelocity; } - const LLVector3& getVelocity() const { return mVelocity; } - const LLVector3& getAcceleration() const { return mAcceleration; } - U8 getNumTEs() const { return mTextureList.size(); } - U8 getExpectedNumTEs() const; - - U8 getMaterial() const { return mMaterial; } - - void setVolumeType(const U8 code); - U8 getVolumeType(); - - // clears existing textures - // copies the contents of other_list into mEntryList - void copyTextureList(const LLPrimTextureList& other_list); - - // clears existing textures - // takes the contents of other_list and clears other_list - void takeTextureList(LLPrimTextureList& other_list); - - inline BOOL isAvatar() const; - inline BOOL isSittingAvatar() const; - inline BOOL isSittingAvatarOnGround() const; - inline bool hasBumpmap() const { return mNumBumpmapTEs > 0;} - - void setFlags(U32 flags) { mMiscFlags = flags; } - void addFlags(U32 flags) { mMiscFlags |= flags; } - void removeFlags(U32 flags) { mMiscFlags &= ~flags; } - U32 getFlags() const { return mMiscFlags; } - - static std::string pCodeToString(const LLPCode pcode); - static LLPCode legacyToPCode(const U8 legacy); - static U8 pCodeToLegacy(const LLPCode pcode); - static bool getTESTAxes(const U8 face, U32* s_axis, U32* t_axis); + + LLPCode getPCode() const { return mPrimitiveCode; } + std::string getPCodeString() const { return pCodeToString(mPrimitiveCode); } + const LLVector3& getAngularVelocity() const { return mAngularVelocity; } + const LLVector3& getVelocity() const { return mVelocity; } + const LLVector3& getAcceleration() const { return mAcceleration; } + U8 getNumTEs() const { return mTextureList.size(); } + U8 getExpectedNumTEs() const; + + U8 getMaterial() const { return mMaterial; } + + void setVolumeType(const U8 code); + U8 getVolumeType(); + + // clears existing textures + // copies the contents of other_list into mEntryList + void copyTextureList(const LLPrimTextureList& other_list); + + // clears existing textures + // takes the contents of other_list and clears other_list + void takeTextureList(LLPrimTextureList& other_list); + + inline BOOL isAvatar() const; + inline BOOL isSittingAvatar() const; + inline BOOL isSittingAvatarOnGround() const; + inline bool hasBumpmap() const { return mNumBumpmapTEs > 0;} + + void setFlags(U32 flags) { mMiscFlags = flags; } + void addFlags(U32 flags) { mMiscFlags |= flags; } + void removeFlags(U32 flags) { mMiscFlags &= ~flags; } + U32 getFlags() const { return mMiscFlags; } + + static std::string pCodeToString(const LLPCode pcode); + static LLPCode legacyToPCode(const U8 legacy); + static U8 pCodeToLegacy(const LLPCode pcode); + static bool getTESTAxes(const U8 face, U32* s_axis, U32* t_axis); BOOL hasRenderMaterialParams() const; - - inline static BOOL isPrimitive(const LLPCode pcode); - inline static BOOL isApp(const LLPCode pcode); + + inline static BOOL isPrimitive(const LLPCode pcode); + inline static BOOL isApp(const LLPCode pcode); private: - void updateNumBumpmap(const U8 index, const U8 bump); + void updateNumBumpmap(const U8 index, const U8 bump); protected: - LLPCode mPrimitiveCode; // Primitive code - LLVector3 mVelocity; // how fast are we moving? - LLVector3 mAcceleration; // are we under constant acceleration? - LLVector3 mAngularVelocity; // angular velocity - LLPointer mVolumep; - LLPrimTextureList mTextureList; // list of texture GUIDs, scales, offsets - U8 mMaterial; // Material code - U8 mNumTEs; // # of faces on the primitve - U8 mNumBumpmapTEs; // number of bumpmap TEs. - U32 mMiscFlags; // home for misc bools + LLPCode mPrimitiveCode; // Primitive code + LLVector3 mVelocity; // how fast are we moving? + LLVector3 mAcceleration; // are we under constant acceleration? + LLVector3 mAngularVelocity; // angular velocity + LLPointer mVolumep; + LLPrimTextureList mTextureList; // list of texture GUIDs, scales, offsets + U8 mMaterial; // Material code + U8 mNumTEs; // # of faces on the primitve + U8 mNumBumpmapTEs; // number of bumpmap TEs. + U32 mMiscFlags; // home for misc bools public: - static LLVolumeMgr* sVolumeManager; + static LLVolumeMgr* sVolumeManager; - enum - { - NO_LOD = -1 - }; + enum + { + NO_LOD = -1 + }; }; inline BOOL LLPrimitive::isAvatar() const { - return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode ) ? TRUE : FALSE; + return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode ) ? TRUE : FALSE; } inline BOOL LLPrimitive::isSittingAvatar() const { - // this is only used server-side - return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode - && ((getFlags() & (PRIM_FLAG_SITTING | PRIM_FLAG_SITTING_ON_GROUND)) != 0) ) ? TRUE : FALSE; + // this is only used server-side + return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode + && ((getFlags() & (PRIM_FLAG_SITTING | PRIM_FLAG_SITTING_ON_GROUND)) != 0) ) ? TRUE : FALSE; } inline BOOL LLPrimitive::isSittingAvatarOnGround() const { - // this is only used server-side - return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode - && ((getFlags() & PRIM_FLAG_SITTING_ON_GROUND) != 0) ) ? TRUE : FALSE; + // this is only used server-side + return ( LL_PCODE_LEGACY_AVATAR == mPrimitiveCode + && ((getFlags() & PRIM_FLAG_SITTING_ON_GROUND) != 0) ) ? TRUE : FALSE; } // static inline BOOL LLPrimitive::isPrimitive(const LLPCode pcode) { - LLPCode base_type = pcode & LL_PCODE_BASE_MASK; + LLPCode base_type = pcode & LL_PCODE_BASE_MASK; - if (base_type && (base_type < LL_PCODE_APP)) - { - return TRUE; - } - return FALSE; + if (base_type && (base_type < LL_PCODE_APP)) + { + return TRUE; + } + return FALSE; } // static inline BOOL LLPrimitive::isApp(const LLPCode pcode) { - LLPCode base_type = pcode & LL_PCODE_BASE_MASK; + LLPCode base_type = pcode & LL_PCODE_BASE_MASK; - return (base_type == LL_PCODE_APP); + return (base_type == LL_PCODE_APP); } @@ -645,153 +645,153 @@ inline BOOL LLPrimitive::isApp(const LLPCode pcode) // Special case for setPosition. If not check-for-finite, fall through to LLXform method. void LLPrimitive::setPosition(const F32 x, const F32 y, const F32 z) { - if (llfinite(x) && llfinite(y) && llfinite(z)) - { - LLXform::setPosition(x, y, z); - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setPosition(x,y,z) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + LLXform::setPosition(x, y, z); + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setPosition(x,y,z) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } // Special case for setPosition. If not check-for-finite, fall through to LLXform method. void LLPrimitive::setPosition(const LLVector3& pos) { - if (pos.isFinite()) - { - LLXform::setPosition(pos); - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setPosition(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } + if (pos.isFinite()) + { + LLXform::setPosition(pos); + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setPosition(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } void LLPrimitive::setAngularVelocity(const LLVector3& avel) -{ - if (avel.isFinite()) - { - mAngularVelocity = avel; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setAngularVelocity" << LL_ENDL; - } +{ + if (avel.isFinite()) + { + mAngularVelocity = avel; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setAngularVelocity" << LL_ENDL; + } } -void LLPrimitive::setAngularVelocity(const F32 x, const F32 y, const F32 z) -{ - if (llfinite(x) && llfinite(y) && llfinite(z)) - { - mAngularVelocity.setVec(x,y,z); - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setAngularVelocity" << LL_ENDL; - } +void LLPrimitive::setAngularVelocity(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mAngularVelocity.setVec(x,y,z); + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setAngularVelocity" << LL_ENDL; + } } -void LLPrimitive::setVelocity(const LLVector3& vel) -{ - if (vel.isFinite()) - { - mVelocity = vel; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setVelocity(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } +void LLPrimitive::setVelocity(const LLVector3& vel) +{ + if (vel.isFinite()) + { + mVelocity = vel; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setVelocity(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } -void LLPrimitive::setVelocity(const F32 x, const F32 y, const F32 z) -{ - if (llfinite(x) && llfinite(y) && llfinite(z)) - { - mVelocity.setVec(x,y,z); - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setVelocity(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } +void LLPrimitive::setVelocity(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mVelocity.setVec(x,y,z); + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setVelocity(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } -void LLPrimitive::setVelocityX(const F32 x) -{ - if (llfinite(x)) - { - mVelocity.mV[VX] = x; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setVelocityX" << LL_ENDL; - } +void LLPrimitive::setVelocityX(const F32 x) +{ + if (llfinite(x)) + { + mVelocity.mV[VX] = x; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setVelocityX" << LL_ENDL; + } } -void LLPrimitive::setVelocityY(const F32 y) -{ - if (llfinite(y)) - { - mVelocity.mV[VY] = y; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setVelocityY" << LL_ENDL; - } +void LLPrimitive::setVelocityY(const F32 y) +{ + if (llfinite(y)) + { + mVelocity.mV[VY] = y; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setVelocityY" << LL_ENDL; + } } -void LLPrimitive::setVelocityZ(const F32 z) -{ - if (llfinite(z)) - { - mVelocity.mV[VZ] = z; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setVelocityZ" << LL_ENDL; - } +void LLPrimitive::setVelocityZ(const F32 z) +{ + if (llfinite(z)) + { + mVelocity.mV[VZ] = z; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setVelocityZ" << LL_ENDL; + } } -void LLPrimitive::addVelocity(const LLVector3& vel) -{ - if (vel.isFinite()) - { - mVelocity += vel; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::addVelocity" << LL_ENDL; - } +void LLPrimitive::addVelocity(const LLVector3& vel) +{ + if (vel.isFinite()) + { + mVelocity += vel; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::addVelocity" << LL_ENDL; + } } -void LLPrimitive::setAcceleration(const LLVector3& accel) -{ - if (accel.isFinite()) - { - mAcceleration = accel; - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setAcceleration(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } +void LLPrimitive::setAcceleration(const LLVector3& accel) +{ + if (accel.isFinite()) + { + mAcceleration = accel; + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setAcceleration(LLVector3) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } -void LLPrimitive::setAcceleration(const F32 x, const F32 y, const F32 z) -{ - if (llfinite(x) && llfinite(y) && llfinite(z)) - { - mAcceleration.setVec(x,y,z); - } - else - { - LL_ERRS() << "Non Finite in LLPrimitive::setAcceleration(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; - } +void LLPrimitive::setAcceleration(const F32 x, const F32 y, const F32 z) +{ + if (llfinite(x) && llfinite(y) && llfinite(z)) + { + mAcceleration.setVec(x,y,z); + } + else + { + LL_ERRS() << "Non Finite in LLPrimitive::setAcceleration(F32,F32,F32) for " << pCodeToString(mPrimitiveCode) << LL_ENDL; + } } #endif // CHECK_FOR_FINITE inline BOOL LLPrimitive::validTE(const U8 te_num) const { - return (mNumTEs && te_num < mNumTEs); + return (mNumTEs && te_num < mNumTEs); } #endif diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index ee2a4c769a..2ed8f8c044 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lltextureentry.cpp * @brief LLTextureEntry base class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -52,10 +52,10 @@ const LLTextureEntry LLTextureEntry::null; static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:"; -// static +// static LLTextureEntry* LLTextureEntry::newTextureEntry() { - return new LLTextureEntry(); + return new LLTextureEntry(); } //=============================================================== @@ -64,7 +64,7 @@ LLTextureEntry::LLTextureEntry() , mSelected(false) , mMaterialUpdatePending(false) { - init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); + init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } LLTextureEntry::LLTextureEntry(const LLUUID& tex_id) @@ -72,7 +72,7 @@ LLTextureEntry::LLTextureEntry(const LLUUID& tex_id) , mSelected(false) , mMaterialUpdatePending(false) { - init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); + init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE); } LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) @@ -85,30 +85,30 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs) LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) { - if (this != &rhs) - { - mID = rhs.mID; - mScaleS = rhs.mScaleS; - mScaleT = rhs.mScaleT; - mOffsetS = rhs.mOffsetS; - mOffsetT = rhs.mOffsetT; - mRotation = rhs.mRotation; - mColor = rhs.mColor; - mBump = rhs.mBump; - mMediaFlags = rhs.mMediaFlags; - mGlow = rhs.mGlow; - mMaterialID = rhs.mMaterialID; - mMaterial = rhs.mMaterial; - if (mMediaEntry != NULL) { - delete mMediaEntry; - } - if (rhs.mMediaEntry != NULL) { - // Make a copy - mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry); - } - else { - mMediaEntry = NULL; - } + if (this != &rhs) + { + mID = rhs.mID; + mScaleS = rhs.mScaleS; + mScaleT = rhs.mScaleT; + mOffsetS = rhs.mOffsetS; + mOffsetT = rhs.mOffsetT; + mRotation = rhs.mRotation; + mColor = rhs.mColor; + mBump = rhs.mBump; + mMediaFlags = rhs.mMediaFlags; + mGlow = rhs.mGlow; + mMaterialID = rhs.mMaterialID; + mMaterial = rhs.mMaterial; + if (mMediaEntry != NULL) { + delete mMediaEntry; + } + if (rhs.mMediaEntry != NULL) { + // Make a copy + mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry); + } + else { + mMediaEntry = NULL; + } mMaterialID = rhs.mMaterialID; @@ -121,7 +121,7 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) { mGLTFMaterial->addTextureEntry(this); } - + if (rhs.mGLTFMaterialOverrides.notNull()) { mGLTFMaterialOverrides = new LLGLTFMaterial(*rhs.mGLTFMaterialOverrides); @@ -130,39 +130,39 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs) { mGLTFMaterialOverrides = nullptr; } - } + } - return *this; + return *this; } void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump) { - setID(tex_id); + setID(tex_id); - mScaleS = scale_s; - mScaleT = scale_t; - mOffsetS = offset_s; - mOffsetT = offset_t; - mRotation = rotation; - mBump = bump; - mMediaFlags = 0x0; + mScaleS = scale_s; + mScaleT = scale_t; + mOffsetS = offset_s; + mOffsetT = offset_t; + mRotation = rotation; + mBump = bump; + mMediaFlags = 0x0; mGlow = 0; - mMaterialID.clear(); - - setColor(LLColor4(1.f, 1.f, 1.f, 1.f)); - if (mMediaEntry != NULL) { - delete mMediaEntry; - } - mMediaEntry = NULL; + mMaterialID.clear(); + + setColor(LLColor4(1.f, 1.f, 1.f, 1.f)); + if (mMediaEntry != NULL) { + delete mMediaEntry; + } + mMediaEntry = NULL; } LLTextureEntry::~LLTextureEntry() { - if(mMediaEntry) - { - delete mMediaEntry; - mMediaEntry = NULL; - } + if(mMediaEntry) + { + delete mMediaEntry; + mMediaEntry = NULL; + } if (mGLTFMaterial) { @@ -173,64 +173,64 @@ LLTextureEntry::~LLTextureEntry() bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const { - if (mID != rhs.mID) return(true); - if (mScaleS != rhs.mScaleS) return(true); - if (mScaleT != rhs.mScaleT) return(true); - if (mOffsetS != rhs.mOffsetS) return(true); - if (mOffsetT != rhs.mOffsetT) return(true); - if (mRotation != rhs.mRotation) return(true); - if (mColor != rhs.mColor) return (true); - if (mBump != rhs.mBump) return (true); - if (mMediaFlags != rhs.mMediaFlags) return (true); - if (mGlow != rhs.mGlow) return (true); - if (mMaterialID != rhs.mMaterialID) return (true); - return(false); + if (mID != rhs.mID) return(true); + if (mScaleS != rhs.mScaleS) return(true); + if (mScaleT != rhs.mScaleT) return(true); + if (mOffsetS != rhs.mOffsetS) return(true); + if (mOffsetT != rhs.mOffsetT) return(true); + if (mRotation != rhs.mRotation) return(true); + if (mColor != rhs.mColor) return (true); + if (mBump != rhs.mBump) return (true); + if (mMediaFlags != rhs.mMediaFlags) return (true); + if (mGlow != rhs.mGlow) return (true); + if (mMaterialID != rhs.mMaterialID) return (true); + return(false); } bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const { - if (mID != rhs.mID) return(false); - if (mScaleS != rhs.mScaleS) return(false); - if (mScaleT != rhs.mScaleT) return(false); - if (mOffsetS != rhs.mOffsetS) return(false); - if (mOffsetT != rhs.mOffsetT) return(false); - if (mRotation != rhs.mRotation) return(false); - if (mColor != rhs.mColor) return (false); - if (mBump != rhs.mBump) return (false); - if (mMediaFlags != rhs.mMediaFlags) return false; - if (mGlow != rhs.mGlow) return false; - if (mMaterialID != rhs.mMaterialID) return (false); - return(true); + if (mID != rhs.mID) return(false); + if (mScaleS != rhs.mScaleS) return(false); + if (mScaleT != rhs.mScaleT) return(false); + if (mOffsetS != rhs.mOffsetS) return(false); + if (mOffsetT != rhs.mOffsetT) return(false); + if (mRotation != rhs.mRotation) return(false); + if (mColor != rhs.mColor) return (false); + if (mBump != rhs.mBump) return (false); + if (mMediaFlags != rhs.mMediaFlags) return false; + if (mGlow != rhs.mGlow) return false; + if (mMaterialID != rhs.mMaterialID) return (false); + return(true); } LLSD LLTextureEntry::asLLSD() const { - LLSD sd; - asLLSD(sd); - return sd; + LLSD sd; + asLLSD(sd); + return sd; } void LLTextureEntry::asLLSD(LLSD& sd) const { LL_PROFILE_ZONE_SCOPED; - sd["imageid"] = mID; - sd["colors"] = ll_sd_from_color4(mColor); - sd["scales"] = mScaleS; - sd["scalet"] = mScaleT; - sd["offsets"] = mOffsetS; - sd["offsett"] = mOffsetT; - sd["imagerot"] = mRotation; - sd["bump"] = getBumpShiny(); - sd["fullbright"] = getFullbright(); - sd["media_flags"] = mMediaFlags; - if (hasMedia()) { - LLSD mediaData; + sd["imageid"] = mID; + sd["colors"] = ll_sd_from_color4(mColor); + sd["scales"] = mScaleS; + sd["scalet"] = mScaleT; + sd["offsets"] = mOffsetS; + sd["offsett"] = mOffsetT; + sd["imagerot"] = mRotation; + sd["bump"] = getBumpShiny(); + sd["fullbright"] = getFullbright(); + sd["media_flags"] = mMediaFlags; + if (hasMedia()) { + LLSD mediaData; if (NULL != getMediaData()) { getMediaData()->asLLSD(mediaData); } - sd[TEXTURE_MEDIA_DATA_KEY] = mediaData; - } - sd["glow"] = mGlow; + sd[TEXTURE_MEDIA_DATA_KEY] = mediaData; + } + sd["glow"] = mGlow; if (mGLTFMaterialOverrides.notNull()) { @@ -241,65 +241,65 @@ void LLTextureEntry::asLLSD(LLSD& sd) const bool LLTextureEntry::fromLLSD(const LLSD& sd) { LL_PROFILE_ZONE_SCOPED; - const char *w, *x; - w = "imageid"; - if (sd.has(w)) - { - setID( sd[w] ); - } else goto fail; - w = "colors"; - if (sd.has(w)) - { - setColor( ll_color4_from_sd(sd["colors"]) ); - } else goto fail; - w = "scales"; - x = "scalet"; - if (sd.has(w) && sd.has(x)) - { - setScale( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); - } else goto fail; - w = "offsets"; - x = "offsett"; - if (sd.has(w) && sd.has(x)) - { - setOffset( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); - } else goto fail; - w = "imagerot"; - if (sd.has(w)) - { - setRotation( (F32)sd[w].asReal() ); - } else goto fail; - w = "bump"; - if (sd.has(w)) - { - setBumpShiny( sd[w].asInteger() ); - } else goto fail; - w = "fullbright"; - if (sd.has(w)) - { - setFullbright( sd[w].asInteger() ); - } else goto fail; - w = "media_flags"; - if (sd.has(w)) - { - setMediaTexGen( sd[w].asInteger() ); - } else goto fail; - // If the "has media" flag doesn't match the fact that - // media data exists, updateMediaData will "fix" it - // by either clearing or setting the flag - w = TEXTURE_MEDIA_DATA_KEY; - if (hasMedia() != sd.has(w)) - { - LL_WARNS() << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() << - ") does not match presence of media_data (" << sd.has(w) << "). Fixing." << LL_ENDL; - } - updateMediaData(sd[w]); - - w = "glow"; - if (sd.has(w)) - { - setGlow((F32)sd[w].asReal() ); - } + const char *w, *x; + w = "imageid"; + if (sd.has(w)) + { + setID( sd[w] ); + } else goto fail; + w = "colors"; + if (sd.has(w)) + { + setColor( ll_color4_from_sd(sd["colors"]) ); + } else goto fail; + w = "scales"; + x = "scalet"; + if (sd.has(w) && sd.has(x)) + { + setScale( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); + } else goto fail; + w = "offsets"; + x = "offsett"; + if (sd.has(w) && sd.has(x)) + { + setOffset( (F32)sd[w].asReal(), (F32)sd[x].asReal() ); + } else goto fail; + w = "imagerot"; + if (sd.has(w)) + { + setRotation( (F32)sd[w].asReal() ); + } else goto fail; + w = "bump"; + if (sd.has(w)) + { + setBumpShiny( sd[w].asInteger() ); + } else goto fail; + w = "fullbright"; + if (sd.has(w)) + { + setFullbright( sd[w].asInteger() ); + } else goto fail; + w = "media_flags"; + if (sd.has(w)) + { + setMediaTexGen( sd[w].asInteger() ); + } else goto fail; + // If the "has media" flag doesn't match the fact that + // media data exists, updateMediaData will "fix" it + // by either clearing or setting the flag + w = TEXTURE_MEDIA_DATA_KEY; + if (hasMedia() != sd.has(w)) + { + LL_WARNS() << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() << + ") does not match presence of media_data (" << sd.has(w) << "). Fixing." << LL_ENDL; + } + updateMediaData(sd[w]); + + w = "glow"; + if (sd.has(w)) + { + setGlow((F32)sd[w].asReal() ); + } w = "gltf_override"; if (sd.has(w)) @@ -319,217 +319,217 @@ bool LLTextureEntry::fromLLSD(const LLSD& sd) } } - return true; + return true; fail: - return false; + return false; } -// virtual +// virtual // override this method for each derived class LLTextureEntry* LLTextureEntry::newBlank() const { - return new LLTextureEntry(); + return new LLTextureEntry(); } -// virtual +// virtual LLTextureEntry* LLTextureEntry::newCopy() const { - return new LLTextureEntry(*this); + return new LLTextureEntry(*this); } S32 LLTextureEntry::setID(const LLUUID &tex_id) { - if (mID != tex_id) - { - mID = tex_id; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + if (mID != tex_id) + { + mID = tex_id; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setScale(F32 s, F32 t) { - S32 retval = 0; + S32 retval = 0; - if ( (mScaleS != s) - ||(mScaleT != t)) - { - mScaleS = s; - mScaleT = t; + if ( (mScaleS != s) + ||(mScaleT != t)) + { + mScaleS = s; + mScaleT = t; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setScaleS(F32 s) { - S32 retval = TEM_CHANGE_NONE; - if (mScaleS != s) - { - mScaleS = s; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + S32 retval = TEM_CHANGE_NONE; + if (mScaleS != s) + { + mScaleS = s; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setScaleT(F32 t) { - S32 retval = TEM_CHANGE_NONE; - if (mScaleT != t) - { - mScaleT = t; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + S32 retval = TEM_CHANGE_NONE; + if (mScaleT != t) + { + mScaleT = t; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setColor(const LLColor4 &color) { - if (mColor != color) - { - mColor = color; - return TEM_CHANGE_COLOR; - } - return TEM_CHANGE_NONE; + if (mColor != color) + { + mColor = color; + return TEM_CHANGE_COLOR; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setColor(const LLColor3 &color) { - if (mColor != color) - { - // This preserves alpha. - mColor.setVec(color); - return TEM_CHANGE_COLOR; - } - return TEM_CHANGE_NONE; + if (mColor != color) + { + // This preserves alpha. + mColor.setVec(color); + return TEM_CHANGE_COLOR; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setAlpha(const F32 alpha) { - if (mColor.mV[VW] != alpha) - { - mColor.mV[VW] = alpha; - return TEM_CHANGE_COLOR; - } - return TEM_CHANGE_NONE; + if (mColor.mV[VW] != alpha) + { + mColor.mV[VW] = alpha; + return TEM_CHANGE_COLOR; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setOffset(F32 s, F32 t) { - S32 retval = 0; + S32 retval = 0; - if ( (mOffsetS != s) - ||(mOffsetT != t)) - { - mOffsetS = s; - mOffsetT = t; + if ( (mOffsetS != s) + ||(mOffsetT != t)) + { + mOffsetS = s; + mOffsetT = t; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setOffsetS(F32 s) { - S32 retval = 0; - if (mOffsetS != s) - { - mOffsetS = s; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + S32 retval = 0; + if (mOffsetS != s) + { + mOffsetS = s; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setOffsetT(F32 t) { - S32 retval = 0; - if (mOffsetT != t) - { - mOffsetT = t; - retval = TEM_CHANGE_TEXTURE; - } - return retval; + S32 retval = 0; + if (mOffsetT != t) + { + mOffsetT = t; + retval = TEM_CHANGE_TEXTURE; + } + return retval; } S32 LLTextureEntry::setRotation(F32 theta) { - if (mRotation != theta && llfinite(theta)) - { - mRotation = theta; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + if (mRotation != theta && llfinite(theta)) + { + mRotation = theta; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setBumpShinyFullbright(U8 bump) { - if (mBump != bump) - { - mBump = bump; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + if (mBump != bump) + { + mBump = bump; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setMediaTexGen(U8 media) { - S32 result = TEM_CHANGE_NONE; - result |= setTexGen(media & TEM_TEX_GEN_MASK); - result |= setMediaFlags(media & TEM_MEDIA_MASK); - return result; + S32 result = TEM_CHANGE_NONE; + result |= setTexGen(media & TEM_TEX_GEN_MASK); + result |= setMediaFlags(media & TEM_MEDIA_MASK); + return result; } S32 LLTextureEntry::setBumpmap(U8 bump) { - bump &= TEM_BUMP_MASK; - if (getBumpmap() != bump) - { - mBump &= ~TEM_BUMP_MASK; - mBump |= bump; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + bump &= TEM_BUMP_MASK; + if (getBumpmap() != bump) + { + mBump &= ~TEM_BUMP_MASK; + mBump |= bump; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setFullbright(U8 fullbright) { - fullbright &= TEM_FULLBRIGHT_MASK; - if (getFullbright() != fullbright) - { - mBump &= ~(TEM_FULLBRIGHT_MASK<isClearedForBaseMaterial()); return getGLTFMaterial(); } @@ -616,77 +616,77 @@ S32 LLTextureEntry::setGLTFRenderMaterial(LLGLTFMaterial* mat) S32 LLTextureEntry::setMediaFlags(U8 media_flags) { - media_flags &= TEM_MEDIA_MASK; - if (getMediaFlags() != media_flags) - { - mMediaFlags &= ~TEM_MEDIA_MASK; - mMediaFlags |= media_flags; - - // Special code for media handling - if( hasMedia() && mMediaEntry == NULL) - { - mMediaEntry = new LLMediaEntry; - } + media_flags &= TEM_MEDIA_MASK; + if (getMediaFlags() != media_flags) + { + mMediaFlags &= ~TEM_MEDIA_MASK; + mMediaFlags |= media_flags; + + // Special code for media handling + if( hasMedia() && mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } else if ( ! hasMedia() && mMediaEntry != NULL) { delete mMediaEntry; mMediaEntry = NULL; } - - return TEM_CHANGE_MEDIA; - } - return TEM_CHANGE_NONE; + + return TEM_CHANGE_MEDIA; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setTexGen(U8 tex_gen) { - tex_gen &= TEM_TEX_GEN_MASK; - if (getTexGen() != tex_gen) - { - mMediaFlags &= ~TEM_TEX_GEN_MASK; - mMediaFlags |= tex_gen; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + tex_gen &= TEM_TEX_GEN_MASK; + if (getTexGen() != tex_gen) + { + mMediaFlags &= ~TEM_TEX_GEN_MASK; + mMediaFlags |= tex_gen; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setGlow(F32 glow) { - if (mGlow != glow) - { - mGlow = glow; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + if (mGlow != glow) + { + mGlow = glow; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID) { - if ( (mMaterialID != pMaterialID) || (mMaterialUpdatePending && !mSelected) ) - { - if (mSelected) - { - mMaterialUpdatePending = true; - mMaterialID = pMaterialID; - return TEM_CHANGE_TEXTURE; - } + if ( (mMaterialID != pMaterialID) || (mMaterialUpdatePending && !mSelected) ) + { + if (mSelected) + { + mMaterialUpdatePending = true; + mMaterialID = pMaterialID; + return TEM_CHANGE_TEXTURE; + } - mMaterialUpdatePending = false; - mMaterialID = pMaterialID; - return TEM_CHANGE_TEXTURE; - } - return TEM_CHANGE_NONE; + mMaterialUpdatePending = false; + mMaterialID = pMaterialID; + return TEM_CHANGE_TEXTURE; + } + return TEM_CHANGE_NONE; } S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams) { - if (mSelected) - { - mMaterialUpdatePending = true; - } - mMaterial = pMaterialParams; - - return TEM_CHANGE_TEXTURE; + if (mSelected) + { + mMaterialUpdatePending = true; + } + mMaterial = pMaterialParams; + + return TEM_CHANGE_TEXTURE; } void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry) @@ -701,23 +701,23 @@ void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry) bool LLTextureEntry::updateMediaData(const LLSD& media_data) { - if (media_data.isUndefined()) - { - // clear the media data + if (media_data.isUndefined()) + { + // clear the media data clearMediaData(); - return false; - } - else { - mMediaFlags |= MF_HAS_MEDIA; - if (mMediaEntry == NULL) - { - mMediaEntry = new LLMediaEntry; - } - // *NOTE: this will *clobber* all of the fields in mMediaEntry + return false; + } + else { + mMediaFlags |= MF_HAS_MEDIA; + if (mMediaEntry == NULL) + { + mMediaEntry = new LLMediaEntry; + } + // *NOTE: this will *clobber* all of the fields in mMediaEntry // with whatever fields are present (or not present) in media_data! - mMediaEntry->fromLLSD(media_data); - return true; - } + mMediaEntry->fromLLSD(media_data); + return true; + } } void LLTextureEntry::clearMediaData() @@ -727,7 +727,7 @@ void LLTextureEntry::clearMediaData() delete mMediaEntry; } mMediaEntry = NULL; -} +} void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields) { @@ -760,10 +760,10 @@ std::string LLTextureEntry::touchMediaVersionString(const std::string &in_versio U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string) { U32 version = 0; - if (!version_string.empty()) + if (!version_string.empty()) { size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX); - if (found != std::string::npos) + if (found != std::string::npos) { found = version_string.find_first_of("/", found); std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found); @@ -777,13 +777,13 @@ U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_ LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string) { LLUUID id; - if (!version_string.empty()) + if (!version_string.empty()) { size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX); - if (found != std::string::npos) + if (found != std::string::npos) { found = version_string.find_first_of("/", found); - if (found != std::string::npos) + if (found != std::string::npos) { std::string v = version_string.substr(found + 1); id.set(v); @@ -796,5 +796,5 @@ LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &versi //static bool LLTextureEntry::isMediaVersionString(const std::string &version_string) { - return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX); + return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX); } diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index be5ad08fbe..28b5bc7495 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -422,27 +422,27 @@ BOOL LLGLSLShader::createShader(std::vector* attributes, mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this); - if (!mUsingBinaryProgram) - { + if (!mUsingBinaryProgram) + { #if DEBUG_SHADER_INCLUDES - fprintf(stderr, "--- %s ---\n", mName.c_str()); + fprintf(stderr, "--- %s ---\n", mName.c_str()); #endif // DEBUG_SHADER_INCLUDES //compile new source - vector< pair >::iterator fileIter = mShaderFiles.begin(); - for (; fileIter != mShaderFiles.end(); fileIter++) - { - GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); - LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (shaderhandle) - { - attachObject(shaderhandle); - } - else - { - success = FALSE; - } - } + vector< pair >::iterator fileIter = mShaderFiles.begin(); + for (; fileIter != mShaderFiles.end(); fileIter++) + { + GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels); + LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; + if (shaderhandle) + { + attachObject(shaderhandle); + } + else + { + success = FALSE; + } + } } // Attach existing objects @@ -606,19 +606,19 @@ BOOL LLGLSLShader::mapAttributes(const std::vector* attrib { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - BOOL res = TRUE; - if (!mUsingBinaryProgram) - { - //before linking, make sure reserved attributes always have consistent locations - for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) - { - const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); - glBindAttribLocation(mProgramObject, i, (const GLchar*)name); - } + BOOL res = TRUE; + if (!mUsingBinaryProgram) + { + //before linking, make sure reserved attributes always have consistent locations + for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) + { + const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); + glBindAttribLocation(mProgramObject, i, (const GLchar*)name); + } - //link the program - res = link(); - } + //link the program + res = link(); + } mAttribute.clear(); U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); @@ -1184,14 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - + if (uniform < 0 || uniform >= (S32)mTexture.size()) { LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL; return -1; } - + S32 index = mTexture[uniform]; if (index != -1) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index ed0f27d143..d7741c51bb 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -234,7 +234,7 @@ public: void addConstant(const LLGLSLShader::eShaderConsts shader_const); //enable/disable texture channel for specified uniform - //if given texture uniform is active in the shader, + //if given texture uniform is active in the shader, //the corresponding channel will be active upon return //returns channel texture is enabled in from [0-MAX) S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR); @@ -256,7 +256,7 @@ public: void bind(); //helper to conditionally bind mRiggedVariant instead of this void bind(bool rigged); - + bool isComplete() const { return mProgramObject != 0; } LLUUID hash(); @@ -330,11 +330,11 @@ private: }; //UI shader (declared here so llui_libtest will link properly) -extern LLGLSLShader gUIProgram; +extern LLGLSLShader gUIProgram; //output vec4(color.rgb,color.a*tex0[tc0].a) -extern LLGLSLShader gSolidColorProgram; +extern LLGLSLShader gSolidColorProgram; //Alpha mask shader (declared here so llappearance can access properly) -extern LLGLSLShader gAlphaMaskProgram; +extern LLGLSLShader gAlphaMaskProgram; #ifdef LL_PROFILER_ENABLE_RENDER_DOC #define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index a590a8e745..be4fc85985 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llgltexture.cpp * @brief Opengl texture implementation * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -29,366 +29,366 @@ LLGLTexture::LLGLTexture(BOOL usemipmaps) { - init(); - mUseMipMaps = usemipmaps; + init(); + mUseMipMaps = usemipmaps; } LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) { - init(); - mFullWidth = width ; - mFullHeight = height ; - mUseMipMaps = usemipmaps; - mComponents = components ; - setTexelsPerImage(); + init(); + mFullWidth = width ; + mFullHeight = height ; + mUseMipMaps = usemipmaps; + mComponents = components ; + setTexelsPerImage(); } LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) { - init(); - mUseMipMaps = usemipmaps ; - // Create an empty image of the specified size and width - mGLTexturep = new LLImageGL(raw, usemipmaps) ; + init(); + mUseMipMaps = usemipmaps ; + // Create an empty image of the specified size and width + mGLTexturep = new LLImageGL(raw, usemipmaps) ; } LLGLTexture::~LLGLTexture() { - cleanup(); + cleanup(); } void LLGLTexture::init() { - mBoostLevel = LLGLTexture::BOOST_NONE; + mBoostLevel = LLGLTexture::BOOST_NONE; - mFullWidth = 0; - mFullHeight = 0; - mTexelsPerImage = 0 ; - mUseMipMaps = FALSE ; - mComponents = 0 ; + mFullWidth = 0; + mFullHeight = 0; + mTexelsPerImage = 0 ; + mUseMipMaps = FALSE ; + mComponents = 0 ; - mTextureState = NO_DELETE ; - mDontDiscard = FALSE; - mNeedsGLTexture = FALSE ; + mTextureState = NO_DELETE ; + mDontDiscard = FALSE; + mNeedsGLTexture = FALSE ; } void LLGLTexture::cleanup() { - if(mGLTexturep) - { - mGLTexturep->cleanup(); - } + if(mGLTexturep) + { + mGLTexturep->cleanup(); + } } // virtual void LLGLTexture::dump() { - if(mGLTexturep) - { - mGLTexturep->dump(); - } + if(mGLTexturep) + { + mGLTexturep->dump(); + } } void LLGLTexture::setBoostLevel(S32 level) { - if(mBoostLevel != level) - { - mBoostLevel = level ; - if(mBoostLevel != LLGLTexture::BOOST_NONE - && mBoostLevel != LLGLTexture::BOOST_ICON + if(mBoostLevel != level) + { + mBoostLevel = level ; + if(mBoostLevel != LLGLTexture::BOOST_NONE + && mBoostLevel != LLGLTexture::BOOST_ICON && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL && mBoostLevel != LLGLTexture::BOOST_TERRAIN) - { - setNoDelete() ; - } - } + { + setNoDelete() ; + } + } } void LLGLTexture::forceActive() { - mTextureState = ACTIVE ; + mTextureState = ACTIVE ; } -void LLGLTexture::setActive() -{ - if(mTextureState != NO_DELETE) - { - mTextureState = ACTIVE ; - } +void LLGLTexture::setActive() +{ + if(mTextureState != NO_DELETE) + { + mTextureState = ACTIVE ; + } } //set the texture to stay in memory -void LLGLTexture::setNoDelete() -{ - mTextureState = NO_DELETE ; +void LLGLTexture::setNoDelete() +{ + mTextureState = NO_DELETE ; } -void LLGLTexture::generateGLTexture() -{ - if(mGLTexturep.isNull()) - { - mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; - } +void LLGLTexture::generateGLTexture() +{ + if(mGLTexturep.isNull()) + { + mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ; + } } LLImageGL* LLGLTexture::getGLTexture() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep ; + return mGLTexturep ; } -BOOL LLGLTexture::createGLTexture() +BOOL LLGLTexture::createGLTexture() { - if(mGLTexturep.isNull()) - { - generateGLTexture() ; - } + if(mGLTexturep.isNull()) + { + generateGLTexture() ; + } - return mGLTexturep->createGLTexture() ; + return mGLTexturep->createGLTexture() ; } BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name) { - llassert(mGLTexturep.notNull()); + llassert(mGLTexturep.notNull()); - BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ; - if(ret) - { - mFullWidth = mGLTexturep->getCurrentWidth() ; - mFullHeight = mGLTexturep->getCurrentHeight() ; - mComponents = mGLTexturep->getComponents() ; - setTexelsPerImage(); - } + if(ret) + { + mFullWidth = mGLTexturep->getCurrentWidth() ; + mFullHeight = mGLTexturep->getCurrentHeight() ; + mComponents = mGLTexturep->getComponents() ; + setTexelsPerImage(); + } - return ret ; + return ret ; } void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) { - llassert(mGLTexturep.notNull()) ; - - mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; + llassert(mGLTexturep.notNull()) ; + + mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; } void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) { - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setAddressMode(mode) ; + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setAddressMode(mode) ; } void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) { - llassert(mGLTexturep.notNull()) ; - mGLTexturep->setFilteringOption(option) ; + llassert(mGLTexturep.notNull()) ; + mGLTexturep->setFilteringOption(option) ; } //virtual -S32 LLGLTexture::getWidth(S32 discard_level) const +S32 LLGLTexture::getWidth(S32 discard_level) const { - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getWidth(discard_level) ; + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getWidth(discard_level) ; } //virtual -S32 LLGLTexture::getHeight(S32 discard_level) const +S32 LLGLTexture::getHeight(S32 discard_level) const { - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getHeight(discard_level) ; + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getHeight(discard_level) ; } S32 LLGLTexture::getMaxDiscardLevel() const { - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMaxDiscardLevel() ; + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getMaxDiscardLevel() ; } S32 LLGLTexture::getDiscardLevel() const { - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getDiscardLevel() ; + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getDiscardLevel() ; } -S8 LLGLTexture::getComponents() const -{ - llassert(mGLTexturep.notNull()) ; - - return mGLTexturep->getComponents() ; +S8 LLGLTexture::getComponents() const +{ + llassert(mGLTexturep.notNull()) ; + + return mGLTexturep->getComponents() ; } -LLGLuint LLGLTexture::getTexName() const -{ - llassert(mGLTexturep.notNull()) ; +LLGLuint LLGLTexture::getTexName() const +{ + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexName() ; + return mGLTexturep->getTexName() ; } -BOOL LLGLTexture::hasGLTexture() const +BOOL LLGLTexture::hasGLTexture() const { - if(mGLTexturep.notNull()) - { - return mGLTexturep->getHasGLTexture() ; - } - return FALSE ; + if(mGLTexturep.notNull()) + { + return mGLTexturep->getHasGLTexture() ; + } + return FALSE ; } BOOL LLGLTexture::getBoundRecently() const { - if(mGLTexturep.notNull()) - { - return mGLTexturep->getBoundRecently() ; - } - return FALSE ; + if(mGLTexturep.notNull()) + { + return mGLTexturep->getBoundRecently() ; + } + return FALSE ; } LLTexUnit::eTextureType LLGLTexture::getTarget(void) const { - llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTarget() ; + llassert(mGLTexturep.notNull()) ; + return mGLTexturep->getTarget() ; } BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ; + return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ; } BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ; + return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ; } void LLGLTexture::setGLTextureCreated (bool initialized) { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - mGLTexturep->setGLTextureCreated (initialized) ; + mGLTexturep->setGLTextureCreated (initialized) ; } -void LLGLTexture::setCategory(S32 category) +void LLGLTexture::setCategory(S32 category) { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - mGLTexturep->setCategory(category) ; + mGLTexturep->setCategory(category) ; } void LLGLTexture::setTexName(LLGLuint texName) { llassert(mGLTexturep.notNull()); - return mGLTexturep->setTexName(texName); + return mGLTexturep->setTexName(texName); } void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target) { llassert(mGLTexturep.notNull()); - return mGLTexturep->setTarget(target, bind_target); + return mGLTexturep->setTarget(target, bind_target); } LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getAddressMode() ; + return mGLTexturep->getAddressMode() ; } S32Bytes LLGLTexture::getTextureMemory() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->mTextureMemory ; + return mGLTexturep->mTextureMemory ; } LLGLenum LLGLTexture::getPrimaryFormat() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getPrimaryFormat() ; + return mGLTexturep->getPrimaryFormat() ; } BOOL LLGLTexture::getIsAlphaMask() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getIsAlphaMask() ; + return mGLTexturep->getIsAlphaMask() ; } BOOL LLGLTexture::getMask(const LLVector2 &tc) { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMask(tc) ; + return mGLTexturep->getMask(tc) ; } F32 LLGLTexture::getTimePassedSinceLastBound() { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTimePassedSinceLastBound() ; + return mGLTexturep->getTimePassedSinceLastBound() ; } -BOOL LLGLTexture::getMissed() const +BOOL LLGLTexture::getMissed() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getMissed() ; + return mGLTexturep->getMissed() ; } BOOL LLGLTexture::isJustBound() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->isJustBound() ; + return mGLTexturep->isJustBound() ; } void LLGLTexture::forceUpdateBindStats(void) const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->forceUpdateBindStats() ; + return mGLTexturep->forceUpdateBindStats() ; } U32 LLGLTexture::getTexelsInAtlas() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexelsInAtlas() ; + return mGLTexturep->getTexelsInAtlas() ; } U32 LLGLTexture::getTexelsInGLTexture() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getTexelsInGLTexture() ; + return mGLTexturep->getTexelsInGLTexture() ; } BOOL LLGLTexture::isGLTextureCreated() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->isGLTextureCreated() ; + return mGLTexturep->isGLTextureCreated() ; } S32 LLGLTexture::getDiscardLevelInAtlas() const { - llassert(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getDiscardLevelInAtlas() ; + return mGLTexturep->getDiscardLevelInAtlas() ; } -void LLGLTexture::destroyGLTexture() +void LLGLTexture::destroyGLTexture() { - if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) - { - mGLTexturep->destroyGLTexture() ; - mTextureState = DELETED ; - } + if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture()) + { + mGLTexturep->destroyGLTexture() ; + mTextureState = DELETED ; + } } void LLGLTexture::setTexelsPerImage() { - U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT)); - U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT)); - mTexelsPerImage = (U32)fullwidth * fullheight; + U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT)); + U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT)); + mTexelsPerImage = (U32)fullwidth * fullheight; } static LLUUID sStubUUID; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index fa6faa2583..f5bef0e291 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -1,25 +1,25 @@ -/** +/** * @file llgltexture.h * @brief Object for managing opengl textures * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -40,87 +40,87 @@ class LLImageRaw; class LLGLTexture : public LLTexture { public: - enum - { - MAX_IMAGE_SIZE_DEFAULT = 2048, - INVALID_DISCARD_LEVEL = 0x7fff - }; - - enum EBoostLevel - { - BOOST_NONE = 0, - BOOST_AVATAR , + enum + { + MAX_IMAGE_SIZE_DEFAULT = 2048, + INVALID_DISCARD_LEVEL = 0x7fff + }; + + enum EBoostLevel + { + BOOST_NONE = 0, + BOOST_AVATAR , BOOST_AVATAR_BAKED , - BOOST_SCULPTED , + BOOST_SCULPTED , BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead. - - BOOST_HIGH = 10, - BOOST_BUMP , + + BOOST_HIGH = 10, + BOOST_BUMP , BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug - BOOST_SELECTED , - BOOST_AVATAR_BAKED_SELF , - BOOST_AVATAR_SELF , // needed for baking avatar - BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. - BOOST_HUD , - BOOST_ICON , - BOOST_THUMBNAIL , - BOOST_UI , - BOOST_PREVIEW , - BOOST_MAP , - BOOST_MAP_VISIBLE , - BOOST_MAX_LEVEL, - - //other texture Categories - LOCAL = BOOST_MAX_LEVEL, - AVATAR_SCRATCH_TEX, - DYNAMIC_TEX, - MEDIA, - ATLAS, - OTHER, - MAX_GL_IMAGE_CATEGORY - }; - - typedef enum - { - DELETED = 0, //removed from memory - DELETION_CANDIDATE, //ready to be removed from memory - INACTIVE, //not be used for the last certain period (i.e., 30 seconds). - ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). - NO_DELETE = 99 //stay in memory, can not be removed. - } LLGLTextureState; + BOOST_SELECTED , + BOOST_AVATAR_BAKED_SELF , + BOOST_AVATAR_SELF , // needed for baking avatar + BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay. + BOOST_HUD , + BOOST_ICON , + BOOST_THUMBNAIL , + BOOST_UI , + BOOST_PREVIEW , + BOOST_MAP , + BOOST_MAP_VISIBLE , + BOOST_MAX_LEVEL, + + //other texture Categories + LOCAL = BOOST_MAX_LEVEL, + AVATAR_SCRATCH_TEX, + DYNAMIC_TEX, + MEDIA, + ATLAS, + OTHER, + MAX_GL_IMAGE_CATEGORY + }; + + typedef enum + { + DELETED = 0, //removed from memory + DELETION_CANDIDATE, //ready to be removed from memory + INACTIVE, //not be used for the last certain period (i.e., 30 seconds). + ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds). + NO_DELETE = 99 //stay in memory, can not be removed. + } LLGLTextureState; protected: - virtual ~LLGLTexture(); - LOG_CLASS(LLGLTexture); + virtual ~LLGLTexture(); + LOG_CLASS(LLGLTexture); public: - LLGLTexture(BOOL usemipmaps = TRUE); - LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ; - LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + LLGLTexture(BOOL usemipmaps = TRUE); + LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + + virtual void dump(); // debug info to LL_INFOS() - virtual void dump(); // debug info to LL_INFOS() + virtual const LLUUID& getID() const; - virtual const LLUUID& getID() const; + void setBoostLevel(S32 level); + S32 getBoostLevel() { return mBoostLevel; } - void setBoostLevel(S32 level); - S32 getBoostLevel() { return mBoostLevel; } + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } - S32 getFullWidth() const { return mFullWidth; } - S32 getFullHeight() const { return mFullHeight; } + void generateGLTexture() ; + void destroyGLTexture() ; - void generateGLTexture() ; - void destroyGLTexture() ; + //--------------------------------------------------------------------------------------------- + //functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + /*virtual*/S32 getWidth(S32 discard_level = -1) const; + /*virtual*/S32 getHeight(S32 discard_level = -1) const; - //--------------------------------------------------------------------------------------------- - //functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - /*virtual*/S32 getWidth(S32 discard_level = -1) const; - /*virtual*/S32 getHeight(S32 discard_level = -1) const; + BOOL hasGLTexture() const ; + LLGLuint getTexName() const ; + BOOL createGLTexture() ; - BOOL hasGLTexture() const ; - LLGLuint getTexName() const ; - BOOL createGLTexture() ; - // Create a GL Texture from an image raw // discard_level - mip level, 0 for highest resultion mip // imageraw - the image to copy from @@ -131,74 +131,74 @@ public: // tex_name - if not null, will be set to the GL name of the texture created BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER, bool defer_copy = false, LLGLuint* tex_name = nullptr); - void setFilteringOption(LLTexUnit::eTextureFilterOptions option); - void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); - void setAddressMode(LLTexUnit::eTextureAddressMode mode); - BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); - BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); - void setGLTextureCreated (bool initialized); - void setCategory(S32 category) ; + void setFilteringOption(LLTexUnit::eTextureFilterOptions option); + void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); + void setAddressMode(LLTexUnit::eTextureAddressMode mode); + BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); + BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0); + void setGLTextureCreated (bool initialized); + void setCategory(S32 category) ; void setTexName(LLGLuint); // for forcing w/ externally created textures only void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target); - LLTexUnit::eTextureAddressMode getAddressMode(void) const ; - S32 getMaxDiscardLevel() const; - S32 getDiscardLevel() const; - S8 getComponents() const; - BOOL getBoundRecently() const; - S32Bytes getTextureMemory() const ; - LLGLenum getPrimaryFormat() const; - BOOL getIsAlphaMask() const ; - LLTexUnit::eTextureType getTarget(void) const ; - BOOL getMask(const LLVector2 &tc); - F32 getTimePassedSinceLastBound(); - BOOL getMissed() const ; - BOOL isJustBound()const ; - void forceUpdateBindStats(void) const; - - U32 getTexelsInAtlas() const ; - U32 getTexelsInGLTexture() const ; - BOOL isGLTextureCreated() const ; - S32 getDiscardLevelInAtlas() const ; - LLGLTextureState getTextureState() const { return mTextureState; } - - //--------------------------------------------------------------------------------------------- - //end of functions to access LLImageGL - //--------------------------------------------------------------------------------------------- - - //----------------- - /*virtual*/ void setActive() ; - void forceActive() ; - void setNoDelete() ; - void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } - BOOL getDontDiscard() const { return mDontDiscard; } - //----------------- + LLTexUnit::eTextureAddressMode getAddressMode(void) const ; + S32 getMaxDiscardLevel() const; + S32 getDiscardLevel() const; + S8 getComponents() const; + BOOL getBoundRecently() const; + S32Bytes getTextureMemory() const ; + LLGLenum getPrimaryFormat() const; + BOOL getIsAlphaMask() const ; + LLTexUnit::eTextureType getTarget(void) const ; + BOOL getMask(const LLVector2 &tc); + F32 getTimePassedSinceLastBound(); + BOOL getMissed() const ; + BOOL isJustBound()const ; + void forceUpdateBindStats(void) const; + + U32 getTexelsInAtlas() const ; + U32 getTexelsInGLTexture() const ; + BOOL isGLTextureCreated() const ; + S32 getDiscardLevelInAtlas() const ; + LLGLTextureState getTextureState() const { return mTextureState; } + + //--------------------------------------------------------------------------------------------- + //end of functions to access LLImageGL + //--------------------------------------------------------------------------------------------- + + //----------------- + /*virtual*/ void setActive() ; + void forceActive() ; + void setNoDelete() ; + void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; } + BOOL getDontDiscard() const { return mDontDiscard; } + //----------------- private: - void cleanup(); - void init(); + void cleanup(); + void init(); protected: - void setTexelsPerImage(); + void setTexelsPerImage(); public: - /*virtual*/ LLImageGL* getGLTexture() const ; + /*virtual*/ LLImageGL* getGLTexture() const ; protected: - S32 mBoostLevel; // enum describing priority level - U32 mFullWidth; - U32 mFullHeight; - BOOL mUseMipMaps; - S8 mComponents; - U32 mTexelsPerImage; // Texels per image. - mutable S8 mNeedsGLTexture; - - //GL texture - LLPointer mGLTexturep ; - S8 mDontDiscard; // Keep full res version of this image (for UI, etc) + S32 mBoostLevel; // enum describing priority level + U32 mFullWidth; + U32 mFullHeight; + BOOL mUseMipMaps; + S8 mComponents; + U32 mTexelsPerImage; // Texels per image. + mutable S8 mNeedsGLTexture; + + //GL texture + LLPointer mGLTexturep ; + S8 mDontDiscard; // Keep full res version of this image (for UI, etc) protected: - LLGLTextureState mTextureState ; + LLGLTextureState mTextureState ; }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 358b35f36b..b92c9363fc 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1,25 +1,25 @@ - /** + /** * @file llrender.cpp * @brief LLRender implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -51,8 +51,8 @@ extern void APIENTRY gl_debug_callback(GLenum source, thread_local LLRender gGL; // Handy copies of last good GL matrices -F32 gGLModelView[16]; -F32 gGLLastModelView[16]; +F32 gGLModelView[16]; +F32 gGLLastModelView[16]; F32 gGLLastProjection[16]; F32 gGLProjection[16]; @@ -60,7 +60,7 @@ F32 gGLProjection[16]; F32 gGLDeltaModelView[16]; F32 gGLInverseDeltaModelView[16]; -S32 gGLViewport[4]; +S32 gGLViewport[4]; U32 LLRender::sUICalls = 0; @@ -80,113 +80,113 @@ static std::unordered_map sVBCache; static const GLenum sGLTextureType[] = { - GL_TEXTURE_2D, - GL_TEXTURE_RECTANGLE, - GL_TEXTURE_CUBE_MAP, + GL_TEXTURE_2D, + GL_TEXTURE_RECTANGLE, + GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, - GL_TEXTURE_2D_MULTISAMPLE, + GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_3D }; static const GLint sGLAddressMode[] = -{ - GL_REPEAT, - GL_MIRRORED_REPEAT, - GL_CLAMP_TO_EDGE +{ + GL_REPEAT, + GL_MIRRORED_REPEAT, + GL_CLAMP_TO_EDGE }; const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; static const GLenum sGLBlendFactor[] = { - GL_ONE, - GL_ZERO, - GL_DST_COLOR, - GL_SRC_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_DST_ALPHA, - GL_SRC_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - - GL_ZERO // 'BF_UNDEF' + GL_ONE, + GL_ZERO, + GL_DST_COLOR, + GL_SRC_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_DST_ALPHA, + GL_SRC_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + + GL_ZERO // 'BF_UNDEF' }; LLTexUnit::LLTexUnit(S32 index) - : mCurrTexType(TT_NONE), + : mCurrTexType(TT_NONE), mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR), - mHasMipMaps(false), - mIndex(index) + mHasMipMaps(false), + mIndex(index) { - llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS); + llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS); } //static U32 LLTexUnit::getInternalType(eTextureType type) { - return sGLTextureType[type]; + return sGLTextureType[type]; } void LLTexUnit::refreshState(void) { - // We set dirty to true so that the tex unit knows to ignore caching - // and we reset the cached tex unit state + // We set dirty to true so that the tex unit knows to ignore caching + // and we reset the cached tex unit state - gGL.flush(); - - glActiveTexture(GL_TEXTURE0 + mIndex); + gGL.flush(); - if (mCurrTexType != TT_NONE) - { - glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); - } - else - { - glBindTexture(GL_TEXTURE_2D, 0); - } + glActiveTexture(GL_TEXTURE0 + mIndex); + + if (mCurrTexType != TT_NONE) + { + glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); + } + else + { + glBindTexture(GL_TEXTURE_2D, 0); + } setTextureColorSpace(mTexColorSpace); } void LLTexUnit::activate(void) { - if (mIndex < 0) return; + if (mIndex < 0) return; - if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) - { - gGL.flush(); - glActiveTexture(GL_TEXTURE0 + mIndex); - gGL.mCurrTextureUnitIndex = mIndex; - } + if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) + { + gGL.flush(); + glActiveTexture(GL_TEXTURE0 + mIndex); + gGL.mCurrTextureUnitIndex = mIndex; + } } void LLTexUnit::enable(eTextureType type) { - if (mIndex < 0) return; + if (mIndex < 0) return; - if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) ) - { - activate(); - if (mCurrTexType != TT_NONE && !gGL.mDirty) - { - disable(); // Force a disable of a previous texture type if it's enabled. - } - mCurrTexType = type; + if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) ) + { + activate(); + if (mCurrTexType != TT_NONE && !gGL.mDirty) + { + disable(); // Force a disable of a previous texture type if it's enabled. + } + mCurrTexType = type; - gGL.flush(); - } + gGL.flush(); + } } void LLTexUnit::disable(void) { - if (mIndex < 0) return; + if (mIndex < 0) return; - if (mCurrTexType != TT_NONE) - { - unbind(mCurrTexType); - mCurrTexType = TT_NONE; - } + if (mCurrTexType != TT_NONE) + { + unbind(mCurrTexType); + mCurrTexType = TT_NONE; + } } void LLTexUnit::bindFast(LLTexture* texture) @@ -211,231 +211,231 @@ void LLTexUnit::bindFast(LLTexture* texture) bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - stop_glerror(); - if (mIndex >= 0) - { - gGL.flush(); - - LLImageGL* gl_tex = NULL ; - - if (texture != NULL && (gl_tex = texture->getGLTexture())) - { - if (gl_tex->getTexName()) //if texture exists - { - //in audit, replace the selected texture by the default one. - if ((mCurrTexture != gl_tex->getTexName()) || forceBind) - { - activate(); - enable(gl_tex->getTarget()); - mCurrTexture = gl_tex->getTexName(); - glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); - if(gl_tex->updateBindStats()) - { - texture->setActive() ; - texture->updateBindStatsForTester() ; - } - mHasMipMaps = gl_tex->mHasMipMaps; - if (gl_tex->mTexOptionsDirty) - { - gl_tex->mTexOptionsDirty = false; - setTextureAddressMode(gl_tex->mAddressMode); - setTextureFilteringOption(gl_tex->mFilterOption); + stop_glerror(); + if (mIndex >= 0) + { + gGL.flush(); + + LLImageGL* gl_tex = NULL ; + + if (texture != NULL && (gl_tex = texture->getGLTexture())) + { + if (gl_tex->getTexName()) //if texture exists + { + //in audit, replace the selected texture by the default one. + if ((mCurrTexture != gl_tex->getTexName()) || forceBind) + { + activate(); + enable(gl_tex->getTarget()); + mCurrTexture = gl_tex->getTexName(); + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + if(gl_tex->updateBindStats()) + { + texture->setActive() ; + texture->updateBindStatsForTester() ; + } + mHasMipMaps = gl_tex->mHasMipMaps; + if (gl_tex->mTexOptionsDirty) + { + gl_tex->mTexOptionsDirty = false; + setTextureAddressMode(gl_tex->mAddressMode); + setTextureFilteringOption(gl_tex->mFilterOption); } setTextureColorSpace(mTexColorSpace); - } - } - else - { - //if deleted, will re-generate it immediately - texture->forceImmediateUpdate() ; - - gl_tex->forceUpdateBindStats() ; - return texture->bindDefaultImage(mIndex); - } - } - else - { - if (texture) - { - LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL; - } - else - { - LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; - } - return false; - } - } - else - { // mIndex < 0 - return false; - } - - return true; + } + } + else + { + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate() ; + + gl_tex->forceUpdateBindStats() ; + return texture->bindDefaultImage(mIndex); + } + } + else + { + if (texture) + { + LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL; + } + else + { + LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + } + return false; + } + } + else + { // mIndex < 0 + return false; + } + + return true; } bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename) { - stop_glerror(); - if (mIndex < 0) return false; + stop_glerror(); + if (mIndex < 0) return false; U32 texname = usename ? usename : texture->getTexName(); - if(!texture) - { - LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; - return false; - } - - if(!texname) - { - if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName()) - { - return bind(LLImageGL::sDefaultGLTexture) ; - } - stop_glerror(); - return false ; - } - - if ((mCurrTexture != texname) || forceBind) - { - gGL.flush(); - stop_glerror(); - activate(); - stop_glerror(); - enable(texture->getTarget()); - stop_glerror(); - mCurrTexture = texname; - glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); - stop_glerror(); + if(!texture) + { + LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + return false; + } + + if(!texname) + { + if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName()) + { + return bind(LLImageGL::sDefaultGLTexture) ; + } + stop_glerror(); + return false ; + } + + if ((mCurrTexture != texname) || forceBind) + { + gGL.flush(); + stop_glerror(); + activate(); + stop_glerror(); + enable(texture->getTarget()); + stop_glerror(); + mCurrTexture = texname; + glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); + stop_glerror(); texture->updateBindStats(); - mHasMipMaps = texture->mHasMipMaps; - if (texture->mTexOptionsDirty) - { - stop_glerror(); - texture->mTexOptionsDirty = false; - setTextureAddressMode(texture->mAddressMode); - setTextureFilteringOption(texture->mFilterOption); - stop_glerror(); - } + mHasMipMaps = texture->mHasMipMaps; + if (texture->mTexOptionsDirty) + { + stop_glerror(); + texture->mTexOptionsDirty = false; + setTextureAddressMode(texture->mAddressMode); + setTextureFilteringOption(texture->mFilterOption); + stop_glerror(); + } setTextureColorSpace(mTexColorSpace); - } + } - stop_glerror(); + stop_glerror(); - return true; + return true; } bool LLTexUnit::bind(LLCubeMap* cubeMap) { - if (mIndex < 0) return false; + if (mIndex < 0) return false; - gGL.flush(); + gGL.flush(); - if (cubeMap == NULL) - { - LL_WARNS() << "NULL LLTexUnit::bind cubemap" << LL_ENDL; - return false; - } + if (cubeMap == NULL) + { + LL_WARNS() << "NULL LLTexUnit::bind cubemap" << LL_ENDL; + return false; + } - if (mCurrTexture != cubeMap->mImages[0]->getTexName()) - { - if (LLCubeMap::sUseCubeMaps) - { - activate(); - enable(LLTexUnit::TT_CUBE_MAP); + if (mCurrTexture != cubeMap->mImages[0]->getTexName()) + { + if (LLCubeMap::sUseCubeMaps) + { + activate(); + enable(LLTexUnit::TT_CUBE_MAP); mCurrTexture = cubeMap->mImages[0]->getTexName(); - glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture); - mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; - cubeMap->mImages[0]->updateBindStats(); - if (cubeMap->mImages[0]->mTexOptionsDirty) - { - cubeMap->mImages[0]->mTexOptionsDirty = false; - setTextureAddressMode(cubeMap->mImages[0]->mAddressMode); - setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); + glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture); + mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps; + cubeMap->mImages[0]->updateBindStats(); + if (cubeMap->mImages[0]->mTexOptionsDirty) + { + cubeMap->mImages[0]->mTexOptionsDirty = false; + setTextureAddressMode(cubeMap->mImages[0]->mAddressMode); + setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption); } setTextureColorSpace(mTexColorSpace); - return true; - } - else - { - LL_WARNS() << "Using cube map without extension!" << LL_ENDL; - return false; - } - } - return true; + return true; + } + else + { + LL_WARNS() << "Using cube map without extension!" << LL_ENDL; + return false; + } + } + return true; } // LLRenderTarget is unavailible on the mapserver since it uses FBOs. bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) { - if (mIndex < 0) return false; + if (mIndex < 0) return false; - gGL.flush(); + gGL.flush(); - if (bindDepth) - { + if (bindDepth) + { llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment - bindManual(renderTarget->getUsage(), renderTarget->getDepth()); - } - else - { - bindManual(renderTarget->getUsage(), renderTarget->getTexture()); - } + bindManual(renderTarget->getUsage(), renderTarget->getDepth()); + } + else + { + bindManual(renderTarget->getUsage(), renderTarget->getTexture()); + } - return true; + return true; } bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { - if (mIndex < 0) - { - return false; - } - - if(mCurrTexture != texture) - { - gGL.flush(); - - activate(); - enable(type); - mCurrTexture = texture; - glBindTexture(sGLTextureType[type], texture); + if (mIndex < 0) + { + return false; + } + + if(mCurrTexture != texture) + { + gGL.flush(); + + activate(); + enable(type); + mCurrTexture = texture; + glBindTexture(sGLTextureType[type], texture); mHasMipMaps = hasMips; setTextureColorSpace(mTexColorSpace); - } - return true; + } + return true; } void LLTexUnit::unbind(eTextureType type) { - stop_glerror(); + stop_glerror(); - if (mIndex < 0) return; + if (mIndex < 0) return; - //always flush and activate for consistency - // some code paths assume unbind always flushes and sets the active texture - gGL.flush(); - activate(); + //always flush and activate for consistency + // some code paths assume unbind always flushes and sets the active texture + gGL.flush(); + activate(); - // Disabled caching of binding state. - if (mCurrTexType == type) - { - mCurrTexture = 0; + // Disabled caching of binding state. + if (mCurrTexType == type) + { + mCurrTexture = 0; // Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping". mTexColorSpace = TCS_LINEAR; - if (type == LLTexUnit::TT_TEXTURE) - { - glBindTexture(sGLTextureType[type], sWhiteTexture); - } - else - { - glBindTexture(sGLTextureType[type], 0); - } - stop_glerror(); - } + if (type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } + stop_glerror(); + } } void LLTexUnit::unbindFast(eTextureType type) @@ -462,184 +462,184 @@ void LLTexUnit::unbindFast(eTextureType type) void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) { - if (mIndex < 0 || mCurrTexture == 0) return; + if (mIndex < 0 || mCurrTexture == 0) return; - gGL.flush(); + gGL.flush(); - activate(); + activate(); - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); - glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); - if (mCurrTexType == TT_CUBE_MAP) - { - glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); - } + glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); + glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]); + if (mCurrTexType == TT_CUBE_MAP) + { + glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]); + } } void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) { - if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; - - gGL.flush(); - - if (option == TFO_POINT) - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (option >= TFO_TRILINEAR && mHasMipMaps) - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else if (option >= TFO_BILINEAR) - { - if (mHasMipMaps) - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - } - else - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - } - else - { - if (mHasMipMaps) - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - } - else - { - glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - - if (gGLManager.mGLVersion >= 4.59f) - { - if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) - { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy); - } - else - { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f); - } - } + if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; + + gGL.flush(); + + if (option == TFO_POINT) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (option >= TFO_TRILINEAR && mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } + else if (option >= TFO_BILINEAR) + { + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + else + { + if (mHasMipMaps) + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + else + { + glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + } + + if (gGLManager.mGLVersion >= 4.59f) + { + if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) + { + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy); + } + else + { + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f); + } + } } GLint LLTexUnit::getTextureSource(eTextureBlendSrc src) { - switch(src) - { - // All four cases should return the same value. - case TBS_PREV_COLOR: - case TBS_PREV_ALPHA: - case TBS_ONE_MINUS_PREV_COLOR: - case TBS_ONE_MINUS_PREV_ALPHA: - return GL_PREVIOUS; - - // All four cases should return the same value. - case TBS_TEX_COLOR: - case TBS_TEX_ALPHA: - case TBS_ONE_MINUS_TEX_COLOR: - case TBS_ONE_MINUS_TEX_ALPHA: - return GL_TEXTURE; - - // All four cases should return the same value. - case TBS_VERT_COLOR: - case TBS_VERT_ALPHA: - case TBS_ONE_MINUS_VERT_COLOR: - case TBS_ONE_MINUS_VERT_ALPHA: - return GL_PRIMARY_COLOR; - - // All four cases should return the same value. - case TBS_CONST_COLOR: - case TBS_CONST_ALPHA: - case TBS_ONE_MINUS_CONST_COLOR: - case TBS_ONE_MINUS_CONST_ALPHA: - return GL_CONSTANT; - - default: - LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL; - return GL_PRIMARY_COLOR; - } + switch(src) + { + // All four cases should return the same value. + case TBS_PREV_COLOR: + case TBS_PREV_ALPHA: + case TBS_ONE_MINUS_PREV_COLOR: + case TBS_ONE_MINUS_PREV_ALPHA: + return GL_PREVIOUS; + + // All four cases should return the same value. + case TBS_TEX_COLOR: + case TBS_TEX_ALPHA: + case TBS_ONE_MINUS_TEX_COLOR: + case TBS_ONE_MINUS_TEX_ALPHA: + return GL_TEXTURE; + + // All four cases should return the same value. + case TBS_VERT_COLOR: + case TBS_VERT_ALPHA: + case TBS_ONE_MINUS_VERT_COLOR: + case TBS_ONE_MINUS_VERT_ALPHA: + return GL_PRIMARY_COLOR; + + // All four cases should return the same value. + case TBS_CONST_COLOR: + case TBS_CONST_ALPHA: + case TBS_ONE_MINUS_CONST_COLOR: + case TBS_ONE_MINUS_CONST_ALPHA: + return GL_CONSTANT; + + default: + LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL; + return GL_PRIMARY_COLOR; + } } GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) { - switch(src) - { - // All four cases should return the same value. - case TBS_PREV_COLOR: - case TBS_TEX_COLOR: - case TBS_VERT_COLOR: - case TBS_CONST_COLOR: - return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR; - - // All four cases should return the same value. - case TBS_PREV_ALPHA: - case TBS_TEX_ALPHA: - case TBS_VERT_ALPHA: - case TBS_CONST_ALPHA: - return GL_SRC_ALPHA; - - // All four cases should return the same value. - case TBS_ONE_MINUS_PREV_COLOR: - case TBS_ONE_MINUS_TEX_COLOR: - case TBS_ONE_MINUS_VERT_COLOR: - case TBS_ONE_MINUS_CONST_COLOR: - return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR; - - // All four cases should return the same value. - case TBS_ONE_MINUS_PREV_ALPHA: - case TBS_ONE_MINUS_TEX_ALPHA: - case TBS_ONE_MINUS_VERT_ALPHA: - case TBS_ONE_MINUS_CONST_ALPHA: - return GL_ONE_MINUS_SRC_ALPHA; - - default: - LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Source Color or Alpha instead." << LL_ENDL; - return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR; - } + switch(src) + { + // All four cases should return the same value. + case TBS_PREV_COLOR: + case TBS_TEX_COLOR: + case TBS_VERT_COLOR: + case TBS_CONST_COLOR: + return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR; + + // All four cases should return the same value. + case TBS_PREV_ALPHA: + case TBS_TEX_ALPHA: + case TBS_VERT_ALPHA: + case TBS_CONST_ALPHA: + return GL_SRC_ALPHA; + + // All four cases should return the same value. + case TBS_ONE_MINUS_PREV_COLOR: + case TBS_ONE_MINUS_TEX_COLOR: + case TBS_ONE_MINUS_VERT_COLOR: + case TBS_ONE_MINUS_CONST_COLOR: + return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR; + + // All four cases should return the same value. + case TBS_ONE_MINUS_PREV_ALPHA: + case TBS_ONE_MINUS_TEX_ALPHA: + case TBS_ONE_MINUS_VERT_ALPHA: + case TBS_ONE_MINUS_CONST_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + + default: + LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Source Color or Alpha instead." << LL_ENDL; + return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR; + } } void LLTexUnit::setColorScale(S32 scale) { - if (mCurrColorScale != scale || gGL.mDirty) - { - mCurrColorScale = scale; - gGL.flush(); - glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); - } + if (mCurrColorScale != scale || gGL.mDirty) + { + mCurrColorScale = scale; + gGL.flush(); + glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); + } } void LLTexUnit::setAlphaScale(S32 scale) { - if (mCurrAlphaScale != scale || gGL.mDirty) - { - mCurrAlphaScale = scale; - gGL.flush(); - glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); - } + if (mCurrAlphaScale != scale || gGL.mDirty) + { + mCurrAlphaScale = scale; + gGL.flush(); + glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); + } } -// Useful for debugging that you've manually assigned a texture operation to the correct +// Useful for debugging that you've manually assigned a texture operation to the correct // texture unit based on the currently set active texture in opengl. void LLTexUnit::debugTextureUnit(void) { - if (mIndex < 0) return; + if (mIndex < 0) return; - GLint activeTexture; - glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); - if ((GL_TEXTURE0 + mIndex) != activeTexture) - { - U32 set_unit = (activeTexture - GL_TEXTURE0); - LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL; - } + GLint activeTexture; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); + if ((GL_TEXTURE0 + mIndex) != activeTexture) + { + U32 set_unit = (activeTexture - GL_TEXTURE0); + LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL; + } } void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) @@ -656,46 +656,46 @@ LLLightState::LLLightState(S32 index) mSpotExponent(0.f), mSpotCutoff(180.f) { - if (mIndex == 0) - { - mDiffuse.set(1,1,1,1); + if (mIndex == 0) + { + mDiffuse.set(1,1,1,1); mDiffuseB.set(0,0,0,0); - mSpecular.set(1,1,1,1); - } + mSpecular.set(1,1,1,1); + } mSunIsPrimary = true; - mAmbient.set(0,0,0,1); - mPosition.set(0,0,1,0); - mSpotDirection.set(0,0,-1); + mAmbient.set(0,0,0,1); + mPosition.set(0,0,1,0); + mSpotDirection.set(0,0,-1); } void LLLightState::enable() { - mEnabled = true; + mEnabled = true; } void LLLightState::disable() { - mEnabled = false; + mEnabled = false; } void LLLightState::setDiffuse(const LLColor4& diffuse) { - if (mDiffuse != diffuse) - { - ++gGL.mLightHash; - mDiffuse = diffuse; - } + if (mDiffuse != diffuse) + { + ++gGL.mLightHash; + mDiffuse = diffuse; + } } void LLLightState::setDiffuseB(const LLColor4& diffuse) { if (mDiffuseB != diffuse) - { - ++gGL.mLightHash; - mDiffuseB = diffuse; - } + { + ++gGL.mLightHash; + mDiffuseB = diffuse; + } } void LLLightState::setSunPrimary(bool v) @@ -703,7 +703,7 @@ void LLLightState::setSunPrimary(bool v) if (mSunIsPrimary != v) { ++gGL.mLightHash; - mSunIsPrimary = v; + mSunIsPrimary = v; } } @@ -727,134 +727,134 @@ void LLLightState::setFalloff(F32 v) void LLLightState::setAmbient(const LLColor4& ambient) { - if (mAmbient != ambient) - { - ++gGL.mLightHash; - mAmbient = ambient; - } + if (mAmbient != ambient) + { + ++gGL.mLightHash; + mAmbient = ambient; + } } void LLLightState::setSpecular(const LLColor4& specular) { - if (mSpecular != specular) - { - ++gGL.mLightHash; - mSpecular = specular; - } + if (mSpecular != specular) + { + ++gGL.mLightHash; + mSpecular = specular; + } } void LLLightState::setPosition(const LLVector4& position) { - //always set position because modelview matrix may have changed - ++gGL.mLightHash; - mPosition = position; - //transform position by current modelview matrix - glh::vec4f pos(position.mV); - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_vec(pos); - mPosition.set(pos.v); + //always set position because modelview matrix may have changed + ++gGL.mLightHash; + mPosition = position; + //transform position by current modelview matrix + glh::vec4f pos(position.mV); + const glh::matrix4f& mat = gGL.getModelviewMatrix(); + mat.mult_matrix_vec(pos); + mPosition.set(pos.v); } void LLLightState::setConstantAttenuation(const F32& atten) { - if (mConstantAtten != atten) - { - mConstantAtten = atten; - ++gGL.mLightHash; - } + if (mConstantAtten != atten) + { + mConstantAtten = atten; + ++gGL.mLightHash; + } } void LLLightState::setLinearAttenuation(const F32& atten) { - if (mLinearAtten != atten) - { - ++gGL.mLightHash; - mLinearAtten = atten; - } + if (mLinearAtten != atten) + { + ++gGL.mLightHash; + mLinearAtten = atten; + } } void LLLightState::setQuadraticAttenuation(const F32& atten) { - if (mQuadraticAtten != atten) - { - ++gGL.mLightHash; - mQuadraticAtten = atten; - } + if (mQuadraticAtten != atten) + { + ++gGL.mLightHash; + mQuadraticAtten = atten; + } } void LLLightState::setSpotExponent(const F32& exponent) { - if (mSpotExponent != exponent) - { - ++gGL.mLightHash; - mSpotExponent = exponent; - } + if (mSpotExponent != exponent) + { + ++gGL.mLightHash; + mSpotExponent = exponent; + } } void LLLightState::setSpotCutoff(const F32& cutoff) { - if (mSpotCutoff != cutoff) - { - ++gGL.mLightHash; - mSpotCutoff = cutoff; - } + if (mSpotCutoff != cutoff) + { + ++gGL.mLightHash; + mSpotCutoff = cutoff; + } } void LLLightState::setSpotDirection(const LLVector3& direction) { - //always set direction because modelview matrix may have changed - ++gGL.mLightHash; - mSpotDirection = direction; - //transform direction by current modelview matrix - glh::vec3f dir(direction.mV); - const glh::matrix4f& mat = gGL.getModelviewMatrix(); - mat.mult_matrix_dir(dir); + //always set direction because modelview matrix may have changed + ++gGL.mLightHash; + mSpotDirection = direction; + //transform direction by current modelview matrix + glh::vec3f dir(direction.mV); + const glh::matrix4f& mat = gGL.getModelviewMatrix(); + mat.mult_matrix_dir(dir); - mSpotDirection.set(dir.v); + mSpotDirection.set(dir.v); } LLRender::LLRender() : mDirty(false), mCount(0), - mQuadCycle(0), + mQuadCycle(0), mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0) -{ - for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) - { +{ + for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) + { mTexUnits[i].mIndex = i; - } + } - for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) - { + for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) + { mLightState[i].mIndex = i; - } + } - for (U32 i = 0; i < 4; i++) - { - mCurrColorMask[i] = true; - } + for (U32 i = 0; i < 4; i++) + { + mCurrColorMask[i] = true; + } - mCurrBlendColorSFactor = BF_UNDEF; - mCurrBlendAlphaSFactor = BF_UNDEF; - mCurrBlendColorDFactor = BF_UNDEF; - mCurrBlendAlphaDFactor = BF_UNDEF; + mCurrBlendColorSFactor = BF_UNDEF; + mCurrBlendAlphaSFactor = BF_UNDEF; + mCurrBlendColorDFactor = BF_UNDEF; + mCurrBlendAlphaDFactor = BF_UNDEF; - mMatrixMode = LLRender::MM_MODELVIEW; - - for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) - { - mMatIdx[i] = 0; - mMatHash[i] = 0; - mCurMatHash[i] = 0xFFFFFFFF; - } + mMatrixMode = LLRender::MM_MODELVIEW; - mLightHash = 0; + for (U32 i = 0; i < NUM_MATRIX_MODES; ++i) + { + mMatIdx[i] = 0; + mMatHash[i] = 0; + mCurMatHash[i] = 0xFFFFFFFF; + } + + mLightHash = 0; } LLRender::~LLRender() { - shutdown(); + shutdown(); } bool LLRender::init(bool needs_vertex_buffer) @@ -923,22 +923,22 @@ void LLRender::shutdown() void LLRender::refreshState(void) { - mDirty = true; + mDirty = true; - U32 active_unit = mCurrTextureUnitIndex; + U32 active_unit = mCurrTextureUnitIndex; - for (U32 i = 0; i < mTexUnits.size(); i++) - { - mTexUnits[i].refreshState(); - } - - mTexUnits[active_unit].activate(); + for (U32 i = 0; i < mTexUnits.size(); i++) + { + mTexUnits[i].refreshState(); + } + + mTexUnits[active_unit].activate(); + + setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); - setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]); - flush(); - mDirty = false; + mDirty = false; } void LLRender::syncLightState() @@ -990,36 +990,36 @@ void LLRender::syncLightState() void LLRender::syncMatrices() { - static const U32 name[] = - { - LLShaderMgr::MODELVIEW_MATRIX, - LLShaderMgr::PROJECTION_MATRIX, - LLShaderMgr::TEXTURE_MATRIX0, - LLShaderMgr::TEXTURE_MATRIX1, - LLShaderMgr::TEXTURE_MATRIX2, - LLShaderMgr::TEXTURE_MATRIX3, - }; + static const U32 name[] = + { + LLShaderMgr::MODELVIEW_MATRIX, + LLShaderMgr::PROJECTION_MATRIX, + LLShaderMgr::TEXTURE_MATRIX0, + LLShaderMgr::TEXTURE_MATRIX1, + LLShaderMgr::TEXTURE_MATRIX2, + LLShaderMgr::TEXTURE_MATRIX3, + }; - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - static glh::matrix4f cached_mvp; + static glh::matrix4f cached_mvp; static glh::matrix4f cached_inv_mdv; - static U32 cached_mvp_mdv_hash = 0xFFFFFFFF; - static U32 cached_mvp_proj_hash = 0xFFFFFFFF; - - static glh::matrix4f cached_normal; - static U32 cached_normal_hash = 0xFFFFFFFF; + static U32 cached_mvp_mdv_hash = 0xFFFFFFFF; + static U32 cached_mvp_proj_hash = 0xFFFFFFFF; - if (shader) - { - //llassert(shader); + static glh::matrix4f cached_normal; + static U32 cached_normal_hash = 0xFFFFFFFF; - bool mvp_done = false; + if (shader) + { + //llassert(shader); + + bool mvp_done = false; - U32 i = MM_MODELVIEW; - if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW]) - { //update modelview, normal, and MVP - glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; + U32 i = MM_MODELVIEW; + if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW]) + { //update modelview, normal, and MVP + glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; // if MDV has changed, update the cached inverse as well if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW]) @@ -1027,240 +1027,240 @@ void LLRender::syncMatrices() cached_inv_mdv = mat.inverse(); } - shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m); - shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW]; + shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m); + shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW]; - //update normal matrix - S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX); - if (loc > -1) - { - if (cached_normal_hash != mMatHash[i]) - { - cached_normal = cached_inv_mdv.transpose(); - cached_normal_hash = mMatHash[i]; - } + //update normal matrix + S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX); + if (loc > -1) + { + if (cached_normal_hash != mMatHash[i]) + { + cached_normal = cached_inv_mdv.transpose(); + cached_normal_hash = mMatHash[i]; + } - glh::matrix4f& norm = cached_normal; + glh::matrix4f& norm = cached_normal; - F32 norm_mat[] = - { - norm.m[0], norm.m[1], norm.m[2], - norm.m[4], norm.m[5], norm.m[6], - norm.m[8], norm.m[9], norm.m[10] - }; + F32 norm_mat[] = + { + norm.m[0], norm.m[1], norm.m[2], + norm.m[4], norm.m[5], norm.m[6], + norm.m[8], norm.m[9], norm.m[10] + }; - shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat); - } + shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat); + } if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX)) - { - shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m); + { + shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m); + } + + //update MVP matrix + mvp_done = true; + loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX); + if (loc > -1) + { + U32 proj = MM_PROJECTION; + + if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) + { + cached_mvp = mat; + cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]); + cached_mvp_mdv_hash = mMatHash[i]; + cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; + } + + shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); } + } - //update MVP matrix - mvp_done = true; - loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX); - if (loc > -1) - { - U32 proj = MM_PROJECTION; - - if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) - { - cached_mvp = mat; - cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]); - cached_mvp_mdv_hash = mMatHash[i]; - cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; - } - - shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); - } - } - - i = MM_PROJECTION; - if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION]) - { //update projection matrix, normal, and MVP - glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; + i = MM_PROJECTION; + if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION]) + { //update projection matrix, normal, and MVP + glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; // GZ: This was previously disabled seemingly due to a bug involving the deferred renderer's regular pushing and popping of mats. - // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially. - // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future. + // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially. + // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future. if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX)) { - glh::matrix4f inv_proj = mat.inverse(); - shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m); + glh::matrix4f inv_proj = mat.inverse(); + shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m); } - // Used by some full screen effects - such as full screen lights, glow, etc. + // Used by some full screen effects - such as full screen lights, glow, etc. if (shader->getUniformLocation(LLShaderMgr::IDENTITY_MATRIX)) { shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glh::matrix4f::identity().m); } - shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m); - shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION]; - - if (!mvp_done) - { - //update MVP matrix - S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX); - if (loc > -1) - { - if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) - { - U32 mdv = MM_MODELVIEW; - cached_mvp = mat; - cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]); - cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW]; - cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; - } - - shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); - } - } - } - - for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i) - { - if (mMatHash[i] != shader->mMatHash[i]) - { - shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m); - shader->mMatHash[i] = mMatHash[i]; - } - } - - - if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics) - { //also sync light state - syncLightState(); - } - } + shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m); + shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION]; + + if (!mvp_done) + { + //update MVP matrix + S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX); + if (loc > -1) + { + if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION]) + { + U32 mdv = MM_MODELVIEW; + cached_mvp = mat; + cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]); + cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW]; + cached_mvp_proj_hash = mMatHash[MM_PROJECTION]; + } + + shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m); + } + } + } + + for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i) + { + if (mMatHash[i] != shader->mMatHash[i]) + { + shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m); + shader->mMatHash[i] = mMatHash[i]; + } + } + + + if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics) + { //also sync light state + syncLightState(); + } + } } void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z) { - flush(); + flush(); - { - glh::matrix4f trans_mat(1,0,0,x, - 0,1,0,y, - 0,0,1,z, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat); - mMatHash[mMatrixMode]++; - } + { + glh::matrix4f trans_mat(1,0,0,x, + 0,1,0,y, + 0,0,1,z, + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat); + mMatHash[mMatrixMode]++; + } } void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z) { - flush(); - - { - glh::matrix4f scale_mat(x,0,0,0, - 0,y,0,0, - 0,0,z,0, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat); - mMatHash[mMatrixMode]++; - } + flush(); + + { + glh::matrix4f scale_mat(x,0,0,0, + 0,y,0,0, + 0,0,z,0, + 0,0,0,1); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat); + mMatHash[mMatrixMode]++; + } } void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar) { - flush(); + flush(); + + { - { + glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left), + 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom), + 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), + 0,0,0,1); - glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left), - 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom), - 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear), - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat); - mMatHash[mMatrixMode]++; - } + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat); + mMatHash[mMatrixMode]++; + } } void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z) { - flush(); + flush(); + + { + F32 r = a * DEG_TO_RAD; - { - F32 r = a * DEG_TO_RAD; + F32 c = cosf(r); + F32 s = sinf(r); - F32 c = cosf(r); - F32 s = sinf(r); + F32 ic = 1.f-c; - F32 ic = 1.f-c; + glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0, + x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0, + x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0, + 0,0,0,1); - glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0, - x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0, - x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0, - 0,0,0,1); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat); - mMatHash[mMatrixMode]++; - } + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat); + mMatHash[mMatrixMode]++; + } } void LLRender::pushMatrix() { - flush(); - - { - if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1) - { - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]]; - ++mMatIdx[mMatrixMode]; - } - else - { - LL_WARNS() << "Matrix stack overflow." << LL_ENDL; - } - } + flush(); + + { + if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1) + { + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]]; + ++mMatIdx[mMatrixMode]; + } + else + { + LL_WARNS() << "Matrix stack overflow." << LL_ENDL; + } + } } void LLRender::popMatrix() { - flush(); - { - if (mMatIdx[mMatrixMode] > 0) - { - --mMatIdx[mMatrixMode]; - mMatHash[mMatrixMode]++; - } - else - { - LL_WARNS() << "Matrix stack underflow." << LL_ENDL; - } - } + flush(); + { + if (mMatIdx[mMatrixMode] > 0) + { + --mMatIdx[mMatrixMode]; + mMatHash[mMatrixMode]++; + } + else + { + LL_WARNS() << "Matrix stack underflow." << LL_ENDL; + } + } } void LLRender::loadMatrix(const GLfloat* m) { - flush(); - { - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m); - mMatHash[mMatrixMode]++; - } + flush(); + { + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m); + mMatHash[mMatrixMode]++; + } } void LLRender::multMatrix(const GLfloat* m) { - flush(); - { - glh::matrix4f mat((GLfloat*) m); - - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat); - mMatHash[mMatrixMode]++; - } + flush(); + { + glh::matrix4f mat((GLfloat*) m); + + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat); + mMatHash[mMatrixMode]++; + } } void LLRender::matrixMode(eMatrixMode mode) { - if (mode == MM_TEXTURE) - { + if (mode == MM_TEXTURE) + { U32 tex_index = gGL.getCurrentTexUnitIndex(); // the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering llassert(tex_index <= 3); @@ -1272,360 +1272,360 @@ void LLRender::matrixMode(eMatrixMode mode) LL_WARNS_ONCE() << "Attempted to assign matrix mode out of bounds: " << mode << LL_ENDL; mode = MM_TEXTURE0; } - } + } - mMatrixMode = mode; + mMatrixMode = mode; } LLRender::eMatrixMode LLRender::getMatrixMode() { - if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3) - { //always return MM_TEXTURE if current matrix mode points at any texture matrix - return MM_TEXTURE; - } + if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3) + { //always return MM_TEXTURE if current matrix mode points at any texture matrix + return MM_TEXTURE; + } - return mMatrixMode; + return mMatrixMode; } void LLRender::loadIdentity() { - flush(); + flush(); - { - llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; + { + llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; - mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); - mMatHash[mMatrixMode]++; - } + mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity(); + mMatHash[mMatrixMode]++; + } } const glh::matrix4f& LLRender::getModelviewMatrix() { - return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; + return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]]; } const glh::matrix4f& LLRender::getProjectionMatrix() { - return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; + return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]]; } void LLRender::translateUI(F32 x, F32 y, F32 z) { - if (mUIOffset.empty()) - { - LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL; - } + if (mUIOffset.empty()) + { + LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL; + } - mUIOffset.back().mV[0] += x; - mUIOffset.back().mV[1] += y; - mUIOffset.back().mV[2] += z; + mUIOffset.back().mV[0] += x; + mUIOffset.back().mV[1] += y; + mUIOffset.back().mV[2] += z; } void LLRender::scaleUI(F32 x, F32 y, F32 z) { - if (mUIScale.empty()) - { - LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL; - } + if (mUIScale.empty()) + { + LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL; + } - mUIScale.back().scaleVec(LLVector3(x,y,z)); + mUIScale.back().scaleVec(LLVector3(x,y,z)); } void LLRender::pushUIMatrix() { - if (mUIOffset.empty()) - { - mUIOffset.push_back(LLVector3(0,0,0)); - } - else - { - mUIOffset.push_back(mUIOffset.back()); - } - - if (mUIScale.empty()) - { - mUIScale.push_back(LLVector3(1,1,1)); - } - else - { - mUIScale.push_back(mUIScale.back()); - } + if (mUIOffset.empty()) + { + mUIOffset.push_back(LLVector3(0,0,0)); + } + else + { + mUIOffset.push_back(mUIOffset.back()); + } + + if (mUIScale.empty()) + { + mUIScale.push_back(LLVector3(1,1,1)); + } + else + { + mUIScale.push_back(mUIScale.back()); + } } void LLRender::popUIMatrix() { - if (mUIOffset.empty()) - { - LL_ERRS() << "UI offset stack blown." << LL_ENDL; - } - mUIOffset.pop_back(); - mUIScale.pop_back(); + if (mUIOffset.empty()) + { + LL_ERRS() << "UI offset stack blown." << LL_ENDL; + } + mUIOffset.pop_back(); + mUIScale.pop_back(); } LLVector3 LLRender::getUITranslation() { - if (mUIOffset.empty()) - { - return LLVector3(0,0,0); - } - return mUIOffset.back(); + if (mUIOffset.empty()) + { + return LLVector3(0,0,0); + } + return mUIOffset.back(); } LLVector3 LLRender::getUIScale() { - if (mUIScale.empty()) - { - return LLVector3(1,1,1); - } - return mUIScale.back(); + if (mUIScale.empty()) + { + return LLVector3(1,1,1); + } + return mUIScale.back(); } void LLRender::loadUIIdentity() { - if (mUIOffset.empty()) - { - LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL; - } - mUIOffset.back().setVec(0,0,0); - mUIScale.back().setVec(1,1,1); + if (mUIOffset.empty()) + { + LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL; + } + mUIOffset.back().setVec(0,0,0); + mUIScale.back().setVec(1,1,1); } void LLRender::setColorMask(bool writeColor, bool writeAlpha) { - setColorMask(writeColor, writeColor, writeColor, writeAlpha); + setColorMask(writeColor, writeColor, writeColor, writeAlpha); } void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha) { - flush(); - - if (mCurrColorMask[0] != writeColorR || - mCurrColorMask[1] != writeColorG || - mCurrColorMask[2] != writeColorB || - mCurrColorMask[3] != writeAlpha) - { - mCurrColorMask[0] = writeColorR; - mCurrColorMask[1] = writeColorG; - mCurrColorMask[2] = writeColorB; - mCurrColorMask[3] = writeAlpha; + flush(); - glColorMask(writeColorR ? GL_TRUE : GL_FALSE, - writeColorG ? GL_TRUE : GL_FALSE, - writeColorB ? GL_TRUE : GL_FALSE, - writeAlpha ? GL_TRUE : GL_FALSE); - } + if (mCurrColorMask[0] != writeColorR || + mCurrColorMask[1] != writeColorG || + mCurrColorMask[2] != writeColorB || + mCurrColorMask[3] != writeAlpha) + { + mCurrColorMask[0] = writeColorR; + mCurrColorMask[1] = writeColorG; + mCurrColorMask[2] = writeColorB; + mCurrColorMask[3] = writeAlpha; + + glColorMask(writeColorR ? GL_TRUE : GL_FALSE, + writeColorG ? GL_TRUE : GL_FALSE, + writeColorB ? GL_TRUE : GL_FALSE, + writeAlpha ? GL_TRUE : GL_FALSE); + } } void LLRender::setSceneBlendType(eBlendType type) { - switch (type) - { - case BT_ALPHA: - blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA); - break; - case BT_ADD: - blendFunc(BF_ONE, BF_ONE); - break; - case BT_ADD_WITH_ALPHA: - blendFunc(BF_SOURCE_ALPHA, BF_ONE); - break; - case BT_MULT: - blendFunc(BF_DEST_COLOR, BF_ZERO); - break; - case BT_MULT_ALPHA: - blendFunc(BF_DEST_ALPHA, BF_ZERO); - break; - case BT_MULT_X2: - blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR); - break; - case BT_REPLACE: - blendFunc(BF_ONE, BF_ZERO); - break; - default: - LL_ERRS() << "Unknown Scene Blend Type: " << type << LL_ENDL; - break; - } + switch (type) + { + case BT_ALPHA: + blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA); + break; + case BT_ADD: + blendFunc(BF_ONE, BF_ONE); + break; + case BT_ADD_WITH_ALPHA: + blendFunc(BF_SOURCE_ALPHA, BF_ONE); + break; + case BT_MULT: + blendFunc(BF_DEST_COLOR, BF_ZERO); + break; + case BT_MULT_ALPHA: + blendFunc(BF_DEST_ALPHA, BF_ZERO); + break; + case BT_MULT_X2: + blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR); + break; + case BT_REPLACE: + blendFunc(BF_ONE, BF_ZERO); + break; + default: + LL_ERRS() << "Unknown Scene Blend Type: " << type << LL_ENDL; + break; + } } void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) { - llassert(sfactor < BF_UNDEF); - llassert(dfactor < BF_UNDEF); - if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || - mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor) - { - mCurrBlendColorSFactor = sfactor; - mCurrBlendAlphaSFactor = sfactor; - mCurrBlendColorDFactor = dfactor; - mCurrBlendAlphaDFactor = dfactor; - flush(); - glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]); - } + llassert(sfactor < BF_UNDEF); + llassert(dfactor < BF_UNDEF); + if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || + mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor) + { + mCurrBlendColorSFactor = sfactor; + mCurrBlendAlphaSFactor = sfactor; + mCurrBlendColorDFactor = dfactor; + mCurrBlendAlphaDFactor = dfactor; + flush(); + glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]); + } } void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, - eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) -{ - llassert(color_sfactor < BF_UNDEF); - llassert(color_dfactor < BF_UNDEF); - llassert(alpha_sfactor < BF_UNDEF); - llassert(alpha_dfactor < BF_UNDEF); - - if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || - mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor) - { - mCurrBlendColorSFactor = color_sfactor; - mCurrBlendAlphaSFactor = alpha_sfactor; - mCurrBlendColorDFactor = color_dfactor; - mCurrBlendAlphaDFactor = alpha_dfactor; - flush(); - + eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) +{ + llassert(color_sfactor < BF_UNDEF); + llassert(color_dfactor < BF_UNDEF); + llassert(alpha_sfactor < BF_UNDEF); + llassert(alpha_dfactor < BF_UNDEF); + + if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || + mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor) + { + mCurrBlendColorSFactor = color_sfactor; + mCurrBlendAlphaSFactor = alpha_sfactor; + mCurrBlendColorDFactor = color_dfactor; + mCurrBlendAlphaDFactor = alpha_dfactor; + flush(); + glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor], sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); - } + } } LLTexUnit* LLRender::getTexUnit(U32 index) { - if (index < mTexUnits.size()) - { - return &mTexUnits[index]; - } - else - { - LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL; - return &mDummyTexUnit; - } + if (index < mTexUnits.size()) + { + return &mTexUnits[index]; + } + else + { + LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL; + return &mDummyTexUnit; + } } LLLightState* LLRender::getLight(U32 index) { - if (index < mLightState.size()) - { - return &mLightState[index]; - } - - return NULL; + if (index < mLightState.size()) + { + return &mLightState[index]; + } + + return NULL; } void LLRender::setAmbientLightColor(const LLColor4& color) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE - if (color != mAmbientLightColor) - { - ++mLightHash; - mAmbientLightColor = color; - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE + if (color != mAmbientLightColor) + { + ++mLightHash; + mAmbientLightColor = color; + } } bool LLRender::verifyTexUnitActive(U32 unitToVerify) { - if (mCurrTextureUnitIndex == unitToVerify) - { - return true; - } - else - { - LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL; - return false; - } + if (mCurrTextureUnitIndex == unitToVerify) + { + return true; + } + else + { + LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL; + return false; + } } void LLRender::clearErrors() { - while (glGetError()) - { - //loop until no more error flags left - } + while (glGetError()) + { + //loop until no more error flags left + } } void LLRender::begin(const GLuint& mode) { - if (mode != mMode) - { - if (mode == LLRender::QUADS) - { - mQuadCycle = 1; - } - - if (mMode == LLRender::QUADS || - mMode == LLRender::LINES || - mMode == LLRender::TRIANGLES || - mMode == LLRender::POINTS) - { - flush(); - } - else if (mCount != 0) - { - LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL; - } - - mMode = mode; - } + if (mode != mMode) + { + if (mode == LLRender::QUADS) + { + mQuadCycle = 1; + } + + if (mMode == LLRender::QUADS || + mMode == LLRender::LINES || + mMode == LLRender::TRIANGLES || + mMode == LLRender::POINTS) + { + flush(); + } + else if (mCount != 0) + { + LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL; + } + + mMode = mode; + } } void LLRender::end() -{ - if (mCount == 0) - { - return; - //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; - } - - if ((mMode != LLRender::QUADS && - mMode != LLRender::LINES && - mMode != LLRender::TRIANGLES && - mMode != LLRender::POINTS) || - mCount > 2048) - { - flush(); - } +{ + if (mCount == 0) + { + return; + //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL; + } + + if ((mMode != LLRender::QUADS && + mMode != LLRender::LINES && + mMode != LLRender::TRIANGLES && + mMode != LLRender::POINTS) || + mCount > 2048) + { + flush(); + } } void LLRender::flush() { - if (mCount > 0) - { + if (mCount > 0) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr); - if (!mUIOffset.empty()) - { - sUICalls++; - sUIVerts += mCount; - } - - //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) - U32 count = mCount; - - if (mMode == LLRender::QUADS && !sGLCoreProfile) - { - if (mCount%4 != 0) - { - count -= (mCount % 4); - LL_WARNS() << "Incomplete quad requested." << LL_ENDL; - } - } - - if (mMode == LLRender::TRIANGLES) - { - if (mCount%3 != 0) - { - count -= (mCount % 3); - LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; - } - } - - if (mMode == LLRender::LINES) - { - if (mCount%2 != 0) - { - count -= (mCount % 2); - LL_WARNS() << "Incomplete line requested." << LL_ENDL; - } - } - - mCount = 0; + if (!mUIOffset.empty()) + { + sUICalls++; + sUIVerts += mCount; + } + + //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) + U32 count = mCount; + + if (mMode == LLRender::QUADS && !sGLCoreProfile) + { + if (mCount%4 != 0) + { + count -= (mCount % 4); + LL_WARNS() << "Incomplete quad requested." << LL_ENDL; + } + } + + if (mMode == LLRender::TRIANGLES) + { + if (mCount%3 != 0) + { + count -= (mCount % 3); + LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; + } + } + + if (mMode == LLRender::LINES) + { + if (mCount%2 != 0) + { + count -= (mCount % 2); + LL_WARNS() << "Incomplete line requested." << LL_ENDL; + } + } + + mCount = 0; if (mBuffer) { @@ -1649,8 +1649,8 @@ void LLRender::flush() hash.finalize(); } - - + + U64 vhash = hash.digest(); // check the VB cache before making a new vertex buffer @@ -1660,7 +1660,7 @@ void LLRender::flush() // Most of our usage of the "immediate mode" style draw calls is actually // sending the same geometry over and over again. // To leverage this, we maintain a running hash of the vertex stream being - // built up before a flush, and then check that hash against a VB + // built up before a flush, and then check that hash against a VB // cache just before creating a vertex buffer in VRAM std::unordered_map::iterator cache = sVBCache.find(vhash); @@ -1739,504 +1739,504 @@ void LLRender::flush() LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL; } - - mVerticesp[0] = mVerticesp[count]; - mTexcoordsp[0] = mTexcoordsp[count]; - mColorsp[0] = mColorsp[count]; - - mCount = 0; - } + + mVerticesp[0] = mVerticesp[count]; + mTexcoordsp[0] = mTexcoordsp[count]; + mColorsp[0] = mColorsp[count]; + + mCount = 0; + } } void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) -{ - //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] - if (mCount > 2048) - { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below - switch (mMode) - { - case LLRender::POINTS: flush(); break; - case LLRender::TRIANGLES: if (mCount%3==0) flush(); break; - case LLRender::QUADS: if(mCount%4 == 0) flush(); break; - case LLRender::LINES: if (mCount%2 == 0) flush(); break; - } - } - - if (mCount > 4094) - { - // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; - return; - } - - if (mUIOffset.empty()) - { - mVerticesp[mCount] = LLVector3(x,y,z); - } - else - { - LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount] = vert; - } - - if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) - { - mQuadCycle++; - if (mQuadCycle == 4) - { //copy two vertices so fourth quad element will add a triangle - mQuadCycle = 0; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-3]; - mColorsp[mCount] = mColorsp[mCount-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-3]; - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-2]; - mColorsp[mCount] = mColorsp[mCount-2]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-2]; - } - } - - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +{ + //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] + if (mCount > 2048) + { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below + switch (mMode) + { + case LLRender::POINTS: flush(); break; + case LLRender::TRIANGLES: if (mCount%3==0) flush(); break; + case LLRender::QUADS: if(mCount%4 == 0) flush(); break; + case LLRender::LINES: if (mCount%2 == 0) flush(); break; + } + } + + if (mCount > 4094) + { + // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; + return; + } + + if (mUIOffset.empty()) + { + mVerticesp[mCount] = LLVector3(x,y,z); + } + else + { + LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); + mVerticesp[mCount] = vert; + } + + if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) + { + mQuadCycle++; + if (mQuadCycle == 4) + { //copy two vertices so fourth quad element will add a triangle + mQuadCycle = 0; + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-3]; + mColorsp[mCount] = mColorsp[mCount-3]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-3]; + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-2]; + mColorsp[mCount] = mColorsp[mCount-2]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-2]; + } + } + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) { - if (mCount + vert_count > 4094) - { - // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; - return; - } - - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy two - mVerticesp[mCount++] = verts[i-3]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount++] = verts[i-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last one - mVerticesp[mCount++] = verts[i++]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else - { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - - mCount++; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - - if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen - mVerticesp[mCount] = mVerticesp[mCount-1]; + if (mCount + vert_count > 4094) + { + // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; + return; + } + + if (sGLCoreProfile && mMode == LLRender::QUADS) + { //quads are deprecated, convert to triangle list + S32 i = 0; + + while (i < vert_count) + { + //read first three + mVerticesp[mCount++] = verts[i++]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount++] = verts[i++]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount++] = verts[i++]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + //copy two + mVerticesp[mCount++] = verts[i-3]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount++] = verts[i-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + //copy last one + mVerticesp[mCount++] = verts[i++]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + } + } + else + { + for (S32 i = 0; i < vert_count; i++) + { + mVerticesp[mCount] = verts[i]; + + mCount++; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + } + } + + if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen + mVerticesp[mCount] = mVerticesp[mCount-1]; } void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count) { - if (mCount + vert_count > 4094) - { - // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; - return; - } - - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount++] = uvs[i-3]; - mColorsp[mCount] = mColorsp[mCount-1]; - - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount++] = uvs[i-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount++] = uvs[i++]; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - else - { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - - mCount++; - mColorsp[mCount] = mColorsp[mCount-1]; - } - } - - if (mCount > 0) - { - mVerticesp[mCount] = mVerticesp[mCount - 1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; - } + if (mCount + vert_count > 4094) + { + // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; + return; + } + + if (sGLCoreProfile && mMode == LLRender::QUADS) + { //quads are deprecated, convert to triangle list + S32 i = 0; + + while (i < vert_count) + { + //read first three + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount++] = uvs[i++]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount++] = uvs[i++]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount++] = uvs[i++]; + mColorsp[mCount] = mColorsp[mCount-1]; + + //copy last two + mVerticesp[mCount] = verts[i-3]; + mTexcoordsp[mCount++] = uvs[i-3]; + mColorsp[mCount] = mColorsp[mCount-1]; + + mVerticesp[mCount] = verts[i-1]; + mTexcoordsp[mCount++] = uvs[i-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + + //copy last one + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount++] = uvs[i++]; + mColorsp[mCount] = mColorsp[mCount-1]; + } + } + else + { + for (S32 i = 0; i < vert_count; i++) + { + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + + mCount++; + mColorsp[mCount] = mColorsp[mCount-1]; + } + } + + if (mCount > 0) + { + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + } } void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) { - if (mCount + vert_count > 4094) - { - // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; - return; - } - - - if (sGLCoreProfile && mMode == LLRender::QUADS) - { //quads are deprecated, convert to triangle list - S32 i = 0; - - while (i < vert_count) - { - //read first three - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - - //copy last two - mVerticesp[mCount] = verts[i-3]; - mTexcoordsp[mCount] = uvs[i-3]; - mColorsp[mCount++] = colors[i-3]; - - mVerticesp[mCount] = verts[i-1]; - mTexcoordsp[mCount] = uvs[i-1]; - mColorsp[mCount++] = colors[i-1]; - - //copy last one - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount++] = colors[i++]; - } - } - else - { - for (S32 i = 0; i < vert_count; i++) - { - mVerticesp[mCount] = verts[i]; - mTexcoordsp[mCount] = uvs[i]; - mColorsp[mCount] = colors[i]; - - mCount++; - } - } - - if (mCount > 0) - { - mVerticesp[mCount] = mVerticesp[mCount - 1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; - mColorsp[mCount] = mColorsp[mCount - 1]; - } + if (mCount + vert_count > 4094) + { + // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; + return; + } + + + if (sGLCoreProfile && mMode == LLRender::QUADS) + { //quads are deprecated, convert to triangle list + S32 i = 0; + + while (i < vert_count) + { + //read first three + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount++] = colors[i++]; + + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount++] = colors[i++]; + + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount++] = colors[i++]; + + //copy last two + mVerticesp[mCount] = verts[i-3]; + mTexcoordsp[mCount] = uvs[i-3]; + mColorsp[mCount++] = colors[i-3]; + + mVerticesp[mCount] = verts[i-1]; + mTexcoordsp[mCount] = uvs[i-1]; + mColorsp[mCount++] = colors[i-1]; + + //copy last one + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount++] = colors[i++]; + } + } + else + { + for (S32 i = 0; i < vert_count; i++) + { + mVerticesp[mCount] = verts[i]; + mTexcoordsp[mCount] = uvs[i]; + mColorsp[mCount] = colors[i]; + + mCount++; + } + } + + if (mCount > 0) + { + mVerticesp[mCount] = mVerticesp[mCount - 1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount - 1]; + mColorsp[mCount] = mColorsp[mCount - 1]; + } } void LLRender::vertex2i(const GLint& x, const GLint& y) { - vertex3f((GLfloat) x, (GLfloat) y, 0); + vertex3f((GLfloat) x, (GLfloat) y, 0); } void LLRender::vertex2f(const GLfloat& x, const GLfloat& y) -{ - vertex3f(x,y,0); +{ + vertex3f(x,y,0); } void LLRender::vertex2fv(const GLfloat* v) -{ - vertex3f(v[0], v[1], 0); +{ + vertex3f(v[0], v[1], 0); } void LLRender::vertex3fv(const GLfloat* v) { - vertex3f(v[0], v[1], v[2]); + vertex3f(v[0], v[1], v[2]); } void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y) -{ - mTexcoordsp[mCount] = LLVector2(x,y); +{ + mTexcoordsp[mCount] = LLVector2(x,y); } void LLRender::texCoord2i(const GLint& x, const GLint& y) -{ - texCoord2f((GLfloat) x, (GLfloat) y); +{ + texCoord2f((GLfloat) x, (GLfloat) y); } void LLRender::texCoord2fv(const GLfloat* tc) -{ - texCoord2f(tc[0], tc[1]); +{ + texCoord2f(tc[0], tc[1]); } void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a) { - if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR) - { - mColorsp[mCount] = LLColor4U(r,g,b,a); - } - else - { //not using shaders or shader reads color from a uniform - diffuseColor4ub(r,g,b,a); - } + if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR) + { + mColorsp[mCount] = LLColor4U(r,g,b,a); + } + else + { //not using shaders or shader reads color from a uniform + diffuseColor4ub(r,g,b,a); + } } void LLRender::color4ubv(const GLubyte* c) { - color4ub(c[0], c[1], c[2], c[3]); + color4ub(c[0], c[1], c[2], c[3]); } void LLRender::color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a) { - color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255), - (GLubyte) (llclamp(g, 0.f, 1.f)*255), - (GLubyte) (llclamp(b, 0.f, 1.f)*255), - (GLubyte) (llclamp(a, 0.f, 1.f)*255)); + color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255), + (GLubyte) (llclamp(g, 0.f, 1.f)*255), + (GLubyte) (llclamp(b, 0.f, 1.f)*255), + (GLubyte) (llclamp(a, 0.f, 1.f)*255)); } void LLRender::color4fv(const GLfloat* c) -{ - color4f(c[0],c[1],c[2],c[3]); +{ + color4f(c[0],c[1],c[2],c[3]); } void LLRender::color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b) -{ - color4f(r,g,b,1); +{ + color4f(r,g,b,1); } void LLRender::color3fv(const GLfloat* c) -{ - color4f(c[0],c[1],c[2],1); +{ + color4f(c[0],c[1],c[2],1); } void LLRender::diffuseColor3f(F32 r, F32 g, F32 b) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f); - } + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f); + } } void LLRender::diffuseColor3fv(const F32* c) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f); - } + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f); + } } void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a); - } + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a); + } } void LLRender::diffuseColor4fv(const F32* c) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c); - } + if (shader) + { + shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c); + } } void LLRender::diffuseColor4ubv(const U8* c) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); - } + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f); + } } void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader != NULL); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader != NULL); - if (shader) - { - shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); - } + if (shader) + { + shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); + } } void LLRender::debugTexUnits(void) { - LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; - std::string active_enabled = "false"; - for (U32 i = 0; i < mTexUnits.size(); i++) - { - if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) - { - if (i == mCurrTextureUnitIndex) active_enabled = "true"; - LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; - LL_INFOS("TextureUnit") << "Enabled As: " ; - switch (getTexUnit(i)->mCurrTexType) - { - case LLTexUnit::TT_TEXTURE: - LL_CONT << "Texture 2D"; - break; - case LLTexUnit::TT_RECT_TEXTURE: - LL_CONT << "Texture Rectangle"; - break; - case LLTexUnit::TT_CUBE_MAP: - LL_CONT << "Cube Map"; - break; - default: - LL_CONT << "ARGH!!! NONE!"; - break; - } - LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL; - } - } - LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL; + LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; + std::string active_enabled = "false"; + for (U32 i = 0; i < mTexUnits.size(); i++) + { + if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE) + { + if (i == mCurrTextureUnitIndex) active_enabled = "true"; + LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL; + LL_INFOS("TextureUnit") << "Enabled As: " ; + switch (getTexUnit(i)->mCurrTexType) + { + case LLTexUnit::TT_TEXTURE: + LL_CONT << "Texture 2D"; + break; + case LLTexUnit::TT_RECT_TEXTURE: + LL_CONT << "Texture Rectangle"; + break; + case LLTexUnit::TT_CUBE_MAP: + LL_CONT << "Cube Map"; + break; + default: + LL_CONT << "ARGH!!! NONE!"; + break; + } + LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL; + } + } + LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL; } glh::matrix4f copy_matrix(F32* src) { - glh::matrix4f ret; - ret.set_value(src); - return ret; + glh::matrix4f ret; + ret.set_value(src); + return ret; } glh::matrix4f get_current_modelview() { - return copy_matrix(gGLModelView); + return copy_matrix(gGLModelView); } glh::matrix4f get_current_projection() { - return copy_matrix(gGLProjection); + return copy_matrix(gGLProjection); } glh::matrix4f get_last_modelview() { - return copy_matrix(gGLLastModelView); + return copy_matrix(gGLLastModelView); } glh::matrix4f get_last_projection() { - return copy_matrix(gGLLastProjection); + return copy_matrix(gGLLastProjection); } void copy_matrix(const glh::matrix4f& src, F32* dst) { - for (U32 i = 0; i < 16; i++) - { - dst[i] = src.m[i]; - } + for (U32 i = 0; i < 16; i++) + { + dst[i] = src.m[i]; + } } void set_current_modelview(const glh::matrix4f& mat) { - copy_matrix(mat, gGLModelView); + copy_matrix(mat, gGLModelView); } void set_current_projection(glh::matrix4f& mat) { - copy_matrix(mat, gGLProjection); + copy_matrix(mat, gGLProjection); } glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar) { - glh::matrix4f ret( - 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left), - 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom), - 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear), - 0.f, 0.f, 0.f, 1.f); + glh::matrix4f ret( + 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left), + 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom), + 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear), + 0.f, 0.f, 0.f, 1.f); - return ret; + return ret; } glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) { - GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f); + GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f); - return glh::matrix4f(f/aspect, 0, 0, 0, - 0, f, 0, 0, - 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar), - 0, 0, -1.f, 0); + return glh::matrix4f(f/aspect, 0, 0, 0, + 0, f, 0, 0, + 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar), + 0, 0, -1.f, 0); } glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up) { - LLVector3 f = center-eye; - f.normVec(); - up.normVec(); - LLVector3 s = f % up; - LLVector3 u = s % f; - - return glh::matrix4f(s[0], s[1], s[2], 0, - u[0], u[1], u[2], 0, - -f[0], -f[1], -f[2], 0, - 0, 0, 0, 1); - + LLVector3 f = center-eye; + f.normVec(); + up.normVec(); + LLVector3 s = f % up; + LLVector3 u = s % f; + + return glh::matrix4f(s[0], s[1], s[2], 0, + u[0], u[1], u[2], 0, + -f[0], -f[1], -f[2], 0, + 0, 0, 0, 1); + } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index da401572d1..340276a752 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -1,25 +1,25 @@ -/** +/** * @file llrendertarget.h * @brief Off screen render target abstraction. Loose wrapper for GL_EXT_framebuffer_objects. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -37,56 +37,56 @@ SAMPLE USAGE: - LLRenderTarget target; + LLRenderTarget target; - ... + ... - //allocate a 256x256 RGBA render target with depth buffer - target.allocate(256,256,GL_RGBA,TRUE); + //allocate a 256x256 RGBA render target with depth buffer + target.allocate(256,256,GL_RGBA,TRUE); - //render to contents of offscreen buffer - target.bindTarget(); - target.clear(); - ... ... - target.flush(); + //render to contents of offscreen buffer + target.bindTarget(); + target.clear(); + ... ... + target.flush(); - ... + ... - //use target as a texture - gGL.getTexUnit(INDEX)->bind(&target); - ... ... + //use target as a texture + gGL.getTexUnit(INDEX)->bind(&target); + ... ... */ class LLRenderTarget { public: - //whether or not to use FBO implementation - static bool sUseFBO; - static U32 sBytesAllocated; - static U32 sCurFBO; - static U32 sCurResX; - static U32 sCurResY; + //whether or not to use FBO implementation + static bool sUseFBO; + static U32 sBytesAllocated; + static U32 sCurFBO; + static U32 sCurResX; + static U32 sCurResY; - LLRenderTarget(); - ~LLRenderTarget(); + LLRenderTarget(); + ~LLRenderTarget(); - //allocate resources for rendering - //must be called before use - //multiple calls will release previously allocated resources + //allocate resources for rendering + //must be called before use + //multiple calls will release previously allocated resources // resX - width // resY - height // color_fmt - GL color format (e.g. GL_RGB) // depth - if true, allocate a depth buffer // usage - deprecated, should always be TT_TEXTURE - bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE); - //resize existing attachments to use new resolution and color format - // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined - // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded - // DO use for render targets that resize often and aren't likely to ruin someone's day if they break - void resize(U32 resx, U32 resy); + //resize existing attachments to use new resolution and color format + // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined + // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded + // DO use for render targets that resize often and aren't likely to ruin someone's day if they break + void resize(U32 resx, U32 resy); //point this render target at a particular LLImageGL // Intended usage: @@ -96,98 +96,98 @@ public: // < issue GL calls> // target.flush(); // target.releaseColorAttachment(); - // + // // attachment -- LLImageGL to render into // use_name -- optional texture name to target instead of attachment->getTexName() // NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with - // addColorAttachment, allocateDepth, resize, etc. + // addColorAttachment, allocateDepth, resize, etc. void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0); // detach from current color attachment void releaseColorAttachment(); - //add color buffer attachment - //limit of 4 color attachments per render target - bool addColorAttachment(U32 color_fmt); + //add color buffer attachment + //limit of 4 color attachments per render target + bool addColorAttachment(U32 color_fmt); - //allocate a depth texture - bool allocateDepth(); + //allocate a depth texture + bool allocateDepth(); - //share depth buffer with provided render target - void shareDepthBuffer(LLRenderTarget& target); + //share depth buffer with provided render target + void shareDepthBuffer(LLRenderTarget& target); - //free any allocated resources - //safe to call redundantly + //free any allocated resources + //safe to call redundantly // asserts that this target is not currently bound or present in the RT stack - void release(); + void release(); - //bind target for rendering - //applies appropriate viewport - // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget + //bind target for rendering + //applies appropriate viewport + // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget // and restores previous binding on flush() (maintains a stack of Render Targets) // Asserts that this target is not currently bound in the stack - void bindTarget(); + void bindTarget(); - //clear render targer, clears depth buffer if present, - //uses scissor rect if in copy-to-texture mode + //clear render targer, clears depth buffer if present, + //uses scissor rect if in copy-to-texture mode // asserts that this target is currently bound - void clear(U32 mask = 0xFFFFFFFF); - - //get applied viewport - void getViewport(S32* viewport); + void clear(U32 mask = 0xFFFFFFFF); + + //get applied viewport + void getViewport(S32* viewport); - //get X resolution - U32 getWidth() const { return mResX; } + //get X resolution + U32 getWidth() const { return mResX; } - //get Y resolution - U32 getHeight() const { return mResY; } + //get Y resolution + U32 getHeight() const { return mResY; } - LLTexUnit::eTextureType getUsage(void) const { return mUsage; } + LLTexUnit::eTextureType getUsage(void) const { return mUsage; } - U32 getTexture(U32 attachment = 0) const; - U32 getNumTextures() const; + U32 getTexture(U32 attachment = 0) const; + U32 getNumTextures() const; - U32 getDepth(void) const { return mDepth; } + U32 getDepth(void) const { return mDepth; } - void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR); + void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR); - //flush rendering operations - //must be called when rendering is complete - //should be used 1:1 with bindTarget - // call bindTarget once, do all your rendering, call flush once + //flush rendering operations + //must be called when rendering is complete + //should be used 1:1 with bindTarget + // call bindTarget once, do all your rendering, call flush once // If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack) // asserts that this target is currently bound - void flush(); + void flush(); - //Returns TRUE if target is ready to be rendered into. - //That is, if the target has been allocated with at least - //one renderable attachment (i.e. color buffer, depth buffer). - bool isComplete() const; + //Returns TRUE if target is ready to be rendered into. + //That is, if the target has been allocated with at least + //one renderable attachment (i.e. color buffer, depth buffer). + bool isComplete() const; // Returns true if this RenderTarget is bound somewhere in the stack bool isBoundInStack() const; - static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } - // *HACK - void swapFBORefs(LLRenderTarget& other); + // *HACK + void swapFBORefs(LLRenderTarget& other); protected: - U32 mResX; - U32 mResY; - std::vector mTex; - std::vector mInternalFormat; - U32 mFBO; + U32 mResX; + U32 mResY; + std::vector mTex; + std::vector mInternalFormat; + U32 mFBO; LLRenderTarget* mPreviousRT = nullptr; U32 mDepth; bool mUseDepth; - LLTexUnit::eTextureMipGeneration mGenerateMipMaps; - U32 mMipLevels; + LLTexUnit::eTextureMipGeneration mGenerateMipMaps; + U32 mMipLevels; + + LLTexUnit::eTextureType mUsage; - LLTexUnit::eTextureType mUsage; - - static LLRenderTarget* sBoundTarget; + static LLRenderTarget* sBoundTarget; }; #endif diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 636e13719a..0f3716bc18 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llshadermgr.cpp * @brief Shader manager implementation. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -58,90 +58,90 @@ LLShaderMgr::~LLShaderMgr() // static LLShaderMgr * LLShaderMgr::instance() { - if(NULL == sInstance) - { - LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL; - } + if(NULL == sInstance) + { + LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL; + } - return sInstance; + return sInstance; } BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { - llassert_always(shader != NULL); - LLShaderFeatures *features = & shader->mFeatures; - - if (features->attachNothing) - { - return TRUE; - } - ////////////////////////////////////// - // Attach Vertex Shader Features First - ////////////////////////////////////// - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->calculatesAtmospherics) - { - if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl")) - { - return FALSE; - } - } - - if (features->calculatesLighting || features->calculatesAtmospherics) - { - if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl")) - { - return FALSE; - } - } - - if (features->calculatesLighting) - { - if (features->isSpecular) - { + llassert_always(shader != NULL); + LLShaderFeatures *features = & shader->mFeatures; + + if (features->attachNothing) + { + return TRUE; + } + ////////////////////////////////////// + // Attach Vertex Shader Features First + ////////////////////////////////////// + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->calculatesAtmospherics) + { + if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl")) + { + return FALSE; + } + } + + if (features->calculatesLighting || features->calculatesAtmospherics) + { + if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl")) + { + return FALSE; + } + } + + if (features->calculatesLighting) + { + if (features->isSpecular) + { if (!shader->attachVertexObject("lighting/lightFuncSpecularV.glsl")) - { - return FALSE; - } - - if (!features->isAlphaLighting) - { + { + return FALSE; + } + + if (!features->isAlphaLighting) + { if (!shader->attachVertexObject("lighting/sumLightsSpecularV.glsl")) - { - return FALSE; - } - } - + { + return FALSE; + } + } + if (!shader->attachVertexObject("lighting/lightSpecularV.glsl")) - { - return FALSE; - } - } - else - { + { + return FALSE; + } + } + else + { if (!shader->attachVertexObject("lighting/lightFuncV.glsl")) - { - return FALSE; - } - - if (!features->isAlphaLighting) - { + { + return FALSE; + } + + if (!features->isAlphaLighting) + { if (!shader->attachVertexObject("lighting/sumLightsV.glsl")) - { - return FALSE; - } - } - + { + return FALSE; + } + } + if (!shader->attachVertexObject("lighting/lightV.glsl")) - { - return FALSE; - } - } - } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->calculatesAtmospherics) + { + return FALSE; + } + } + } + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->calculatesAtmospherics) { if (!shader->attachVertexObject("environment/srgbF.glsl")) // NOTE -- "F" suffix is superfluous here, there is nothing fragment specific in srgbF { @@ -153,39 +153,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } if (!shader->attachVertexObject("windlight/atmosphericsV.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - if (features->hasSkinning) - { + if (features->hasSkinning) + { if (!shader->attachVertexObject("avatar/avatarSkinV.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - if (features->hasObjectSkinning) - { + if (features->hasObjectSkinning) + { shader->mRiggedVariant = shader; if (!shader->attachVertexObject("avatar/objectSkinV.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } if (!shader->attachVertexObject("deferred/textureUtilV.glsl")) { return FALSE; } - - /////////////////////////////////////// - // Attach Fragment Shader Features Next - /////////////////////////////////////// + + /////////////////////////////////////// + // Attach Fragment Shader Features Next + /////////////////////////////////////// // NOTE order of shader object attaching is VERY IMPORTANT!!! - + if (!shader->attachFragmentObject("deferred/globalF.glsl")) { return FALSE; @@ -199,46 +199,46 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } - if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred) - { - if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl")) - { - return FALSE; - } - } + if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred) + { + if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl")) + { + return FALSE; + } + } if (features->calculatesLighting || features->calculatesAtmospherics) - { + { if (!shader->attachFragmentObject("windlight/atmosphericsHelpersF.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } // we want this BEFORE shadows and AO because those facilities use pos/norm access if (features->isDeferred || features->hasReflectionProbes) - { + { if (!shader->attachFragmentObject("deferred/deferredUtil.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - if (features->hasScreenSpaceReflections || features->hasReflectionProbes) - { + if (features->hasScreenSpaceReflections || features->hasReflectionProbes) + { if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl")) { return FALSE; } - } + } if (features->hasShadows) - { + { if (!shader->attachFragmentObject("deferred/shadowUtil.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } if (features->hasReflectionProbes) { @@ -249,33 +249,33 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } if (features->hasAmbientOcclusion) - { + { if (!shader->attachFragmentObject("deferred/aoUtil.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - if (features->hasGamma || features->isDeferred) - { + if (features->hasGamma || features->isDeferred) + { if (!shader->attachFragmentObject("windlight/gammaF.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - if (features->hasAtmospherics || features->isDeferred) + if (features->hasAtmospherics || features->isDeferred) { if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) { return FALSE; } if (!shader->attachFragmentObject("windlight/atmosphericsF.glsl")) - { - return FALSE; - } - } - + { + return FALSE; + } + } + if (features->isPBRTerrain) { if (!shader->attachFragmentObject("deferred/pbrterrainUtilF.glsl")) @@ -283,71 +283,71 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } - - // NOTE order of shader object attaching is VERY IMPORTANT!!! - if (features->hasAtmospherics) - { + + // NOTE order of shader object attaching is VERY IMPORTANT!!! + if (features->hasAtmospherics) + { if (!shader->attachFragmentObject("environment/waterFogF.glsl")) - { - return FALSE; - } - } - - if (features->hasLighting) - { - if (features->disableTextureIndex) - { - if (features->hasAlphaMask) - { + { + return FALSE; + } + } + + if (features->hasLighting) + { + if (features->disableTextureIndex) + { + if (features->hasAlphaMask) + { if (!shader->attachFragmentObject("lighting/lightAlphaMaskNonIndexedF.glsl")) - { - return FALSE; - } - } - else - { + { + return FALSE; + } + } + else + { if (!shader->attachFragmentObject("lighting/lightNonIndexedF.glsl")) - { - return FALSE; - } - } - } - else - { - if (features->hasAlphaMask) - { + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { if (!shader->attachFragmentObject("lighting/lightAlphaMaskF.glsl")) - { - return FALSE; - } - } - else - { + { + return FALSE; + } + } + else + { if (!shader->attachFragmentObject("lighting/lightF.glsl")) - { - return FALSE; - } - } - shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels, 1); - } - } - - if (features->mIndexedTextureChannels <= 1) - { - if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl")) - { - return FALSE; - } - } - else - { + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels, 1); + } + } + + if (features->mIndexedTextureChannels <= 1) + { + if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl")) + { + return FALSE; + } + } + else + { if (!shader->attachVertexObject("objects/indexedTextureV.glsl")) - { - return FALSE; - } - } + { + return FALSE; + } + } - return TRUE; + return TRUE; } //============================================================================ @@ -355,20 +355,20 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) static std::string get_shader_log(GLuint ret) { - std::string res; - - //get log length - GLint length; + std::string res; + + //get log length + GLint length; glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &length); - if (length > 0) - { - //the log could be any size, so allocate appropriately - GLchar* log = new GLchar[length]; + if (length > 0) + { + //the log could be any size, so allocate appropriately + GLchar* log = new GLchar[length]; glGetShaderInfoLog(ret, length, &length, log); - res = std::string((char *)log); - delete[] log; - } - return res; + res = std::string((char *)log); + delete[] log; + } + return res; } static std::string get_program_log(GLuint ret) @@ -376,7 +376,7 @@ static std::string get_program_log(GLuint ret) LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; std::string res; - //get log length + //get log length GLint length; glGetProgramiv(ret, GL_INFO_LOG_LENGTH, &length); if (length > 0) @@ -408,16 +408,16 @@ static std::string get_object_log(GLuint ret) //dump shader source for debugging void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text) { - char num_str[16]; // U32 = max 10 digits + char num_str[16]; // U32 = max 10 digits - LL_SHADER_LOADING_WARNS() << "\n"; + LL_SHADER_LOADING_WARNS() << "\n"; - for (U32 i = 0; i < shader_code_count; i++) - { - snprintf(num_str, sizeof(num_str), "%4d: ", i+1); - std::string line_number(num_str); - LL_CONT << line_number << shader_code_text[i]; - } + for (U32 i = 0; i < shader_code_count; i++) + { + snprintf(num_str, sizeof(num_str), "%4d: ", i+1); + std::string line_number(num_str); + LL_CONT << line_number << shader_code_text[i]; + } LL_CONT << LL_ENDL; } @@ -431,11 +431,11 @@ void LLShaderMgr::dumpObjectLog(GLuint ret, BOOL warns, const std::string& filen fname = "unknown shader file"; } - if (log.length() > 0) - { + if (log.length() > 0) + { LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << LL_ENDL; LL_SHADER_LOADING_WARNS() << "\n" << log << LL_ENDL; - } + } } GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines, S32 texture_index_channels) @@ -449,25 +449,25 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } #endif - GLenum error = GL_NO_ERROR; + GLenum error = GL_NO_ERROR; + + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << " for file: " << filename << LL_ENDL; + } - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << " for file: " << filename << LL_ENDL; - } - - if (filename.empty()) - { - return 0; - } + if (filename.empty()) + { + return 0; + } - //read in from file - LLFILE* file = NULL; + //read in from file + LLFILE* file = NULL; - S32 try_gpu_class = shader_level; - S32 gpu_class; + S32 try_gpu_class = shader_level; + S32 gpu_class; std::string open_file_name; @@ -492,7 +492,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev { //find the most relevant file for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--) - { //search from the current gpu class down to class 1 to find the most relevant shader + { //search from the current gpu class down to class 1 to find the most relevant shader std::stringstream fname; fname << getShaderDirPrefix(); fname << gpu_class << "/" << filename; @@ -513,7 +513,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev */ LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL; - file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */ + file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */ if (file) { LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL; @@ -521,31 +521,31 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } } } - - if (file == NULL) - { - LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL; - return 0; - } - //we can't have any lines longer than 1024 characters - //or any shaders longer than 4096 lines... deal - DaveP + if (file == NULL) + { + LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL; + return 0; + } + + //we can't have any lines longer than 1024 characters + //or any shaders longer than 4096 lines... deal - DaveP GLchar buff[1024]; GLchar *extra_code_text[1024]; GLchar *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL }; GLuint extra_code_count = 0, shader_code_count = 0; BOOST_STATIC_ASSERT(LL_ARRAY_SIZE(extra_code_text) < LL_ARRAY_SIZE(shader_code_text)); - - - S32 major_version = gGLManager.mGLSLVersionMajor; - S32 minor_version = gGLManager.mGLSLVersionMinor; - - if (major_version == 1 && minor_version < 30) - { + + + S32 major_version = gGLManager.mGLSLVersionMajor; + S32 minor_version = gGLManager.mGLSLVersionMinor; + + if (major_version == 1 && minor_version < 30) + { llassert(false); // GL 3.1 or later required - } - else - { + } + else + { if (major_version >= 4) { //set version to 400 or 420 @@ -561,24 +561,24 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev else if (major_version == 3) { if (minor_version < 10) - { - shader_code_text[shader_code_count++] = strdup("#version 300\n"); - } - else if (minor_version <= 19) - { - shader_code_text[shader_code_count++] = strdup("#version 310\n"); - } - else if (minor_version <= 29) - { - shader_code_text[shader_code_count++] = strdup("#version 320\n"); - } + { + shader_code_text[shader_code_count++] = strdup("#version 300\n"); + } + else if (minor_version <= 19) + { + shader_code_text[shader_code_count++] = strdup("#version 310\n"); + } + else if (minor_version <= 29) + { + shader_code_text[shader_code_count++] = strdup("#version 320\n"); + } else { shader_code_text[shader_code_count++] = strdup("#version 330\n"); } } - else - { + else + { if (type == GL_GEOMETRY_SHADER) { //set version to 1.50 @@ -595,10 +595,10 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("precision mediump int;\n"); extra_code_text[extra_code_count++] = strdup("precision highp float;\n"); } - } + } - extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); - } + extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n"); + } if (sMirrorsEnabled) { @@ -613,125 +613,125 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_HDRI 1.0\n"); // bit 2 extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n"); - if (defines) - { - for (auto iter = defines->begin(); iter != defines->end(); ++iter) - { - std::string define = "#define " + iter->first + " " + iter->second + "\n"; - extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str()); - } - } - - if( gGLManager.mIsAMD ) - { - extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" ); - } - - if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER) - { - //use specified number of texture channels for indexed texture rendering - - /* prepend shader code that looks like this: - - uniform sampler2D tex0; - uniform sampler2D tex1; - uniform sampler2D tex2; - . - . - . - uniform sampler2D texN; - - flat in int vary_texture_index; - - vec4 ret = vec4(1,0,1,1); - - vec4 diffuseLookup(vec2 texcoord) - { - switch (vary_texture_index) - { - case 0: ret = texture(tex0, texcoord); break; - case 1: ret = texture(tex1, texcoord); break; - case 2: ret = texture(tex2, texcoord); break; - . - . - . - case N: return texture(texN, texcoord); break; - } - - return ret; - } - */ - - extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n"); - - //uniform declartion - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string decl = llformat("uniform sampler2D tex%d;\n", i); - extra_code_text[extra_code_count++] = strdup(decl.c_str()); - } - - if (texture_index_channels > 1) - { - extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n"); - } - - extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); - extra_code_text[extra_code_count++] = strdup("{\n"); - - - if (texture_index_channels == 1) - { //don't use flow control, that's silly - extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - else if (major_version > 1 || minor_version >= 30) - { //switches are supported in GLSL 1.30 and later - if (gGLManager.mIsNVIDIA) - { //switches are unreliable on some NVIDIA drivers - for (U32 i = 0; i < texture_index_channels; ++i) - { - std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); - extra_code_text[extra_code_count++] = strdup(if_string.c_str()); - } - extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - else - { - extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n"); - extra_code_text[extra_code_count++] = strdup("\t{\n"); - - //switch body - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i); - extra_code_text[extra_code_count++] = strdup(case_str.c_str()); - } - - extra_code_text[extra_code_count++] = strdup("\t}\n"); - extra_code_text[extra_code_count++] = strdup("\treturn ret;\n"); - extra_code_text[extra_code_count++] = strdup("}\n"); - } - } - else - { //should never get here. Indexed texture rendering requires GLSL 1.30 or later - // (for passing integers between vertex and fragment shaders) - LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL; - } - } - - //copy file into memory - enum { - flag_write_to_out_of_extra_block_area = 0x01 - , flag_extra_block_marker_was_found = 0x02 - }; - - unsigned char flags = flag_write_to_out_of_extra_block_area; - - GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0; - + if (defines) + { + for (auto iter = defines->begin(); iter != defines->end(); ++iter) + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str()); + } + } + + if( gGLManager.mIsAMD ) + { + extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" ); + } + + if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER) + { + //use specified number of texture channels for indexed texture rendering + + /* prepend shader code that looks like this: + + uniform sampler2D tex0; + uniform sampler2D tex1; + uniform sampler2D tex2; + . + . + . + uniform sampler2D texN; + + flat in int vary_texture_index; + + vec4 ret = vec4(1,0,1,1); + + vec4 diffuseLookup(vec2 texcoord) + { + switch (vary_texture_index) + { + case 0: ret = texture(tex0, texcoord); break; + case 1: ret = texture(tex1, texcoord); break; + case 2: ret = texture(tex2, texcoord); break; + . + . + . + case N: return texture(texN, texcoord); break; + } + + return ret; + } + */ + + extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n"); + + //uniform declartion + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string decl = llformat("uniform sampler2D tex%d;\n", i); + extra_code_text[extra_code_count++] = strdup(decl.c_str()); + } + + if (texture_index_channels > 1) + { + extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n"); + } + + extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); + extra_code_text[extra_code_count++] = strdup("{\n"); + + + if (texture_index_channels == 1) + { //don't use flow control, that's silly + extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + else if (major_version > 1 || minor_version >= 30) + { //switches are supported in GLSL 1.30 and later + if (gGLManager.mIsNVIDIA) + { //switches are unreliable on some NVIDIA drivers + for (U32 i = 0; i < texture_index_channels; ++i) + { + std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + extra_code_text[extra_code_count++] = strdup(if_string.c_str()); + } + extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + else + { + extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); + extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n"); + extra_code_text[extra_code_count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i); + extra_code_text[extra_code_count++] = strdup(case_str.c_str()); + } + + extra_code_text[extra_code_count++] = strdup("\t}\n"); + extra_code_text[extra_code_count++] = strdup("\treturn ret;\n"); + extra_code_text[extra_code_count++] = strdup("}\n"); + } + } + else + { //should never get here. Indexed texture rendering requires GLSL 1.30 or later + // (for passing integers between vertex and fragment shaders) + LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL; + } + } + + //copy file into memory + enum { + flag_write_to_out_of_extra_block_area = 0x01 + , flag_extra_block_marker_was_found = 0x02 + }; + + unsigned char flags = flag_write_to_out_of_extra_block_area; + + GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0; + #define TOUCH_SHADERS 0 #if TOUCH_SHADERS @@ -739,13 +739,13 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev bool touched = false; #endif - while(NULL != fgets((char *)buff, 1024, file) - && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) - { - file_lines_count++; + while(NULL != fgets((char *)buff, 1024, file) + && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text))) + { + file_lines_count++; + + bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]"); - bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]"); - #if TOUCH_SHADERS if (NULL != strstr((const char*)buff, marker)) { @@ -753,67 +753,67 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } #endif - if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags)) - { - if(!(flag_write_to_out_of_extra_block_area & flags)) - { - //shift - for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code; - from < shader_code_count; ++to, ++from) - { - shader_code_text[to] = shader_code_text[from]; - } - - shader_code_count -= extra_code_count; - } - - //copy extra code - for(GLuint n = 0; n < extra_code_count - && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n) - { - shader_code_text[shader_code_count++] = extra_code_text[n]; - } - - extra_code_count = 0; - - flags &= ~flag_write_to_out_of_extra_block_area; - flags |= flag_extra_block_marker_was_found; - } + if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags)) + { + if(!(flag_write_to_out_of_extra_block_area & flags)) + { + //shift + for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code; + from < shader_code_count; ++to, ++from) + { + shader_code_text[to] = shader_code_text[from]; + } + + shader_code_count -= extra_code_count; + } + + //copy extra code + for(GLuint n = 0; n < extra_code_count + && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n) + { + shader_code_text[shader_code_count++] = extra_code_text[n]; + } + + extra_code_count = 0; + + flags &= ~flag_write_to_out_of_extra_block_area; + flags |= flag_extra_block_marker_was_found; + } else { shader_code_text[shader_code_count] = (GLchar *)strdup((char *)buff); - + if(flag_write_to_out_of_extra_block_area & flags) { shader_code_text[extra_code_count + start_shader_code + out_of_extra_block_counter] = shader_code_text[shader_code_count]; out_of_extra_block_counter++; - + if(out_of_extra_block_counter == extra_code_count) { shader_code_count += extra_code_count; flags &= ~flag_write_to_out_of_extra_block_area; } } - + ++shader_code_count; - } - } //while - - if(!(flag_extra_block_marker_was_found & flags)) - { - for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n) - { - shader_code_text[n] = extra_code_text[n - start_shader_code]; - } - - if (file_lines_count < extra_code_count) - { - shader_code_count += extra_code_count; - } - - extra_code_count = 0; - } + } + } //while + + if(!(flag_extra_block_marker_was_found & flags)) + { + for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n) + { + shader_code_text[n] = extra_code_text[n - start_shader_code]; + } + + if (file_lines_count < extra_code_count) + { + shader_code_count += extra_code_count; + } + + extra_code_count = 0; + } #if TOUCH_SHADERS if (!touched) @@ -822,106 +822,106 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } #endif - fclose(file); + fclose(file); - //create shader object + //create shader object GLuint ret = glCreateShader(type); - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL; - if (ret) - { - glDeleteShader(ret); //no longer need handle - ret = 0; - } - } - - //load source - if (ret) - { - glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL); - - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL; - glDeleteShader(ret); //no longer need handle - ret = 0; - } - } - - //compile source - if (ret) - { - glCompileShader(ret); - - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL; - glDeleteShader(ret); //no longer need handle - ret = 0; - } - } - - if (error == GL_NO_ERROR) - { - //check for errors - GLint success = GL_TRUE; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL; + if (ret) + { + glDeleteShader(ret); //no longer need handle + ret = 0; + } + } + + //load source + if (ret) + { + glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL); + + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL; + glDeleteShader(ret); //no longer need handle + ret = 0; + } + } + + //compile source + if (ret) + { + glCompileShader(ret); + + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL; + glDeleteShader(ret); //no longer need handle + ret = 0; + } + } + + if (error == GL_NO_ERROR) + { + //check for errors + GLint success = GL_TRUE; glGetShaderiv(ret, GL_COMPILE_STATUS, &success); - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) - { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL; - dumpObjectLog(ret, TRUE, open_file_name); - dumpShaderSource(shader_code_count, shader_code_text); - glDeleteShader(ret); //no longer need handle - ret = 0; - } - } - else - { - ret = 0; - } - stop_glerror(); - - //free memory - for (GLuint i = 0; i < shader_code_count; i++) - { - free(shader_code_text[i]); - } - - //successfully loaded, save results - if (ret) - { - // Add shader file to map + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL; + dumpObjectLog(ret, TRUE, open_file_name); + dumpShaderSource(shader_code_count, shader_code_text); + glDeleteShader(ret); //no longer need handle + ret = 0; + } + } + else + { + ret = 0; + } + stop_glerror(); + + //free memory + for (GLuint i = 0; i < shader_code_count; i++) + { + free(shader_code_text[i]); + } + + //successfully loaded, save results + if (ret) + { + // Add shader file to map if (type == GL_VERTEX_SHADER) { mVertexShaderObjects[filename] = ret; } else if (type == GL_FRAGMENT_SHADER) { mFragmentShaderObjects[filename] = ret; } - shader_level = try_gpu_class; - } - else - { - if (shader_level > 1) - { - shader_level--; - return loadShaderFile(filename, shader_level, type, defines, texture_index_channels); - } - LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; - } - return ret; + shader_level = try_gpu_class; + } + else + { + if (shader_level > 1) + { + shader_level--; + return loadShaderFile(filename, shader_level, type, defines, texture_index_channels); + } + LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; + } + return ret; } BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors) { - //check for errors + //check for errors { LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glLinkProgram"); glLinkProgram(obj); @@ -941,238 +941,238 @@ BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors) } } - std::string log = get_program_log(obj); - LLStringUtil::toLower(log); - if (log.find("software") != std::string::npos) - { - LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; - success = GL_FALSE; - suppress_errors = FALSE; - } - return success; + std::string log = get_program_log(obj); + LLStringUtil::toLower(log); + if (log.find("software") != std::string::npos) + { + LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL; + success = GL_FALSE; + suppress_errors = FALSE; + } + return success; } BOOL LLShaderMgr::validateProgramObject(GLuint obj) { - //check program validity against current GL - glValidateProgram(obj); - GLint success = GL_TRUE; + //check program validity against current GL + glValidateProgram(obj); + GLint success = GL_TRUE; glGetProgramiv(obj, GL_LINK_STATUS, &success); - if (success == GL_FALSE) - { - LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL; - dumpObjectLog(obj); - } - else - { - dumpObjectLog(obj, FALSE); - } - - return success; + if (success == GL_FALSE) + { + LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL; + dumpObjectLog(obj); + } + else + { + dumpObjectLog(obj, FALSE); + } + + return success; } void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version) { - LL_INFOS() << "Initializing shader cache" << LL_ENDL; - - mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled; - - if(!mShaderCacheEnabled || mShaderCacheInitialized) - return; - - mShaderCacheInitialized = true; - - mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); - LLFile::mkdir(mShaderCacheDir); - - { - std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); - if (gDirUtilp->fileExists(meta_out_path)) - { - LL_INFOS() << "Loading shader cache metadata" << LL_ENDL; - - llifstream instream(meta_out_path); - LLSD in_data; - LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); - instream.close(); - - if (old_cache_version == current_cache_version) - { - for (const auto& data_pair : llsd::inMap(in_data)) - { - ProgramBinaryData binary_info = ProgramBinaryData(); - binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger(); - binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger(); - binary_info.mLastUsedTime = data_pair.second["last_used"].asReal(); - mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info); - } - } - else - { - LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL; - clearShaderCache(); - } - } - } + LL_INFOS() << "Initializing shader cache" << LL_ENDL; + + mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled; + + if(!mShaderCacheEnabled || mShaderCacheInitialized) + return; + + mShaderCacheInitialized = true; + + mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); + LLFile::mkdir(mShaderCacheDir); + + { + std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); + if (gDirUtilp->fileExists(meta_out_path)) + { + LL_INFOS() << "Loading shader cache metadata" << LL_ENDL; + + llifstream instream(meta_out_path); + LLSD in_data; + LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED); + instream.close(); + + if (old_cache_version == current_cache_version) + { + for (const auto& data_pair : llsd::inMap(in_data)) + { + ProgramBinaryData binary_info = ProgramBinaryData(); + binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger(); + binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger(); + binary_info.mLastUsedTime = data_pair.second["last_used"].asReal(); + mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info); + } + } + else + { + LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL; + clearShaderCache(); + } + } + } } void LLShaderMgr::clearShaderCache() { - std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); - LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL; - const std::string mask = "*"; - gDirUtilp->deleteFilesInDir(shader_cache, mask); - mShaderBinaryCache.clear(); + std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache"); + LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL; + const std::string mask = "*"; + gDirUtilp->deleteFilesInDir(shader_cache, mask); + mShaderBinaryCache.clear(); } void LLShaderMgr::persistShaderCacheMetadata() { - if(!mShaderCacheEnabled) return; - - LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL; - - LLSD out = LLSD::emptyMap(); - - static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days - const F32 current_time = LLTimer::getTotalSeconds(); - for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();) - { - const ProgramBinaryData& shader_metadata = it->second; - if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time) - { - std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin"); - LLFile::remove(shader_path); - it = mShaderBinaryCache.erase(it); - } - else - { - LLSD data = LLSD::emptyMap(); - data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat); - data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength); - data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime); - out[it->first.asString()] = data; - ++it; - } - } - - std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); - llofstream outstream(meta_out_path); - LLSDSerialize::toNotation(out, outstream); - outstream.close(); + if(!mShaderCacheEnabled) return; + + LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL; + + LLSD out = LLSD::emptyMap(); + + static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days + const F32 current_time = LLTimer::getTotalSeconds(); + for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();) + { + const ProgramBinaryData& shader_metadata = it->second; + if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time) + { + std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin"); + LLFile::remove(shader_path); + it = mShaderBinaryCache.erase(it); + } + else + { + LLSD data = LLSD::emptyMap(); + data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat); + data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength); + data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime); + out[it->first.asString()] = data; + ++it; + } + } + + std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd"); + llofstream outstream(meta_out_path); + LLSDSerialize::toNotation(out, outstream); + outstream.close(); } bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader) { - if (!mShaderCacheEnabled) return false; - - glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - - auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash); - if (binary_iter != mShaderBinaryCache.end()) - { - std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); - auto& shader_info = binary_iter->second; - if (shader_info.mBinaryLength > 0) - { - std::vector in_data; - in_data.resize(shader_info.mBinaryLength); - - LLUniqueFile filep = LLFile::fopen(in_path, "rb"); - if (filep) - { - size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep); - filep.close(); - - if (result == in_data.size()) - { - GLenum error = glGetError(); // Clear current error - glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength); - - error = glGetError(); - GLint success = GL_TRUE; - glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success); - if (error == GL_NO_ERROR && success == GL_TRUE) - { - binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds(); - LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL; - return true; - } - } - } - } - //an error occured, normally we would print log but in this case it means the shader needs recompiling. - LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL; - LLFile::remove(in_path); - mShaderBinaryCache.erase(binary_iter); - } - return false; + if (!mShaderCacheEnabled) return false; + + glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + + auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash); + if (binary_iter != mShaderBinaryCache.end()) + { + std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); + auto& shader_info = binary_iter->second; + if (shader_info.mBinaryLength > 0) + { + std::vector in_data; + in_data.resize(shader_info.mBinaryLength); + + LLUniqueFile filep = LLFile::fopen(in_path, "rb"); + if (filep) + { + size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep); + filep.close(); + + if (result == in_data.size()) + { + GLenum error = glGetError(); // Clear current error + glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength); + + error = glGetError(); + GLint success = GL_TRUE; + glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success); + if (error == GL_NO_ERROR && success == GL_TRUE) + { + binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds(); + LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL; + return true; + } + } + } + } + //an error occured, normally we would print log but in this case it means the shader needs recompiling. + LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL; + LLFile::remove(in_path); + mShaderBinaryCache.erase(binary_iter); + } + return false; } bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader) { - if (!mShaderCacheEnabled) return true; - - ProgramBinaryData binary_info = ProgramBinaryData(); - glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength); - if (binary_info.mBinaryLength > 0) - { - std::vector program_binary; - program_binary.resize(binary_info.mBinaryLength); - - GLenum error = glGetError(); // Clear current error - glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data()); - error = glGetError(); - if (error == GL_NO_ERROR) - { - std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); - LLUniqueFile outfile = LLFile::fopen(out_path, "wb"); - if (outfile) - { - fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile); - outfile.close(); - - binary_info.mLastUsedTime = LLTimer::getTotalSeconds(); - - mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info); - return true; - } - } - } - return false; + if (!mShaderCacheEnabled) return true; + + ProgramBinaryData binary_info = ProgramBinaryData(); + glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength); + if (binary_info.mBinaryLength > 0) + { + std::vector program_binary; + program_binary.resize(binary_info.mBinaryLength); + + GLenum error = glGetError(); // Clear current error + glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data()); + error = glGetError(); + if (error == GL_NO_ERROR) + { + std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin"); + LLUniqueFile outfile = LLFile::fopen(out_path, "wb"); + if (outfile) + { + fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile); + outfile.close(); + + binary_info.mLastUsedTime = LLTimer::getTotalSeconds(); + + mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info); + return true; + } + } + } + return false; } //virtual void LLShaderMgr::initAttribsAndUniforms() { - //MUST match order of enum in LLVertexBuffer.h - mReservedAttribs.push_back("position"); - mReservedAttribs.push_back("normal"); - mReservedAttribs.push_back("texcoord0"); - mReservedAttribs.push_back("texcoord1"); - mReservedAttribs.push_back("texcoord2"); - mReservedAttribs.push_back("texcoord3"); - mReservedAttribs.push_back("diffuse_color"); - mReservedAttribs.push_back("emissive"); - mReservedAttribs.push_back("tangent"); - mReservedAttribs.push_back("weight"); - mReservedAttribs.push_back("weight4"); - mReservedAttribs.push_back("clothing"); - mReservedAttribs.push_back("texture_index"); - - //matrix state - mReservedUniforms.push_back("modelview_matrix"); - mReservedUniforms.push_back("projection_matrix"); - mReservedUniforms.push_back("inv_proj"); - mReservedUniforms.push_back("modelview_projection_matrix"); + //MUST match order of enum in LLVertexBuffer.h + mReservedAttribs.push_back("position"); + mReservedAttribs.push_back("normal"); + mReservedAttribs.push_back("texcoord0"); + mReservedAttribs.push_back("texcoord1"); + mReservedAttribs.push_back("texcoord2"); + mReservedAttribs.push_back("texcoord3"); + mReservedAttribs.push_back("diffuse_color"); + mReservedAttribs.push_back("emissive"); + mReservedAttribs.push_back("tangent"); + mReservedAttribs.push_back("weight"); + mReservedAttribs.push_back("weight4"); + mReservedAttribs.push_back("clothing"); + mReservedAttribs.push_back("texture_index"); + + //matrix state + mReservedUniforms.push_back("modelview_matrix"); + mReservedUniforms.push_back("projection_matrix"); + mReservedUniforms.push_back("inv_proj"); + mReservedUniforms.push_back("modelview_projection_matrix"); mReservedUniforms.push_back("inv_modelview"); mReservedUniforms.push_back("identity_matrix"); - mReservedUniforms.push_back("normal_matrix"); - mReservedUniforms.push_back("texture_matrix0"); - mReservedUniforms.push_back("texture_matrix1"); - mReservedUniforms.push_back("texture_matrix2"); - mReservedUniforms.push_back("texture_matrix3"); - mReservedUniforms.push_back("object_plane_s"); - mReservedUniforms.push_back("object_plane_t"); + mReservedUniforms.push_back("normal_matrix"); + mReservedUniforms.push_back("texture_matrix0"); + mReservedUniforms.push_back("texture_matrix1"); + mReservedUniforms.push_back("texture_matrix2"); + mReservedUniforms.push_back("texture_matrix3"); + mReservedUniforms.push_back("object_plane_s"); + mReservedUniforms.push_back("object_plane_t"); mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF) mReservedUniforms.push_back("texture_normal_transform"); // (GLTF) @@ -1181,38 +1181,38 @@ void LLShaderMgr::initAttribsAndUniforms() llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1); - mReservedUniforms.push_back("viewport"); + mReservedUniforms.push_back("viewport"); - mReservedUniforms.push_back("light_position"); - mReservedUniforms.push_back("light_direction"); - mReservedUniforms.push_back("light_attenuation"); + mReservedUniforms.push_back("light_position"); + mReservedUniforms.push_back("light_direction"); + mReservedUniforms.push_back("light_attenuation"); mReservedUniforms.push_back("light_deferred_attenuation"); - mReservedUniforms.push_back("light_diffuse"); - mReservedUniforms.push_back("light_ambient"); - mReservedUniforms.push_back("light_count"); - mReservedUniforms.push_back("light"); - mReservedUniforms.push_back("light_col"); - mReservedUniforms.push_back("far_z"); + mReservedUniforms.push_back("light_diffuse"); + mReservedUniforms.push_back("light_ambient"); + mReservedUniforms.push_back("light_count"); + mReservedUniforms.push_back("light"); + mReservedUniforms.push_back("light_col"); + mReservedUniforms.push_back("far_z"); - llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1); + llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1); //NOTE: MUST match order in eGLSLReservedUniforms - mReservedUniforms.push_back("proj_mat"); - mReservedUniforms.push_back("proj_near"); - mReservedUniforms.push_back("proj_p"); - mReservedUniforms.push_back("proj_n"); - mReservedUniforms.push_back("proj_origin"); - mReservedUniforms.push_back("proj_range"); - mReservedUniforms.push_back("proj_ambiance"); - mReservedUniforms.push_back("proj_shadow_idx"); - mReservedUniforms.push_back("shadow_fade"); - mReservedUniforms.push_back("proj_focus"); - mReservedUniforms.push_back("proj_lod"); - mReservedUniforms.push_back("proj_ambient_lod"); - - llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1); - - mReservedUniforms.push_back("color"); + mReservedUniforms.push_back("proj_mat"); + mReservedUniforms.push_back("proj_near"); + mReservedUniforms.push_back("proj_p"); + mReservedUniforms.push_back("proj_n"); + mReservedUniforms.push_back("proj_origin"); + mReservedUniforms.push_back("proj_range"); + mReservedUniforms.push_back("proj_ambiance"); + mReservedUniforms.push_back("proj_shadow_idx"); + mReservedUniforms.push_back("shadow_fade"); + mReservedUniforms.push_back("proj_focus"); + mReservedUniforms.push_back("proj_lod"); + mReservedUniforms.push_back("proj_ambient_lod"); + + llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1); + + mReservedUniforms.push_back("color"); mReservedUniforms.push_back("emissiveColor"); mReservedUniforms.push_back("metallicFactor"); mReservedUniforms.push_back("roughnessFactor"); @@ -1220,95 +1220,95 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("clipPlane"); mReservedUniforms.push_back("clipSign"); - mReservedUniforms.push_back("diffuseMap"); + mReservedUniforms.push_back("diffuseMap"); mReservedUniforms.push_back("altDiffuseMap"); - mReservedUniforms.push_back("specularMap"); + mReservedUniforms.push_back("specularMap"); mReservedUniforms.push_back("emissiveMap"); - mReservedUniforms.push_back("bumpMap"); + mReservedUniforms.push_back("bumpMap"); mReservedUniforms.push_back("bumpMap2"); - mReservedUniforms.push_back("environmentMap"); + mReservedUniforms.push_back("environmentMap"); mReservedUniforms.push_back("sceneMap"); mReservedUniforms.push_back("sceneDepth"); mReservedUniforms.push_back("reflectionProbes"); mReservedUniforms.push_back("irradianceProbes"); mReservedUniforms.push_back("heroProbes"); - mReservedUniforms.push_back("cloud_noise_texture"); + mReservedUniforms.push_back("cloud_noise_texture"); mReservedUniforms.push_back("cloud_noise_texture_next"); - mReservedUniforms.push_back("fullbright"); - mReservedUniforms.push_back("lightnorm"); - mReservedUniforms.push_back("sunlight_color"); - mReservedUniforms.push_back("ambient_color"); + mReservedUniforms.push_back("fullbright"); + mReservedUniforms.push_back("lightnorm"); + mReservedUniforms.push_back("sunlight_color"); + mReservedUniforms.push_back("ambient_color"); mReservedUniforms.push_back("sky_hdr_scale"); mReservedUniforms.push_back("sky_sunlight_scale"); mReservedUniforms.push_back("sky_ambient_scale"); - mReservedUniforms.push_back("blue_horizon"); + mReservedUniforms.push_back("blue_horizon"); mReservedUniforms.push_back("blue_density"); mReservedUniforms.push_back("haze_horizon"); - mReservedUniforms.push_back("haze_density"); - mReservedUniforms.push_back("cloud_shadow"); - mReservedUniforms.push_back("density_multiplier"); - mReservedUniforms.push_back("distance_multiplier"); - mReservedUniforms.push_back("max_y"); - mReservedUniforms.push_back("glow"); - mReservedUniforms.push_back("cloud_color"); - mReservedUniforms.push_back("cloud_pos_density1"); - mReservedUniforms.push_back("cloud_pos_density2"); - mReservedUniforms.push_back("cloud_scale"); - mReservedUniforms.push_back("gamma"); - mReservedUniforms.push_back("scene_light_strength"); + mReservedUniforms.push_back("haze_density"); + mReservedUniforms.push_back("cloud_shadow"); + mReservedUniforms.push_back("density_multiplier"); + mReservedUniforms.push_back("distance_multiplier"); + mReservedUniforms.push_back("max_y"); + mReservedUniforms.push_back("glow"); + mReservedUniforms.push_back("cloud_color"); + mReservedUniforms.push_back("cloud_pos_density1"); + mReservedUniforms.push_back("cloud_pos_density2"); + mReservedUniforms.push_back("cloud_scale"); + mReservedUniforms.push_back("gamma"); + mReservedUniforms.push_back("scene_light_strength"); - llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1); + llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1); - mReservedUniforms.push_back("center"); - mReservedUniforms.push_back("size"); - mReservedUniforms.push_back("falloff"); + mReservedUniforms.push_back("center"); + mReservedUniforms.push_back("size"); + mReservedUniforms.push_back("falloff"); - mReservedUniforms.push_back("box_center"); - mReservedUniforms.push_back("box_size"); + mReservedUniforms.push_back("box_center"); + mReservedUniforms.push_back("box_size"); - mReservedUniforms.push_back("minLuminance"); - mReservedUniforms.push_back("maxExtractAlpha"); - mReservedUniforms.push_back("lumWeights"); - mReservedUniforms.push_back("warmthWeights"); - mReservedUniforms.push_back("warmthAmount"); - mReservedUniforms.push_back("glowStrength"); - mReservedUniforms.push_back("glowDelta"); - mReservedUniforms.push_back("glowNoiseMap"); + mReservedUniforms.push_back("minLuminance"); + mReservedUniforms.push_back("maxExtractAlpha"); + mReservedUniforms.push_back("lumWeights"); + mReservedUniforms.push_back("warmthWeights"); + mReservedUniforms.push_back("warmthAmount"); + mReservedUniforms.push_back("glowStrength"); + mReservedUniforms.push_back("glowDelta"); + mReservedUniforms.push_back("glowNoiseMap"); - llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1); + llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1); - mReservedUniforms.push_back("minimum_alpha"); - mReservedUniforms.push_back("emissive_brightness"); + mReservedUniforms.push_back("minimum_alpha"); + mReservedUniforms.push_back("emissive_brightness"); // Deferred - mReservedUniforms.push_back("shadow_matrix"); - mReservedUniforms.push_back("env_mat"); - mReservedUniforms.push_back("shadow_clip"); - mReservedUniforms.push_back("sun_wash"); - mReservedUniforms.push_back("shadow_noise"); - mReservedUniforms.push_back("blur_size"); - mReservedUniforms.push_back("ssao_radius"); - mReservedUniforms.push_back("ssao_max_radius"); - mReservedUniforms.push_back("ssao_factor"); - mReservedUniforms.push_back("ssao_factor_inv"); - mReservedUniforms.push_back("ssao_effect_mat"); - mReservedUniforms.push_back("screen_res"); - mReservedUniforms.push_back("near_clip"); - mReservedUniforms.push_back("shadow_offset"); - mReservedUniforms.push_back("shadow_bias"); - mReservedUniforms.push_back("spot_shadow_bias"); - mReservedUniforms.push_back("spot_shadow_offset"); - mReservedUniforms.push_back("sun_dir"); + mReservedUniforms.push_back("shadow_matrix"); + mReservedUniforms.push_back("env_mat"); + mReservedUniforms.push_back("shadow_clip"); + mReservedUniforms.push_back("sun_wash"); + mReservedUniforms.push_back("shadow_noise"); + mReservedUniforms.push_back("blur_size"); + mReservedUniforms.push_back("ssao_radius"); + mReservedUniforms.push_back("ssao_max_radius"); + mReservedUniforms.push_back("ssao_factor"); + mReservedUniforms.push_back("ssao_factor_inv"); + mReservedUniforms.push_back("ssao_effect_mat"); + mReservedUniforms.push_back("screen_res"); + mReservedUniforms.push_back("near_clip"); + mReservedUniforms.push_back("shadow_offset"); + mReservedUniforms.push_back("shadow_bias"); + mReservedUniforms.push_back("spot_shadow_bias"); + mReservedUniforms.push_back("spot_shadow_offset"); + mReservedUniforms.push_back("sun_dir"); mReservedUniforms.push_back("moon_dir"); - mReservedUniforms.push_back("shadow_res"); - mReservedUniforms.push_back("proj_shadow_res"); - mReservedUniforms.push_back("depth_cutoff"); - mReservedUniforms.push_back("norm_cutoff"); - mReservedUniforms.push_back("shadow_target_width"); - - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1); + mReservedUniforms.push_back("shadow_res"); + mReservedUniforms.push_back("proj_shadow_res"); + mReservedUniforms.push_back("depth_cutoff"); + mReservedUniforms.push_back("norm_cutoff"); + mReservedUniforms.push_back("shadow_target_width"); + + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1); mReservedUniforms.push_back("iterationCount"); mReservedUniforms.push_back("rayStep"); @@ -1322,105 +1322,105 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("inv_modelview_delta"); mReservedUniforms.push_back("cube_snapshot"); - mReservedUniforms.push_back("tc_scale"); - mReservedUniforms.push_back("rcp_screen_res"); - mReservedUniforms.push_back("rcp_frame_opt"); - mReservedUniforms.push_back("rcp_frame_opt2"); - - mReservedUniforms.push_back("focal_distance"); - mReservedUniforms.push_back("blur_constant"); - mReservedUniforms.push_back("tan_pixel_angle"); - mReservedUniforms.push_back("magnification"); - mReservedUniforms.push_back("max_cof"); - mReservedUniforms.push_back("res_scale"); - mReservedUniforms.push_back("dof_width"); - mReservedUniforms.push_back("dof_height"); - - mReservedUniforms.push_back("depthMap"); - mReservedUniforms.push_back("shadowMap0"); - mReservedUniforms.push_back("shadowMap1"); - mReservedUniforms.push_back("shadowMap2"); - mReservedUniforms.push_back("shadowMap3"); - mReservedUniforms.push_back("shadowMap4"); - mReservedUniforms.push_back("shadowMap5"); - - llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1); - - mReservedUniforms.push_back("normalMap"); - mReservedUniforms.push_back("positionMap"); - mReservedUniforms.push_back("diffuseRect"); - mReservedUniforms.push_back("specularRect"); + mReservedUniforms.push_back("tc_scale"); + mReservedUniforms.push_back("rcp_screen_res"); + mReservedUniforms.push_back("rcp_frame_opt"); + mReservedUniforms.push_back("rcp_frame_opt2"); + + mReservedUniforms.push_back("focal_distance"); + mReservedUniforms.push_back("blur_constant"); + mReservedUniforms.push_back("tan_pixel_angle"); + mReservedUniforms.push_back("magnification"); + mReservedUniforms.push_back("max_cof"); + mReservedUniforms.push_back("res_scale"); + mReservedUniforms.push_back("dof_width"); + mReservedUniforms.push_back("dof_height"); + + mReservedUniforms.push_back("depthMap"); + mReservedUniforms.push_back("shadowMap0"); + mReservedUniforms.push_back("shadowMap1"); + mReservedUniforms.push_back("shadowMap2"); + mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("shadowMap4"); + mReservedUniforms.push_back("shadowMap5"); + + llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1); + + mReservedUniforms.push_back("normalMap"); + mReservedUniforms.push_back("positionMap"); + mReservedUniforms.push_back("diffuseRect"); + mReservedUniforms.push_back("specularRect"); mReservedUniforms.push_back("emissiveRect"); mReservedUniforms.push_back("exposureMap"); mReservedUniforms.push_back("brdfLut"); - mReservedUniforms.push_back("noiseMap"); - mReservedUniforms.push_back("lightFunc"); - mReservedUniforms.push_back("lightMap"); - mReservedUniforms.push_back("bloomMap"); - mReservedUniforms.push_back("projectionMap"); - mReservedUniforms.push_back("norm_mat"); - mReservedUniforms.push_back("texture_gamma"); - - mReservedUniforms.push_back("specular_color"); - mReservedUniforms.push_back("env_intensity"); - - mReservedUniforms.push_back("matrixPalette"); - mReservedUniforms.push_back("translationPalette"); - - mReservedUniforms.push_back("screenTex"); - mReservedUniforms.push_back("screenDepth"); - mReservedUniforms.push_back("refTex"); - mReservedUniforms.push_back("eyeVec"); - mReservedUniforms.push_back("time"); - mReservedUniforms.push_back("waveDir1"); - mReservedUniforms.push_back("waveDir2"); - mReservedUniforms.push_back("lightDir"); - mReservedUniforms.push_back("specular"); - mReservedUniforms.push_back("lightExp"); - mReservedUniforms.push_back("waterFogColor"); + mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightFunc"); + mReservedUniforms.push_back("lightMap"); + mReservedUniforms.push_back("bloomMap"); + mReservedUniforms.push_back("projectionMap"); + mReservedUniforms.push_back("norm_mat"); + mReservedUniforms.push_back("texture_gamma"); + + mReservedUniforms.push_back("specular_color"); + mReservedUniforms.push_back("env_intensity"); + + mReservedUniforms.push_back("matrixPalette"); + mReservedUniforms.push_back("translationPalette"); + + mReservedUniforms.push_back("screenTex"); + mReservedUniforms.push_back("screenDepth"); + mReservedUniforms.push_back("refTex"); + mReservedUniforms.push_back("eyeVec"); + mReservedUniforms.push_back("time"); + mReservedUniforms.push_back("waveDir1"); + mReservedUniforms.push_back("waveDir2"); + mReservedUniforms.push_back("lightDir"); + mReservedUniforms.push_back("specular"); + mReservedUniforms.push_back("lightExp"); + mReservedUniforms.push_back("waterFogColor"); mReservedUniforms.push_back("waterFogColorLinear"); - mReservedUniforms.push_back("waterFogDensity"); - mReservedUniforms.push_back("waterFogKS"); - mReservedUniforms.push_back("refScale"); - mReservedUniforms.push_back("waterHeight"); - mReservedUniforms.push_back("waterPlane"); - mReservedUniforms.push_back("normScale"); - mReservedUniforms.push_back("fresnelScale"); - mReservedUniforms.push_back("fresnelOffset"); - mReservedUniforms.push_back("blurMultiplier"); - mReservedUniforms.push_back("sunAngle"); - mReservedUniforms.push_back("scaledAngle"); - mReservedUniforms.push_back("sunAngle2"); - - mReservedUniforms.push_back("camPosLocal"); - - mReservedUniforms.push_back("gWindDir"); - mReservedUniforms.push_back("gSinWaveParams"); - mReservedUniforms.push_back("gGravity"); - - mReservedUniforms.push_back("detail_0"); - mReservedUniforms.push_back("detail_1"); - mReservedUniforms.push_back("detail_2"); - mReservedUniforms.push_back("detail_3"); - - mReservedUniforms.push_back("alpha_ramp"); - - mReservedUniforms.push_back("detail_0_base_color"); - mReservedUniforms.push_back("detail_1_base_color"); - mReservedUniforms.push_back("detail_2_base_color"); - mReservedUniforms.push_back("detail_3_base_color"); - mReservedUniforms.push_back("detail_0_normal"); - mReservedUniforms.push_back("detail_1_normal"); - mReservedUniforms.push_back("detail_2_normal"); - mReservedUniforms.push_back("detail_3_normal"); - mReservedUniforms.push_back("detail_0_metallic_roughness"); - mReservedUniforms.push_back("detail_1_metallic_roughness"); - mReservedUniforms.push_back("detail_2_metallic_roughness"); - mReservedUniforms.push_back("detail_3_metallic_roughness"); - mReservedUniforms.push_back("detail_0_emissive"); - mReservedUniforms.push_back("detail_1_emissive"); - mReservedUniforms.push_back("detail_2_emissive"); - mReservedUniforms.push_back("detail_3_emissive"); + mReservedUniforms.push_back("waterFogDensity"); + mReservedUniforms.push_back("waterFogKS"); + mReservedUniforms.push_back("refScale"); + mReservedUniforms.push_back("waterHeight"); + mReservedUniforms.push_back("waterPlane"); + mReservedUniforms.push_back("normScale"); + mReservedUniforms.push_back("fresnelScale"); + mReservedUniforms.push_back("fresnelOffset"); + mReservedUniforms.push_back("blurMultiplier"); + mReservedUniforms.push_back("sunAngle"); + mReservedUniforms.push_back("scaledAngle"); + mReservedUniforms.push_back("sunAngle2"); + + mReservedUniforms.push_back("camPosLocal"); + + mReservedUniforms.push_back("gWindDir"); + mReservedUniforms.push_back("gSinWaveParams"); + mReservedUniforms.push_back("gGravity"); + + mReservedUniforms.push_back("detail_0"); + mReservedUniforms.push_back("detail_1"); + mReservedUniforms.push_back("detail_2"); + mReservedUniforms.push_back("detail_3"); + + mReservedUniforms.push_back("alpha_ramp"); + + mReservedUniforms.push_back("detail_0_base_color"); + mReservedUniforms.push_back("detail_1_base_color"); + mReservedUniforms.push_back("detail_2_base_color"); + mReservedUniforms.push_back("detail_3_base_color"); + mReservedUniforms.push_back("detail_0_normal"); + mReservedUniforms.push_back("detail_1_normal"); + mReservedUniforms.push_back("detail_2_normal"); + mReservedUniforms.push_back("detail_3_normal"); + mReservedUniforms.push_back("detail_0_metallic_roughness"); + mReservedUniforms.push_back("detail_1_metallic_roughness"); + mReservedUniforms.push_back("detail_2_metallic_roughness"); + mReservedUniforms.push_back("detail_3_metallic_roughness"); + mReservedUniforms.push_back("detail_0_emissive"); + mReservedUniforms.push_back("detail_1_emissive"); + mReservedUniforms.push_back("detail_2_emissive"); + mReservedUniforms.push_back("detail_3_emissive"); mReservedUniforms.push_back("baseColorFactors"); mReservedUniforms.push_back("metallicFactors"); @@ -1428,8 +1428,8 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("emissiveColors"); mReservedUniforms.push_back("minimum_alphas"); - mReservedUniforms.push_back("origin"); - mReservedUniforms.push_back("display_gamma"); + mReservedUniforms.push_back("origin"); + mReservedUniforms.push_back("display_gamma"); mReservedUniforms.push_back("inscatter"); mReservedUniforms.push_back("sun_size"); @@ -1462,17 +1462,17 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("debug_normal_draw_length"); - llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); + llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS); - std::set dupe_check; + std::set dupe_check; - for (U32 i = 0; i < mReservedUniforms.size(); ++i) - { - if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end()) - { - LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL; - } - dupe_check.insert(mReservedUniforms[i]); - } + for (U32 i = 0; i < mReservedUniforms.size(); ++i) + { + if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end()) + { + LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL; + } + dupe_check.insert(mReservedUniforms[i]); + } } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index eb13418cd7..8b13e822d5 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -1,25 +1,25 @@ -/** +/** * @file llshadermgr.h * @brief Shader Manager * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -33,8 +33,8 @@ class LLShaderMgr { public: - LLShaderMgr(); - virtual ~LLShaderMgr(); + LLShaderMgr(); + virtual ~LLShaderMgr(); // clang-format off typedef enum @@ -323,23 +323,23 @@ public: } eGLSLReservedUniforms; // clang-format on - // singleton pattern implementation - static LLShaderMgr * instance(); + // singleton pattern implementation + static LLShaderMgr * instance(); - virtual void initAttribsAndUniforms(void); + virtual void initAttribsAndUniforms(void); - BOOL attachShaderFeatures(LLGLSLShader * shader); - void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = ""); + BOOL attachShaderFeatures(LLGLSLShader * shader); + void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = ""); void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text); - BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE); - BOOL validateProgramObject(GLuint obj); - GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines = NULL, S32 texture_index_channels = -1); + BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE); + BOOL validateProgramObject(GLuint obj); + GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines = NULL, S32 texture_index_channels = -1); - // Implemented in the application to actually point to the shader directory. - virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual + // Implemented in the application to actually point to the shader directory. + virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual - // Implemented in the application to actually update out of date uniforms for a particular shader - virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual + // Implemented in the application to actually update out of date uniforms for a particular shader + virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version); void clearShaderCache(); @@ -349,14 +349,14 @@ public: bool saveCachedProgramBinary(LLGLSLShader* shader); public: - // Map of shader names to compiled + // Map of shader names to compiled std::map mVertexShaderObjects; std::map mFragmentShaderObjects; - //global (reserved slot) shader parameters - std::vector mReservedAttribs; + //global (reserved slot) shader parameters + std::vector mReservedAttribs; - std::vector mReservedUniforms; + std::vector mReservedUniforms; struct ProgramBinaryData { @@ -372,8 +372,8 @@ public: protected: - // our parameter manager singleton instance - static LLShaderMgr * sInstance; + // our parameter manager singleton instance + static LLShaderMgr * sInstance; }; //LLShaderMgr diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1d81c3778b..7caf20f40b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvertexbuffer.cpp * @brief LLVertexBuffer implementation * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -41,25 +41,25 @@ //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2 U32 nhpo2(U32 v) { - U32 r = 1; - while (r < v) { - r *= 2; - } - return r; + U32 r = 1; + while (r < v) { + r *= 2; + } + return r; } //which power of 2 is i? //assumes i is a power of 2 > 0 U32 wpo2(U32 i) { - llassert(i > 0); - llassert(nhpo2(i) == i); + llassert(i > 0); + llassert(nhpo2(i) == i); - U32 r = 0; + U32 r = 0; - while (i >>= 1) ++r; + while (i >>= 1) ++r; - return r; + return r; } struct CompareMappedRegion @@ -381,7 +381,7 @@ public: Entry& entry = entries.back(); name = entry.mGLName; data = entry.mData; - + entries.pop_back(); if (entries.empty()) { @@ -474,9 +474,9 @@ public: } #if 0 - LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent", - mDistributed / 1000000, - mAllocated / 1000000, + LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent", + mDistributed / 1000000, + mAllocated / 1000000, (mAllocated + mReserved) / 1000000, // total bytes ((mAllocated+mReserved-mDistributed)*100)/llmax(mDistributed, (U64) 1), // overhead percent (mHits*100)/llmax(mMisses+mHits, (U32)1)) // hit rate percent @@ -522,7 +522,7 @@ U64 LLVertexBuffer::getBytesAllocated() } //============================================================================ -// +// //static U32 LLVertexBuffer::sGLRenderBuffer = 0; U32 LLVertexBuffer::sGLRenderIndices = 0; @@ -533,50 +533,50 @@ U32 LLVertexBuffer::sVertexCount = 0; //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { - sizeof(LLVector4), // TYPE_VERTEX, - sizeof(LLVector4), // TYPE_NORMAL, - sizeof(LLVector2), // TYPE_TEXCOORD0, - sizeof(LLVector2), // TYPE_TEXCOORD1, - sizeof(LLVector2), // TYPE_TEXCOORD2, - sizeof(LLVector2), // TYPE_TEXCOORD3, - sizeof(LLColor4U), // TYPE_COLOR, - sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently - sizeof(LLVector4), // TYPE_TANGENT, - sizeof(F32), // TYPE_WEIGHT, - sizeof(LLVector4), // TYPE_WEIGHT4, - sizeof(LLVector4), // TYPE_CLOTHWEIGHT, - sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes + sizeof(LLVector4), // TYPE_VERTEX, + sizeof(LLVector4), // TYPE_NORMAL, + sizeof(LLVector2), // TYPE_TEXCOORD0, + sizeof(LLVector2), // TYPE_TEXCOORD1, + sizeof(LLVector2), // TYPE_TEXCOORD2, + sizeof(LLVector2), // TYPE_TEXCOORD3, + sizeof(LLColor4U), // TYPE_COLOR, + sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently + sizeof(LLVector4), // TYPE_TANGENT, + sizeof(F32), // TYPE_WEIGHT, + sizeof(LLVector4), // TYPE_WEIGHT4, + sizeof(LLVector4), // TYPE_CLOTHWEIGHT, + sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes }; static const std::string vb_type_name[] = { - "TYPE_VERTEX", - "TYPE_NORMAL", - "TYPE_TEXCOORD0", - "TYPE_TEXCOORD1", - "TYPE_TEXCOORD2", - "TYPE_TEXCOORD3", - "TYPE_COLOR", - "TYPE_EMISSIVE", - "TYPE_TANGENT", - "TYPE_WEIGHT", - "TYPE_WEIGHT4", - "TYPE_CLOTHWEIGHT", - "TYPE_TEXTURE_INDEX", - "TYPE_MAX", - "TYPE_INDEX", + "TYPE_VERTEX", + "TYPE_NORMAL", + "TYPE_TEXCOORD0", + "TYPE_TEXCOORD1", + "TYPE_TEXCOORD2", + "TYPE_TEXCOORD3", + "TYPE_COLOR", + "TYPE_EMISSIVE", + "TYPE_TANGENT", + "TYPE_WEIGHT", + "TYPE_WEIGHT4", + "TYPE_CLOTHWEIGHT", + "TYPE_TEXTURE_INDEX", + "TYPE_MAX", + "TYPE_INDEX", }; const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] = { - GL_TRIANGLES, - GL_TRIANGLE_STRIP, - GL_TRIANGLE_FAN, - GL_POINTS, - GL_LINES, - GL_LINE_STRIP, - GL_QUADS, - GL_LINE_LOOP, + GL_TRIANGLES, + GL_TRIANGLE_STRIP, + GL_TRIANGLE_FAN, + GL_POINTS, + GL_LINES, + GL_LINE_STRIP, + GL_QUADS, + GL_LINE_LOOP, }; //static @@ -598,7 +598,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } } else - { //was disabled + { //was disabled if (data_mask & mask) { //needs to be enabled glEnableVertexAttribArray(loc); @@ -627,18 +627,18 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos) void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); + llassert(LLGLSLShader::sCurBoundShaderPtr != NULL); + + gGL.syncMatrices(); - gGL.syncMatrices(); + U32 mask = LLVertexBuffer::MAP_VERTEX; + if (tc) + { + mask = mask | LLVertexBuffer::MAP_TEXCOORD0; + } - U32 mask = LLVertexBuffer::MAP_VERTEX; - if (tc) - { - mask = mask | LLVertexBuffer::MAP_TEXCOORD0; - } + unbind(); - unbind(); - gGL.begin(mode); if (tc != nullptr) @@ -672,32 +672,32 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of llassert(start < (U32)mNumVerts); llassert(end < (U32)mNumVerts); - if (start >= (U32) mNumVerts || - end >= (U32) mNumVerts) - { - LL_ERRS() << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << LL_ENDL; - } + if (start >= (U32) mNumVerts || + end >= (U32) mNumVerts) + { + LL_ERRS() << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << LL_ENDL; + } - llassert(mNumIndices >= 0); + llassert(mNumIndices >= 0); - if (indices_offset >= (U32) mNumIndices || - indices_offset + count > (U32) mNumIndices) - { - LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL; - } + if (indices_offset >= (U32) mNumIndices || + indices_offset + count > (U32) mNumIndices) + { + LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL; + } - { - U16* idx = (U16*) mMappedIndexData+indices_offset; - for (U32 i = 0; i < count; ++i) - { + { + U16* idx = (U16*) mMappedIndexData+indices_offset; + for (U32 i = 0; i < count; ++i) + { llassert(idx[i] >= start); llassert(idx[i] <= end); - if (idx[i] < start || idx[i] > end) - { - LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL; - } - } + if (idx[i] < start || idx[i] > end) + { + LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL; + } + } LLVector4a* v = (LLVector4a*)mMappedData; @@ -709,29 +709,29 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of } } - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader && shader->mFeatures.mIndexedTextureChannels > 1) + { + LLVector4a* v = (LLVector4a*) mMappedData; - if (shader && shader->mFeatures.mIndexedTextureChannels > 1) - { - LLVector4a* v = (LLVector4a*) mMappedData; - - for (U32 i = start; i < end; i++) - { + for (U32 i = start; i < end; i++) + { U32 idx = (U32) (v[i][3]+0.25f); - if (idx >= shader->mFeatures.mIndexedTextureChannels) - { - LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL; - } - } - } - } + if (idx >= shader->mFeatures.mIndexedTextureChannels) + { + LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL; + } + } + } + } return true; } #ifdef LL_PROFILER_ENABLE_RENDER_DOC void LLVertexBuffer::setLabel(const char* label) { - LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label); + LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label); } #endif @@ -756,7 +756,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const llassert(first + count <= mNumVerts); llassert(mGLBuffer == sGLRenderBuffer); llassert(mGLIndices == sGLRenderIndices); - + gGL.syncMatrices(); glDrawArrays(sGLMode[mode], first, count); } @@ -778,21 +778,21 @@ void LLVertexBuffer::initClass(LLWindow* window) #endif } -//static +//static void LLVertexBuffer::unbind() { glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - sGLRenderBuffer = 0; - sGLRenderIndices = 0; + sGLRenderBuffer = 0; + sGLRenderIndices = 0; } //static void LLVertexBuffer::cleanupClass() { - unbind(); - + unbind(); + delete sVBOPool; sVBOPool = nullptr; @@ -812,71 +812,71 @@ void LLVertexBuffer::cleanupClass() //---------------------------------------------------------------------------- -LLVertexBuffer::LLVertexBuffer(U32 typemask) -: LLRefCount(), - mTypeMask(typemask) +LLVertexBuffer::LLVertexBuffer(U32 typemask) +: LLRefCount(), + mTypeMask(typemask) { - //zero out offsets - for (U32 i = 0; i < TYPE_MAX; i++) - { - mOffsets[i] = 0; - } + //zero out offsets + for (U32 i = 0; i < TYPE_MAX; i++) + { + mOffsets[i] = 0; + } } //static U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices) { U32 offset = 0; - for (U32 i=0; i= 0); + llassert(nverts >= 0); - bool success = true; + bool success = true; - if (nverts > 65536) - { - LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; - nverts = 65536; - } + if (nverts > 65536) + { + LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; + nverts = 65536; + } - U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); + U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts); if (needed_size != mSize) { @@ -1012,42 +1012,42 @@ bool LLVertexBuffer::updateNumVerts(U32 nverts) } llassert(mSize == needed_size); - mNumVerts = nverts; - return success; + mNumVerts = nverts; + return success; } bool LLVertexBuffer::updateNumIndices(U32 nindices) { - llassert(nindices >= 0); + llassert(nindices >= 0); - bool success = true; + bool success = true; - U32 needed_size = sizeof(U16) * nindices; + U32 needed_size = sizeof(U16) * nindices; - if (needed_size != mIndicesSize) - { - success &= createGLIndices(needed_size); - } + if (needed_size != mIndicesSize) + { + success &= createGLIndices(needed_size); + } llassert(mIndicesSize == needed_size); - mNumIndices = nindices; - return success; + mNumIndices = nindices; + return success; } bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices) { - if (nverts < 0 || nindices < 0 || - nverts > 65536) - { - LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL; - } + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL; + } + + bool success = true; - bool success = true; + success &= updateNumVerts(nverts); + success &= updateNumIndices(nindices); - success &= updateNumVerts(nverts); - success &= updateNumIndices(nindices); - - return success; + return success; } //---------------------------------------------------------------------------- @@ -1056,17 +1056,17 @@ bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices) // otherwise return false bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end) { - - if (end < region.mStart || - start > region.mEnd) - { //gap exists, do not merge - return false; - } + + if (end < region.mStart || + start > region.mEnd) + { //gap exists, do not merge + return false; + } region.mStart = llmin(region.mStart, start); region.mEnd = llmax(region.mEnd, end); - return true; + return true; } @@ -1074,7 +1074,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end) U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - + if (count == -1) { count = mNumVerts - index; @@ -1083,24 +1083,24 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde U32 start = mOffsets[type] + sTypeSize[type] * index; U32 end = start + sTypeSize[type] * count-1; - bool flagged = false; - // flag region as mapped - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) - { - MappedRegion& region = mMappedVertexRegions[i]; + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + MappedRegion& region = mMappedVertexRegions[i]; if (expand_region(region, start, end)) { flagged = true; break; } - } + } - if (!flagged) - { - //didn't expand an existing region, make a new one + if (!flagged) + { + //didn't expand an existing region, make a new one mMappedVertexRegions.push_back({ start, end }); - } - + } + return mMappedData+mOffsets[type]+sTypeSize[type]*index; } @@ -1108,11 +1108,11 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; - - if (count == -1) - { - count = mNumIndices-index; - } + + if (count == -1) + { + count = mNumIndices-index; + } U32 start = sizeof(U16) * index; U32 end = start + sizeof(U16) * count-1; @@ -1175,23 +1175,23 @@ void LLVertexBuffer::unmapBuffer() } }; - if (!mMappedVertexRegions.empty()) - { + if (!mMappedVertexRegions.empty()) + { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex"); if (sGLRenderBuffer != mGLBuffer) { glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); sGLRenderBuffer = mGLBuffer; } - + U32 start = 0; U32 end = 0; std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion()); - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) - { - const MappedRegion& region = mMappedVertexRegions[i]; + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + const MappedRegion& region = mMappedVertexRegions[i]; if (region.mStart == end + 1) { end = region.mEnd; @@ -1202,15 +1202,15 @@ void LLVertexBuffer::unmapBuffer() start = region.mStart; end = region.mEnd; } - } + } flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start); - mMappedVertexRegions.clear(); - } - - if (!mMappedIndexRegions.empty()) - { + mMappedVertexRegions.clear(); + } + + if (!mMappedIndexRegions.empty()) + { LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index"); if (mGLIndices != sGLRenderIndices) @@ -1240,86 +1240,86 @@ void LLVertexBuffer::unmapBuffer() flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start); - mMappedIndexRegions.clear(); - } + mMappedIndexRegions.clear(); + } } //---------------------------------------------------------------------------- template struct VertexBufferStrider { - typedef LLStrider strider_t; - static bool get(LLVertexBuffer& vbo, - strider_t& strider, - S32 index, S32 count) - { - if (type == LLVertexBuffer::TYPE_INDEX) - { - U8* ptr = vbo.mapIndexBuffer(index, count); - - if (ptr == NULL) - { - LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL; - return false; - } - - strider = (T*)ptr; - strider.setStride(0); - return true; - } - else if (vbo.hasDataType(type)) - { + typedef LLStrider strider_t; + static bool get(LLVertexBuffer& vbo, + strider_t& strider, + S32 index, S32 count) + { + if (type == LLVertexBuffer::TYPE_INDEX) + { + U8* ptr = vbo.mapIndexBuffer(index, count); + + if (ptr == NULL) + { + LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL; + return false; + } + + strider = (T*)ptr; + strider.setStride(0); + return true; + } + else if (vbo.hasDataType(type)) + { U32 stride = LLVertexBuffer::sTypeSize[type]; - U8* ptr = vbo.mapVertexBuffer(type, index, count); - - if (ptr == NULL) - { - LL_WARNS() << "mapVertexBuffer failed!" << LL_ENDL; - return false; - } - - strider = (T*)ptr; - strider.setStride(stride); - return true; - } - else - { - LL_ERRS() << "VertexBufferStrider could not find valid vertex data." << LL_ENDL; - } - return false; - } + U8* ptr = vbo.mapVertexBuffer(type, index, count); + + if (ptr == NULL) + { + LL_WARNS() << "mapVertexBuffer failed!" << LL_ENDL; + return false; + } + + strider = (T*)ptr; + strider.setStride(stride); + return true; + } + else + { + LL_ERRS() << "VertexBufferStrider could not find valid vertex data." << LL_ENDL; + } + return false; + } }; bool LLVertexBuffer::getVertexStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getVertexStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getIndexStrider(LLStrider& strider, U32 index, S32 count) { llassert(mIndicesStride == 2); // cannot access 32-bit indices with U16 strider llassert(mIndicesType == GL_UNSIGNED_SHORT); - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getTexCoord0Strider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getTexCoord1Strider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getTexCoord2Strider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getNormalStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getNormalStrider(LLStrider& strider, U32 index, S32 count) { @@ -1327,33 +1327,33 @@ bool LLVertexBuffer::getNormalStrider(LLStrider& strider, U32 index, } bool LLVertexBuffer::getTangentStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getTangentStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getColorStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getEmissiveStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getWeightStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, U32 index, S32 count) { - return VertexBufferStrider::get(*this, strider, index, count); + return VertexBufferStrider::get(*this, strider, index, count); } //---------------------------------------------------------------------------- @@ -1373,7 +1373,7 @@ void LLVertexBuffer::setBuffer() // this Vertex Buffer must provide all necessary attributes for currently bound shader llassert_msg((data_mask & mTypeMask) == data_mask, - "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x" + "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x" << std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec); if (sGLRenderBuffer != mGLBuffer) @@ -1388,7 +1388,7 @@ void LLVertexBuffer::setBuffer() setupVertexBuffer(); sLastMask = data_mask; } - + if (mGLIndices != sGLRenderIndices) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 669d89aabf..b634609929 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -1,25 +1,25 @@ -/** +/** * @file llvertexbuffer.h * @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -51,51 +51,51 @@ //============================================================================ -// base class +// base class class LLPrivateMemoryPool; class LLVertexBuffer final : public LLRefCount { public: - struct MappedRegion - { + struct MappedRegion + { U32 mStart; U32 mEnd; - }; + }; - LLVertexBuffer(const LLVertexBuffer& rhs) - { - *this = rhs; - } + LLVertexBuffer(const LLVertexBuffer& rhs) + { + *this = rhs; + } - const LLVertexBuffer& operator=(const LLVertexBuffer& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } + const LLVertexBuffer& operator=(const LLVertexBuffer& rhs) + { + LL_ERRS() << "Illegal operation!" << LL_ENDL; + return *this; + } - static void initClass(LLWindow* window); - static void cleanupClass(); - static void setupClientArrays(U32 data_mask); - static void drawArrays(U32 mode, const std::vector& pos); - static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp); + static void initClass(LLWindow* window); + static void cleanupClass(); + static void setupClientArrays(U32 data_mask); + static void drawArrays(U32 mode, const std::vector& pos); + static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp); - static void unbind(); //unbind any bound vertex buffer + static void unbind(); //unbind any bound vertex buffer - //get the size of a vertex with the given typemask - static U32 calcVertexSize(const U32& typemask); + //get the size of a vertex with the given typemask + static U32 calcVertexSize(const U32& typemask); - //get the size of a buffer with the given typemask and vertex count - //fill offsets with the offset of each vertex component array into the buffer - // indexed by the following enum - static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices); + //get the size of a buffer with the given typemask and vertex count + //fill offsets with the offset of each vertex component array into the buffer + // indexed by the following enum + static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices); - //WARNING -- when updating these enums you MUST - // 1 - update LLVertexBuffer::sTypeSize + //WARNING -- when updating these enums you MUST + // 1 - update LLVertexBuffer::sTypeSize // 2 - update LLVertexBuffer::vb_type_name - // 3 - add a strider accessor - // 4 - modify LLVertexBuffer::setupVertexBuffer - // 6 - modify LLViewerShaderMgr::mReservedAttribs - + // 3 - add a strider accessor + // 4 - modify LLVertexBuffer::setupVertexBuffer + // 6 - modify LLViewerShaderMgr::mReservedAttribs + // clang-format off enum AttributeType { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms() TYPE_VERTEX = 0, // "position" @@ -112,83 +112,83 @@ public: TYPE_CLOTHWEIGHT, // "clothing" TYPE_TEXTURE_INDEX, // "texture_index" TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer - TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer + TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer }; // clang-format on enum { - MAP_VERTEX = (1<getVertexBuffer(verts); - // vb->getNormalStrider(norms); - // setVertsNorms(verts, norms); - // vb->unmapBuffer(); - bool getVertexStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getVertexStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getIndexStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getTexCoord0Strider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getTexCoord1Strider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getTexCoord2Strider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getNormalStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getNormalStrider(LLStrider& strider, U32 index = 0, S32 count = -1); - bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getColorStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getEmissiveStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getWeight4Strider(LLStrider& strider, U32 index=0, S32 count = -1); - bool getClothWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); - + void setBuffer(); + + // Only call each getVertexPointer, etc, once before calling unmapBuffer() + // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer() + // example: + // vb->getVertexBuffer(verts); + // vb->getNormalStrider(norms); + // setVertsNorms(verts, norms); + // vb->unmapBuffer(); + bool getVertexStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getVertexStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getIndexStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getTexCoord0Strider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getTexCoord1Strider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getTexCoord2Strider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getNormalStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getNormalStrider(LLStrider& strider, U32 index = 0, S32 count = -1); + bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getTangentStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getColorStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getEmissiveStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getWeight4Strider(LLStrider& strider, U32 index=0, S32 count = -1); + bool getClothWeightStrider(LLStrider& strider, U32 index=0, S32 count = -1); + void setPositionData(const LLVector4a* data); void setNormalData(const LLVector4a* data); void setTangentData(const LLVector4a* data); @@ -198,75 +198,75 @@ public: void setIndexData(const U16* data); void setIndexData(const U32* data); - U32 getNumVerts() const { return mNumVerts; } - U32 getNumIndices() const { return mNumIndices; } - - U32 getTypeMask() const { return mTypeMask; } - bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); } + U32 getNumVerts() const { return mNumVerts; } + U32 getNumIndices() const { return mNumIndices; } + + U32 getTypeMask() const { return mTypeMask; } + bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); } U32 getSize() const { return mSize; } - U32 getIndicesSize() const { return mIndicesSize; } - U8* getMappedData() const { return mMappedData; } - U8* getMappedIndices() const { return mMappedIndexData; } - U32 getOffset(AttributeType type) const { return mOffsets[type]; } - + U32 getIndicesSize() const { return mIndicesSize; } + U8* getMappedData() const { return mMappedData; } + U8* getMappedIndices() const { return mMappedIndexData; } + U32 getOffset(AttributeType type) const { return mOffsets[type]; } + // these functions assume (and assert on) the current VBO being bound // Detailed error checking can be enabled by setting gDebugGL to true - void draw(U32 mode, U32 count, U32 indices_offset) const; - void drawArrays(U32 mode, U32 offset, U32 count) const; + void draw(U32 mode, U32 count, U32 indices_offset) const; + void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; - //for debugging, validate data in given range is valid - bool validateRange(U32 start, U32 end, U32 count, U32 offset) const; + //for debugging, validate data in given range is valid + bool validateRange(U32 start, U32 end, U32 count, U32 offset) const; + + #ifdef LL_PROFILER_ENABLE_RENDER_DOC + void setLabel(const char* label); + #endif - #ifdef LL_PROFILER_ENABLE_RENDER_DOC - void setLabel(const char* label); - #endif - -protected: - U32 mGLBuffer = 0; // GL VBO handle - U32 mGLIndices = 0; // GL IBO handle - U32 mNumVerts = 0; // Number of vertices allocated - U32 mNumIndices = 0; // Number of indices allocated +protected: + U32 mGLBuffer = 0; // GL VBO handle + U32 mGLIndices = 0; // GL IBO handle + U32 mNumVerts = 0; // Number of vertices allocated + U32 mNumIndices = 0; // Number of indices allocated U32 mIndicesType = GL_UNSIGNED_SHORT; // type of indices in index buffer U32 mIndicesStride = 2; // size of each index in bytes - U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute + U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute + + U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped) + U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped) - U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped) - U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped) + U32 mTypeMask = 0; // bitmask of present vertex attributes - U32 mTypeMask = 0; // bitmask of present vertex attributes - - U32 mSize = 0; // size in bytes of mMappedData - U32 mIndicesSize = 0; // size in bytes of mMappedIndexData + U32 mSize = 0; // size in bytes of mMappedData + U32 mIndicesSize = 0; // size in bytes of mMappedIndexData - std::vector mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL - std::vector mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL + std::vector mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL + std::vector mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL private: // DEPRECATED - // These function signatures are deprecated, but for some reason + // These function signatures are deprecated, but for some reason // there are classes in an external package that depend on LLVertexBuffer - + // TODO: move these classes into viewer repository friend class LLNavShapeVBOManager; friend class LLNavMeshVBOManager; - + LLVertexBuffer(U32 typemask, U32 usage) : LLVertexBuffer(typemask) {} - bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); } + bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); } public: static U64 getBytesAllocated(); - static const U32 sTypeSize[TYPE_MAX]; - static const U32 sGLMode[LLRender::NUM_MODES]; - static U32 sGLRenderBuffer; - static U32 sGLRenderIndices; - static U32 sLastMask; - static U32 sVertexCount; + static const U32 sTypeSize[TYPE_MAX]; + static const U32 sGLMode[LLRender::NUM_MODES]; + static U32 sGLRenderBuffer; + static U32 sGLRenderIndices; + static U32 sLastMask; + static U32 sVertexCount; }; #ifdef LL_PROFILER_ENABLE_RENDER_DOC diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl index 43863dd37a..d3ca3ec8c1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarEyesV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file avatarEyesV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -40,12 +40,12 @@ out vec3 vary_position; void main() { - //transform vertex - vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - vary_normal = normalize(normal_matrix * normal); + //transform vertex + vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + + vary_normal = normalize(normal_matrix * normal); - vertex_color = diffuse_color; + vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index db7597dd74..b904df3a1b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file avatarF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -37,21 +37,21 @@ in vec3 vary_position; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec4 diff = texture(diffuseMap, vary_texcoord0.xy); - - if (diff.a < minimum_alpha) - { - discard; - } - - frag_data[0] = vec4(diff.rgb, 0.0); - frag_data[1] = vec4(0,0,0,0); - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + vec4 diff = texture(diffuseMap, vary_texcoord0.xy); + + if (diff.a < minimum_alpha) + { + discard; + } + + frag_data[0] = vec4(diff.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 5cc2846156..aabbbac12a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -1,28 +1,28 @@ -/** +/** * @file avatarV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ - + uniform mat4 projection_matrix; in vec3 position; @@ -39,27 +39,27 @@ out vec3 vary_position; void main() { - vary_texcoord0 = texcoord0; - - vec4 pos; - vec3 norm; - - vec4 pos_in = vec4(position.xyz, 1.0); - mat4 trans = getSkinnedTransform(); - pos.x = dot(trans[0], pos_in); - pos.y = dot(trans[1], pos_in); - pos.z = dot(trans[2], pos_in); - pos.w = 1.0; - - norm.x = dot(trans[0].xyz, normal); - norm.y = dot(trans[1].xyz, normal); - norm.z = dot(trans[2].xyz, normal); - norm = normalize(norm); - - vary_normal = norm; - + vary_texcoord0 = texcoord0; + + vec4 pos; + vec3 norm; + + vec4 pos_in = vec4(position.xyz, 1.0); + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], pos_in); + pos.y = dot(trans[1], pos_in); + pos.z = dot(trans[2], pos_in); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, normal); + norm.y = dot(trans[1].xyz, normal); + norm.z = dot(trans[2].xyz, normal); + norm = normalize(norm); + + vary_normal = norm; + vary_position = pos.xyz; - gl_Position = projection_matrix * pos; + gl_Position = projection_matrix * pos; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 8483f257fa..2cc3085cd0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -1,30 +1,30 @@ -/** +/** * @file bumpF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ /*[EXTRA_CODE_HERE]*/ - + out vec4 frag_data[4]; uniform float minimum_alpha; @@ -40,28 +40,28 @@ in vec2 vary_texcoord0; in vec3 vary_position; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec4 col = texture(diffuseMap, vary_texcoord0.xy); - - if(col.a < minimum_alpha) - { - discard; - } - col *= vertex_color; - - vec3 norm = texture(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; + vec4 col = texture(diffuseMap, vary_texcoord0.xy); + + if(col.a < minimum_alpha) + { + discard; + } + col *= vertex_color; + + vec3 norm = texture(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0; + + vec3 tnorm = vec3(dot(norm,vary_mat0), + dot(norm,vary_mat1), + dot(norm,vary_mat2)); - vec3 tnorm = vec3(dot(norm,vary_mat0), - dot(norm,vary_mat1), - dot(norm,vary_mat2)); - - frag_data[0] = vec4(col.rgb, 0.0); - frag_data[1] = vertex_color.aaaa; // spec - //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested - vec3 nvn = normalize(tnorm); - frag_data[2] = vec4(nvn, GBUFFER_FLAG_HAS_ATMOS); + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(tnorm); + frag_data[2] = vec4(nvn, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index 74319349f6..a381392f6c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file bumpV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -48,29 +48,29 @@ uniform mat4 projection_matrix; void main() { - //transform vertex + //transform vertex #ifdef HAS_SKIN mat4 mat = getObjectSkinnedTransform(); - mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; + mat = modelview_matrix * mat; + vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz; vary_position = pos; - gl_Position = projection_matrix*vec4(pos, 1.0); + gl_Position = projection_matrix*vec4(pos, 1.0); - vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); - vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); + vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz); + vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz); #else vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); - vec3 n = normalize(normal_matrix * normal); - vec3 t = normalize(normal_matrix * tangent.xyz); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vec3 n = normalize(normal_matrix * normal); + vec3 t = normalize(normal_matrix * tangent.xyz); #endif - vec3 b = cross(n, t) * tangent.w; - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + vec3 b = cross(n, t) * tangent.w; + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); - vary_mat0 = vec3(t.x, b.x, n.x); - vary_mat1 = vec3(t.y, b.y, n.y); - vary_mat2 = vec3(t.z, b.z, n.z); - - vertex_color = diffuse_color; + vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index f6696e270c..385920f622 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1/deferred/deferredUtil.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -366,14 +366,14 @@ vec3 pbrIbl(vec3 diffuseColor, float perceptualRough) { // retrieve a scale and bias to F0. See [1], Figure 3 - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); - vec3 diffuseLight = irradiance; - vec3 specularLight = radiance; - - vec3 diffuse = diffuseLight * diffuseColor; - vec3 specular = specularLight * (specularColor * brdf.x + brdf.y); + vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); + vec3 diffuseLight = irradiance; + vec3 specularLight = radiance; - return (diffuse + specular) * ao; + vec3 diffuse = diffuseLight * diffuseColor; + vec3 specular = specularLight * (specularColor * brdf.x + brdf.y); + + return (diffuse + specular) * ao; } @@ -382,18 +382,18 @@ vec3 pbrIbl(vec3 diffuseColor, // of the shading terms, outlined in the Readme.MD Appendix. struct PBRInfo { - float NdotL; // cos angle between normal and light direction - float NdotV; // cos angle between normal and view direction - float NdotH; // cos angle between normal and half vector - float LdotH; // cos angle between light direction and half vector - float VdotH; // cos angle between view direction and half vector - float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) - float metalness; // metallic value at the surface - vec3 reflectance0; // full reflectance color (normal incidence angle) - vec3 reflectance90; // reflectance color at grazing angle - float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) - vec3 diffuseColor; // color contribution from diffuse lighting - vec3 specularColor; // color contribution from specular lighting + float NdotL; // cos angle between normal and light direction + float NdotV; // cos angle between normal and view direction + float NdotH; // cos angle between normal and half vector + float LdotH; // cos angle between light direction and half vector + float VdotH; // cos angle between view direction and half vector + float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) + float metalness; // metallic value at the surface + vec3 reflectance0; // full reflectance color (normal incidence angle) + vec3 reflectance90; // reflectance color at grazing angle + float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) + vec3 diffuseColor; // color contribution from diffuse lighting + vec3 specularColor; // color contribution from specular lighting }; // Basic Lambertian diffuse @@ -401,14 +401,14 @@ struct PBRInfo // See also [1], Equation 1 vec3 diffuse(PBRInfo pbrInputs) { - return pbrInputs.diffuseColor / M_PI; + return pbrInputs.diffuseColor / M_PI; } // The following equation models the Fresnel reflectance term of the spec equation (aka F()) // Implementation of fresnel from [4], Equation 15 vec3 specularReflection(PBRInfo pbrInputs) { - return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); + return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); } // This calculates the specular geometric attenuation (aka G()), @@ -417,13 +417,13 @@ vec3 specularReflection(PBRInfo pbrInputs) // alphaRoughness as input as originally proposed in [2]. float geometricOcclusion(PBRInfo pbrInputs) { - float NdotL = pbrInputs.NdotL; - float NdotV = pbrInputs.NdotV; - float r = pbrInputs.alphaRoughness; + float NdotL = pbrInputs.NdotL; + float NdotV = pbrInputs.NdotV; + float r = pbrInputs.alphaRoughness; - float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); - float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); - return attenuationL * attenuationV; + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + return attenuationL * attenuationV; } // The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) @@ -431,13 +431,13 @@ float geometricOcclusion(PBRInfo pbrInputs) // Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. float microfacetDistribution(PBRInfo pbrInputs) { - float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; - float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; - return roughnessSq / (M_PI * f * f); + float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; + float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; + return roughnessSq / (M_PI * f * f); } -vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, - float perceptualRoughness, +vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, + float perceptualRoughness, float metallic, vec3 n, // normal vec3 v, // surface point to camera @@ -445,53 +445,53 @@ vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor, { // make sure specular highlights from punctual lights don't fall off of polished surfaces perceptualRoughness = max(perceptualRoughness, 8.0/255.0); - - float alphaRoughness = perceptualRoughness * perceptualRoughness; - - // Compute reflectance. - float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); - - // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. - // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. - float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); - vec3 specularEnvironmentR0 = specularColor.rgb; - vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; - - vec3 h = normalize(l+v); // Half vector between both l and v - vec3 reflection = -normalize(reflect(v, n)); - reflection.y *= -1.0f; - - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float LdotH = clamp(dot(l, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); - - PBRInfo pbrInputs = PBRInfo( - NdotL, - NdotV, - NdotH, - LdotH, - VdotH, - perceptualRoughness, - metallic, - specularEnvironmentR0, - specularEnvironmentR90, - alphaRoughness, - diffuseColor, - specularColor - ); - - // Calculate the shading terms for the microfacet specular shading model - vec3 F = specularReflection(pbrInputs); - float G = geometricOcclusion(pbrInputs); - float D = microfacetDistribution(pbrInputs); - - // Calculation of analytical lighting contribution - vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); - vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); - // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) - vec3 color = NdotL * (diffuseContrib + specContrib); + + float alphaRoughness = perceptualRoughness * perceptualRoughness; + + // Compute reflectance. + float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); + + // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. + // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. + float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); + vec3 specularEnvironmentR0 = specularColor.rgb; + vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; + + vec3 h = normalize(l+v); // Half vector between both l and v + vec3 reflection = -normalize(reflect(v, n)); + reflection.y *= -1.0f; + + float NdotL = clamp(dot(n, l), 0.001, 1.0); + float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); + float NdotH = clamp(dot(n, h), 0.0, 1.0); + float LdotH = clamp(dot(l, h), 0.0, 1.0); + float VdotH = clamp(dot(v, h), 0.0, 1.0); + + PBRInfo pbrInputs = PBRInfo( + NdotL, + NdotV, + NdotH, + LdotH, + VdotH, + perceptualRoughness, + metallic, + specularEnvironmentR0, + specularEnvironmentR90, + alphaRoughness, + diffuseColor, + specularColor + ); + + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); + + // Calculation of analytical lighting contribution + vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); + vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); + // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) + vec3 color = NdotL * (diffuseContrib + specContrib); return clamp(color, vec3(0), vec3(10)); } @@ -509,9 +509,9 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v, vec3 color = vec3(0); float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0); - + color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness); - + color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir)) * sunlit * 3.0 * scol; //magic number to balance with legacy materials color += colorEmissive; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl index 82d5d363d2..1751e17814 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file diffuseAlphaMaskF.glsl * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, 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$ */ @@ -39,21 +39,21 @@ in vec2 vary_texcoord0; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color; - - if (col.a < minimum_alpha) - { - discard; - } - - frag_data[0] = vec4(col.rgb, 0.0); - frag_data[1] = vec4(0,0,0,0); // spec - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + vec4 col = texture(diffuseMap, vary_texcoord0.xy) * vertex_color; + + if (col.a < minimum_alpha) + { + discard; + } + + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); // spec + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl index 788ea633fc..f5b517a8ea 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file diffuseAlphaMaskIndexedF.glsl * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, 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$ */ @@ -37,20 +37,20 @@ in vec2 vary_texcoord0; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color; - - if (col.a < minimum_alpha) - { - discard; - } - - frag_data[0] = vec4(col.rgb, 0.0); - frag_data[1] = vec4(0,0,0,0); - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + vec4 col = diffuseLookup(vary_texcoord0.xy) * vertex_color; + + if (col.a < minimum_alpha) + { + discard; + } + + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl index 22e6d60419..89ea0c1710 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file diffuseAlphaMaskNoColorF.glsl * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2005, 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$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_data[4]; @@ -34,19 +34,19 @@ uniform sampler2D diffuseMap; in vec3 vary_normal; in vec2 vary_texcoord0; -void main() +void main() { - vec4 col = texture(diffuseMap, vary_texcoord0.xy); - - if (col.a < minimum_alpha) - { - discard; - } - - frag_data[0] = vec4(col.rgb, 0.0); - frag_data[1] = vec4(0,0,0,0); // spec - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + vec4 col = texture(diffuseMap, vary_texcoord0.xy); + + if (col.a < minimum_alpha) + { + discard; + } + + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); // spec + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 799fc62a42..7f056a51e8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -1,30 +1,30 @@ -/** +/** * @file diffuseF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ /*[EXTRA_CODE_HERE]*/ - + out vec4 frag_data[4]; uniform sampler2D diffuseMap; @@ -36,15 +36,15 @@ in vec3 vary_position; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb; - frag_data[0] = vec4(col, 0.0); - frag_data[1] = vertex_color.aaaa; // spec - //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + vec3 col = vertex_color.rgb * texture(diffuseMap, vary_texcoord0.xy).rgb; + frag_data[0] = vec4(col, 0.0); + frag_data[1] = vertex_color.aaaa; // spec + //frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl index 3362a180c6..5c73878ba9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file diffuseIndexedF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -35,17 +35,17 @@ in vec3 vary_position; void mirrorClip(vec3 pos); vec3 linear_to_srgb(vec3 c); -void main() +void main() { mirrorClip(vary_position); - vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; + vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb; - vec3 spec; - spec.rgb = vec3(vertex_color.a); + vec3 spec; + spec.rgb = vec3(vertex_color.a); - frag_data[0] = vec4(col, 0.0); - frag_data[1] = vec4(spec, vertex_color.a); // spec - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[0] = vec4(col, 0.0); + frag_data[1] = vec4(spec, vertex_color.a); // spec + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(vertex_color.a, 0, 0, 0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 64230dc680..4bd31cef9e 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file diffuseV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -59,13 +59,13 @@ void main() vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); #else vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_normal = normalize(normal_matrix * normal); #endif - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - passTextureIndex(); - vertex_color = diffuse_color; + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + + passTextureIndex(); + + vertex_color = diffuse_color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index c64f65e32c..99cb23839a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file impostorF.glsl * * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -38,20 +38,20 @@ in vec2 vary_texcoord0; vec3 linear_to_srgb(vec3 c); -void main() +void main() { - vec4 col = texture(diffuseMap, vary_texcoord0.xy); + vec4 col = texture(diffuseMap, vary_texcoord0.xy); - if (col.a < minimum_alpha) - { - discard; - } + if (col.a < minimum_alpha) + { + discard; + } - vec4 norm = texture(normalMap, vary_texcoord0.xy); - vec4 spec = texture(specularMap, vary_texcoord0.xy); + vec4 norm = texture(normalMap, vary_texcoord0.xy); + vec4 spec = texture(specularMap, vary_texcoord0.xy); - frag_data[0] = vec4(col.rgb, 0.0); - frag_data[1] = spec; - frag_data[2] = vec4(norm.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[0] = vec4(col.rgb, 0.0); + frag_data[1] = spec; + frag_data[2] = vec4(norm.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl index ddf878ae60..b6528dfcf8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file materialV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -65,67 +65,67 @@ out vec3 vary_normal; in vec2 texcoord2; out vec2 vary_texcoord2; #endif - + out vec4 vertex_color; out vec2 vary_texcoord0; void main() { #ifdef HAS_SKIN - mat4 mat = getObjectSkinnedTransform(); + mat4 mat = getObjectSkinnedTransform(); - mat = modelview_matrix * mat; + mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; + vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; - vary_position = pos; + vary_position = pos; - gl_Position = projection_matrix*vec4(pos,1.0); + gl_Position = projection_matrix*vec4(pos,1.0); #else - //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); #endif - - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - + + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + #ifdef HAS_NORMAL_MAP - vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; + vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; #endif #ifdef HAS_SPECULAR_MAP - vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy; + vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy; #endif #ifdef HAS_SKIN - vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); + vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz); #ifdef HAS_NORMAL_MAP - vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); + vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz); vary_tangent = t; vary_sign = tangent.w; vary_normal = n; #else //HAS_NORMAL_MAP - vary_normal = n; + vary_normal = n; #endif //HAS_NORMAL_MAP #else //HAS_SKIN - vec3 n = normalize(normal_matrix * normal); + vec3 n = normalize(normal_matrix * normal); #ifdef HAS_NORMAL_MAP - vec3 t = normalize(normal_matrix * tangent.xyz); + vec3 t = normalize(normal_matrix * tangent.xyz); vary_tangent = t; vary_sign = tangent.w; vary_normal = n; #else //HAS_NORMAL_MAP - vary_normal = n; + vary_normal = n; #endif //HAS_NORMAL_MAP #endif //HAS_SKIN - - vertex_color = diffuse_color; + + vertex_color = diffuse_color; #if !defined(HAS_SKIN) - vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; + vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; #endif } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl index 5e0141910b..fd020afd57 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file pbropaqueV.glsl * * $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$ */ @@ -54,7 +54,7 @@ out vec2 base_color_texcoord; out vec2 normal_texcoord; out vec2 metallic_roughness_texcoord; out vec2 emissive_texcoord; - + out vec4 vertex_color; out vec3 vary_tangent; @@ -68,18 +68,18 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh void main() { #ifdef HAS_SKIN - mat4 mat = getObjectSkinnedTransform(); + mat4 mat = getObjectSkinnedTransform(); - mat = modelview_matrix * mat; + mat = modelview_matrix * mat; - vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; + vec3 pos = (mat*vec4(position.xyz,1.0)).xyz; vary_position = pos; - gl_Position = projection_matrix*vec4(pos,1.0); + gl_Position = projection_matrix*vec4(pos,1.0); #else vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; - //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); #endif base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); @@ -88,11 +88,11 @@ void main() emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0); #ifdef HAS_SKIN - vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz; - vec3 t = (mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz; + vec3 n = (mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz; + vec3 t = (mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz; #else //HAS_SKIN - vec3 n = normal_matrix * normal; - vec3 t = normal_matrix * tangent.xyz; + vec3 n = normal_matrix * normal; + vec3 t = normal_matrix * tangent.xyz; #endif n = normalize(n); @@ -100,11 +100,11 @@ void main() vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform, texture_matrix0)); vary_sign = tangent.w; vary_normal = n; - - vertex_color = diffuse_color; + + vertex_color = diffuse_color; } -#else +#else // fullbright HUD implementation @@ -121,7 +121,7 @@ in vec2 texcoord0; out vec2 base_color_texcoord; out vec2 emissive_texcoord; - + out vec4 vertex_color; vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); @@ -129,7 +129,7 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl void main() { //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); base_color_texcoord = texture_transform(texcoord0, texture_base_color_transform, texture_matrix0); emissive_texcoord = texture_transform(texcoord0, texture_emissive_transform, texture_matrix0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 489fc26e3f..4efb9a1f53 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file class1\environment\pbrterrainV.glsl * * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2023, 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$ */ @@ -56,12 +56,12 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh void main() { //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; - vec3 n = normal_matrix * normal; + vec3 n = normal_matrix * normal; vary_vertex_normal = normal; - vec3 t = normal_matrix * tangent.xyz; + vec3 t = normal_matrix * tangent.xyz; vary_tangent = normalize(t); // *TODO: Decide if we want this. It may be better to just calculate the @@ -88,7 +88,7 @@ void main() #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0); #endif - + vec4 tc = vec4(texcoord1,0,1); vary_texcoord0.zw = tc.xy; vary_texcoord1.xy = tc.xy-vec2(2.0, 0.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 1629ed91c8..a0eb6cfbb8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -1,28 +1,28 @@ -/** +/** * @file postDeferredGammaCorrect.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_color; @@ -79,7 +79,7 @@ vec3 RRTAndODTFit(vec3 color) } -// tone mapping +// tone mapping vec3 toneMapACES_Hill(vec3 color) { color = ACESInputMat * color; @@ -103,7 +103,7 @@ vec3 toneMap(vec3 color) { #ifndef NO_POST float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - + color *= exposure * exp_scale; // mix ACES and Linear here as a compromise to avoid over-darkening legacy content @@ -117,38 +117,38 @@ vec3 toneMap(vec3 color) //================================= // borrowed noise from: -// -// By Morgan McGuire @morgan3d, http://graphicscodex.com +// +// By Morgan McGuire @morgan3d, http://graphicscodex.com // float hash(float n) { return fract(sin(n) * 1e4); } float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); } float noise(float x) { - float i = floor(x); - float f = fract(x); - float u = f * f * (3.0 - 2.0 * f); - return mix(hash(i), hash(i + 1.0), u); + float i = floor(x); + float f = fract(x); + float u = f * f * (3.0 - 2.0 * f); + return mix(hash(i), hash(i + 1.0), u); } float noise(vec2 x) { - vec2 i = floor(x); - vec2 f = fract(x); - - // Four corners in 2D of a tile - float a = hash(i); - float b = hash(i + vec2(1.0, 0.0)); - float c = hash(i + vec2(0.0, 1.0)); - float d = hash(i + vec2(1.0, 1.0)); - - // Simple 2D lerp using smoothstep envelope between the values. - // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), - // mix(c, d, smoothstep(0.0, 1.0, f.x)), - // smoothstep(0.0, 1.0, f.y))); - - // Same code, with the clamps in smoothstep and common subexpressions - // optimized away. - vec2 u = f * f * (3.0 - 2.0 * f); - return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; + vec2 i = floor(x); + vec2 f = fract(x); + + // Four corners in 2D of a tile + float a = hash(i); + float b = hash(i + vec2(1.0, 0.0)); + float c = hash(i + vec2(0.0, 1.0)); + float d = hash(i + vec2(1.0, 1.0)); + + // Simple 2D lerp using smoothstep envelope between the values. + // return vec3(mix(mix(a, b, smoothstep(0.0, 1.0, f.x)), + // mix(c, d, smoothstep(0.0, 1.0, f.x)), + // smoothstep(0.0, 1.0, f.y))); + + // Same code, with the clamps in smoothstep and common subexpressions + // optimized away. + vec2 u = f * f * (3.0 - 2.0 * f); + return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y; } //============================= @@ -171,7 +171,7 @@ vec3 legacyGamma(vec3 color) return c; } -void main() +void main() { //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB) vec4 diff = texture(diffuseRect, vary_fragcoord); diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 708acd0194..05922ecb1a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file treeF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -37,18 +37,18 @@ in vec3 vary_position; uniform float minimum_alpha; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - vec4 col = texture(diffuseMap, vary_texcoord0.xy); - if (col.a < minimum_alpha) - { - discard; - } + vec4 col = texture(diffuseMap, vary_texcoord0.xy); + if (col.a < minimum_alpha) + { + discard; + } - frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); - frag_data[1] = vec4(0,0,0,0); - vec3 nvn = normalize(vary_normal); - frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); + frag_data[0] = vec4(vertex_color.rgb*col.rgb, 0.0); + frag_data[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + frag_data[2] = vec4(nvn.xyz, GBUFFER_FLAG_HAS_ATMOS); frag_data[3] = vec4(0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index c84fccd4c6..ef5602f1e5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file treeV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -39,13 +39,13 @@ out vec3 vary_position; void main() { - //transform vertex - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz; - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - - vary_normal = normalize(normal_matrix * normal); + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + + vary_normal = normalize(normal_matrix * normal); - vertex_color = vec4(1,1,1,1); + vertex_color = vec4(1,1,1,1); } diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl index 388042e7e0..2bfd45f3b0 100644 --- a/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file normaldebugF.glsl * * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2023, 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$ */ @@ -27,7 +27,7 @@ out vec4 frag_color; in vec4 vertex_color; -void main() +void main() { - frag_color = max(vertex_color, vec4(0)); + frag_color = max(vertex_color, vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl index b198bc2485..ae726190c7 100644 --- a/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/normaldebugV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file normaldebugV.glsl * * $LicenseInfo:firstyear=2023&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2023, 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$ */ @@ -65,10 +65,10 @@ void main() vec4 world_pos = mat * vec4(position.xyz,1.0); - gl_Position = projection_matrix * world_pos; - normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat); + gl_Position = projection_matrix * world_pos; + normal_g = get_screen_normal(position.xyz, world_pos, normal.xyz, mat); #ifdef HAS_ATTRIBUTE_TANGENT - tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat); + tangent_g = get_screen_normal(position.xyz, world_pos, tangent.xyz, mat); #endif } diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl index c1ed1bfe6e..feb0947649 100644 --- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file radianceGenF.glsl * * $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$ */ - + /*[EXTRA_CODE_HERE]*/ @@ -36,7 +36,7 @@ in vec3 vary_dir; //uniform float roughness; uniform float mipLevel; -uniform int u_width; +uniform int u_width; uniform float max_probe_lod; uniform float probe_strength; @@ -74,96 +74,96 @@ const float PI = 3.1415926536; // Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/ float random(vec2 co) { - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,vec2(a,b)); - float sn= mod(dt,3.14); - return fract(sin(sn) * c); + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,vec2(a,b)); + float sn= mod(dt,3.14); + return fract(sin(sn) * c); } -vec2 hammersley2d(uint i, uint N) +vec2 hammersley2d(uint i, uint N) { - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return vec2(float(i) /float(N), rdi); + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return vec2(float(i) /float(N), rdi); } // Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf -vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) +vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) { - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 tangentX = normalize(cross(up, normal)); - vec3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 tangentX = normalize(cross(up, normal)); + vec3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); } // Normal Distribution function float D_GGX(float dotNH, float roughness) { - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom*denom); + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); } vec4 prefilterEnvMap(vec3 R) { - vec3 N = R; - vec3 V = R; - vec4 color = vec4(0.0); - float totalWeight = 0.0; - float envMapDim = float(textureSize(reflectionProbes, 0).s); + vec3 N = R; + vec3 V = R; + vec4 color = vec4(0.0); + float totalWeight = 0.0; + float envMapDim = float(textureSize(reflectionProbes, 0).s); float roughness = mipLevel/max_probe_lod; int numSamples = max(int(PROBE_FILTER_SAMPLES*roughness), 1); float numMips = max_probe_lod+1; - for(uint i = 0u; i < numSamples; i++) { - vec2 Xi = hammersley2d(i, numSamples); - vec3 H = importanceSample_GGX(Xi, roughness, N); - vec3 L = 2.0 * dot(V, H) * H - V; - float dotNL = clamp(dot(N, L), 0.0, 1.0); - if(dotNL > 0.0) { - // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ - - float dotNH = clamp(dot(N, H), 0.0, 1.0); - float dotVH = clamp(dot(V, H), 0.0, 1.0); - - // Probability Distribution Function - float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; - // Slid angle of current smple - float omegaS = 1.0 / (float(numSamples) * pdf); - // Solid angle of 1 pixel across all cube faces - float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); - // Biased (+1.0) mip level for better result - float mipLevel = roughness == 0.0 ? 0.0 : clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, max_probe_lod); - color += textureLod(reflectionProbes, vec4(L, sourceIdx), mipLevel) * dotNL; - totalWeight += dotNL; - } - } - return (color / totalWeight); + for(uint i = 0u; i < numSamples; i++) { + vec2 Xi = hammersley2d(i, numSamples); + vec3 H = importanceSample_GGX(Xi, roughness, N); + vec3 L = 2.0 * dot(V, H) * H - V; + float dotNL = clamp(dot(N, L), 0.0, 1.0); + if(dotNL > 0.0) { + // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/ + + float dotNH = clamp(dot(N, H), 0.0, 1.0); + float dotVH = clamp(dot(V, H), 0.0, 1.0); + + // Probability Distribution Function + float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001; + // Slid angle of current smple + float omegaS = 1.0 / (float(numSamples) * pdf); + // Solid angle of 1 pixel across all cube faces + float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim); + // Biased (+1.0) mip level for better result + float mipLevel = roughness == 0.0 ? 0.0 : clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, max_probe_lod); + color += textureLod(reflectionProbes, vec4(L, sourceIdx), mipLevel) * dotNL; + totalWeight += dotNL; + } + } + return (color / totalWeight); } void main() -{ - vec3 N = normalize(vary_dir); - frag_color = max(prefilterEnvMap(N), vec4(0)); +{ + vec3 N = normalize(vary_dir); + frag_color = max(prefilterEnvMap(N), vec4(0)); frag_color.a *= probe_strength; } // ============================================================================================================= diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl index 142f2a5d71..09a505d69d 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file bumpF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -34,11 +34,11 @@ in vec3 vary_position; void mirrorClip(vec3 pos); -void main() +void main() { mirrorClip(vary_position); - float tex0 = texture(texture0, vary_texcoord0.xy).a; - float tex1 = texture(texture1, vary_texcoord1.xy).a; + float tex0 = texture(texture0, vary_texcoord0.xy).a; + float tex1 = texture(texture1, vary_texcoord1.xy).a; - frag_color = max(vec4(tex0+(1.0-tex1)-0.5), vec4(0)); + frag_color = max(vec4(tex0+(1.0-tex1)-0.5), vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl index b8a02fbdec..95cdfb6fae 100644 --- a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl @@ -1,24 +1,24 @@ -/** +/** * @file bumpV.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -42,7 +42,7 @@ uniform mat4 projection_matrix; void main() { - //transform vertex + //transform vertex #ifdef HAS_SKIN mat4 mat = getObjectSkinnedTransform(); mat = modelview_matrix * mat; @@ -51,8 +51,8 @@ void main() gl_Position = projection_matrix * pos; #else vary_position = (modelview_matrix * vec4(position.xyz, 1.0)).xyz; - gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); + gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0); #endif - vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; + vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; + vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 7a1a54a77a..210ecce8db 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -1,24 +1,24 @@ -/** +/** * @file alphaF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ @@ -60,7 +60,7 @@ uniform vec2 screen_res; uniform int sun_up_factor; uniform vec4 light_position[8]; uniform vec3 light_direction[8]; -uniform vec4 light_attenuation[8]; +uniform vec4 light_attenuation[8]; uniform vec3 light_diffuse[8]; void waterClip(vec3 pos); @@ -91,15 +91,15 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float falloff_factor = (12.0 * fa) - 9.0; float inverted_la = falloff_factor / la; // Yes, it makes me want to cry as well. DJH - + vec3 col = vec3(0); - //get light vector - vec3 lv = lp.xyz-v; + //get light vector + vec3 lv = lp.xyz-v; - //get distance - float dist = length(lv); - float da = 1.0; + //get distance + float dist = length(lv); + float da = 1.0; /*if (dist > inverted_la) { @@ -112,23 +112,23 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec if (proj_tc.z < 0 || proj_tc.z > 1 || proj_tc.x < 0 - || proj_tc.x > 1 + || proj_tc.x > 1 || proj_tc.y < 0 || proj_tc.y > 1) { return col; }*/ - if (dist > 0.0 && inverted_la > 0.0) - { + if (dist > 0.0 && inverted_la > 0.0) + { dist /= inverted_la; - //normalize light vector - lv = normalize(lv); - - //distance attenuation - float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); - dist_atten *= dist_atten; + //normalize light vector + lv = normalize(lv); + + //distance attenuation + float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0); + dist_atten *= dist_atten; dist_atten *= 2.0f; if (dist_atten <= 0.0) @@ -136,20 +136,20 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec return col; } - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 - //angular attenuation - da *= dot(n, lv); + //angular attenuation + da *= dot(n, lv); da = max(0.0, da); - float lit = 0.0f; + float lit = 0.0f; float amb_da = 0.0;//ambiance; if (da > 0) { - lit = max(da * dist_atten,0.0); + lit = max(da * dist_atten,0.0); col = lit * light_col * diffuse; amb_da += (da*0.5+0.5) * ambiance; } @@ -166,12 +166,12 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec return col; } -void main() +void main() { mirrorClip(vary_position); vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - + vec4 pos = vec4(vary_position, 1.0); #ifndef IS_AVATAR_SKIN // clip against water plane unless this is a legacy avatar skin @@ -202,7 +202,7 @@ void main() float final_alpha = diffuse_srgb.a * vertex_color.a; diffuse_srgb.rgb *= vertex_color.rgb; - + // Insure we don't pollute depth with invis pixels in impostor rendering // if (final_alpha < minimum_alpha) @@ -225,7 +225,7 @@ void main() final_alpha *= vertex_color.a; if (final_alpha < minimum_alpha) - { // TODO: figure out how to get invisible faces out of + { // TODO: figure out how to get invisible faces out of // render batches without breaking glow discard; } @@ -248,11 +248,11 @@ void main() vec3 glossenv; vec3 legacyenv; sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0, true, amblit_linear); - + float da = dot(norm.xyz, light_dir.xyz); da = clamp(da, -1.0, 1.0); - + float final_da = da; final_da = clamp(final_da, 0.0f, 1.0f); @@ -269,7 +269,7 @@ void main() color.rgb *= diffuse_linear.rgb; vec4 light = vec4(0,0,0,0); - + #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diffuse_linear.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w); LIGHT_LOOP(1) diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl index c382a9fbc0..03dc3d7113 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file fullbrightShinyF.glsl * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ - + /*[EXTRA_CODE_HERE]*/ out vec4 frag_color; @@ -59,16 +59,16 @@ void main() { mirrorClip(vary_position); #ifdef HAS_DIFFUSE_LOOKUP - vec4 color = diffuseLookup(vary_texcoord0.xy); + vec4 color = diffuseLookup(vary_texcoord0.xy); #else - vec4 color = texture(diffuseMap, vary_texcoord0.xy); + vec4 color = texture(diffuseMap, vary_texcoord0.xy); #endif - - color.rgb *= vertex_color.rgb; - // SL-9632 HUDs are affected by Atmosphere + color.rgb *= vertex_color.rgb; + + // SL-9632 HUDs are affected by Atmosphere #ifndef IS_HUD - + vec3 sunlit; vec3 amblit; vec3 additive; @@ -90,8 +90,8 @@ void main() applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity); #endif - color.a = 1.0; + color.a = 1.0; - frag_color = max(color, vec4(0)); + frag_color = max(color, vec4(0)); } diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 2a20eb79d2..d3e19cf4a8 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -100,7 +100,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float falloff_factor = (12.0 * fa) - 9.0; float inverted_la = falloff_factor / la; // Yes, it makes me want to cry as well. DJH - + vec3 col = vec3(0); //get light vector @@ -220,19 +220,19 @@ in vec2 vary_texcoord0; vec3 getNormal(inout float glossiness) { #ifdef HAS_NORMAL_MAP - vec4 vNt = texture(bumpMap, vary_texcoord1.xy); + vec4 vNt = texture(bumpMap, vary_texcoord1.xy); glossiness *= vNt.a; - vNt.xyz = vNt.xyz * 2 - 1; + vNt.xyz = vNt.xyz * 2 - 1; float sign = vary_sign; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; - + vec3 vB = sign * cross(vN, vT); vec3 tnorm = normalize( vNt.x * vT + vNt.y * vB + vNt.z * vN ); - return tnorm; + return tnorm; #else - return normalize(vary_normal); + return normalize(vary_normal); #endif } @@ -269,9 +269,9 @@ void waterClip() float getEmissive(vec4 diffcol) { #if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE) - return emissive_brightness; + return emissive_brightness; #else - return max(diffcol.a, emissive_brightness); + return max(diffcol.a, emissive_brightness); #endif } @@ -295,7 +295,7 @@ void main() // diffcol == diffuse map combined with vertex color vec4 diffcol = texture(diffuseMap, vary_texcoord0.xy); - diffcol.rgb *= vertex_color.rgb; + diffcol.rgb *= vertex_color.rgb; alphaMask(diffcol.a); // spec == specular map combined with specular color @@ -328,7 +328,7 @@ void main() vec3 additive; vec3 atten; calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten); - + vec3 sunlit_linear = srgb_to_linear(sunlit); vec3 amblit_linear = amblit; @@ -336,7 +336,7 @@ void main() vec3 glossenv; vec3 legacyenv; sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env, true, amblit_linear); - + color = ambenv; float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0); @@ -408,7 +408,7 @@ void main() frag_color = max(vec4(color, al), vec4(0)); -#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer +#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer // deferred path // See: C++: addDeferredAttachment(), shader: softenLightF.glsl float flag = GBUFFER_FLAG_HAS_ATMOS; diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index ef086fc3be..728d70ebb2 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -4,25 +4,25 @@ * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2007, 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$ */ - + out vec4 frag_color; uniform sampler2D diffuseMap; @@ -57,27 +57,27 @@ in vec3 vary_position; vec4 applyWaterFogViewLinearNoClip(vec3 pos, vec4 color); void mirrorClip(vec3 position); -void main() +void main() { - mirrorClip(vary_position); - vec4 color; + mirrorClip(vary_position); + vec4 color; //get detail normals - vec3 wave1 = texture(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; - vec3 wave2 = texture(bumpMap, littleWave.xy).xyz*2.0-1.0; - vec3 wave3 = texture(bumpMap, littleWave.zw).xyz*2.0-1.0; - vec3 wavef = normalize(wave1+wave2+wave3); - - //figure out distortion vector (ripply) - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - distort = distort+wavef.xy*refScale; + vec3 wave1 = texture(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0; + vec3 wave2 = texture(bumpMap, littleWave.xy).xyz*2.0-1.0; + vec3 wave3 = texture(bumpMap, littleWave.zw).xyz*2.0-1.0; + vec3 wavef = normalize(wave1+wave2+wave3); + + //figure out distortion vector (ripply) + vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + distort = distort+wavef.xy*refScale; #ifdef TRANSPARENT_WATER - vec4 fb = texture(screenTex, distort); + vec4 fb = texture(screenTex, distort); #else vec4 fb = vec4(waterFogColorLinear, 0.0); #endif - + fb = applyWaterFogViewLinearNoClip(vary_position, fb); frag_color = max(fb, vec4(0)); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index b2a81aa025..a5592188a9 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -1,28 +1,28 @@ -/** +/** * @file waterF.glsl * * $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$ */ - + // class3/environment/waterF.glsl out vec4 frag_color; @@ -129,7 +129,7 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, vec3 getPositionWithNDC(vec3 ndc); -void main() +void main() { mirrorClip(vary_position); vN = vary_normal; @@ -160,7 +160,7 @@ void main() vec3 wave3 = BlendNormal(wave3_a, wave3_b); vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - + //wave1 = transform_normal(wave1); //wave2 = transform_normal(wave2); //wave3 = transform_normal(wave3); @@ -171,7 +171,7 @@ void main() vec3 up = transform_normal(vec3(0,0,1)); float vdu = -dot(viewVec, up)*2; - + vec3 wave_ibl = wavef; wave_ibl.z *= 2.0; wave_ibl = transform_normal(normalize(wave_ibl)); @@ -185,13 +185,13 @@ void main() //wavef = vec3(0, 0, 1); wavef = transform_normal(wavef); - - float dist2 = dist; - dist = max(dist, 5.0); - - float dmod = sqrt(dist); - - //figure out distortion vector (ripply) + + float dist2 = dist; + dist = max(dist, 5.0); + + float dmod = sqrt(dist); + + //figure out distortion vector (ripply) vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0); distort2 = clamp(distort2, vec2(0), vec2(0.999)); @@ -235,7 +235,7 @@ void main() float metallic = 0.0; float perceptualRoughness = 0.05; float gloss = 1.0 - perceptualRoughness; - + vec3 irradiance = vec3(0); vec3 radiance = vec3(0); sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit); @@ -251,7 +251,7 @@ void main() vec3 colorEmissive = vec3(0); float ao = 1.0; vec3 light_dir = transform_normal(lightDir); - + perceptualRoughness = 0.0; metallic = 1.0; @@ -284,7 +284,7 @@ void main() color = ((1.0 - f) * color) + fb.rgb; float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05); - + frag_color = max(vec4(color, spec), vec4(0)); } diff --git a/indra/newview/gltf/asset.h b/indra/newview/gltf/asset.h index 6e576a1ffe..5ceac74a8a 100644 --- a/indra/newview/gltf/asset.h +++ b/indra/newview/gltf/asset.h @@ -33,7 +33,7 @@ #include "primitive.h" #include "animation.h" -extern F32SecondsImplicit gFrameTimeSeconds; +extern F32SecondsImplicit gFrameTimeSeconds; // LL GLTF Implementation namespace LL @@ -52,7 +52,7 @@ namespace LL std::string mName; const Material& operator=(const tinygltf::Material& src); - + void allocateGLResources(Asset& asset); }; @@ -64,7 +64,7 @@ namespace LL std::string mName; const Mesh& operator=(const tinygltf::Mesh& src); - + void allocateGLResources(Asset& asset); }; @@ -85,7 +85,7 @@ namespace LL // if true, translation/rotation/scale are valid and up to date bool mTRSValid = false; - + bool mNeedsApplyMatrix = false; std::vector mChildren; @@ -146,7 +146,7 @@ namespace LL std::string mName; const Scene& operator=(const tinygltf::Scene& src); - + void updateTransforms(Asset& asset); void updateRenderTransforms(Asset& asset, const LLMatrix4a& modelview); }; @@ -229,7 +229,7 @@ namespace LL // prepare the asset for rendering void allocateGLResources(const std::string& filename, const tinygltf::Model& model); - + // Called periodically (typically once per frame) // Any ongoing work (such as animations) should be handled here // NOT guaranteed to be called every frame @@ -242,7 +242,7 @@ namespace LL // update node render transforms void updateRenderTransforms(const LLMatrix4a& modelview); - + void render(bool opaque, bool rigged = false); void renderOpaque(); void renderTransparent(); @@ -256,9 +256,9 @@ namespace LL LLVector4a* tangent = nullptr, // return the surface tangent at the intersection point S32* primitive_hitp = nullptr // return the index of the primitive that was hit ); - + const Asset& operator=(const tinygltf::Model& src); - + }; } } diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 4e3439ea5c..7003eab6d0 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -129,7 +129,7 @@ void GLTFSceneManager::update() Asset* asset = mObjects[i]->mGLTFAsset; asset->update(); - + } } @@ -137,9 +137,9 @@ void GLTFSceneManager::render(bool opaque, bool rigged) { // for debugging, just render the whole scene as opaque // by traversing the whole scenegraph - // Assumes camera transform is already set and + // Assumes camera transform is already set and // appropriate shader is already bound - + gGL.matrixMode(LLRender::MM_MODELVIEW); for (U32 i = 0; i < mObjects.size(); ++i) @@ -281,10 +281,10 @@ LLDrawable* GLTFSceneManager::lineSegmentIntersect(const LLVector4a& start, cons LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent) // return the surface tangent at the intersection point + LLVector4a* tangent) // return the surface tangent at the intersection point { LLDrawable* drawable = nullptr; - + LLVector4a local_end = end; LLVector4a position; @@ -314,8 +314,8 @@ LLDrawable* GLTFSceneManager::lineSegmentIntersect(const LLVector4a& start, cons void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size); -extern LLVector4a gDebugRaycastStart; -extern LLVector4a gDebugRaycastEnd; +extern LLVector4a gDebugRaycastStart; +extern LLVector4a gDebugRaycastEnd; void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree); @@ -336,7 +336,7 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) agent_to_asset.affineTransform(gDebugRaycastStart, start); agent_to_asset.affineTransform(gDebugRaycastEnd, end); - + for (auto& node : asset->mNodes) { Mesh& mesh = asset->mMeshes[node.mMesh]; @@ -344,7 +344,7 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) if (node.mMesh != INVALID_INDEX) { gGL.loadMatrix((F32*)node.mRenderMatrix.mMatrix); - + // draw bounding box of mesh primitives if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { @@ -549,7 +549,7 @@ void GLTFSceneManager::renderDebug() gGL.loadMatrix((F32*) node->mRenderMatrix.mMatrix); - + auto* listener = (LLVolumeOctreeListener*) primitive->mOctree->getListener(0); drawBoxOutline(listener->mBounds[0], listener->mBounds[1]); diff --git a/indra/newview/gltfscenemanager.h b/indra/newview/gltfscenemanager.h index d286f335e4..7966606dfa 100644 --- a/indra/newview/gltfscenemanager.h +++ b/indra/newview/gltfscenemanager.h @@ -36,7 +36,7 @@ namespace LL public: ~GLTFSceneManager(); // load GLTF file from disk - + void load(); // open filepicker to choose asset void load(const std::string& filename); // load asset from filename @@ -55,7 +55,7 @@ namespace LL LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent); // return the surface tangent at the intersection point + LLVector4a* tangent); // return the surface tangent at the intersection point bool lineSegmentIntersect(LLVOVolume* obj, GLTF::Asset* asset, const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, S32* face_hitp, S32* primitive_hitp, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent); diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp index 0717d92ea7..4ac4d2136f 100644 --- a/indra/newview/llagentbenefits.cpp +++ b/indra/newview/llagentbenefits.cpp @@ -28,14 +28,14 @@ #include "llviewertexture.h" LLAgentBenefits::LLAgentBenefits(): - m_initalized(false), - m_animated_object_limit(-1), - m_animation_upload_cost(-1), - m_attachment_limit(-1), - m_group_membership_limit(-1), - m_picks_limit(-1), - m_sound_upload_cost(-1), - m_texture_upload_cost(-1) + m_initalized(false), + m_animated_object_limit(-1), + m_animation_upload_cost(-1), + m_attachment_limit(-1), + m_group_membership_limit(-1), + m_picks_limit(-1), + m_sound_upload_cost(-1), + m_texture_upload_cost(-1) { } @@ -48,53 +48,53 @@ LLAgentBenefits::~LLAgentBenefits() // the viewer cares about are integer. bool get_required_S32(const LLSD& sd, const LLSD::String& key, S32& value) { - value = -1; - if (sd.has(key)) - { - value = sd[key].asInteger(); - return true; - } - - LL_WARNS("Benefits") << "Missing required benefit field " << key << LL_ENDL; - return false; + value = -1; + if (sd.has(key)) + { + value = sd[key].asInteger(); + return true; + } + + LL_WARNS("Benefits") << "Missing required benefit field " << key << LL_ENDL; + return false; } bool LLAgentBenefits::init(const LLSD& benefits_sd) { - LL_DEBUGS("Benefits") << "initializing benefits from " << benefits_sd << LL_ENDL; - - if (!get_required_S32(benefits_sd, "animated_object_limit", m_animated_object_limit)) - { - return false; - } - if (!get_required_S32(benefits_sd, "animation_upload_cost", m_animation_upload_cost)) - { - return false; - } - if (!get_required_S32(benefits_sd, "attachment_limit", m_attachment_limit)) - { - return false; - } - if (!get_required_S32(benefits_sd, "create_group_cost", m_create_group_cost)) - { - return false; - } - if (!get_required_S32(benefits_sd, "group_membership_limit", m_group_membership_limit)) - { - return false; - } - if (!get_required_S32(benefits_sd, "picks_limit", m_picks_limit)) - { - return false; - } - if (!get_required_S32(benefits_sd, "sound_upload_cost", m_sound_upload_cost)) - { - return false; - } - if (!get_required_S32(benefits_sd, "texture_upload_cost", m_texture_upload_cost)) - { - return false; - } + LL_DEBUGS("Benefits") << "initializing benefits from " << benefits_sd << LL_ENDL; + + if (!get_required_S32(benefits_sd, "animated_object_limit", m_animated_object_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "animation_upload_cost", m_animation_upload_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "attachment_limit", m_attachment_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "create_group_cost", m_create_group_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "group_membership_limit", m_group_membership_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "picks_limit", m_picks_limit)) + { + return false; + } + if (!get_required_S32(benefits_sd, "sound_upload_cost", m_sound_upload_cost)) + { + return false; + } + if (!get_required_S32(benefits_sd, "texture_upload_cost", m_texture_upload_cost)) + { + return false; + } if (benefits_sd.has("large_texture_upload_cost")) { @@ -116,49 +116,49 @@ bool LLAgentBenefits::init(const LLSD& benefits_sd) m_2k_texture_upload_cost.push_back(m_texture_upload_cost); } - // FIXME PREMIUM - either use this field or get rid of it - m_initalized = true; - return true; + // FIXME PREMIUM - either use this field or get rid of it + m_initalized = true; + return true; } S32 LLAgentBenefits::getAnimatedObjectLimit() const { - return m_animated_object_limit; + return m_animated_object_limit; } S32 LLAgentBenefits::getAnimationUploadCost() const { - return m_animation_upload_cost; + return m_animation_upload_cost; } S32 LLAgentBenefits::getAttachmentLimit() const { - return m_attachment_limit; + return m_attachment_limit; } S32 LLAgentBenefits::getCreateGroupCost() const { - return m_create_group_cost; + return m_create_group_cost; } S32 LLAgentBenefits::getGroupMembershipLimit() const { - return m_group_membership_limit; + return m_group_membership_limit; } S32 LLAgentBenefits::getPicksLimit() const { - return m_picks_limit; + return m_picks_limit; } S32 LLAgentBenefits::getSoundUploadCost() const { - return m_sound_upload_cost; + return m_sound_upload_cost; } S32 LLAgentBenefits::getTextureUploadCost() const { - return m_texture_upload_cost; + return m_texture_upload_cost; } S32 LLAgentBenefits::getTextureUploadCost(const LLViewerTexture* tex) const @@ -206,23 +206,23 @@ S32 LLAgentBenefits::get2KTextureUploadCost(S32 area) const bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const { - bool succ = false; - if (asset_type == LLAssetType::AT_TEXTURE) - { + bool succ = false; + if (asset_type == LLAssetType::AT_TEXTURE) + { cost = getTextureUploadCost(); - succ = true; - } - else if (asset_type == LLAssetType::AT_SOUND) - { - cost = getSoundUploadCost(); - succ = true; - } - else if (asset_type == LLAssetType::AT_ANIMATION) - { - cost = getAnimationUploadCost(); - succ = true; - } - return succ; + succ = true; + } + else if (asset_type == LLAssetType::AT_SOUND) + { + cost = getSoundUploadCost(); + succ = true; + } + else if (asset_type == LLAssetType::AT_ANIMATION) + { + cost = getAnimationUploadCost(); + succ = true; + } + return succ; } LLAgentBenefitsMgr::LLAgentBenefitsMgr() @@ -236,65 +236,65 @@ LLAgentBenefitsMgr::~LLAgentBenefitsMgr() // static const LLAgentBenefits& LLAgentBenefitsMgr::current() { - return instance().mCurrent; + return instance().mCurrent; } // static const LLAgentBenefits& LLAgentBenefitsMgr::get(const std::string& package) { - if (instance().mPackageMap.find(package) != instance().mPackageMap.end()) - { - return instance().mPackageMap[package]; - } - else - { - return instance().mDefault; - } + if (instance().mPackageMap.find(package) != instance().mPackageMap.end()) + { + return instance().mPackageMap[package]; + } + else + { + return instance().mDefault; + } } // static bool LLAgentBenefitsMgr::init(const std::string& package, const LLSD& benefits_sd) { - LLAgentBenefits benefits; - if (!benefits.init(benefits_sd)) - { - LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; - return false; - } - else - { - instance().mPackageMap[package] = benefits; - } - return true; + LLAgentBenefits benefits; + if (!benefits.init(benefits_sd)) + { + LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; + return false; + } + else + { + instance().mPackageMap[package] = benefits; + } + return true; } // static bool LLAgentBenefitsMgr::initCurrent(const std::string& package, const LLSD& benefits_sd) { - LLAgentBenefits benefits; - if (!benefits.init(benefits_sd)) - { - LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; - return false; - } - else - { - instance().mCurrent = benefits; - instance().mCurrentName = package; - } - return true; + LLAgentBenefits benefits; + if (!benefits.init(benefits_sd)) + { + LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL; + return false; + } + else + { + instance().mCurrent = benefits; + instance().mCurrentName = package; + } + return true; } // static bool LLAgentBenefitsMgr::has(const std::string& package) { - return instance().mPackageMap.find(package) != instance().mPackageMap.end(); + return instance().mPackageMap.find(package) != instance().mPackageMap.end(); } //static bool LLAgentBenefitsMgr::isCurrent(const std::string& package) { - return instance().mCurrentName == package; + return instance().mCurrentName == package; } diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h index 962d0f9371..ff23241aa9 100644 --- a/indra/newview/llagentbenefits.h +++ b/indra/newview/llagentbenefits.h @@ -38,59 +38,59 @@ class LLAgentBenefits public: static constexpr S32 MIN_2K_TEXTURE_AREA = 1024 * 1024 + 1; - LLAgentBenefits(); - ~LLAgentBenefits(); - LOG_CLASS(LLAgentBenefits); + LLAgentBenefits(); + ~LLAgentBenefits(); + LOG_CLASS(LLAgentBenefits); - bool init(const LLSD& benefits_sd); + bool init(const LLSD& benefits_sd); - S32 getAnimatedObjectLimit() const; - S32 getAnimationUploadCost() const; - S32 getAttachmentLimit() const; - S32 getCreateGroupCost() const; - S32 getGroupMembershipLimit() const; - S32 getPicksLimit() const; - S32 getSoundUploadCost() const; - S32 getTextureUploadCost() const; + S32 getAnimatedObjectLimit() const; + S32 getAnimationUploadCost() const; + S32 getAttachmentLimit() const; + S32 getCreateGroupCost() const; + S32 getGroupMembershipLimit() const; + S32 getPicksLimit() const; + S32 getSoundUploadCost() const; + S32 getTextureUploadCost() const; S32 getTextureUploadCost(const LLViewerTexture* tex) const; S32 getTextureUploadCost(const LLImageBase* tex) const; S32 get2KTextureUploadCost(S32 area) const; - bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const; - + bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const; + private: - S32 m_animated_object_limit; - S32 m_animation_upload_cost; - S32 m_attachment_limit; - S32 m_create_group_cost; - S32 m_group_membership_limit; - S32 m_picks_limit; - S32 m_sound_upload_cost; - S32 m_texture_upload_cost; + S32 m_animated_object_limit; + S32 m_animation_upload_cost; + S32 m_attachment_limit; + S32 m_create_group_cost; + S32 m_group_membership_limit; + S32 m_picks_limit; + S32 m_sound_upload_cost; + S32 m_texture_upload_cost; std::vector m_2k_texture_upload_cost; - bool m_initalized; + bool m_initalized; }; -class LLAgentBenefitsMgr: public LLSingleton +class LLAgentBenefitsMgr: public LLSingleton { - LLSINGLETON(LLAgentBenefitsMgr); - ~LLAgentBenefitsMgr(); - LOG_CLASS(LLAgentBenefitsMgr); + LLSINGLETON(LLAgentBenefitsMgr); + ~LLAgentBenefitsMgr(); + LOG_CLASS(LLAgentBenefitsMgr); public: - static const LLAgentBenefits& current(); - static const LLAgentBenefits& get(const std::string& package); - static bool init(const std::string& package, const LLSD& benefits_sd); - static bool initCurrent(const std::string& package, const LLSD& benefits_sd); - static bool has(const std::string& package); - static bool isCurrent(const std::string& package); + static const LLAgentBenefits& current(); + static const LLAgentBenefits& get(const std::string& package); + static bool init(const std::string& package, const LLSD& benefits_sd); + static bool initCurrent(const std::string& package, const LLSD& benefits_sd); + static bool has(const std::string& package); + static bool isCurrent(const std::string& package); private: - std::string mCurrentName; - LLAgentBenefits mCurrent; - LLAgentBenefits mDefault; - std::map mPackageMap; + std::string mCurrentName; + LLAgentBenefits mCurrent; + LLAgentBenefits mDefault; + std::map mPackageMap; }; diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 1764acfc67..70ff7f1941 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -1,31 +1,31 @@ -/** +/** * @file llagentcamera.cpp * @brief LLAgent class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h" -#include "llagentcamera.h" +#include "llagentcamera.h" #include "pipeline.h" @@ -60,8 +60,8 @@ const F32 MIN_ZOOM_FRACTION = 0.25f; const F32 INITIAL_ZOOM_FRACTION = 1.f; const F32 MAX_ZOOM_FRACTION = 8.f; -const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds -const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds +const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds +const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f; const F32 CAMERA_LAG_HALF_LIFE = 0.25f; @@ -102,8 +102,8 @@ const F32 OBJECT_EXTENTS_PADDING = 0.5f; static bool isDisableCameraConstraints() { - static LLCachedControl sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false); - return sDisableCameraConstraints; + static LLCachedControl sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false); + return sDisableCameraConstraints; } // The agent instance. @@ -113,84 +113,84 @@ LLAgentCamera gAgentCamera; // LLAgentCamera() //----------------------------------------------------------------------------- LLAgentCamera::LLAgentCamera() : - mInitialized(false), - - mDrawDistance( DEFAULT_FAR_PLANE ), - - mLookAt(NULL), - mPointAt(NULL), - - mHUDTargetZoom(1.f), - mHUDCurZoom(1.f), - - mForceMouselook(FALSE), - - mCameraMode( CAMERA_MODE_THIRD_PERSON ), - mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), - - mCameraPreset(CAMERA_PRESET_REAR_VIEW), - - mCameraAnimating( FALSE ), - mAnimationCameraStartGlobal(), - mAnimationFocusStartGlobal(), - mAnimationTimer(), - mAnimationDuration(0.33f), - - mCameraFOVZoomFactor(0.f), - mCameraCurrentFOVZoomFactor(0.f), - mCameraFocusOffset(), - - mCameraCollidePlane(), - - mCurrentCameraDistance(2.f), // meters, set in init() - mTargetCameraDistance(2.f), - mCameraZoomFraction(1.f), // deprecated - mThirdPersonHeadOffset(0.f, 0.f, 1.f), - mSitCameraEnabled(FALSE), - mCameraSmoothingLastPositionGlobal(), - mCameraSmoothingLastPositionAgent(), - mCameraSmoothingStop(false), - - mCameraUpVector(LLVector3::z_axis), // default is straight up - - mFocusOnAvatar(TRUE), - mAllowChangeToFollow(FALSE), - mFocusGlobal(), - mFocusTargetGlobal(), - mFocusObject(NULL), - mFocusObjectDist(0.f), - mFocusObjectOffset(), - mTrackFocusObject(TRUE), - - mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed - mWalkKey(0), // like AtKey, but causes less forward thrust - mLeftKey(0), - mUpKey(0), - mYawKey(0.f), - mPitchKey(0.f), - - mOrbitLeftKey(0.f), - mOrbitRightKey(0.f), - mOrbitUpKey(0.f), - mOrbitDownKey(0.f), - mOrbitInKey(0.f), - mOrbitOutKey(0.f), - - mPanUpKey(0.f), - mPanDownKey(0.f), - mPanLeftKey(0.f), - mPanRightKey(0.f), - mPanInKey(0.f), - mPanOutKey(0.f) -{ - mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); - - clearGeneralKeys(); - clearOrbitKeys(); - clearPanKeys(); - - resetPanDiff(); - resetOrbitDiff(); + mInitialized(false), + + mDrawDistance( DEFAULT_FAR_PLANE ), + + mLookAt(NULL), + mPointAt(NULL), + + mHUDTargetZoom(1.f), + mHUDCurZoom(1.f), + + mForceMouselook(FALSE), + + mCameraMode( CAMERA_MODE_THIRD_PERSON ), + mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), + + mCameraPreset(CAMERA_PRESET_REAR_VIEW), + + mCameraAnimating( FALSE ), + mAnimationCameraStartGlobal(), + mAnimationFocusStartGlobal(), + mAnimationTimer(), + mAnimationDuration(0.33f), + + mCameraFOVZoomFactor(0.f), + mCameraCurrentFOVZoomFactor(0.f), + mCameraFocusOffset(), + + mCameraCollidePlane(), + + mCurrentCameraDistance(2.f), // meters, set in init() + mTargetCameraDistance(2.f), + mCameraZoomFraction(1.f), // deprecated + mThirdPersonHeadOffset(0.f, 0.f, 1.f), + mSitCameraEnabled(FALSE), + mCameraSmoothingLastPositionGlobal(), + mCameraSmoothingLastPositionAgent(), + mCameraSmoothingStop(false), + + mCameraUpVector(LLVector3::z_axis), // default is straight up + + mFocusOnAvatar(TRUE), + mAllowChangeToFollow(FALSE), + mFocusGlobal(), + mFocusTargetGlobal(), + mFocusObject(NULL), + mFocusObjectDist(0.f), + mFocusObjectOffset(), + mTrackFocusObject(TRUE), + + mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed + mWalkKey(0), // like AtKey, but causes less forward thrust + mLeftKey(0), + mUpKey(0), + mYawKey(0.f), + mPitchKey(0.f), + + mOrbitLeftKey(0.f), + mOrbitRightKey(0.f), + mOrbitUpKey(0.f), + mOrbitDownKey(0.f), + mOrbitInKey(0.f), + mOrbitOutKey(0.f), + + mPanUpKey(0.f), + mPanDownKey(0.f), + mPanLeftKey(0.f), + mPanRightKey(0.f), + mPanInKey(0.f), + mPanOutKey(0.f) +{ + mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); + + clearGeneralKeys(); + clearOrbitKeys(); + clearPanKeys(); + + resetPanDiff(); + resetOrbitDiff(); } // Requires gSavedSettings to be initialized. @@ -199,28 +199,28 @@ LLAgentCamera::LLAgentCamera() : //----------------------------------------------------------------------------- void LLAgentCamera::init() { - // *Note: this is where LLViewerCamera::getInstance() used to be constructed. + // *Note: this is where LLViewerCamera::getInstance() used to be constructed. - mDrawDistance = gSavedSettings.getF32("RenderFarClip"); + mDrawDistance = gSavedSettings.getF32("RenderFarClip"); - LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); - // Leave at 0.1 meters until we have real near clip management - LLViewerCamera::getInstance()->setNear(0.1f); - LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h - LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() ); // default, overridden in LLViewerWindow::reshape - LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape + LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW); + // Leave at 0.1 meters until we have real near clip management + LLViewerCamera::getInstance()->setNear(0.1f); + LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h + LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() ); // default, overridden in LLViewerWindow::reshape + LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape - mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); - - mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); + mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); - mCameraCollidePlane.clearVec(); - mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); - mTargetCameraDistance = mCurrentCameraDistance; - mCameraZoomFraction = 1.f; - mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPresetType"); - mInitialized = true; + mCameraCollidePlane.clearVec(); + mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); + mTargetCameraDistance = mCurrentCameraDistance; + mCameraZoomFraction = 1.f; + mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + + mInitialized = true; } //----------------------------------------------------------------------------- @@ -228,40 +228,40 @@ void LLAgentCamera::init() //----------------------------------------------------------------------------- void LLAgentCamera::cleanup() { - setSitCamera(LLUUID::null); + setSitCamera(LLUUID::null); - if(mLookAt) - { - mLookAt->markDead() ; - mLookAt = NULL; - } - if(mPointAt) - { - mPointAt->markDead() ; - mPointAt = NULL; - } - setFocusObject(NULL); + if(mLookAt) + { + mLookAt->markDead() ; + mLookAt = NULL; + } + if(mPointAt) + { + mPointAt->markDead() ; + mPointAt = NULL; + } + setFocusObject(NULL); } void LLAgentCamera::setAvatarObject(LLVOAvatarSelf* avatar) { - if (!mLookAt) - { - mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); - } - if (!mPointAt) - { - mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); - } - - if (!mLookAt.isNull()) - { - mLookAt->setSourceObject(avatar); - } - if (!mPointAt.isNull()) - { - mPointAt->setSourceObject(avatar); - } + if (!mLookAt) + { + mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); + } + if (!mPointAt) + { + mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); + } + + if (!mLookAt.isNull()) + { + mLookAt->setSourceObject(avatar); + } + if (!mPointAt.isNull()) + { + mPointAt->setSourceObject(avatar); + } } //----------------------------------------------------------------------------- @@ -269,9 +269,9 @@ void LLAgentCamera::setAvatarObject(LLVOAvatarSelf* avatar) //----------------------------------------------------------------------------- LLAgentCamera::~LLAgentCamera() { - cleanup(); + cleanup(); - // *Note: this is where LLViewerCamera::getInstance() used to be deleted. + // *Note: this is where LLViewerCamera::getInstance() used to be deleted. } // Change camera back to third person, stop the autopilot, @@ -281,80 +281,80 @@ LLAgentCamera::~LLAgentCamera() //----------------------------------------------------------------------------- void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) { - if (gDisconnected) - { - return; - } - - if (gAgent.getAutoPilot()) - { - gAgent.stopAutoPilot(TRUE); - } - - LLSelectMgr::getInstance()->unhighlightAll(); - - // By popular request, keep land selection while walking around. JC - // LLViewerParcelMgr::getInstance()->deselectLand(); - - // force deselect when walking and attachment is selected - // this is so people don't wig out when their avatar moves without animating - if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - if (gMenuHolder != NULL) - { - // Hide all popup menus - gMenuHolder->hideMenus(); - } - - if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) - { - changeCameraToDefault(); - - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - handle_toggle_flycam(); - } - - // reset avatar mode from eventual residual motion - if (LLToolMgr::getInstance()->inBuildMode()) - { - LLViewerJoystick::getInstance()->moveAvatar(true); - } - - //Camera Tool is needed for Free Camera Control Mode - if (!LLFloaterCamera::inFreeCameraMode()) - { - LLFloaterReg::hideInstance("build"); - - // Switch back to basic toolset - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - gViewerWindow->showCursor(); - } - - - if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) - { - if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) - { - // leaving mouse-steer mode - LLVector3 agent_at_axis = gAgent.getAtAxis(); - agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); - agent_at_axis.normalize(); - gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); - } - - setFocusOnAvatar(TRUE, ANIMATE); - - mCameraFOVZoomFactor = 0.f; - } - resetPanDiff(); - resetOrbitDiff(); - mHUDTargetZoom = 1.f; + if (gDisconnected) + { + return; + } + + if (gAgent.getAutoPilot()) + { + gAgent.stopAutoPilot(TRUE); + } + + LLSelectMgr::getInstance()->unhighlightAll(); + + // By popular request, keep land selection while walking around. JC + // LLViewerParcelMgr::getInstance()->deselectLand(); + + // force deselect when walking and attachment is selected + // this is so people don't wig out when their avatar moves without animating + if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) + { + LLSelectMgr::getInstance()->deselectAll(); + } + + if (gMenuHolder != NULL) + { + // Hide all popup menus + gMenuHolder->hideMenus(); + } + + if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) + { + changeCameraToDefault(); + + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + handle_toggle_flycam(); + } + + // reset avatar mode from eventual residual motion + if (LLToolMgr::getInstance()->inBuildMode()) + { + LLViewerJoystick::getInstance()->moveAvatar(true); + } + + //Camera Tool is needed for Free Camera Control Mode + if (!LLFloaterCamera::inFreeCameraMode()) + { + LLFloaterReg::hideInstance("build"); + + // Switch back to basic toolset + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + gViewerWindow->showCursor(); + } + + + if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) + { + if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) + { + // leaving mouse-steer mode + LLVector3 agent_at_axis = gAgent.getAtAxis(); + agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); + agent_at_axis.normalize(); + gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); + } + + setFocusOnAvatar(TRUE, ANIMATE); + + mCameraFOVZoomFactor = 0.f; + } + resetPanDiff(); + resetOrbitDiff(); + mHUDTargetZoom = 1.f; if (LLSelectMgr::getInstance()->mAllowSelectAvatar) { @@ -375,14 +375,14 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) //----------------------------------------------------------------------------- void LLAgentCamera::unlockView() { - if (getFocusOnAvatar()) - { - if (isAgentAvatarValid()) - { - setFocusGlobal(LLVector3d::zero, gAgentAvatarp->mID); - } - setFocusOnAvatar(FALSE, FALSE); // no animation - } + if (getFocusOnAvatar()) + { + if (isAgentAvatarValid()) + { + setFocusGlobal(LLVector3d::zero, gAgentAvatarp->mID); + } + setFocusOnAvatar(FALSE, FALSE); // no animation + } } //----------------------------------------------------------------------------- @@ -390,10 +390,10 @@ void LLAgentCamera::unlockView() //----------------------------------------------------------------------------- void LLAgentCamera::slamLookAt(const LLVector3 &look_at) { - LLVector3 look_at_norm = look_at; - look_at_norm.mV[VZ] = 0.f; - look_at_norm.normalize(); - gAgent.resetAxes(look_at_norm); + LLVector3 look_at_norm = look_at; + look_at_norm.mV[VZ] = 0.f; + look_at_norm.normalize(); + gAgent.resetAxes(look_at_norm); } //----------------------------------------------------------------------------- @@ -401,172 +401,172 @@ void LLAgentCamera::slamLookAt(const LLVector3 &look_at) //----------------------------------------------------------------------------- LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y) { - LLMatrix4 obj_matrix = object->getRenderMatrix(); - LLQuaternion obj_rot = object->getRenderRotation(); - LLVector3 obj_pos = object->getRenderPosition(); + LLMatrix4 obj_matrix = object->getRenderMatrix(); + LLQuaternion obj_rot = object->getRenderRotation(); + LLVector3 obj_pos = object->getRenderPosition(); - // if is avatar - don't do any funk heuristics to position the focal point - // see DEV-30589 - if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar())) - { - return original_focus_point - obj_pos; - } + // if is avatar - don't do any funk heuristics to position the focal point + // see DEV-30589 + if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar())) + { + return original_focus_point - obj_pos; + } if (object->isAvatar()) { LLVOAvatar* av = object->asAvatar(); return original_focus_point - av->getCharacterPosition(); } - - LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation - LLVector3 object_extents = object->getScale(); - - // make sure they object extents are non-zero - object_extents.clamp(0.001f, F32_MAX); - - // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object - LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); - obj_to_cam_ray.rotVec(inv_obj_rot); - obj_to_cam_ray.normalize(); - - // obj_to_cam_ray_proportions are the (positive) ratios of - // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. - LLVector3 obj_to_cam_ray_proportions; - obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); - obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); - obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); - - // find the largest ratio stored in obj_to_cam_ray_proportions - // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera - LLVector3 longest_object_axis; - // is x-axis longest? - if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY] - && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) - { - // then grab it - longest_object_axis.setVec(obj_matrix.getFwdRow4()); - } - // is y-axis longest? - else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) - { - // then grab it - longest_object_axis.setVec(obj_matrix.getLeftRow4()); - } - // otherwise, use z axis - else - { - longest_object_axis.setVec(obj_matrix.getUpRow4()); - } - - // Use this axis as the normal to project mouse click on to plane with that normal, at the object center. - // This generates a point behind the mouse cursor that is approximately in the middle of the object in - // terms of depth. - // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. - // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable - // eccentricity to the object orientation - LLVector3 focus_plane_normal(longest_object_axis); - focus_plane_normal.normalize(); - - LLVector3d focus_pt_global; - gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); - LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); - - // find vector from camera to focus point in object space - LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); - camera_to_focus_vec.rotVec(inv_obj_rot); - - // find vector from object origin to focus point in object coordinates - LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; - // convert to object-local space - focus_offset_from_object_center.rotVec(inv_obj_rot); - - // We need to project the focus point back into the bounding box of the focused object. - // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis - LLVector3 clip_fraction; - - // for each axis... - for (U32 axis = VX; axis <= VZ; axis++) - { - //...calculate distance that focus offset sits outside of bounding box along that axis... - //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center - F32 dist_out_of_bounds; - if (focus_offset_from_object_center.mV[axis] > 0.f) - { - dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); - } - else - { - dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); - } - - //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis - if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) - { - // don't divide by very small number - clip_fraction.mV[axis] = 0.f; - } - else - { - clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; - } - } - - LLVector3 abs_clip_fraction = clip_fraction; - abs_clip_fraction.abs(); - - // find axis of focus offset that is *most* outside the bounding box and use that to - // rescale focus offset to inside object extents - if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] - && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) - { - focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; - } - else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) - { - focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; - } - else - { - focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; - } - - // convert back to world space - focus_offset_from_object_center.rotVec(obj_rot); - - // now, based on distance of camera from object relative to object size - // push the focus point towards the near surface of the object when (relatively) close to the objcet - // or keep the focus point in the object middle when (relatively) far - // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars - // is almost always "tumble about middle" and not "spin around surface point" - { - LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); - - //now that we have the object relative position, we should bias toward the center of the object - //based on the distance of the camera to the focus point vs. the distance of the camera to the focus - - F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); - F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); - - - LLBBox obj_bbox = object->getBoundingBoxAgent(); - F32 bias = 0.f; - - // virtual_camera_pos is the camera position we are simulating by backing the camera off - // and adjusting the FOV - LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); - - // if the camera is inside the object (large, hollow objects, for example) - // leave focus point all the way to destination depth, away from object center - if(!obj_bbox.containsPointAgent(virtual_camera_pos)) - { - // perform magic number biasing of focus point towards surface vs. planar center - bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); - obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); - } - - focus_offset_from_object_center = obj_rel; - } - - return focus_offset_from_object_center; + + LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation + LLVector3 object_extents = object->getScale(); + + // make sure they object extents are non-zero + object_extents.clamp(0.001f, F32_MAX); + + // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object + LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin(); + obj_to_cam_ray.rotVec(inv_obj_rot); + obj_to_cam_ray.normalize(); + + // obj_to_cam_ray_proportions are the (positive) ratios of + // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions. + LLVector3 obj_to_cam_ray_proportions; + obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]); + obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]); + obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]); + + // find the largest ratio stored in obj_to_cam_ray_proportions + // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera + LLVector3 longest_object_axis; + // is x-axis longest? + if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY] + && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ]) + { + // then grab it + longest_object_axis.setVec(obj_matrix.getFwdRow4()); + } + // is y-axis longest? + else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ]) + { + // then grab it + longest_object_axis.setVec(obj_matrix.getLeftRow4()); + } + // otherwise, use z axis + else + { + longest_object_axis.setVec(obj_matrix.getUpRow4()); + } + + // Use this axis as the normal to project mouse click on to plane with that normal, at the object center. + // This generates a point behind the mouse cursor that is approximately in the middle of the object in + // terms of depth. + // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera. + // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable + // eccentricity to the object orientation + LLVector3 focus_plane_normal(longest_object_axis); + focus_plane_normal.normalize(); + + LLVector3d focus_pt_global; + gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal); + LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global); + + // find vector from camera to focus point in object space + LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin(); + camera_to_focus_vec.rotVec(inv_obj_rot); + + // find vector from object origin to focus point in object coordinates + LLVector3 focus_offset_from_object_center = focus_pt - obj_pos; + // convert to object-local space + focus_offset_from_object_center.rotVec(inv_obj_rot); + + // We need to project the focus point back into the bounding box of the focused object. + // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis + LLVector3 clip_fraction; + + // for each axis... + for (U32 axis = VX; axis <= VZ; axis++) + { + //...calculate distance that focus offset sits outside of bounding box along that axis... + //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center + F32 dist_out_of_bounds; + if (focus_offset_from_object_center.mV[axis] > 0.f) + { + dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f)); + } + else + { + dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f)); + } + + //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis + if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f) + { + // don't divide by very small number + clip_fraction.mV[axis] = 0.f; + } + else + { + clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis]; + } + } + + LLVector3 abs_clip_fraction = clip_fraction; + abs_clip_fraction.abs(); + + // find axis of focus offset that is *most* outside the bounding box and use that to + // rescale focus offset to inside object extents + if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] + && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ]) + { + focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec; + } + else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ]) + { + focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec; + } + else + { + focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec; + } + + // convert back to world space + focus_offset_from_object_center.rotVec(obj_rot); + + // now, based on distance of camera from object relative to object size + // push the focus point towards the near surface of the object when (relatively) close to the objcet + // or keep the focus point in the object middle when (relatively) far + // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars + // is almost always "tumble about middle" and not "spin around surface point" + { + LLVector3 obj_rel = original_focus_point - object->getRenderPosition(); + + //now that we have the object relative position, we should bias toward the center of the object + //based on the distance of the camera to the focus point vs. the distance of the camera to the focus + + F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis()); + F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin()); + + + LLBBox obj_bbox = object->getBoundingBoxAgent(); + F32 bias = 0.f; + + // virtual_camera_pos is the camera position we are simulating by backing the camera off + // and adjusting the FOV + LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor)); + + // if the camera is inside the object (large, hollow objects, for example) + // leave focus point all the way to destination depth, away from object center + if(!obj_bbox.containsPointAgent(virtual_camera_pos)) + { + // perform magic number biasing of focus point towards surface vs. planar center + bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f); + obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias); + } + + focus_offset_from_object_center = obj_rel; + } + + return focus_offset_from_object_center; } //----------------------------------------------------------------------------- @@ -574,277 +574,277 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi //----------------------------------------------------------------------------- BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance) { - BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) + BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) - if (!mFocusObject || mFocusObject->isDead() || - mFocusObject->isMesh() || - isDisableCameraConstraints()) - { - obj_min_distance = 0.f; - return TRUE; - } + if (!mFocusObject || mFocusObject->isDead() || + mFocusObject->isMesh() || + isDisableCameraConstraints()) + { + obj_min_distance = 0.f; + return TRUE; + } - if (mFocusObject->mDrawable.isNull()) - { + if (mFocusObject->mDrawable.isNull()) + { #ifdef LL_RELEASE_FOR_DOWNLOAD - LL_WARNS() << "Focus object with no drawable!" << LL_ENDL; + LL_WARNS() << "Focus object with no drawable!" << LL_ENDL; #else - mFocusObject->dump(); - LL_ERRS() << "Focus object with no drawable!" << LL_ENDL; + mFocusObject->dump(); + LL_ERRS() << "Focus object with no drawable!" << LL_ENDL; #endif - obj_min_distance = 0.f; - return TRUE; - } - - LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); - LLVector3 target_offset_origin = mFocusObjectOffset; - LLVector3 camera_offset_target(getCameraPositionAgent() - gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); - - // convert offsets into object local space - camera_offset_target.rotVec(inv_object_rot); - target_offset_origin.rotVec(inv_object_rot); - - // push around object extents based on target offset - LLVector3 object_extents = mFocusObject->getScale(); - if (mFocusObject->isAvatar()) - { - // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) - object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; - object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; - object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; - soft_limit = TRUE; - } - LLVector3 abs_target_offset = target_offset_origin; - abs_target_offset.abs(); - - LLVector3 target_offset_dir = target_offset_origin; - - BOOL target_outside_object_extents = FALSE; - - for (U32 i = VX; i <= VZ; i++) - { - if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) - { - target_outside_object_extents = TRUE; - } - if (camera_offset_target.mV[i] > 0.f) - { - object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; - } - else - { - object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; - } - } - - // don't shrink the object extents so far that the object inverts - object_extents.clamp(0.001f, F32_MAX); - - // move into first octant - LLVector3 camera_offset_target_abs_norm = camera_offset_target; - camera_offset_target_abs_norm.abs(); - // make sure offset is non-zero - camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); - camera_offset_target_abs_norm.normalize(); - - // find camera position relative to normalized object extents - LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; - camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; - camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; - camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; - - if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && - camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) - { - if (camera_offset_target_abs_norm.mV[VX] < 0.001f) - { - obj_min_distance = object_extents.mV[VX] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; - } - } - else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) - { - if (camera_offset_target_abs_norm.mV[VY] < 0.001f) - { - obj_min_distance = object_extents.mV[VY] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; - } - } - else - { - if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) - { - obj_min_distance = object_extents.mV[VZ] * 0.5f; - } - else - { - obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; - } - } - - LLVector3 object_split_axis; - LLVector3 target_offset_scaled = target_offset_origin; - target_offset_scaled.abs(); - target_offset_scaled.normalize(); - target_offset_scaled.mV[VX] /= object_extents.mV[VX]; - target_offset_scaled.mV[VY] /= object_extents.mV[VY]; - target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; - - if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && - target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) - { - object_split_axis = LLVector3::x_axis; - } - else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) - { - object_split_axis = LLVector3::y_axis; - } - else - { - object_split_axis = LLVector3::z_axis; - } - - LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); - - - F32 camera_offset_clip = camera_offset_object * object_split_axis; - F32 target_offset_clip = target_offset_dir * object_split_axis; - - // target has moved outside of object extents - // check to see if camera and target are on same side - if (target_outside_object_extents) - { - if (camera_offset_clip > 0.f && target_offset_clip > 0.f) - { - return FALSE; - } - else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) - { - return FALSE; - } - } - - // clamp obj distance to diagonal of 10 by 10 cube - obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); - - obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); - - return TRUE; + obj_min_distance = 0.f; + return TRUE; + } + + LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation(); + LLVector3 target_offset_origin = mFocusObjectOffset; + LLVector3 camera_offset_target(getCameraPositionAgent() - gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + + // convert offsets into object local space + camera_offset_target.rotVec(inv_object_rot); + target_offset_origin.rotVec(inv_object_rot); + + // push around object extents based on target offset + LLVector3 object_extents = mFocusObject->getScale(); + if (mFocusObject->isAvatar()) + { + // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom) + object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR; + object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR; + object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR; + soft_limit = TRUE; + } + LLVector3 abs_target_offset = target_offset_origin; + abs_target_offset.abs(); + + LLVector3 target_offset_dir = target_offset_origin; + + BOOL target_outside_object_extents = FALSE; + + for (U32 i = VX; i <= VZ; i++) + { + if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING) + { + target_outside_object_extents = TRUE; + } + if (camera_offset_target.mV[i] > 0.f) + { + object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f; + } + else + { + object_extents.mV[i] += target_offset_origin.mV[i] * 2.f; + } + } + + // don't shrink the object extents so far that the object inverts + object_extents.clamp(0.001f, F32_MAX); + + // move into first octant + LLVector3 camera_offset_target_abs_norm = camera_offset_target; + camera_offset_target_abs_norm.abs(); + // make sure offset is non-zero + camera_offset_target_abs_norm.clamp(0.001f, F32_MAX); + camera_offset_target_abs_norm.normalize(); + + // find camera position relative to normalized object extents + LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm; + camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX]; + camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY]; + camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ]; + + if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && + camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ]) + { + if (camera_offset_target_abs_norm.mV[VX] < 0.001f) + { + obj_min_distance = object_extents.mV[VX] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX]; + } + } + else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ]) + { + if (camera_offset_target_abs_norm.mV[VY] < 0.001f) + { + obj_min_distance = object_extents.mV[VY] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY]; + } + } + else + { + if (camera_offset_target_abs_norm.mV[VZ] < 0.001f) + { + obj_min_distance = object_extents.mV[VZ] * 0.5f; + } + else + { + obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ]; + } + } + + LLVector3 object_split_axis; + LLVector3 target_offset_scaled = target_offset_origin; + target_offset_scaled.abs(); + target_offset_scaled.normalize(); + target_offset_scaled.mV[VX] /= object_extents.mV[VX]; + target_offset_scaled.mV[VY] /= object_extents.mV[VY]; + target_offset_scaled.mV[VZ] /= object_extents.mV[VZ]; + + if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && + target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ]) + { + object_split_axis = LLVector3::x_axis; + } + else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ]) + { + object_split_axis = LLVector3::y_axis; + } + else + { + object_split_axis = LLVector3::z_axis; + } + + LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent()); + + + F32 camera_offset_clip = camera_offset_object * object_split_axis; + F32 target_offset_clip = target_offset_dir * object_split_axis; + + // target has moved outside of object extents + // check to see if camera and target are on same side + if (target_outside_object_extents) + { + if (camera_offset_clip > 0.f && target_offset_clip > 0.f) + { + return FALSE; + } + else if (camera_offset_clip < 0.f && target_offset_clip < 0.f) + { + return FALSE; + } + } + + // clamp obj distance to diagonal of 10 by 10 cube + obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3); + + obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f); + + return TRUE; } F32 LLAgentCamera::getCameraZoomFraction(bool get_third_person) { - // 0.f -> camera zoomed all the way out - // 1.f -> camera zoomed all the way in - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // already [0,1] - return mHUDTargetZoom; - } - - if (isDisableCameraConstraints()) - { - return mCameraZoomFraction; - } - - if (get_third_person || (mFocusOnAvatar && cameraThirdPerson())) - { - return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); - } - - if (cameraCustomizeAvatar()) - { - F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); - return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); - } - - F32 min_zoom; - F32 max_zoom = getCameraMaxZoomDistance(); - - F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - else - { - min_zoom = LAND_MIN_ZOOM; - } - - return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f); + // 0.f -> camera zoomed all the way out + // 1.f -> camera zoomed all the way in + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // already [0,1] + return mHUDTargetZoom; + } + + if (isDisableCameraConstraints()) + { + return mCameraZoomFraction; + } + + if (get_third_person || (mFocusOnAvatar && cameraThirdPerson())) + { + return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); + } + + if (cameraCustomizeAvatar()) + { + F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); + return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); + } + + F32 min_zoom; + F32 max_zoom = getCameraMaxZoomDistance(); + + F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + else + { + min_zoom = LAND_MIN_ZOOM; + } + + return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f); } void LLAgentCamera::setCameraZoomFraction(F32 fraction) { - // 0.f -> camera zoomed all the way out - // 1.f -> camera zoomed all the way in - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - mHUDTargetZoom = fraction; - } - else if (isDisableCameraConstraints()) - { - mCameraZoomFraction = fraction; - } - else if (mFocusOnAvatar && cameraThirdPerson()) - { - mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); - } - else if (cameraCustomizeAvatar()) - { - LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; - camera_offset_dir.normalize(); - mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); - } - else - { - F32 min_zoom = LAND_MIN_ZOOM; - F32 max_zoom = getCameraMaxZoomDistance(); - - if (mFocusObject.notNull()) - { - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - } - - LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; - camera_offset_dir.normalize(); - mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); - } - - startCameraAnimation(); + // 0.f -> camera zoomed all the way out + // 1.f -> camera zoomed all the way in + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + mHUDTargetZoom = fraction; + } + else if (isDisableCameraConstraints()) + { + mCameraZoomFraction = fraction; + } + else if (mFocusOnAvatar && cameraThirdPerson()) + { + mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); + } + else if (cameraCustomizeAvatar()) + { + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; + camera_offset_dir.normalize(); + mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM); + } + else + { + F32 min_zoom = LAND_MIN_ZOOM; + F32 max_zoom = getCameraMaxZoomDistance(); + + if (mFocusObject.notNull()) + { + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + } + + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; + camera_offset_dir.normalize(); + mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); + } + + startCameraAnimation(); } F32 LLAgentCamera::getAgentHUDTargetZoom() { - static LLCachedControl hud_scale_factor(gSavedSettings, "HUDScaleFactor"); - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor; + static LLCachedControl hud_scale_factor(gSavedSettings, "HUDScaleFactor"); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor; } //----------------------------------------------------------------------------- @@ -852,22 +852,22 @@ F32 LLAgentCamera::getAgentHUDTargetZoom() //----------------------------------------------------------------------------- void LLAgentCamera::cameraOrbitAround(const F32 radians) { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // do nothing for hud selection - } - else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) - { - gAgent.yaw(radians); - } - else - { - mOrbitAroundRadians += radians; - mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); - - cameraZoomIn(1.f); - } + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // do nothing for hud selection + } + else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW)) + { + gAgent.yaw(radians); + } + else + { + mOrbitAroundRadians += radians; + mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); + + cameraZoomIn(1.f); + } } @@ -876,51 +876,51 @@ void LLAgentCamera::cameraOrbitAround(const F32 radians) //----------------------------------------------------------------------------- void LLAgentCamera::cameraOrbitOver(const F32 angle) { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // do nothing for hud selection - } - else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - gAgent.pitch(angle); - } - else - { - LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); - camera_offset_unit.normalize(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // do nothing for hud selection + } + else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + gAgent.pitch(angle); + } + else + { + LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); + camera_offset_unit.normalize(); - F32 angle_from_up = acos( camera_offset_unit * gAgent.getReferenceUpVector() ); + F32 angle_from_up = acos( camera_offset_unit * gAgent.getReferenceUpVector() ); - LLVector3d left_axis; - left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); - F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); - mOrbitOverAngle += angle_from_up - new_angle; - mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD); + mOrbitOverAngle += angle_from_up - new_angle; + mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis); - cameraZoomIn(1.f); - } + cameraZoomIn(1.f); + } } void LLAgentCamera::resetCameraOrbit() { - LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); - camera_offset_unit.normalize(); + LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); + camera_offset_unit.normalize(); + + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis); - LLVector3d left_axis; - left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); - mCameraFocusOffsetTarget.rotVec(-mOrbitOverAngle, left_axis); - - mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f); + mCameraFocusOffsetTarget.rotVec(-mOrbitAroundRadians, 0.f, 0.f, 1.f); - cameraZoomIn(1.f); - resetOrbitDiff(); + cameraZoomIn(1.f); + resetOrbitDiff(); } void LLAgentCamera::resetOrbitDiff() { - mOrbitAroundRadians = 0; - mOrbitOverAngle = 0; + mOrbitAroundRadians = 0; + mOrbitOverAngle = 0; } //----------------------------------------------------------------------------- @@ -928,56 +928,56 @@ void LLAgentCamera::resetOrbitDiff() //----------------------------------------------------------------------------- void LLAgentCamera::cameraZoomIn(const F32 fraction) { - if (gDisconnected) - { - return; - } - - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - if (LLToolMgr::getInstance()->inBuildMode() && selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - // just update hud zoom level - mHUDTargetZoom /= fraction; - return; - } + if (gDisconnected) + { + return; + } - LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); - F32 current_distance = (F32)camera_offset_unit.normalize(); - F32 new_distance = current_distance * fraction; + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (LLToolMgr::getInstance()->inBuildMode() && selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + // just update hud zoom level + mHUDTargetZoom /= fraction; + return; + } - // Unless camera is unlocked - if (!isDisableCameraConstraints()) - { - F32 min_zoom = LAND_MIN_ZOOM; + LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); + F32 current_distance = (F32)camera_offset_unit.normalize(); + F32 new_distance = current_distance * fraction; - // Don't move through focus point - if (mFocusObject) - { - LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); + // Unless camera is unlocked + if (!isDisableCameraConstraints()) + { + F32 min_zoom = LAND_MIN_ZOOM; - if (mFocusObject->isAvatar()) - { - calcCameraMinDistance(min_zoom); - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } + // Don't move through focus point + if (mFocusObject) + { + LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); + + if (mFocusObject->isAvatar()) + { + calcCameraMinDistance(min_zoom); + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } - new_distance = llmax(new_distance, min_zoom); + new_distance = llmax(new_distance, min_zoom); - F32 max_distance = getCameraMaxZoomDistance(); - max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154 - new_distance = llmin(new_distance, max_distance); + F32 max_distance = getCameraMaxZoomDistance(); + max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154 + new_distance = llmin(new_distance, max_distance); - if (cameraCustomizeAvatar()) - { - new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); - } - } + if (cameraCustomizeAvatar()) + { + new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); + } + } - mCameraFocusOffsetTarget = new_distance * camera_offset_unit; + mCameraFocusOffsetTarget = new_distance * camera_offset_unit; } //----------------------------------------------------------------------------- @@ -985,80 +985,80 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) //----------------------------------------------------------------------------- void LLAgentCamera::cameraOrbitIn(const F32 meters) { - if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale")); - - mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; - - if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) - { - // No need to animate, camera is already there. - changeCameraToMouselook(FALSE); - } - - if (!isDisableCameraConstraints()) - { - mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); - } - } - else - { - LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); - F32 current_distance = (F32)camera_offset_unit.normalize(); - F32 new_distance = current_distance - meters; - - // Unless camera is unlocked - if (!isDisableCameraConstraints()) - { - F32 min_zoom = LAND_MIN_ZOOM; - - // Don't move through focus point - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - - new_distance = llmax(new_distance, min_zoom); - - F32 max_distance = getCameraMaxZoomDistance(); - new_distance = llmin(new_distance, max_distance); - - if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) - { - new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); - } - } - - // Compute new camera offset - mCameraFocusOffsetTarget = new_distance * camera_offset_unit; - cameraZoomIn(1.f); - } -} + if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale")); -//----------------------------------------------------------------------------- -// cameraPanIn() -//----------------------------------------------------------------------------- -void LLAgentCamera::cameraPanIn(F32 meters) -{ - LLVector3d at_axis; - at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); + mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; - mPanFocusDiff += meters * at_axis; + if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f) + { + // No need to animate, camera is already there. + changeCameraToMouselook(FALSE); + } + + if (!isDisableCameraConstraints()) + { + mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); + } + } + else + { + LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); + F32 current_distance = (F32)camera_offset_unit.normalize(); + F32 new_distance = current_distance - meters; - mFocusTargetGlobal += meters * at_axis; - mFocusGlobal = mFocusTargetGlobal; - // don't enforce zoom constraints as this is the only way for users to get past them easily - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + // Unless camera is unlocked + if (!isDisableCameraConstraints()) + { + F32 min_zoom = LAND_MIN_ZOOM; + + // Don't move through focus point + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + + new_distance = llmax(new_distance, min_zoom); + + F32 max_distance = getCameraMaxZoomDistance(); + new_distance = llmin(new_distance, max_distance); + + if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) + { + new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); + } + } + + // Compute new camera offset + mCameraFocusOffsetTarget = new_distance * camera_offset_unit; + cameraZoomIn(1.f); + } +} + +//----------------------------------------------------------------------------- +// cameraPanIn() +//----------------------------------------------------------------------------- +void LLAgentCamera::cameraPanIn(F32 meters) +{ + LLVector3d at_axis; + at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis()); + + mPanFocusDiff += meters * at_axis; + + mFocusTargetGlobal += meters * at_axis; + mFocusGlobal = mFocusTargetGlobal; + // don't enforce zoom constraints as this is the only way for users to get past them easily + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); } //----------------------------------------------------------------------------- @@ -1066,21 +1066,21 @@ void LLAgentCamera::cameraPanIn(F32 meters) //----------------------------------------------------------------------------- void LLAgentCamera::cameraPanLeft(F32 meters) { - LLVector3d left_axis; - left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + LLVector3d left_axis; + left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis()); + + mPanFocusDiff += meters * left_axis; - mPanFocusDiff += meters * left_axis; + mFocusTargetGlobal += meters * left_axis; + mFocusGlobal = mFocusTargetGlobal; - mFocusTargetGlobal += meters * left_axis; - mFocusGlobal = mFocusTargetGlobal; + // disable smoothing for camera pan, which causes some residents unhappiness + mCameraSmoothingStop = true; - // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = true; - - cameraZoomIn(1.f); - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + cameraZoomIn(1.f); + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); } //----------------------------------------------------------------------------- @@ -1088,41 +1088,41 @@ void LLAgentCamera::cameraPanLeft(F32 meters) //----------------------------------------------------------------------------- void LLAgentCamera::cameraPanUp(F32 meters) { - LLVector3d up_axis; - up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); + LLVector3d up_axis; + up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis()); - mPanFocusDiff += meters * up_axis; + mPanFocusDiff += meters * up_axis; - mFocusTargetGlobal += meters * up_axis; - mFocusGlobal = mFocusTargetGlobal; + mFocusTargetGlobal += meters * up_axis; + mFocusGlobal = mFocusTargetGlobal; - // disable smoothing for camera pan, which causes some residents unhappiness - mCameraSmoothingStop = true; + // disable smoothing for camera pan, which causes some residents unhappiness + mCameraSmoothingStop = true; - cameraZoomIn(1.f); - updateFocusOffset(); - // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + cameraZoomIn(1.f); + updateFocusOffset(); + // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); } void LLAgentCamera::resetCameraPan() { - mFocusTargetGlobal -= mPanFocusDiff; + mFocusTargetGlobal -= mPanFocusDiff; - mFocusGlobal = mFocusTargetGlobal; - mCameraSmoothingStop = true; + mFocusGlobal = mFocusTargetGlobal; + mCameraSmoothingStop = true; - cameraZoomIn(1.f); - updateFocusOffset(); + cameraZoomIn(1.f); + updateFocusOffset(); - mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); + mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal(); - resetPanDiff(); + resetPanDiff(); } void LLAgentCamera::resetPanDiff() { - mPanFocusDiff.clear(); + mPanFocusDiff.clear(); } //----------------------------------------------------------------------------- @@ -1130,67 +1130,67 @@ void LLAgentCamera::resetPanDiff() //----------------------------------------------------------------------------- void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) { - static LLVector3 last_at_axis; - - if (!isAgentAvatarValid()) return; - - LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); - LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); - - if (LLTrace::get_frame_recording().getLastRecording().getLastValue(*gViewerWindow->getMouseVelocityStat()) < 0.01f - && (root_at * last_at_axis > 0.95f)) - { - LLVector3 vel = gAgentAvatarp->getVelocity(); - if (vel.magVecSquared() > 4.f) - { - setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, vel * av_inv_rot); - } - else - { - // *FIX: rotate mframeagent by sit object's rotation? - LLQuaternion look_rotation = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); // use camera's current rotation - LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; - setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, look_offset); - } - last_at_axis = root_at; - return; - } - - last_at_axis = root_at; - - if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) - { - setLookAt(LOOKAT_TARGET_NONE, gAgentAvatarp, LLVector3(-2.f, 0.f, 0.f)); - } - else - { - // Move head based on cursor position - ELookAtType lookAtType = LOOKAT_TARGET_NONE; - LLVector3 headLookAxis; - LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); - - if (cameraMouselook()) - { - lookAtType = LOOKAT_TARGET_MOUSELOOK; - } - else if (cameraThirdPerson()) - { - // range from -.5 to .5 - F32 x_from_center = - ((F32) mouse_x / (F32) gViewerWindow->getWorldViewWidthScaled() ) - 0.5f; - F32 y_from_center = - ((F32) mouse_y / (F32) gViewerWindow->getWorldViewHeightScaled() ) - 0.5f; - - frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); - frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); - lookAtType = LOOKAT_TARGET_FREELOOK; - } - - headLookAxis = frameCamera.getAtAxis(); - // RN: we use world-space offset for mouselook and freelook - //headLookAxis = headLookAxis * av_inv_rot; - setLookAt(lookAtType, gAgentAvatarp, headLookAxis); - } + static LLVector3 last_at_axis; + + if (!isAgentAvatarValid()) return; + + LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); + LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); + + if (LLTrace::get_frame_recording().getLastRecording().getLastValue(*gViewerWindow->getMouseVelocityStat()) < 0.01f + && (root_at * last_at_axis > 0.95f)) + { + LLVector3 vel = gAgentAvatarp->getVelocity(); + if (vel.magVecSquared() > 4.f) + { + setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, vel * av_inv_rot); + } + else + { + // *FIX: rotate mframeagent by sit object's rotation? + LLQuaternion look_rotation = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); // use camera's current rotation + LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; + setLookAt(LOOKAT_TARGET_IDLE, gAgentAvatarp, look_offset); + } + last_at_axis = root_at; + return; + } + + last_at_axis = root_at; + + if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) + { + setLookAt(LOOKAT_TARGET_NONE, gAgentAvatarp, LLVector3(-2.f, 0.f, 0.f)); + } + else + { + // Move head based on cursor position + ELookAtType lookAtType = LOOKAT_TARGET_NONE; + LLVector3 headLookAxis; + LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); + + if (cameraMouselook()) + { + lookAtType = LOOKAT_TARGET_MOUSELOOK; + } + else if (cameraThirdPerson()) + { + // range from -.5 to .5 + F32 x_from_center = + ((F32) mouse_x / (F32) gViewerWindow->getWorldViewWidthScaled() ) - 0.5f; + F32 y_from_center = + ((F32) mouse_y / (F32) gViewerWindow->getWorldViewHeightScaled() ) - 0.5f; + + frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD); + frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD); + lookAtType = LOOKAT_TARGET_FREELOOK; + } + + headLookAxis = frameCamera.getAtAxis(); + // RN: we use world-space offset for mouselook and freelook + //headLookAxis = headLookAxis * av_inv_rot; + setLookAt(lookAtType, gAgentAvatarp, headLookAxis); + } } static LLTrace::BlockTimerStatHandle FTM_UPDATE_CAMERA("Camera"); @@ -1202,377 +1202,377 @@ extern BOOL gCubeSnapshot; //----------------------------------------------------------------------------- void LLAgentCamera::updateCamera() { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA); + LL_RECORD_BLOCK_TIME(FTM_UPDATE_CAMERA); if (gCubeSnapshot) { return; } - // - changed camera_skyward to the new global "mCameraUpVector" - mCameraUpVector = LLVector3::z_axis; - //LLVector3 camera_skyward(0.f, 0.f, 1.f); - - U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; - - validateFocusObject(); - - if (isAgentAvatarValid() && - gAgentAvatarp->isSitting() && - camera_mode == CAMERA_MODE_MOUSELOOK) - { - //changed camera_skyward to the new global "mCameraUpVector" - mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); - } - - if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) - { - mAllowChangeToFollow = FALSE; - mFocusOnAvatar = TRUE; - changeCameraToFollow(); - } - - //NOTE - this needs to be integrated into a general upVector system here within llAgent. - if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - mCameraUpVector = mFollowCam.getUpVector(); - } - - if (mSitCameraEnabled) - { - if (mSitCameraReferenceObject->isDead()) - { - setSitCamera(LLUUID::null); - } - } - - // Update UI with our camera inputs - LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance("camera"); - if (camera_floater) - { - camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left - gAgentCamera.getOrbitUpKey() > 0.f, // top - gAgentCamera.getOrbitLeftKey() > 0.f, // right - gAgentCamera.getOrbitDownKey() > 0.f); // bottom - - camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left - gAgentCamera.getPanUpKey() > 0.f, // top - gAgentCamera.getPanRightKey() > 0.f, // right - gAgentCamera.getPanDownKey() > 0.f); // bottom - } - - // Handle camera movement based on keyboard. - const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second - const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second - const F32 PAN_RATE = 5.f; // meters per second - - if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey()) - { - F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey(); - cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); - } - - if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey()) - { - F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey(); - cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped); - } - - if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey()) - { - F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey(); - - LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); - F32 distance_to_focus = (F32)to_focus.magVec(); - // Move at distance (in meters) meters per second - cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); - } - - if (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey()) - { - F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey(); - cameraPanIn(input_rate * PAN_RATE / gFPSClamped); - } - - if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey()) - { - F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey(); - cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped ); - } - - if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey()) - { - F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey(); - cameraPanUp(input_rate * PAN_RATE / gFPSClamped ); - } - - // Clear camera keyboard keys. - gAgentCamera.clearOrbitKeys(); - gAgentCamera.clearPanKeys(); - - // lerp camera focus offset - mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); - - if ( mCameraMode == CAMERA_MODE_FOLLOW ) - { - if (isAgentAvatarValid()) - { - //-------------------------------------------------------------------------------- - // this is where the avatar's position and rotation are given to followCam, and - // where it is updated. All three of its attributes are updated: (1) position, - // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. - //-------------------------------------------------------------------------------- - // *TODO: use combined rotation of frameagent and sit object - LLQuaternion avatarRotationForFollowCam = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); - - LLFollowCamParams* current_cam = LLFollowCamMgr::getInstance()->getActiveFollowCamParams(); - if (current_cam) - { - mFollowCam.copyParams(*current_cam); - mFollowCam.setSubjectPositionAndRotation( gAgentAvatarp->getRenderPosition(), avatarRotationForFollowCam ); - mFollowCam.update(); - LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); - } - else - { - changeCameraToThirdPerson(TRUE); - } - } - } - - BOOL hit_limit; - LLVector3d camera_pos_global; - LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); - mCameraVirtualPositionAgent = gAgent.getPosAgentFromGlobal(camera_target_global); - LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); - - // perform field of view correction - mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); - camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); - - gAgent.setShowAvatar(TRUE); // can see avatar by default - - // Adjust position for animation - if (mCameraAnimating) - { - F32 time = mAnimationTimer.getElapsedTimeF32(); - - // yet another instance of critically damped motion, hooray! - // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); - - // linear interpolation - F32 fraction_of_animation = time / mAnimationDuration; - - BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; - BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; - F32 fraction_animation_to_skip; - - if (mAnimationCameraStartGlobal == camera_target_global) - { - fraction_animation_to_skip = 0.f; - } - else - { - LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; - fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); - } - F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; - F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; - - if (fraction_of_animation < animation_finish_fraction) - { - if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) - { - gAgent.setShowAvatar(FALSE); - } - - // ...adjust position for animation - F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); - camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); - mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); - } - else - { - // ...animation complete - mCameraAnimating = FALSE; - - camera_pos_global = camera_target_global; - mFocusGlobal = focus_target_global; - - gAgent.endAnimationUpdateUI(); - gAgent.setShowAvatar(TRUE); - } - - if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK)) - { - gAgentAvatarp->updateAttachmentVisibility(mCameraMode); - } - } - else - { - camera_pos_global = camera_target_global; - mFocusGlobal = focus_target_global; - gAgent.setShowAvatar(TRUE); - } - - // smoothing - if (TRUE) - { - LLVector3d agent_pos = gAgent.getPositionGlobal(); - LLVector3d camera_pos_agent = camera_pos_global - agent_pos; - // Sitting on what you're manipulating can cause camera jitter with smoothing. - // This turns off smoothing while editing. -MG - bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); - mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; - - if (cameraThirdPerson() && !mCameraSmoothingStop) - { - const F32 SMOOTHING_HALF_LIFE = 0.02f; - - F32 smoothing = LLSmoothInterpolation::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); - - if (mFocusOnAvatar && !mFocusObject) // we differentiate on avatar mode - { - // for avatar-relative focus, we smooth in avatar space - - // the avatar moves too jerkily w/r/t global space to smooth there. - - LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); - camera_pos_global = camera_pos_agent + agent_pos; - } - } - else - { - LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); - } - } - } - - mCameraSmoothingLastPositionGlobal = camera_pos_global; - mCameraSmoothingLastPositionAgent = camera_pos_agent; - mCameraSmoothingStop = false; - } - - - mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); - -// LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; - - LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); - - mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); - - // Move the camera - - LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); - //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); - - // Change FOV - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); - - // follow camera when in customize mode - if (cameraCustomizeAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); - } - - // update the travel distance stat - // this isn't directly related to the camera - // but this seemed like the best place to do this - LLVector3d global_pos = gAgent.getPositionGlobal(); - if (!gAgent.getLastPositionGlobal().isExactlyZero()) - { - LLVector3d delta = global_pos - gAgent.getLastPositionGlobal(); - gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec()); - } - gAgent.setLastPositionGlobal(global_pos); - - if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook()) - { - LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() + - LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + - LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); - LLVector3 diff = mCameraPositionAgent - head_pos; - diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); - - LLJoint* torso_joint = gAgentAvatarp->mTorsop; - LLJoint* chest_joint = gAgentAvatarp->mChestp; - LLVector3 torso_scale = torso_joint->getScale(); - LLVector3 chest_scale = chest_joint->getScale(); - - // shorten avatar skeleton to avoid foot interpenetration - if (!gAgentAvatarp->mInAir) - { - LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); - F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); - F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); - torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - - LLJoint* neck_joint = gAgentAvatarp->mNeckp; - LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); - scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); - chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - diff.mV[VZ] = 0.f; - } - - // SL-315 - gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); - - gAgentAvatarp->mRoot->updateWorldMatrixChildren(); - - 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; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *attached_object = attachment_iter->get(); - if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) - { - // clear any existing "early" movements of attachment - attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); - gPipeline.updateMoveNormalAsync(attached_object->mDrawable); - attached_object->updateText(); - } - } - } - - torso_joint->setScale(torso_scale); - chest_joint->setScale(chest_scale); - } + // - changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = LLVector3::z_axis; + //LLVector3 camera_skyward(0.f, 0.f, 1.f); + + U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + + validateFocusObject(); + + if (isAgentAvatarValid() && + gAgentAvatarp->isSitting() && + camera_mode == CAMERA_MODE_MOUSELOOK) + { + //changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = mCameraUpVector * gAgentAvatarp->getRenderRotation(); + } + + if (cameraThirdPerson() && (mFocusOnAvatar || mAllowChangeToFollow) && LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) + { + mAllowChangeToFollow = FALSE; + mFocusOnAvatar = TRUE; + changeCameraToFollow(); + } + + //NOTE - this needs to be integrated into a general upVector system here within llAgent. + if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) + { + mCameraUpVector = mFollowCam.getUpVector(); + } + + if (mSitCameraEnabled) + { + if (mSitCameraReferenceObject->isDead()) + { + setSitCamera(LLUUID::null); + } + } + + // Update UI with our camera inputs + LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance("camera"); + if (camera_floater) + { + camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left + gAgentCamera.getOrbitUpKey() > 0.f, // top + gAgentCamera.getOrbitLeftKey() > 0.f, // right + gAgentCamera.getOrbitDownKey() > 0.f); // bottom + + camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left + gAgentCamera.getPanUpKey() > 0.f, // top + gAgentCamera.getPanRightKey() > 0.f, // right + gAgentCamera.getPanDownKey() > 0.f); // bottom + } + + // Handle camera movement based on keyboard. + const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second + const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second + const F32 PAN_RATE = 5.f; // meters per second + + if (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey()) + { + F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey(); + cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); + } + + if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey()) + { + F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey(); + cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped); + } + + if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey()) + { + F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey(); + + LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal(); + F32 distance_to_focus = (F32)to_focus.magVec(); + // Move at distance (in meters) meters per second + cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped ); + } + + if (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey()) + { + F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey(); + cameraPanIn(input_rate * PAN_RATE / gFPSClamped); + } + + if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey()) + { + F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey(); + cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped ); + } + + if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey()) + { + F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey(); + cameraPanUp(input_rate * PAN_RATE / gFPSClamped ); + } + + // Clear camera keyboard keys. + gAgentCamera.clearOrbitKeys(); + gAgentCamera.clearPanKeys(); + + // lerp camera focus offset + mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + + if ( mCameraMode == CAMERA_MODE_FOLLOW ) + { + if (isAgentAvatarValid()) + { + //-------------------------------------------------------------------------------- + // this is where the avatar's position and rotation are given to followCam, and + // where it is updated. All three of its attributes are updated: (1) position, + // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. + //-------------------------------------------------------------------------------- + // *TODO: use combined rotation of frameagent and sit object + LLQuaternion avatarRotationForFollowCam = gAgentAvatarp->isSitting() ? gAgentAvatarp->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); + + LLFollowCamParams* current_cam = LLFollowCamMgr::getInstance()->getActiveFollowCamParams(); + if (current_cam) + { + mFollowCam.copyParams(*current_cam); + mFollowCam.setSubjectPositionAndRotation( gAgentAvatarp->getRenderPosition(), avatarRotationForFollowCam ); + mFollowCam.update(); + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); + } + else + { + changeCameraToThirdPerson(TRUE); + } + } + } + + BOOL hit_limit; + LLVector3d camera_pos_global; + LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); + mCameraVirtualPositionAgent = gAgent.getPosAgentFromGlobal(camera_target_global); + LLVector3d focus_target_global = calcFocusPositionTargetGlobal(); + + // perform field of view correction + mCameraFOVZoomFactor = calcCameraFOVZoomFactor(); + camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor); + + gAgent.setShowAvatar(TRUE); // can see avatar by default + + // Adjust position for animation + if (mCameraAnimating) + { + F32 time = mAnimationTimer.getElapsedTimeF32(); + + // yet another instance of critically damped motion, hooray! + // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE); + + // linear interpolation + F32 fraction_of_animation = time / mAnimationDuration; + + BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK; + BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK; + F32 fraction_animation_to_skip; + + if (mAnimationCameraStartGlobal == camera_target_global) + { + fraction_animation_to_skip = 0.f; + } + else + { + LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global; + fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec(); + } + F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f; + F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f; + + if (fraction_of_animation < animation_finish_fraction) + { + if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction ) + { + gAgent.setShowAvatar(FALSE); + } + + // ...adjust position for animation + F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation); + camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation); + mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation); + } + else + { + // ...animation complete + mCameraAnimating = FALSE; + + camera_pos_global = camera_target_global; + mFocusGlobal = focus_target_global; + + gAgent.endAnimationUpdateUI(); + gAgent.setShowAvatar(TRUE); + } + + if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK)) + { + gAgentAvatarp->updateAttachmentVisibility(mCameraMode); + } + } + else + { + camera_pos_global = camera_target_global; + mFocusGlobal = focus_target_global; + gAgent.setShowAvatar(TRUE); + } + + // smoothing + if (TRUE) + { + LLVector3d agent_pos = gAgent.getPositionGlobal(); + LLVector3d camera_pos_agent = camera_pos_global - agent_pos; + // Sitting on what you're manipulating can cause camera jitter with smoothing. + // This turns off smoothing while editing. -MG + bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); + mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; + + if (cameraThirdPerson() && !mCameraSmoothingStop) + { + const F32 SMOOTHING_HALF_LIFE = 0.02f; + + F32 smoothing = LLSmoothInterpolation::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); + + if (mFocusOnAvatar && !mFocusObject) // we differentiate on avatar mode + { + // for avatar-relative focus, we smooth in avatar space - + // the avatar moves too jerkily w/r/t global space to smooth there. + + LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); + camera_pos_global = camera_pos_agent + agent_pos; + } + } + else + { + LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); + } + } + } + + mCameraSmoothingLastPositionGlobal = camera_pos_global; + mCameraSmoothingLastPositionAgent = camera_pos_agent; + mCameraSmoothingStop = false; + } + + + mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); + +// LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; + + LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); + + mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); + + // Move the camera + + LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); + //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); + + // Change FOV + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); + + // follow camera when in customize mode + if (cameraCustomizeAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); + } + + // update the travel distance stat + // this isn't directly related to the camera + // but this seemed like the best place to do this + LLVector3d global_pos = gAgent.getPositionGlobal(); + if (!gAgent.getLastPositionGlobal().isExactlyZero()) + { + LLVector3d delta = global_pos - gAgent.getLastPositionGlobal(); + gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec()); + } + gAgent.setLastPositionGlobal(global_pos); + + if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !gAgentAvatarp->isSitting() && cameraMouselook()) + { + LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() + + LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + + LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); + LLVector3 diff = mCameraPositionAgent - head_pos; + diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); + + LLJoint* torso_joint = gAgentAvatarp->mTorsop; + LLJoint* chest_joint = gAgentAvatarp->mChestp; + LLVector3 torso_scale = torso_joint->getScale(); + LLVector3 chest_scale = chest_joint->getScale(); + + // shorten avatar skeleton to avoid foot interpenetration + if (!gAgentAvatarp->mInAir) + { + LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); + F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); + F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); + torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + + LLJoint* neck_joint = gAgentAvatarp->mNeckp; + LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); + scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); + chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + diff.mV[VZ] = 0.f; + } + + // SL-315 + gAgentAvatarp->mPelvisp->setPosition(gAgentAvatarp->mPelvisp->getPosition() + diff); + + gAgentAvatarp->mRoot->updateWorldMatrixChildren(); + + 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; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = attachment_iter->get(); + if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) + { + // clear any existing "early" movements of attachment + attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); + gPipeline.updateMoveNormalAsync(attached_object->mDrawable); + attached_object->updateText(); + } + } + } + + torso_joint->setScale(torso_scale); + chest_joint->setScale(chest_scale); + } } void LLAgentCamera::updateLastCamera() { - mLastCameraMode = mCameraMode; + mLastCameraMode = mCameraMode; } void LLAgentCamera::updateFocusOffset() { - validateFocusObject(); - if (mFocusObject.notNull()) - { - LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition()); - mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); - } + validateFocusObject(); + if (mFocusObject.notNull()) + { + LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition()); + mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); + } } void LLAgentCamera::validateFocusObject() { - if (mFocusObject.notNull() && - mFocusObject->isDead()) - { - mFocusObjectOffset.clearVec(); - clearFocusObject(); - mCameraFOVZoomFactor = 0.f; - } + if (mFocusObject.notNull() && + mFocusObject->isDead()) + { + mFocusObjectOffset.clearVec(); + clearFocusObject(); + mCameraFOVZoomFactor = 0.f; + } } //----------------------------------------------------------------------------- @@ -1580,124 +1580,124 @@ void LLAgentCamera::validateFocusObject() //----------------------------------------------------------------------------- LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal() { - if (mFocusObject.notNull() && mFocusObject->isDead()) - { - clearFocusObject(); - } - - if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) - { - mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); - return mFocusTargetGlobal; - } - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - LLVector3d at_axis(1.0, 0.0, 0.0); - LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot(); - if (!root_object->flagCameraDecoupled()) - { - agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); - } - } - at_axis = at_axis * agent_rot; - mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; - return mFocusTargetGlobal; - } - else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) - { - if (mFocusOnAvatar) - { - LLVector3 focus_target = isAgentAvatarValid() - ? gAgentAvatarp->mHeadp->getWorldPosition() - : gAgent.getPositionAgent(); - LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); - mFocusTargetGlobal = focus_target_global; - } - return mFocusTargetGlobal; - } - else if (!mFocusOnAvatar) - { - if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) - { - LLDrawable* drawablep = mFocusObject->mDrawable; - - if (mTrackFocusObject && - drawablep && - drawablep->isActive()) - { - if (!mFocusObject->isAvatar()) - { - if (mFocusObject->isSelected()) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - gPipeline.updateMoveDampedAsync(drawablep); - } - } - } - } - // if not tracking object, update offset based on new object position - else - { - updateFocusOffset(); - } - LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; - mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent)); - } - return mFocusTargetGlobal; - } - else if (mSitCameraEnabled && isAgentAvatarValid() && gAgentAvatarp->isSitting() && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); - return gAgent.getPosGlobalFromAgent(target_pos); - } - else - { - return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(); - } + if (mFocusObject.notNull() && mFocusObject->isDead()) + { + clearFocusObject(); + } + + if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); + return mFocusTargetGlobal; + } + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + LLVector3d at_axis(1.0, 0.0, 0.0); + LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + LLViewerObject* root_object = (LLViewerObject*)gAgentAvatarp->getRoot(); + if (!root_object->flagCameraDecoupled()) + { + agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); + } + } + at_axis = at_axis * agent_rot; + mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; + return mFocusTargetGlobal; + } + else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) + { + if (mFocusOnAvatar) + { + LLVector3 focus_target = isAgentAvatarValid() + ? gAgentAvatarp->mHeadp->getWorldPosition() + : gAgent.getPositionAgent(); + LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); + mFocusTargetGlobal = focus_target_global; + } + return mFocusTargetGlobal; + } + else if (!mFocusOnAvatar) + { + if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) + { + LLDrawable* drawablep = mFocusObject->mDrawable; + + if (mTrackFocusObject && + drawablep && + drawablep->isActive()) + { + if (!mFocusObject->isAvatar()) + { + if (mFocusObject->isSelected()) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + gPipeline.updateMoveDampedAsync(drawablep); + } + } + } + } + // if not tracking object, update offset based on new object position + else + { + updateFocusOffset(); + } + LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; + mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent)); + } + return mFocusTargetGlobal; + } + else if (mSitCameraEnabled && isAgentAvatarValid() && gAgentAvatarp->isSitting() && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); + return gAgent.getPosGlobalFromAgent(target_pos); + } + else + { + return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(); + } } LLVector3d LLAgentCamera::calcThirdPersonFocusOffset() { - // ...offset from avatar - LLVector3d focus_offset; - LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); - } + // ...offset from avatar + LLVector3d focus_offset; + LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + agent_rot *= ((LLViewerObject*)(gAgentAvatarp->getParent()))->getRenderRotation(); + } static LLCachedControl focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); - return focus_offset_initial * agent_rot; + return focus_offset_initial * agent_rot; } void LLAgentCamera::setupSitCamera() { - // agent frame entering this function is in world coordinates - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis * ~parent_rot); - } + // agent frame entering this function is in world coordinates + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~parent_rot); + } } //----------------------------------------------------------------------------- @@ -1705,7 +1705,7 @@ void LLAgentCamera::setupSitCamera() //----------------------------------------------------------------------------- const LLVector3 &LLAgentCamera::getCameraPositionAgent() const { - return LLViewerCamera::getInstance()->getOrigin(); + return LLViewerCamera::getInstance()->getOrigin(); } //----------------------------------------------------------------------------- @@ -1713,39 +1713,39 @@ const LLVector3 &LLAgentCamera::getCameraPositionAgent() const //----------------------------------------------------------------------------- LLVector3d LLAgentCamera::getCameraPositionGlobal() const { - return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); + return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); } //----------------------------------------------------------------------------- // calcCameraFOVZoomFactor() //----------------------------------------------------------------------------- -F32 LLAgentCamera::calcCameraFOVZoomFactor() +F32 LLAgentCamera::calcCameraFOVZoomFactor() { - LLVector3 camera_offset_dir; - camera_offset_dir.setVec(mCameraFocusOffset); + LLVector3 camera_offset_dir; + camera_offset_dir.setVec(mCameraFocusOffset); - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } - else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) - { - // don't FOV zoom on mostly transparent objects - F32 obj_min_dist = 0.f; - calcCameraMinDistance(obj_min_dist); - F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } + else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) + { + // don't FOV zoom on mostly transparent objects + F32 obj_min_dist = 0.f; + calcCameraMinDistance(obj_min_dist); + F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); - mFocusObjectDist = obj_min_dist - current_distance; + mFocusObjectDist = obj_min_dist - current_distance; - F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); - return new_fov_zoom; - } - else // focusing on land or avatar - { - // keep old field of view until user changes focus explicitly - return mCameraFOVZoomFactor; - //return 0.f; - } + F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); + return new_fov_zoom; + } + else // focusing on land or avatar + { + // keep old field of view until user changes focus explicitly + return mCameraFOVZoomFactor; + //return 0.f; + } } //----------------------------------------------------------------------------- @@ -1753,307 +1753,307 @@ F32 LLAgentCamera::calcCameraFOVZoomFactor() //----------------------------------------------------------------------------- LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) { - // Compute base camera position and look-at points. - F32 camera_land_height; - LLVector3d frame_center_global = !isAgentAvatarValid() ? - gAgent.getPositionGlobal() : - gAgent.getPosGlobalFromAgent(getAvatarRootPosition()); - - BOOL isConstrained = FALSE; - LLVector3d head_offset; - head_offset.setVec(mThirdPersonHeadOffset); - - LLVector3d camera_position_global; - - if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) - { - camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); - } - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull()) - { - LL_WARNS() << "Null avatar drawable!" << LL_ENDL; - return LLVector3d::zero; - } - - head_offset.clearVec(); - F32 fixup; + // Compute base camera position and look-at points. + F32 camera_land_height; + LLVector3d frame_center_global = !isAgentAvatarValid() ? + gAgent.getPositionGlobal() : + gAgent.getPosGlobalFromAgent(getAvatarRootPosition()); + + BOOL isConstrained = FALSE; + LLVector3d head_offset; + head_offset.setVec(mThirdPersonHeadOffset); + + LLVector3d camera_position_global; + + if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) + { + camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); + } + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + if (!isAgentAvatarValid() || gAgentAvatarp->mDrawable.isNull()) + { + LL_WARNS() << "Null avatar drawable!" << LL_ENDL; + return LLVector3d::zero; + } + + head_offset.clearVec(); + F32 fixup; if (gAgentAvatarp->hasPelvisFixup(fixup) && !gAgentAvatarp->isSitting()) - { - head_offset[VZ] -= fixup; - } - if (gAgentAvatarp->isSitting()) - { - head_offset.mdV[VZ] += 0.1; - } - - if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent()) - { - gAgentAvatarp->updateHeadOffset(); - head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX]; - head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY]; - head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; - const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix(); - camera_position_global = gAgent.getPosGlobalFromAgent - ((gAgentAvatarp->getPosition()+ - LLVector3(head_offset)*gAgentAvatarp->getRotation()) * mat); - } - else - { - head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; - camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global; - head_offset = head_offset * gAgentAvatarp->getRenderRotation(); - camera_position_global = camera_position_global + head_offset; - } - } - else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) - { - LLVector3 local_camera_offset; - F32 camera_distance = 0.f; - - if (mSitCameraEnabled - && isAgentAvatarValid() - && gAgentAvatarp->isSitting() - && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); - - camera_position_global = gAgent.getPosGlobalFromAgent(target_pos); - } - else - { + { + head_offset[VZ] -= fixup; + } + if (gAgentAvatarp->isSitting()) + { + head_offset.mdV[VZ] += 0.1; + } + + if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent()) + { + gAgentAvatarp->updateHeadOffset(); + head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX]; + head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY]; + head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; + const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix(); + camera_position_global = gAgent.getPosGlobalFromAgent + ((gAgentAvatarp->getPosition()+ + LLVector3(head_offset)*gAgentAvatarp->getRotation()) * mat); + } + else + { + head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ]; + camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global; + head_offset = head_offset * gAgentAvatarp->getRenderRotation(); + camera_position_global = camera_position_global + head_offset; + } + } + else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) + { + LLVector3 local_camera_offset; + F32 camera_distance = 0.f; + + if (mSitCameraEnabled + && isAgentAvatarValid() + && gAgentAvatarp->isSitting() + && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); + + camera_position_global = gAgent.getPosGlobalFromAgent(target_pos); + } + else + { static LLCachedControl camera_offset_scale(gSavedSettings, "CameraOffsetScale"); local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * camera_offset_scale; - // are we sitting down? - if (isAgentAvatarValid() && gAgentAvatarp->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot; - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis * ~parent_rot); - - local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; - } - else - { - local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); - } - - if (!isDisableCameraConstraints() && !mCameraCollidePlane.isExactlyZero() && - (!isAgentAvatarValid() || !gAgentAvatarp->isSitting())) - { - LLVector3 plane_normal; - plane_normal.setVec(mCameraCollidePlane.mV); - - F32 offset_dot_norm = local_camera_offset * plane_normal; - if (llabs(offset_dot_norm) < 0.001f) - { - offset_dot_norm = 0.001f; - } - - camera_distance = local_camera_offset.normalize(); - - F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; - - // if agent is outside the colliding half-plane - if (pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - // check to see if camera is on the opposite side (inside) the half-plane - if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) - { - // diminish offset by factor to push it back outside the half-plane - camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; - } - } - else - { - if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; - } - } - } - else - { - camera_distance = local_camera_offset.normalize(); - } - - mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); - - if (mTargetCameraDistance != mCurrentCameraDistance) - { - F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); - - mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); - } - - // Make the camera distance current - local_camera_offset *= mCurrentCameraDistance; - - // set the global camera position - LLVector3d camera_offset; - - camera_offset.setVec( local_camera_offset ); - camera_position_global = frame_center_global + head_offset + camera_offset; - - if (isAgentAvatarValid()) - { - LLVector3d camera_lag_d; - F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); - LLVector3 target_lag; - LLVector3 vel = gAgent.getVelocity(); - - // lag by appropriate amount for flying - F32 time_in_air = gAgentAvatarp->mTimeInAir.getElapsedTimeF32(); - if(!mCameraAnimating && gAgentAvatarp->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) - { - LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis(); - frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector()); - frame_at_axis.normalize(); - - //transition smoothly in air mode, to avoid camera pop - F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; - u = llclamp(u, 0.f, 1.f); - - lag_interp *= u; - - if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == gAgentAvatarp->getID()) - { - // disable camera lag when using mouse-directed steering - target_lag.clearVec(); - } - else - { - target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; - } - - mCameraLag = lerp(mCameraLag, target_lag, lag_interp); - - F32 lag_dist = mCameraLag.magVec(); - if (lag_dist > MAX_CAMERA_LAG) - { - mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; - } - - // clamp camera lag so that avatar is always in front - F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; - if (dot < -(MIN_CAMERA_LAG * u)) - { - mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; - } - } - else - { - mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); - } - - camera_lag_d.setVec(mCameraLag); - camera_position_global = camera_position_global - camera_lag_d; - } - } - } - else - { - LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); - // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value - camera_position_global = focusPosGlobal + mCameraFocusOffset; - } - - if (!isDisableCameraConstraints() && !gAgent.isGodlike()) - { - LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); - bool constrain = true; - if(regionp && regionp->canManageEstate()) - { - constrain = false; - } - if(constrain) - { - F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance; - - LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal(); - F32 camera_distance = (F32)camera_offset.magVec(); - - if(camera_distance > max_dist) - { - camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset; - isConstrained = TRUE; - } - } + // are we sitting down? + if (isAgentAvatarValid() && gAgentAvatarp->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)gAgentAvatarp->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot; + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~parent_rot); + + local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; + } + else + { + local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); + } + + if (!isDisableCameraConstraints() && !mCameraCollidePlane.isExactlyZero() && + (!isAgentAvatarValid() || !gAgentAvatarp->isSitting())) + { + LLVector3 plane_normal; + plane_normal.setVec(mCameraCollidePlane.mV); + + F32 offset_dot_norm = local_camera_offset * plane_normal; + if (llabs(offset_dot_norm) < 0.001f) + { + offset_dot_norm = 0.001f; + } + + camera_distance = local_camera_offset.normalize(); + + F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; + + // if agent is outside the colliding half-plane + if (pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + // check to see if camera is on the opposite side (inside) the half-plane + if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) + { + // diminish offset by factor to push it back outside the half-plane + camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; + } + } + else + { + if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; + } + } + } + else + { + camera_distance = local_camera_offset.normalize(); + } + + mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); + + if (mTargetCameraDistance != mCurrentCameraDistance) + { + F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + + mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); + } + + // Make the camera distance current + local_camera_offset *= mCurrentCameraDistance; + + // set the global camera position + LLVector3d camera_offset; + + camera_offset.setVec( local_camera_offset ); + camera_position_global = frame_center_global + head_offset + camera_offset; + + if (isAgentAvatarValid()) + { + LLVector3d camera_lag_d; + F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); + LLVector3 target_lag; + LLVector3 vel = gAgent.getVelocity(); + + // lag by appropriate amount for flying + F32 time_in_air = gAgentAvatarp->mTimeInAir.getElapsedTimeF32(); + if(!mCameraAnimating && gAgentAvatarp->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) + { + LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis(); + frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector()); + frame_at_axis.normalize(); + + //transition smoothly in air mode, to avoid camera pop + F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; + u = llclamp(u, 0.f, 1.f); + + lag_interp *= u; + + if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == gAgentAvatarp->getID()) + { + // disable camera lag when using mouse-directed steering + target_lag.clearVec(); + } + else + { + target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; + } + + mCameraLag = lerp(mCameraLag, target_lag, lag_interp); + + F32 lag_dist = mCameraLag.magVec(); + if (lag_dist > MAX_CAMERA_LAG) + { + mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; + } + + // clamp camera lag so that avatar is always in front + F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; + if (dot < -(MIN_CAMERA_LAG * u)) + { + mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; + } + } + else + { + mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); + } + + camera_lag_d.setVec(mCameraLag); + camera_position_global = camera_position_global - camera_lag_d; + } + } + } + else + { + LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); + // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value + camera_position_global = focusPosGlobal + mCameraFocusOffset; + } + + if (!isDisableCameraConstraints() && !gAgent.isGodlike()) + { + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); + bool constrain = true; + if(regionp && regionp->canManageEstate()) + { + constrain = false; + } + if(constrain) + { + F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance; + + LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal(); + F32 camera_distance = (F32)camera_offset.magVec(); + + if(camera_distance > max_dist) + { + camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset; + isConstrained = TRUE; + } + } // JC - Could constrain camera based on parcel stuff here. -// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); -// -// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) -// { -// camera_position_global = last_position_global; +// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); // -// isConstrained = TRUE; -// } - } +// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) +// { +// camera_position_global = last_position_global; +// +// isConstrained = TRUE; +// } + } - // Don't let camera go underground - F32 camera_min_off_ground = getCameraMinOffGround(); - camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); - F32 minZ = llmax(F_ALMOST_ZERO, camera_land_height + camera_min_off_ground); - if (camera_position_global.mdV[VZ] < minZ) - { - camera_position_global.mdV[VZ] = minZ; - isConstrained = TRUE; - } + // Don't let camera go underground + F32 camera_min_off_ground = getCameraMinOffGround(); + camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); + F32 minZ = llmax(F_ALMOST_ZERO, camera_land_height + camera_min_off_ground); + if (camera_position_global.mdV[VZ] < minZ) + { + camera_position_global.mdV[VZ] = minZ; + isConstrained = TRUE; + } - if (hit_limit) - { - *hit_limit = isConstrained; - } + if (hit_limit) + { + *hit_limit = isConstrained; + } - return camera_position_global; + return camera_position_global; } LLVector3 LLAgentCamera::getCurrentCameraOffset() { - return (LLViewerCamera::getInstance()->getOrigin() - getAvatarRootPosition() - mThirdPersonHeadOffset) * ~getCurrentAvatarRotation(); + return (LLViewerCamera::getInstance()->getOrigin() - getAvatarRootPosition() - mThirdPersonHeadOffset) * ~getCurrentAvatarRotation(); } LLVector3d LLAgentCamera::getCurrentFocusOffset() { - return (mFocusTargetGlobal - gAgent.getPositionGlobal()) * ~getCurrentAvatarRotation(); + return (mFocusTargetGlobal - gAgent.getPositionGlobal()) * ~getCurrentAvatarRotation(); } LLQuaternion LLAgentCamera::getCurrentAvatarRotation() { - LLViewerObject* sit_object = (LLViewerObject*)gAgentAvatarp->getParent(); - - LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); - LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; - return av_rot * obj_rot; + LLViewerObject* sit_object = (LLViewerObject*)gAgentAvatarp->getParent(); + + LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); + LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; + return av_rot * obj_rot; } bool LLAgentCamera::isJoystickCameraUsed() { - return ((mOrbitAroundRadians != 0) || (mOrbitOverAngle != 0) || !mPanFocusDiff.isNull()); + return ((mOrbitAroundRadians != 0) || (mOrbitOverAngle != 0) || !mPanFocusDiff.isNull()); } LLVector3 LLAgentCamera::getCameraOffsetInitial() { // getCameraOffsetInitial and getFocusOffsetInitial can be called on update from idle before init() static LLCachedControl camera_offset_initial (gSavedSettings, "CameraOffsetRearView", LLVector3()); - return camera_offset_initial; + return camera_offset_initial; } LLVector3d LLAgentCamera::getFocusOffsetInitial() { static LLCachedControl focus_offset_initial(gSavedSettings, "FocusOffsetRearView", LLVector3d()); - return focus_offset_initial; + return focus_offset_initial; } F32 LLAgentCamera::getCameraMaxZoomDistance() @@ -2082,48 +2082,48 @@ LLVector3 LLAgentCamera::getAvatarRootPosition() //----------------------------------------------------------------------------- void LLAgentCamera::handleScrollWheel(S32 clicks) { - if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar()) - { - if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place - { - mFollowCam.zoom(clicks); - if (mFollowCam.isZoomedToMinimumDistance()) - { - changeCameraToMouselook(FALSE); - } - } - } - else - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); - - // Block if camera is animating - if (mCameraAnimating) - { - return; - } - - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom_factor = (F32)pow(0.8, -clicks); - cameraZoomIn(zoom_factor); - } - else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON)) - { - F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); - - F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); - current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); - - cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); - } - else - { - F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); - cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); - } - } + if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar()) + { + if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place + { + mFollowCam.zoom(clicks); + if (mFollowCam.isZoomedToMinimumDistance()) + { + changeCameraToMouselook(FALSE); + } + } + } + else + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); + + // Block if camera is animating + if (mCameraAnimating) + { + return; + } + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom_factor = (F32)pow(0.8, -clicks); + cameraZoomIn(zoom_factor); + } + else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON)) + { + F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); + + F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); + current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); + + cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); + } + else + { + F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); + cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); + } + } } @@ -2132,17 +2132,17 @@ void LLAgentCamera::handleScrollWheel(S32 clicks) //----------------------------------------------------------------------------- F32 LLAgentCamera::getCameraMinOffGround() { - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } - if (isDisableCameraConstraints()) - { - return -1000.f; - } + if (isDisableCameraConstraints()) + { + return -1000.f; + } - return 0.5f; + return 0.5f; } @@ -2151,15 +2151,15 @@ F32 LLAgentCamera::getCameraMinOffGround() //----------------------------------------------------------------------------- void LLAgentCamera::resetCamera() { - // Remove any pitch from the avatar - LLVector3 at = gAgent.getFrameAgent().getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - // have to explicitly clear field of view zoom now - mCameraFOVZoomFactor = 0.f; + // Remove any pitch from the avatar + LLVector3 at = gAgent.getFrameAgent().getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + // have to explicitly clear field of view zoom now + mCameraFOVZoomFactor = 0.f; - updateCamera(); + updateCamera(); } //----------------------------------------------------------------------------- @@ -2167,58 +2167,58 @@ void LLAgentCamera::resetCamera() //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToMouselook(BOOL animate) { - if (!gSavedSettings.getBOOL("EnableMouselook") - || LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - // visibility changes at end of animation - gViewerWindow->getWindow()->resetBusyCount(); - - // Menus should not remain open on switching to mouselook... - LLMenuGL::sMenuContainer->hideMenus(); - LLUI::getInstance()->clearPopups(); - - // unpause avatar animation - gAgent.unpauseAnimation(); - - LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - - if (isAgentAvatarValid()) - { - gAgentAvatarp->stopMotion(ANIM_AGENT_BODY_NOISE); - gAgentAvatarp->stopMotion(ANIM_AGENT_BREATHE_ROT); - } - - //gViewerWindow->stopGrab(); - LLSelectMgr::getInstance()->deselectAll(); - gViewerWindow->hideCursor(); - gViewerWindow->moveCursorToCenter(); - - if (mCameraMode != CAMERA_MODE_MOUSELOOK) - { - gFocusMgr.setKeyboardFocus(NULL); - - updateLastCamera(); - mCameraMode = CAMERA_MODE_MOUSELOOK; - const U32 old_flags = gAgent.getControlFlags(); - gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != gAgent.getControlFlags()) - { - gAgent.setFlagsDirty(); - } - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - gAgent.endAnimationUpdateUI(); - } - } + if (!gSavedSettings.getBOOL("EnableMouselook") + || LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + // visibility changes at end of animation + gViewerWindow->getWindow()->resetBusyCount(); + + // Menus should not remain open on switching to mouselook... + LLMenuGL::sMenuContainer->hideMenus(); + LLUI::getInstance()->clearPopups(); + + // unpause avatar animation + gAgent.unpauseAnimation(); + + LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); + + if (isAgentAvatarValid()) + { + gAgentAvatarp->stopMotion(ANIM_AGENT_BODY_NOISE); + gAgentAvatarp->stopMotion(ANIM_AGENT_BREATHE_ROT); + } + + //gViewerWindow->stopGrab(); + LLSelectMgr::getInstance()->deselectAll(); + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + + if (mCameraMode != CAMERA_MODE_MOUSELOOK) + { + gFocusMgr.setKeyboardFocus(NULL); + + updateLastCamera(); + mCameraMode = CAMERA_MODE_MOUSELOOK; + const U32 old_flags = gAgent.getControlFlags(); + gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != gAgent.getControlFlags()) + { + gAgent.setFlagsDirty(); + } + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + } } @@ -2227,24 +2227,24 @@ void LLAgentCamera::changeCameraToMouselook(BOOL animate) //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToDefault() { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } - if (LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) - { - changeCameraToFollow(); - } - else - { - changeCameraToThirdPerson(); - } - if (gSavedSettings.getBOOL("HideUIControls")) - { - gViewerWindow->setUIVisibility(false); - LLPanelStandStopFlying::getInstance()->setVisible(false); - } + if (LLFollowCamMgr::getInstance()->getActiveFollowCamParams()) + { + changeCameraToFollow(); + } + else + { + changeCameraToThirdPerson(); + } + if (gSavedSettings.getBOOL("HideUIControls")) + { + gViewerWindow->setUIVisibility(false); + LLPanelStandStopFlying::getInstance()->setVisible(false); + } } @@ -2253,53 +2253,53 @@ void LLAgentCamera::changeCameraToDefault() //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToFollow(BOOL animate) { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - if(mCameraMode != CAMERA_MODE_FOLLOW) - { - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - animate = FALSE; - } - startCameraAnimation(); - - updateLastCamera(); - mCameraMode = CAMERA_MODE_FOLLOW; - - // bang-in the current focus, position, and up vector of the follow cam - mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); - - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - if (isAgentAvatarValid()) - { - // SL-315 - gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); - gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); - gAgentAvatarp->startMotion( ANIM_AGENT_BREATHE_ROT ); - } - - // unpause avatar animation - gAgent.unpauseAnimation(); - - gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - gAgent.endAnimationUpdateUI(); - } - } + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + if(mCameraMode != CAMERA_MODE_FOLLOW) + { + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + animate = FALSE; + } + startCameraAnimation(); + + updateLastCamera(); + mCameraMode = CAMERA_MODE_FOLLOW; + + // bang-in the current focus, position, and up vector of the follow cam + mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); + + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + if (isAgentAvatarValid()) + { + // SL-315 + gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); + gAgentAvatarp->startMotion( ANIM_AGENT_BODY_NOISE ); + gAgentAvatarp->startMotion( ANIM_AGENT_BREATHE_ROT ); + } + + // unpause avatar animation + gAgent.unpauseAnimation(); + + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + } } //----------------------------------------------------------------------------- @@ -2307,69 +2307,69 @@ void LLAgentCamera::changeCameraToFollow(BOOL animate) //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - gViewerWindow->getWindow()->resetBusyCount(); - - mCameraZoomFraction = INITIAL_ZOOM_FRACTION; - - if (isAgentAvatarValid()) - { - if (!gAgentAvatarp->isSitting()) - { - // SL-315 - gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); - } - gAgentAvatarp->startMotion(ANIM_AGENT_BODY_NOISE); - gAgentAvatarp->startMotion(ANIM_AGENT_BREATHE_ROT); - } - - LLVector3 at_axis; - - // unpause avatar animation - gAgent.unpauseAnimation(); - - if (mCameraMode != CAMERA_MODE_THIRD_PERSON) - { - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - mCameraLag.clearVec(); - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - mCurrentCameraDistance = MIN_CAMERA_DISTANCE; - mTargetCameraDistance = MIN_CAMERA_DISTANCE; - animate = FALSE; - } - updateLastCamera(); - mCameraMode = CAMERA_MODE_THIRD_PERSON; - gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - } - - // Remove any pitch from the avatar - if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) - { - at_axis = gAgent.getFrameAgent().getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis); - } - - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - gAgent.endAnimationUpdateUI(); - } + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + gViewerWindow->getWindow()->resetBusyCount(); + + mCameraZoomFraction = INITIAL_ZOOM_FRACTION; + + if (isAgentAvatarValid()) + { + if (!gAgentAvatarp->isSitting()) + { + // SL-315 + gAgentAvatarp->mPelvisp->setPosition(LLVector3::zero); + } + gAgentAvatarp->startMotion(ANIM_AGENT_BODY_NOISE); + gAgentAvatarp->startMotion(ANIM_AGENT_BREATHE_ROT); + } + + LLVector3 at_axis; + + // unpause avatar animation + gAgent.unpauseAnimation(); + + if (mCameraMode != CAMERA_MODE_THIRD_PERSON) + { + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + mCameraLag.clearVec(); + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + mCurrentCameraDistance = MIN_CAMERA_DISTANCE; + mTargetCameraDistance = MIN_CAMERA_DISTANCE; + animate = FALSE; + } + updateLastCamera(); + mCameraMode = CAMERA_MODE_THIRD_PERSON; + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + } + + // Remove any pitch from the avatar + if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) + { + at_axis = gAgent.getFrameAgent().getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis); + } + + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } } //----------------------------------------------------------------------------- @@ -2377,89 +2377,89 @@ void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) //----------------------------------------------------------------------------- void LLAgentCamera::changeCameraToCustomizeAvatar() { - if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) - { - return; - } + if (LLViewerJoystick::getInstance()->getOverrideCamera() || !isAgentAvatarValid()) + { + return; + } - gAgent.standUp(); // force stand up - gViewerWindow->getWindow()->resetBusyCount(); + gAgent.standUp(); // force stand up + gViewerWindow->getWindow()->resetBusyCount(); if (LLSelectMgr::getInstance()->getSelection()->isAttachment()) { LLSelectMgr::getInstance()->deselectAll(); } - if (gFaceEditToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); - } - - startCameraAnimation(); - - if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) - { - updateLastCamera(); - mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; - gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); - - gFocusMgr.setKeyboardFocus( NULL ); - gFocusMgr.setMouseCapture( NULL ); - if( gMorphView ) - { - gMorphView->setVisible( TRUE ); - } - // Remove any pitch or rotation from the avatar - LLVector3 at = gAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - - gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); - gAgent.setCustomAnim(TRUE); - gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); - LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); - - if (turn_motion) - { - // delay camera animation long enough to play through turn animation - setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); - } - } - - LLVector3 agent_at = gAgent.getAtAxis(); - agent_at.mV[VZ] = 0.f; - agent_at.normalize(); - - // default focus point for customize avatar - LLVector3 focus_target = isAgentAvatarValid() - ? gAgentAvatarp->mHeadp->getWorldPosition() - : gAgent.getPositionAgent(); - - LLVector3d camera_offset(agent_at * -1.0); - // push camera up and out from avatar - camera_offset.mdV[VZ] = 0.1f; - camera_offset *= CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST; - LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); - setAnimationDuration(gSavedSettings.getF32("ZoomTime")); - setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID()); + if (gFaceEditToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); + } + + startCameraAnimation(); + + if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) + { + updateLastCamera(); + mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + + gFocusMgr.setKeyboardFocus( NULL ); + gFocusMgr.setMouseCapture( NULL ); + if( gMorphView ) + { + gMorphView->setVisible( TRUE ); + } + // Remove any pitch or rotation from the avatar + LLVector3 at = gAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + + gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); + gAgent.setCustomAnim(TRUE); + gAgentAvatarp->startMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = gAgentAvatarp->findMotion(ANIM_AGENT_CUSTOMIZE); + + if (turn_motion) + { + // delay camera animation long enough to play through turn animation + setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); + } + } + + LLVector3 agent_at = gAgent.getAtAxis(); + agent_at.mV[VZ] = 0.f; + agent_at.normalize(); + + // default focus point for customize avatar + LLVector3 focus_target = isAgentAvatarValid() + ? gAgentAvatarp->mHeadp->getWorldPosition() + : gAgent.getPositionAgent(); + + LLVector3d camera_offset(agent_at * -1.0); + // push camera up and out from avatar + camera_offset.mdV[VZ] = 0.1f; + camera_offset *= CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST; + LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); + setAnimationDuration(gSavedSettings.getF32("ZoomTime")); + setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID()); } void LLAgentCamera::switchCameraPreset(ECameraPreset preset) { - //zoom is supposed to be reset for the front and group views - mCameraZoomFraction = 1.f; + //zoom is supposed to be reset for the front and group views + mCameraZoomFraction = 1.f; - //focusing on avatar in that case means following him on movements - mFocusOnAvatar = TRUE; + //focusing on avatar in that case means following him on movements + mFocusOnAvatar = TRUE; - mCameraPreset = preset; + mCameraPreset = preset; - resetPanDiff(); - resetOrbitDiff(); + resetPanDiff(); + resetOrbitDiff(); - gSavedSettings.setU32("CameraPresetType", mCameraPreset); + gSavedSettings.setU32("CameraPresetType", mCameraPreset); } @@ -2468,17 +2468,17 @@ void LLAgentCamera::switchCameraPreset(ECameraPreset preset) // void LLAgentCamera::setAnimationDuration(F32 duration) -{ - if (mCameraAnimating) - { - // do not cut any existing camera animation short - F32 animation_left = llmax(0.f, mAnimationDuration - mAnimationTimer.getElapsedTimeF32()); - mAnimationDuration = llmax(duration, animation_left); - } - else - { - mAnimationDuration = duration; - } +{ + if (mCameraAnimating) + { + // do not cut any existing camera animation short + F32 animation_left = llmax(0.f, mAnimationDuration - mAnimationTimer.getElapsedTimeF32()); + mAnimationDuration = llmax(duration, animation_left); + } + else + { + mAnimationDuration = duration; + } } //----------------------------------------------------------------------------- @@ -2486,11 +2486,11 @@ void LLAgentCamera::setAnimationDuration(F32 duration) //----------------------------------------------------------------------------- void LLAgentCamera::startCameraAnimation() { - mAnimationCameraStartGlobal = getCameraPositionGlobal(); - mAnimationFocusStartGlobal = mFocusGlobal; - setAnimationDuration(gSavedSettings.getF32("ZoomTime")); - mAnimationTimer.reset(); - mCameraAnimating = TRUE; + mAnimationCameraStartGlobal = getCameraPositionGlobal(); + mAnimationFocusStartGlobal = mFocusGlobal; + setAnimationDuration(gSavedSettings.getF32("ZoomTime")); + mAnimationTimer.reset(); + mCameraAnimating = TRUE; } //----------------------------------------------------------------------------- @@ -2498,23 +2498,23 @@ void LLAgentCamera::startCameraAnimation() //----------------------------------------------------------------------------- void LLAgentCamera::stopCameraAnimation() { - mCameraAnimating = FALSE; + mCameraAnimating = FALSE; } void LLAgentCamera::clearFocusObject() { - if (mFocusObject.notNull()) - { - startCameraAnimation(); + if (mFocusObject.notNull()) + { + startCameraAnimation(); - setFocusObject(NULL); - mFocusObjectOffset.clearVec(); - } + setFocusObject(NULL); + mFocusObjectOffset.clearVec(); + } } void LLAgentCamera::setFocusObject(LLViewerObject* object) { - mFocusObject = object; + mFocusObject = object; } // Focus on a point, but try to keep camera position stable. @@ -2523,104 +2523,104 @@ void LLAgentCamera::setFocusObject(LLViewerObject* object) //----------------------------------------------------------------------------- void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick) { - LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); + LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); - if (objectp && pick.mGLTFNodeIndex == -1) - { - // focus on object plus designated offset - // which may or may not be same as pick.mPosGlobal - setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); - } - else - { - // focus directly on point where user clicked - setFocusGlobal(pick.mPosGlobal, pick.mObjectID); - } + if (objectp && pick.mGLTFNodeIndex == -1) + { + // focus on object plus designated offset + // which may or may not be same as pick.mPosGlobal + setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); + } + else + { + // focus directly on point where user clicked + setFocusGlobal(pick.mPosGlobal, pick.mObjectID); + } } void LLAgentCamera::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) { - setFocusObject(gObjectList.findObject(object_id)); - LLVector3d old_focus = mFocusTargetGlobal; - LLViewerObject *focus_obj = mFocusObject; - - // if focus has changed - if (old_focus != focus) - { - if (focus.isExactlyZero()) - { - if (isAgentAvatarValid()) - { - mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = gAgent.getPositionGlobal(); - } - mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; - mCameraFocusOffset = mCameraFocusOffsetTarget; - setLookAt(LOOKAT_TARGET_CLEAR); - } - else - { - mFocusTargetGlobal = focus; - if (!focus_obj) - { - mCameraFOVZoomFactor = 0.f; - } - - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; - - startCameraAnimation(); - - if (focus_obj) - { - if (focus_obj->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (gAgent.getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); - } - } - } - else // focus == mFocusTargetGlobal - { - if (focus.isExactlyZero()) - { - if (isAgentAvatarValid()) - { - mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = gAgent.getPositionGlobal(); - } - } - mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; - mCameraFocusOffset = mCameraFocusOffsetTarget; - } - - if (mFocusObject.notNull()) - { - // for attachments, make offset relative to avatar, not the attachment - if (mFocusObject->isAttachment()) - { - while (mFocusObject.notNull() && !mFocusObject->isAvatar()) - { - mFocusObject = (LLViewerObject*) mFocusObject->getParent(); - } - setFocusObject((LLViewerObject*)mFocusObject); - } - updateFocusOffset(); - } + setFocusObject(gObjectList.findObject(object_id)); + LLVector3d old_focus = mFocusTargetGlobal; + LLViewerObject *focus_obj = mFocusObject; + + // if focus has changed + if (old_focus != focus) + { + if (focus.isExactlyZero()) + { + if (isAgentAvatarValid()) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = gAgent.getPositionGlobal(); + } + mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; + mCameraFocusOffset = mCameraFocusOffsetTarget; + setLookAt(LOOKAT_TARGET_CLEAR); + } + else + { + mFocusTargetGlobal = focus; + if (!focus_obj) + { + mCameraFOVZoomFactor = 0.f; + } + + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; + + startCameraAnimation(); + + if (focus_obj) + { + if (focus_obj->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (gAgent.getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + } + } + } + else // focus == mFocusTargetGlobal + { + if (focus.isExactlyZero()) + { + if (isAgentAvatarValid()) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = gAgent.getPositionGlobal(); + } + } + mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; + mCameraFocusOffset = mCameraFocusOffsetTarget; + } + + if (mFocusObject.notNull()) + { + // for attachments, make offset relative to avatar, not the attachment + if (mFocusObject->isAttachment()) + { + while (mFocusObject.notNull() && !mFocusObject->isAvatar()) + { + mFocusObject = (LLViewerObject*) mFocusObject->getParent(); + } + setFocusObject((LLViewerObject*)mFocusObject); + } + updateFocusOffset(); + } } // Used for avatar customization @@ -2629,48 +2629,48 @@ void LLAgentCamera::setFocusGlobal(const LLVector3d& focus, const LLUUID &object //----------------------------------------------------------------------------- void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id) { - LLVector3d old_focus = mFocusTargetGlobal.isExactlyZero() ? focus : mFocusTargetGlobal; - - F64 focus_delta_squared = (old_focus - focus).magVecSquared(); - const F64 ANIM_EPSILON_SQUARED = 0.0001; - if (focus_delta_squared > ANIM_EPSILON_SQUARED) - { - startCameraAnimation(); - } - - //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); - setFocusObject(gObjectList.findObject(object_id)); - mFocusTargetGlobal = focus; - mCameraFocusOffsetTarget = camera_pos - focus; - mCameraFocusOffset = mCameraFocusOffsetTarget; - - if (mFocusObject) - { - if (mFocusObject->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (gAgent.getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); - } - - if (mCameraAnimating) - { - const F64 ANIM_METERS_PER_SECOND = 10.0; - const F64 MIN_ANIM_SECONDS = 0.5; - const F64 MAX_ANIM_SECONDS = 10.0; - F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); - anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); - setAnimationDuration( (F32)anim_duration ); - } - - updateFocusOffset(); + LLVector3d old_focus = mFocusTargetGlobal.isExactlyZero() ? focus : mFocusTargetGlobal; + + F64 focus_delta_squared = (old_focus - focus).magVecSquared(); + const F64 ANIM_EPSILON_SQUARED = 0.0001; + if (focus_delta_squared > ANIM_EPSILON_SQUARED) + { + startCameraAnimation(); + } + + //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); + setFocusObject(gObjectList.findObject(object_id)); + mFocusTargetGlobal = focus; + mCameraFocusOffsetTarget = camera_pos - focus; + mCameraFocusOffset = mCameraFocusOffsetTarget; + + if (mFocusObject) + { + if (mFocusObject->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (gAgent.getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + } + + if (mCameraAnimating) + { + const F64 ANIM_METERS_PER_SECOND = 10.0; + const F64 MIN_ANIM_SECONDS = 0.5; + const F64 MAX_ANIM_SECONDS = 10.0; + F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); + anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); + setAnimationDuration( (F32)anim_duration ); + } + + updateFocusOffset(); } //----------------------------------------------------------------------------- @@ -2678,27 +2678,27 @@ void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, con //----------------------------------------------------------------------------- void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus) { - BOOL camera_enabled = !object_id.isNull(); - - if (camera_enabled) - { - LLViewerObject *reference_object = gObjectList.findObject(object_id); - if (reference_object) - { - //convert to root object relative? - mSitCameraPos = camera_pos; - mSitCameraFocus = camera_focus; - mSitCameraReferenceObject = reference_object; - mSitCameraEnabled = TRUE; - } - } - else - { - mSitCameraPos.clearVec(); - mSitCameraFocus.clearVec(); - mSitCameraReferenceObject = NULL; - mSitCameraEnabled = FALSE; - } + BOOL camera_enabled = !object_id.isNull(); + + if (camera_enabled) + { + LLViewerObject *reference_object = gObjectList.findObject(object_id); + if (reference_object) + { + //convert to root object relative? + mSitCameraPos = camera_pos; + mSitCameraFocus = camera_focus; + mSitCameraReferenceObject = reference_object; + mSitCameraEnabled = TRUE; + } + } + else + { + mSitCameraPos.clearVec(); + mSitCameraFocus.clearVec(); + mSitCameraReferenceObject = NULL; + mSitCameraEnabled = FALSE; + } } //----------------------------------------------------------------------------- @@ -2706,30 +2706,30 @@ void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camer //----------------------------------------------------------------------------- void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate, BOOL reset_axes) { - if (focus_on_avatar != mFocusOnAvatar) - { - if (animate) - { - startCameraAnimation(); - } - else - { - stopCameraAnimation(); - } - } - - //RN: when focused on the avatar, we're not "looking" at it - // looking implies intent while focusing on avatar means - // you're just walking around with a camera on you...eesh. - if (!mFocusOnAvatar && focus_on_avatar && reset_axes) - { - setFocusGlobal(LLVector3d::zero); - mCameraFOVZoomFactor = 0.f; - if (mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - LLVector3 at_axis; - if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) - { + if (focus_on_avatar != mFocusOnAvatar) + { + if (animate) + { + startCameraAnimation(); + } + else + { + stopCameraAnimation(); + } + } + + //RN: when focused on the avatar, we're not "looking" at it + // looking implies intent while focusing on avatar means + // you're just walking around with a camera on you...eesh. + if (!mFocusOnAvatar && focus_on_avatar && reset_axes) + { + setFocusGlobal(LLVector3d::zero); + mCameraFOVZoomFactor = 0.f; + if (mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + LLVector3 at_axis; + if (!isAgentAvatarValid() || !gAgentAvatarp->getParent()) + { // In case of front view rotate agent to look into direction opposite to camera // In case of rear view rotate agent into diraction same as camera, e t c LLVector3 vect = getCameraOffsetInitial(); @@ -2743,44 +2743,44 @@ void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate, BOOL re at_axis.normalize(); gAgent.resetAxes(at_axis); gAgent.yaw(0); - } - } - } - // unlocking camera from avatar - else if (mFocusOnAvatar && !focus_on_avatar) - { - // keep camera focus point consistent, even though it is now unlocked - setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); - mAllowChangeToFollow = FALSE; - } - - mFocusOnAvatar = focus_on_avatar; + } + } + } + // unlocking camera from avatar + else if (mFocusOnAvatar && !focus_on_avatar) + { + // keep camera focus point consistent, even though it is now unlocked + setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); + mAllowChangeToFollow = FALSE; + } + + mFocusOnAvatar = focus_on_avatar; } BOOL LLAgentCamera::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) { - if(object && object->isAttachment()) - { - LLViewerObject* parent = object; - while(parent) - { - if (parent == gAgentAvatarp) - { - // looking at an attachment on ourselves, which we don't want to do - object = gAgentAvatarp; - position.clearVec(); - } - parent = (LLViewerObject*)parent->getParent(); - } - } - if(!mLookAt || mLookAt->isDead()) - { - mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); - mLookAt->setSourceObject(gAgentAvatarp); - } - - return mLookAt->setLookAt(target_type, object, position); + if(object && object->isAttachment()) + { + LLViewerObject* parent = object; + while(parent) + { + if (parent == gAgentAvatarp) + { + // looking at an attachment on ourselves, which we don't want to do + object = gAgentAvatarp; + position.clearVec(); + } + parent = (LLViewerObject*)parent->getParent(); + } + } + if(!mLookAt || mLookAt->isDead()) + { + mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); + mLookAt->setSourceObject(gAgentAvatarp); + } + + return mLookAt->setLookAt(target_type, object, position); } //----------------------------------------------------------------------------- @@ -2788,168 +2788,168 @@ BOOL LLAgentCamera::setLookAt(ELookAtType target_type, LLViewerObject *object, L //----------------------------------------------------------------------------- void LLAgentCamera::lookAtLastChat() { - // Block if camera is animating or not in normal third person camera mode - if (mCameraAnimating || !cameraThirdPerson()) - { - return; - } - - LLViewerObject *chatter = gObjectList.findObject(gAgent.getLastChatter()); - if (!chatter) - { - return; - } - - LLVector3 delta_pos; - if (chatter->isAvatar()) - { - LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; - if (isAgentAvatarValid() && chatter_av->mHeadp) - { - delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgentAvatarp->mHeadp->getWorldPosition(); - } - else - { - delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); - } - delta_pos.normalize(); - - gAgent.setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusOnAvatar(FALSE, FALSE); - - if (chatter_av->mHeadp) - { - setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter()); - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - } - else - { - setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - } - } - else - { - delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); - delta_pos.normalize(); - - gAgent.setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusOnAvatar(FALSE, FALSE); - - setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - } + // Block if camera is animating or not in normal third person camera mode + if (mCameraAnimating || !cameraThirdPerson()) + { + return; + } + + LLViewerObject *chatter = gObjectList.findObject(gAgent.getLastChatter()); + if (!chatter) + { + return; + } + + LLVector3 delta_pos; + if (chatter->isAvatar()) + { + LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; + if (isAgentAvatarValid() && chatter_av->mHeadp) + { + delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgentAvatarp->mHeadp->getWorldPosition(); + } + else + { + delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); + } + delta_pos.normalize(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + setFocusOnAvatar(FALSE, FALSE); + + if (chatter_av->mHeadp) + { + setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + } + else + { + setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + } + } + else + { + delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); + delta_pos.normalize(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgentAvatarp->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + setFocusOnAvatar(FALSE, FALSE); + + setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + } } bool LLAgentCamera::isfollowCamLocked() { - return mFollowCam.getPositionLocked(); + return mFollowCam.getPositionLocked(); } BOOL LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) { - // disallow pointing at attachments and avatars - if (object && (object->isAttachment() || object->isAvatar())) - { - return FALSE; - } - if (!mPointAt || mPointAt->isDead()) - { - mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); - mPointAt->setSourceObject(gAgentAvatarp); - } - return mPointAt->setPointAt(target_type, object, position); + // disallow pointing at attachments and avatars + if (object && (object->isAttachment() || object->isAvatar())) + { + return FALSE; + } + if (!mPointAt || mPointAt->isDead()) + { + mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); + mPointAt->setSourceObject(gAgentAvatarp); + } + return mPointAt->setPointAt(target_type, object, position); } void LLAgentCamera::rotateToInitSitRot() { - gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); - gAgent.rotate(mInitSitRot); + gAgent.rotate(~gAgent.getFrameAgent().getQuaternion()); + gAgent.rotate(mInitSitRot); } void LLAgentCamera::resetCameraZoomFraction() -{ - mCameraZoomFraction = INITIAL_ZOOM_FRACTION; +{ + mCameraZoomFraction = INITIAL_ZOOM_FRACTION; } ELookAtType LLAgentCamera::getLookAtType() { - if (mLookAt) - { - return mLookAt->getLookAtType(); - } - return LOOKAT_TARGET_NONE; + if (mLookAt) + { + return mLookAt->getLookAtType(); + } + return LOOKAT_TARGET_NONE; } EPointAtType LLAgentCamera::getPointAtType() -{ - if (mPointAt) - { - return mPointAt->getPointAtType(); - } - return POINTAT_TARGET_NONE; +{ + if (mPointAt) + { + return mPointAt->getPointAtType(); + } + return POINTAT_TARGET_NONE; } void LLAgentCamera::clearGeneralKeys() { - mAtKey = 0; - mWalkKey = 0; - mLeftKey = 0; - mUpKey = 0; - mYawKey = 0.f; - mPitchKey = 0.f; + mAtKey = 0; + mWalkKey = 0; + mLeftKey = 0; + mUpKey = 0; + mYawKey = 0.f; + mPitchKey = 0.f; } void LLAgentCamera::clearOrbitKeys() { - mOrbitLeftKey = 0.f; - mOrbitRightKey = 0.f; - mOrbitUpKey = 0.f; - mOrbitDownKey = 0.f; - mOrbitInKey = 0.f; - mOrbitOutKey = 0.f; + mOrbitLeftKey = 0.f; + mOrbitRightKey = 0.f; + mOrbitUpKey = 0.f; + mOrbitDownKey = 0.f; + mOrbitInKey = 0.f; + mOrbitOutKey = 0.f; } void LLAgentCamera::clearPanKeys() { - mPanRightKey = 0.f; - mPanLeftKey = 0.f; - mPanUpKey = 0.f; - mPanDownKey = 0.f; - mPanInKey = 0.f; - mPanOutKey = 0.f; + mPanRightKey = 0.f; + mPanLeftKey = 0.f; + mPanUpKey = 0.f; + mPanDownKey = 0.f; + mPanInKey = 0.f; + mPanOutKey = 0.f; } // static S32 LLAgentCamera::directionToKey(S32 direction) { - if (direction > 0) return 1; - if (direction < 0) return -1; - return 0; + if (direction > 0) return 1; + if (direction < 0) return -1; + return 0; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 90f9b38f2d..617cd18e9f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -108,7 +108,7 @@ #include "llscenemonitor.h" #include "llavatarrenderinfoaccountant.h" #include "lllocalbitmaps.h" -#include "llperfstats.h" +#include "llperfstats.h" #include "llgltfmateriallist.h" // Linden library includes @@ -148,7 +148,7 @@ #include #if LL_WINDOWS -# include // For _SH_DENYWR in processMarkerFiles +# include // For _SH_DENYWR in processMarkerFiles #else # include // For processMarkerFiles #endif @@ -319,16 +319,16 @@ const char* gPlatform = LL_PLATFORM_KEY; LLSD gDebugInfo; -U32 gFrameCount = 0; +U32 gFrameCount = 0; U32 gForegroundFrameCount = 0; // number of frames that app window was in foreground LLPumpIO* gServicePump = NULL; U64MicrosecondsImplicit gFrameTime = 0; F32SecondsImplicit gFrameTimeSeconds = 0.f; F32SecondsImplicit gFrameIntervalSeconds = 0.f; -F32 gFPSClamped = 10.f; // Pretend we start at target rate. -F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets -U64MicrosecondsImplicit gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds +F32 gFPSClamped = 10.f; // Pretend we start at target rate. +F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets +U64MicrosecondsImplicit gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds LLTimer gRenderStartTime; LLFrameTimer gForegroundTime; @@ -341,24 +341,24 @@ F32 gLogoutMaxTime = LOGOUT_REQUEST_TIME; S32 gPendingMetricsUploads = 0; -BOOL gDisconnected = FALSE; +BOOL gDisconnected = FALSE; // used to restore texture state after a mode switch -LLFrameTimer gRestoreGLTimer; -BOOL gRestoreGL = FALSE; -bool gUseWireframe = FALSE; +LLFrameTimer gRestoreGLTimer; +BOOL gRestoreGL = FALSE; +bool gUseWireframe = FALSE; LLMemoryInfo gSysMemory; U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp std::string gLastVersionChannel; -LLVector3 gWindVec(3.0, 3.0, 0.0); -LLVector3 gRelativeWindVec(0.0, 0.0, 0.0); +LLVector3 gWindVec(3.0, 3.0, 0.0); +LLVector3 gRelativeWindVec(0.0, 0.0, 0.0); -U32 gPacketsIn = 0; +U32 gPacketsIn = 0; -BOOL gPrintMessagesThisFrame = FALSE; +BOOL gPrintMessagesThisFrame = FALSE; BOOL gRandomizeFramerate = FALSE; BOOL gPeriodicSlowFrame = FALSE; @@ -393,53 +393,53 @@ const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; static std::set default_trans_args; void init_default_trans_args() { - default_trans_args.insert("SECOND_LIFE"); // World - default_trans_args.insert("APP_NAME"); - default_trans_args.insert("CAPITALIZED_APP_NAME"); - default_trans_args.insert("SECOND_LIFE_GRID"); - default_trans_args.insert("SUPPORT_SITE"); - // This URL shows up in a surprising number of places in various skin - // files. We really only want to have to maintain a single copy of it. - default_trans_args.insert("create_account_url"); + default_trans_args.insert("SECOND_LIFE"); // World + default_trans_args.insert("APP_NAME"); + default_trans_args.insert("CAPITALIZED_APP_NAME"); + default_trans_args.insert("SECOND_LIFE_GRID"); + default_trans_args.insert("SUPPORT_SITE"); + // This URL shows up in a surprising number of places in various skin + // files. We really only want to have to maintain a single copy of it. + default_trans_args.insert("create_account_url"); } struct SettingsFile : public LLInitParam::Block { - Mandatory name; - Optional file_name; - Optional required, - persistent; - Optional file_name_setting; - - SettingsFile() - : name("name"), - file_name("file_name"), - required("required", false), - persistent("persistent", true), - file_name_setting("file_name_setting") - {} + Mandatory name; + Optional file_name; + Optional required, + persistent; + Optional file_name_setting; + + SettingsFile() + : name("name"), + file_name("file_name"), + required("required", false), + persistent("persistent", true), + file_name_setting("file_name_setting") + {} }; struct SettingsGroup : public LLInitParam::Block { - Mandatory name; - Mandatory path_index; - Multiple files; - - SettingsGroup() - : name("name"), - path_index("path_index"), - files("file") - {} + Mandatory name; + Mandatory path_index; + Multiple files; + + SettingsGroup() + : name("name"), + path_index("path_index"), + files("file") + {} }; struct SettingsFiles : public LLInitParam::Block { - Multiple groups; + Multiple groups; - SettingsFiles() - : groups("group") - {} + SettingsFiles() + : groups("group") + {} }; static std::string gWindowTitle; @@ -454,122 +454,122 @@ static bool app_metrics_qa_mode = false; void idle_afk_check() { - // check idle timers - F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); - F32 afk_timeout = gSavedSettings.getS32("AFKTimeout"); - if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK()) - { - LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; - gAgent.setAFK(); - } + // check idle timers + F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); + F32 afk_timeout = gSavedSettings.getS32("AFKTimeout"); + if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK()) + { + LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; + gAgent.setAFK(); + } } // A callback set in LLAppViewer::init() static void ui_audio_callback(const LLUUID& uuid) { - if (gAudiop) - { - SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); - gAudiop->triggerSound(soundData); - } + if (gAudiop) + { + SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + gAudiop->triggerSound(soundData); + } } // A callback set in LLAppViewer::init() static void deferred_ui_audio_callback(const LLUUID& uuid) { - if (gAudiop) - { - SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); - LLDeferredSounds::instance().deferSound(soundData); - } + if (gAudiop) + { + SoundData soundData(uuid, gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + LLDeferredSounds::instance().deferSound(soundData); + } } -bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) +bool create_text_segment_icon_from_url_match(LLUrlMatch* match,LLTextBase* base) { - if(!match || !base || base->getPlainText()) - return false; - - LLUUID match_id = match->getID(); - - LLIconCtrl* icon; - - if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor - || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group - { - LLGroupIconCtrl::Params icon_params; - icon_params.group_id = match_id; - icon_params.rect = LLRect(0, 16, 16, 0); - icon_params.visible = true; - icon = LLUICtrlFactory::instance().create(icon_params); - } - else - { - LLAvatarIconCtrl::Params icon_params; - icon_params.avatar_id = match_id; - icon_params.rect = LLRect(0, 16, 16, 0); - icon_params.visible = true; - icon = LLUICtrlFactory::instance().create(icon_params); - } - - LLInlineViewSegment::Params params; - params.force_newline = false; - params.view = icon; - params.left_pad = 4; - params.right_pad = 4; - params.top_pad = -2; - params.bottom_pad = 2; - - base->appendWidget(params," ",false); - - return true; + if(!match || !base || base->getPlainText()) + return false; + + LLUUID match_id = match->getID(); + + LLIconCtrl* icon; + + if( match->getMenuName() == "menu_url_group.xml" // See LLUrlEntryGroup constructor + || gAgent.isInGroup(match_id, TRUE)) //This check seems unfiting, urls are either /agent or /group + { + LLGroupIconCtrl::Params icon_params; + icon_params.group_id = match_id; + icon_params.rect = LLRect(0, 16, 16, 0); + icon_params.visible = true; + icon = LLUICtrlFactory::instance().create(icon_params); + } + else + { + LLAvatarIconCtrl::Params icon_params; + icon_params.avatar_id = match_id; + icon_params.rect = LLRect(0, 16, 16, 0); + icon_params.visible = true; + icon = LLUICtrlFactory::instance().create(icon_params); + } + + LLInlineViewSegment::Params params; + params.force_newline = false; + params.view = icon; + params.left_pad = 4; + params.right_pad = 4; + params.top_pad = -2; + params.bottom_pad = 2; + + base->appendWidget(params," ",false); + + return true; } // Use these strictly for things that are constructed at startup, // or for things that are performance critical. JC static void settings_to_globals() { - LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad"); - BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); - BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); + LLBUTTON_H_PAD = gSavedSettings.getS32("ButtonHPad"); + BTN_HEIGHT_SMALL = gSavedSettings.getS32("ButtonHeightSmall"); + BTN_HEIGHT = gSavedSettings.getS32("ButtonHeight"); - MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight"); - MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth"); + MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight"); + MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth"); - LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); + LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); #if LL_DARWIN LLRender::sGLCoreProfile = true; #else LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile"); #endif - LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); - LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); - LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); - LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR); - LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; - LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); - LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); - LLVOAvatar::sLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR); - LLVOAvatar::sPhysicsLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR); - LLVOAvatar::updateImpostorRendering(gSavedSettings.getU32("RenderAvatarMaxNonImpostors")); - LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible"); - // clamp auto-open time to some minimum usable value - LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); - LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive"); - LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections"); - LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); - - gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns")); - gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns")); - gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle")); - - gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); - gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); + LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); + LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); + LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); + LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR); + LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; + LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); + LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); + LLVOAvatar::sLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR); + LLVOAvatar::sPhysicsLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR); + LLVOAvatar::updateImpostorRendering(gSavedSettings.getU32("RenderAvatarMaxNonImpostors")); + LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible"); + // clamp auto-open time to some minimum usable value + LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); + LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive"); + LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections"); + LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); + + gAgentPilot.setNumRuns(gSavedSettings.getS32("StatsNumRuns")); + gAgentPilot.setQuitAfterRuns(gSavedSettings.getBOOL("StatsQuitAfterRuns")); + gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle")); + + gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc"); + gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates"); LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); - + #if LL_DARWIN LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); - gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); + gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); #endif } @@ -587,41 +587,41 @@ static void settings_modify() class LLFastTimerLogThread : public LLThread { public: - std::string mFile; - - LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log") - { - std::string file_name = test_name + std::string(".slp"); - mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name); - } - - void run() - { - llofstream os(mFile.c_str()); - - while (!LLAppViewer::instance()->isQuitting()) - { - LLTrace::BlockTimer::writeLog(os); - os.flush(); - ms_sleep(32); - } - - os.close(); - } + std::string mFile; + + LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log") + { + std::string file_name = test_name + std::string(".slp"); + mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name); + } + + void run() + { + llofstream os(mFile.c_str()); + + while (!LLAppViewer::instance()->isQuitting()) + { + LLTrace::BlockTimer::writeLog(os); + os.flush(); + ms_sleep(32); + } + + os.close(); + } }; //virtual bool LLAppViewer::initSLURLHandler() { - // does nothing unless subclassed - return false; + // does nothing unless subclassed + return false; } //virtual bool LLAppViewer::sendURLToOtherInstance(const std::string& url) { - // does nothing unless subclassed - return false; + // does nothing unless subclassed + return false; } //---------------------------------------------------------------------------- @@ -637,402 +637,402 @@ LLPurgeDiskCacheThread* LLAppViewer::sPurgeDiskCacheThread = NULL; std::string getRuntime() { - return llformat("%.4f", (F32)LLTimer::getElapsedSeconds().value()); + return llformat("%.4f", (F32)LLTimer::getElapsedSeconds().value()); } LLAppViewer::LLAppViewer() -: mMarkerFile(), - mLogoutMarkerFile(), - mReportedCrash(false), - mNumSessions(0), +: mMarkerFile(), + mLogoutMarkerFile(), + mReportedCrash(false), + mNumSessions(0), mGeneralThreadPool(nullptr), - mPurgeCache(false), - mPurgeCacheOnExit(false), - mPurgeUserDataOnExit(false), - mSecondInstance(false), - mUpdaterNotFound(false), - mSavedFinalSnapshot(false), - mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. - mQuitRequested(false), - mLogoutRequestSent(false), - mLastAgentControlFlags(0), - mLastAgentForceUpdate(0), - mMainloopTimeout(NULL), - mAgentRegionLastAlive(false), - mRandomizeFramerate(LLCachedControl(gSavedSettings,"Randomize Framerate", FALSE)), - mPeriodicSlowFrame(LLCachedControl(gSavedSettings,"Periodic Slow Frame", FALSE)), - mFastTimerLogThread(NULL), - mSettingsLocationList(NULL), - mIsFirstRun(false) + mPurgeCache(false), + mPurgeCacheOnExit(false), + mPurgeUserDataOnExit(false), + mSecondInstance(false), + mUpdaterNotFound(false), + mSavedFinalSnapshot(false), + mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. + mQuitRequested(false), + mLogoutRequestSent(false), + mLastAgentControlFlags(0), + mLastAgentForceUpdate(0), + mMainloopTimeout(NULL), + mAgentRegionLastAlive(false), + mRandomizeFramerate(LLCachedControl(gSavedSettings,"Randomize Framerate", FALSE)), + mPeriodicSlowFrame(LLCachedControl(gSavedSettings,"Periodic Slow Frame", FALSE)), + mFastTimerLogThread(NULL), + mSettingsLocationList(NULL), + mIsFirstRun(false) { - if(NULL != sInstance) - { - LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL; - } + if(NULL != sInstance) + { + LL_ERRS() << "Oh no! An instance of LLAppViewer already exists! LLAppViewer is sort of like a singleton." << LL_ENDL; + } mDumpPath =""; - // Need to do this initialization before we do anything else, since anything - // that touches files should really go through the lldir API - gDirUtilp->initAppDirs("SecondLife"); - // - // IMPORTANT! Do NOT put anything that will write - // into the log files during normal startup until AFTER - // we run the "program crashed last time" error handler below. - // - sInstance = this; - - gLoggedInTime.stop(); - - processMarkerFiles(); - // - // OK to write stuff to logs now, we've now crash reported if necessary - // - - LLLoginInstance::instance().setPlatformInfo(gPlatform, LLOSInfo::instance().getOSVersionString(), LLOSInfo::instance().getOSStringSimple()); - - // Under some circumstances we want to read the static_debug_info.log file - // from the previous viewer run between this constructor call and the - // init() call, which will overwrite the static_debug_info.log file for - // THIS run. So setDebugFileNames() early. + // Need to do this initialization before we do anything else, since anything + // that touches files should really go through the lldir API + gDirUtilp->initAppDirs("SecondLife"); + // + // IMPORTANT! Do NOT put anything that will write + // into the log files during normal startup until AFTER + // we run the "program crashed last time" error handler below. + // + sInstance = this; + + gLoggedInTime.stop(); + + processMarkerFiles(); + // + // OK to write stuff to logs now, we've now crash reported if necessary + // + + LLLoginInstance::instance().setPlatformInfo(gPlatform, LLOSInfo::instance().getOSVersionString(), LLOSInfo::instance().getOSStringSimple()); + + // Under some circumstances we want to read the static_debug_info.log file + // from the previous viewer run between this constructor call and the + // init() call, which will overwrite the static_debug_info.log file for + // THIS run. So setDebugFileNames() early. # ifdef LL_BUGSPLAT - // MAINT-8917: don't create a dump directory just for the - // static_debug_info.log file - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + // MAINT-8917: don't create a dump directory just for the + // static_debug_info.log file + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); # else // ! LL_BUGSPLAT - // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); + // write Google Breakpad minidump files to a per-run dump directory to avoid multiple viewer issues. + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); # endif // ! LL_BUGSPLAT - mDumpPath = logdir; + mDumpPath = logdir; - setDebugFileNames(logdir); + setDebugFileNames(logdir); } LLAppViewer::~LLAppViewer() { - delete mSettingsLocationList; + delete mSettingsLocationList; - destroyMainloopTimeout(); + destroyMainloopTimeout(); - // If we got to this destructor somehow, the app didn't hang. - removeMarkerFiles(); + // If we got to this destructor somehow, the app didn't hang. + removeMarkerFiles(); } class LLUITranslationBridge : public LLTranslationBridge { public: - virtual std::string getString(const std::string &xml_desc) - { - return LLTrans::getString(xml_desc); - } + virtual std::string getString(const std::string &xml_desc) + { + return LLTrans::getString(xml_desc); + } }; bool LLAppViewer::init() { - setupErrorHandling(mSecondInstance); + setupErrorHandling(mSecondInstance); - // - // Start of the application - // + // + // Start of the application + // // initialize the LLSettingsType translation bridge. LLTranslationBridge::ptr_t trans = std::make_shared(); LLSettingsType::initParamSingleton(trans); - // initialize SSE options - LLVector4a::initClass(); + // initialize SSE options + LLVector4a::initClass(); - //initialize particle index pool - LLVOPartGroup::initClass(); + //initialize particle index pool + LLVOPartGroup::initClass(); - // set skin search path to default, will be overridden later - // this allows simple skinned file lookups to work - gDirUtilp->setSkinFolder("default", "en"); + // set skin search path to default, will be overridden later + // this allows simple skinned file lookups to work + gDirUtilp->setSkinFolder("default", "en"); -// initLoggingAndGetLastDuration(); +// initLoggingAndGetLastDuration(); - // - // OK to write stuff to logs now, we've now crash reported if necessary - // - init_default_trans_args(); + // + // OK to write stuff to logs now, we've now crash reported if necessary + // + init_default_trans_args(); // inits from settings.xml and from strings.xml - if (!initConfiguration()) - return false; + if (!initConfiguration()) + return false; - LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; + LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ; - //set the max heap size. - initMaxHeapSize() ; - LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); + //set the max heap size. + initMaxHeapSize() ; + LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize")); - // Although initLoggingAndGetLastDuration() is the right place to mess with - // setFatalFunction(), we can't query gSavedSettings until after - // initConfiguration(). - S32 rc(gSavedSettings.getS32("QAModeTermCode")); - if (rc >= 0) - { - // QAModeTermCode set, terminate with that rc on LL_ERRS. Use - // _exit() rather than exit() because normal cleanup depends too - // much on successful startup! - LLError::setFatalFunction([rc](const std::string&){ _exit(rc); }); - } + // Although initLoggingAndGetLastDuration() is the right place to mess with + // setFatalFunction(), we can't query gSavedSettings until after + // initConfiguration(). + S32 rc(gSavedSettings.getS32("QAModeTermCode")); + if (rc >= 0) + { + // QAModeTermCode set, terminate with that rc on LL_ERRS. Use + // _exit() rather than exit() because normal cleanup depends too + // much on successful startup! + LLError::setFatalFunction([rc](const std::string&){ _exit(rc); }); + } mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); - // Initialize the non-LLCurl libcurl library. Should be called - // before consumers (LLTextureFetch). - mAppCoreHttp.init(); + // Initialize the non-LLCurl libcurl library. Should be called + // before consumers (LLTextureFetch). + mAppCoreHttp.init(); - LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ; + LL_INFOS("InitInfo") << "LLCore::Http initialized." << LL_ENDL ; LLMachineID::init(); - { - if (gSavedSettings.getBOOL("QAModeMetrics")) - { - app_metrics_qa_mode = true; - app_metrics_interval = METRICS_INTERVAL_QA; - } - LLViewerAssetStatsFF::init(); - } - - initThreads(); - LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; - - // Initialize settings early so that the defaults for ignorable dialogs are - // picked up and then correctly re-saved after launching the updater (STORM-1268). - LLUI::settings_map_t settings_map; - settings_map["config"] = &gSavedSettings; - settings_map["ignores"] = &gWarningSettings; - settings_map["floater"] = &gSavedSettings; // *TODO: New settings file - settings_map["account"] = &gSavedPerAccountSettings; - - LLUI::initParamSingleton(settings_map, - LLUIImageList::getInstance(), - ui_audio_callback, - deferred_ui_audio_callback); - LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; - - // NOW LLUI::getLanguage() should work. gDirUtilp must know the language - // for this session ASAP so all the file-loading commands that follow, - // that use findSkinnedFilenames(), will include the localized files. - gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage()); - - // Setup LLTrans after LLUI::initClass has been called. - initStrings(); + { + if (gSavedSettings.getBOOL("QAModeMetrics")) + { + app_metrics_qa_mode = true; + app_metrics_interval = METRICS_INTERVAL_QA; + } + LLViewerAssetStatsFF::init(); + } + + initThreads(); + LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; + + // Initialize settings early so that the defaults for ignorable dialogs are + // picked up and then correctly re-saved after launching the updater (STORM-1268). + LLUI::settings_map_t settings_map; + settings_map["config"] = &gSavedSettings; + settings_map["ignores"] = &gWarningSettings; + settings_map["floater"] = &gSavedSettings; // *TODO: New settings file + settings_map["account"] = &gSavedPerAccountSettings; + + LLUI::initParamSingleton(settings_map, + LLUIImageList::getInstance(), + ui_audio_callback, + deferred_ui_audio_callback); + LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + + // NOW LLUI::getLanguage() should work. gDirUtilp must know the language + // for this session ASAP so all the file-loading commands that follow, + // that use findSkinnedFilenames(), will include the localized files. + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage()); + + // Setup LLTrans after LLUI::initClass has been called. + initStrings(); // initialize LLWearableType translation bridge. // Will immediately use LLTranslationBridge to init LLWearableDictionary LLWearableType::initParamSingleton(trans); - // Setup notifications after LLUI::initClass() has been called. - LLNotifications::instance(); - LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; + // Setup notifications after LLUI::initClass() has been called. + LLNotifications::instance(); + LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////// - // *FIX: The following code isn't grouped into functions yet. + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////// + // *FIX: The following code isn't grouped into functions yet. - // - // Various introspection concerning the libs we're using - particularly - // the libs involved in getting to a full login screen. - // - LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL; - LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL; + // + // Various introspection concerning the libs we're using - particularly + // the libs involved in getting to a full login screen. + // + LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL; + LL_INFOS("InitInfo") << "libcurl version is: " << LLCore::LLHttp::getCURLVersion() << LL_ENDL; - ///////////////////////////////////////////////// - // OS-specific login dialogs - ///////////////////////////////////////////////// + ///////////////////////////////////////////////// + // OS-specific login dialogs + ///////////////////////////////////////////////// - //test_cached_control(); + //test_cached_control(); - // track number of times that app has run - mNumSessions = gSavedSettings.getS32("NumSessions"); - mNumSessions++; - gSavedSettings.setS32("NumSessions", mNumSessions); + // track number of times that app has run + mNumSessions = gSavedSettings.getS32("NumSessions"); + mNumSessions++; + gSavedSettings.setS32("NumSessions", mNumSessions); - // LLKeyboard relies on LLUI to know what some accelerator keys are called. - LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); + // LLKeyboard relies on LLUI to know what some accelerator keys are called. + LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString ); - // Provide the text fields with callbacks for opening Urls - LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null)); - LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false)); - LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null)); - LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); + // Provide the text fields with callbacks for opening Urls + LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null)); + LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null, false)); + LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null)); + LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor); - // Let code in llui access the viewer help floater - LLUI::getInstance()->mHelpImpl = LLViewerHelp::getInstance(); + // Let code in llui access the viewer help floater + LLUI::getInstance()->mHelpImpl = LLViewerHelp::getInstance(); - LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ; + LL_INFOS("InitInfo") << "UI initialization is done." << LL_ENDL ; - // Load translations for tooltips - LLFloater::initClass(); - LLUrlFloaterDispatchHandler::registerInDispatcher(); + // Load translations for tooltips + LLFloater::initClass(); + LLUrlFloaterDispatchHandler::registerInDispatcher(); - ///////////////////////////////////////////////// + ///////////////////////////////////////////////// - LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated + LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated - LLViewerFloaterReg::registerFloaters(); + LLViewerFloaterReg::registerFloaters(); - ///////////////////////////////////////////////// - // - // Load settings files - // - // - LLGroupMgr::parseRoleActions("role_actions.xml"); + ///////////////////////////////////////////////// + // + // Load settings files + // + // + LLGroupMgr::parseRoleActions("role_actions.xml"); - LLAgent::parseTeleportMessages("teleport_strings.xml"); + LLAgent::parseTeleportMessages("teleport_strings.xml"); - // load MIME type -> media impl mappings - std::string mime_types_name; + // load MIME type -> media impl mappings + std::string mime_types_name; #if LL_DARWIN - mime_types_name = "mime_types_mac.xml"; + mime_types_name = "mime_types_mac.xml"; #elif LL_LINUX - mime_types_name = "mime_types_linux.xml"; + mime_types_name = "mime_types_linux.xml"; #else - mime_types_name = "mime_types.xml"; + mime_types_name = "mime_types.xml"; #endif - LLMIMETypes::parseMIMETypes( mime_types_name ); - - // Copy settings to globals. *TODO: Remove or move to appropriage class initializers - settings_to_globals(); - // Setup settings listeners - settings_setup_listeners(); - // Modify settings based on system configuration and compile options - settings_modify(); - - // Find partition serial number (Windows) or hardware serial (Mac) - mSerialNumber = generateSerialNumber(); - - // do any necessary set-up for accepting incoming SLURLs from apps - initSLURLHandler(); - - if(false == initHardwareTest()) - { - // Early out from user choice. - return false; - } - LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ; - - // Prepare for out-of-memory situations, during which we will crash on - // purpose and save a dump. + LLMIMETypes::parseMIMETypes( mime_types_name ); + + // Copy settings to globals. *TODO: Remove or move to appropriage class initializers + settings_to_globals(); + // Setup settings listeners + settings_setup_listeners(); + // Modify settings based on system configuration and compile options + settings_modify(); + + // Find partition serial number (Windows) or hardware serial (Mac) + mSerialNumber = generateSerialNumber(); + + // do any necessary set-up for accepting incoming SLURLs from apps + initSLURLHandler(); + + if(false == initHardwareTest()) + { + // Early out from user choice. + return false; + } + LL_INFOS("InitInfo") << "Hardware test initialization done." << LL_ENDL ; + + // Prepare for out-of-memory situations, during which we will crash on + // purpose and save a dump. #if LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP - MemSetErrorHandler(first_mem_error_handler); + MemSetErrorHandler(first_mem_error_handler); #endif // LL_WINDOWS && LL_RELEASE_FOR_DOWNLOAD && LL_USE_SMARTHEAP - // *Note: this is where gViewerStats used to be created. + // *Note: this is where gViewerStats used to be created. - if (!initCache()) - { - LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; - std::ostringstream msg; - msg << LLTrans::getString("MBUnableToAccessFile"); - OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); - return 0; - } - LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; + if (!initCache()) + { + LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; + std::ostringstream msg; + msg << LLTrans::getString("MBUnableToAccessFile"); + OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); + return 0; + } + LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; // Initialize event recorder LLViewerEventRecorder::createInstance(); - // - // Initialize the window - // - gGLActive = TRUE; - initWindow(); - LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; + // + // Initialize the window + // + gGLActive = TRUE; + initWindow(); + LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; // writeSystemInfo can be called after window is initialized (gViewerWindow non-null) writeSystemInfo(); - // initWindow also initializes the Feature List, so now we can initialize this global. - LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); + // initWindow also initializes the Feature List, so now we can initialize this global. + LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); - // call all self-registered classes - LLInitClassList::instance().fireCallbacks(); + // call all self-registered classes + LLInitClassList::instance().fireCallbacks(); - LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts + LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts - gGLManager.getGLInfo(gDebugInfo); - gGLManager.printGLInfoString(); + gGLManager.getGLInfo(gDebugInfo); + gGLManager.printGLInfoString(); - // If we don't have the right GL requirements, exit. - if (!gGLManager.mHasRequirements) - { + // If we don't have the right GL requirements, exit. + if (!gGLManager.mHasRequirements) + { // already handled with a MBVideoDrvErr - return 0; - } - - // Without SSE2 support we will crash almost immediately, warn here. - if (!gSysCPU.hasSSE2()) - { - // can't use an alert here since we're exiting and - // all hell breaks lose. - OSMessageBox( - LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"), - LLStringUtil::null, - OSMB_OK); - return 0; - } - - // alert the user if they are using unsupported hardware - if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) - { - bool unsupported = false; - LLSD args; - std::string minSpecs; - - // get cpu data from xml - std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount")); - S32 minCPU = 0; - minCPUString >> minCPU; - - // get RAM data from XML - std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount")); - U64Bytes minRAM; - minRAMString >> minRAM; - - if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN) - { - minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU"); - minSpecs += "\n"; - unsupported = true; - } - if(gSysCPU.getMHz() < minCPU) - { - minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU"); - minSpecs += "\n"; - unsupported = true; - } - if(gSysMemory.getPhysicalMemoryKB() < minRAM) - { - minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM"); - minSpecs += "\n"; - unsupported = true; - } - - if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN) - { - LLNotificationsUtil::add("UnknownGPU"); - } - - if(unsupported) - { - if(!gSavedSettings.controlExists("WarnUnsupportedHardware") - || gSavedSettings.getBOOL("WarnUnsupportedHardware")) - { - args["MINSPECS"] = minSpecs; - LLNotificationsUtil::add("UnsupportedHardware", args ); - } - - } - } + return 0; + } + + // Without SSE2 support we will crash almost immediately, warn here. + if (!gSysCPU.hasSSE2()) + { + // can't use an alert here since we're exiting and + // all hell breaks lose. + OSMessageBox( + LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"), + LLStringUtil::null, + OSMB_OK); + return 0; + } + + // alert the user if they are using unsupported hardware + if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) + { + bool unsupported = false; + LLSD args; + std::string minSpecs; + + // get cpu data from xml + std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount")); + S32 minCPU = 0; + minCPUString >> minCPU; + + // get RAM data from XML + std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount")); + U64Bytes minRAM; + minRAMString >> minRAM; + + if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN) + { + minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU"); + minSpecs += "\n"; + unsupported = true; + } + if(gSysCPU.getMHz() < minCPU) + { + minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU"); + minSpecs += "\n"; + unsupported = true; + } + if(gSysMemory.getPhysicalMemoryKB() < minRAM) + { + minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM"); + minSpecs += "\n"; + unsupported = true; + } + + if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN) + { + LLNotificationsUtil::add("UnknownGPU"); + } + + if(unsupported) + { + if(!gSavedSettings.controlExists("WarnUnsupportedHardware") + || gSavedSettings.getBOOL("WarnUnsupportedHardware")) + { + args["MINSPECS"] = minSpecs; + LLNotificationsUtil::add("UnsupportedHardware", args ); + } + + } + } #if LL_WINDOWS && ADDRESS_SIZE == 64 if (gGLManager.mIsIntel) @@ -1083,54 +1083,54 @@ bool LLAppViewer::init() // Obsolete? mExpectedGLVersion is always zero #if LL_WINDOWS - if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) - { - std::string url; - if (gGLManager.mIsIntel) - { - url = LLTrans::getString("IntelDriverPage"); - } - else if (gGLManager.mIsNVIDIA) - { - url = LLTrans::getString("NvidiaDriverPage"); - } - else if (gGLManager.mIsAMD) - { - url = LLTrans::getString("AMDDriverPage"); - } - - if (!url.empty()) - { - LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url)); - } - } + if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) + { + std::string url; + if (gGLManager.mIsIntel) + { + url = LLTrans::getString("IntelDriverPage"); + } + else if (gGLManager.mIsNVIDIA) + { + url = LLTrans::getString("NvidiaDriverPage"); + } + else if (gGLManager.mIsAMD) + { + url = LLTrans::getString("AMDDriverPage"); + } + + if (!url.empty()) + { + LLNotificationsUtil::add("OldGPUDriver", LLSD().with("URL", url)); + } + } #endif - // save the graphics card - gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); + // save the graphics card + gDebugInfo["GraphicsCard"] = LLFeatureManager::getInstance()->getGPUString(); - // Save the current version to the prefs file - gSavedSettings.setString("LastRunVersion", - LLVersionInfo::instance().getChannelAndVersion()); + // Save the current version to the prefs file + gSavedSettings.setString("LastRunVersion", + LLVersionInfo::instance().getChannelAndVersion()); - gSimLastTime = gRenderStartTime.getElapsedTimeF32(); - gSimFrames = (F32)gFrameCount; + gSimLastTime = gRenderStartTime.getElapsedTimeF32(); + gSimFrames = (F32)gFrameCount; if (gSavedSettings.getBOOL("JoystickEnabled")) { LLViewerJoystick::getInstance()->init(false); } - try { - initializeSecHandler(); - } - catch (LLProtectedDataException&) - { - LLNotificationsUtil::add("CorruptedProtectedDataStore"); - } + try { + initializeSecHandler(); + } + catch (LLProtectedDataException&) + { + LLNotificationsUtil::add("CorruptedProtectedDataStore"); + } - gGLActive = FALSE; + gGLActive = FALSE; #if LL_RELEASE_FOR_DOWNLOAD // Skip updater if this is a non-interactive instance @@ -1228,25 +1228,25 @@ bool LLAppViewer::init() << LL_ENDL; } - LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; + LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; - //EXT-7013 - On windows for some locale (Japanese) standard - //datetime formatting functions didn't support some parameters such as "weekday". - //Names for days and months localized in xml are also useful for Polish locale(STORM-107). - std::string language = gSavedSettings.getString("Language"); - if(language == "ja" || language == "pl") - { - LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); - LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); - LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); - LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); - LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); - - LLStringOps::sAM = LLTrans::getString("dateTimeAM"); - LLStringOps::sPM = LLTrans::getString("dateTimePM"); - } + //EXT-7013 - On windows for some locale (Japanese) standard + //datetime formatting functions didn't support some parameters such as "weekday". + //Names for days and months localized in xml are also useful for Polish locale(STORM-107). + std::string language = gSavedSettings.getString("Language"); + if(language == "ja" || language == "pl") + { + LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); + LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); + LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); + LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); + LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); + + LLStringOps::sAM = LLTrans::getString("dateTimeAM"); + LLStringOps::sPM = LLTrans::getString("dateTimePM"); + } - LLAgentLanguage::init(); + LLAgentLanguage::init(); /// Tell the Coprocedure manager how to discover and store the pool sizes // what I wanted @@ -1254,27 +1254,27 @@ bool LLAppViewer::init() boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); - // TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement - // some other protection to make sure we don't use network before initializng proxy + // TODO: consider moving proxy initialization here or LLCopocedureManager after proxy initialization, may be implement + // some other protection to make sure we don't use network before initializng proxy - /*----------------------------------------------------------------------*/ - // nat 2016-06-29 moved the following here from the former mainLoop(). - mMainloopTimeout = new LLWatchdogTimeout(); + /*----------------------------------------------------------------------*/ + // nat 2016-06-29 moved the following here from the former mainLoop(). + mMainloopTimeout = new LLWatchdogTimeout(); - // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO(gAPRPoolp); + // Create IO Pump to use for HTTP Requests. + gServicePump = new LLPumpIO(gAPRPoolp); - // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. - LLVoiceChannel::initClass(); - LLVoiceClient::initParamSingleton(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); + LLVoiceChannel::initClass(); + LLVoiceClient::initParamSingleton(gServicePump); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); - joystick = LLViewerJoystick::getInstance(); - joystick->setNeedsReset(true); - /*----------------------------------------------------------------------*/ - // Load User's bindings - loadKeyBindings(); + joystick = LLViewerJoystick::getInstance(); + joystick->setNeedsReset(true); + /*----------------------------------------------------------------------*/ + // Load User's bindings + loadKeyBindings(); //LLSimpleton creations LLEnvironment::createInstance(); @@ -1291,23 +1291,23 @@ bool LLAppViewer::init() } #endif - return true; + return true; } void LLAppViewer::initMaxHeapSize() { - //set the max heap size. - //here is some info regarding to the max heap size: - //------------------------------------------------------------------------------------------ - // OS | setting | SL address bits | max manageable memory space | max heap size - // Win 32 | default | 32-bit | 2GB | < 1.7GB - // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB - //Linux 32 | default | 32-bit | 3GB | < 2.7GB - //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB - //64-bit OS |default | 32-bit | 4GB | < 3.7GB - //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB) - //------------------------------------------------------------------------------------------ - //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB. + //set the max heap size. + //here is some info regarding to the max heap size: + //------------------------------------------------------------------------------------------ + // OS | setting | SL address bits | max manageable memory space | max heap size + // Win 32 | default | 32-bit | 2GB | < 1.7GB + // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB + //Linux 32 | default | 32-bit | 3GB | < 2.7GB + //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB + //64-bit OS |default | 32-bit | 4GB | < 3.7GB + //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB) + //------------------------------------------------------------------------------------------ + //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB. #ifndef LL_X86_64 F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ; @@ -1324,42 +1324,42 @@ LLTrace::BlockTimerStatHandle FTM_FRAME("Frame"); bool LLAppViewer::frame() { - bool ret = false; - - if (gSimulateMemLeak) - { - try - { - ret = doFrame(); - } - catch (const LLContinueError&) - { - LOG_UNHANDLED_EXCEPTION(""); - } - catch (std::bad_alloc&) - { - LLMemory::logMemoryInfo(TRUE); - LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance("mem_leaking"); - if (mem_leak_instance) - { - mem_leak_instance->stop(); - } - LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL; - } - } - else - { - try - { - ret = doFrame(); - } - catch (const LLContinueError&) - { - LOG_UNHANDLED_EXCEPTION(""); - } - } - - return ret; + bool ret = false; + + if (gSimulateMemLeak) + { + try + { + ret = doFrame(); + } + catch (const LLContinueError&) + { + LOG_UNHANDLED_EXCEPTION(""); + } + catch (std::bad_alloc&) + { + LLMemory::logMemoryInfo(TRUE); + LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance("mem_leaking"); + if (mem_leak_instance) + { + mem_leak_instance->stop(); + } + LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL; + } + } + else + { + try + { + ret = doFrame(); + } + catch (const LLContinueError&) + { + LOG_UNHANDLED_EXCEPTION(""); + } + } + + return ret; } bool LLAppViewer::doFrame() @@ -1452,63 +1452,63 @@ bool LLAppViewer::doFrame() } } - if (!LLApp::isExiting()) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df JoystickKeyboard" ) - pingMainloopTimeout("Main:JoystickKeyboard"); - - // Scan keyboard for movement keys. Command keys and typing - // are handled by windows callbacks. Don't do this until we're - // done initializing. JC - if (gViewerWindow - && (gHeadlessClient || gViewerWindow->getWindow()->getVisible()) - && gViewerWindow->getActive() - && !gViewerWindow->getWindow()->getMinimized() - && LLStartUp::getStartupState() == STATE_STARTED - && (gHeadlessClient || !gViewerWindow->getShowProgress()) - && !gFocusMgr.focusLocked()) - { + if (!LLApp::isExiting()) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df JoystickKeyboard" ) + pingMainloopTimeout("Main:JoystickKeyboard"); + + // Scan keyboard for movement keys. Command keys and typing + // are handled by windows callbacks. Don't do this until we're + // done initializing. JC + if (gViewerWindow + && (gHeadlessClient || gViewerWindow->getWindow()->getVisible()) + && gViewerWindow->getActive() + && !gViewerWindow->getWindow()->getMinimized() + && LLStartUp::getStartupState() == STATE_STARTED + && (gHeadlessClient || !gViewerWindow->getShowProgress()) + && !gFocusMgr.focusLocked()) + { LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); - joystick->scanJoystick(); - gKeyboard->scanKeyboard(); + joystick->scanJoystick(); + gKeyboard->scanKeyboard(); gViewerInput.scanMouse(); - } + } - // Update state based on messages, user input, object idle. - { - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" ) - pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - } + // Update state based on messages, user input, object idle. + { + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" ) + pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! + } - { + { LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_IDLE); LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df idle"); - idle(); - } + idle(); + } - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) - resumeMainloopTimeout(); - } - } + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) + resumeMainloopTimeout(); + } + } - if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) - { - pauseMainloopTimeout(); - saveFinalSnapshot(); + if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) + { + pauseMainloopTimeout(); + saveFinalSnapshot(); if (LLVoiceClient::instanceExists()) { LLVoiceClient::getInstance()->terminate(); } - disconnectViewer(); - resumeMainloopTimeout(); - } + disconnectViewer(); + resumeMainloopTimeout(); + } - // Render scene. - // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 + // Render scene. + // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 if (!LLApp::isExiting() && !gHeadlessClient && gViewerWindow) { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("df Display"); @@ -1532,159 +1532,159 @@ bool LLAppViewer::doFrame() LLViewerStatsRecorder::instance().idle(); } } - } + } - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" ) - pingMainloopTimeout("Main:Sleep"); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" ) + pingMainloopTimeout("Main:Sleep"); - pauseMainloopTimeout(); - } + pauseMainloopTimeout(); + } - // Sleep and run background threads - { - //LL_RECORD_BLOCK_TIME(SLEEP2); - LL_PROFILE_ZONE_WARN( "Sleep2" ) + // Sleep and run background threads + { + //LL_RECORD_BLOCK_TIME(SLEEP2); + LL_PROFILE_ZONE_WARN( "Sleep2" ) - // yield some time to the os based on command line option - static LLCachedControl yield_time(gSavedSettings, "YieldTime", -1); - if(yield_time >= 0) - { + // yield some time to the os based on command line option + static LLCachedControl yield_time(gSavedSettings, "YieldTime", -1); + if(yield_time >= 0) + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Yield"); - LL_PROFILE_ZONE_NUM( yield_time ) - ms_sleep(yield_time); - } - - if (gNonInteractive) - { - S32 non_interactive_ms_sleep_time = 100; - LLAppViewer::getTextureCache()->pause(); - ms_sleep(non_interactive_ms_sleep_time); - } - - // yield cooperatively when not running as foreground window - // and when not quiting (causes trouble at mac's cleanup stage) - if (!LLApp::isExiting() - && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus())) - { - // Sleep if we're not rendering, or the window is minimized. - static LLCachedControl s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40); - S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000); - // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads - // of equal priority on Windows - if (milliseconds_to_sleep > 0) - { + LL_PROFILE_ZONE_NUM( yield_time ) + ms_sleep(yield_time); + } + + if (gNonInteractive) + { + S32 non_interactive_ms_sleep_time = 100; + LLAppViewer::getTextureCache()->pause(); + ms_sleep(non_interactive_ms_sleep_time); + } + + // yield cooperatively when not running as foreground window + // and when not quiting (causes trouble at mac's cleanup stage) + if (!LLApp::isExiting() + && ((gViewerWindow && !gViewerWindow->getWindow()->getVisible()) + || !gFocusMgr.getAppHasFocus())) + { + // Sleep if we're not rendering, or the window is minimized. + static LLCachedControl s_background_yield_time(gSavedSettings, "BackgroundYieldTime", 40); + S32 milliseconds_to_sleep = llclamp((S32)s_background_yield_time, 0, 1000); + // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads + // of equal priority on Windows + if (milliseconds_to_sleep > 0) + { LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SLEEP ); ms_sleep(milliseconds_to_sleep); - // also pause worker threads during this wait period - LLAppViewer::getTextureCache()->pause(); - } - } - - if (mRandomizeFramerate) - { - ms_sleep(rand() % 200); - } - - if (mPeriodicSlowFrame - && (gFrameCount % 10 == 0)) - { - LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; - ms_sleep(500); - } - - S32 total_work_pending = 0; - S32 total_io_pending = 0; - { - S32 work_pending = 0; - S32 io_pending = 0; - F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); - - work_pending += updateTextureThreads(max_time); - - { + // also pause worker threads during this wait period + LLAppViewer::getTextureCache()->pause(); + } + } + + if (mRandomizeFramerate) + { + ms_sleep(rand() % 200); + } + + if (mPeriodicSlowFrame + && (gFrameCount % 10 == 0)) + { + LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; + ms_sleep(500); + } + + S32 total_work_pending = 0; + S32 total_io_pending = 0; + { + S32 work_pending = 0; + S32 io_pending = 0; + F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); + + work_pending += updateTextureThreads(max_time); + + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("LFS Thread"); - io_pending += LLLFSThread::updateClass(1); - } - - if (io_pending > 1000) - { - ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up - } - - total_work_pending += work_pending ; - total_io_pending += io_pending ; - - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df gMeshRepo" ) - gMeshRepo.update() ; - } - - if(!total_work_pending) //pause texture fetching threads if nothing to process. - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" ) - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getTextureFetch()->pause(); - } - if(!total_io_pending) //pause file threads if nothing to process. - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df LLVFSThread" ) - LLLFSThread::sLocal->pause(); - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) - resumeMainloopTimeout(); - } - pingMainloopTimeout("Main:End"); - } - } - - if (LLApp::isExiting()) - { - // Save snapshot for next time, if we made it through initialization - if (STATE_STARTED == LLStartUp::getStartupState()) - { - saveFinalSnapshot(); - } - - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->terminate(); - } - - delete gServicePump; - gServicePump = NULL; - - destroyMainloopTimeout(); - - LL_INFOS() << "Exiting main_loop" << LL_ENDL; - } + io_pending += LLLFSThread::updateClass(1); + } + + if (io_pending > 1000) + { + ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up + } + + total_work_pending += work_pending ; + total_io_pending += io_pending ; + + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df gMeshRepo" ) + gMeshRepo.update() ; + } + + if(!total_work_pending) //pause texture fetching threads if nothing to process. + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df getTextureCache" ) + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getTextureFetch()->pause(); + } + if(!total_io_pending) //pause file threads if nothing to process. + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df LLVFSThread" ) + LLLFSThread::sLocal->pause(); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df resumeMainloopTimeout" ) + resumeMainloopTimeout(); + } + pingMainloopTimeout("Main:End"); + } + } + + if (LLApp::isExiting()) + { + // Save snapshot for next time, if we made it through initialization + if (STATE_STARTED == LLStartUp::getStartupState()) + { + saveFinalSnapshot(); + } + + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->terminate(); + } + + delete gServicePump; + gServicePump = NULL; + + destroyMainloopTimeout(); + + LL_INFOS() << "Exiting main_loop" << LL_ENDL; + } }LLPerfStats::StatsRecorder::endFrame(); LL_PROFILER_FRAME_END - return ! LLApp::isRunning(); + return ! LLApp::isRunning(); } S32 LLAppViewer::updateTextureThreads(F32 max_time) { - S32 work_pending = 0; - { + S32 work_pending = 0; + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Texture Cache"); - work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread - } - { + work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread + } + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Decode"); - work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread - } - { + work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread + } + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Image Fetch"); - work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread - } - return work_pending; + work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread + } + return work_pending; } void LLAppViewer::flushLFSIO() @@ -1709,200 +1709,200 @@ bool LLAppViewer::cleanup() { LLAtmosphere::cleanupClass(); - //ditch LLVOAvatarSelf instance - gAgentAvatarp = NULL; + //ditch LLVOAvatarSelf instance + gAgentAvatarp = NULL; LLNotifications::instance().clear(); - // workaround for DEV-35406 crash on shutdown - LLEventPumps::instance().reset(true); + // workaround for DEV-35406 crash on shutdown + LLEventPumps::instance().reset(true); - //dump scene loading monitor results - if (LLSceneMonitor::instanceExists()) - { - if (!isSecondInstance()) - { + //dump scene loading monitor results + if (LLSceneMonitor::instanceExists()) + { + if (!isSecondInstance()) + { std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"); - LLSceneMonitor::instance().dumpToFile(dump_path); - } - LLSceneMonitor::deleteSingleton(); - } - - // There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block - // here, completely redundant with the one that occurs later in this same - // function. Presumably the duplication was due to an automated merge gone - // bad. Not knowing which instance to prefer, we chose to retain the later - // one because it happens just after mFastTimerLogThread is deleted. This - // comment is in case we guessed wrong, so we can move it here instead. + LLSceneMonitor::instance().dumpToFile(dump_path); + } + LLSceneMonitor::deleteSingleton(); + } + + // There used to be an 'if (LLFastTimerView::sAnalyzePerformance)' block + // here, completely redundant with the one that occurs later in this same + // function. Presumably the duplication was due to an automated merge gone + // bad. Not knowing which instance to prefer, we chose to retain the later + // one because it happens just after mFastTimerLogThread is deleted. This + // comment is in case we guessed wrong, so we can move it here instead. #if LL_LINUX - // remove any old breakpad minidump files from the log directory - if (! isError()) - { - std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); - gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); - } + // remove any old breakpad minidump files from the log directory + if (! isError()) + { + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + } #endif - // Kill off LLLeap objects. We can find them all because LLLeap is derived - // from LLInstanceTracker. - LLLeap::instance_snapshot().deleteAll(); + // Kill off LLLeap objects. We can find them all because LLLeap is derived + // from LLInstanceTracker. + LLLeap::instance_snapshot().deleteAll(); - //flag all elements as needing to be destroyed immediately - // to ensure shutdown order - LLMortician::setZealous(TRUE); + //flag all elements as needing to be destroyed immediately + // to ensure shutdown order + LLMortician::setZealous(TRUE); // Give any remaining SLPlugin instances a chance to exit cleanly. LLPluginProcessParent::shutdown(); - disconnectViewer(); - LLViewerCamera::deleteSingleton(); + disconnectViewer(); + LLViewerCamera::deleteSingleton(); + + LL_INFOS() << "Viewer disconnected" << LL_ENDL; - LL_INFOS() << "Viewer disconnected" << LL_ENDL; - - if (gKeyboard) - { - gKeyboard->resetKeys(); - } + if (gKeyboard) + { + gKeyboard->resetKeys(); + } - display_cleanup(); + display_cleanup(); - release_start_screen(); // just in case + release_start_screen(); // just in case - LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder + LLError::logToFixedBuffer(NULL); // stop the fixed buffer recorder - LL_INFOS() << "Cleaning Up" << LL_ENDL; + LL_INFOS() << "Cleaning Up" << LL_ENDL; - // shut down mesh streamer - gMeshRepo.shutdown(); + // shut down mesh streamer + gMeshRepo.shutdown(); - // shut down Havok - LLPhysicsExtensions::quitSystem(); + // shut down Havok + LLPhysicsExtensions::quitSystem(); - // Must clean up texture references before viewer window is destroyed. - if(LLHUDManager::instanceExists()) - { - LLHUDManager::getInstance()->updateEffects(); - LLHUDObject::updateAll(); - LLHUDManager::getInstance()->cleanupEffects(); - LLHUDObject::cleanupHUDObjects(); - LL_INFOS() << "HUD Objects cleaned up" << LL_ENDL; - } + // Must clean up texture references before viewer window is destroyed. + if(LLHUDManager::instanceExists()) + { + LLHUDManager::getInstance()->updateEffects(); + LLHUDObject::updateAll(); + LLHUDManager::getInstance()->cleanupEffects(); + LLHUDObject::cleanupHUDObjects(); + LL_INFOS() << "HUD Objects cleaned up" << LL_ENDL; + } - LLKeyframeDataCache::clear(); + LLKeyframeDataCache::clear(); - // End TransferManager before deleting systems it depends on (Audio, AssetStorage) + // End TransferManager before deleting systems it depends on (Audio, AssetStorage) #if 0 // this seems to get us stuck in an infinite loop... - gTransferManager.cleanup(); + gTransferManager.cleanup(); #endif - // Note: this is where gWorldMap used to be deleted. + // Note: this is where gWorldMap used to be deleted. - // Note: this is where gHUDManager used to be deleted. - if(LLHUDManager::instanceExists()) - { - LLHUDManager::getInstance()->shutdownClass(); - } + // Note: this is where gHUDManager used to be deleted. + if(LLHUDManager::instanceExists()) + { + LLHUDManager::getInstance()->shutdownClass(); + } - delete gAssetStorage; - gAssetStorage = NULL; + delete gAssetStorage; + gAssetStorage = NULL; - LLPolyMesh::freeAllMeshes(); + LLPolyMesh::freeAllMeshes(); - LLStartUp::cleanupNameCache(); + LLStartUp::cleanupNameCache(); - // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted. + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted. - if (LLWorldMap::instanceExists()) - { - LLWorldMap::getInstance()->reset(); // release any images - } + if (LLWorldMap::instanceExists()) + { + LLWorldMap::getInstance()->reset(); // release any images + } - LLCalc::cleanUp(); + LLCalc::cleanUp(); - LL_INFOS() << "Global stuff deleted" << LL_ENDL; + LL_INFOS() << "Global stuff deleted" << LL_ENDL; - if (gAudiop) - { + if (gAudiop) + { LL_INFOS() << "Shutting down audio" << LL_ENDL; // be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it. gAudiop->stopInternetStream(); // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); - delete sai; - gAudiop->setStreamingAudioImpl(NULL); + delete sai; + gAudiop->setStreamingAudioImpl(NULL); // shut down the audio subsystem gAudiop->shutdown(); - delete gAudiop; - gAudiop = NULL; - } - - // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. + delete gAudiop; + gAudiop = NULL; + } - // Patch up settings for next time - // Must do this before we delete the viewer window, - // such that we can suck rectangle information out of - // it. - cleanupSavedSettings(); - LL_INFOS() << "Settings patched up" << LL_ENDL; + // Note: this is where LLFeatureManager::getInstance()-> used to be deleted. - // delete some of the files left around in the cache. - removeCacheFiles("*.wav"); - removeCacheFiles("*.tmp"); - removeCacheFiles("*.lso"); - removeCacheFiles("*.out"); - removeCacheFiles("*.dsf"); - removeCacheFiles("*.bodypart"); - removeCacheFiles("*.clothing"); + // Patch up settings for next time + // Must do this before we delete the viewer window, + // such that we can suck rectangle information out of + // it. + cleanupSavedSettings(); + LL_INFOS() << "Settings patched up" << LL_ENDL; - LL_INFOS() << "Cache files removed" << LL_ENDL; + // delete some of the files left around in the cache. + removeCacheFiles("*.wav"); + removeCacheFiles("*.tmp"); + removeCacheFiles("*.lso"); + removeCacheFiles("*.out"); + removeCacheFiles("*.dsf"); + removeCacheFiles("*.bodypart"); + removeCacheFiles("*.clothing"); - LL_INFOS() << "Shutting down Views" << LL_ENDL; + LL_INFOS() << "Cache files removed" << LL_ENDL; - // Destroy the UI - if( gViewerWindow) - gViewerWindow->shutdownViews(); + LL_INFOS() << "Shutting down Views" << LL_ENDL; - LL_INFOS() << "Cleaning up Inventory" << LL_ENDL; + // Destroy the UI + if( gViewerWindow) + gViewerWindow->shutdownViews(); - // Cleanup Inventory after the UI since it will delete any remaining observers - // (Deleted observers should have already removed themselves) - gInventory.cleanupInventory(); + LL_INFOS() << "Cleaning up Inventory" << LL_ENDL; - LLCoros::getInstance()->printActiveCoroutines(); + // Cleanup Inventory after the UI since it will delete any remaining observers + // (Deleted observers should have already removed themselves) + gInventory.cleanupInventory(); - LL_INFOS() << "Cleaning up Selections" << LL_ENDL; + LLCoros::getInstance()->printActiveCoroutines(); - // Clean up selection managers after UI is destroyed, as UI may be observing them. - // Clean up before GL is shut down because we might be holding on to objects with texture references - LLSelectMgr::cleanupGlobals(); + LL_INFOS() << "Cleaning up Selections" << LL_ENDL; - LL_INFOS() << "Shutting down OpenGL" << LL_ENDL; + // Clean up selection managers after UI is destroyed, as UI may be observing them. + // Clean up before GL is shut down because we might be holding on to objects with texture references + LLSelectMgr::cleanupGlobals(); - // Shut down OpenGL - if( gViewerWindow) - { - gViewerWindow->shutdownGL(); + LL_INFOS() << "Shutting down OpenGL" << LL_ENDL; - // Destroy window, and make sure we're not fullscreen - // This may generate window reshape and activation events. - // Therefore must do this before destroying the message system. - delete gViewerWindow; - gViewerWindow = NULL; - LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; - } + // Shut down OpenGL + if( gViewerWindow) + { + gViewerWindow->shutdownGL(); + + // Destroy window, and make sure we're not fullscreen + // This may generate window reshape and activation events. + // Therefore must do this before destroying the message system. + delete gViewerWindow; + gViewerWindow = NULL; + LL_INFOS() << "ViewerWindow deleted" << LL_ENDL; + } LLSplashScreen::show(); LLSplashScreen::update(LLTrans::getString("ShuttingDown")); - LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL; + LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL; - // viewer UI relies on keyboard so keep it aound until viewer UI isa gone - delete gKeyboard; - gKeyboard = NULL; + // viewer UI relies on keyboard so keep it aound until viewer UI isa gone + delete gKeyboard; + gKeyboard = NULL; if (LLViewerJoystick::instanceExists()) { @@ -1910,280 +1910,280 @@ bool LLAppViewer::cleanup() LLViewerJoystick::getInstance()->terminate(); } - LL_INFOS() << "Cleaning up Objects" << LL_ENDL; + LL_INFOS() << "Cleaning up Objects" << LL_ENDL; - LLViewerObject::cleanupVOClasses(); + LLViewerObject::cleanupVOClasses(); - SUBSYSTEM_CLEANUP(LLAvatarAppearance); + SUBSYSTEM_CLEANUP(LLAvatarAppearance); - SUBSYSTEM_CLEANUP(LLPostProcess); + SUBSYSTEM_CLEANUP(LLPostProcess); - LLTracker::cleanupInstance(); + LLTracker::cleanupInstance(); - // *FIX: This is handled in LLAppViewerWin32::cleanup(). - // I'm keeping the comment to remember its order in cleanup, - // in case of unforseen dependency. - //#if LL_WINDOWS - // gDXHardware.cleanup(); - //#endif // LL_WINDOWS + // *FIX: This is handled in LLAppViewerWin32::cleanup(). + // I'm keeping the comment to remember its order in cleanup, + // in case of unforseen dependency. + //#if LL_WINDOWS + // gDXHardware.cleanup(); + //#endif // LL_WINDOWS - LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager(); - if (!volume_manager->cleanup()) - { - LL_WARNS() << "Remaining references in the volume manager!" << LL_ENDL; - } - LLPrimitive::cleanupVolumeManager(); + LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager(); + if (!volume_manager->cleanup()) + { + LL_WARNS() << "Remaining references in the volume manager!" << LL_ENDL; + } + LLPrimitive::cleanupVolumeManager(); - LL_INFOS() << "Additional Cleanup..." << LL_ENDL; + LL_INFOS() << "Additional Cleanup..." << LL_ENDL; - LLViewerParcelMgr::cleanupGlobals(); + LLViewerParcelMgr::cleanupGlobals(); - // *Note: this is where gViewerStats used to be deleted. + // *Note: this is where gViewerStats used to be deleted. - //end_messaging_system(); + //end_messaging_system(); - LLPrimitive::cleanupVolumeManager(); - SUBSYSTEM_CLEANUP(LLWorldMapView); - SUBSYSTEM_CLEANUP(LLFolderViewItem); + LLPrimitive::cleanupVolumeManager(); + SUBSYSTEM_CLEANUP(LLWorldMapView); + SUBSYSTEM_CLEANUP(LLFolderViewItem); - LL_INFOS() << "Saving Data" << LL_ENDL; + LL_INFOS() << "Saving Data" << LL_ENDL; - // Store the time of our current logoff - gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); + // Store the time of our current logoff + gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); if (LLEnvironment::instanceExists()) { - //Store environment settings if necessary + //Store environment settings if necessary LLEnvironment::getInstance()->saveToSettings(); } - // Must do this after all panels have been deleted because panels that have persistent rects - // save their rects on delete. - gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - - LLUIColorTable::instance().saveUserSettings(); - - // PerAccountSettingsFile should be empty if no user has been logged on. - // *FIX:Mani This should get really saved in a "logoff" mode. - if (gSavedSettings.getString("PerAccountSettingsFile").empty()) - { - LL_INFOS() << "Not saving per-account settings; don't know the account name yet." << LL_ENDL; - } - // Only save per account settings if the previous login succeeded, otherwise - // we might end up with a cleared out settings file in case a previous login - // failed after loading per account settings. - else if (!mSavePerAccountSettings) - { - LL_INFOS() << "Not saving per-account settings; last login was not successful." << LL_ENDL; - } - else - { - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - LL_INFOS() << "Saved settings" << LL_ENDL; - - if (LLViewerParcelAskPlay::instanceExists()) - { - LLViewerParcelAskPlay::getInstance()->saveSettings(); - } - } - - std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings")); - gWarningSettings.saveToFile(warnings_settings_filename, TRUE); - - // Save URL history file - LLURLHistory::saveFile("url_history.xml"); - - // save mute list. gMuteList used to also be deleted here too. - if (gAgent.isInitialized() && LLMuteList::instanceExists()) - { - LLMuteList::getInstance()->cache(gAgent.getID()); - } - - //save call log list - if (LLConversationLog::instanceExists()) - { - LLConversationLog::instance().cache(); - } - - clearSecHandler(); + // Must do this after all panels have been deleted because panels that have persistent rects + // save their rects on delete. + gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - if (mPurgeCacheOnExit) - { - LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); - } - - writeDebugInfo(); - - LLLocationHistory::getInstance()->save(); - - LLAvatarIconIDCache::getInstance()->save(); - - // Stop the plugin read thread if it's running. - LLPluginProcessParent::setUseReadThread(false); - - LL_INFOS() << "Shutting down Threads" << LL_ENDL; - - // Let threads finish - LLTimer idleTimer; - idleTimer.reset(); - const F64 max_idle_time = 5.f; // 5 seconds - while(1) - { - S32 pending = 0; - pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread - pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread - pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread - pending += LLLFSThread::updateClass(0); - F64 idle_time = idleTimer.getElapsedTimeF64(); - if(!pending) - { - break ; //done - } - else if(idle_time >= max_idle_time) - { - LL_WARNS() << "Quitting with pending background tasks." << LL_ENDL; - break; - } - } + LLUIColorTable::instance().saveUserSettings(); - if (mPurgeUserDataOnExit) + // PerAccountSettingsFile should be empty if no user has been logged on. + // *FIX:Mani This should get really saved in a "logoff" mode. + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) { - // Ideally we should not save anything from this session since it is going to be purged now, - // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code - std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId(); - gDirUtilp->deleteDirAndContents(user_path); + LL_INFOS() << "Not saving per-account settings; don't know the account name yet." << LL_ENDL; } + // Only save per account settings if the previous login succeeded, otherwise + // we might end up with a cleared out settings file in case a previous login + // failed after loading per account settings. + else if (!mSavePerAccountSettings) + { + LL_INFOS() << "Not saving per-account settings; last login was not successful." << LL_ENDL; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + LL_INFOS() << "Saved settings" << LL_ENDL; - // Delete workers first - // shotdown all worker threads before deleting them in case of co-dependencies - mAppCoreHttp.requestStop(); - sTextureFetch->shutdown(); - sTextureCache->shutdown(); - sImageDecodeThread->shutdown(); - sPurgeDiskCacheThread->shutdown(); - if (mGeneralThreadPool) - { - mGeneralThreadPool->close(); - } - - sTextureFetch->shutDownTextureCacheThread() ; - LLLFSThread::sLocal->shutdown(); + if (LLViewerParcelAskPlay::instanceExists()) + { + LLViewerParcelAskPlay::getInstance()->saveSettings(); + } + } - LL_INFOS() << "Shutting down message system" << LL_ENDL; - end_messaging_system(); + std::string warnings_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Warnings")); + gWarningSettings.saveToFile(warnings_settings_filename, TRUE); - // Non-LLCurl libcurl library - mAppCoreHttp.cleanup(); + // Save URL history file + LLURLHistory::saveFile("url_history.xml"); - SUBSYSTEM_CLEANUP(LLFilePickerThread); - SUBSYSTEM_CLEANUP(LLDirPickerThread); + // save mute list. gMuteList used to also be deleted here too. + if (gAgent.isInitialized() && LLMuteList::instanceExists()) + { + LLMuteList::getInstance()->cache(gAgent.getID()); + } - //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) - delete sTextureCache; - sTextureCache = NULL; - if (sTextureFetch) + //save call log list + if (LLConversationLog::instanceExists()) + { + LLConversationLog::instance().cache(); + } + + clearSecHandler(); + + if (mPurgeCacheOnExit) + { + LL_INFOS() << "Purging all cache files on exit" << LL_ENDL; + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""), "*.*"); + } + + writeDebugInfo(); + + LLLocationHistory::getInstance()->save(); + + LLAvatarIconIDCache::getInstance()->save(); + + // Stop the plugin read thread if it's running. + LLPluginProcessParent::setUseReadThread(false); + + LL_INFOS() << "Shutting down Threads" << LL_ENDL; + + // Let threads finish + LLTimer idleTimer; + idleTimer.reset(); + const F64 max_idle_time = 5.f; // 5 seconds + while(1) + { + S32 pending = 0; + pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread + pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread + pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread + pending += LLLFSThread::updateClass(0); + F64 idle_time = idleTimer.getElapsedTimeF64(); + if(!pending) + { + break ; //done + } + else if(idle_time >= max_idle_time) + { + LL_WARNS() << "Quitting with pending background tasks." << LL_ENDL; + break; + } + } + + if (mPurgeUserDataOnExit) + { + // Ideally we should not save anything from this session since it is going to be purged now, + // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code + std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId(); + gDirUtilp->deleteDirAndContents(user_path); + } + + // Delete workers first + // shotdown all worker threads before deleting them in case of co-dependencies + mAppCoreHttp.requestStop(); + sTextureFetch->shutdown(); + sTextureCache->shutdown(); + sImageDecodeThread->shutdown(); + sPurgeDiskCacheThread->shutdown(); + if (mGeneralThreadPool) + { + mGeneralThreadPool->close(); + } + + sTextureFetch->shutDownTextureCacheThread() ; + LLLFSThread::sLocal->shutdown(); + + LL_INFOS() << "Shutting down message system" << LL_ENDL; + end_messaging_system(); + + // Non-LLCurl libcurl library + mAppCoreHttp.cleanup(); + + SUBSYSTEM_CLEANUP(LLFilePickerThread); + SUBSYSTEM_CLEANUP(LLDirPickerThread); + + //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) + delete sTextureCache; + sTextureCache = NULL; + if (sTextureFetch) { sTextureFetch->shutdown(); sTextureFetch->waitOnPending(); delete sTextureFetch; sTextureFetch = NULL; } - delete sImageDecodeThread; + delete sImageDecodeThread; sImageDecodeThread = NULL; - delete mFastTimerLogThread; - mFastTimerLogThread = NULL; - delete sPurgeDiskCacheThread; - sPurgeDiskCacheThread = NULL; + delete mFastTimerLogThread; + mFastTimerLogThread = NULL; + delete sPurgeDiskCacheThread; + sPurgeDiskCacheThread = NULL; delete mGeneralThreadPool; mGeneralThreadPool = NULL; - if (LLFastTimerView::sAnalyzePerformance) - { - LL_INFOS() << "Analyzing performance" << LL_ENDL; + if (LLFastTimerView::sAnalyzePerformance) + { + LL_INFOS() << "Analyzing performance" << LL_ENDL; - std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp"; - std::string current_name = LLTrace::BlockTimer::sLogName + ".slp"; - std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv"; + std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp"; + std::string current_name = LLTrace::BlockTimer::sLogName + ".slp"; + std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv"; - LLFastTimerView::doAnalysis( - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name), - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name), - gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name)); - } + LLFastTimerView::doAnalysis( + gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name), + gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name), + gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name)); + } - SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ; + SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ; - LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; + LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; - //Note: - //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown() - //because some new image might be generated during cleaning up media. --bao - gTextureList.shutdown(); // shutdown again in case a callback added something - LLUIImageList::getInstance()->cleanUp(); + //Note: + //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown() + //because some new image might be generated during cleaning up media. --bao + gTextureList.shutdown(); // shutdown again in case a callback added something + LLUIImageList::getInstance()->cleanUp(); - SUBSYSTEM_CLEANUP(LLImage); - SUBSYSTEM_CLEANUP(LLLFSThread); + SUBSYSTEM_CLEANUP(LLImage); + SUBSYSTEM_CLEANUP(LLLFSThread); - LL_INFOS() << "Misc Cleanup" << LL_ENDL; + LL_INFOS() << "Misc Cleanup" << LL_ENDL; - gSavedSettings.cleanup(); - LLUIColorTable::instance().clear(); + gSavedSettings.cleanup(); + LLUIColorTable::instance().clear(); - LLWatchdog::getInstance()->cleanup(); + LLWatchdog::getInstance()->cleanup(); - LLViewerAssetStatsFF::cleanup(); + LLViewerAssetStatsFF::cleanup(); - // If we're exiting to launch an URL, do that here so the screen - // is at the right resolution before we launch IE. - if (!gLaunchFileOnQuit.empty()) - { - LL_INFOS() << "Launch file on quit." << LL_ENDL; + // If we're exiting to launch an URL, do that here so the screen + // is at the right resolution before we launch IE. + if (!gLaunchFileOnQuit.empty()) + { + LL_INFOS() << "Launch file on quit." << LL_ENDL; #if LL_WINDOWS - // Indicate an application is starting. - SetCursor(LoadCursor(NULL, IDC_WAIT)); + // Indicate an application is starting. + SetCursor(LoadCursor(NULL, IDC_WAIT)); #endif - // HACK: Attempt to wait until the screen res. switch is complete. - ms_sleep(1000); + // HACK: Attempt to wait until the screen res. switch is complete. + ms_sleep(1000); - LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); - LL_INFOS() << "File launched." << LL_ENDL; - } - // make sure nothing uses applyProxySettings by this point. - LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; - SUBSYSTEM_CLEANUP(LLProxy); + LLWeb::loadURLExternal( gLaunchFileOnQuit, false ); + LL_INFOS() << "File launched." << LL_ENDL; + } + // make sure nothing uses applyProxySettings by this point. + LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; + SUBSYSTEM_CLEANUP(LLProxy); LLCore::LLHttp::cleanup(); - ll_close_fail_log(); + ll_close_fail_log(); - LLError::LLCallStacks::cleanup(); + LLError::LLCallStacks::cleanup(); LL::GLTFSceneManager::deleteSingleton(); - LLEnvironment::deleteSingleton(); - LLSelectMgr::deleteSingleton(); - LLViewerEventRecorder::deleteSingleton(); + LLEnvironment::deleteSingleton(); + LLSelectMgr::deleteSingleton(); + LLViewerEventRecorder::deleteSingleton(); LLWorld::deleteSingleton(); LLVoiceClient::deleteSingleton(); - // It's not at first obvious where, in this long sequence, a generic cleanup - // call OUGHT to go. So let's say this: as we migrate cleanup from - // explicit hand-placed calls into the generic mechanism, eventually - // all cleanup will get subsumed into the generic call. So the calls you - // still see above are calls that MUST happen before the generic cleanup - // kicks in. + // It's not at first obvious where, in this long sequence, a generic cleanup + // call OUGHT to go. So let's say this: as we migrate cleanup from + // explicit hand-placed calls into the generic mechanism, eventually + // all cleanup will get subsumed into the generic call. So the calls you + // still see above are calls that MUST happen before the generic cleanup + // kicks in. - // This calls every remaining LLSingleton's cleanupSingleton() and - // deleteSingleton() methods. - LLSingletonBase::deleteAll(); + // This calls every remaining LLSingleton's cleanupSingleton() and + // deleteSingleton() methods. + LLSingletonBase::deleteAll(); LLSplashScreen::hide(); LL_INFOS() << "Goodbye!" << LL_ENDL; - removeDumpDir(); + removeDumpDir(); - // return 0; - return true; + // return 0; + return true; } void LLAppViewer::initGeneralThread() @@ -2199,11 +2199,11 @@ void LLAppViewer::initGeneralThread() bool LLAppViewer::initThreads() { - static const bool enable_threads = true; + static const bool enable_threads = true; - LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); + LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); - LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo + LLLFSThread::initClass(enable_threads && true); // TODO: fix crashes associated with this shutdo //auto configure thread count LLSD threadCounts = gSavedSettings.getLLSD("ThreadPoolSizes"); @@ -2218,39 +2218,39 @@ bool LLAppViewer::initThreads() } // The only configurable thread count right now is ImageDecode - // The viewer typically starts around 8 threads not including image decode, + // The viewer typically starts around 8 threads not including image decode, // so try to leave at least one core free S32 image_decode_count = llclamp(cores - 9, 1, 8); threadCounts["ImageDecode"] = image_decode_count; gSavedSettings.setLLSD("ThreadPoolSizes", threadCounts); - // Image decoding - LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); - LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); - LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), - enable_threads && true, - app_metrics_qa_mode); + // Image decoding + LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); + LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); + LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), + enable_threads && true, + app_metrics_qa_mode); // general task background thread (LLPerfStats, etc) LLAppViewer::instance()->initGeneralThread(); - LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread(); + LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread(); - if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog) - { - LLTrace::BlockTimer::setLogLock(new LLMutex()); - mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName); - mFastTimerLogThread->start(); - } + if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog) + { + LLTrace::BlockTimer::setLogLock(new LLMutex()); + mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName); + mFastTimerLogThread->start(); + } - // Mesh streaming and caching - gMeshRepo.init(); + // Mesh streaming and caching + gMeshRepo.init(); - LLFilePickerThread::initClass(); - LLDirPickerThread::initClass(); + LLFilePickerThread::initClass(); + LLDirPickerThread::initClass(); - // *FIX: no error handling here! - return true; + // *FIX: no error handling here! + return true; } void errorCallback(LLError::ELevel level, const std::string &error_string) @@ -2294,7 +2294,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() if (mSecondInstance) { LLFile::mkdir(gDirUtilp->getDumpLogsDirPath()); - + LLUUID uid; uid.generate(); LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log")); @@ -2365,123 +2365,123 @@ void LLAppViewer::initLoggingAndGetLastDuration() } bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, - bool set_defaults) + bool set_defaults) { - if (!mSettingsLocationList) - { - LL_ERRS() << "Invalid settings location list" << LL_ENDL; - } - - for (const SettingsGroup& group : mSettingsLocationList->groups) - { - // skip settings groups that aren't the one we requested - if (group.name() != location_key) continue; - - ELLPath path_index = (ELLPath)group.path_index(); - if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST) - { - LL_ERRS() << "Out of range path index in app_settings/settings_files.xml" << LL_ENDL; - return false; - } - - for (const SettingsFile& file : group.files) - { - LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name() - << " - from location " << location_key << LL_ENDL; - - auto settings_group = LLControlGroup::getInstance(file.name); - if(!settings_group) - { - LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL; - continue; - } - - std::string full_settings_path; - - if (file.file_name_setting.isProvided() - && gSavedSettings.controlExists(file.file_name_setting)) - { - // try to find filename stored in file_name_setting control - full_settings_path = gSavedSettings.getString(file.file_name_setting); - if (full_settings_path.empty()) - { - continue; - } - else if (!gDirUtilp->fileExists(full_settings_path)) - { - // search in default path - full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path); - } - } - else - { - // by default, use specified file name - full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name()); - } - - if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent)) - { // success! - LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL; - } - else - { // failed to load - if(file.required) - { + if (!mSettingsLocationList) + { + LL_ERRS() << "Invalid settings location list" << LL_ENDL; + } + + for (const SettingsGroup& group : mSettingsLocationList->groups) + { + // skip settings groups that aren't the one we requested + if (group.name() != location_key) continue; + + ELLPath path_index = (ELLPath)group.path_index(); + if(path_index <= LL_PATH_NONE || path_index >= LL_PATH_LAST) + { + LL_ERRS() << "Out of range path index in app_settings/settings_files.xml" << LL_ENDL; + return false; + } + + for (const SettingsFile& file : group.files) + { + LL_INFOS("Settings") << "Attempting to load settings for the group " << file.name() + << " - from location " << location_key << LL_ENDL; + + auto settings_group = LLControlGroup::getInstance(file.name); + if(!settings_group) + { + LL_WARNS("Settings") << "No matching settings group for name " << file.name() << LL_ENDL; + continue; + } + + std::string full_settings_path; + + if (file.file_name_setting.isProvided() + && gSavedSettings.controlExists(file.file_name_setting)) + { + // try to find filename stored in file_name_setting control + full_settings_path = gSavedSettings.getString(file.file_name_setting); + if (full_settings_path.empty()) + { + continue; + } + else if (!gDirUtilp->fileExists(full_settings_path)) + { + // search in default path + full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, full_settings_path); + } + } + else + { + // by default, use specified file name + full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name()); + } + + if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent)) + { // success! + LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL; + } + else + { // failed to load + if(file.required) + { LLError::LLUserWarningMsg::showMissingFiles(); - LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL; - return false; - } - else - { - // only complain if we actually have a filename at this point - if (!full_settings_path.empty()) - { - LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL; - } - } - } - } - } - - return true; + LL_ERRS() << "Error: Cannot load required settings file from: " << full_settings_path << LL_ENDL; + return false; + } + else + { + // only complain if we actually have a filename at this point + if (!full_settings_path.empty()) + { + LL_INFOS("Settings") << "Cannot load " << full_settings_path << " - No settings found." << LL_ENDL; + } + } + } + } + } + + return true; } std::string LLAppViewer::getSettingsFilename(const std::string& location_key, - const std::string& file) + const std::string& file) { - for (const SettingsGroup& group : mSettingsLocationList->groups) - { - if (group.name() == location_key) - { - for (const SettingsFile& settings_file : group.files) - { - if (settings_file.name() == file) - { - return settings_file.file_name; - } - } - } - } - - return std::string(); + for (const SettingsGroup& group : mSettingsLocationList->groups) + { + if (group.name() == location_key) + { + for (const SettingsFile& settings_file : group.files) + { + if (settings_file.name() == file) + { + return settings_file.file_name; + } + } + } + } + + return std::string(); } void LLAppViewer::loadColorSettings() { - LLUIColorTable::instance().loadFromSettings(); + LLUIColorTable::instance().loadFromSettings(); } namespace { void handleCommandLineError(LLControlGroupCLP& clp) { - LL_WARNS() << "Error parsing command line options. Command Line options ignored." << LL_ENDL; + LL_WARNS() << "Error parsing command line options. Command Line options ignored." << LL_ENDL; - LL_INFOS() << "Command line usage:\n" << clp << LL_ENDL; + LL_INFOS() << "Command line usage:\n" << clp << LL_ENDL; - OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()), - LLStringUtil::null, - OSMB_OK); + OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()), + LLStringUtil::null, + OSMB_OK); } } // anonymous namespace @@ -2489,42 +2489,42 @@ namespace // Name can be specified as ".", with default group being Global. bool tempSetControl(const std::string& name, const std::string& value) { - std::string name_part; - std::string group_part; - LLControlVariable* control = NULL; - - // Name can be further split into ControlGroup.Name, with the default control group being Global - size_t pos = name.find('.'); - if (pos != std::string::npos) - { - group_part = name.substr(0, pos); - name_part = name.substr(pos+1); - LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; - auto g = LLControlGroup::getInstance(group_part); - if (g) control = g->getControl(name_part); - } - else - { - LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; - control = gSavedSettings.getControl(name); - } - - if (control) - { - control->setValue(value, false); - return true; - } - return false; + std::string name_part; + std::string group_part; + LLControlVariable* control = NULL; + + // Name can be further split into ControlGroup.Name, with the default control group being Global + size_t pos = name.find('.'); + if (pos != std::string::npos) + { + group_part = name.substr(0, pos); + name_part = name.substr(pos+1); + LL_INFOS() << "Setting " << group_part << "." << name_part << " to " << value << LL_ENDL; + auto g = LLControlGroup::getInstance(group_part); + if (g) control = g->getControl(name_part); + } + else + { + LL_INFOS() << "Setting Global." << name << " to " << value << LL_ENDL; + control = gSavedSettings.getControl(name); + } + + if (control) + { + control->setValue(value, false); + return true; + } + return false; } bool LLAppViewer::initConfiguration() { - //Load settings files list - std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); - LLXMLNodePtr root; - BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL); - if (!success) - { + //Load settings files list + std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); + LLXMLNodePtr root; + BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL); + if (!success) + { LL_WARNS() << "Cannot load default configuration file " << settings_file_list << LL_ENDL; LLError::LLUserWarningMsg::showMissingFiles(); if (gDirUtilp->fileExists(settings_file_list)) @@ -2541,175 +2541,175 @@ bool LLAppViewer::initConfiguration() << "and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; } - } + } - mSettingsLocationList = new SettingsFiles(); + mSettingsLocationList = new SettingsFiles(); - LLXUIParser parser; - parser.readXUI(root, *mSettingsLocationList, settings_file_list); + LLXUIParser parser; + parser.readXUI(root, *mSettingsLocationList, settings_file_list); - if (!mSettingsLocationList->validateBlock()) - { + if (!mSettingsLocationList->validateBlock()) + { LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Invalid settings file list " << settings_file_list << LL_ENDL; - } - - // The settings and command line parsing have a fragile - // order-of-operation: - // - load defaults from app_settings - // - set procedural settings values - // - read command line settings - // - selectively apply settings needed to load user settings. + } + + // The settings and command line parsing have a fragile + // order-of-operation: + // - load defaults from app_settings + // - set procedural settings values + // - read command line settings + // - selectively apply settings needed to load user settings. // - load overrides from user_settings - // - apply command line settings (to override the overrides) - // - load per account settings (happens in llstartup - - // - load defaults - bool set_defaults = true; - if(!loadSettingsFromDirectory("Default", set_defaults)) - { - OSMessageBox( - "Unable to load default settings file. The installation may be corrupted.", - LLStringUtil::null,OSMB_OK); - return false; - } - - initStrings(); // setup paths for LLTrans based on settings files only - // - set procedural settings - // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet - gSavedSettings.setString("ClientSettingsFile", + // - apply command line settings (to override the overrides) + // - load per account settings (happens in llstartup + + // - load defaults + bool set_defaults = true; + if(!loadSettingsFromDirectory("Default", set_defaults)) + { + OSMessageBox( + "Unable to load default settings file. The installation may be corrupted.", + LLStringUtil::null,OSMB_OK); + return false; + } + + initStrings(); // setup paths for LLTrans based on settings files only + // - set procedural settings + // Note: can't use LL_PATH_PER_SL_ACCOUNT for any of these since we haven't logged in yet + gSavedSettings.setString("ClientSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, getSettingsFilename("Default", "Global"))); -#ifndef LL_RELEASE_FOR_DOWNLOAD - // provide developer build only overrides for these control variables that are not - // persisted to settings.xml - LLControlVariable* c = gSavedSettings.getControl("AllowMultipleViewers"); - if (c) - { - c->setValue(true, false); - } - - gSavedSettings.setBOOL("QAMode", TRUE ); - gSavedSettings.setS32("WatchdogEnabled", 0); +#ifndef LL_RELEASE_FOR_DOWNLOAD + // provide developer build only overrides for these control variables that are not + // persisted to settings.xml + LLControlVariable* c = gSavedSettings.getControl("AllowMultipleViewers"); + if (c) + { + c->setValue(true, false); + } + + gSavedSettings.setBOOL("QAMode", TRUE ); + gSavedSettings.setS32("WatchdogEnabled", 0); #endif - // These are warnings that appear on the first experience of that condition. - // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse - // for disable/reset ability -// LLFirstUse::addConfigVariable("FirstBalanceIncrease"); -// LLFirstUse::addConfigVariable("FirstBalanceDecrease"); -// LLFirstUse::addConfigVariable("FirstSit"); -// LLFirstUse::addConfigVariable("FirstMap"); -// LLFirstUse::addConfigVariable("FirstGoTo"); -// LLFirstUse::addConfigVariable("FirstBuild"); -// LLFirstUse::addConfigVariable("FirstLeftClickNoHit"); -// LLFirstUse::addConfigVariable("FirstTeleport"); -// LLFirstUse::addConfigVariable("FirstOverrideKeys"); -// LLFirstUse::addConfigVariable("FirstAttach"); -// LLFirstUse::addConfigVariable("FirstAppearance"); -// LLFirstUse::addConfigVariable("FirstInventory"); -// LLFirstUse::addConfigVariable("FirstSandbox"); -// LLFirstUse::addConfigVariable("FirstFlexible"); -// LLFirstUse::addConfigVariable("FirstDebugMenus"); -// LLFirstUse::addConfigVariable("FirstSculptedPrim"); -// LLFirstUse::addConfigVariable("FirstVoice"); -// LLFirstUse::addConfigVariable("FirstMedia"); - - // - read command line settings. - LLControlGroupCLP clp; - std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, - "cmd_line.xml"); - - clp.configure(cmd_line_config, &gSavedSettings); - - if(!initParseCommandLine(clp)) - { - handleCommandLineError(clp); - return false; - } - - // - selectively apply settings - - // If the user has specified a alternate settings file name. - // Load it now before loading the user_settings/settings.xml - if(clp.hasOption("settings")) - { - std::string user_settings_filename = - gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, - clp.getOption("settings")[0]); - gSavedSettings.setString("ClientSettingsFile", user_settings_filename); - LL_INFOS("Settings") << "Using command line specified settings filename: " - << user_settings_filename << LL_ENDL; - } - - // - load overrides from user_settings - loadSettingsFromDirectory("User"); - - if (gSavedSettings.getBOOL("FirstRunThisInstall")) - { - // Set firstrun flag to indicate that some further init actiona should be taken - // like determining screen DPI value and so on - mIsFirstRun = true; - - gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); - } - - if (clp.hasOption("sessionsettings")) - { - std::string session_settings_filename = clp.getOption("sessionsettings")[0]; - gSavedSettings.setString("SessionSettingsFile", session_settings_filename); - LL_INFOS("Settings") << "Using session settings filename: " - << session_settings_filename << LL_ENDL; - } - loadSettingsFromDirectory("Session"); - - if (clp.hasOption("usersessionsettings")) - { - std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0]; - gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename); - LL_INFOS("Settings") << "Using user session settings filename: " - << user_session_settings_filename << LL_ENDL; - - } - loadSettingsFromDirectory("UserSession"); - - // - apply command line settings - if (! clp.notify()) - { - handleCommandLineError(clp); - return false; - } - - // Register the core crash option as soon as we can - // if we want gdb post-mortem on cores we need to be up and running - // ASAP or we might miss init issue etc. - if(gSavedSettings.getBOOL("DisableCrashLogger")) - { - LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL; - disableCrashlogger(); - } - - gNonInteractive = gSavedSettings.getBOOL("NonInteractive"); - // Handle initialization from settings. - // Start up the debugging console before handling other options. - if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive) - { - initConsole(); - } - - if(clp.hasOption("help")) - { - std::ostringstream msg; - msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp; - LL_INFOS() << msg.str() << LL_ENDL; - - OSMessageBox( - msg.str(), - LLStringUtil::null, - OSMB_OK); - - return false; - } + // These are warnings that appear on the first experience of that condition. + // They are already set in the settings_default.xml file, but still need to be added to LLFirstUse + // for disable/reset ability +// LLFirstUse::addConfigVariable("FirstBalanceIncrease"); +// LLFirstUse::addConfigVariable("FirstBalanceDecrease"); +// LLFirstUse::addConfigVariable("FirstSit"); +// LLFirstUse::addConfigVariable("FirstMap"); +// LLFirstUse::addConfigVariable("FirstGoTo"); +// LLFirstUse::addConfigVariable("FirstBuild"); +// LLFirstUse::addConfigVariable("FirstLeftClickNoHit"); +// LLFirstUse::addConfigVariable("FirstTeleport"); +// LLFirstUse::addConfigVariable("FirstOverrideKeys"); +// LLFirstUse::addConfigVariable("FirstAttach"); +// LLFirstUse::addConfigVariable("FirstAppearance"); +// LLFirstUse::addConfigVariable("FirstInventory"); +// LLFirstUse::addConfigVariable("FirstSandbox"); +// LLFirstUse::addConfigVariable("FirstFlexible"); +// LLFirstUse::addConfigVariable("FirstDebugMenus"); +// LLFirstUse::addConfigVariable("FirstSculptedPrim"); +// LLFirstUse::addConfigVariable("FirstVoice"); +// LLFirstUse::addConfigVariable("FirstMedia"); + + // - read command line settings. + LLControlGroupCLP clp; + std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, + "cmd_line.xml"); + + clp.configure(cmd_line_config, &gSavedSettings); + + if(!initParseCommandLine(clp)) + { + handleCommandLineError(clp); + return false; + } + + // - selectively apply settings + + // If the user has specified a alternate settings file name. + // Load it now before loading the user_settings/settings.xml + if(clp.hasOption("settings")) + { + std::string user_settings_filename = + gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, + clp.getOption("settings")[0]); + gSavedSettings.setString("ClientSettingsFile", user_settings_filename); + LL_INFOS("Settings") << "Using command line specified settings filename: " + << user_settings_filename << LL_ENDL; + } + + // - load overrides from user_settings + loadSettingsFromDirectory("User"); + + if (gSavedSettings.getBOOL("FirstRunThisInstall")) + { + // Set firstrun flag to indicate that some further init actiona should be taken + // like determining screen DPI value and so on + mIsFirstRun = true; + + gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); + } + + if (clp.hasOption("sessionsettings")) + { + std::string session_settings_filename = clp.getOption("sessionsettings")[0]; + gSavedSettings.setString("SessionSettingsFile", session_settings_filename); + LL_INFOS("Settings") << "Using session settings filename: " + << session_settings_filename << LL_ENDL; + } + loadSettingsFromDirectory("Session"); + + if (clp.hasOption("usersessionsettings")) + { + std::string user_session_settings_filename = clp.getOption("usersessionsettings")[0]; + gSavedSettings.setString("UserSessionSettingsFile", user_session_settings_filename); + LL_INFOS("Settings") << "Using user session settings filename: " + << user_session_settings_filename << LL_ENDL; + + } + loadSettingsFromDirectory("UserSession"); + + // - apply command line settings + if (! clp.notify()) + { + handleCommandLineError(clp); + return false; + } + + // Register the core crash option as soon as we can + // if we want gdb post-mortem on cores we need to be up and running + // ASAP or we might miss init issue etc. + if(gSavedSettings.getBOOL("DisableCrashLogger")) + { + LL_WARNS() << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << LL_ENDL; + disableCrashlogger(); + } + + gNonInteractive = gSavedSettings.getBOOL("NonInteractive"); + // Handle initialization from settings. + // Start up the debugging console before handling other options. + if (gSavedSettings.getBOOL("ShowConsoleWindow") && !gNonInteractive) + { + initConsole(); + } + + if(clp.hasOption("help")) + { + std::ostringstream msg; + msg << LLTrans::getString("MBCmdLineUsg") << "\n" << clp; + LL_INFOS() << msg.str() << LL_ENDL; + + OSMessageBox( + msg.str(), + LLStringUtil::null, + OSMB_OK); + + return false; + } if(clp.hasOption("set")) { @@ -2727,43 +2727,43 @@ bool LLAppViewer::initConfiguration() const std::string& value = *(++itr); if (!tempSetControl(name,value)) { - LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL; + LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL; } } } } if (clp.hasOption("logevents")) { - LLViewerEventRecorder::instance().setEventLoggingOn(); + LLViewerEventRecorder::instance().setEventLoggingOn(); } - std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel")); - if(! CmdLineChannel.empty()) + std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel")); + if(! CmdLineChannel.empty()) { - LLVersionInfo::instance().resetChannel(CmdLineChannel); - } + LLVersionInfo::instance().resetChannel(CmdLineChannel); + } - // If we have specified crash on startup, set the global so we'll trigger the crash at the right time - gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup"); + // If we have specified crash on startup, set the global so we'll trigger the crash at the right time + gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup"); - if (gSavedSettings.getBOOL("LogPerformance")) - { - LLTrace::BlockTimer::sLog = true; - LLTrace::BlockTimer::sLogName = std::string("performance"); - } + if (gSavedSettings.getBOOL("LogPerformance")) + { + LLTrace::BlockTimer::sLog = true; + LLTrace::BlockTimer::sLogName = std::string("performance"); + } - std::string test_name(gSavedSettings.getString("LogMetrics")); - if (! test_name.empty()) - { - LLTrace::BlockTimer::sMetricLog = TRUE; - // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test - // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...) - LL_INFOS() << "'--logmetrics' argument : " << test_name << LL_ENDL; - LLTrace::BlockTimer::sLogName = test_name; - } + std::string test_name(gSavedSettings.getString("LogMetrics")); + if (! test_name.empty()) + { + LLTrace::BlockTimer::sMetricLog = TRUE; + // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test + // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...) + LL_INFOS() << "'--logmetrics' argument : " << test_name << LL_ENDL; + LLTrace::BlockTimer::sLogName = test_name; + } - if (clp.hasOption("graphicslevel")) - { + if (clp.hasOption("graphicslevel")) + { // User explicitly requested --graphicslevel on the command line. We // expect this switch has already set RenderQualityPerformance. Check // that value for validity later. @@ -2772,18 +2772,18 @@ bool LLAppViewer::initConfiguration() // will call LLFeatureManager::applyRecommendedSettings(), which // overwrites this settings variable! mForceGraphicsLevel = gSavedSettings.getU32("RenderQualityPerformance"); - } + } - LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); - gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession")); + LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); + gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession")); - if (gSavedSettings.getBOOL("DebugSession")) - { - gDebugSession = TRUE; - gDebugGL = TRUE; + if (gSavedSettings.getBOOL("DebugSession")) + { + gDebugSession = TRUE; + gDebugGL = TRUE; - ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log")); - } + ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log")); + } if (gSavedSettings.getBOOL("RenderDebugGLSession")) { @@ -2794,47 +2794,47 @@ bool LLAppViewer::initConfiguration() gSavedSettings.setBOOL("RenderDebugGLSession", FALSE); } - const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); - if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) - { - // Examining "Language" may not suffice -- see LLUI::getLanguage() - // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much - // good because we haven't yet called LLUI::initClass(). - gDirUtilp->setSkinFolder(skinfolder->getValue().asString(), - gSavedSettings.getString("Language")); - } - - if (gSavedSettings.getBOOL("SpellCheck")) - { - std::list dict_list; - std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); - boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); - if (!dict_list.empty()) - { - LLSpellChecker::setUseSpellCheck(dict_list.front()); - dict_list.pop_front(); - LLSpellChecker::instance().setSecondaryDictionaries(dict_list); - } - } - - if (gNonInteractive) - { - tempSetControl("AllowMultipleViewers", "TRUE"); - tempSetControl("SLURLPassToOtherInstance", "FALSE"); - tempSetControl("RenderWater", "FALSE"); - tempSetControl("FlyingAtExit", "FALSE"); - tempSetControl("WindowWidth", "1024"); - tempSetControl("WindowHeight", "200"); - LLError::setEnabledLogTypesMask(0); - llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance")); - } - - - // Handle slurl use. NOTE: Don't let SL-55321 reappear. - // This initial-SLURL logic, up through the call to - // sendURLToOtherInstance(), must precede LLSplashScreen::show() -- - // because if sendURLToOtherInstance() succeeds, we take a fast exit, - // SKIPPING the splash screen and everything else. + const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); + if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) + { + // Examining "Language" may not suffice -- see LLUI::getLanguage() + // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much + // good because we haven't yet called LLUI::initClass(). + gDirUtilp->setSkinFolder(skinfolder->getValue().asString(), + gSavedSettings.getString("Language")); + } + + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + } + } + + if (gNonInteractive) + { + tempSetControl("AllowMultipleViewers", "TRUE"); + tempSetControl("SLURLPassToOtherInstance", "FALSE"); + tempSetControl("RenderWater", "FALSE"); + tempSetControl("FlyingAtExit", "FALSE"); + tempSetControl("WindowWidth", "1024"); + tempSetControl("WindowHeight", "200"); + LLError::setEnabledLogTypesMask(0); + llassert_always(!gSavedSettings.getBOOL("SLURLPassToOtherInstance")); + } + + + // Handle slurl use. NOTE: Don't let SL-55321 reappear. + // This initial-SLURL logic, up through the call to + // sendURLToOtherInstance(), must precede LLSplashScreen::show() -- + // because if sendURLToOtherInstance() succeeds, we take a fast exit, + // SKIPPING the splash screen and everything else. // *FIX: This init code should be made more robust to prevent // the issue SL-55321 from returning. One thought is to allow @@ -2852,143 +2852,143 @@ bool LLAppViewer::initConfiguration() // other browsers) and do the rough equivalent of command // injection and steal passwords. Phoenix. SL-55321 - std::string starting_location; - - std::string cmd_line_login_location(gSavedSettings.getString("CmdLineLoginLocation")); - if(! cmd_line_login_location.empty()) - { - starting_location = cmd_line_login_location; - } - else - { - std::string default_login_location(gSavedSettings.getString("DefaultLoginLocation")); - if (! default_login_location.empty()) - { - starting_location = default_login_location; - } - } - - LLSLURL start_slurl; - if (! starting_location.empty()) - { - start_slurl = starting_location; - LLStartUp::setStartSLURL(start_slurl); - if(start_slurl.getType() == LLSLURL::LOCATION) - { - LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid()); - } - } - - // NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL() - std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" ); - if ( !nextLoginLocation.empty() ) - { - LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<useMutex(); // LLApp and LLMutex magic must be manually enabled - LLPrimitive::setVolumeManager(volume_manager); - - // Note: this is where we used to initialize gFeatureManagerp. - - gStartTime = totalTime(); - - // - // Set the name of the window - // - gWindowTitle = LLTrans::getString("APP_NAME"); + std::string starting_location; + + std::string cmd_line_login_location(gSavedSettings.getString("CmdLineLoginLocation")); + if(! cmd_line_login_location.empty()) + { + starting_location = cmd_line_login_location; + } + else + { + std::string default_login_location(gSavedSettings.getString("DefaultLoginLocation")); + if (! default_login_location.empty()) + { + starting_location = default_login_location; + } + } + + LLSLURL start_slurl; + if (! starting_location.empty()) + { + start_slurl = starting_location; + LLStartUp::setStartSLURL(start_slurl); + if(start_slurl.getType() == LLSLURL::LOCATION) + { + LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid()); + } + } + + // NextLoginLocation is set as a side effect of LLStartUp::setStartSLURL() + std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" ); + if ( !nextLoginLocation.empty() ) + { + LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<useMutex(); // LLApp and LLMutex magic must be manually enabled + LLPrimitive::setVolumeManager(volume_manager); + + // Note: this is where we used to initialize gFeatureManagerp. + + gStartTime = totalTime(); + + // + // Set the name of the window + // + gWindowTitle = LLTrans::getString("APP_NAME"); #if LL_DEBUG - gWindowTitle += std::string(" [DEBUG]"); + gWindowTitle += std::string(" [DEBUG]"); #endif - if (!gArgs.empty()) - { - gWindowTitle += std::string(" ") + gArgs; - } - LLStringUtil::truncate(gWindowTitle, 255); - - // - // Check for another instance of the app running - // This happens AFTER LLSplashScreen::show(). That may or may not be - // important. - // - if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers")) - { - OSMessageBox( - LLTrans::getString("MBAlreadyRunning"), - LLStringUtil::null, - OSMB_OK); - return false; - } - - if (mSecondInstance) - { - // This is the second instance of SL. Mute voice, - // but make sure the setting is *not* persisted. - // Also see LLVivoxVoiceClient::voiceEnabled() - LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat"); - if(enable_voice) - { - const BOOL DO_NOT_PERSIST = FALSE; - enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST); - } - } - - gLastRunVersion = gSavedSettings.getString("LastRunVersion"); - - loadColorSettings(); - - // Let anyone else who cares know that we've populated our settings - // variables. - for (const auto& key : LLControlGroup::key_snapshot()) - { - // For each named instance of LLControlGroup, send an event saying - // we've initialized an LLControlGroup instance by that name. - LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key)); - } + if (!gArgs.empty()) + { + gWindowTitle += std::string(" ") + gArgs; + } + LLStringUtil::truncate(gWindowTitle, 255); + + // + // Check for another instance of the app running + // This happens AFTER LLSplashScreen::show(). That may or may not be + // important. + // + if (mSecondInstance && !gSavedSettings.getBOOL("AllowMultipleViewers")) + { + OSMessageBox( + LLTrans::getString("MBAlreadyRunning"), + LLStringUtil::null, + OSMB_OK); + return false; + } + + if (mSecondInstance) + { + // This is the second instance of SL. Mute voice, + // but make sure the setting is *not* persisted. + // Also see LLVivoxVoiceClient::voiceEnabled() + LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat"); + if(enable_voice) + { + const BOOL DO_NOT_PERSIST = FALSE; + enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST); + } + } + + gLastRunVersion = gSavedSettings.getString("LastRunVersion"); + + loadColorSettings(); + + // Let anyone else who cares know that we've populated our settings + // variables. + for (const auto& key : LLControlGroup::key_snapshot()) + { + // For each named instance of LLControlGroup, send an event saying + // we've initialized an LLControlGroup instance by that name. + LLEventPumps::instance().obtain("LLControlGroup").post(LLSDMap("init", key)); + } LLError::LLUserWarningMsg::setOutOfMemoryStrings(LLTrans::getString("MBOutOfMemoryTitle"), LLTrans::getString("MBOutOfMemoryErr")); - return true; // Config was successful. + return true; // Config was successful. } // The following logic is replicated in initConfiguration() (to be able to get @@ -2997,214 +2997,214 @@ bool LLAppViewer::initConfiguration() // keeps growing, necessitating a method all its own. void LLAppViewer::initStrings() { - std::string strings_file = "strings.xml"; - std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file); - if (strings_path_full.empty() || !LLFile::isfile(strings_path_full)) - { - if (strings_path_full.empty()) - { - LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL; - } - else - { - llstat st; - int rc = LLFile::stat(strings_path_full, &st); - if (rc != 0) - { - LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL; - } - else if (S_ISDIR(st.st_mode)) - { - LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL; - } - else - { - LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL; - } - } - - // initial check to make sure files are there failed - gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); + std::string strings_file = "strings.xml"; + std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file); + if (strings_path_full.empty() || !LLFile::isfile(strings_path_full)) + { + if (strings_path_full.empty()) + { + LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL; + } + else + { + llstat st; + int rc = LLFile::stat(strings_path_full, &st); + if (rc != 0) + { + LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL; + } + else if (S_ISDIR(st.st_mode)) + { + LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL; + } + else + { + LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL; + } + } + + // initial check to make sure files are there failed + gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); LLError::LLUserWarningMsg::showMissingFiles(); - LL_ERRS() << "Viewer failed to find localization and UI files." - << " Please reinstall viewer from https://secondlife.com/support/downloads" - << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; - } - LLTransUtil::parseStrings(strings_file, default_trans_args); - LLTransUtil::parseLanguageStrings("language_settings.xml"); - - // parseStrings() sets up the LLTrans substitution table. Add this one item. - LLTrans::setDefaultArg("[sourceid]", gSavedSettings.getString("sourceid")); - - // Now that we've set "[sourceid]", have to go back through - // default_trans_args and reinitialize all those other keys because some - // of them, in turn, reference "[sourceid]". - for (const std::string& key : default_trans_args) - { - std::string brackets(key), nobrackets(key); - // Invalid to inspect key[0] if key is empty(). But then, the entire - // body of this loop is pointless if key is empty(). - if (key.empty()) - continue; - - if (key[0] != '[') - { - // key was passed without brackets. That means that 'nobrackets' - // is correct but 'brackets' is not. - brackets = STRINGIZE('[' << brackets << ']'); - } - else - { - // key was passed with brackets. That means that 'brackets' is - // correct but 'nobrackets' is not. Erase the left bracket. - nobrackets.erase(0, 1); - std::string::size_type length(nobrackets.length()); - if (length && nobrackets[length - 1] == ']') - { - nobrackets.erase(length - 1); - } - } - // Calling LLTrans::getString() is what embeds the other default - // translation strings into this one. - LLTrans::setDefaultArg(brackets, LLTrans::getString(nobrackets)); - } + LL_ERRS() << "Viewer failed to find localization and UI files." + << " Please reinstall viewer from https://secondlife.com/support/downloads" + << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; + } + LLTransUtil::parseStrings(strings_file, default_trans_args); + LLTransUtil::parseLanguageStrings("language_settings.xml"); + + // parseStrings() sets up the LLTrans substitution table. Add this one item. + LLTrans::setDefaultArg("[sourceid]", gSavedSettings.getString("sourceid")); + + // Now that we've set "[sourceid]", have to go back through + // default_trans_args and reinitialize all those other keys because some + // of them, in turn, reference "[sourceid]". + for (const std::string& key : default_trans_args) + { + std::string brackets(key), nobrackets(key); + // Invalid to inspect key[0] if key is empty(). But then, the entire + // body of this loop is pointless if key is empty(). + if (key.empty()) + continue; + + if (key[0] != '[') + { + // key was passed without brackets. That means that 'nobrackets' + // is correct but 'brackets' is not. + brackets = STRINGIZE('[' << brackets << ']'); + } + else + { + // key was passed with brackets. That means that 'brackets' is + // correct but 'nobrackets' is not. Erase the left bracket. + nobrackets.erase(0, 1); + std::string::size_type length(nobrackets.length()); + if (length && nobrackets[length - 1] == ']') + { + nobrackets.erase(length - 1); + } + } + // Calling LLTrans::getString() is what embeds the other default + // translation strings into this one. + LLTrans::setDefaultArg(brackets, LLTrans::getString(nobrackets)); + } } bool LLAppViewer::meetsRequirementsForMaximizedStart() { bool maximizedOk = (gSysMemory.getPhysicalMemoryKB() >= U32Gigabytes(1)); - return maximizedOk; + return maximizedOk; } bool LLAppViewer::initWindow() { - LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL; - - // store setting in a global for easy access and modification - gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient"); - - // always start windowed - BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth"); - - LLViewerWindow::Params window_params; - window_params - .title(gWindowTitle) - .name(VIEWER_WINDOW_CLASSNAME) - .x(gSavedSettings.getS32("WindowX")) - .y(gSavedSettings.getS32("WindowY")) - .width(gSavedSettings.getU32("WindowWidth")) - .height(gSavedSettings.getU32("WindowHeight")) - .min_width(gSavedSettings.getU32("MinWindowWidth")) - .min_height(gSavedSettings.getU32("MinWindowHeight")) - .fullscreen(gSavedSettings.getBOOL("FullScreen")) - .ignore_pixel_depth(ignorePixelDepth) - .first_run(mIsFirstRun); - - gViewerWindow = new LLViewerWindow(window_params); - - LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL; - - // Need to load feature table before cheking to start watchdog. - bool use_watchdog = false; - int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); - if (watchdog_enabled_setting == -1) - { - use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); - } - else - { - // The user has explicitly set this setting; always use that value. - use_watchdog = bool(watchdog_enabled_setting); - } - - LL_INFOS("AppInit") << "watchdog" - << (use_watchdog ? " " : " NOT ") - << "enabled" - << " (setting = " << watchdog_enabled_setting << ")" - << LL_ENDL; - - if (use_watchdog) - { - LLWatchdog::getInstance()->init(); - } - - LLNotificationsUI::LLNotificationManager::getInstance(); + LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL; + + // store setting in a global for easy access and modification + gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient"); + + // always start windowed + BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth"); + + LLViewerWindow::Params window_params; + window_params + .title(gWindowTitle) + .name(VIEWER_WINDOW_CLASSNAME) + .x(gSavedSettings.getS32("WindowX")) + .y(gSavedSettings.getS32("WindowY")) + .width(gSavedSettings.getU32("WindowWidth")) + .height(gSavedSettings.getU32("WindowHeight")) + .min_width(gSavedSettings.getU32("MinWindowWidth")) + .min_height(gSavedSettings.getU32("MinWindowHeight")) + .fullscreen(gSavedSettings.getBOOL("FullScreen")) + .ignore_pixel_depth(ignorePixelDepth) + .first_run(mIsFirstRun); + + gViewerWindow = new LLViewerWindow(window_params); + + LL_INFOS("AppInit") << "gViewerwindow created." << LL_ENDL; + + // Need to load feature table before cheking to start watchdog. + bool use_watchdog = false; + int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled"); + if (watchdog_enabled_setting == -1) + { + use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled"); + } + else + { + // The user has explicitly set this setting; always use that value. + use_watchdog = bool(watchdog_enabled_setting); + } + + LL_INFOS("AppInit") << "watchdog" + << (use_watchdog ? " " : " NOT ") + << "enabled" + << " (setting = " << watchdog_enabled_setting << ")" + << LL_ENDL; + + if (use_watchdog) + { + LLWatchdog::getInstance()->init(); + } + + LLNotificationsUI::LLNotificationManager::getInstance(); #ifdef LL_DARWIN - //Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later) - LLOSInfo& os_info = LLOSInfo::instance(); - if (os_info.mMajorVer == 10 && os_info.mMinorVer < 7) - { - if ( os_info.mMinorVer == 6 && os_info.mBuild < 8 ) - gViewerWindow->getWindow()->setOldResize(true); - } + //Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later) + LLOSInfo& os_info = LLOSInfo::instance(); + if (os_info.mMajorVer == 10 && os_info.mMinorVer < 7) + { + if ( os_info.mMinorVer == 6 && os_info.mBuild < 8 ) + gViewerWindow->getWindow()->setOldResize(true); + } #endif - if (gSavedSettings.getBOOL("WindowMaximized")) - { - gViewerWindow->getWindow()->maximize(); - } + if (gSavedSettings.getBOOL("WindowMaximized")) + { + gViewerWindow->getWindow()->maximize(); + } - // - // Initialize GL stuff - // + // + // Initialize GL stuff + // - if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel))) - { - LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false); - gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel); - } + if (mForceGraphicsLevel && (LLFeatureManager::instance().isValidGraphicsLevel(*mForceGraphicsLevel))) + { + LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false); + gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel); + } - // Set this flag in case we crash while initializing GL - gSavedSettings.setBOOL("RenderInitError", TRUE); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + // Set this flag in case we crash while initializing GL + gSavedSettings.setBOOL("RenderInitError", TRUE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); - gPipeline.init(); - LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL; + gPipeline.init(); + LL_INFOS("AppInit") << "gPipeline Initialized" << LL_ENDL; - stop_glerror(); - gViewerWindow->initGLDefaults(); + stop_glerror(); + gViewerWindow->initGLDefaults(); - gSavedSettings.setBOOL("RenderInitError", FALSE); - gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); + gSavedSettings.setBOOL("RenderInitError", FALSE); + gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); - //If we have a startup crash, it's usually near GL initialization, so simulate that. - if(gCrashOnStartup) - { - LLAppViewer::instance()->forceErrorLLError(); - } + //If we have a startup crash, it's usually near GL initialization, so simulate that. + if(gCrashOnStartup) + { + LLAppViewer::instance()->forceErrorLLError(); + } - // - // Determine if the window should start maximized on initial run based - // on graphics capability - // - if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart()) - { - LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL; - gSavedSettings.setBOOL("WindowMaximized", TRUE); - } + // + // Determine if the window should start maximized on initial run based + // on graphics capability + // + if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart()) + { + LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL; + gSavedSettings.setBOOL("WindowMaximized", TRUE); + } - if (gSavedSettings.getBOOL("WindowMaximized")) - { - gViewerWindow->getWindow()->maximize(); - } + if (gSavedSettings.getBOOL("WindowMaximized")) + { + gViewerWindow->getWindow()->maximize(); + } - LLUI::getInstance()->mWindow = gViewerWindow->getWindow(); + LLUI::getInstance()->mWindow = gViewerWindow->getWindow(); - // Show watch cursor - gViewerWindow->setCursor(UI_CURSOR_WAIT); + // Show watch cursor + gViewerWindow->setCursor(UI_CURSOR_WAIT); - // Finish view initialization - gViewerWindow->initBase(); + // Finish view initialization + gViewerWindow->initBase(); - // show viewer window - //gViewerWindow->getWindow()->show(); + // show viewer window + //gViewerWindow->getWindow()->show(); - LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL; + LL_INFOS("AppInit") << "Window initialization done." << LL_ENDL; - return true; + return true; } bool LLAppViewer::isUpdaterMissing() @@ -3243,28 +3243,28 @@ void LLAppViewer::writeDebugInfo(bool isStatic) LLSD LLAppViewer::getViewerInfo() const { - // The point of having one method build an LLSD info block and the other - // construct the user-visible About string is to ensure that the same info - // is available to a getInfo() caller as to the user opening - // LLFloaterAbout. - LLSD info; - auto& versionInfo(LLVersionInfo::instance()); - // With GitHub builds, the build number is too big to fit in a 32-bit int, - // and LLSD doesn't deal with integers wider than int. Use string. - info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(), - versionInfo.getPatch(), stringize(versionInfo.getBuild())); - info["VIEWER_VERSION_STR"] = versionInfo.getVersion(); - info["CHANNEL"] = versionInfo.getChannel(); - info["ADDRESS_SIZE"] = ADDRESS_SIZE; - std::string build_config = versionInfo.getBuildConfig(); - if (build_config != "Release") - { - info["BUILD_CONFIG"] = build_config; - } - - // return a URL to the release notes for this viewer, such as: - // https://releasenotes.secondlife.com/viewer/2.1.0.123456.html - std::string url = versionInfo.getReleaseNotes(); // VVM supplied + // The point of having one method build an LLSD info block and the other + // construct the user-visible About string is to ensure that the same info + // is available to a getInfo() caller as to the user opening + // LLFloaterAbout. + LLSD info; + auto& versionInfo(LLVersionInfo::instance()); + // With GitHub builds, the build number is too big to fit in a 32-bit int, + // and LLSD doesn't deal with integers wider than int. Use string. + info["VIEWER_VERSION"] = llsd::array(versionInfo.getMajor(), versionInfo.getMinor(), + versionInfo.getPatch(), stringize(versionInfo.getBuild())); + info["VIEWER_VERSION_STR"] = versionInfo.getVersion(); + info["CHANNEL"] = versionInfo.getChannel(); + info["ADDRESS_SIZE"] = ADDRESS_SIZE; + std::string build_config = versionInfo.getBuildConfig(); + if (build_config != "Release") + { + info["BUILD_CONFIG"] = build_config; + } + + // return a URL to the release notes for this viewer, such as: + // https://releasenotes.secondlife.com/viewer/2.1.0.123456.html + std::string url = versionInfo.getReleaseNotes(); // VVM supplied if (url.empty()) { url = LLTrans::getString("RELEASE_NOTES_BASE_URL"); @@ -3272,32 +3272,32 @@ LLSD LLAppViewer::getViewerInfo() const url += "/"; url += LLURI::escape(versionInfo.getVersion()) + ".html"; } - info["VIEWER_RELEASE_NOTES_URL"] = url; - - // Position - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - LLVector3d pos = gAgent.getPositionGlobal(); - info["POSITION"] = ll_sd_from_vector3d(pos); - info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos)); - info["REGION"] = gAgent.getRegion()->getName(); - - boost::regex regex("\\.(secondlife|lindenlab)\\..*"); - info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, ""); - info["SERVER_VERSION"] = gLastVersionChannel; - LLSLURL slurl; - LLAgentUI::buildSLURL(slurl); - info["SLURL"] = slurl.getSLURLString(); - } - - // CPU - info["CPU"] = gSysCPU.getCPUString(); - info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().valueInUnits()); - // Moved hack adjustment to Windows memory size into llsys.cpp - info["OS_VERSION"] = LLOSInfo::instance().getOSString(); - info["GRAPHICS_CARD_VENDOR"] = ll_safe_string((const char*)(glGetString(GL_VENDOR))); - info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER))); + info["VIEWER_RELEASE_NOTES_URL"] = url; + + // Position + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + LLVector3d pos = gAgent.getPositionGlobal(); + info["POSITION"] = ll_sd_from_vector3d(pos); + info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos)); + info["REGION"] = gAgent.getRegion()->getName(); + + boost::regex regex("\\.(secondlife|lindenlab)\\..*"); + info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, ""); + info["SERVER_VERSION"] = gLastVersionChannel; + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + info["SLURL"] = slurl.getSLURLString(); + } + + // CPU + info["CPU"] = gSysCPU.getCPUString(); + info["MEMORY_MB"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().valueInUnits()); + // Moved hack adjustment to Windows memory size into llsys.cpp + info["OS_VERSION"] = LLOSInfo::instance().getOSString(); + info["GRAPHICS_CARD_VENDOR"] = ll_safe_string((const char*)(glGetString(GL_VENDOR))); + info["GRAPHICS_CARD"] = ll_safe_string((const char*)(glGetString(GL_RENDERER))); #if LL_WINDOWS std::string drvinfo; @@ -3322,22 +3322,22 @@ LLSD LLAppViewer::getViewerInfo() const drvinfo = gDXHardware.getDriverVersionWMI(LLDXHardware::GPU_ANY); } - if (!drvinfo.empty()) - { - info["GRAPHICS_DRIVER_VERSION"] = drvinfo; - } - else - { - LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL; - LLSD driver_info = gDXHardware.getDisplayInfo(); - if (driver_info.has("DriverVersion")) - { - info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"]; - } - } + if (!drvinfo.empty()) + { + info["GRAPHICS_DRIVER_VERSION"] = drvinfo; + } + else + { + LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL; + LLSD driver_info = gDXHardware.getDisplayInfo(); + if (driver_info.has("DriverVersion")) + { + info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"]; + } + } #endif - info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION))); + info["OPENGL_VERSION"] = ll_safe_string((const char*)(glGetString(GL_VERSION))); // Settings @@ -3356,16 +3356,16 @@ LLSD LLAppViewer::getViewerInfo() const info["HIDPI"] = gHiDPISupport; #endif - // Libraries + // Libraries - info["J2C_VERSION"] = LLImageJ2C::getEngineInfo(); - bool want_fullname = true; - info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined"; - if(LLVoiceClient::getInstance()->voiceEnabled()) - { + info["J2C_VERSION"] = LLImageJ2C::getEngineInfo(); + bool want_fullname = true; + info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : "Undefined"; + if(LLVoiceClient::getInstance()->voiceEnabled()) + { LLVoiceVersionInfo version = LLVoiceClient::getInstance()->getVersion(); const std::string build_version = version.mBuildVersion; - std::ostringstream version_string; + std::ostringstream version_string; if (std::equal(build_version.begin(), build_version.begin() + version.serverVersion.size(), version.serverVersion.begin())) { // Normal case: Show type and build version. @@ -3375,210 +3375,210 @@ LLSD LLAppViewer::getViewerInfo() const { // Mismatch: Show both versions. version_string << version.serverVersion << "/" << build_version << std::endl; } - info["VOICE_VERSION"] = version_string.str(); - } - else - { - info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); - } + info["VOICE_VERSION"] = version_string.str(); + } + else + { + info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); + } #if !LL_LINUX - std::ostringstream cef_ver_codec; - cef_ver_codec << "Dullahan: "; - cef_ver_codec << DULLAHAN_VERSION_MAJOR; - cef_ver_codec << "."; - cef_ver_codec << DULLAHAN_VERSION_MINOR; - cef_ver_codec << "."; - cef_ver_codec << DULLAHAN_VERSION_POINT; - cef_ver_codec << "."; - cef_ver_codec << DULLAHAN_VERSION_BUILD; - - cef_ver_codec << std::endl; - cef_ver_codec << " CEF: "; - cef_ver_codec << CEF_VERSION; - - cef_ver_codec << std::endl; - cef_ver_codec << " Chromium: "; - cef_ver_codec << CHROME_VERSION_MAJOR; - cef_ver_codec << "."; - cef_ver_codec << CHROME_VERSION_MINOR; - cef_ver_codec << "."; - cef_ver_codec << CHROME_VERSION_BUILD; - cef_ver_codec << "."; - cef_ver_codec << CHROME_VERSION_PATCH; - - info["LIBCEF_VERSION"] = cef_ver_codec.str(); + std::ostringstream cef_ver_codec; + cef_ver_codec << "Dullahan: "; + cef_ver_codec << DULLAHAN_VERSION_MAJOR; + cef_ver_codec << "."; + cef_ver_codec << DULLAHAN_VERSION_MINOR; + cef_ver_codec << "."; + cef_ver_codec << DULLAHAN_VERSION_POINT; + cef_ver_codec << "."; + cef_ver_codec << DULLAHAN_VERSION_BUILD; + + cef_ver_codec << std::endl; + cef_ver_codec << " CEF: "; + cef_ver_codec << CEF_VERSION; + + cef_ver_codec << std::endl; + cef_ver_codec << " Chromium: "; + cef_ver_codec << CHROME_VERSION_MAJOR; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_MINOR; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_BUILD; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_PATCH; + + info["LIBCEF_VERSION"] = cef_ver_codec.str(); #else - info["LIBCEF_VERSION"] = "Undefined"; + info["LIBCEF_VERSION"] = "Undefined"; #endif #if !LL_LINUX - std::ostringstream vlc_ver_codec; - vlc_ver_codec << LIBVLC_VERSION_MAJOR; - vlc_ver_codec << "."; - vlc_ver_codec << LIBVLC_VERSION_MINOR; - vlc_ver_codec << "."; - vlc_ver_codec << LIBVLC_VERSION_REVISION; - info["LIBVLC_VERSION"] = vlc_ver_codec.str(); + std::ostringstream vlc_ver_codec; + vlc_ver_codec << LIBVLC_VERSION_MAJOR; + vlc_ver_codec << "."; + vlc_ver_codec << LIBVLC_VERSION_MINOR; + vlc_ver_codec << "."; + vlc_ver_codec << LIBVLC_VERSION_REVISION; + info["LIBVLC_VERSION"] = vlc_ver_codec.str(); #else - info["LIBVLC_VERSION"] = "Undefined"; + info["LIBVLC_VERSION"] = "Undefined"; #endif - S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); - if (packets_in > 0) - { - info["PACKETS_LOST"] = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST); - info["PACKETS_IN"] = packets_in; - info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal(); - } - - if (mServerReleaseNotesURL.empty()) - { - if (gAgent.getRegion()) - { - info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("RetrievingData"); - } - else - { - info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("NotConnected"); - } - } - else if (LLStringUtil::startsWith(mServerReleaseNotesURL, "http")) // it's an URL - { - info["SERVER_RELEASE_NOTES_URL"] = "[" + LLWeb::escapeURL(mServerReleaseNotesURL) + " " + LLTrans::getString("ReleaseNotes") + "]"; - } - else - { - info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL; - } + S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); + if (packets_in > 0) + { + info["PACKETS_LOST"] = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_LOST); + info["PACKETS_IN"] = packets_in; + info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal(); + } + + if (mServerReleaseNotesURL.empty()) + { + if (gAgent.getRegion()) + { + info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("RetrievingData"); + } + else + { + info["SERVER_RELEASE_NOTES_URL"] = LLTrans::getString("NotConnected"); + } + } + else if (LLStringUtil::startsWith(mServerReleaseNotesURL, "http")) // it's an URL + { + info["SERVER_RELEASE_NOTES_URL"] = "[" + LLWeb::escapeURL(mServerReleaseNotesURL) + " " + LLTrans::getString("ReleaseNotes") + "]"; + } + else + { + info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL; + } // populate field for new local disk cache with some details info["DISK_CACHE_INFO"] = LLDiskCache::getInstance()->getCacheInfo(); - return info; + return info; } std::string LLAppViewer::getViewerInfoString(bool default_string) const { - std::ostringstream support; - - LLSD info(getViewerInfo()); - - // Render the LLSD from getInfo() as a format_map_t - LLStringUtil::format_map_t args; - - // allow the "Release Notes" URL label to be localized - args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string); - - for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap()); - ii != iend; ++ii) - { - if (! ii->second.isArray()) - { - // Scalar value - if (ii->second.isUndefined()) - { - args[ii->first] = LLTrans::getString("none_text", default_string); - } - else - { - // don't forget to render value asString() - args[ii->first] = ii->second.asString(); - } - } - else - { - // array value: build KEY_0, KEY_1 etc. entries - for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n) - { - args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString(); - } - } - } - - // Now build the various pieces - support << LLTrans::getString("AboutHeader", args, default_string); - if (info.has("BUILD_CONFIG")) - { - support << "\n" << LLTrans::getString("BuildConfig", args, default_string); - } - if (info.has("REGION")) - { - support << "\n\n" << LLTrans::getString("AboutPosition", args, default_string); - } - support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string); - support << "\n"; - if (info.has("GRAPHICS_DRIVER_VERSION")) - { - support << "\n" << LLTrans::getString("AboutDriver", args, default_string); - } - support << "\n" << LLTrans::getString("AboutOGL", args, default_string); - support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string); + std::ostringstream support; + + LLSD info(getViewerInfo()); + + // Render the LLSD from getInfo() as a format_map_t + LLStringUtil::format_map_t args; + + // allow the "Release Notes" URL label to be localized + args["ReleaseNotes"] = LLTrans::getString("ReleaseNotes", default_string); + + for (LLSD::map_const_iterator ii(info.beginMap()), iend(info.endMap()); + ii != iend; ++ii) + { + if (! ii->second.isArray()) + { + // Scalar value + if (ii->second.isUndefined()) + { + args[ii->first] = LLTrans::getString("none_text", default_string); + } + else + { + // don't forget to render value asString() + args[ii->first] = ii->second.asString(); + } + } + else + { + // array value: build KEY_0, KEY_1 etc. entries + for (LLSD::Integer n(0), size(ii->second.size()); n < size; ++n) + { + args[STRINGIZE(ii->first << '_' << n)] = ii->second[n].asString(); + } + } + } + + // Now build the various pieces + support << LLTrans::getString("AboutHeader", args, default_string); + if (info.has("BUILD_CONFIG")) + { + support << "\n" << LLTrans::getString("BuildConfig", args, default_string); + } + if (info.has("REGION")) + { + support << "\n\n" << LLTrans::getString("AboutPosition", args, default_string); + } + support << "\n\n" << LLTrans::getString("AboutSystem", args, default_string); + support << "\n"; + if (info.has("GRAPHICS_DRIVER_VERSION")) + { + support << "\n" << LLTrans::getString("AboutDriver", args, default_string); + } + support << "\n" << LLTrans::getString("AboutOGL", args, default_string); + support << "\n\n" << LLTrans::getString("AboutSettings", args, default_string); #if LL_DARWIN - support << "\n" << LLTrans::getString("AboutOSXHiDPI", args, default_string); + support << "\n" << LLTrans::getString("AboutOSXHiDPI", args, default_string); #endif - support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string); - if (info.has("COMPILER")) - { - support << "\n" << LLTrans::getString("AboutCompiler", args, default_string); - } - if (info.has("PACKETS_IN")) - { - support << '\n' << LLTrans::getString("AboutTraffic", args, default_string); - } - - // SLT timestamp - LLSD substitution; - substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected(); - support << "\n" << LLTrans::getString("AboutTime", substitution, default_string); - - return support.str(); + support << "\n\n" << LLTrans::getString("AboutLibs", args, default_string); + if (info.has("COMPILER")) + { + support << "\n" << LLTrans::getString("AboutCompiler", args, default_string); + } + if (info.has("PACKETS_IN")) + { + support << '\n' << LLTrans::getString("AboutTraffic", args, default_string); + } + + // SLT timestamp + LLSD substitution; + substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected(); + support << "\n" << LLTrans::getString("AboutTime", substitution, default_string); + + return support.str(); } void LLAppViewer::cleanupSavedSettings() { - gSavedSettings.setBOOL("MouseSun", FALSE); + gSavedSettings.setBOOL("MouseSun", FALSE); - gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator + gSavedSettings.setBOOL("UseEnergy", TRUE); // force toggle to turn off, since sends message to simulator - gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc); + gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc); - gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates); + gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates); - if (gDebugView) - { - gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible()); - } + if (gDebugView) + { + gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible()); + } - // save window position if not maximized - // as we don't track it in callbacks - if(NULL != gViewerWindow) - { - BOOL maximized = gViewerWindow->getWindow()->getMaximized(); - if (!maximized) - { - LLCoordScreen window_pos; + // save window position if not maximized + // as we don't track it in callbacks + if(NULL != gViewerWindow) + { + BOOL maximized = gViewerWindow->getWindow()->getMaximized(); + if (!maximized) + { + LLCoordScreen window_pos; - if (gViewerWindow->getWindow()->getPosition(&window_pos)) - { - gSavedSettings.setS32("WindowX", window_pos.mX); - gSavedSettings.setS32("WindowY", window_pos.mY); - } - } - } + if (gViewerWindow->getWindow()->getPosition(&window_pos)) + { + gSavedSettings.setS32("WindowX", window_pos.mX); + gSavedSettings.setS32("WindowY", window_pos.mY); + } + } + } gSavedSettings.setF32("MapScale", LLWorldMapView::getScaleSetting()); - // Some things are cached in LLAgent. - if (gAgent.isInitialized()) - { - gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance); - } + // Some things are cached in LLAgent. + if (gAgent.isInitialized()) + { + gSavedSettings.setF32("RenderFarClip", gAgentCamera.mDrawDistance); + } } void LLAppViewer::removeCacheFiles(const std::string& file_mask) { - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask); + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask); } void LLAppViewer::writeSystemInfo() @@ -3588,96 +3588,96 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["Dynamic"] = LLSD::emptyMap(); #if LL_WINDOWS && !LL_BUGSPLAT - gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log"); + gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log"); #else //Not ideal but sufficient for good reporting. gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLife.old"); //LLError::logFileName(); #endif - gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel(); - gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor(); - gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor(); - gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch(); - gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild()); - gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize(); + gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel(); + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild()); + gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::instance().getAddressSize(); - gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); + gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); - gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); - gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); - gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz(); - gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec(); - gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); - gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); + gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); + gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); + gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz(); + gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec(); + gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); + gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); - gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); - gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits()); - gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple(); + gDebugInfo["RAMInfo"]["Physical"] = LLSD::Integer(gSysMemory.getPhysicalMemoryKB().value()); + gDebugInfo["RAMInfo"]["Allocated"] = LLSD::Integer(gMemoryAllocated.valueInUnits()); + gDebugInfo["OSInfo"] = LLOSInfo::instance().getOSStringSimple(); - // The user is not logged on yet, but record the current grid choice login url - // which may have been the intended grid. - gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); + // The user is not logged on yet, but record the current grid choice login url + // which may have been the intended grid. + gDebugInfo["GridName"] = LLGridManager::getInstance()->getGridId(); - // *FIX:Mani - move this down in llappviewerwin32 + // *FIX:Mani - move this down in llappviewerwin32 #ifdef LL_WINDOWS - DWORD thread_id = GetCurrentThreadId(); - gDebugInfo["MainloopThreadID"] = (S32)thread_id; + DWORD thread_id = GetCurrentThreadId(); + gDebugInfo["MainloopThreadID"] = (S32)thread_id; #endif #ifndef LL_BUGSPLAT - // "CrashNotHandled" is set here, while things are running well, - // in case of a freeze. If there is a freeze, the crash logger will be launched - // and can read this value from the debug_info.log. - gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true); + // "CrashNotHandled" is set here, while things are running well, + // in case of a freeze. If there is a freeze, the crash logger will be launched + // and can read this value from the debug_info.log. + gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true); #else // LL_BUGSPLAT - // "CrashNotHandled" is obsolete; it used (not very successsfully) + // "CrashNotHandled" is obsolete; it used (not very successsfully) // to try to distinguish crashes from freezes - the intent here to to avoid calling it a freeze - gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false); + gDebugInfo["CrashNotHandled"] = LLSD::Boolean(false); #endif // ! LL_BUGSPLAT - // Insert crash host url (url to post crash log to) if configured. This insures - // that the crash report will go to the proper location in the case of a - // prior freeze. - std::string crashHostUrl = gSavedSettings.get("CrashHostUrl"); - if(crashHostUrl != "") - { - gDebugInfo["CrashHostUrl"] = crashHostUrl; - } - - // Dump some debugging info - LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL; - LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::instance().getChannelAndVersion() << LL_ENDL; - - // Dump the local time and time zone - time_t now; - time(&now); - char tbuffer[256]; /* Flawfinder: ignore */ - strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now)); - LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL; - - // query some system information - LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL; - LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL; - LL_INFOS("SystemInfo") << "OS: " << LLOSInfo::instance().getOSStringSimple() << LL_ENDL; - LL_INFOS("SystemInfo") << "OS info: " << LLOSInfo::instance() << LL_ENDL; + // Insert crash host url (url to post crash log to) if configured. This insures + // that the crash report will go to the proper location in the case of a + // prior freeze. + std::string crashHostUrl = gSavedSettings.get("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } + + // Dump some debugging info + LL_INFOS("SystemInfo") << "Application: " << LLTrans::getString("APP_NAME") << LL_ENDL; + LL_INFOS("SystemInfo") << "Version: " << LLVersionInfo::instance().getChannelAndVersion() << LL_ENDL; + + // Dump the local time and time zone + time_t now; + time(&now); + char tbuffer[256]; /* Flawfinder: ignore */ + strftime(tbuffer, 256, "%Y-%m-%dT%H:%M:%S %Z", localtime(&now)); + LL_INFOS("SystemInfo") << "Local time: " << tbuffer << LL_ENDL; + + // query some system information + LL_INFOS("SystemInfo") << "CPU info:\n" << gSysCPU << LL_ENDL; + LL_INFOS("SystemInfo") << "Memory info:\n" << gSysMemory << LL_ENDL; + LL_INFOS("SystemInfo") << "OS: " << LLOSInfo::instance().getOSStringSimple() << LL_ENDL; + LL_INFOS("SystemInfo") << "OS info: " << LLOSInfo::instance() << LL_ENDL; gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); - gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); - gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); - gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin()); - gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); + gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); + gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); + gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin()); + gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); if (gViewerWindow) { - std::vector resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList(); - for (auto res_iter : resolutions) - { - gDebugInfo["DisplayInfo"].append(res_iter); - } + std::vector resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList(); + for (auto res_iter : resolutions) + { + gDebugInfo["DisplayInfo"].append(res_iter); + } } - writeDebugInfo(); // Save out debug_info.log early, in case of crash. + writeDebugInfo(); // Save out debug_info.log early, in case of crash. } #ifdef LL_WINDOWS @@ -3689,265 +3689,265 @@ void LLAppViewer::writeSystemInfo() // TODO make this a member function. void getFileList() { - std::stringstream filenames; - - typedef std::vector vec; - std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,""); - vec file_vec = gDirUtilp->getFilesInDir(pathname); - for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter) - { - filenames << *iter << " "; - if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) ) - { - std::string fullname = pathname + *iter; - llifstream fdat( fullname.c_str(), std::ifstream::binary); - if (fdat) - { - char buf[5]; - fdat.read(buf,4); - fdat.close(); - if (!strncmp(buf,"MDMP",4)) - { - gDebugInfo["Dynamic"]["MinidumpPath"] = fullname; - break; - } - } - } - } - filenames << std::endl; - gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str(); + std::stringstream filenames; + + typedef std::vector vec; + std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,""); + vec file_vec = gDirUtilp->getFilesInDir(pathname); + for(vec::const_iterator iter=file_vec.begin(); iter!=file_vec.end(); ++iter) + { + filenames << *iter << " "; + if ( ( iter->length() > 30 ) && (iter->rfind(".dmp") == (iter->length()-4) ) ) + { + std::string fullname = pathname + *iter; + llifstream fdat( fullname.c_str(), std::ifstream::binary); + if (fdat) + { + char buf[5]; + fdat.read(buf,4); + fdat.close(); + if (!strncmp(buf,"MDMP",4)) + { + gDebugInfo["Dynamic"]["MinidumpPath"] = fullname; + break; + } + } + } + } + filenames << std::endl; + gDebugInfo["Dynamic"]["DumpDirContents"] = filenames.str(); } #endif // static void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file) { - std::string marker_version(LLVersionInfo::instance().getChannelAndVersion()); - if ( marker_version.length() > MAX_MARKER_LENGTH ) - { - LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")" - << " greater than maximum (" << MAX_MARKER_LENGTH << ")" - << ": marker matching may be incorrect" - << LL_ENDL; - } - - // record the viewer version in the marker file - marker_file.write(marker_version.data(), marker_version.length()); + std::string marker_version(LLVersionInfo::instance().getChannelAndVersion()); + if ( marker_version.length() > MAX_MARKER_LENGTH ) + { + LL_WARNS_ONCE("MarkerFile") << "Version length ("<< marker_version.length()<< ")" + << " greater than maximum (" << MAX_MARKER_LENGTH << ")" + << ": marker matching may be incorrect" + << LL_ENDL; + } + + // record the viewer version in the marker file + marker_file.write(marker_version.data(), marker_version.length()); } bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const { - bool sameVersion = false; - - std::string my_version(LLVersionInfo::instance().getChannelAndVersion()); - char marker_version[MAX_MARKER_LENGTH]; - S32 marker_version_length; - - LLAPRFile marker_file; - marker_file.open(marker_name, LL_APR_RB); - if (marker_file.getFileHandle()) - { - marker_version_length = marker_file.read(marker_version, sizeof(marker_version)); - std::string marker_string(marker_version, marker_version_length); - if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) ) - { - sameVersion = true; - } - LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': " - << "\n mine '" << my_version << "'" - << "\n marker '" << marker_string << "'" - << "\n " << ( sameVersion ? "same" : "different" ) << " version" - << LL_ENDL; - marker_file.close(); - } - return sameVersion; + bool sameVersion = false; + + std::string my_version(LLVersionInfo::instance().getChannelAndVersion()); + char marker_version[MAX_MARKER_LENGTH]; + S32 marker_version_length; + + LLAPRFile marker_file; + marker_file.open(marker_name, LL_APR_RB); + if (marker_file.getFileHandle()) + { + marker_version_length = marker_file.read(marker_version, sizeof(marker_version)); + std::string marker_string(marker_version, marker_version_length); + if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) ) + { + sameVersion = true; + } + LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': " + << "\n mine '" << my_version << "'" + << "\n marker '" << marker_string << "'" + << "\n " << ( sameVersion ? "same" : "different" ) << " version" + << LL_ENDL; + marker_file.close(); + } + return sameVersion; } void LLAppViewer::processMarkerFiles() { - //We've got 4 things to test for here - // - Other Process Running (SecondLife.exec_marker present, locked) - // - Freeze (SecondLife.exec_marker present, not locked) - // - LLError Crash (SecondLife.llerror_marker present) - // - Other Crash (SecondLife.error_marker present) - // These checks should also remove these files for the last 2 cases if they currently exist - - std::ostringstream marker_log_stream; - bool marker_is_same_version = true; - // first, look for the marker created at startup and deleted on a clean exit - mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); - if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB)) - { - // File exists... - // first, read it to see if it was created by the same version (we need this later) - marker_is_same_version = markerIsSameVersion(mMarkerFileName); - - // now test to see if this file is locked by a running process (try to open for write) - marker_log_stream << "Checking exec marker file for lock..."; - mMarkerFile.open(mMarkerFileName, LL_APR_WB); - apr_file_t* fMarker = mMarkerFile.getFileHandle() ; - if (!fMarker) - { - marker_log_stream << "Exec marker file open failed - assume it is locked."; - mSecondInstance = true; // lock means that instance is running. - } - else - { - // We were able to open it, now try to lock it ourselves... - if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) - { - marker_log_stream << "Locking exec marker failed."; - mSecondInstance = true; // lost a race? be conservative - } - else - { - // No other instances; we've locked this file now, so record our version; delete on quit. - recordMarkerVersion(mMarkerFile); - marker_log_stream << "Exec marker file existed but was not locked; rewritten."; - } - } - initLoggingAndGetLastDuration(); - - std::string marker_log_msg(marker_log_stream.str()); - LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL; - - if (mSecondInstance) - { - LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL; - } - else if (marker_is_same_version) - { - // the file existed, is ours, and matched our version, so we can report on what it says - LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL; - gLastExecEvent = LAST_EXEC_OTHER_CRASH; - } - else - { - LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL; - } - } - else // marker did not exist... last exec (if any) did not freeze - { - initLoggingAndGetLastDuration(); - // Create the marker file for this execution & lock it; it will be deleted on a clean exit - apr_status_t s; - s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE); - - if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) - { - LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL; - if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE)) - { - recordMarkerVersion(mMarkerFile); - LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL; - } - else - { - LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL; - } - } - else - { - LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL; - } - } - - // now check for cases in which the exec marker may have been cleaned up by crash handlers - - // check for any last exec event report based on whether or not it happened during logout - // (the logout marker is created when logout begins) - std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); - if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB)) - { - if (markerIsSameVersion(logout_marker_file)) - { - gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; - LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; - } - else - { - LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL; - } - LLAPRFile::remove(logout_marker_file); - } - // further refine based on whether or not a marker created during an llerr crash is found - std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); - if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) - { - if (markerIsSameVersion(llerror_marker_file)) - { - if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE ) - { - gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; - } - else - { - gLastExecEvent = LAST_EXEC_LLERROR_CRASH; - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL; - } - } - else - { - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL; - } - LLAPRFile::remove(llerror_marker_file); - } - // and last refine based on whether or not a marker created during a non-llerr crash is found - std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); - if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) - { - if (markerIsSameVersion(error_marker_file)) - { - if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) - { - gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; - } - else - { - gLastExecEvent = LAST_EXEC_OTHER_CRASH; - LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; - } - } - else - { - LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL; - } - LLAPRFile::remove(error_marker_file); - } + //We've got 4 things to test for here + // - Other Process Running (SecondLife.exec_marker present, locked) + // - Freeze (SecondLife.exec_marker present, not locked) + // - LLError Crash (SecondLife.llerror_marker present) + // - Other Crash (SecondLife.error_marker present) + // These checks should also remove these files for the last 2 cases if they currently exist + + std::ostringstream marker_log_stream; + bool marker_is_same_version = true; + // first, look for the marker created at startup and deleted on a clean exit + mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME); + if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB)) + { + // File exists... + // first, read it to see if it was created by the same version (we need this later) + marker_is_same_version = markerIsSameVersion(mMarkerFileName); + + // now test to see if this file is locked by a running process (try to open for write) + marker_log_stream << "Checking exec marker file for lock..."; + mMarkerFile.open(mMarkerFileName, LL_APR_WB); + apr_file_t* fMarker = mMarkerFile.getFileHandle() ; + if (!fMarker) + { + marker_log_stream << "Exec marker file open failed - assume it is locked."; + mSecondInstance = true; // lock means that instance is running. + } + else + { + // We were able to open it, now try to lock it ourselves... + if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS) + { + marker_log_stream << "Locking exec marker failed."; + mSecondInstance = true; // lost a race? be conservative + } + else + { + // No other instances; we've locked this file now, so record our version; delete on quit. + recordMarkerVersion(mMarkerFile); + marker_log_stream << "Exec marker file existed but was not locked; rewritten."; + } + } + initLoggingAndGetLastDuration(); + + std::string marker_log_msg(marker_log_stream.str()); + LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL; + + if (mSecondInstance) + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' owned by another instance" << LL_ENDL; + } + else if (marker_is_same_version) + { + // the file existed, is ours, and matched our version, so we can report on what it says + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL; + gLastExecEvent = LAST_EXEC_OTHER_CRASH; + } + else + { + LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found, but versions did not match" << LL_ENDL; + } + } + else // marker did not exist... last exec (if any) did not freeze + { + initLoggingAndGetLastDuration(); + // Create the marker file for this execution & lock it; it will be deleted on a clean exit + apr_status_t s; + s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE); + + if (s == APR_SUCCESS && mMarkerFile.getFileHandle()) + { + LL_DEBUGS("MarkerFile") << "Exec marker file '"<< mMarkerFileName << "' created." << LL_ENDL; + if (APR_SUCCESS == apr_file_lock(mMarkerFile.getFileHandle(), APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE)) + { + recordMarkerVersion(mMarkerFile); + LL_DEBUGS("MarkerFile") << "Exec marker file locked." << LL_ENDL; + } + else + { + LL_WARNS("MarkerFile") << "Exec marker file cannot be locked." << LL_ENDL; + } + } + else + { + LL_WARNS("MarkerFile") << "Failed to create exec marker file '"<< mMarkerFileName << "'." << LL_ENDL; + } + } + + // now check for cases in which the exec marker may have been cleaned up by crash handlers + + // check for any last exec event report based on whether or not it happened during logout + // (the logout marker is created when logout begins) + std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); + if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB)) + { + if (markerIsSameVersion(logout_marker_file)) + { + gLastExecEvent = LAST_EXEC_LOGOUT_FROZE; + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "', changing LastExecEvent to LOGOUT_FROZE" << LL_ENDL; + } + else + { + LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(logout_marker_file); + } + // further refine based on whether or not a marker created during an llerr crash is found + std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); + if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) + { + if (markerIsSameVersion(llerror_marker_file)) + { + if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE ) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_LLERROR_CRASH; + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(llerror_marker_file); + } + // and last refine based on whether or not a marker created during a non-llerr crash is found + std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) + { + if (markerIsSameVersion(error_marker_file)) + { + if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) + { + gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; + } + else + { + gLastExecEvent = LAST_EXEC_OTHER_CRASH; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL; + } + LLAPRFile::remove(error_marker_file); + } } void LLAppViewer::removeMarkerFiles() { - if (!mSecondInstance) - { - if (mMarkerFile.getFileHandle()) - { - mMarkerFile.close() ; - LLAPRFile::remove( mMarkerFileName ); - LL_DEBUGS("MarkerFile") << "removed exec marker '"<updateAvatarRezMetrics(true); // force a last packet to be sent. - } - - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal(gAgent.getPositionGlobal()); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - LLHUDManager::getInstance()->sendEffects(); - effectp->markDead() ;//remove it. - - // Attempt to close all floaters that might be - // editing things. - if (gFloaterView) - { - // application is quitting - gFloaterView->closeAllChildren(true); - } - - // Send preferences once, when exiting - bool include_preferences = true; - send_viewer_stats(include_preferences); - - gLogoutTimer.reset(); - mQuitRequested = true; + LL_INFOS() << "requestQuit" << LL_ENDL; + + LLViewerRegion* region = gAgent.getRegion(); + + if( (LLStartUp::getStartupState() < STATE_STARTED) || !region ) + { + // If we have a region, make some attempt to send a logout request first. + // This prevents the halfway-logged-in avatar from hanging around inworld for a couple minutes. + if(region) + { + sendLogoutRequest(); + } + + // Quit immediately + forceQuit(); + return; + } + + // Try to send metrics back to the grid + metricsSend(!gDisconnected); + + // Try to send last batch of avatar rez metrics. + if (!gDisconnected && isAgentAvatarValid()) + { + gAgentAvatarp->updateAvatarRezMetrics(true); // force a last packet to be sent. + } + + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(gAgent.getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + LLHUDManager::getInstance()->sendEffects(); + effectp->markDead() ;//remove it. + + // Attempt to close all floaters that might be + // editing things. + if (gFloaterView) + { + // application is quitting + gFloaterView->closeAllChildren(true); + } + + // Send preferences once, when exiting + bool include_preferences = true; + send_viewer_stats(include_preferences); + + gLogoutTimer.reset(); + mQuitRequested = true; } static bool finish_quit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - LLAppViewer::instance()->requestQuit(); - } - return false; + if (option == 0) + { + LLAppViewer::instance()->requestQuit(); + } + return false; } static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit); void LLAppViewer::userQuit() { - LL_INFOS() << "User requested quit" << LL_ENDL; - if (gDisconnected - || !gViewerWindow - || !gViewerWindow->getProgressView() - || gViewerWindow->getProgressView()->getVisible()) - { - requestQuit(); - } - else - { - LLNotificationsUtil::add("ConfirmQuit"); - } + LL_INFOS() << "User requested quit" << LL_ENDL; + if (gDisconnected + || !gViewerWindow + || !gViewerWindow->getProgressView() + || gViewerWindow->getProgressView()->getVisible()) + { + requestQuit(); + } + else + { + LLNotificationsUtil::add("ConfirmQuit"); + } } static bool finish_early_exit(const LLSD& notification, const LLSD& response) { - LLAppViewer::instance()->forceQuit(); - return false; + LLAppViewer::instance()->forceQuit(); + return false; } void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions) { - LL_WARNS() << "app_early_exit: " << name << LL_ENDL; - gDoDisconnect = TRUE; - LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit); + LL_WARNS() << "app_early_exit: " << name << LL_ENDL; + gDoDisconnect = TRUE; + LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit); } // case where we need the viewer to exit without any need for notifications void LLAppViewer::earlyExitNoNotify() { - LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL; - gDoDisconnect = TRUE; - finish_early_exit( LLSD(), LLSD() ); + LL_WARNS() << "app_early_exit with no notification: " << LL_ENDL; + gDoDisconnect = TRUE; + finish_early_exit( LLSD(), LLSD() ); } void LLAppViewer::abortQuit() { LL_INFOS() << "abortQuit()" << LL_ENDL; - mQuitRequested = false; + mQuitRequested = false; } void LLAppViewer::migrateCacheDirectory() { #if LL_WINDOWS || LL_DARWIN - // NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from - // /library/application support/SecondLife/cache This should clear/delete the old dir. - - // As of 1.23 the Windows cache moved from - // C:\Documents and Settings\James\Application Support\SecondLife\cache - // to - // C:\Documents and Settings\James\Local Settings\Application Support\SecondLife - // - // The Windows Vista equivalent is from - // C:\Users\James\AppData\Roaming\SecondLife\cache - // to - // C:\Users\James\AppData\Local\SecondLife - // - // Note the absence of \cache on the second path. James. - - // Only do this once per fresh install of this version. - if (gSavedSettings.getBOOL("MigrateCacheDirectory")) - { - gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE); - - std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache"); - std::string new_cache_dir = gDirUtilp->getCacheDir(true); - - if (gDirUtilp->fileExists(old_cache_dir)) - { - LL_INFOS() << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << LL_ENDL; - - // Migrate inventory cache to avoid pain to inventory database after mass update - S32 file_count = 0; - std::string file_name; - std::string mask = "*.*"; - - LLDirIterator iter(old_cache_dir, mask); - while (iter.next(file_name)) - { - if (file_name == "." || file_name == "..") continue; - std::string source_path = gDirUtilp->add(old_cache_dir, file_name); - std::string dest_path = gDirUtilp->add(new_cache_dir, file_name); - if (!LLFile::rename(source_path, dest_path)) - { - file_count++; - } - } - LL_INFOS() << "Moved " << file_count << " files" << LL_ENDL; - - // Nuke the old cache - gDirUtilp->setCacheDir(old_cache_dir); - purgeCache(); - gDirUtilp->setCacheDir(new_cache_dir); + // NOTE: (Nyx) as of 1.21, cache for mac is moving to /library/caches/SecondLife from + // /library/application support/SecondLife/cache This should clear/delete the old dir. + + // As of 1.23 the Windows cache moved from + // C:\Documents and Settings\James\Application Support\SecondLife\cache + // to + // C:\Documents and Settings\James\Local Settings\Application Support\SecondLife + // + // The Windows Vista equivalent is from + // C:\Users\James\AppData\Roaming\SecondLife\cache + // to + // C:\Users\James\AppData\Local\SecondLife + // + // Note the absence of \cache on the second path. James. + + // Only do this once per fresh install of this version. + if (gSavedSettings.getBOOL("MigrateCacheDirectory")) + { + gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE); + + std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache"); + std::string new_cache_dir = gDirUtilp->getCacheDir(true); + + if (gDirUtilp->fileExists(old_cache_dir)) + { + LL_INFOS() << "Migrating cache from " << old_cache_dir << " to " << new_cache_dir << LL_ENDL; + + // Migrate inventory cache to avoid pain to inventory database after mass update + S32 file_count = 0; + std::string file_name; + std::string mask = "*.*"; + + LLDirIterator iter(old_cache_dir, mask); + while (iter.next(file_name)) + { + if (file_name == "." || file_name == "..") continue; + std::string source_path = gDirUtilp->add(old_cache_dir, file_name); + std::string dest_path = gDirUtilp->add(new_cache_dir, file_name); + if (!LLFile::rename(source_path, dest_path)) + { + file_count++; + } + } + LL_INFOS() << "Moved " << file_count << " files" << LL_ENDL; + + // Nuke the old cache + gDirUtilp->setCacheDir(old_cache_dir); + purgeCache(); + gDirUtilp->setCacheDir(new_cache_dir); #if LL_DARWIN - // Clean up Mac files not deleted by removing *.* - std::string ds_store = old_cache_dir + "/.DS_Store"; - if (gDirUtilp->fileExists(ds_store)) - { - LLFile::remove(ds_store); - } + // Clean up Mac files not deleted by removing *.* + std::string ds_store = old_cache_dir + "/.DS_Store"; + if (gDirUtilp->fileExists(ds_store)) + { + LLFile::remove(ds_store); + } #endif - if (LLFile::rmdir(old_cache_dir) != 0) - { - LL_WARNS() << "could not delete old cache directory " << old_cache_dir << LL_ENDL; - } - } - } + if (LLFile::rmdir(old_cache_dir) != 0) + { + LL_WARNS() << "could not delete old cache directory " << old_cache_dir << LL_ENDL; + } + } + } #endif // LL_WINDOWS || LL_DARWIN } //static U32 LLAppViewer::getTextureCacheVersion() { - // Viewer texture cache version, change if the texture cache format changes. - // 2021-03-10 Bumping up by one to help obviate texture cache issues with - // Simple Cache Viewer - see SL-14985 for more information - //const U32 TEXTURE_CACHE_VERSION = 8; - const U32 TEXTURE_CACHE_VERSION = 9; + // Viewer texture cache version, change if the texture cache format changes. + // 2021-03-10 Bumping up by one to help obviate texture cache issues with + // Simple Cache Viewer - see SL-14985 for more information + //const U32 TEXTURE_CACHE_VERSION = 8; + const U32 TEXTURE_CACHE_VERSION = 9; - return TEXTURE_CACHE_VERSION ; + return TEXTURE_CACHE_VERSION ; } //static @@ -4190,92 +4190,92 @@ U32 LLAppViewer::getDiskCacheVersion() //static U32 LLAppViewer::getObjectCacheVersion() { - // Viewer object cache version, change if object update - // format changes. JC - const U32 INDRA_OBJECT_CACHE_VERSION = 17; + // Viewer object cache version, change if object update + // format changes. JC + const U32 INDRA_OBJECT_CACHE_VERSION = 17; - return INDRA_OBJECT_CACHE_VERSION; + return INDRA_OBJECT_CACHE_VERSION; } bool LLAppViewer::initCache() { - mPurgeCache = false; - BOOL read_only = mSecondInstance ? TRUE : FALSE; - LLAppViewer::getTextureCache()->setReadOnly(read_only) ; - LLVOCache::initParamSingleton(read_only); + mPurgeCache = false; + BOOL read_only = mSecondInstance ? TRUE : FALSE; + LLAppViewer::getTextureCache()->setReadOnly(read_only) ; + LLVOCache::initParamSingleton(read_only); - // initialize the new disk cache using saved settings - const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName"); + // initialize the new disk cache using saved settings + const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName"); - const U32 MB = 1024 * 1024; + const U32 MB = 1024 * 1024; const uintmax_t MIN_CACHE_SIZE = 256 * MB; - const uintmax_t MAX_CACHE_SIZE = 9984ll * MB; + const uintmax_t MAX_CACHE_SIZE = 9984ll * MB; const uintmax_t setting_cache_total_size = uintmax_t(gSavedSettings.getU32("CacheSize")) * MB; const uintmax_t cache_total_size = llclamp(setting_cache_total_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); const F64 disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal"); const F64 texture_cache_percent = 100.0 - disk_cache_percent; - // note that the maximum size of this cache is defined as a percentage of the - // total cache size - the 'CacheSize' pref - for all caches. + // note that the maximum size of this cache is defined as a percentage of the + // total cache size - the 'CacheSize' pref - for all caches. const uintmax_t disk_cache_size = uintmax_t(cache_total_size * disk_cache_percent / 100); - const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo"); + const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo"); - bool texture_cache_mismatch = false; + bool texture_cache_mismatch = false; bool remove_vfs_files = false; - if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) - { - texture_cache_mismatch = true; - if(!read_only) - { - gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); + if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) + { + texture_cache_mismatch = true; + if(!read_only) + { + gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); //texture cache version was bumped up in Simple Cache Viewer, and at this point old vfs files are not needed - remove_vfs_files = true; - } - } - - if(!read_only) - { - // Purge cache if user requested it - if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || - gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) - { - LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL; - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; - // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad - texture_cache_mismatch = true; - } - - // We have moved the location of the cache directory over time. - migrateCacheDirectory(); - - // Setup and verify the cache location - std::string cache_location = gSavedSettings.getString("CacheLocation"); - std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); - if (new_cache_location != cache_location) - { - LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL; - gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); - purgeCache(); // purge old cache - gDirUtilp->deleteDirAndContents(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name)); - gSavedSettings.setString("CacheLocation", new_cache_location); - gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location)); - } - } - - if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"))) - { - LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL; - gSavedSettings.setString("CacheLocation", ""); - gSavedSettings.setString("CacheLocationTopFolder", ""); - } - - const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); - LLDiskCache::initParamSingleton(cache_dir, disk_cache_size, enable_cache_debug_info); - - if (!read_only) - { + remove_vfs_files = true; + } + } + + if(!read_only) + { + // Purge cache if user requested it + if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || + gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + { + LL_INFOS("AppCache") << "Startup cache purge requested: " << (gSavedSettings.getBOOL("PurgeCacheOnStartup") ? "ALWAYS" : "ONCE") << LL_ENDL; + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); + mPurgeCache = true; + // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad + texture_cache_mismatch = true; + } + + // We have moved the location of the cache directory over time. + migrateCacheDirectory(); + + // Setup and verify the cache location + std::string cache_location = gSavedSettings.getString("CacheLocation"); + std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); + if (new_cache_location != cache_location) + { + LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL; + gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); + purgeCache(); // purge old cache + gDirUtilp->deleteDirAndContents(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name)); + gSavedSettings.setString("CacheLocation", new_cache_location); + gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location)); + } + } + + if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"))) + { + LL_WARNS("AppCache") << "Unable to set cache location" << LL_ENDL; + gSavedSettings.setString("CacheLocation", ""); + gSavedSettings.setString("CacheLocationTopFolder", ""); + } + + const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name); + LLDiskCache::initParamSingleton(cache_dir, disk_cache_size, enable_cache_debug_info); + + if (!read_only) + { if (gSavedSettings.getS32("DiskCacheVersion") != LLAppViewer::getDiskCacheVersion()) { LLDiskCache::getInstance()->clearCache(); @@ -4287,166 +4287,166 @@ bool LLAppViewer::initCache() { LLDiskCache::getInstance()->removeOldVFSFiles(); } - + if (mPurgeCache) - { - LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); - purgeCache(); - - // clear the new C++ file system based cache - LLDiskCache::getInstance()->clearCache(); - } - else - { - // purge excessive files from the new file system based cache - LLDiskCache::getInstance()->purge(); - } - } - LLAppViewer::getPurgeDiskCacheThread()->start(); - - LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); - - // Init the texture cache + { + LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); + purgeCache(); + + // clear the new C++ file system based cache + LLDiskCache::getInstance()->clearCache(); + } + else + { + // purge excessive files from the new file system based cache + LLDiskCache::getInstance()->purge(); + } + } + LLAppViewer::getPurgeDiskCacheThread()->start(); + + LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); + + // Init the texture cache // Allocate the remaining percent which is not allocated to the disk cache const S64 texture_cache_size = S64(cache_total_size * texture_cache_percent / 100); LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); - LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); + LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); return true; } void LLAppViewer::addOnIdleCallback(const boost::function& cb) { - gMainloopWork.post(cb); + gMainloopWork.post(cb); } void LLAppViewer::loadKeyBindings() { - std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); - if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file)) - { - // Failed to load custom bindings, try default ones - key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); - if (!gViewerInput.loadBindingsXML(key_bindings_file)) - { + std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml"); + if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file)) + { + // Failed to load custom bindings, try default ones + key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml"); + if (!gViewerInput.loadBindingsXML(key_bindings_file)) + { LLError::LLUserWarningMsg::showMissingFiles(); - LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL; - } - } + LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL; + } + } LLUrlRegistry::instance().setKeybindingHandler(&gViewerInput); } void LLAppViewer::purgeCache() { - LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; - LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); - LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); - LLViewerShaderMgr::instance()->clearShaderCache(); - std::string browser_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache"); - if (LLFile::isdir(browser_cache)) - { - // cef does not support clear_cache and clear_cookies, so clear what we can manually. - gDirUtilp->deleteDirAndContents(browser_cache); - } - gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*"); + LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL; + LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE); + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE); + LLViewerShaderMgr::instance()->clearShaderCache(); + std::string browser_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "cef_cache"); + if (LLFile::isdir(browser_cache)) + { + // cef does not support clear_cache and clear_cookies, so clear what we can manually. + gDirUtilp->deleteDirAndContents(browser_cache); + } + gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*"); } //purge cache immediately, do not wait until the next login. void LLAppViewer::purgeCacheImmediate() { - LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; - LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false); - LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); + LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; + LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false); + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); } std::string LLAppViewer::getSecondLifeTitle() const { - return LLTrans::getString("APP_NAME"); + return LLTrans::getString("APP_NAME"); } std::string LLAppViewer::getWindowTitle() const { - return gWindowTitle; + return gWindowTitle; } // Callback from a dialog indicating user was logged out. bool finish_disconnect(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (1 == option) - { + if (1 == option) + { LLAppViewer::instance()->forceQuit(); - } - return false; + } + return false; } // Callback from an early disconnect dialog, force an exit bool finish_forced_disconnect(const LLSD& notification, const LLSD& response) { - LLAppViewer::instance()->forceQuit(); - return false; + LLAppViewer::instance()->forceQuit(); + return false; } void LLAppViewer::forceDisconnect(const std::string& mesg) { - if (gDoDisconnect) - { - // Already popped up one of these dialogs, don't - // do this again. - return; - } - - // *TODO: Translate the message if possible - std::string big_reason = LLAgent::sTeleportErrorMessages[mesg]; - if ( big_reason.size() == 0 ) - { - big_reason = mesg; - } - - LLSD args; - gDoDisconnect = TRUE; - - if (LLStartUp::getStartupState() < STATE_STARTED) - { - // Tell users what happened - args["ERROR_MESSAGE"] = big_reason; - LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); - } - else - { - args["MESSAGE"] = big_reason; - LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); - } + if (gDoDisconnect) + { + // Already popped up one of these dialogs, don't + // do this again. + return; + } + + // *TODO: Translate the message if possible + std::string big_reason = LLAgent::sTeleportErrorMessages[mesg]; + if ( big_reason.size() == 0 ) + { + big_reason = mesg; + } + + LLSD args; + gDoDisconnect = TRUE; + + if (LLStartUp::getStartupState() < STATE_STARTED) + { + // Tell users what happened + args["ERROR_MESSAGE"] = big_reason; + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); + } + else + { + args["MESSAGE"] = big_reason; + LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); + } } void LLAppViewer::badNetworkHandler() { - // Dump the packet - gMessageSystem->dumpPacketToLog(); - - // Flush all of our caches on exit in the case of disconnect due to - // invalid packets. - - mPurgeCacheOnExit = TRUE; - - std::ostringstream message; - message << - "The viewer has detected mangled network data indicative\n" - "of a bad upstream network connection or an incomplete\n" - "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n" - " \n" - "Try uninstalling and reinstalling to see if this resolves \n" - "the issue. \n" - " \n" - "If the problem continues, see the Tech Support FAQ at: \n" - "www.secondlife.com/support"; - forceDisconnect(message.str()); - - LLApp::instance()->writeMiniDump(); + // Dump the packet + gMessageSystem->dumpPacketToLog(); + + // Flush all of our caches on exit in the case of disconnect due to + // invalid packets. + + mPurgeCacheOnExit = TRUE; + + std::ostringstream message; + message << + "The viewer has detected mangled network data indicative\n" + "of a bad upstream network connection or an incomplete\n" + "local installation of " << LLAppViewer::instance()->getSecondLifeTitle() << ". \n" + " \n" + "Try uninstalling and reinstalling to see if this resolves \n" + "the issue. \n" + " \n" + "If the problem continues, see the Tech Support FAQ at: \n" + "www.secondlife.com/support"; + forceDisconnect(message.str()); + + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. @@ -4454,93 +4454,93 @@ void LLAppViewer::badNetworkHandler() // is destroyed. void LLAppViewer::saveFinalSnapshot() { - if (!mSavedFinalSnapshot) - { - gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal()); - gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal()); - gViewerWindow->setCursor(UI_CURSOR_WAIT); - gAgentCamera.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch - gSavedSettings.setBOOL("ShowParcelOwners", FALSE); - idle(); - - std::string snap_filename = gDirUtilp->getLindenUserDir(); - snap_filename += gDirUtilp->getDirDelimiter(); - snap_filename += LLStartUp::getScreenLastFilename(); - // use full pixel dimensions of viewer window (not post-scale dimensions) - gViewerWindow->saveSnapshot(snap_filename, - gViewerWindow->getWindowWidthRaw(), - gViewerWindow->getWindowHeightRaw(), - FALSE, - gSavedSettings.getBOOL("RenderHUDInSnapshot"), - TRUE, - LLSnapshotModel::SNAPSHOT_TYPE_COLOR, - LLSnapshotModel::SNAPSHOT_FORMAT_PNG); - mSavedFinalSnapshot = TRUE; - - if (gAgent.isInHomeRegion()) - { - LLVector3d home; - if (gAgent.getHomePosGlobal(&home) && dist_vec(home, gAgent.getPositionGlobal()) < 10) - { - // We are at home position or close to it, see if we need to create home screenshot - // Notes: - // 1. It might be beneficial to also replace home if file is too old - // 2. This is far from best way/place to update screenshot since location might be not fully loaded, - // but we don't have many options - std::string snap_home = gDirUtilp->getLindenUserDir(); - snap_home += gDirUtilp->getDirDelimiter(); - snap_home += LLStartUp::getScreenHomeFilename(); - if (!gDirUtilp->fileExists(snap_home)) - { - // We are at home position yet no home image exist, fix it - LLFile::copy(snap_filename, snap_home); - } - } - } - } + if (!mSavedFinalSnapshot) + { + gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal()); + gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal()); + gViewerWindow->setCursor(UI_CURSOR_WAIT); + gAgentCamera.changeCameraToThirdPerson( FALSE ); // don't animate, need immediate switch + gSavedSettings.setBOOL("ShowParcelOwners", FALSE); + idle(); + + std::string snap_filename = gDirUtilp->getLindenUserDir(); + snap_filename += gDirUtilp->getDirDelimiter(); + snap_filename += LLStartUp::getScreenLastFilename(); + // use full pixel dimensions of viewer window (not post-scale dimensions) + gViewerWindow->saveSnapshot(snap_filename, + gViewerWindow->getWindowWidthRaw(), + gViewerWindow->getWindowHeightRaw(), + FALSE, + gSavedSettings.getBOOL("RenderHUDInSnapshot"), + TRUE, + LLSnapshotModel::SNAPSHOT_TYPE_COLOR, + LLSnapshotModel::SNAPSHOT_FORMAT_PNG); + mSavedFinalSnapshot = TRUE; + + if (gAgent.isInHomeRegion()) + { + LLVector3d home; + if (gAgent.getHomePosGlobal(&home) && dist_vec(home, gAgent.getPositionGlobal()) < 10) + { + // We are at home position or close to it, see if we need to create home screenshot + // Notes: + // 1. It might be beneficial to also replace home if file is too old + // 2. This is far from best way/place to update screenshot since location might be not fully loaded, + // but we don't have many options + std::string snap_home = gDirUtilp->getLindenUserDir(); + snap_home += gDirUtilp->getDirDelimiter(); + snap_home += LLStartUp::getScreenHomeFilename(); + if (!gDirUtilp->fileExists(snap_home)) + { + // We are at home position yet no home image exist, fix it + LLFile::copy(snap_filename, snap_home); + } + } + } + } } void LLAppViewer::loadNameCache() { - // display names cache - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); - LL_INFOS("AvNameCache") << filename << LL_ENDL; - llifstream name_cache_stream(filename.c_str()); - if(name_cache_stream.is_open()) - { - if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream)) + // display names cache + std::string filename = + gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); + LL_INFOS("AvNameCache") << filename << LL_ENDL; + llifstream name_cache_stream(filename.c_str()); + if(name_cache_stream.is_open()) + { + if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream)) { LL_WARNS("AppInit") << "removing invalid '" << filename << "'" << LL_ENDL; name_cache_stream.close(); LLFile::remove(filename); } - } + } - if (!gCacheName) return; + if (!gCacheName) return; - std::string name_cache; - name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); - llifstream cache_file(name_cache.c_str()); - if(cache_file.is_open()) - { - if(gCacheName->importFile(cache_file)) return; - } + std::string name_cache; + name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); + llifstream cache_file(name_cache.c_str()); + if(cache_file.is_open()) + { + if(gCacheName->importFile(cache_file)) return; + } } void LLAppViewer::saveNameCache() { - // display names cache - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); - llofstream name_cache_stream(filename.c_str()); - if(name_cache_stream.is_open()) - { - LLAvatarNameCache::getInstance()->exportFile(name_cache_stream); + // display names cache + std::string filename = + gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); + llofstream name_cache_stream(filename.c_str()); + if(name_cache_stream.is_open()) + { + LLAvatarNameCache::getInstance()->exportFile(name_cache_stream); } // real names cache - if (gCacheName) + if (gCacheName) { std::string name_cache; name_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "name.cache"); @@ -4549,24 +4549,24 @@ void LLAppViewer::saveNameCache() { gCacheName->exportFile(cache_file); } - } + } } -/*! @brief This class is an LLFrameTimer that can be created with - an elapsed time that starts counting up from the given value - rather than 0.0. +/*! @brief This class is an LLFrameTimer that can be created with + an elapsed time that starts counting up from the given value + rather than 0.0. - Otherwise it behaves the same way as LLFrameTimer. + Otherwise it behaves the same way as LLFrameTimer. */ class LLFrameStatsTimer : public LLFrameTimer { public: - LLFrameStatsTimer(F64 elapsed_already = 0.0) - : LLFrameTimer() - { - mStartTime -= elapsed_already; - } + LLFrameStatsTimer(F64 elapsed_already = 0.0) + : LLFrameTimer() + { + mStartTime -= elapsed_already; + } }; static LLTrace::BlockTimerStatHandle FTM_AUDIO_UPDATE("Update Audio"); @@ -4592,118 +4592,118 @@ static LLTrace::BlockTimerStatHandle FTM_HUD_EFFECTS("HUD Effects"); void LLAppViewer::idle() { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; - pingMainloopTimeout("Main:Idle"); + pingMainloopTimeout("Main:Idle"); - // Update frame timers - static LLTimer idle_timer; + // Update frame timers + static LLTimer idle_timer; - LLFrameTimer::updateFrameTime(); - LLFrameTimer::updateFrameCount(); - LLEventTimer::updateClass(); + LLFrameTimer::updateFrameTime(); + LLFrameTimer::updateFrameCount(); + LLEventTimer::updateClass(); LLPerfStats::updateClass(); - // LLApp::stepFrame() performs the above three calls plus mRunner.run(). - // Not sure why we don't call stepFrame() here, except that LLRunner seems - // completely redundant with LLEventTimer. - LLNotificationsUI::LLToast::updateClass(); - LLSmoothInterpolation::updateInterpolants(); - LLMortician::updateClass(); - LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() - LLDirPickerThread::clearDead(); - F32 dt_raw = idle_timer.getElapsedTimeAndResetF32(); + // LLApp::stepFrame() performs the above three calls plus mRunner.run(). + // Not sure why we don't call stepFrame() here, except that LLRunner seems + // completely redundant with LLEventTimer. + LLNotificationsUI::LLToast::updateClass(); + LLSmoothInterpolation::updateInterpolants(); + LLMortician::updateClass(); + LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() + LLDirPickerThread::clearDead(); + F32 dt_raw = idle_timer.getElapsedTimeAndResetF32(); LLGLTFMaterialList::flushUpdates(); - // Service the WorkQueue we use for replies from worker threads. - // Use function statics for the timeslice setting so we only have to fetch - // and convert MainWorkTime once. - static F32 MainWorkTimeRaw = gSavedSettings.getF32("MainWorkTime"); - static F32Milliseconds MainWorkTimeMs(MainWorkTimeRaw); - // MainWorkTime is specified in fractional milliseconds, but std::chrono - // uses integer representations. What if we want less than a microsecond? - // Use nanoseconds. We're very sure we will never need to specify a - // MainWorkTime that would be larger than we could express in - // std::chrono::nanoseconds. - static std::chrono::nanoseconds MainWorkTimeNanoSec{ - std::chrono::nanoseconds::rep(MainWorkTimeMs.value() * 1000000)}; - gMainloopWork.runFor(MainWorkTimeNanoSec); - - // Cap out-of-control frame times - // Too low because in menus, swapping, debugger, etc. - // Too high because idle called with no objects in view, etc. - const F32 MIN_FRAME_RATE = 1.f; - const F32 MAX_FRAME_RATE = 200.f; - - F32 frame_rate_clamped = 1.f / dt_raw; - frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE); - gFrameDTClamped = 1.f / frame_rate_clamped; - - // Global frame timer - // Smoothly weight toward current frame - gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f; - - F32 qas = gSavedSettings.getF32("QuitAfterSeconds"); - if (qas > 0.f) - { - if (gRenderStartTime.getElapsedTimeF32() > qas) - { - LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - } - } - - // Must wait until both have avatar object and mute list, so poll - // here. - LLIMProcessing::requestOfflineMessages(); - - /////////////////////////////////// - // - // Special case idle if still starting up - // - if (LLStartUp::getStartupState() < STATE_STARTED) - { - // Skip rest if idle startup returns false (essentially, no world yet) - gGLActive = TRUE; - if (!idle_startup()) - { - gGLActive = FALSE; - return; - } - gGLActive = FALSE; - } - - - F32 yaw = 0.f; // radians - - if (!gDisconnected) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("network"); //LL_RECORD_BLOCK_TIME(FTM_NETWORK); - // Update spaceserver timeinfo - LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + LLUnits::Seconds::fromValue(dt_raw)); - - - ////////////////////////////////////// - // - // Update simulator agent state - // - - if (gSavedSettings.getBOOL("RotateRight")) - { - gAgent.moveYaw(-1.f); - } - - { + // Service the WorkQueue we use for replies from worker threads. + // Use function statics for the timeslice setting so we only have to fetch + // and convert MainWorkTime once. + static F32 MainWorkTimeRaw = gSavedSettings.getF32("MainWorkTime"); + static F32Milliseconds MainWorkTimeMs(MainWorkTimeRaw); + // MainWorkTime is specified in fractional milliseconds, but std::chrono + // uses integer representations. What if we want less than a microsecond? + // Use nanoseconds. We're very sure we will never need to specify a + // MainWorkTime that would be larger than we could express in + // std::chrono::nanoseconds. + static std::chrono::nanoseconds MainWorkTimeNanoSec{ + std::chrono::nanoseconds::rep(MainWorkTimeMs.value() * 1000000)}; + gMainloopWork.runFor(MainWorkTimeNanoSec); + + // Cap out-of-control frame times + // Too low because in menus, swapping, debugger, etc. + // Too high because idle called with no objects in view, etc. + const F32 MIN_FRAME_RATE = 1.f; + const F32 MAX_FRAME_RATE = 200.f; + + F32 frame_rate_clamped = 1.f / dt_raw; + frame_rate_clamped = llclamp(frame_rate_clamped, MIN_FRAME_RATE, MAX_FRAME_RATE); + gFrameDTClamped = 1.f / frame_rate_clamped; + + // Global frame timer + // Smoothly weight toward current frame + gFPSClamped = (frame_rate_clamped + (4.f * gFPSClamped)) / 5.f; + + F32 qas = gSavedSettings.getF32("QuitAfterSeconds"); + if (qas > 0.f) + { + if (gRenderStartTime.getElapsedTimeF32() > qas) + { + LL_INFOS() << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << LL_ENDL; + LLAppViewer::instance()->forceQuit(); + } + } + + // Must wait until both have avatar object and mute list, so poll + // here. + LLIMProcessing::requestOfflineMessages(); + + /////////////////////////////////// + // + // Special case idle if still starting up + // + if (LLStartUp::getStartupState() < STATE_STARTED) + { + // Skip rest if idle startup returns false (essentially, no world yet) + gGLActive = TRUE; + if (!idle_startup()) + { + gGLActive = FALSE; + return; + } + gGLActive = FALSE; + } + + + F32 yaw = 0.f; // radians + + if (!gDisconnected) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("network"); //LL_RECORD_BLOCK_TIME(FTM_NETWORK); + // Update spaceserver timeinfo + LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + LLUnits::Seconds::fromValue(dt_raw)); + + + ////////////////////////////////////// + // + // Update simulator agent state + // + + if (gSavedSettings.getBOOL("RotateRight")) + { + gAgent.moveYaw(-1.f); + } + + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP("Autopilot"); - // Handle automatic walking towards points - gAgentPilot.updateTarget(); - gAgent.autoPilot(&yaw); - } + // Handle automatic walking towards points + gAgentPilot.updateTarget(); + gAgent.autoPilot(&yaw); + } - static LLFrameTimer agent_update_timer; + static LLFrameTimer agent_update_timer; - // When appropriate, update agent location to the simulator. - F32 agent_update_time = agent_update_timer.getElapsedTimeF32(); - F32 agent_force_update_time = mLastAgentForceUpdate + agent_update_time; + // When appropriate, update agent location to the simulator. + F32 agent_update_time = agent_update_timer.getElapsedTimeF32(); + F32 agent_force_update_time = mLastAgentForceUpdate + agent_update_time; bool timed_out = agent_update_time > (1.0f / (F32)AGENT_UPDATES_PER_SECOND); BOOL force_send = // if there is something to send @@ -4714,111 +4714,111 @@ void LLAppViewer::idle() || (agent_force_update_time > (1.0f / (F32) AGENT_FORCE_UPDATES_PER_SECOND)); // timing out doesn't warranty that an update will be sent, // just that it will be checked. - if (force_send || timed_out) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - // Send avatar and camera info - mLastAgentControlFlags = gAgent.getControlFlags(); - mLastAgentForceUpdate = force_send ? 0 : agent_force_update_time; - send_agent_update(force_send); - agent_update_timer.reset(); - } - } - - ////////////////////////////////////// - // - // Manage statistics - // - // - { - // Initialize the viewer_stats_timer with an already elapsed time - // of SEND_STATS_PERIOD so that the initial stats report will - // be sent immediately. - static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD); - - // Update session stats every large chunk of time - // *FIX: (?) SAMANTHA - if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected) - { - LL_INFOS() << "Transmitting sessions stats" << LL_ENDL; - bool include_preferences = false; - send_viewer_stats(include_preferences); - viewer_stats_timer.reset(); - } - - // Print the object debugging stats - static LLFrameTimer object_debug_timer; - if (object_debug_timer.getElapsedTimeF32() > 5.f) - { - object_debug_timer.reset(); - if (gObjectList.mNumDeadObjectUpdates) - { - LL_INFOS() << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << LL_ENDL; - gObjectList.mNumDeadObjectUpdates = 0; - } - if (gObjectList.mNumUnknownUpdates) - { - LL_INFOS() << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << LL_ENDL; - gObjectList.mNumUnknownUpdates = 0; - } - - } - } - - if (!gDisconnected) - { + if (force_send || timed_out) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; + // Send avatar and camera info + mLastAgentControlFlags = gAgent.getControlFlags(); + mLastAgentForceUpdate = force_send ? 0 : agent_force_update_time; + send_agent_update(force_send); + agent_update_timer.reset(); + } + } + + ////////////////////////////////////// + // + // Manage statistics + // + // + { + // Initialize the viewer_stats_timer with an already elapsed time + // of SEND_STATS_PERIOD so that the initial stats report will + // be sent immediately. + static LLFrameStatsTimer viewer_stats_timer(SEND_STATS_PERIOD); + + // Update session stats every large chunk of time + // *FIX: (?) SAMANTHA + if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected) + { + LL_INFOS() << "Transmitting sessions stats" << LL_ENDL; + bool include_preferences = false; + send_viewer_stats(include_preferences); + viewer_stats_timer.reset(); + } + + // Print the object debugging stats + static LLFrameTimer object_debug_timer; + if (object_debug_timer.getElapsedTimeF32() > 5.f) + { + object_debug_timer.reset(); + if (gObjectList.mNumDeadObjectUpdates) + { + LL_INFOS() << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << LL_ENDL; + gObjectList.mNumDeadObjectUpdates = 0; + } + if (gObjectList.mNumUnknownUpdates) + { + LL_INFOS() << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << LL_ENDL; + gObjectList.mNumUnknownUpdates = 0; + } + + } + } + + if (!gDisconnected) + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Network"); - //////////////////////////////////////////////// - // - // Network processing - // - // NOTE: Starting at this point, we may still have pointers to "dead" objects - // floating throughout the various object lists. - // - idleNameCache(); - idleNetwork(); + //////////////////////////////////////////////// + // + // Network processing + // + // NOTE: Starting at this point, we may still have pointers to "dead" objects + // floating throughout the various object lists. + // + idleNameCache(); + idleNetwork(); - // Check for away from keyboard, kick idle agents. - idle_afk_check(); + // Check for away from keyboard, kick idle agents. + idle_afk_check(); - // Update statistics for this frame - update_statistics(); - } + // Update statistics for this frame + update_statistics(); + } - //////////////////////////////////////// - // - // Handle the regular UI idle callbacks as well as - // hover callbacks - // + //////////////////////////////////////// + // + // Handle the regular UI idle callbacks as well as + // hover callbacks + // #ifdef LL_DARWIN - if (!mQuitRequested) //MAINT-4243 + if (!mQuitRequested) //MAINT-4243 #endif - { -// LL_RECORD_BLOCK_TIME(FTM_IDLE_CB); + { +// LL_RECORD_BLOCK_TIME(FTM_IDLE_CB); - // Do event notifications if necessary. Yes, we may want to move this elsewhere. - gEventNotifier.update(); + // Do event notifications if necessary. Yes, we may want to move this elsewhere. + gEventNotifier.update(); - gIdleCallbacks.callFunctions(); - gInventory.idleNotifyObservers(); - LLAvatarTracker::instance().idleNotifyObservers(); - } + gIdleCallbacks.callFunctions(); + gInventory.idleNotifyObservers(); + LLAvatarTracker::instance().idleNotifyObservers(); + } - // Metrics logging (LLViewerAssetStats, etc.) - { - static LLTimer report_interval; + // Metrics logging (LLViewerAssetStats, etc.) + { + static LLTimer report_interval; - // *TODO: Add configuration controls for this - F32 seconds = report_interval.getElapsedTimeF32(); - if (seconds >= app_metrics_interval) - { - metricsSend(! gDisconnected); - report_interval.reset(); - } - } + // *TODO: Add configuration controls for this + F32 seconds = report_interval.getElapsedTimeF32(); + if (seconds >= app_metrics_interval) + { + metricsSend(! gDisconnected); + report_interval.reset(); + } + } // Update layonts, handle mouse events, tooltips, e t c @@ -4827,336 +4827,336 @@ void LLAppViewer::idle() // opening chat. gViewerWindow->updateUI(); - if (gDisconnected) + if (gDisconnected) { - return; + return; } - if (gTeleportDisplay) + if (gTeleportDisplay) { - return; + return; } - /////////////////////////////////////// - // Agent and camera movement - // - LLCoordGL current_mouse = gViewerWindow->getCurrentMouse(); + /////////////////////////////////////// + // Agent and camera movement + // + LLCoordGL current_mouse = gViewerWindow->getCurrentMouse(); - { - // After agent and camera moved, figure out if we need to - // deselect objects. - LLSelectMgr::getInstance()->deselectAllIfTooFar(); + { + // After agent and camera moved, figure out if we need to + // deselect objects. + LLSelectMgr::getInstance()->deselectAllIfTooFar(); - } + } - { - // Handle pending gesture processing - LL_RECORD_BLOCK_TIME(FTM_AGENT_POSITION); - LLGestureMgr::instance().update(); + { + // Handle pending gesture processing + LL_RECORD_BLOCK_TIME(FTM_AGENT_POSITION); + LLGestureMgr::instance().update(); - gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); - } + gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); + } - { - LL_RECORD_BLOCK_TIME(FTM_OBJECTLIST_UPDATE); + { + LL_RECORD_BLOCK_TIME(FTM_OBJECTLIST_UPDATE); if (!(logoutRequestSent() && hasSavedFinalSnapshot())) - { - gObjectList.update(gAgent); + { + gObjectList.update(gAgent); LL::GLTFSceneManager::instance().update(); - } - } - - ////////////////////////////////////// - // - // Deletes objects... - // Has to be done after doing idleUpdates (which can kill objects) - // - - { - LL_RECORD_BLOCK_TIME(FTM_CLEANUP); - { - gObjectList.cleanDeadObjects(); - } - { - LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLES); - LLDrawable::cleanupDeadDrawables(); - } - } - - // - // After this point, in theory we should never see a dead object - // in the various object/drawable lists. - // - - ////////////////////////////////////// - // - // Update/send HUD effects - // - // At this point, HUD effects may clean up some references to - // dead objects. - // - - { - LL_RECORD_BLOCK_TIME(FTM_HUD_EFFECTS); - LLSelectMgr::getInstance()->updateEffects(); - LLHUDManager::getInstance()->cleanupEffects(); - LLHUDManager::getInstance()->sendEffects(); - } - - //////////////////////////////////////// - // - // Unpack layer data that we've received - // - - { - LL_RECORD_BLOCK_TIME(FTM_NETWORK); - gVLManager.unpackData(); - } - - ///////////////////////// - // - // Update surfaces, and surface textures as well. - // - - LLWorld::getInstance()->updateVisibilities(); - { - const F32 max_region_update_time = .001f; // 1ms - LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE); - LLWorld::getInstance()->updateRegions(max_region_update_time); - } - - ///////////////////////// - // - // Update weather effects - // - - // Update wind vector - LLVector3 wind_position_region; - static LLVector3 average_wind; - - LLViewerRegion *regionp; - regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position - if (regionp) - { - gWindVec = regionp->mWind.getVelocity(wind_position_region); - - // Compute average wind and use to drive motion of water - - average_wind = regionp->mWind.getAverage(); - gSky.setWind(average_wind); - //LLVOWater::setWind(average_wind); - } - else - { - gWindVec.setVec(0.0f, 0.0f, 0.0f); - } - - ////////////////////////////////////// - // - // Sort and cull in the new renderer are moved to pipeline.cpp - // Here, particles are updated and drawables are moved. - // - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP("world update"); //LL_RECORD_BLOCK_TIME(FTM_WORLD_UPDATE); - gPipeline.updateMove(); - } - - LLWorld::getInstance()->updateParticles(); - - if (gAgentPilot.isPlaying() && gAgentPilot.getOverrideCamera()) - { - gAgentPilot.moveCamera(); - } - else if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - LLViewerJoystick::getInstance()->moveFlycam(); - } - else - { - if (LLToolMgr::getInstance()->inBuildMode()) - { - LLViewerJoystick::getInstance()->moveObjects(); - } - - gAgentCamera.updateCamera(); - } - - // update media focus - LLViewerMediaFocus::getInstance()->update(); - - // Update marketplace - LLMarketplaceInventoryImporter::update(); - LLMarketplaceInventoryNotifications::update(); - - // objects and camera should be in sync, do LOD calculations now - { - LL_RECORD_BLOCK_TIME(FTM_LOD_UPDATE); - gObjectList.updateApparentAngles(gAgent); - } - - // Update AV render info - LLAvatarRenderInfoAccountant::getInstance()->idle(); - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_APP("audio update"); //LL_RECORD_BLOCK_TIME(FTM_AUDIO_UPDATE); - - if (gAudiop) - { - audio_update_volume(false); - audio_update_listener(); - audio_update_wind(false); - - // this line actually commits the changes we've made to source positions, etc. - gAudiop->idle(); - } - } - - // Handle shutdown process, for example, - // wait for floaters to close, send quit message, - // forcibly quit if it has taken too long - if (mQuitRequested) - { - gGLActive = TRUE; - idleShutdown(); - } + } + } + + ////////////////////////////////////// + // + // Deletes objects... + // Has to be done after doing idleUpdates (which can kill objects) + // + + { + LL_RECORD_BLOCK_TIME(FTM_CLEANUP); + { + gObjectList.cleanDeadObjects(); + } + { + LL_RECORD_BLOCK_TIME(FTM_CLEANUP_DRAWABLES); + LLDrawable::cleanupDeadDrawables(); + } + } + + // + // After this point, in theory we should never see a dead object + // in the various object/drawable lists. + // + + ////////////////////////////////////// + // + // Update/send HUD effects + // + // At this point, HUD effects may clean up some references to + // dead objects. + // + + { + LL_RECORD_BLOCK_TIME(FTM_HUD_EFFECTS); + LLSelectMgr::getInstance()->updateEffects(); + LLHUDManager::getInstance()->cleanupEffects(); + LLHUDManager::getInstance()->sendEffects(); + } + + //////////////////////////////////////// + // + // Unpack layer data that we've received + // + + { + LL_RECORD_BLOCK_TIME(FTM_NETWORK); + gVLManager.unpackData(); + } + + ///////////////////////// + // + // Update surfaces, and surface textures as well. + // + + LLWorld::getInstance()->updateVisibilities(); + { + const F32 max_region_update_time = .001f; // 1ms + LL_RECORD_BLOCK_TIME(FTM_REGION_UPDATE); + LLWorld::getInstance()->updateRegions(max_region_update_time); + } + + ///////////////////////// + // + // Update weather effects + // + + // Update wind vector + LLVector3 wind_position_region; + static LLVector3 average_wind; + + LLViewerRegion *regionp; + regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position + if (regionp) + { + gWindVec = regionp->mWind.getVelocity(wind_position_region); + + // Compute average wind and use to drive motion of water + + average_wind = regionp->mWind.getAverage(); + gSky.setWind(average_wind); + //LLVOWater::setWind(average_wind); + } + else + { + gWindVec.setVec(0.0f, 0.0f, 0.0f); + } + + ////////////////////////////////////// + // + // Sort and cull in the new renderer are moved to pipeline.cpp + // Here, particles are updated and drawables are moved. + // + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("world update"); //LL_RECORD_BLOCK_TIME(FTM_WORLD_UPDATE); + gPipeline.updateMove(); + } + + LLWorld::getInstance()->updateParticles(); + + if (gAgentPilot.isPlaying() && gAgentPilot.getOverrideCamera()) + { + gAgentPilot.moveCamera(); + } + else if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + LLViewerJoystick::getInstance()->moveFlycam(); + } + else + { + if (LLToolMgr::getInstance()->inBuildMode()) + { + LLViewerJoystick::getInstance()->moveObjects(); + } + + gAgentCamera.updateCamera(); + } + + // update media focus + LLViewerMediaFocus::getInstance()->update(); + + // Update marketplace + LLMarketplaceInventoryImporter::update(); + LLMarketplaceInventoryNotifications::update(); + + // objects and camera should be in sync, do LOD calculations now + { + LL_RECORD_BLOCK_TIME(FTM_LOD_UPDATE); + gObjectList.updateApparentAngles(gAgent); + } + + // Update AV render info + LLAvatarRenderInfoAccountant::getInstance()->idle(); + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_APP("audio update"); //LL_RECORD_BLOCK_TIME(FTM_AUDIO_UPDATE); + + if (gAudiop) + { + audio_update_volume(false); + audio_update_listener(); + audio_update_wind(false); + + // this line actually commits the changes we've made to source positions, etc. + gAudiop->idle(); + } + } + + // Handle shutdown process, for example, + // wait for floaters to close, send quit message, + // forcibly quit if it has taken too long + if (mQuitRequested) + { + gGLActive = TRUE; + idleShutdown(); + } } void LLAppViewer::idleShutdown() { - // Wait for all modal alerts to get resolved - if (LLModalDialog::activeCount() > 0) - { - return; - } - - // close IM interface - if(gIMMgr) - { - gIMMgr->disconnectAllSessions(); - } - - // Wait for all floaters to get resolved - if (gFloaterView - && !gFloaterView->allChildrenClosed()) - { - return; - } - - - - - // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup() - // *TODO: ugly - static bool saved_teleport_history = false; - if (!saved_teleport_history) - { - saved_teleport_history = true; - LLTeleportHistory::getInstance()->dump(); - LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this - return; - } - - static bool saved_snapshot = false; - if (!saved_snapshot) - { - saved_snapshot = true; - saveFinalSnapshot(); - return; - } - - const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f; - - S32 pending_uploads = gAssetStorage->getNumPendingUploads(); - if (pending_uploads > 0 - && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME - && !logoutRequestSent()) - { - static S32 total_uploads = 0; - // Sometimes total upload count can change during logout. - total_uploads = llmax(total_uploads, pending_uploads); - gViewerWindow->setShowProgress(TRUE); - S32 finished_uploads = total_uploads - pending_uploads; - F32 percent = 100.f * finished_uploads / total_uploads; - gViewerWindow->setProgressPercent(percent); - gViewerWindow->setProgressString(LLTrans::getString("SavingSettings")); - return; - } - - if (gPendingMetricsUploads > 0 - && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME - && !logoutRequestSent()) - { + // Wait for all modal alerts to get resolved + if (LLModalDialog::activeCount() > 0) + { + return; + } + + // close IM interface + if(gIMMgr) + { + gIMMgr->disconnectAllSessions(); + } + + // Wait for all floaters to get resolved + if (gFloaterView + && !gFloaterView->allChildrenClosed()) + { + return; + } + + + + + // ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup() + // *TODO: ugly + static bool saved_teleport_history = false; + if (!saved_teleport_history) + { + saved_teleport_history = true; + LLTeleportHistory::getInstance()->dump(); + LLLocationHistory::getInstance()->save(); // *TODO: find a better place for doing this + return; + } + + static bool saved_snapshot = false; + if (!saved_snapshot) + { + saved_snapshot = true; + saveFinalSnapshot(); + return; + } + + const F32 SHUTDOWN_UPLOAD_SAVE_TIME = 5.f; + + S32 pending_uploads = gAssetStorage->getNumPendingUploads(); + if (pending_uploads > 0 + && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME + && !logoutRequestSent()) + { + static S32 total_uploads = 0; + // Sometimes total upload count can change during logout. + total_uploads = llmax(total_uploads, pending_uploads); + gViewerWindow->setShowProgress(TRUE); + S32 finished_uploads = total_uploads - pending_uploads; + F32 percent = 100.f * finished_uploads / total_uploads; + gViewerWindow->setProgressPercent(percent); + gViewerWindow->setProgressString(LLTrans::getString("SavingSettings")); + return; + } + + if (gPendingMetricsUploads > 0 + && gLogoutTimer.getElapsedTimeF32() < SHUTDOWN_UPLOAD_SAVE_TIME + && !logoutRequestSent()) + { gViewerWindow->setShowProgress(TRUE); gViewerWindow->setProgressPercent(100.f); gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); - return; - } - - // All floaters are closed. Tell server we want to quit. - if( !logoutRequestSent() ) - { - sendLogoutRequest(); - - // Wait for a LogoutReply message - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(100.f); - gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); - return; - } - - // Make sure that we quit if we haven't received a reply from the server. - if( logoutRequestSent() - && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime ) - { - forceQuit(); - return; - } + return; + } + + // All floaters are closed. Tell server we want to quit. + if( !logoutRequestSent() ) + { + sendLogoutRequest(); + + // Wait for a LogoutReply message + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(100.f); + gViewerWindow->setProgressString(LLTrans::getString("LoggingOut")); + return; + } + + // Make sure that we quit if we haven't received a reply from the server. + if( logoutRequestSent() + && gLogoutTimer.getElapsedTimeF32() > gLogoutMaxTime ) + { + forceQuit(); + return; + } } void LLAppViewer::sendLogoutRequest() { - if(!mLogoutRequestSent && gMessageSystem) - { - //Set internal status variables and marker files before actually starting the logout process - gLogoutInProgress = TRUE; - if (!mSecondInstance) - { - mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); - if (mLogoutMarkerFile.getFileHandle()) - { - LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL; - recordMarkerVersion(mLogoutMarkerFile); - } - else - { - LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; - } - } - else - { - LL_INFOS("MarkerFile") << "Did not logout marker file because this is a second instance" << LL_ENDL; - } - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_LogoutRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - - gLogoutTimer.reset(); - gLogoutMaxTime = LOGOUT_REQUEST_TIME; - mLogoutRequestSent = TRUE; - - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->leaveChannel(); - } - } + if(!mLogoutRequestSent && gMessageSystem) + { + //Set internal status variables and marker files before actually starting the logout process + gLogoutInProgress = TRUE; + if (!mSecondInstance) + { + mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); + + mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); + if (mLogoutMarkerFile.getFileHandle()) + { + LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL; + recordMarkerVersion(mLogoutMarkerFile); + } + else + { + LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; + } + } + else + { + LL_INFOS("MarkerFile") << "Did not logout marker file because this is a second instance" << LL_ENDL; + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_LogoutRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + + gLogoutTimer.reset(); + gLogoutMaxTime = LOGOUT_REQUEST_TIME; + mLogoutRequestSent = TRUE; + + if(LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->leaveChannel(); + } + } } void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp) @@ -5202,19 +5202,19 @@ void LLAppViewer::updateNameLookupUrl(const LLViewerRegion * regionp) void LLAppViewer::idleNameCache() { - // Neither old nor new name cache can function before agent has a region - LLViewerRegion* region = gAgent.getRegion(); + // Neither old nor new name cache can function before agent has a region + LLViewerRegion* region = gAgent.getRegion(); if (!region) { return; } - // deal with any queued name requests and replies. - gCacheName->processPending(); + // deal with any queued name requests and replies. + gCacheName->processPending(); - // Can't run the new cache until we have the list of capabilities - // for the agent region, and can therefore decide whether to use - // display names or fall back to the old name system. + // Can't run the new cache until we have the list of capabilities + // for the agent region, and can therefore decide whether to use + // display names or fall back to the old name system. if (!region->capabilitiesReceived()) { return; @@ -5244,141 +5244,141 @@ static LLTrace::BlockTimerStatHandle FTM_CHECK_REGION_CIRCUIT("Check Region Circ void LLAppViewer::idleNetwork() { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - pingMainloopTimeout("idleNetwork"); - - gObjectList.mNumNewObjects = 0; - S32 total_decoded = 0; - - if (!gSavedSettings.getBOOL("SpeedTest")) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode - - LLTimer check_message_timer; - // Read all available packets from network - const S64 frame_count = gFrameCount; // U32->S64 - F32 total_time = 0.0f; - - { - LockMessageChecker lmc(gMessageSystem); - while (lmc.checkAllMessages(frame_count, gServicePump)) - { - if (gDoDisconnect) - { - // We're disconnecting, don't process any more messages from the server - // We're usually disconnecting due to either network corruption or a - // server going down, so this is OK. - break; - } - - total_decoded++; - gPacketsIn++; - - if (total_decoded > MESSAGE_MAX_PER_FRAME) - { - break; - } + pingMainloopTimeout("idleNetwork"); + + gObjectList.mNumNewObjects = 0; + S32 total_decoded = 0; + + if (!gSavedSettings.getBOOL("SpeedTest")) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode + + LLTimer check_message_timer; + // Read all available packets from network + const S64 frame_count = gFrameCount; // U32->S64 + F32 total_time = 0.0f; + + { + LockMessageChecker lmc(gMessageSystem); + while (lmc.checkAllMessages(frame_count, gServicePump)) + { + if (gDoDisconnect) + { + // We're disconnecting, don't process any more messages from the server + // We're usually disconnecting due to either network corruption or a + // server going down, so this is OK. + break; + } + + total_decoded++; + gPacketsIn++; + + if (total_decoded > MESSAGE_MAX_PER_FRAME) + { + break; + } #ifdef TIME_THROTTLE_MESSAGES - // Prevent slow packets from completely destroying the frame rate. - // This usually happens due to clumps of avatars taking huge amount - // of network processing time (which needs to be fixed, but this is - // a good limit anyway). - total_time = check_message_timer.getElapsedTimeF32(); - if (total_time >= CheckMessagesMaxTime) - break; + // Prevent slow packets from completely destroying the frame rate. + // This usually happens due to clumps of avatars taking huge amount + // of network processing time (which needs to be fixed, but this is + // a good limit anyway). + total_time = check_message_timer.getElapsedTimeF32(); + if (total_time >= CheckMessagesMaxTime) + break; #endif - } + } - // Handle per-frame message system processing. - lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); - } + // Handle per-frame message system processing. + lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); + } #ifdef TIME_THROTTLE_MESSAGES - if (total_time >= CheckMessagesMaxTime) - { - // Increase CheckMessagesMaxTime so that we will eventually catch up - CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames - } - else - { - // Reset CheckMessagesMaxTime to default value - CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; - } + if (total_time >= CheckMessagesMaxTime) + { + // Increase CheckMessagesMaxTime so that we will eventually catch up + CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames + } + else + { + // Reset CheckMessagesMaxTime to default value + CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME; + } #endif - // we want to clear the control after sending out all necessary agent updates - gAgent.resetControlFlags(); - - // Decode enqueued messages... - S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; - - if( remaining_possible_decodes <= 0 ) - { - LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL; - } - - if (gPrintMessagesThisFrame) - { - LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL; - gPrintMessagesThisFrame = FALSE; - } - } - add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); - - // Retransmit unacknowledged packets. - gXferManager->retransmitUnackedPackets(); - gAssetStorage->checkForTimeouts(); - gViewerThrottle.updateDynamicThrottle(); - - // Check that the circuit between the viewer and the agent's current - // region is still alive - LLViewerRegion *agent_region = gAgent.getRegion(); - if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED)) - { - LLUUID this_region_id = agent_region->getRegionID(); - bool this_region_alive = agent_region->isAlive(); - if ((mAgentRegionLastAlive && !this_region_alive) // newly dead - && (mAgentRegionLastID == this_region_id)) // same region - { - forceDisconnect(LLTrans::getString("AgentLostConnection")); - } - mAgentRegionLastID = this_region_id; - mAgentRegionLastAlive = this_region_alive; - } + // we want to clear the control after sending out all necessary agent updates + gAgent.resetControlFlags(); + + // Decode enqueued messages... + S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; + + if( remaining_possible_decodes <= 0 ) + { + LL_INFOS() << "Maxed out number of messages per frame at " << MESSAGE_MAX_PER_FRAME << LL_ENDL; + } + + if (gPrintMessagesThisFrame) + { + LL_INFOS() << "Decoded " << total_decoded << " msgs this frame!" << LL_ENDL; + gPrintMessagesThisFrame = FALSE; + } + } + add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); + + // Retransmit unacknowledged packets. + gXferManager->retransmitUnackedPackets(); + gAssetStorage->checkForTimeouts(); + gViewerThrottle.updateDynamicThrottle(); + + // Check that the circuit between the viewer and the agent's current + // region is still alive + LLViewerRegion *agent_region = gAgent.getRegion(); + if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED)) + { + LLUUID this_region_id = agent_region->getRegionID(); + bool this_region_alive = agent_region->isAlive(); + if ((mAgentRegionLastAlive && !this_region_alive) // newly dead + && (mAgentRegionLastID == this_region_id)) // same region + { + forceDisconnect(LLTrans::getString("AgentLostConnection")); + } + mAgentRegionLastID = this_region_id; + mAgentRegionLastAlive = this_region_alive; + } } void LLAppViewer::disconnectViewer() { - if (gDisconnected) - { - return; - } - // - // Cleanup after quitting. - // - // Save snapshot for next time, if we made it through initialization - - LL_INFOS() << "Disconnecting viewer!" << LL_ENDL; - - // Dump our frame statistics - - // Remember if we were flying - gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() ); - - // Un-minimize all windows so they don't get saved minimized - if (gFloaterView) - { - gFloaterView->restoreAll(); - } - - if (LLSelectMgr::instanceExists()) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - // save inventory if appropriate + if (gDisconnected) + { + return; + } + // + // Cleanup after quitting. + // + // Save snapshot for next time, if we made it through initialization + + LL_INFOS() << "Disconnecting viewer!" << LL_ENDL; + + // Dump our frame statistics + + // Remember if we were flying + gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() ); + + // Un-minimize all windows so they don't get saved minimized + if (gFloaterView) + { + gFloaterView->restoreAll(); + } + + if (LLSelectMgr::instanceExists()) + { + LLSelectMgr::getInstance()->deselectAll(); + } + + // save inventory if appropriate if (gInventory.isInventoryUsable() && gAgent.getID().notNull()) // Shouldn't be null at this stage { @@ -5393,44 +5393,44 @@ void LLAppViewer::disconnectViewer() } } - saveNameCache(); - if (LLExperienceCache::instanceExists()) - { - // TODO: LLExperienceCache::cleanup() logic should be moved to - // cleanupSingleton(). - LLExperienceCache::instance().cleanup(); - } + saveNameCache(); + if (LLExperienceCache::instanceExists()) + { + // TODO: LLExperienceCache::cleanup() logic should be moved to + // cleanupSingleton(). + LLExperienceCache::instance().cleanup(); + } - // close inventory interface, close all windows - LLSidepanelInventory::cleanup(); + // close inventory interface, close all windows + LLSidepanelInventory::cleanup(); - gAgentWearables.cleanup(); - gAgentCamera.cleanup(); - // Also writes cached agent settings to gSavedSettings - gAgent.cleanup(); + gAgentWearables.cleanup(); + gAgentCamera.cleanup(); + // Also writes cached agent settings to gSavedSettings + gAgent.cleanup(); - // This is where we used to call gObjectList.destroy() and then delete gWorldp. - // Now we just ask the LLWorld singleton to cleanly shut down. - if(LLWorld::instanceExists()) - { - LLWorld::getInstance()->resetClass(); - } - LLVOCache::deleteSingleton(); + // This is where we used to call gObjectList.destroy() and then delete gWorldp. + // Now we just ask the LLWorld singleton to cleanly shut down. + if(LLWorld::instanceExists()) + { + LLWorld::getInstance()->resetClass(); + } + LLVOCache::deleteSingleton(); - // call all self-registered classes - LLDestroyClassList::instance().fireCallbacks(); + // call all self-registered classes + LLDestroyClassList::instance().fireCallbacks(); - cleanup_xfer_manager(); - gDisconnected = TRUE; + cleanup_xfer_manager(); + gDisconnected = TRUE; - // Pass the connection state to LLUrlEntryParcel not to attempt - // parcel info requests while disconnected. - LLUrlEntryParcel::setDisconnected(gDisconnected); + // Pass the connection state to LLUrlEntryParcel not to attempt + // parcel info requests while disconnected. + LLUrlEntryParcel::setDisconnected(gDisconnected); } void LLAppViewer::forceErrorLLError() { - LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; + LL_ERRS() << "This is a deliberate llerror" << LL_ENDL; } void LLAppViewer::forceErrorLLErrorMsg() @@ -5443,7 +5443,7 @@ void LLAppViewer::forceErrorLLErrorMsg() void LLAppViewer::forceErrorBreakpoint() { - LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; + LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; #ifdef LL_WINDOWS DebugBreak(); #else @@ -5454,7 +5454,7 @@ void LLAppViewer::forceErrorBreakpoint() void LLAppViewer::forceErrorBadMemoryAccess() { - LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL; + LL_WARNS() << "Forcing a deliberate bad memory access" << LL_ENDL; S32* crash = NULL; *crash = 0xDEADBEEF; return; @@ -5462,7 +5462,7 @@ void LLAppViewer::forceErrorBadMemoryAccess() void LLAppViewer::forceErrorInfiniteLoop() { - LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; + LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; // Loop is intentionally complicated to fool basic loop detection LLTimer timer_total; LLTimer timer_expiry; @@ -5481,7 +5481,7 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { - LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; + LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; LLTHROW(LLException("User selected Force Software Exception")); } @@ -5494,8 +5494,8 @@ void LLAppViewer::forceErrorOSSpecificException() void LLAppViewer::forceErrorDriverCrash() { - LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; - glDeleteTextures(1, NULL); + LL_WARNS() << "Forcing a deliberate driver crash" << LL_ENDL; + glDeleteTextures(1, NULL); } void LLAppViewer::forceErrorCoroutineCrash() @@ -5527,120 +5527,120 @@ void LLAppViewer::forceErrorThreadCrash() void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs) { - if(!mMainloopTimeout) - { - mMainloopTimeout = new LLWatchdogTimeout(); - resumeMainloopTimeout(state, secs); - } + if(!mMainloopTimeout) + { + mMainloopTimeout = new LLWatchdogTimeout(); + resumeMainloopTimeout(state, secs); + } } void LLAppViewer::destroyMainloopTimeout() { - if(mMainloopTimeout) - { - delete mMainloopTimeout; - mMainloopTimeout = NULL; - } + if(mMainloopTimeout) + { + delete mMainloopTimeout; + mMainloopTimeout = NULL; + } } void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs) { - if(mMainloopTimeout) - { - if(secs < 0.0f) - { - static LLCachedControl mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); - mMainloopTimeout->start(state); - } + if(mMainloopTimeout) + { + if(secs < 0.0f) + { + static LLCachedControl mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); + secs = mainloop_timeout; + } + + mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->start(state); + } } void LLAppViewer::pauseMainloopTimeout() { - if(mMainloopTimeout) - { - mMainloopTimeout->stop(); - } + if(mMainloopTimeout) + { + mMainloopTimeout->stop(); + } } void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs) { LL_PROFILE_ZONE_SCOPED_CATEGORY_APP; - if(mMainloopTimeout) - { - if(secs < 0.0f) - { - static LLCachedControl mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); - secs = mainloop_timeout; - } - - mMainloopTimeout->setTimeout(secs); - mMainloopTimeout->ping(state); - } + if(mMainloopTimeout) + { + if(secs < 0.0f) + { + static LLCachedControl mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60); + secs = mainloop_timeout; + } + + mMainloopTimeout->setTimeout(secs); + mMainloopTimeout->ping(state); + } } void LLAppViewer::handleLoginComplete() { - gLoggedInTime.start(); - initMainloopTimeout("Mainloop Init"); - - // Store some data to DebugInfo in case of a freeze. - gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel(); - - gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor(); - gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor(); - gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch(); - gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild()); - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if ( parcel && parcel->getMusicURL()[0]) - { - gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL(); - } - if ( parcel && parcel->getMediaURL()[0]) - { - gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL(); - } - - gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); - gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); - gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); - gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); - - if(gAgent.getRegion()) - { - gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName(); - gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName(); - } - - if(LLAppViewer::instance()->mMainloopTimeout) - { - gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); - } - - mOnLoginCompleted(); - - writeDebugInfo(); - - // we logged in successfully, so save settings on logout - LL_INFOS() << "Login successful, per account settings will be saved on log out." << LL_ENDL; - mSavePerAccountSettings=true; + gLoggedInTime.start(); + initMainloopTimeout("Mainloop Init"); + + // Store some data to DebugInfo in case of a freeze. + gDebugInfo["ClientInfo"]["Name"] = LLVersionInfo::instance().getChannel(); + + gDebugInfo["ClientInfo"]["MajorVersion"] = LLVersionInfo::instance().getMajor(); + gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::instance().getMinor(); + gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::instance().getPatch(); + gDebugInfo["ClientInfo"]["BuildVersion"] = std::to_string(LLVersionInfo::instance().getBuild()); + + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if ( parcel && parcel->getMusicURL()[0]) + { + gDebugInfo["ParcelMusicURL"] = parcel->getMusicURL(); + } + if ( parcel && parcel->getMediaURL()[0]) + { + gDebugInfo["ParcelMediaURL"] = parcel->getMediaURL(); + } + + gDebugInfo["SettingsFilename"] = gSavedSettings.getString("ClientSettingsFile"); + gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); + gDebugInfo["ViewerExePath"] = gDirUtilp->getExecutablePathAndName(); + gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); + + if(gAgent.getRegion()) + { + gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName(); + gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName(); + } + + if(LLAppViewer::instance()->mMainloopTimeout) + { + gDebugInfo["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); + } + + mOnLoginCompleted(); + + writeDebugInfo(); + + // we logged in successfully, so save settings on logout + LL_INFOS() << "Login successful, per account settings will be saved on log out." << LL_ENDL; + mSavePerAccountSettings=true; } //virtual void LLAppViewer::setMasterSystemAudioMute(bool mute) { - gSavedSettings.setBOOL("MuteAudio", mute); + gSavedSettings.setBOOL("MuteAudio", mute); } //virtual bool LLAppViewer::getMasterSystemAudioMute() { - return gSavedSettings.getBOOL("MuteAudio"); + return gSavedSettings.getBOOL("MuteAudio"); } //---------------------------------------------------------------------------- @@ -5656,10 +5656,10 @@ bool LLAppViewer::getMasterSystemAudioMute() */ void LLAppViewer::metricsUpdateRegion(U64 region_handle) { - if (0 != region_handle) - { - LLViewerAssetStatsFF::set_region(region_handle); - } + if (0 != region_handle) + { + LLViewerAssetStatsFF::set_region(region_handle); + } } /** @@ -5668,35 +5668,35 @@ void LLAppViewer::metricsUpdateRegion(U64 region_handle) */ void LLAppViewer::metricsSend(bool enable_reporting) { - if (! gViewerAssetStats) - return; + if (! gViewerAssetStats) + return; - if (LLAppViewer::sTextureFetch) - { - LLViewerRegion * regionp = gAgent.getRegion(); + if (LLAppViewer::sTextureFetch) + { + LLViewerRegion * regionp = gAgent.getRegion(); - if (enable_reporting && regionp) - { - std::string caps_url = regionp->getCapability("ViewerMetrics"); + if (enable_reporting && regionp) + { + std::string caps_url = regionp->getCapability("ViewerMetrics"); LLSD sd = gViewerAssetStats->asLLSD(true); - // Send a report request into 'thread1' to get the rest of the data - // and provide some additional parameters while here. - LLAppViewer::sTextureFetch->commandSendMetrics(caps_url, - gAgentSessionID, - gAgentID, - sd); - } - else - { - LLAppViewer::sTextureFetch->commandDataBreak(); - } - } - - // Reset even if we can't report. Rather than gather up a huge chunk of - // data, we'll keep to our sampling interval and retain the data - // resolution in time. - gViewerAssetStats->restart(); + // Send a report request into 'thread1' to get the rest of the data + // and provide some additional parameters while here. + LLAppViewer::sTextureFetch->commandSendMetrics(caps_url, + gAgentSessionID, + gAgentID, + sd); + } + else + { + LLAppViewer::sTextureFetch->commandDataBreak(); + } + } + + // Reset even if we can't report. Rather than gather up a huge chunk of + // data, we'll keep to our sampling interval and retain the data + // resolution in time. + gViewerAssetStats->restart(); } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index fc182fc2e2..726667813a 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -1,25 +1,25 @@ -/** +/** * @file lldrawable.h * @brief LLDrawable class definition * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -67,280 +67,280 @@ class LLDrawable public: typedef std::vector face_list_t; - LLDrawable(const LLDrawable& rhs) + LLDrawable(const LLDrawable& rhs) : LLViewerOctreeEntryData(rhs) - { - *this = rhs; - } - - const LLDrawable& operator=(const LLDrawable& rhs) - { - LL_ERRS() << "Illegal operation!" << LL_ENDL; - return *this; - } - - static void initClass(); - - LLDrawable(LLViewerObject *vobj, bool new_entry = false); - - void markDead(); // Mark this drawable as dead - BOOL isDead() const { return isState(DEAD); } - BOOL isNew() const { return !isState(BUILT); } - BOOL isUnload() const { return isState(FOR_UNLOAD); } - - BOOL isLight() const; - - virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE); - - LLSpatialGroup* getSpatialGroup()const {return (LLSpatialGroup*)getGroup();} - LLViewerRegion* getRegion() const { return mVObjp->getRegion(); } - const LLTextureEntry* getTextureEntry(U8 which) const { return mVObjp->getTE(which); } - LLPointer& getVObj() { return mVObjp; } - const LLViewerObject *getVObj() const { return mVObjp; } - LLVOVolume* getVOVolume() const; // cast mVObjp tp LLVOVolume if OK - - const LLMatrix4& getWorldMatrix() const { return mXform.getWorldMatrix(); } - const LLMatrix4& getRenderMatrix() const; - void setPosition(LLVector3 v) const { } - const LLVector3& getPosition() const { return mXform.getPosition(); } - const LLVector3& getWorldPosition() const { return mXform.getPositionW(); } - const LLVector3 getPositionAgent() const; - const LLVector3& getScale() const { return mCurrentScale; } - void setScale(const LLVector3& scale) { mCurrentScale = scale; } - const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } - const LLQuaternion& getRotation() const { return mXform.getRotation(); } - F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } - S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } - - void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } - LLXformMatrix* getXform() { return &mXform; } - - U32 getState() const { return mState; } - BOOL isState (U32 bits) const { return ((mState & bits) != 0); } - void setState (U32 bits) { mState |= bits; } - void clearState(U32 bits) { mState &= ~bits; } - - BOOL isAvatar() const { return mVObjp.notNull() && mVObjp->isAvatar(); } - BOOL isRoot() const { return !mParent || mParent->isAvatar(); } + { + *this = rhs; + } + + const LLDrawable& operator=(const LLDrawable& rhs) + { + LL_ERRS() << "Illegal operation!" << LL_ENDL; + return *this; + } + + static void initClass(); + + LLDrawable(LLViewerObject *vobj, bool new_entry = false); + + void markDead(); // Mark this drawable as dead + BOOL isDead() const { return isState(DEAD); } + BOOL isNew() const { return !isState(BUILT); } + BOOL isUnload() const { return isState(FOR_UNLOAD); } + + BOOL isLight() const; + + virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE); + + LLSpatialGroup* getSpatialGroup()const {return (LLSpatialGroup*)getGroup();} + LLViewerRegion* getRegion() const { return mVObjp->getRegion(); } + const LLTextureEntry* getTextureEntry(U8 which) const { return mVObjp->getTE(which); } + LLPointer& getVObj() { return mVObjp; } + const LLViewerObject *getVObj() const { return mVObjp; } + LLVOVolume* getVOVolume() const; // cast mVObjp tp LLVOVolume if OK + + const LLMatrix4& getWorldMatrix() const { return mXform.getWorldMatrix(); } + const LLMatrix4& getRenderMatrix() const; + void setPosition(LLVector3 v) const { } + const LLVector3& getPosition() const { return mXform.getPosition(); } + const LLVector3& getWorldPosition() const { return mXform.getPositionW(); } + const LLVector3 getPositionAgent() const; + const LLVector3& getScale() const { return mCurrentScale; } + void setScale(const LLVector3& scale) { mCurrentScale = scale; } + const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } + const LLQuaternion& getRotation() const { return mXform.getRotation(); } + F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } + S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } + + void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } + LLXformMatrix* getXform() { return &mXform; } + + U32 getState() const { return mState; } + BOOL isState (U32 bits) const { return ((mState & bits) != 0); } + void setState (U32 bits) { mState |= bits; } + void clearState(U32 bits) { mState &= ~bits; } + + BOOL isAvatar() const { return mVObjp.notNull() && mVObjp->isAvatar(); } + BOOL isRoot() const { return !mParent || mParent->isAvatar(); } LLDrawable* getRoot(); - BOOL isSpatialRoot() const { return !mParent || mParent->isAvatar(); } - virtual BOOL isSpatialBridge() const { return FALSE; } - virtual LLSpatialPartition* asPartition() { return NULL; } - LLDrawable* getParent() const { return mParent; } - - // must set parent through LLViewerObject:: () - //BOOL setParent(LLDrawable *parent); - - inline LLFace* getFace(const S32 i) const; - inline S32 getNumFaces() const; + BOOL isSpatialRoot() const { return !mParent || mParent->isAvatar(); } + virtual BOOL isSpatialBridge() const { return FALSE; } + virtual LLSpatialPartition* asPartition() { return NULL; } + LLDrawable* getParent() const { return mParent; } + + // must set parent through LLViewerObject:: () + //BOOL setParent(LLDrawable *parent); + + inline LLFace* getFace(const S32 i) const; + inline S32 getNumFaces() const; face_list_t& getFaces() { return mFaces; } const face_list_t& getFaces() const { return mFaces; } - //void removeFace(const S32 i); // SJB: Avoid using this, it's slow - LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); - LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep); - LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp); - LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp, LLViewerTexture *specularp); - void deleteFaces(S32 offset, S32 count); - void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); - void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); - void mergeFaces(LLDrawable* src); - - void init(bool new_entry); - void unload(); - void destroy(); - - void update(); - F32 updateXform(BOOL undamped); - - virtual void makeActive(); - /*virtual*/ void makeStatic(BOOL warning_enabled = TRUE); - - BOOL isActive() const { return isState(ACTIVE); } - BOOL isStatic() const { return !isActive(); } - BOOL isAnimating() const; - - virtual BOOL updateMove(); - virtual void movePartition(); - - void updateTexture(); - void updateMaterial(); - virtual void updateDistance(LLCamera& camera, bool force_update); - BOOL updateGeometry(); - void updateFaceSize(S32 idx); - - void updateSpecialHoverCursor(BOOL enabled); - - virtual void shiftPos(const LLVector4a &shift_vector); - - S32 getGeneration() const { return mGeneration; } - - BOOL getLit() const { return isState(UNLIT) ? FALSE : TRUE; } - void setLit(BOOL lit) { lit ? clearState(UNLIT) : setState(UNLIT); } - - bool isVisible() const; - bool isRecentlyVisible() const; - - virtual void cleanupReferences(); - - void setGroup(LLViewerOctreeGroup* group); - void setRadius(const F32 radius); - F32 getRadius() const { return mRadius; } - F32 getVisibilityRadius() const; - - void updateUVMinMax(); // Updates the cache of sun space bounding box. - - const LLVector3& getBounds(LLVector3& min, LLVector3& max) const; - virtual void updateSpatialExtents(); - virtual void updateBinRadius(); - - void setRenderType(S32 type) { mRenderType = type; } - BOOL isRenderType(S32 type) { return mRenderType == type; } - S32 getRenderType() { return mRenderType; } - - // Debugging methods - S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... - - LLSpatialPartition* getSpatialPartition(); - - void removeFromOctree(); - - void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } - LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } - - // Statics - static void incrementVisible(); - static void cleanupDeadDrawables(); + //void removeFace(const S32 i); // SJB: Avoid using this, it's slow + LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep); + LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep); + LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp); + LLFace* addFace(const LLTextureEntry *te, LLViewerTexture *texturep, LLViewerTexture *normalp, LLViewerTexture *specularp); + void deleteFaces(S32 offset, S32 count); + void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); + void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); + void mergeFaces(LLDrawable* src); + + void init(bool new_entry); + void unload(); + void destroy(); + + void update(); + F32 updateXform(BOOL undamped); + + virtual void makeActive(); + /*virtual*/ void makeStatic(BOOL warning_enabled = TRUE); + + BOOL isActive() const { return isState(ACTIVE); } + BOOL isStatic() const { return !isActive(); } + BOOL isAnimating() const; + + virtual BOOL updateMove(); + virtual void movePartition(); + + void updateTexture(); + void updateMaterial(); + virtual void updateDistance(LLCamera& camera, bool force_update); + BOOL updateGeometry(); + void updateFaceSize(S32 idx); + + void updateSpecialHoverCursor(BOOL enabled); + + virtual void shiftPos(const LLVector4a &shift_vector); + + S32 getGeneration() const { return mGeneration; } + + BOOL getLit() const { return isState(UNLIT) ? FALSE : TRUE; } + void setLit(BOOL lit) { lit ? clearState(UNLIT) : setState(UNLIT); } + + bool isVisible() const; + bool isRecentlyVisible() const; + + virtual void cleanupReferences(); + + void setGroup(LLViewerOctreeGroup* group); + void setRadius(const F32 radius); + F32 getRadius() const { return mRadius; } + F32 getVisibilityRadius() const; + + void updateUVMinMax(); // Updates the cache of sun space bounding box. + + const LLVector3& getBounds(LLVector3& min, LLVector3& max) const; + virtual void updateSpatialExtents(); + virtual void updateBinRadius(); + + void setRenderType(S32 type) { mRenderType = type; } + BOOL isRenderType(S32 type) { return mRenderType == type; } + S32 getRenderType() { return mRenderType; } + + // Debugging methods + S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... + + LLSpatialPartition* getSpatialPartition(); + + void removeFromOctree(); + + void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } + LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } + + // Statics + static void incrementVisible(); + static void cleanupDeadDrawables(); protected: - ~LLDrawable() { destroy(); } - void moveUpdatePipeline(BOOL moved); - void updatePartition(); - BOOL updateMoveDamped(); - BOOL updateMoveUndamped(); - + ~LLDrawable() { destroy(); } + void moveUpdatePipeline(BOOL moved); + void updatePartition(); + BOOL updateMoveDamped(); + BOOL updateMoveUndamped(); + public: - friend class LLPipeline; - friend class LLDrawPool; - friend class LLSpatialBridge; - - typedef std::unordered_set > drawable_set_t; + friend class LLPipeline; + friend class LLDrawPool; + friend class LLSpatialBridge; + + typedef std::unordered_set > drawable_set_t; typedef std::set > ordered_drawable_set_t; - typedef std::vector > drawable_vector_t; - typedef std::list > drawable_list_t; - typedef std::queue > drawable_queue_t; - - struct CompareDistanceGreater - { - bool operator()(const LLDrawable* const& lhs, const LLDrawable* const& rhs) - { - return lhs->mDistanceWRTCamera < rhs->mDistanceWRTCamera; // farthest = last - } - }; - - struct CompareDistanceGreaterVisibleFirst - { - bool operator()(const LLDrawable* const& lhs, const LLDrawable* const& rhs) - { - if (lhs->isVisible() && !rhs->isVisible()) - { - return TRUE; //visible things come first - } - else if (!lhs->isVisible() && rhs->isVisible()) - { - return FALSE; //rhs is visible, comes first - } - - return lhs->mDistanceWRTCamera < rhs->mDistanceWRTCamera; // farthest = last - } - }; - - typedef enum e_drawable_flags - { - IN_REBUILD_Q = 0x00000001, - EARLY_MOVE = 0x00000004, - MOVE_UNDAMPED = 0x00000008, - ON_MOVE_LIST = 0x00000010, - UV = 0x00000020, - UNLIT = 0x00000040, - LIGHT = 0x00000080, - REBUILD_VOLUME = 0x00000100, //volume changed LOD or parameters, or vertex buffer changed - REBUILD_TCOORD = 0x00000200, //texture coordinates changed - REBUILD_COLOR = 0x00000400, //color changed - REBUILD_POSITION= 0x00000800, //vertex positions/normals changed - REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR, - REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR, - REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME, - REBUILD_RIGGED = 0x00001000, - ON_SHIFT_LIST = 0x00002000, - ACTIVE = 0x00004000, - DEAD = 0x00008000, - INVISIBLE = 0x00010000, // stay invisible until flag is cleared - NEARBY_LIGHT = 0x00020000, // In gPipeline.mNearbyLightSet - BUILT = 0x00040000, - FORCE_INVISIBLE = 0x00080000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) - HAS_ALPHA = 0x00100000, - RIGGED = 0x00200000, //has a rigged face + typedef std::vector > drawable_vector_t; + typedef std::list > drawable_list_t; + typedef std::queue > drawable_queue_t; + + struct CompareDistanceGreater + { + bool operator()(const LLDrawable* const& lhs, const LLDrawable* const& rhs) + { + return lhs->mDistanceWRTCamera < rhs->mDistanceWRTCamera; // farthest = last + } + }; + + struct CompareDistanceGreaterVisibleFirst + { + bool operator()(const LLDrawable* const& lhs, const LLDrawable* const& rhs) + { + if (lhs->isVisible() && !rhs->isVisible()) + { + return TRUE; //visible things come first + } + else if (!lhs->isVisible() && rhs->isVisible()) + { + return FALSE; //rhs is visible, comes first + } + + return lhs->mDistanceWRTCamera < rhs->mDistanceWRTCamera; // farthest = last + } + }; + + typedef enum e_drawable_flags + { + IN_REBUILD_Q = 0x00000001, + EARLY_MOVE = 0x00000004, + MOVE_UNDAMPED = 0x00000008, + ON_MOVE_LIST = 0x00000010, + UV = 0x00000020, + UNLIT = 0x00000040, + LIGHT = 0x00000080, + REBUILD_VOLUME = 0x00000100, //volume changed LOD or parameters, or vertex buffer changed + REBUILD_TCOORD = 0x00000200, //texture coordinates changed + REBUILD_COLOR = 0x00000400, //color changed + REBUILD_POSITION= 0x00000800, //vertex positions/normals changed + REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR, + REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR, + REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME, + REBUILD_RIGGED = 0x00001000, + ON_SHIFT_LIST = 0x00002000, + ACTIVE = 0x00004000, + DEAD = 0x00008000, + INVISIBLE = 0x00010000, // stay invisible until flag is cleared + NEARBY_LIGHT = 0x00020000, // In gPipeline.mNearbyLightSet + BUILT = 0x00040000, + FORCE_INVISIBLE = 0x00080000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned) + HAS_ALPHA = 0x00100000, + RIGGED = 0x00200000, //has a rigged face RIGGED_CHILD = 0x00400000, //has a child with a rigged face - PARTITION_MOVE = 0x00800000, - ANIMATED_CHILD = 0x01000000, - ACTIVE_CHILD = 0x02000000, - FOR_UNLOAD = 0x04000000, //should be unload from memory + PARTITION_MOVE = 0x00800000, + ANIMATED_CHILD = 0x01000000, + ACTIVE_CHILD = 0x02000000, + FOR_UNLOAD = 0x04000000, //should be unload from memory MIRROR = 0x08000000, // Used as a mirror, needs a hero probe position to be calculated. - } EDrawableFlags; + } EDrawableFlags; public: - LLXformMatrix mXform; + LLXformMatrix mXform; - // vis data - LLPointer mParent; + // vis data + LLPointer mParent; - F32 mDistanceWRTCamera; + F32 mDistanceWRTCamera; - static F32 sCurPixelAngle; //current pixels per radian + static F32 sCurPixelAngle; //current pixels per radian private: - U32 mState; - S32 mRenderType; - LLPointer mVObjp; - face_list_t mFaces; - LLPointer mSpatialBridge; - - F32 mRadius; - S32 mGeneration; - - LLVector3 mCurrentScale; - - static U32 sNumZombieDrawables; - static std::vector > sDeadList; + U32 mState; + S32 mRenderType; + LLPointer mVObjp; + face_list_t mFaces; + LLPointer mSpatialBridge; + + F32 mRadius; + S32 mGeneration; + + LLVector3 mCurrentScale; + + static U32 sNumZombieDrawables; + static std::vector > sDeadList; } LL_ALIGN_POSTFIX(16); inline LLFace* LLDrawable::getFace(const S32 i) const { - //switch these asserts to LL_ERRS() -- davep - //llassert((U32)i < mFaces.size()); - //llassert(mFaces[i]); - - if ((U32) i >= mFaces.size()) - { - LL_WARNS() << "Invalid face index." << LL_ENDL; - return NULL; - } - - if (!mFaces[i]) - { - LL_WARNS() << "Null face found." << LL_ENDL; - return NULL; - } - - return mFaces[i]; + //switch these asserts to LL_ERRS() -- davep + //llassert((U32)i < mFaces.size()); + //llassert(mFaces[i]); + + if ((U32) i >= mFaces.size()) + { + LL_WARNS() << "Invalid face index." << LL_ENDL; + return NULL; + } + + if (!mFaces[i]) + { + LL_WARNS() << "Null face found." << LL_ENDL; + return NULL; + } + + return mFaces[i]; } inline S32 LLDrawable::getNumFaces()const { - return (S32)mFaces.size(); + return (S32)mFaces.size(); } #endif diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 556760632a..2d44949c4a 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpool.cpp * @brief LLDrawPool class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -60,81 +60,81 @@ S32 LLDrawPool::sNumDrawPools = 0; //============================= LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) { - LLDrawPool *poolp = NULL; - switch (type) - { - case POOL_SIMPLE: - poolp = new LLDrawPoolSimple(); - break; - case POOL_GRASS: - poolp = new LLDrawPoolGrass(); - break; - case POOL_ALPHA_MASK: - poolp = new LLDrawPoolAlphaMask(); - break; - case POOL_FULLBRIGHT_ALPHA_MASK: - poolp = new LLDrawPoolFullbrightAlphaMask(); - break; - case POOL_FULLBRIGHT: - poolp = new LLDrawPoolFullbright(); - break; - case POOL_GLOW: - poolp = new LLDrawPoolGlow(); - break; - case POOL_ALPHA_PRE_WATER: - poolp = new LLDrawPoolAlpha(LLDrawPool::POOL_ALPHA_PRE_WATER); - break; + LLDrawPool *poolp = NULL; + switch (type) + { + case POOL_SIMPLE: + poolp = new LLDrawPoolSimple(); + break; + case POOL_GRASS: + poolp = new LLDrawPoolGrass(); + break; + case POOL_ALPHA_MASK: + poolp = new LLDrawPoolAlphaMask(); + break; + case POOL_FULLBRIGHT_ALPHA_MASK: + poolp = new LLDrawPoolFullbrightAlphaMask(); + break; + case POOL_FULLBRIGHT: + poolp = new LLDrawPoolFullbright(); + break; + case POOL_GLOW: + poolp = new LLDrawPoolGlow(); + break; + case POOL_ALPHA_PRE_WATER: + poolp = new LLDrawPoolAlpha(LLDrawPool::POOL_ALPHA_PRE_WATER); + break; case POOL_ALPHA_POST_WATER: poolp = new LLDrawPoolAlpha(LLDrawPool::POOL_ALPHA_POST_WATER); break; - case POOL_AVATAR: - case POOL_CONTROL_AV: - poolp = new LLDrawPoolAvatar(type); - break; - case POOL_TREE: - poolp = new LLDrawPoolTree(tex0); - break; - case POOL_TERRAIN: - poolp = new LLDrawPoolTerrain(tex0); - break; - case POOL_SKY: - poolp = new LLDrawPoolSky(); - break; - case POOL_VOIDWATER: - case POOL_WATER: - poolp = new LLDrawPoolWater(); - break; - case POOL_BUMP: - poolp = new LLDrawPoolBump(); - break; - case POOL_MATERIALS: - poolp = new LLDrawPoolMaterials(); - break; - case POOL_WL_SKY: - poolp = new LLDrawPoolWLSky(); - break; - case POOL_GLTF_PBR: - poolp = new LLDrawPoolGLTFPBR(); + case POOL_AVATAR: + case POOL_CONTROL_AV: + poolp = new LLDrawPoolAvatar(type); + break; + case POOL_TREE: + poolp = new LLDrawPoolTree(tex0); + break; + case POOL_TERRAIN: + poolp = new LLDrawPoolTerrain(tex0); + break; + case POOL_SKY: + poolp = new LLDrawPoolSky(); + break; + case POOL_VOIDWATER: + case POOL_WATER: + poolp = new LLDrawPoolWater(); + break; + case POOL_BUMP: + poolp = new LLDrawPoolBump(); + break; + case POOL_MATERIALS: + poolp = new LLDrawPoolMaterials(); + break; + case POOL_WL_SKY: + poolp = new LLDrawPoolWLSky(); + break; + case POOL_GLTF_PBR: + poolp = new LLDrawPoolGLTFPBR(); break; case POOL_GLTF_PBR_ALPHA_MASK: poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK); - break; - default: - LL_ERRS() << "Unknown draw pool type!" << LL_ENDL; - return NULL; - } + break; + default: + LL_ERRS() << "Unknown draw pool type!" << LL_ENDL; + return NULL; + } - llassert(poolp->mType == type); - return poolp; + llassert(poolp->mType == type); + return poolp; } LLDrawPool::LLDrawPool(const U32 type) { - mType = type; - sNumDrawPools++; - mId = sNumDrawPools; - mShaderLevel = 0; - mSkipRender = false; + mType = type; + sNumDrawPools++; + mId = sNumDrawPools; + mShaderLevel = 0; + mSkipRender = false; } LLDrawPool::~LLDrawPool() @@ -144,7 +144,7 @@ LLDrawPool::~LLDrawPool() LLViewerTexture *LLDrawPool::getDebugTexture() { - return NULL; + return NULL; } //virtual @@ -152,55 +152,55 @@ void LLDrawPool::beginRenderPass( S32 pass ) { } -//virtual -S32 LLDrawPool::getNumPasses() +//virtual +S32 LLDrawPool::getNumPasses() { - return 1; + return 1; } - -//virtual + +//virtual void LLDrawPool::beginDeferredPass(S32 pass) { } -//virtual +//virtual void LLDrawPool::endDeferredPass(S32 pass) { } -//virtual +//virtual S32 LLDrawPool::getNumDeferredPasses() { - return 0; + return 0; } -//virtual +//virtual void LLDrawPool::renderDeferred(S32 pass) { } -//virtual +//virtual void LLDrawPool::beginPostDeferredPass(S32 pass) { } -//virtual +//virtual void LLDrawPool::endPostDeferredPass(S32 pass) { } -//virtual +//virtual S32 LLDrawPool::getNumPostDeferredPasses() { - return 0; + return 0; } -//virtual +//virtual void LLDrawPool::renderPostDeferred(S32 pass) { @@ -209,29 +209,29 @@ void LLDrawPool::renderPostDeferred(S32 pass) //virtual void LLDrawPool::endRenderPass( S32 pass ) { - //make sure channel 0 is active channel - gGL.getTexUnit(0)->activate(); + //make sure channel 0 is active channel + gGL.getTexUnit(0)->activate(); } -//virtual +//virtual void LLDrawPool::beginShadowPass(S32 pass) { } -//virtual +//virtual void LLDrawPool::endShadowPass(S32 pass) { } -//virtual +//virtual S32 LLDrawPool::getNumShadowPasses() { - return 0; + return 0; } -//virtual +//virtual void LLDrawPool::renderShadow(S32 pass) { @@ -243,20 +243,20 @@ void LLDrawPool::renderShadow(S32 pass) LLFacePool::LLFacePool(const U32 type) : LLDrawPool(type) { - resetDrawOrders(); + resetDrawOrders(); } LLFacePool::~LLFacePool() { - destroy(); + destroy(); } void LLFacePool::destroy() { - if (!mReferences.empty()) - { - LL_INFOS() << mReferences.size() << " references left on deletion of draw pool!" << LL_ENDL; - } + if (!mReferences.empty()) + { + LL_INFOS() << mReferences.size() << " references left on deletion of draw pool!" << LL_ENDL; + } } void LLFacePool::dirtyTextures(const std::set& textures) @@ -265,59 +265,59 @@ void LLFacePool::dirtyTextures(const std::set& textures void LLFacePool::enqueue(LLFace* facep) { - mDrawFace.push_back(facep); + mDrawFace.push_back(facep); } // virtual BOOL LLFacePool::addFace(LLFace *facep) { - addFaceReference(facep); - return TRUE; + addFaceReference(facep); + return TRUE; } // virtual BOOL LLFacePool::removeFace(LLFace *facep) { - removeFaceReference(facep); + removeFaceReference(facep); - vector_replace_with_last(mDrawFace, facep); + vector_replace_with_last(mDrawFace, facep); - return TRUE; + return TRUE; } // Not absolutely sure if we should be resetting all of the chained pools as well - djs void LLFacePool::resetDrawOrders() { - mDrawFace.resize(0); + mDrawFace.resize(0); } LLViewerTexture *LLFacePool::getTexture() { - return NULL; + return NULL; } void LLFacePool::removeFaceReference(LLFace *facep) { - if (facep->getReferenceIndex() != -1) - { - if (facep->getReferenceIndex() != (S32)mReferences.size()) - { - LLFace *back = mReferences.back(); - mReferences[facep->getReferenceIndex()] = back; - back->setReferenceIndex(facep->getReferenceIndex()); - } - mReferences.pop_back(); - } - facep->setReferenceIndex(-1); + if (facep->getReferenceIndex() != -1) + { + if (facep->getReferenceIndex() != (S32)mReferences.size()) + { + LLFace *back = mReferences.back(); + mReferences[facep->getReferenceIndex()] = back; + back->setReferenceIndex(facep->getReferenceIndex()); + } + mReferences.pop_back(); + } + facep->setReferenceIndex(-1); } void LLFacePool::addFaceReference(LLFace *facep) { - if (-1 == facep->getReferenceIndex()) - { - facep->setReferenceIndex(mReferences.size()); - mReferences.push_back(facep); - } + if (-1 == facep->getReferenceIndex()) + { + facep->setReferenceIndex(mReferences.size()); + mReferences.push_back(facep); + } } void LLFacePool::pushFaceGeometry() @@ -330,47 +330,47 @@ void LLFacePool::pushFaceGeometry() BOOL LLFacePool::verify() const { - BOOL ok = TRUE; - - for (std::vector::const_iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - const LLFace* facep = *iter; - if (facep->getPool() != this) - { - LL_INFOS() << "Face in wrong pool!" << LL_ENDL; - facep->printDebugInfo(); - ok = FALSE; - } - else if (!facep->verify()) - { - ok = FALSE; - } - } - - return ok; + BOOL ok = TRUE; + + for (std::vector::const_iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + const LLFace* facep = *iter; + if (facep->getPool() != this) + { + LL_INFOS() << "Face in wrong pool!" << LL_ENDL; + facep->printDebugInfo(); + ok = FALSE; + } + else if (!facep->verify()) + { + ok = FALSE; + } + } + + return ok; } void LLFacePool::printDebugInfo() const { - LL_INFOS() << "Pool " << this << " Type: " << getType() << LL_ENDL; + LL_INFOS() << "Pool " << this << " Type: " << getType() << LL_ENDL; } BOOL LLFacePool::LLOverrideFaceColor::sOverrideFaceColor = FALSE; void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4& color) { - gGL.diffuseColor4fv(color.mV); + gGL.diffuseColor4fv(color.mV); } void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4U& color) { - glColor4ubv(color.mV); + glColor4ubv(color.mV); } void LLFacePool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) { - gGL.diffuseColor4f(r,g,b,a); + gGL.diffuseColor4f(r,g,b,a); } @@ -391,16 +391,16 @@ LLRenderPass::~LLRenderPass() void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, bool texture) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo *pparams = *k; - if (pparams) + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo *pparams = *k; + if (pparams) { pushBatch(*pparams, texture); - } - } + } + } } void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool texture) @@ -409,11 +409,11 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, bool textu LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; - + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { LLDrawInfo* pparams = *k; - if (pparams) + if (pparams) { if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash) { @@ -465,7 +465,7 @@ void LLRenderPass::pushUntexturedBatches(U32 type) void LLRenderPass::pushRiggedBatches(U32 type, bool texture, bool batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - + if (texture) { LLVOAvatar* lastAvatar = nullptr; @@ -521,13 +521,13 @@ void LLRenderPass::pushMaskBatches(U32 type, bool texture, bool batch_textures) LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; auto* begin = gPipeline.beginRenderMap(type); auto* end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_iterator i = begin; i != end; ) - { + for (LLCullResult::drawinfo_iterator i = begin; i != end; ) + { LLDrawInfo* pparams = *i; LLCullResult::increment_iterator(i, end); - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); - pushBatch(*pparams, texture, batch_textures); - } + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff); + pushBatch(*pparams, texture, batch_textures); + } } void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_textures) @@ -567,22 +567,22 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, bool texture, bool batch_text void LLRenderPass::applyModelMatrix(const LLDrawInfo& params) { - applyModelMatrix(params.mModelMatrix); + applyModelMatrix(params.mModelMatrix); } void LLRenderPass::applyModelMatrix(const LLMatrix4* model_matrix) { - if (model_matrix != gGLLastMatrix) - { - gGLLastMatrix = model_matrix; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(gGLModelView); - if (model_matrix) - { - gGL.multMatrix((GLfloat*) model_matrix->mMatrix); - } - gPipeline.mMatrixOpCount++; - } + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } } void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textures) @@ -595,51 +595,51 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textur return; } - applyModelMatrix(params); - - bool tex_setup = false; - - { - if (batch_textures && params.mTextureList.size() > 1) - { - for (U32 i = 0; i < params.mTextureList.size(); ++i) - { - if (params.mTextureList[i].notNull()) - { - gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); - } - } - } - else - { //not batching textures or batch has only 1 texture -- might need a texture matrix - if (params.mTexture.notNull()) - { - gGL.getTexUnit(0)->bindFast(params.mTexture); - if (params.mTextureMatrix) - { - tex_setup = true; - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - } - else - { - gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); - } - } - } - + applyModelMatrix(params); + + bool tex_setup = false; + + { + if (batch_textures && params.mTextureList.size() > 1) + { + for (U32 i = 0; i < params.mTextureList.size(); ++i) + { + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); + } + } + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTexture.notNull()) + { + gGL.getTexUnit(0)->bindFast(params.mTexture); + if (params.mTextureMatrix) + { + tex_setup = true; + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + else + { + gGL.getTexUnit(0)->unbindFast(LLTexUnit::TT_TEXTURE); + } + } + } + params.mVertexBuffer->setBuffer(); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - if (tex_setup) - { + if (tex_setup) + { gGL.matrixMode(LLRender::MM_TEXTURE0); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } } void LLRenderPass::pushUntexturedBatch(LLDrawInfo& params) diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index c69f386c6d..789d8d45c9 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpool.h * @brief LLDrawPool class definition * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -43,87 +43,87 @@ class LLMeshSkinInfo; class LLDrawPool { public: - static S32 sNumDrawPools; + static S32 sNumDrawPools; - enum - { - // Correspond to LLPipeline render type + enum + { + // Correspond to LLPipeline render type // Also controls render order, so passes that don't use alpha masking/blending should come before // other passes to preserve hierarchical Z for occlusion queries. Occlusion queries happen just // before grass, so grass should be the first alpha masked pool. Other ordering should be done // based on fill rate and likelihood to occlude future passes (faster, large occluders first). - // + // POOL_SKY = 1, POOL_WL_SKY, - POOL_SIMPLE, - POOL_FULLBRIGHT, - POOL_BUMP, + POOL_SIMPLE, + POOL_FULLBRIGHT, + POOL_BUMP, POOL_MATERIALS, POOL_GLTF_PBR, - POOL_TERRAIN, + POOL_TERRAIN, POOL_GRASS, POOL_GLTF_PBR_ALPHA_MASK, - POOL_TREE, - POOL_ALPHA_MASK, - POOL_FULLBRIGHT_ALPHA_MASK, - POOL_AVATAR, - POOL_CONTROL_AV, // Animesh - POOL_GLOW, - POOL_ALPHA_PRE_WATER, + POOL_TREE, + POOL_ALPHA_MASK, + POOL_FULLBRIGHT_ALPHA_MASK, + POOL_AVATAR, + POOL_CONTROL_AV, // Animesh + POOL_GLOW, + POOL_ALPHA_PRE_WATER, POOL_VOIDWATER, POOL_WATER, POOL_ALPHA_POST_WATER, POOL_ALPHA, // note there is no actual "POOL_ALPHA" but pre-water and post-water pools consume POOL_ALPHA faces - NUM_POOL_TYPES, - }; - - LLDrawPool(const U32 type); - virtual ~LLDrawPool(); - - virtual BOOL isDead() = 0; - - S32 getId() const { return mId; } - U32 getType() const { return mType; } - - BOOL getSkipRenderFlag() const { return mSkipRender;} - void setSkipRenderFlag( BOOL flag ) { mSkipRender = flag; } - - virtual LLViewerTexture *getDebugTexture(); - virtual void beginRenderPass( S32 pass ); - virtual void endRenderPass( S32 pass ); - virtual S32 getNumPasses(); - - virtual void beginDeferredPass(S32 pass); - virtual void endDeferredPass(S32 pass); - virtual S32 getNumDeferredPasses(); - virtual void renderDeferred(S32 pass = 0); - - virtual void beginPostDeferredPass(S32 pass); - virtual void endPostDeferredPass(S32 pass); - virtual S32 getNumPostDeferredPasses(); - virtual void renderPostDeferred(S32 pass = 0); - - virtual void beginShadowPass(S32 pass); - virtual void endShadowPass(S32 pass); - virtual S32 getNumShadowPasses(); - virtual void renderShadow(S32 pass = 0); + NUM_POOL_TYPES, + }; + + LLDrawPool(const U32 type); + virtual ~LLDrawPool(); + + virtual BOOL isDead() = 0; + + S32 getId() const { return mId; } + U32 getType() const { return mType; } + + BOOL getSkipRenderFlag() const { return mSkipRender;} + void setSkipRenderFlag( BOOL flag ) { mSkipRender = flag; } + + virtual LLViewerTexture *getDebugTexture(); + virtual void beginRenderPass( S32 pass ); + virtual void endRenderPass( S32 pass ); + virtual S32 getNumPasses(); + + virtual void beginDeferredPass(S32 pass); + virtual void endDeferredPass(S32 pass); + virtual S32 getNumDeferredPasses(); + virtual void renderDeferred(S32 pass = 0); + + virtual void beginPostDeferredPass(S32 pass); + virtual void endPostDeferredPass(S32 pass); + virtual S32 getNumPostDeferredPasses(); + virtual void renderPostDeferred(S32 pass = 0); + + virtual void beginShadowPass(S32 pass); + virtual void endShadowPass(S32 pass); + virtual S32 getNumShadowPasses(); + virtual void renderShadow(S32 pass = 0); virtual void render(S32 pass = 0) {}; virtual void prerender() {}; virtual U32 getVertexDataMask() { return 0; } // DEPRECATED -- draw pool doesn't actually determine vertex data mask any more - virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct! - virtual S32 getShaderLevel() const { return mShaderLevel; } - - static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL); - virtual LLViewerTexture* getTexture() = 0; - virtual BOOL isFacePool() { return FALSE; } - virtual void resetDrawOrders() = 0; + virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct! + virtual S32 getShaderLevel() const { return mShaderLevel; } + + static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL); + virtual LLViewerTexture* getTexture() = 0; + virtual BOOL isFacePool() { return FALSE; } + virtual void resetDrawOrders() = 0; virtual void pushFaceGeometry() {} - S32 mShaderLevel; - S32 mId; - U32 mType; // Type of draw pool - BOOL mSkipRender; + S32 mShaderLevel; + S32 mId; + U32 mType; // Type of draw pool + BOOL mSkipRender; }; class LLRenderPass : public LLDrawPool @@ -132,77 +132,77 @@ public: // list of possible LLRenderPass types to assign a render batch to // NOTE: "rigged" variant MUST be non-rigged variant + 1 // see LLVolumeGeometryManager::registerFace() - enum - { - PASS_SIMPLE = NUM_POOL_TYPES, + enum + { + PASS_SIMPLE = NUM_POOL_TYPES, PASS_SIMPLE_RIGGED, - PASS_GRASS, - PASS_FULLBRIGHT, + PASS_GRASS, + PASS_FULLBRIGHT, PASS_FULLBRIGHT_RIGGED, - PASS_INVISIBLE, + PASS_INVISIBLE, PASS_INVISIBLE_RIGGED, - PASS_INVISI_SHINY, + PASS_INVISI_SHINY, PASS_INVISI_SHINY_RIGGED, - PASS_FULLBRIGHT_SHINY, + PASS_FULLBRIGHT_SHINY, PASS_FULLBRIGHT_SHINY_RIGGED, - PASS_SHINY, + PASS_SHINY, PASS_SHINY_RIGGED, - PASS_BUMP, + PASS_BUMP, PASS_BUMP_RIGGED, - PASS_POST_BUMP, + PASS_POST_BUMP, PASS_POST_BUMP_RIGGED, - PASS_MATERIAL, + PASS_MATERIAL, PASS_MATERIAL_RIGGED, - PASS_MATERIAL_ALPHA, + PASS_MATERIAL_ALPHA, PASS_MATERIAL_ALPHA_RIGGED, - PASS_MATERIAL_ALPHA_MASK, // Diffuse texture used as alpha mask + PASS_MATERIAL_ALPHA_MASK, // Diffuse texture used as alpha mask PASS_MATERIAL_ALPHA_MASK_RIGGED, - PASS_MATERIAL_ALPHA_EMISSIVE, + PASS_MATERIAL_ALPHA_EMISSIVE, PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, - PASS_SPECMAP, + PASS_SPECMAP, PASS_SPECMAP_RIGGED, - PASS_SPECMAP_BLEND, + PASS_SPECMAP_BLEND, PASS_SPECMAP_BLEND_RIGGED, - PASS_SPECMAP_MASK, // Diffuse texture used as alpha mask and specular texture(map) + PASS_SPECMAP_MASK, // Diffuse texture used as alpha mask and specular texture(map) PASS_SPECMAP_MASK_RIGGED, - PASS_SPECMAP_EMISSIVE, + PASS_SPECMAP_EMISSIVE, PASS_SPECMAP_EMISSIVE_RIGGED, - PASS_NORMMAP, + PASS_NORMMAP, PASS_NORMMAP_RIGGED, - PASS_NORMMAP_BLEND, + PASS_NORMMAP_BLEND, PASS_NORMMAP_BLEND_RIGGED, - PASS_NORMMAP_MASK, // Diffuse texture used as alpha mask and normal map + PASS_NORMMAP_MASK, // Diffuse texture used as alpha mask and normal map PASS_NORMMAP_MASK_RIGGED, - PASS_NORMMAP_EMISSIVE, + PASS_NORMMAP_EMISSIVE, PASS_NORMMAP_EMISSIVE_RIGGED, - PASS_NORMSPEC, + PASS_NORMSPEC, PASS_NORMSPEC_RIGGED, - PASS_NORMSPEC_BLEND, + PASS_NORMSPEC_BLEND, PASS_NORMSPEC_BLEND_RIGGED, - PASS_NORMSPEC_MASK, // Diffuse texture used as alpha mask with normal and specular map + PASS_NORMSPEC_MASK, // Diffuse texture used as alpha mask with normal and specular map PASS_NORMSPEC_MASK_RIGGED, - PASS_NORMSPEC_EMISSIVE, + PASS_NORMSPEC_EMISSIVE, PASS_NORMSPEC_EMISSIVE_RIGGED, - PASS_GLOW, + PASS_GLOW, PASS_GLOW_RIGGED, PASS_GLTF_GLOW, PASS_GLTF_GLOW_RIGGED, - PASS_ALPHA, + PASS_ALPHA, PASS_ALPHA_RIGGED, - PASS_ALPHA_MASK, + PASS_ALPHA_MASK, PASS_ALPHA_MASK_RIGGED, - PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright + PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, - PASS_ALPHA_INVISIBLE, + PASS_ALPHA_INVISIBLE, PASS_ALPHA_INVISIBLE_RIGGED, PASS_GLTF_PBR, PASS_GLTF_PBR_RIGGED, PASS_GLTF_PBR_ALPHA_MASK, PASS_GLTF_PBR_ALPHA_MASK_RIGGED, - NUM_RENDER_TYPES, - }; + NUM_RENDER_TYPES, + }; - #ifdef LL_PROFILER_ENABLE_RENDER_DOC + #ifdef LL_PROFILER_ENABLE_RENDER_DOC static inline const char* lookupPassName(U32 pass) { switch (pass) @@ -336,22 +336,22 @@ public: default: return "Unknown pass"; } - } - #else + } + #else static inline const char* lookupPass(U32 pass) { return ""; } - #endif + #endif - LLRenderPass(const U32 type); - virtual ~LLRenderPass(); - /*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; } - LLViewerTexture* getTexture() { return NULL; } - BOOL isDead() { return FALSE; } - void resetDrawOrders() { } + LLRenderPass(const U32 type); + virtual ~LLRenderPass(); + /*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; } + LLViewerTexture* getTexture() { return NULL; } + BOOL isDead() { return FALSE; } + void resetDrawOrders() { } - static void applyModelMatrix(const LLDrawInfo& params); + static void applyModelMatrix(const LLDrawInfo& params); // For rendering that doesn't use LLDrawInfo for some reason - static void applyModelMatrix(const LLMatrix4* model_matrix); - void pushBatches(U32 type, bool texture = true, bool batch_textures = false); + static void applyModelMatrix(const LLMatrix4* model_matrix); + void pushBatches(U32 type, bool texture = true, bool batch_textures = false); void pushUntexturedBatches(U32 type); void pushRiggedBatches(U32 type, bool texture = true, bool batch_textures = false); @@ -379,104 +379,104 @@ public: static void pushUntexturedGLTFBatch(LLDrawInfo& params); static void pushUntexturedRiggedGLTFBatch(LLDrawInfo& params, LLVOAvatar*& lastAvatar, U64& lastMeshId); - void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false); + void pushMaskBatches(U32 type, bool texture = true, bool batch_textures = false); void pushRiggedMaskBatches(U32 type, bool texture = true, bool batch_textures = false); - void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false); + void pushBatch(LLDrawInfo& params, bool texture, bool batch_textures = false); void pushUntexturedBatch(LLDrawInfo& params); - void pushBumpBatch(LLDrawInfo& params, bool texture, bool batch_textures = false); + void pushBumpBatch(LLDrawInfo& params, bool texture, bool batch_textures = false); static bool uploadMatrixPalette(LLDrawInfo& params); static bool uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo); - virtual void renderGroup(LLSpatialGroup* group, U32 type, bool texture = true); + virtual void renderGroup(LLSpatialGroup* group, U32 type, bool texture = true); virtual void renderRiggedGroup(LLSpatialGroup* group, U32 type, bool texture = true); }; class LLFacePool : public LLDrawPool { public: - typedef std::vector face_array_t; - - enum - { - SHADER_LEVEL_SCATTERING = 2 - }; + typedef std::vector face_array_t; + + enum + { + SHADER_LEVEL_SCATTERING = 2 + }; public: - LLFacePool(const U32 type); - virtual ~LLFacePool(); - - BOOL isDead() { return mReferences.empty(); } - - virtual LLViewerTexture *getTexture(); - virtual void dirtyTextures(const std::set& textures); + LLFacePool(const U32 type); + virtual ~LLFacePool(); + + BOOL isDead() { return mReferences.empty(); } + + virtual LLViewerTexture *getTexture(); + virtual void dirtyTextures(const std::set& textures); + + virtual void enqueue(LLFace *face); + virtual BOOL addFace(LLFace *face); + virtual BOOL removeFace(LLFace *face); - virtual void enqueue(LLFace *face); - virtual BOOL addFace(LLFace *face); - virtual BOOL removeFace(LLFace *face); + virtual BOOL verify() const; // Verify that all data in the draw pool is correct! - virtual BOOL verify() const; // Verify that all data in the draw pool is correct! - - virtual void resetDrawOrders(); - void resetAll(); + virtual void resetDrawOrders(); + void resetAll(); - void destroy(); + void destroy(); - void buildEdges(); + void buildEdges(); - void addFaceReference(LLFace *facep); - void removeFaceReference(LLFace *facep); + void addFaceReference(LLFace *facep); + void removeFaceReference(LLFace *facep); - void printDebugInfo() const; - - BOOL isFacePool() { return TRUE; } + void printDebugInfo() const; + + BOOL isFacePool() { return TRUE; } // call drawIndexed on every draw face void pushFaceGeometry(); - friend class LLFace; - friend class LLPipeline; + friend class LLFace; + friend class LLPipeline; public: - face_array_t mDrawFace; - face_array_t mMoveFace; - face_array_t mReferences; + face_array_t mDrawFace; + face_array_t mMoveFace; + face_array_t mReferences; public: - class LLOverrideFaceColor - { - public: - LLOverrideFaceColor(LLDrawPool* pool) - : mOverride(sOverrideFaceColor), mPool(pool) - { - sOverrideFaceColor = TRUE; - } - LLOverrideFaceColor(LLDrawPool* pool, const LLColor4& color) - : mOverride(sOverrideFaceColor), mPool(pool) - { - sOverrideFaceColor = TRUE; - setColor(color); - } - LLOverrideFaceColor(LLDrawPool* pool, const LLColor4U& color) - : mOverride(sOverrideFaceColor), mPool(pool) - { - sOverrideFaceColor = TRUE; - setColor(color); - } - LLOverrideFaceColor(LLDrawPool* pool, F32 r, F32 g, F32 b, F32 a) - : mOverride(sOverrideFaceColor), mPool(pool) - { - sOverrideFaceColor = TRUE; - setColor(r, g, b, a); - } - ~LLOverrideFaceColor() - { - sOverrideFaceColor = mOverride; - } - void setColor(const LLColor4& color); - void setColor(const LLColor4U& color); - void setColor(F32 r, F32 g, F32 b, F32 a); - BOOL mOverride; - LLDrawPool* mPool; - static BOOL sOverrideFaceColor; - }; + class LLOverrideFaceColor + { + public: + LLOverrideFaceColor(LLDrawPool* pool) + : mOverride(sOverrideFaceColor), mPool(pool) + { + sOverrideFaceColor = TRUE; + } + LLOverrideFaceColor(LLDrawPool* pool, const LLColor4& color) + : mOverride(sOverrideFaceColor), mPool(pool) + { + sOverrideFaceColor = TRUE; + setColor(color); + } + LLOverrideFaceColor(LLDrawPool* pool, const LLColor4U& color) + : mOverride(sOverrideFaceColor), mPool(pool) + { + sOverrideFaceColor = TRUE; + setColor(color); + } + LLOverrideFaceColor(LLDrawPool* pool, F32 r, F32 g, F32 b, F32 a) + : mOverride(sOverrideFaceColor), mPool(pool) + { + sOverrideFaceColor = TRUE; + setColor(r, g, b, a); + } + ~LLOverrideFaceColor() + { + sOverrideFaceColor = mOverride; + } + void setColor(const LLColor4& color); + void setColor(const LLColor4U& color); + void setColor(F32 r, F32 g, F32 b, F32 a); + BOOL mOverride; + LLDrawPool* mPool; + static BOOL sOverrideFaceColor; + }; }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index fd27010877..60cfe9440d 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpoolalpha.cpp * @brief LLDrawPoolAlpha class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -39,7 +39,7 @@ #include "lldrawable.h" #include "llface.h" #include "llviewercamera.h" -#include "llviewertexturelist.h" // For debugging +#include "llviewertexturelist.h" // For debugging #include "llviewerobjectlist.h" // For debugging #include "llviewerwindow.h" #include "pipeline.h" @@ -66,11 +66,11 @@ static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255 static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f; LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : - LLRenderPass(type), target_shader(NULL), - mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), - mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) + LLRenderPass(type), target_shader(NULL), + mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF), + mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF) { - + } LLDrawPoolAlpha::~LLDrawPoolAlpha() @@ -80,15 +80,15 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha() void LLDrawPoolAlpha::prerender() { - mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); // TODO: is this even necessay? These are probably set to never discard LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(1024.f*1024.f); LLViewerFetchedTexture::sWhiteImagep->addTextureStats(1024.f * 1024.f); } -S32 LLDrawPoolAlpha::getNumPostDeferredPasses() -{ +S32 LLDrawPoolAlpha::getNumPostDeferredPasses() +{ return 1; } @@ -108,7 +108,7 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d { shader->mCanBindFast = false; } - + shader->bind(); shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f)); @@ -139,15 +139,15 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d //also prepare rigged variant if (shader->mRiggedVariant && shader->mRiggedVariant != shader) - { + { prepare_alpha_shader(shader->mRiggedVariant, textureGamma, deferredEnvironment, water_sign); } } extern BOOL gCubeSnapshot; -void LLDrawPoolAlpha::renderPostDeferred(S32 pass) -{ +void LLDrawPoolAlpha::renderPostDeferred(S32 pass) +{ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; if (LLPipeline::isWaterClip() && getType() == LLDrawPool::POOL_ALPHA_PRE_WATER) @@ -177,13 +177,13 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) prepare_alpha_shader(pbr_emissive_shader, true, false, water_sign); - fullbright_shader = + fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightAlphaMaskProgram : (LLPipeline::sRenderingHUDs) ? &gHUDFullbrightAlphaMaskAlphaProgram : &gDeferredFullbrightAlphaMaskAlphaProgram; prepare_alpha_shader(fullbright_shader, true, true, water_sign); - simple_shader = + simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram : (LLPipeline::sRenderingHUDs) ? &gHUDAlphaProgram : &gDeferredAlphaProgram; @@ -196,8 +196,8 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) prepare_alpha_shader(&materialShader[i], false, true, water_sign); } - pbr_shader = - (LLPipeline::sRenderingHUDs) ? &gHUDPBRAlphaProgram : + pbr_shader = + (LLPipeline::sRenderingHUDs) ? &gHUDPBRAlphaProgram : &gDeferredPBRAlphaProgram; prepare_alpha_shader(pbr_shader, false, true, water_sign); @@ -217,7 +217,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) // final pass, render to depth for depth of field effects if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField") && !gCubeSnapshot && !LLPipeline::sRenderingHUDs && getType() == LLDrawPool::POOL_ALPHA_POST_WATER) - { + { //update depth buffer sampler simple_shader = fullbright_shader = &gDeferredFullbrightAlphaMaskProgram; @@ -229,7 +229,7 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass) // If the face is more than 90% transparent, then don't update the Depth buffer for Dof // We don't want the nearly invisible objects to cause of DoF effects - renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, true); // <--- discard mostly transparent faces gGL.setColorMask(true, false); @@ -287,8 +287,8 @@ void LLDrawPoolAlpha::forwardRender(bool rigged) void LLDrawPoolAlpha::renderDebugAlpha() { - if (sShowDebugAlpha) - { + if (sShowDebugAlpha) + { gHighlightProgram.bind(); gGL.diffuseColor4f(1, 0, 0, 1); gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::getSmokeImage()); @@ -296,19 +296,19 @@ void LLDrawPoolAlpha::renderDebugAlpha() renderAlphaHighlight(); - pushUntexturedBatches(LLRenderPass::PASS_ALPHA_MASK); - pushUntexturedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE); + pushUntexturedBatches(LLRenderPass::PASS_ALPHA_MASK); + pushUntexturedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE); - // Material alpha mask - gGL.diffuseColor4f(0, 0, 1, 1); - pushUntexturedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK); - pushUntexturedBatches(LLRenderPass::PASS_NORMMAP_MASK); - pushUntexturedBatches(LLRenderPass::PASS_SPECMAP_MASK); - pushUntexturedBatches(LLRenderPass::PASS_NORMSPEC_MASK); - pushUntexturedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + // Material alpha mask + gGL.diffuseColor4f(0, 0, 1, 1); + pushUntexturedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK); + pushUntexturedBatches(LLRenderPass::PASS_NORMMAP_MASK); + pushUntexturedBatches(LLRenderPass::PASS_SPECMAP_MASK); + pushUntexturedBatches(LLRenderPass::PASS_NORMSPEC_MASK); + pushUntexturedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); pushUntexturedBatches(LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK); - gGL.diffuseColor4f(0, 1, 0, 1); + gGL.diffuseColor4f(0, 1, 0, 1); pushUntexturedBatches(LLRenderPass::PASS_INVISIBLE); gHighlightProgram.mRiggedVariant->bind(); @@ -329,7 +329,7 @@ void LLDrawPoolAlpha::renderDebugAlpha() gGL.diffuseColor4f(0, 1, 0, 1); pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, false); LLGLSLShader::sCurBoundShaderPtr->unbind(); - } + } } void LLDrawPoolAlpha::renderAlphaHighlight() @@ -348,7 +348,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight() if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA+pass]; // <-- hacky + pass to use PASS_ALPHA_RIGGED on second pass for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) { @@ -403,7 +403,7 @@ inline void Draw(LLDrawInfo* draw, U32 mask) { draw->mVertexBuffer->setBuffer(); LLRenderPass::applyModelMatrix(*draw); - draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); + draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material) @@ -485,19 +485,19 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material) void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup) { if (tex_setup) - { - gGL.getTexUnit(0)->activate(); + { + gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } } void LLDrawPoolAlpha::drawEmissive(LLDrawInfo* draw) { LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f); draw->mVertexBuffer->setBuffer(); - draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); + draw->mVertexBuffer->drawRange(LLRender::TRIANGLES, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset); } @@ -561,7 +561,7 @@ void LLDrawPoolAlpha::renderRiggedPbrEmissives(std::vector& emissiv { LLGLDepthTest depth(GL_TRUE, GL_FALSE); //disable depth writes since "emissive" is additive so sorting doesn't matter pbr_emissive_shader->bind(true); - + LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; @@ -588,7 +588,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; BOOL initialized_lighting = FALSE; - BOOL light_enabled = TRUE; + BOOL light_enabled = TRUE; LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; @@ -607,7 +607,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) begin = gPipeline.beginAlphaGroups(); end = gPipeline.endAlphaGroups(); } - + LLEnvironment& env = LLEnvironment::instance(); F32 water_height = env.getWaterHeight(); @@ -619,15 +619,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) for (LLCullResult::sg_iterator i = begin; i != end; ++i) - { + { LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("renderAlpha - group"); - LLSpatialGroup* group = *i; - llassert(group); - llassert(group->getSpatialPartition()); + LLSpatialGroup* group = *i; + llassert(group); + llassert(group->getSpatialPartition()); - if (group->getSpatialPartition()->mRenderByGroup && - !group->isDead()) - { + if (group->getSpatialPartition()->mRenderByGroup && + !group->isDead()) + { LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); const LLVector4a* ext = bridge ? bridge->getSpatialExtents() : group->getExtents(); @@ -660,17 +660,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) pbr_emissives.resize(0); pbr_rigged_emissives.resize(0); - bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE - || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE + || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; - bool disable_cull = is_particle_or_hud_particle; - LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); + bool disable_cull = is_particle_or_hud_particle; + LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0); - LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; + LLSpatialGroup::drawmap_elem_t& draw_info = rigged ? group->mDrawMap[LLRenderPass::PASS_ALPHA_RIGGED] : group->mDrawMap[LLRenderPass::PASS_ALPHA]; for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; + { + LLDrawInfo& params = **k; if ((bool)params.mAvatar != rigged) { continue; @@ -681,7 +681,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) LLRenderPass::applyModelMatrix(params); LLMaterial* mat = NULL; - LLGLTFMaterial *gltf_mat = params.mGLTFMaterial; + LLGLTFMaterial *gltf_mat = params.mGLTFMaterial; LLGLDisable cull_face(gltf_mat && gltf_mat->mDoubleSided ? GL_CULL_FACE : 0); @@ -803,8 +803,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) bool tex_setup = TexSetup(¶ms, (mat != nullptr)); - { - gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); + { + gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); bool reset_minimum_alpha = false; if (!LLPipeline::sImpostorRender && @@ -823,12 +823,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { current_shader->setMinimumAlpha(MINIMUM_ALPHA); } - } + } - // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha. - if (getType() != LLDrawPool::POOL_ALPHA_PRE_WATER && - params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) - { + // If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha. + if (getType() != LLDrawPool::POOL_ALPHA_PRE_WATER && + params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE)) + { if (params.mAvatar != nullptr) { if (params.mGLTFMaterial.isNull()) @@ -851,16 +851,16 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) pbr_emissives.push_back(¶ms); } } - } - - if (tex_setup) - { - gGL.getTexUnit(0)->activate(); + } + + if (tex_setup) + { + gGL.getTexUnit(0)->activate(); gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - } + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + } // render emissive faces into alpha channel for bloom effects if (!depth_only) @@ -909,17 +909,17 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) lastShader->bind(); } } - } - } + } + } - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - if (!light_enabled) - { - gPipeline.enableLightsDynamic(); - } + if (!light_enabled) + { + gPipeline.enableLightsDynamic(); + } } bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 24df11c158..eec17149e7 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpoolbump.cpp * @brief LLDrawPoolBump class implementation * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -54,7 +54,7 @@ //#include "../tools/imdebug/imdebug.h" // static -LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; +LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT]; LL::WorkQueue::weak_t LLBumpImageList::sMainQueue; LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue; LLRenderTarget LLBumpImageList::sRenderTarget; @@ -84,13 +84,13 @@ static BOOL shiny = FALSE; #define LL_BUMPLIST_MULTITHREADED 1 -// static +// static void LLStandardBumpmap::shutdown() { - LLStandardBumpmap::destroyGL(); + LLStandardBumpmap::destroyGL(); } -// static +// static void LLStandardBumpmap::restoreGL() { addstandard(); @@ -99,12 +99,12 @@ void LLStandardBumpmap::restoreGL() // static void LLStandardBumpmap::addstandard() { - if(!gTextureList.isInitialized()) - { - //Note: loading pre-configuration sometimes triggers this call. - //But it is safe to return here because bump images will be reloaded during initialization later. - return ; - } + if(!gTextureList.isInitialized()) + { + //Note: loading pre-configuration sometimes triggers this call. + //But it is safe to return here because bump images will be reloaded during initialization later. + return ; + } if (LLStartUp::getStartupState() < STATE_SEED_CAP_GRANTED) { @@ -112,99 +112,99 @@ void LLStandardBumpmap::addstandard() return; } - // can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup. Sigh. So clear the list every time before we (re-)add the standard bumpmaps. - //llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 ); - clear(); - LL_INFOS() << "Adding standard bumpmaps." << LL_ENDL; - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None"); // BE_NO_BUMP - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness"); // BE_BRIGHTNESS - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS - - std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" ); - LLFILE* file = LLFile::fopen( file_name, "rt" ); /*Flawfinder: ignore*/ - if( !file ) - { - LL_WARNS() << "Could not open std_bump <" << file_name << ">" << LL_ENDL; - return; - } - - S32 file_version = 0; - - S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version ); - if( fields_read != 1 ) - { - LL_WARNS() << "Bad LLStandardBumpmap header" << LL_ENDL; - return; - } - - if( file_version > STD_BUMP_LATEST_FILE_VERSION ) - { - LL_WARNS() << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << LL_ENDL; - return; - } - - while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) ) - { - // *NOTE: This buffer size is hard coded into scanf() below. - char label[2048] = ""; /* Flawfinder: ignore */ - char bump_image_id[2048] = ""; /* Flawfinder: ignore */ - fields_read = fscanf( /* Flawfinder: ignore */ - file, "\n%2047s %2047s", label, bump_image_id); - if( EOF == fields_read ) - { - break; - } - if( fields_read != 2 ) - { - LL_WARNS() << "Bad LLStandardBumpmap entry" << LL_ENDL; - return; - } - -// LL_INFOS() << "Loading bumpmap: " << bump_image_id << " from viewerart" << LL_ENDL; - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = - LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLGLTexture::LOCAL) ; - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); - gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0, 30.f) ; - LLStandardBumpmap::sStandardBumpmapCount++; - } - - fclose( file ); + // can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup. Sigh. So clear the list every time before we (re-)add the standard bumpmaps. + //llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 ); + clear(); + LL_INFOS() << "Adding standard bumpmaps." << LL_ENDL; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("None"); // BE_NO_BUMP + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Brightness"); // BE_BRIGHTNESS + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS + + std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" ); + LLFILE* file = LLFile::fopen( file_name, "rt" ); /*Flawfinder: ignore*/ + if( !file ) + { + LL_WARNS() << "Could not open std_bump <" << file_name << ">" << LL_ENDL; + return; + } + + S32 file_version = 0; + + S32 fields_read = fscanf( file, "LLStandardBumpmap version %d", &file_version ); + if( fields_read != 1 ) + { + LL_WARNS() << "Bad LLStandardBumpmap header" << LL_ENDL; + return; + } + + if( file_version > STD_BUMP_LATEST_FILE_VERSION ) + { + LL_WARNS() << "LLStandardBumpmap has newer version (" << file_version << ") than viewer (" << STD_BUMP_LATEST_FILE_VERSION << ")" << LL_ENDL; + return; + } + + while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) ) + { + // *NOTE: This buffer size is hard coded into scanf() below. + char label[2048] = ""; /* Flawfinder: ignore */ + char bump_image_id[2048] = ""; /* Flawfinder: ignore */ + fields_read = fscanf( /* Flawfinder: ignore */ + file, "\n%2047s %2047s", label, bump_image_id); + if( EOF == fields_read ) + { + break; + } + if( fields_read != 2 ) + { + LL_WARNS() << "Bad LLStandardBumpmap entry" << LL_ENDL; + return; + } + +// LL_INFOS() << "Loading bumpmap: " << bump_image_id << " from viewerart" << LL_ENDL; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = + LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLGLTexture::LOCAL) ; + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0, 30.f) ; + LLStandardBumpmap::sStandardBumpmapCount++; + } + + fclose( file ); } // static void LLStandardBumpmap::clear() { - LL_INFOS() << "Clearing standard bumpmaps." << LL_ENDL; - for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ ) - { - gStandardBumpmapList[i].mLabel.assign(""); - gStandardBumpmapList[i].mImage = NULL; - } - sStandardBumpmapCount = 0; + LL_INFOS() << "Clearing standard bumpmaps." << LL_ENDL; + for( U32 i = 0; i < LLStandardBumpmap::sStandardBumpmapCount; i++ ) + { + gStandardBumpmapList[i].mLabel.assign(""); + gStandardBumpmapList[i].mImage = NULL; + } + sStandardBumpmapCount = 0; } // static void LLStandardBumpmap::destroyGL() { - clear(); + clear(); } //////////////////////////////////////////////////////////////// -LLDrawPoolBump::LLDrawPoolBump() +LLDrawPoolBump::LLDrawPoolBump() : LLRenderPass(LLDrawPool::POOL_BUMP) { - shiny = FALSE; + shiny = FALSE; } void LLDrawPoolBump::prerender() { - mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); + mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } // static @@ -217,88 +217,88 @@ S32 LLDrawPoolBump::numBumpPasses() //static void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - if( cube_map && !LLPipeline::sReflectionProbesEnabled ) - { - if (shader ) - { - LLMatrix4 mat; - mat.initRows(LLVector4(gGLModelView+0), - LLVector4(gGLModelView+4), - LLVector4(gGLModelView+8), - LLVector4(gGLModelView+12)); - LLVector3 vec = LLVector3(gShinyOrigin) * mat; - LLVector4 vec4(vec, gShinyOrigin.mV[3]); - shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); - if (shader_level > 1) - { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if( cube_map && !LLPipeline::sReflectionProbesEnabled ) + { + if (shader ) + { + LLMatrix4 mat; + mat.initRows(LLVector4(gGLModelView+0), + LLVector4(gGLModelView+4), + LLVector4(gGLModelView+8), + LLVector4(gGLModelView+12)); + LLVector3 vec = LLVector3(gShinyOrigin) * mat; + LLVector4 vec4(vec, gShinyOrigin.mV[3]); + shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); + if (shader_level > 1) + { cube_map->setMatrix(1); - // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for - // the cube map in the one pass shiny shaders - cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - cube_map->enableTexture(cube_channel); - diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - else - { + // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for + // the cube map in the one pass shiny shaders + cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + cube_map->enableTexture(cube_channel); + diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } + else + { cube_map->setMatrix(0); - cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - diffuse_channel = -1; - cube_map->enable(cube_channel); - } - gGL.getTexUnit(cube_channel)->bind(cube_map); - gGL.getTexUnit(0)->activate(); - } - else - { - cube_channel = 0; - diffuse_channel = -1; - gGL.getTexUnit(0)->disable(); - cube_map->enable(0); + cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + diffuse_channel = -1; + cube_map->enable(cube_channel); + } + gGL.getTexUnit(cube_channel)->bind(cube_map); + gGL.getTexUnit(0)->activate(); + } + else + { + cube_channel = 0; + diffuse_channel = -1; + gGL.getTexUnit(0)->disable(); + cube_map->enable(0); cube_map->setMatrix(0); - gGL.getTexUnit(0)->bind(cube_map); - } - } + gGL.getTexUnit(0)->bind(cube_map); + } + } } //static void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel) { - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - if( cube_map && !LLPipeline::sReflectionProbesEnabled) - { - if (shader_level > 1) - { - shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) - { - if (diffuse_channel != 0) - { - shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - } - } + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if( cube_map && !LLPipeline::sReflectionProbesEnabled) + { + if (shader_level > 1) + { + shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0) + { + if (diffuse_channel != 0) + { + shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + } + } + } // Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0 // MAINT-755 - cube_map->disable(); + cube_map->disable(); cube_map->restoreMatrix(); - } + } } void LLDrawPoolBump::beginFullbrightShiny() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - - sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; - // Second pass: environment map - shader = &gDeferredFullbrightShinyProgram; + sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; + + // Second pass: environment map + shader = &gDeferredFullbrightShinyProgram; if (LLPipeline::sRenderingHUDs) { shader = &gHUDFullbrightShinyProgram; } - + if (mRigged) { llassert(shader->mRiggedVariant); @@ -312,32 +312,32 @@ void LLDrawPoolBump::beginFullbrightShiny() gGL.getTexUnit(channel)->bind(&gPipeline.mExposureMap); } - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map && !LLPipeline::sReflectionProbesEnabled) { - // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for - // the cube map in the one pass shiny shaders - gGL.getTexUnit(1)->disable(); - cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - cube_map->enableTexture(cube_channel); - diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - - gGL.getTexUnit(cube_channel)->bind(cube_map); - gGL.getTexUnit(0)->activate(); + // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for + // the cube map in the one pass shiny shaders + gGL.getTexUnit(1)->disable(); + cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + cube_map->enableTexture(cube_channel); + diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + + gGL.getTexUnit(cube_channel)->bind(cube_map); + gGL.getTexUnit(0)->activate(); } - { - LLMatrix4 mat; - mat.initRows(LLVector4(gGLModelView+0), - LLVector4(gGLModelView+4), - LLVector4(gGLModelView+8), - LLVector4(gGLModelView+12)); - shader->bind(); - - LLVector3 vec = LLVector3(gShinyOrigin) * mat; - LLVector4 vec4(vec, gShinyOrigin.mV[3]); - shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); + { + LLMatrix4 mat; + mat.initRows(LLVector4(gGLModelView+0), + LLVector4(gGLModelView+4), + LLVector4(gGLModelView+8), + LLVector4(gGLModelView+12)); + shader->bind(); + + LLVector3 vec = LLVector3(gShinyOrigin) * mat; + LLVector4 vec4(vec, gShinyOrigin.mV[3]); + shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); if (LLPipeline::sReflectionProbesEnabled) { @@ -347,25 +347,25 @@ void LLDrawPoolBump::beginFullbrightShiny() { gPipeline.setEnvMat(*shader); } - } + } - if (mShaderLevel > 1) - { //indexed texture rendering, channel 0 is always diffuse - diffuse_channel = 0; - } + if (mShaderLevel > 1) + { //indexed texture rendering, channel 0 is always diffuse + diffuse_channel = 0; + } - shiny = TRUE; + shiny = TRUE; } void LLDrawPoolBump::renderFullbrightShiny() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - { - LLGLEnable blend_enable(GL_BLEND); + { + LLGLEnable blend_enable(GL_BLEND); - if (mShaderLevel > 1) - { + if (mShaderLevel > 1) + { if (mRigged) { LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, true, true); @@ -374,9 +374,9 @@ void LLDrawPoolBump::renderFullbrightShiny() { LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, true, true); } - } - else - { + } + else + { if (mRigged) { LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED); @@ -385,125 +385,125 @@ void LLDrawPoolBump::renderFullbrightShiny() { LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY); } - } - } + } + } } void LLDrawPoolBump::endFullbrightShiny() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY); - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - if( cube_map && !LLPipeline::sReflectionProbesEnabled ) - { - cube_map->disable(); + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if( cube_map && !LLPipeline::sReflectionProbesEnabled ) + { + cube_map->disable(); if (shader->mFeatures.hasReflectionProbes) { gPipeline.unbindReflectionProbes(*shader); } - shader->unbind(); - } - - diffuse_channel = -1; - cube_channel = 0; - shiny = FALSE; + shader->unbind(); + } + + diffuse_channel = -1; + cube_channel = 0; + shiny = FALSE; } void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, bool texture = true) -{ - LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; - - for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) - { - LLDrawInfo& params = **k; - - applyModelMatrix(params); - - params.mVertexBuffer->setBuffer(); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - } +{ + LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type]; + + for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo& params = **k; + + applyModelMatrix(params); + + params.mVertexBuffer->setBuffer(); + params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + } } // static BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { - U8 bump_code = params.mBump; + U8 bump_code = params.mBump; - return bindBumpMap(bump_code, params.mTexture, channel); + return bindBumpMap(bump_code, params.mTexture, channel); } //static BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) { - const LLTextureEntry* te = face->getTextureEntry(); - if (te) - { - U8 bump_code = te->getBumpmap(); - return bindBumpMap(bump_code, face->getTexture(), channel); - } - - return FALSE; + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + U8 bump_code = te->getBumpmap(); + return bindBumpMap(bump_code, face->getTexture(), channel); + } + + return FALSE; } //static BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, S32 channel) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - //Note: texture atlas does not support bump texture now. - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; - if(!tex) - { - //if the texture is not a fetched texture - return FALSE; - } - - LLViewerTexture* bump = NULL; - - switch( bump_code ) - { - case BE_NO_BUMP: - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); - break; - - default: - if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) - { - bump = gStandardBumpmapList[bump_code].mImage; - gBumpImageList.addTextureStats(bump_code, tex->getID(), tex->getMaxVirtualSize()); - } - break; - } - - if (bump) - { - if (channel == -2) - { - gGL.getTexUnit(1)->bindFast(bump); - gGL.getTexUnit(0)->bindFast(bump); - } - else - { + //Note: texture atlas does not support bump texture now. + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; + if(!tex) + { + //if the texture is not a fetched texture + return FALSE; + } + + LLViewerTexture* bump = NULL; + + switch( bump_code ) + { + case BE_NO_BUMP: + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + bump = gBumpImageList.getBrightnessDarknessImage( tex, bump_code ); + break; + + default: + if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) + { + bump = gStandardBumpmapList[bump_code].mImage; + gBumpImageList.addTextureStats(bump_code, tex->getID(), tex->getMaxVirtualSize()); + } + break; + } + + if (bump) + { + if (channel == -2) + { + gGL.getTexUnit(1)->bindFast(bump); + gGL.getTexUnit(0)->bindFast(bump); + } + else + { // NOTE: do not use bindFast here (see SL-16222) gGL.getTexUnit(channel)->bind(bump); - } + } - return TRUE; - } + return TRUE; + } - return FALSE; + return FALSE; } //static void LLDrawPoolBump::beginBump() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - sVertexMask = VERTEX_MASK_BUMP; - // Optional second pass: emboss bump map - stop_glerror(); + sVertexMask = VERTEX_MASK_BUMP; + // Optional second pass: emboss bump map + stop_glerror(); shader = &gObjectBumpProgram; @@ -515,21 +515,21 @@ void LLDrawPoolBump::beginBump() shader->bind(); - gGL.setSceneBlendType(LLRender::BT_MULT_X2); - stop_glerror(); + gGL.setSceneBlendType(LLRender::BT_MULT_X2); + stop_glerror(); } //static void LLDrawPoolBump::renderBump(U32 pass) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP); - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL); - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(1,1,1,1); - /// Get rid of z-fighting with non-bump pass. - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - pushBumpBatches(pass); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL); + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(1,1,1,1); + /// Get rid of z-fighting with non-bump pass. + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + pushBumpBatches(pass); } //static @@ -541,7 +541,7 @@ void LLDrawPoolBump::endBump(U32 pass) } S32 LLDrawPoolBump::getNumDeferredPasses() -{ +{ return 1; } @@ -604,7 +604,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass) void LLDrawPoolBump::renderPostDeferred(S32 pass) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - + S32 num_passes = LLPipeline::sRenderingHUDs ? 1 : 2; // skip rigged pass when rendering HUDs for (int i = 0; i < num_passes; ++i) @@ -632,127 +632,127 @@ void LLDrawPoolBump::renderPostDeferred(S32 pass) void LLBumpImageList::init() { - llassert( mBrightnessEntries.size() == 0 ); - llassert( mDarknessEntries.size() == 0 ); + llassert( mBrightnessEntries.size() == 0 ); + llassert( mDarknessEntries.size() == 0 ); - LLStandardBumpmap::restoreGL(); + LLStandardBumpmap::restoreGL(); sMainQueue = LL::WorkQueue::getInstance("mainloop"); sTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader. } void LLBumpImageList::clear() { - LL_INFOS() << "Clearing dynamic bumpmaps." << LL_ENDL; - // these will be re-populated on-demand - mBrightnessEntries.clear(); - mDarknessEntries.clear(); + LL_INFOS() << "Clearing dynamic bumpmaps." << LL_ENDL; + // these will be re-populated on-demand + mBrightnessEntries.clear(); + mDarknessEntries.clear(); sRenderTarget.release(); - LLStandardBumpmap::clear(); + LLStandardBumpmap::clear(); } void LLBumpImageList::shutdown() { - clear(); - LLStandardBumpmap::shutdown(); + clear(); + LLStandardBumpmap::shutdown(); } void LLBumpImageList::destroyGL() { - clear(); - LLStandardBumpmap::destroyGL(); + clear(); + LLStandardBumpmap::destroyGL(); } void LLBumpImageList::restoreGL() { - if(!gTextureList.isInitialized()) - { - //safe to return here because bump images will be reloaded during initialization later. - return ; - } - - LLStandardBumpmap::restoreGL(); - // Images will be recreated as they are needed. + if(!gTextureList.isInitialized()) + { + //safe to return here because bump images will be reloaded during initialization later. + return ; + } + + LLStandardBumpmap::restoreGL(); + // Images will be recreated as they are needed. } LLBumpImageList::~LLBumpImageList() { - // Shutdown should have already been called. - llassert( mBrightnessEntries.size() == 0 ); - llassert( mDarknessEntries.size() == 0 ); + // Shutdown should have already been called. + llassert( mBrightnessEntries.size() == 0 ); + llassert( mDarknessEntries.size() == 0 ); } // Note: Does nothing for entries in gStandardBumpmapList that are not actually standard bump images (e.g. none, brightness, and darkness) void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size) { - bump &= TEM_BUMP_MASK; - LLViewerFetchedTexture* bump_image = gStandardBumpmapList[bump].mImage; - if( bump_image ) - { - bump_image->addTextureStats(virtual_size); - } + bump &= TEM_BUMP_MASK; + LLViewerFetchedTexture* bump_image = gStandardBumpmapList[bump].mImage; + if( bump_image ) + { + bump_image->addTextureStats(virtual_size); + } } void LLBumpImageList::updateImages() -{ - for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) - { - LLViewerTexture* image = iter->second; - if( image ) - { - BOOL destroy = TRUE; - if( image->hasGLTexture()) - { - if( image->getBoundRecently() ) - { - destroy = FALSE; - } - else - { - image->destroyGLTexture(); - } - } - - if( destroy ) - { - //LL_INFOS() << "*** Destroying bright " << (void*)image << LL_ENDL; - iter = mBrightnessEntries.erase(iter); // deletes the image thanks to reference counting +{ + for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) + { + LLViewerTexture* image = iter->second; + if( image ) + { + BOOL destroy = TRUE; + if( image->hasGLTexture()) + { + if( image->getBoundRecently() ) + { + destroy = FALSE; + } + else + { + image->destroyGLTexture(); + } + } + + if( destroy ) + { + //LL_INFOS() << "*** Destroying bright " << (void*)image << LL_ENDL; + iter = mBrightnessEntries.erase(iter); // deletes the image thanks to reference counting continue; - } - } + } + } ++iter; - } - - for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) - { - bump_image_map_t::iterator curiter = iter++; - LLViewerTexture* image = curiter->second; - if( image ) - { - BOOL destroy = TRUE; - if( image->hasGLTexture()) - { - if( image->getBoundRecently() ) - { - destroy = FALSE; - } - else - { - image->destroyGLTexture(); - } - } - - if( destroy ) - { - //LL_INFOS() << "*** Destroying dark " << (void*)image << LL_ENDL;; - mDarknessEntries.erase(curiter); // deletes the image thanks to reference counting - } - } - } + } + + for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) + { + bump_image_map_t::iterator curiter = iter++; + LLViewerTexture* image = curiter->second; + if( image ) + { + BOOL destroy = TRUE; + if( image->hasGLTexture()) + { + if( image->getBoundRecently() ) + { + destroy = FALSE; + } + else + { + image->destroyGLTexture(); + } + } + + if( destroy ) + { + //LL_INFOS() << "*** Destroying dark " << (void*)image << LL_ENDL;; + mDarknessEntries.erase(curiter); // deletes the image thanks to reference counting + } + } + } } @@ -760,52 +760,52 @@ void LLBumpImageList::updateImages() LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) ); - - LLViewerTexture* bump = NULL; - - bump_image_map_t* entries_list = NULL; - void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL; - - switch( bump_code ) - { - case BE_BRIGHTNESS: - entries_list = &mBrightnessEntries; - callback_func = LLBumpImageList::onSourceBrightnessLoaded; - break; - case BE_DARKNESS: - entries_list = &mDarknessEntries; - callback_func = LLBumpImageList::onSourceDarknessLoaded; - break; - default: - llassert(0); - return NULL; - } - - bump_image_map_t::iterator iter = entries_list->find(src_image->getID()); - if (iter != entries_list->end() && iter->second.notNull()) - { - bump = iter->second; - } - else - { - (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( TRUE ); - bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image - } - - if (!src_image->hasCallbacks()) - { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again - if (src_image->getWidth() != bump->getWidth() || - src_image->getHeight() != bump->getHeight())// || - //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) - { - src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ; - src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); - src_image->forceToSaveRawImage(0) ; - } - } - - return bump; + llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) ); + + LLViewerTexture* bump = NULL; + + bump_image_map_t* entries_list = NULL; + void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL; + + switch( bump_code ) + { + case BE_BRIGHTNESS: + entries_list = &mBrightnessEntries; + callback_func = LLBumpImageList::onSourceBrightnessLoaded; + break; + case BE_DARKNESS: + entries_list = &mDarknessEntries; + callback_func = LLBumpImageList::onSourceDarknessLoaded; + break; + default: + llassert(0); + return NULL; + } + + bump_image_map_t::iterator iter = entries_list->find(src_image->getID()); + if (iter != entries_list->end() && iter->second.notNull()) + { + bump = iter->second; + } + else + { + (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( TRUE ); + bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image + } + + if (!src_image->hasCallbacks()) + { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again + if (src_image->getWidth() != bump->getWidth() || + src_image->getHeight() != bump->getHeight())// || + //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) + { + src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ; + src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); + src_image->forceToSaveRawImage(0) ; + } + } + + return bump; } @@ -813,94 +813,94 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText void LLBumpImageList::onSourceBrightnessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - LLUUID* source_asset_id = (LLUUID*)userdata; - LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS ); - if( final ) - { - delete source_asset_id; - } + LLUUID* source_asset_id = (LLUUID*)userdata; + LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS ); + if( final ) + { + delete source_asset_id; + } } // static void LLBumpImageList::onSourceDarknessLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - LLUUID* source_asset_id = (LLUUID*)userdata; - LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS ); - if( final ) - { - delete source_asset_id; - } + LLUUID* source_asset_id = (LLUUID*)userdata; + LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS ); + if( final ) + { + delete source_asset_id; + } } void LLBumpImageList::onSourceStandardLoaded( BOOL success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - if (success && LLPipeline::sRenderDeferred) - { + if (success && LLPipeline::sRenderDeferred) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - LLPointer nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); - { - generateNormalMapFromAlpha(src, nrm_image); - } - src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); - { - src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image); - } - } + LLPointer nrm_image = new LLImageRaw(src->getWidth(), src->getHeight(), 4); + { + generateNormalMapFromAlpha(src, nrm_image); + } + src_vi->setExplicitFormat(GL_RGBA, GL_RGBA); + { + src_vi->createGLTexture(src_vi->getDiscardLevel(), nrm_image); + } + } } void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image) { - U8* nrm_data = nrm_image->getData(); - S32 resX = src->getWidth(); - S32 resY = src->getHeight(); - - U8* src_data = src->getData(); - - S32 src_cmp = src->getComponents(); - - F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale"); - - U32 idx = 0; - //generate normal map from pseudo-heightfield - for (S32 j = 0; j < resY; ++j) - { - for (S32 i = 0; i < resX; ++i) - { - S32 rX = (i+1)%resX; - S32 rY = (j+1)%resY; - S32 lX = (i-1)%resX; - S32 lY = (j-1)%resY; - - if (lX < 0) - { - lX += resX; - } - if (lY < 0) - { - lY += resY; - } - - F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1]; - - LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH); - LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH); - LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH); - LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH); - - LLVector3 norm = right%down + down%left + left%up + up%right; - - norm.normVec(); - - norm *= 0.5f; - norm += LLVector3(0.5f,0.5f,0.5f); - - idx = (j*resX+i)*4; - nrm_data[idx+0]= (U8) (norm.mV[0]*255); - nrm_data[idx+1]= (U8) (norm.mV[1]*255); - nrm_data[idx+2]= (U8) (norm.mV[2]*255); - nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1]; - } - } + U8* nrm_data = nrm_image->getData(); + S32 resX = src->getWidth(); + S32 resY = src->getHeight(); + + U8* src_data = src->getData(); + + S32 src_cmp = src->getComponents(); + + F32 norm_scale = gSavedSettings.getF32("RenderNormalMapScale"); + + U32 idx = 0; + //generate normal map from pseudo-heightfield + for (S32 j = 0; j < resY; ++j) + { + for (S32 i = 0; i < resX; ++i) + { + S32 rX = (i+1)%resX; + S32 rY = (j+1)%resY; + S32 lX = (i-1)%resX; + S32 lY = (j-1)%resY; + + if (lX < 0) + { + lX += resX; + } + if (lY < 0) + { + lY += resY; + } + + F32 cH = (F32) src_data[(j*resX+i)*src_cmp+src_cmp-1]; + + LLVector3 right = LLVector3(norm_scale, 0, (F32) src_data[(j*resX+rX)*src_cmp+src_cmp-1]-cH); + LLVector3 left = LLVector3(-norm_scale, 0, (F32) src_data[(j*resX+lX)*src_cmp+src_cmp-1]-cH); + LLVector3 up = LLVector3(0, -norm_scale, (F32) src_data[(lY*resX+i)*src_cmp+src_cmp-1]-cH); + LLVector3 down = LLVector3(0, norm_scale, (F32) src_data[(rY*resX+i)*src_cmp+src_cmp-1]-cH); + + LLVector3 norm = right%down + down%left + left%up + up%right; + + norm.normVec(); + + norm *= 0.5f; + norm += LLVector3(0.5f,0.5f,0.5f); + + idx = (j*resX+i)*4; + nrm_data[idx+0]= (U8) (norm.mV[0]*255); + nrm_data[idx+1]= (U8) (norm.mV[1]*255); + nrm_data[idx+2]= (U8) (norm.mV[2]*255); + nrm_data[idx+3]= src_data[(j*resX+i)*src_cmp+src_cmp-1]; + } + } } // static @@ -908,147 +908,147 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI { LL_PROFILE_ZONE_SCOPED; - if( success ) - { + if( success ) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); - bump_image_map_t::iterator iter = entries_list.find(source_asset_id); - - { - if (iter == entries_list.end() || - iter->second.isNull() || - iter->second->getWidth() != src->getWidth() || - iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution - { //make sure an entry exists for this image - entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(TRUE); - iter = entries_list.find(src_vi->getID()); - } - } - - if (iter->second->getWidth() != src->getWidth() || - iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution - { - LLPointer dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1); - U8* dst_data = dst_image->getData(); - S32 dst_data_size = dst_image->getDataSize(); - - U8* src_data = src->getData(); - S32 src_data_size = src->getDataSize(); - - S32 src_components = src->getComponents(); - - // Convert to luminance and then scale and bias that to get ready for - // embossed bump mapping. (0-255 maps to 127-255) - - // Convert to fixed point so we don't have to worry about precision/clamping. - const S32 FIXED_PT = 8; - const S32 R_WEIGHT = S32(0.2995f * (1< maximum ) - { - maximum = dst_data[i]; - } - } - } - else - { - llassert(0); - dst_image->clear(); - } - } - break; - case 3: - case 4: - { - if( src_data_size == dst_data_size * src_components ) - { - for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) - { - // RGB to luminance - dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT; - //llassert( dst_data[i] <= 255 );true because it's 8bit - if( dst_data[i] < minimum ) - { - minimum = dst_data[i]; - } - if( dst_data[i] > maximum ) - { - maximum = dst_data[i]; - } - } - } - else - { - llassert(0); - dst_image->clear(); - } - } - break; - default: - llassert(0); - dst_image->clear(); - break; - } - - if( maximum > minimum ) - { - U8 bias_and_scale_lut[256]; - F32 twice_one_over_range = 2.f / (maximum - minimum); - S32 i; - - const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes. - if (BE_DARKNESS == bump_code) - { - for( i = minimum; i <= maximum; i++ ) - { - F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f; - bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128)); - } - } - else - { - for( i = minimum; i <= maximum; i++ ) - { - F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f; - bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128)); - } - } - - for( i = 0; i < dst_data_size; i++ ) - { - dst_data[i] = bias_and_scale_lut[dst_data[i]]; - } - } - - //--------------------------------------------------- - // immediately assign bump to a smart pointer in case some local smart pointer - // accidentally releases it. + bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); + bump_image_map_t::iterator iter = entries_list.find(source_asset_id); + + { + if (iter == entries_list.end() || + iter->second.isNull() || + iter->second->getWidth() != src->getWidth() || + iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution + { //make sure an entry exists for this image + entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(TRUE); + iter = entries_list.find(src_vi->getID()); + } + } + + if (iter->second->getWidth() != src->getWidth() || + iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution + { + LLPointer dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1); + U8* dst_data = dst_image->getData(); + S32 dst_data_size = dst_image->getDataSize(); + + U8* src_data = src->getData(); + S32 src_data_size = src->getDataSize(); + + S32 src_components = src->getComponents(); + + // Convert to luminance and then scale and bias that to get ready for + // embossed bump mapping. (0-255 maps to 127-255) + + // Convert to fixed point so we don't have to worry about precision/clamping. + const S32 FIXED_PT = 8; + const S32 R_WEIGHT = S32(0.2995f * (1< maximum ) + { + maximum = dst_data[i]; + } + } + } + else + { + llassert(0); + dst_image->clear(); + } + } + break; + case 3: + case 4: + { + if( src_data_size == dst_data_size * src_components ) + { + for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components ) + { + // RGB to luminance + dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT; + //llassert( dst_data[i] <= 255 );true because it's 8bit + if( dst_data[i] < minimum ) + { + minimum = dst_data[i]; + } + if( dst_data[i] > maximum ) + { + maximum = dst_data[i]; + } + } + } + else + { + llassert(0); + dst_image->clear(); + } + } + break; + default: + llassert(0); + dst_image->clear(); + break; + } + + if( maximum > minimum ) + { + U8 bias_and_scale_lut[256]; + F32 twice_one_over_range = 2.f / (maximum - minimum); + S32 i; + + const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes. + if (BE_DARKNESS == bump_code) + { + for( i = minimum; i <= maximum; i++ ) + { + F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f; + bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128)); + } + } + else + { + for( i = minimum; i <= maximum; i++ ) + { + F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f; + bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128)); + } + } + + for( i = 0; i < dst_data_size; i++ ) + { + dst_data[i] = bias_and_scale_lut[dst_data[i]]; + } + } + + //--------------------------------------------------- + // immediately assign bump to a smart pointer in case some local smart pointer + // accidentally releases it. LLPointer bump = iter->second; - if (!LLPipeline::sRenderDeferred) - { - bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); + if (!LLPipeline::sRenderDeferred) + { + bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); #if LL_BUMPLIST_MULTITHREADED auto tex_queue = LLImageGLThread::sEnabledTextures ? sTexUpdateQueue.lock() : nullptr; @@ -1074,9 +1074,9 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI { bump->createGLTexture(0, dst_image); } - } - else - { //convert to normal map + } + else + { //convert to normal map LL_PROFILE_ZONE_NAMED("bil - create normal map"); LLImageGL* img = bump->getGLTexture(); LLImageRaw* dst_ptr = dst_image.get(); @@ -1180,16 +1180,16 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI } - } + } - iter->second = bump; // derefs (and deletes) old image - //--------------------------------------------------- - } - } + iter->second = bump; // derefs (and deletes) old image + //--------------------------------------------------- + } + } } void LLDrawPoolBump::pushBumpBatches(U32 type) -{ +{ LLVOAvatar* avatar = nullptr; U64 skin = 0; @@ -1201,12 +1201,12 @@ void LLDrawPoolBump::pushBumpBatches(U32 type) LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) - { - LLDrawInfo& params = **i; + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) + { + LLDrawInfo& params = **i; - if (LLDrawPoolBump::bindBumpMap(params)) - { + if (LLDrawPoolBump::bindBumpMap(params)) + { if (mRigged) { if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash) @@ -1222,80 +1222,80 @@ void LLDrawPoolBump::pushBumpBatches(U32 type) } } } - pushBumpBatch(params, false); - } - } + pushBumpBatch(params, false); + } + } } void LLRenderPass::pushBumpBatch(LLDrawInfo& params, bool texture, bool batch_textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - applyModelMatrix(params); - - bool tex_setup = false; - - if (batch_textures && params.mTextureList.size() > 1) - { - for (U32 i = 0; i < params.mTextureList.size(); ++i) - { - if (params.mTextureList[i].notNull()) - { - gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); - } - } - } - else - { //not batching textures or batch has only 1 texture -- might need a texture matrix - if (params.mTextureMatrix) - { - if (shiny) - { - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - } - else - { - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - - gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - - tex_setup = true; - } - - if (shiny && mShaderLevel > 1 && texture) - { - if (params.mTexture.notNull()) - { - gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); - } - else - { - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); - } - } - } - - params.mVertexBuffer->setBuffer(); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); + applyModelMatrix(params); + + bool tex_setup = false; + + if (batch_textures && params.mTextureList.size() > 1) + { + for (U32 i = 0; i < params.mTextureList.size(); ++i) + { + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bindFast(params.mTextureList[i]); + } + } + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTextureMatrix) + { + if (shiny) + { + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + } + else + { + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + + gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + + tex_setup = true; + } + + if (shiny && mShaderLevel > 1 && texture) + { + if (params.mTexture.notNull()) + { + gGL.getTexUnit(diffuse_channel)->bindFast(params.mTexture); + } + else + { + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + } + } + } + + params.mVertexBuffer->setBuffer(); + params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); if (tex_setup) - { - if (shiny) - { - gGL.getTexUnit(0)->activate(); - } - else - { - gGL.getTexUnit(0)->activate(); - gGL.matrixMode(LLRender::MM_TEXTURE); - } - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } + { + if (shiny) + { + gGL.getTexUnit(0)->activate(); + } + else + { + gGL.getTexUnit(0)->activate(); + gGL.matrixMode(LLRender::MM_TEXTURE); + } + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } } diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index c5932a6ad9..1b8097c3a4 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpoolterrain.cpp * @brief LLDrawPoolTerrain class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -39,7 +39,7 @@ #include "llsurfacepatch.h" #include "llviewerregion.h" #include "llvlcomposition.h" -#include "llviewerparcelmgr.h" // for gRenderParcelOwnership +#include "llviewerparcelmgr.h" // for gRenderParcelOwnership #include "llviewerparceloverlay.h" #include "llvosurfacepatch.h" #include "llviewercamera.h" @@ -62,47 +62,47 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_TERRAIN("Terrain Shadow"); LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : - LLFacePool(POOL_TERRAIN), - mTexturep(texturep) + LLFacePool(POOL_TERRAIN), + mTexturep(texturep) { - // Hack! - sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); - sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale"); - sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); - mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD); - - //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); - mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - - m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD_2D); - - //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); - m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - - mTexturep->setBoostLevel(LLGLTexture::BOOST_TERRAIN); - - //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + // Hack! + sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); + sPBRDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainPBRScale"); + sPBRDetailMode = gSavedSettings.getS32("RenderTerrainPBRDetail"); + mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD); + + //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); + mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); + + m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD_2D); + + //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); + m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); + + mTexturep->setBoostLevel(LLGLTexture::BOOST_TERRAIN); + + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } LLDrawPoolTerrain::~LLDrawPoolTerrain() { - llassert( gPipeline.findPool( getType(), getTexture() ) == NULL ); + llassert( gPipeline.findPool( getType(), getTexture() ) == NULL ); } -U32 LLDrawPoolTerrain::getVertexDataMask() -{ - if (LLPipeline::sShadowRender) - { - return LLVertexBuffer::MAP_VERTEX; - } - else if (LLGLSLShader::sCurBoundShaderPtr) - { - return VERTEX_DATA_MASK & ~(LLVertexBuffer::MAP_TEXCOORD2 | LLVertexBuffer::MAP_TEXCOORD3); - } - else - { - return VERTEX_DATA_MASK; - } +U32 LLDrawPoolTerrain::getVertexDataMask() +{ + if (LLPipeline::sShadowRender) + { + return LLVertexBuffer::MAP_VERTEX; + } + else if (LLGLSLShader::sCurBoundShaderPtr) + { + return VERTEX_DATA_MASK & ~(LLVertexBuffer::MAP_TEXCOORD2 | LLVertexBuffer::MAP_TEXCOORD3); + } + else + { + return VERTEX_DATA_MASK; + } } void LLDrawPoolTerrain::prerender() @@ -113,50 +113,50 @@ void LLDrawPoolTerrain::prerender() void LLDrawPoolTerrain::boostTerrainDetailTextures() { // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); compp->boost(); } void LLDrawPoolTerrain::beginDeferredPass(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); - LLFacePool::beginRenderPass(pass); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); + LLFacePool::beginRenderPass(pass); } void LLDrawPoolTerrain::endDeferredPass(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); - LLFacePool::endRenderPass(pass); - sShader->unbind(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); + LLFacePool::endRenderPass(pass); + sShader->unbind(); } void LLDrawPoolTerrain::renderDeferred(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); - if (mDrawFace.empty()) - { - return; - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN); + if (mDrawFace.empty()) + { + return; + } boostTerrainDetailTextures(); - renderFullShader(); + renderFullShader(); - // Special-case for land ownership feedback - if (gSavedSettings.getBOOL("ShowParcelOwners")) - { - hilightParcelOwners(); - } + // Special-case for land ownership feedback + if (gSavedSettings.getBOOL("ShowParcelOwners")) + { + hilightParcelOwners(); + } } void LLDrawPoolTerrain::beginShadowPass(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); - LLFacePool::beginRenderPass(pass); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gDeferredShadowProgram.bind(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); + LLFacePool::beginRenderPass(pass); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gDeferredShadowProgram.bind(); LLEnvironment& environment = LLEnvironment::instance(); gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); @@ -164,50 +164,50 @@ void LLDrawPoolTerrain::beginShadowPass(S32 pass) void LLDrawPoolTerrain::endShadowPass(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); - LLFacePool::endRenderPass(pass); - gDeferredShadowProgram.unbind(); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); + LLFacePool::endRenderPass(pass); + gDeferredShadowProgram.unbind(); } void LLDrawPoolTerrain::renderShadow(S32 pass) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); - if (mDrawFace.empty()) - { - return; - } - //LLGLEnable offset(GL_POLYGON_OFFSET); - //glCullFace(GL_FRONT); - drawLoop(); - //glCullFace(GL_BACK); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_TERRAIN); + if (mDrawFace.empty()) + { + return; + } + //LLGLEnable offset(GL_POLYGON_OFFSET); + //glCullFace(GL_FRONT); + drawLoop(); + //glCullFace(GL_BACK); } void LLDrawPoolTerrain::drawLoop() { - if (!mDrawFace.empty()) - { - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; + if (!mDrawFace.empty()) + { + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); LLRenderPass::applyModelMatrix(&facep->getDrawable()->getRegion()->mRenderMatrix); - facep->renderIndexed(); - } - } + facep->renderIndexed(); + } + } } void LLDrawPoolTerrain::renderFullShader() { const BOOL use_local_materials = gLocalTerrainMaterials.materialsReady(true, false); - // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); const BOOL use_textures = !use_local_materials && (compp->getMaterialType() == LLTerrainMaterials::Type::TEXTURE); - + if (use_textures) { // Use textures @@ -226,129 +226,129 @@ void LLDrawPoolTerrain::renderFullShader() void LLDrawPoolTerrain::renderFullShaderTextures() { - // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); - - LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; - LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; - LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; - LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; - - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; - - LLVector4 tp0, tp1; - - tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); - tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); - - // - // detail texture 0 - // - S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); - gGL.getTexUnit(detail0)->bind(detail_texture0p); + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + + LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; + LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; + LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; + LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; + + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; + + LLVector4 tp0, tp1; + + tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); + tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); + + // + // detail texture 0 + // + S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); + gGL.getTexUnit(detail0)->bind(detail_texture0p); gGL.getTexUnit(detail0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail0)->activate(); + gGL.getTexUnit(detail0)->activate(); - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader); - - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); - shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); + shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - // - // detail texture 1 - // - S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); - gGL.getTexUnit(detail1)->bind(detail_texture1p); - gGL.getTexUnit(detail1)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail1)->activate(); - - // detail texture 2 - // - S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); - gGL.getTexUnit(detail2)->bind(detail_texture2p); + // + // detail texture 1 + // + S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); + gGL.getTexUnit(detail1)->bind(detail_texture1p); + gGL.getTexUnit(detail1)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail1)->activate(); + + // detail texture 2 + // + S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); + gGL.getTexUnit(detail2)->bind(detail_texture2p); gGL.getTexUnit(detail2)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail2)->activate(); - - - // detail texture 3 - // - S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); - gGL.getTexUnit(detail3)->bind(detail_texture3p); - gGL.getTexUnit(detail3)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - gGL.getTexUnit(detail3)->activate(); - - // - // Alpha Ramp - // - S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); - gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); + gGL.getTexUnit(detail2)->activate(); + + + // detail texture 3 + // + S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); + gGL.getTexUnit(detail3)->bind(detail_texture3p); + gGL.getTexUnit(detail3)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + gGL.getTexUnit(detail3)->activate(); + + // + // Alpha Ramp + // + S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - // GL_BLEND disabled by default - drawLoop(); - - // Disable multitexture - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); - - gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(alpha_ramp)->disable(); - gGL.getTexUnit(alpha_ramp)->activate(); - - gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail3)->disable(); - gGL.getTexUnit(detail3)->activate(); - - gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail2)->disable(); - gGL.getTexUnit(detail2)->activate(); - - gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail1)->disable(); - gGL.getTexUnit(detail1)->activate(); - - //---------------------------------------------------------------------------- - // Restore Texture Unit 0 defaults - - gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail0)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(detail0)->activate(); + // GL_BLEND disabled by default + drawLoop(); + + // Disable multitexture + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3); + + gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(alpha_ramp)->disable(); + gGL.getTexUnit(alpha_ramp)->activate(); + + gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail3)->disable(); + gGL.getTexUnit(detail3)->activate(); + + gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail2)->disable(); + gGL.getTexUnit(detail2)->activate(); + + gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail1)->disable(); + gGL.getTexUnit(detail1)->activate(); + + //---------------------------------------------------------------------------- + // Restore Texture Unit 0 defaults + + gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(detail0)->activate(); } // *TODO: Investigate use of bindFast for PBR terrain textures void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) { - // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); - LLPointer (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + LLPointer (*fetched_materials)[LLVLComposition::ASSET_COUNT] = &compp->mDetailMaterials; - constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT; + constexpr U32 terrain_material_count = LLVLComposition::ASSET_COUNT; #ifdef SHOW_ASSERT - constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; - llassert(shader_material_count == terrain_material_count); + constexpr U32 shader_material_count = 1 + LLViewerShaderMgr::TERRAIN_DETAIL3_BASE_COLOR - LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR; + llassert(shader_material_count == terrain_material_count); #endif if (local_materials) { // Override region terrain with the global local override terrain - fetched_materials = &gLocalTerrainMaterials.mDetailMaterials; + fetched_materials = &gLocalTerrainMaterials.mDetailMaterials; + } + const LLGLTFMaterial* materials[terrain_material_count]; + for (U32 i = 0; i < terrain_material_count; ++i) + { + materials[i] = (*fetched_materials)[i].get(); + if (!materials[i]) { materials[i] = &LLGLTFMaterial::sDefault; } } - const LLGLTFMaterial* materials[terrain_material_count]; - for (U32 i = 0; i < terrain_material_count; ++i) - { - materials[i] = (*fetched_materials)[i].get(); - if (!materials[i]) { materials[i] = &LLGLTFMaterial::sDefault; } - } S32 detail_basecolor[terrain_material_count]; S32 detail_normal[terrain_material_count]; @@ -357,19 +357,19 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) for (U32 i = 0; i < terrain_material_count; ++i) { - LLViewerTexture* detail_basecolor_texturep = nullptr; - LLViewerTexture* detail_normal_texturep = nullptr; - LLViewerTexture* detail_metalrough_texturep = nullptr; - LLViewerTexture* detail_emissive_texturep = nullptr; - - const LLFetchedGLTFMaterial* fetched_material = (*fetched_materials)[i].get(); - if (fetched_material) - { - detail_basecolor_texturep = fetched_material->mBaseColorTexture; - detail_normal_texturep = fetched_material->mNormalTexture; - detail_metalrough_texturep = fetched_material->mMetallicRoughnessTexture; - detail_emissive_texturep = fetched_material->mEmissiveTexture; - } + LLViewerTexture* detail_basecolor_texturep = nullptr; + LLViewerTexture* detail_normal_texturep = nullptr; + LLViewerTexture* detail_metalrough_texturep = nullptr; + LLViewerTexture* detail_emissive_texturep = nullptr; + + const LLFetchedGLTFMaterial* fetched_material = (*fetched_materials)[i].get(); + if (fetched_material) + { + detail_basecolor_texturep = fetched_material->mBaseColorTexture; + detail_normal_texturep = fetched_material->mNormalTexture; + detail_metalrough_texturep = fetched_material->mMetallicRoughnessTexture; + detail_emissive_texturep = fetched_material->mEmissiveTexture; + } detail_basecolor[i] = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0_BASE_COLOR + i); if (detail_basecolor_texturep) @@ -429,16 +429,16 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) } } - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader); - + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + // *TODO: Figure out why this offset is *sometimes* producing seams at the // region edge, and repeat jumps when crossing regions, when // RenderTerrainPBRScale is not a factor of the region scale. - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; LLGLTFMaterial::TextureTransform base_color_transform; base_color_transform.mScale = LLVector2(sPBRDetailScale, sPBRDetailScale); @@ -451,11 +451,11 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater(); - // - // Alpha Ramp - // - S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); - gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); + // + // Alpha Ramp + // + S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep); gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); // @@ -500,16 +500,16 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) } shader->uniform4f(LLShaderMgr::TERRAIN_MINIMUM_ALPHAS, minimum_alphas[0], minimum_alphas[1], minimum_alphas[2], minimum_alphas[3]); - // GL_BLEND disabled by default - drawLoop(); + // GL_BLEND disabled by default + drawLoop(); - // Disable multitexture + // Disable multitexture - sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); + sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP); - gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(alpha_ramp)->disable(); - gGL.getTexUnit(alpha_ramp)->activate(); + gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(alpha_ramp)->disable(); + gGL.getTexUnit(alpha_ramp)->activate(); for (U32 i = 0; i < terrain_material_count; ++i) { @@ -556,466 +556,466 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) void LLDrawPoolTerrain::hilightParcelOwners() { - { //use fullbright shader for highlighting - LLGLSLShader* old_shader = sShader; - sShader->unbind(); - sShader = &gDeferredHighlightProgram; - sShader->bind(); - gGL.diffuseColor4f(1, 1, 1, 1); - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - renderOwnership(); - sShader = old_shader; - sShader->bind(); - } - + { //use fullbright shader for highlighting + LLGLSLShader* old_shader = sShader; + sShader->unbind(); + sShader = &gDeferredHighlightProgram; + sShader->bind(); + gGL.diffuseColor4f(1, 1, 1, 1); + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + renderOwnership(); + sShader = old_shader; + sShader->bind(); + } + } void LLDrawPoolTerrain::renderFull4TU() { - // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); - LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; - LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; - LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; - LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; - - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; - - LLVector4 tp0, tp1; - - tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); - tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); - - gGL.blendFunc(LLRender::BF_ONE_MINUS_SOURCE_ALPHA, LLRender::BF_SOURCE_ALPHA); - - //---------------------------------------------------------------------------- - // Pass 1/1 - - // - // Stage 0: detail texture 0 - // - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(detail_texture0p); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - // - // Stage 1: Generate alpha ramp for detail0/detail1 transition - // - - gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->activate(); - - // - // Stage 2: Interpolate detail1 with existing based on ramp - // - gGL.getTexUnit(2)->bind(detail_texture1p); - gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(2)->activate(); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - // - // Stage 3: Modulate with primary (vertex) color for lighting - // - gGL.getTexUnit(3)->bind(detail_texture1p); - gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(3)->activate(); - - gGL.getTexUnit(0)->activate(); - - // GL_BLEND disabled by default - drawLoop(); - - //---------------------------------------------------------------------------- - // Second pass - - // Stage 0: Write detail3 into base - // - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(detail_texture3p); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - // - // Stage 1: Generate alpha ramp for detail2/detail3 transition - // - gGL.getTexUnit(1)->bind(m2DAlphaRampImagep); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->activate(); - - // Set the texture matrix - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.translatef(-2.f, 0.f, 0.f); - - // - // Stage 2: Interpolate detail2 with existing based on ramp - // - gGL.getTexUnit(2)->bind(detail_texture2p); - gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(2)->activate(); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - // - // Stage 3: Generate alpha ramp for detail1/detail2 transition - // - gGL.getTexUnit(3)->bind(m2DAlphaRampImagep); - gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(3)->activate(); - - // Set the texture matrix - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.translatef(-1.f, 0.f, 0.f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.getTexUnit(0)->activate(); - { - LLGLEnable blend(GL_BLEND); - drawLoop(); - } - - LLVertexBuffer::unbind(); - // Disable multitexture - gGL.getTexUnit(3)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(3)->disable(); - gGL.getTexUnit(3)->activate(); - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(2)->disable(); - gGL.getTexUnit(2)->activate(); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->activate(); - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - // Restore blend state - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - //---------------------------------------------------------------------------- - // Restore Texture Unit 0 defaults - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; + LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; + LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; + LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; + + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; + + LLVector4 tp0, tp1; + + tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); + tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); + + gGL.blendFunc(LLRender::BF_ONE_MINUS_SOURCE_ALPHA, LLRender::BF_SOURCE_ALPHA); + + //---------------------------------------------------------------------------- + // Pass 1/1 + + // + // Stage 0: detail texture 0 + // + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(detail_texture0p); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + // + // Stage 1: Generate alpha ramp for detail0/detail1 transition + // + + gGL.getTexUnit(1)->bind(m2DAlphaRampImagep.get()); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->activate(); + + // + // Stage 2: Interpolate detail1 with existing based on ramp + // + gGL.getTexUnit(2)->bind(detail_texture1p); + gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->activate(); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + // + // Stage 3: Modulate with primary (vertex) color for lighting + // + gGL.getTexUnit(3)->bind(detail_texture1p); + gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(3)->activate(); + + gGL.getTexUnit(0)->activate(); + + // GL_BLEND disabled by default + drawLoop(); + + //---------------------------------------------------------------------------- + // Second pass + + // Stage 0: Write detail3 into base + // + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(detail_texture3p); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + // + // Stage 1: Generate alpha ramp for detail2/detail3 transition + // + gGL.getTexUnit(1)->bind(m2DAlphaRampImagep); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->activate(); + + // Set the texture matrix + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.translatef(-2.f, 0.f, 0.f); + + // + // Stage 2: Interpolate detail2 with existing based on ramp + // + gGL.getTexUnit(2)->bind(detail_texture2p); + gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->activate(); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + // + // Stage 3: Generate alpha ramp for detail1/detail2 transition + // + gGL.getTexUnit(3)->bind(m2DAlphaRampImagep); + gGL.getTexUnit(3)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(3)->activate(); + + // Set the texture matrix + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.translatef(-1.f, 0.f, 0.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + gGL.getTexUnit(0)->activate(); + { + LLGLEnable blend(GL_BLEND); + drawLoop(); + } + + LLVertexBuffer::unbind(); + // Disable multitexture + gGL.getTexUnit(3)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(3)->disable(); + gGL.getTexUnit(3)->activate(); + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->disable(); + gGL.getTexUnit(2)->activate(); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->activate(); + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + // Restore blend state + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + //---------------------------------------------------------------------------- + // Restore Texture Unit 0 defaults + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } void LLDrawPoolTerrain::renderFull2TU() { - // Hack! Get the region that this draw pool is rendering from! - LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); - LLVLComposition *compp = regionp->getComposition(); - LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; - LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; - LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; - LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; - - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; - - LLVector4 tp0, tp1; - - tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); - tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); - - gGL.blendFunc(LLRender::BF_ONE_MINUS_SOURCE_ALPHA, LLRender::BF_SOURCE_ALPHA); - - //---------------------------------------------------------------------------- - // Pass 1/4 - - // - // Stage 0: Render detail 0 into base - // - gGL.getTexUnit(0)->bind(detail_texture0p); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - drawLoop(); - - //---------------------------------------------------------------------------- - // Pass 2/4 - - // - // Stage 0: Generate alpha ramp for detail0/detail1 transition - // - gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - - // - // Stage 1: Write detail1 - // - gGL.getTexUnit(1)->bind(detail_texture1p); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->activate(); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - gGL.getTexUnit(0)->activate(); - { - LLGLEnable blend(GL_BLEND); - drawLoop(); - } - //---------------------------------------------------------------------------- - // Pass 3/4 - - // - // Stage 0: Generate alpha ramp for detail1/detail2 transition - // - gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); - - // Set the texture matrix - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.translatef(-1.f, 0.f, 0.f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - // - // Stage 1: Write detail2 - // - gGL.getTexUnit(1)->bind(detail_texture2p); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->activate(); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - { - LLGLEnable blend(GL_BLEND); - drawLoop(); - } - - //---------------------------------------------------------------------------- - // Pass 4/4 - - // - // Stage 0: Generate alpha ramp for detail2/detail3 transition - // - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); - // Set the texture matrix - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.translatef(-2.f, 0.f, 0.f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - // Stage 1: Write detail3 - gGL.getTexUnit(1)->bind(detail_texture3p); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->activate(); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - - gGL.getTexUnit(0)->activate(); - { - LLGLEnable blend(GL_BLEND); - drawLoop(); - } - - // Restore blend state - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - // Disable multitexture - - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->activate(); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - - //---------------------------------------------------------------------------- - // Restore Texture Unit 0 defaults - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + LLViewerTexture *detail_texture0p = compp->mDetailTextures[0]; + LLViewerTexture *detail_texture1p = compp->mDetailTextures[1]; + LLViewerTexture *detail_texture2p = compp->mDetailTextures[2]; + LLViewerTexture *detail_texture3p = compp->mDetailTextures[3]; + + LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); + F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale; + F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale; + + LLVector4 tp0, tp1; + + tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x); + tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y); + + gGL.blendFunc(LLRender::BF_ONE_MINUS_SOURCE_ALPHA, LLRender::BF_SOURCE_ALPHA); + + //---------------------------------------------------------------------------- + // Pass 1/4 + + // + // Stage 0: Render detail 0 into base + // + gGL.getTexUnit(0)->bind(detail_texture0p); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + drawLoop(); + + //---------------------------------------------------------------------------- + // Pass 2/4 + + // + // Stage 0: Generate alpha ramp for detail0/detail1 transition + // + gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + + // + // Stage 1: Write detail1 + // + gGL.getTexUnit(1)->bind(detail_texture1p); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->activate(); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + gGL.getTexUnit(0)->activate(); + { + LLGLEnable blend(GL_BLEND); + drawLoop(); + } + //---------------------------------------------------------------------------- + // Pass 3/4 + + // + // Stage 0: Generate alpha ramp for detail1/detail2 transition + // + gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); + + // Set the texture matrix + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.translatef(-1.f, 0.f, 0.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + // + // Stage 1: Write detail2 + // + gGL.getTexUnit(1)->bind(detail_texture2p); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->activate(); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + { + LLGLEnable blend(GL_BLEND); + drawLoop(); + } + + //---------------------------------------------------------------------------- + // Pass 4/4 + + // + // Stage 0: Generate alpha ramp for detail2/detail3 transition + // + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); + // Set the texture matrix + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.translatef(-2.f, 0.f, 0.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + // Stage 1: Write detail3 + gGL.getTexUnit(1)->bind(detail_texture3p); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->activate(); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); + + gGL.getTexUnit(0)->activate(); + { + LLGLEnable blend(GL_BLEND); + drawLoop(); + } + + // Restore blend state + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + // Disable multitexture + + gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->activate(); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + + //---------------------------------------------------------------------------- + // Restore Texture Unit 0 defaults + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } void LLDrawPoolTerrain::renderSimple() { - LLVector4 tp0, tp1; - - //---------------------------------------------------------------------------- - // Pass 1/1 - - // Stage 0: Base terrain texture pass - mTexturep->addTextureStats(1024.f*1024.f); - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->bind(mTexturep); - - LLVector3 origin_agent = mDrawFace[0]->getDrawable()->getVObj()->getRegion()->getOriginAgent(); - F32 tscale = 1.f/256.f; - tp0.setVec(tscale, 0.f, 0.0f, -1.f*(origin_agent.mV[0]/256.f)); - tp1.setVec(0.f, tscale, 0.0f, -1.f*(origin_agent.mV[1]/256.f)); - - sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); - sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); - - drawLoop(); - - //---------------------------------------------------------------------------- - // Restore Texture Unit 0 defaults - - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); + LLVector4 tp0, tp1; + + //---------------------------------------------------------------------------- + // Pass 1/1 + + // Stage 0: Base terrain texture pass + mTexturep->addTextureStats(1024.f*1024.f); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->bind(mTexturep); + + LLVector3 origin_agent = mDrawFace[0]->getDrawable()->getVObj()->getRegion()->getOriginAgent(); + F32 tscale = 1.f/256.f; + tp0.setVec(tscale, 0.f, 0.0f, -1.f*(origin_agent.mV[0]/256.f)); + tp1.setVec(0.f, tscale, 0.0f, -1.f*(origin_agent.mV[1]/256.f)); + + sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); + sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV); + + drawLoop(); + + //---------------------------------------------------------------------------- + // Restore Texture Unit 0 defaults + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } //============================================================================ void LLDrawPoolTerrain::renderOwnership() { - LLGLSPipelineAlpha gls_pipeline_alpha; - - llassert(!mDrawFace.empty()); - - // Each terrain pool is associated with a single region. - // We need to peek back into the viewer's data to find out - // which ownership overlay texture to use. - LLFace *facep = mDrawFace[0]; - LLDrawable *drawablep = facep->getDrawable(); - const LLViewerObject *objectp = drawablep->getVObj(); - const LLVOSurfacePatch *vo_surface_patchp = (LLVOSurfacePatch *)objectp; - LLSurfacePatch *surface_patchp = vo_surface_patchp->getPatch(); - LLSurface *surfacep = surface_patchp->getSurface(); - LLViewerRegion *regionp = surfacep->getRegion(); - LLViewerParcelOverlay *overlayp = regionp->getParcelOverlay(); - LLViewerTexture *texturep = overlayp->getTexture(); - - gGL.getTexUnit(0)->bind(texturep); - - // *NOTE: Because the region is 256 meters wide, but has 257 pixels, the - // texture coordinates for pixel 256x256 is not 1,1. This makes the - // ownership map not line up with the selection. We address this with - // a texture matrix multiply. - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.pushMatrix(); - - const F32 TEXTURE_FUDGE = 257.f / 256.f; - gGL.scalef( TEXTURE_FUDGE, TEXTURE_FUDGE, 1.f ); - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - facep->renderIndexed(); - } - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); + LLGLSPipelineAlpha gls_pipeline_alpha; + + llassert(!mDrawFace.empty()); + + // Each terrain pool is associated with a single region. + // We need to peek back into the viewer's data to find out + // which ownership overlay texture to use. + LLFace *facep = mDrawFace[0]; + LLDrawable *drawablep = facep->getDrawable(); + const LLViewerObject *objectp = drawablep->getVObj(); + const LLVOSurfacePatch *vo_surface_patchp = (LLVOSurfacePatch *)objectp; + LLSurfacePatch *surface_patchp = vo_surface_patchp->getPatch(); + LLSurface *surfacep = surface_patchp->getSurface(); + LLViewerRegion *regionp = surfacep->getRegion(); + LLViewerParcelOverlay *overlayp = regionp->getParcelOverlay(); + LLViewerTexture *texturep = overlayp->getTexture(); + + gGL.getTexUnit(0)->bind(texturep); + + // *NOTE: Because the region is 256 meters wide, but has 257 pixels, the + // texture coordinates for pixel 256x256 is not 1,1. This makes the + // ownership map not line up with the selection. We address this with + // a texture matrix multiply. + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.pushMatrix(); + + const F32 TEXTURE_FUDGE = 257.f / 256.f; + gGL.scalef( TEXTURE_FUDGE, TEXTURE_FUDGE, 1.f ); + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; + facep->renderIndexed(); + } + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); } void LLDrawPoolTerrain::dirtyTextures(const std::set& textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ; - if (tex && textures.find(tex) != textures.end()) - { - for (std::vector::iterator iter = mReferences.begin(); - iter != mReferences.end(); iter++) - { - LLFace *facep = *iter; - gPipeline.markTextured(facep->getDrawable()); - } - } + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ; + if (tex && textures.find(tex) != textures.end()) + { + for (std::vector::iterator iter = mReferences.begin(); + iter != mReferences.end(); iter++) + { + LLFace *facep = *iter; + gPipeline.markTextured(facep->getDrawable()); + } + } } LLViewerTexture *LLDrawPoolTerrain::getTexture() { - return mTexturep; + return mTexturep; } LLViewerTexture *LLDrawPoolTerrain::getDebugTexture() { - return mTexturep; + return mTexturep; } LLColor3 LLDrawPoolTerrain::getDebugColor() const { - return LLColor3(0.f, 0.f, 1.f); + return LLColor3(0.f, 0.f, 1.f); } diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 13f031c8e7..5ee91eb47c 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpoolterrain.h * @brief LLDrawPoolTerrain class definition * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -31,7 +31,7 @@ class LLDrawPoolTerrain : public LLFacePool { - LLPointer mTexturep; + LLPointer mTexturep; public: enum { @@ -40,51 +40,51 @@ public: LLVertexBuffer::MAP_TANGENT | // Only PBR terrain uses this currently LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 - }; + }; - virtual U32 getVertexDataMask(); - LLDrawPoolTerrain(LLViewerTexture *texturep); - virtual ~LLDrawPoolTerrain(); + virtual U32 getVertexDataMask(); + LLDrawPoolTerrain(LLViewerTexture *texturep); + virtual ~LLDrawPoolTerrain(); - /*virtual*/ S32 getNumDeferredPasses() { return 1; } - /*virtual*/ void beginDeferredPass(S32 pass); - /*virtual*/ void endDeferredPass(S32 pass); - /*virtual*/ void renderDeferred(S32 pass); + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); - /*virtual*/ S32 getNumShadowPasses() { return 1; } - /*virtual*/ void beginShadowPass(S32 pass); - /*virtual*/ void endShadowPass(S32 pass); - /*virtual*/ void renderShadow(S32 pass); + /*virtual*/ S32 getNumShadowPasses() { return 1; } + /*virtual*/ void beginShadowPass(S32 pass); + /*virtual*/ void endShadowPass(S32 pass); + /*virtual*/ void renderShadow(S32 pass); - /*virtual*/ void prerender(); - /*virtual*/ void dirtyTextures(const std::set& textures); - /*virtual*/ LLViewerTexture *getTexture(); - /*virtual*/ LLViewerTexture *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display + /*virtual*/ void prerender(); + /*virtual*/ void dirtyTextures(const std::set& textures); + /*virtual*/ LLViewerTexture *getTexture(); + /*virtual*/ LLViewerTexture *getDebugTexture(); + /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - LLPointer mAlphaRampImagep; - LLPointer m2DAlphaRampImagep; - LLPointer mAlphaNoiseImagep; + LLPointer mAlphaRampImagep; + LLPointer m2DAlphaRampImagep; + LLPointer mAlphaNoiseImagep; - static S32 sPBRDetailMode; - static F32 sDetailScale; // textures per meter - static F32 sPBRDetailScale; // textures per meter + static S32 sPBRDetailMode; + static F32 sDetailScale; // textures per meter + static F32 sPBRDetailScale; // textures per meter protected: void boostTerrainDetailTextures(); - void renderSimple(); - void renderOwnership(); + void renderSimple(); + void renderOwnership(); - void renderFull2TU(); - void renderFull4TU(); - void renderFullShader(); - void renderFullShaderTextures(); - void renderFullShaderPBR(BOOL local_materials = false); - void drawLoop(); + void renderFull2TU(); + void renderFull4TU(); + void renderFullShader(); + void renderFullShaderTextures(); + void renderFullShaderPBR(BOOL local_materials = false); + void drawLoop(); private: - void hilightParcelOwners(); + void hilightParcelOwners(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 50c4a2c1b3..43620747d4 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpooltree.cpp * @brief LLDrawPoolTree class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -44,10 +44,10 @@ S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) : - LLFacePool(POOL_TREE), - mTexturep(texturep) + LLFacePool(POOL_TREE), + mTexturep(texturep) { - mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); + mTexturep->setAddressMode(LLTexUnit::TAM_WRAP); } //============================================ @@ -55,11 +55,11 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) : //============================================ void LLDrawPoolTree::beginDeferredPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); - - shader = &gDeferredTreeProgram; - shader->bind(); - shader->setMinimumAlpha(0.5f); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); + + shader = &gDeferredTreeProgram; + shader->bind(); + shader->setMinimumAlpha(0.5f); } void LLDrawPoolTree::renderDeferred(S32 pass) @@ -96,9 +96,9 @@ void LLDrawPoolTree::renderDeferred(S32 pass) void LLDrawPoolTree::endDeferredPass(S32 pass) { - LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); - - shader->unbind(); + LL_RECORD_BLOCK_TIME(FTM_RENDER_TREES); + + shader->unbind(); } //============================================ @@ -107,49 +107,49 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) void LLDrawPoolTree::beginShadowPass(S32 pass) { LL_PROFILE_ZONE_SCOPED; - - glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), - gSavedSettings.getF32("RenderDeferredTreeShadowBias")); + + glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), + gSavedSettings.getF32("RenderDeferredTreeShadowBias")); LLEnvironment& environment = LLEnvironment::instance(); - gDeferredTreeShadowProgram.bind(); + gDeferredTreeShadowProgram.bind(); gDeferredTreeShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - gDeferredTreeShadowProgram.setMinimumAlpha(0.5f); + gDeferredTreeShadowProgram.setMinimumAlpha(0.5f); } void LLDrawPoolTree::renderShadow(S32 pass) { - renderDeferred(pass); + renderDeferred(pass); } void LLDrawPoolTree::endShadowPass(S32 pass) { LL_PROFILE_ZONE_SCOPED; - - glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), - gSavedSettings.getF32("RenderDeferredSpotShadowBias")); - gDeferredTreeShadowProgram.unbind(); + + glPolygonOffset(gSavedSettings.getF32("RenderDeferredSpotShadowOffset"), + gSavedSettings.getF32("RenderDeferredSpotShadowBias")); + gDeferredTreeShadowProgram.unbind(); } BOOL LLDrawPoolTree::verify() const { - return TRUE; + return TRUE; } LLViewerTexture *LLDrawPoolTree::getTexture() { - return mTexturep; + return mTexturep; } LLViewerTexture *LLDrawPoolTree::getDebugTexture() { - return mTexturep; + return mTexturep; } LLColor3 LLDrawPoolTree::getDebugColor() const { - return LLColor3(1.f, 0.f, 1.f); + return LLColor3(1.f, 0.f, 1.f); } diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 68be354533..c16b6408d7 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldrawpoolwlsky.cpp * @brief LLDrawPoolWLSky class implementation * * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -33,7 +33,7 @@ #include "llimage.h" #include "llrender.h" #include "llatmosphere.h" -#include "llenvironment.h" +#include "llenvironment.h" #include "llglslshader.h" #include "llgl.h" @@ -59,7 +59,7 @@ static LLGLSLShader* moon_shader = NULL; static float sStarTime; LLDrawPoolWLSky::LLDrawPoolWLSky(void) : - LLDrawPool(POOL_WL_SKY) + LLDrawPool(POOL_WL_SKY) { } @@ -69,13 +69,13 @@ LLDrawPoolWLSky::~LLDrawPoolWLSky() LLViewerTexture *LLDrawPoolWLSky::getDebugTexture() { - return NULL; + return NULL; } void LLDrawPoolWLSky::beginDeferredPass(S32 pass) { - sky_shader = &gDeferredWLSkyProgram; - cloud_shader = &gDeferredWLCloudProgram; + sky_shader = &gDeferredWLSkyProgram; + cloud_shader = &gDeferredWLCloudProgram; sun_shader = &gDeferredWLSunProgram; @@ -98,34 +98,34 @@ void LLDrawPoolWLSky::renderDome(const LLVector3& camPosLocal, F32 camHeightLoca llassert_always(NULL != shader); gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - - //chop off translation - if (LLPipeline::sReflectionRender && camPosLocal.mV[2] > 256.f) - { - gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], 256.f-camPosLocal.mV[2]*0.5f); - } - else - { - gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]); - } - - - // the windlight sky dome works most conveniently in a coordinate system - // where Y is up, so permute our basis vectors accordingly. - gGL.rotatef(120.f, 1.f / F_SQRT3, 1.f / F_SQRT3, 1.f / F_SQRT3); - - gGL.scalef(0.333f, 0.333f, 0.333f); - - gGL.translatef(0.f,-camHeightLocal, 0.f); - - // Draw WL Sky - shader->uniform3f(sCamPosLocal, 0.f, camHeightLocal, 0.f); + gGL.pushMatrix(); + + //chop off translation + if (LLPipeline::sReflectionRender && camPosLocal.mV[2] > 256.f) + { + gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], 256.f-camPosLocal.mV[2]*0.5f); + } + else + { + gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]); + } + + + // the windlight sky dome works most conveniently in a coordinate system + // where Y is up, so permute our basis vectors accordingly. + gGL.rotatef(120.f, 1.f / F_SQRT3, 1.f / F_SQRT3, 1.f / F_SQRT3); + + gGL.scalef(0.333f, 0.333f, 0.333f); + + gGL.translatef(0.f,-camHeightLocal, 0.f); + + // Draw WL Sky + shader->uniform3f(sCamPosLocal, 0.f, camHeightLocal, 0.f); gSky.mVOWLSkyp->drawDome(); gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gGL.popMatrix(); } extern LLPointer gEXRImage; @@ -150,8 +150,8 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); - if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) - { + if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) + { if (use_hdri_sky()) { sky_shader = &gEnvironmentMapProgram; @@ -211,9 +211,9 @@ void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 ca sky_shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, psky->getIsSunUp() ? 1 : 0); /// Render the skydome - renderDome(origin, camHeightLocal, sky_shader); + renderDome(origin, camHeightLocal, sky_shader); - sky_shader->unbind(); + sky_shader->unbind(); } } @@ -224,30 +224,30 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const return; } - LLGLSPipelineBlendSkyBox gls_sky(true, false); + LLGLSPipelineBlendSkyBox gls_sky(true, false); - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); F32 star_alpha = LLEnvironment::instance().getCurrentSky()->getStarBrightness() / 500.0f; - // If start_brightness is not set, exit - if(star_alpha < 0.001f) - { - LL_DEBUGS("SKY") << "star_brightness below threshold." << LL_ENDL; - return; - } + // If start_brightness is not set, exit + if(star_alpha < 0.001f) + { + LL_DEBUGS("SKY") << "star_brightness below threshold." << LL_ENDL; + return; + } - gDeferredStarProgram.bind(); + gDeferredStarProgram.bind(); LLViewerTexture* tex_a = gSky.mVOSkyp->getBloomTex(); LLViewerTexture* tex_b = gSky.mVOSkyp->getBloomTexNext(); F32 blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor(); - + if (tex_a && (!tex_b || (tex_a == tex_b))) { // Bind current and next sun textures - gGL.getTexUnit(0)->bind(tex_a); + gGL.getTexUnit(0)->bind(tex_a); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); blend_factor = 0; } @@ -263,29 +263,29 @@ void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const gGL.getTexUnit(1)->bind(tex_b); } - gGL.pushMatrix(); - gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]); - gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); + gGL.pushMatrix(); + gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]); + gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); gDeferredStarProgram.uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); if (LLPipeline::sReflectionRender) { star_alpha = 1.0f; } - gDeferredStarProgram.uniform1f(sCustomAlpha, star_alpha); + gDeferredStarProgram.uniform1f(sCustomAlpha, star_alpha); sStarTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; gDeferredStarProgram.uniform1f(LLShaderMgr::WATER_TIME, sStarTime); - gSky.mVOWLSkyp->drawStars(); + gSky.mVOWLSkyp->drawStars(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); gDeferredStarProgram.unbind(); - gGL.popMatrix(); + gGL.popMatrix(); } void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const @@ -295,13 +295,13 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 return; } - if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp && gSky.mVOSkyp->getCloudNoiseTex()) - { + if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp && gSky.mVOSkyp->getCloudNoiseTex()) + { LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - LLGLSPipelineBlendSkyBox pipeline(true, true); - - cloudshader->bind(); + LLGLSPipelineBlendSkyBox pipeline(true, true); + + cloudshader->bind(); LLPointer cloud_noise = gSky.mVOSkyp->getCloudNoiseTex(); LLPointer cloud_noise_next = gSky.mVOSkyp->getCloudNoiseTexNext(); @@ -342,14 +342,14 @@ void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance); cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor()); - /// Render the skydome + /// Render the skydome renderDome(camPosLocal, camHeightLocal, cloudshader); - cloudshader->unbind(); + cloudshader->unbind(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); - } + } } void LLDrawPoolWLSky::renderHeavenlyBodies() @@ -359,19 +359,19 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLGLSPipelineBlendSkyBox gls_skybox(true, true); // SL-14113 we need moon to write to depth to clip stars behind LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); - gGL.pushMatrix(); - gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); + gGL.pushMatrix(); + gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]); - LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN]; + LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN]; F32 blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor(); bool can_use_vertex_shaders = gPipeline.shadersLoaded(); bool can_use_windlight_shaders = gPipeline.canUseWindLightShaders(); - if (gSky.mVOSkyp->getSun().getDraw() && face && face->getGeomCount()) - { - LLPointer tex_a = face->getTexture(LLRender::DIFFUSE_MAP); + if (gSky.mVOSkyp->getSun().getDraw() && face && face->getGeomCount()) + { + LLPointer tex_a = face->getTexture(LLRender::DIFFUSE_MAP); LLPointer tex_b = face->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -415,17 +415,17 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() sun_shader->unbind(); } } - } + } - face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]; + face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]; - if (gSky.mVOSkyp->getMoon().getDraw() && face && face->getTexture(LLRender::DIFFUSE_MAP) && face->getGeomCount() && moon_shader) - { + if (gSky.mVOSkyp->getMoon().getDraw() && face && face->getTexture(LLRender::DIFFUSE_MAP) && face->getGeomCount() && moon_shader) + { LLViewerTexture* tex_a = face->getTexture(LLRender::DIFFUSE_MAP); LLViewerTexture* tex_b = face->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP); - LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor()); - + LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor()); + if (can_use_vertex_shaders && can_use_windlight_shaders && (tex_a || tex_b)) { moon_shader->bind(); @@ -472,10 +472,10 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() void LLDrawPoolWLSky::renderDeferred(S32 pass) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY); - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY) || gSky.mVOSkyp.isNull()) - { - return; - } + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY) || gSky.mVOSkyp.isNull()) + { + return; + } // TODO: remove gSky.mVOSkyp and fold sun/moon into LLVOWLSky gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable); @@ -504,7 +504,7 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass) LLViewerTexture* LLDrawPoolWLSky::getTexture() { - return NULL; + return NULL; } void LLDrawPoolWLSky::resetDrawOrders() diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 24818241ab..f1145948a7 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lldynamictexture.cpp * @brief Implementation of LLViewerDynamicTexture class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -30,7 +30,7 @@ // Linden library includes #include "llglheaders.h" -#include "llwindow.h" // getPosition() +#include "llwindow.h" // getPosition() // Viewer includes #include "llviewerwindow.h" @@ -50,16 +50,16 @@ S32 LLViewerDynamicTexture::sNumRenders = 0; //----------------------------------------------------------------------------- // LLViewerDynamicTexture() //----------------------------------------------------------------------------- -LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) : - LLViewerTexture(width, height, components, FALSE), - mClamp(clamp) +LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 components, EOrder order, BOOL clamp) : + LLViewerTexture(width, height, components, FALSE), + mClamp(clamp) { - llassert((1 <= components) && (components <= 4)); + llassert((1 <= components) && (components <= 4)); - generateGLTexture(); + generateGLTexture(); - llassert( 0 <= order && order < ORDER_COUNT ); - LLViewerDynamicTexture::sInstances[ order ].insert(this); + llassert( 0 <= order && order < ORDER_COUNT ); + LLViewerDynamicTexture::sInstances[ order ].insert(this); } //----------------------------------------------------------------------------- @@ -67,16 +67,16 @@ LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 compon //----------------------------------------------------------------------------- LLViewerDynamicTexture::~LLViewerDynamicTexture() { - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. - } + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case. + } } -//virtual +//virtual S8 LLViewerDynamicTexture::getType() const { - return LLViewerTexture::DYNAMIC_TEXTURE ; + return LLViewerTexture::DYNAMIC_TEXTURE ; } //----------------------------------------------------------------------------- @@ -84,25 +84,25 @@ S8 LLViewerDynamicTexture::getType() const //----------------------------------------------------------------------------- void LLViewerDynamicTexture::generateGLTexture() { - LLViewerTexture::generateGLTexture() ; - generateGLTexture(-1, 0, 0, FALSE); + LLViewerTexture::generateGLTexture() ; + generateGLTexture(-1, 0, 0, FALSE); } void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) { - if (mComponents < 1 || mComponents > 4) - { - LL_ERRS() << "Bad number of components in dynamic texture: " << mComponents << LL_ENDL; - } - - LLPointer raw_image = new LLImageRaw(mFullWidth, mFullHeight, mComponents); - if (internal_format >= 0) - { - setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); - } - createGLTexture(0, raw_image, 0, TRUE, LLGLTexture::DYNAMIC_TEX); - setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); - mGLTexturep->setGLTextureCreated(false); + if (mComponents < 1 || mComponents > 4) + { + LL_ERRS() << "Bad number of components in dynamic texture: " << mComponents << LL_ENDL; + } + + LLPointer raw_image = new LLImageRaw(mFullWidth, mFullHeight, mComponents); + if (internal_format >= 0) + { + setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); + } + createGLTexture(0, raw_image, 0, TRUE, LLGLTexture::DYNAMIC_TEX); + setAddressMode((mClamp) ? LLTexUnit::TAM_CLAMP : LLTexUnit::TAM_WRAP); + mGLTexturep->setGLTextureCreated(false); } //----------------------------------------------------------------------------- @@ -110,7 +110,7 @@ void LLViewerDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum //----------------------------------------------------------------------------- BOOL LLViewerDynamicTexture::render() { - return FALSE; + return FALSE; } //----------------------------------------------------------------------------- @@ -121,22 +121,22 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //use the bottom left corner - mOrigin.set(0, 0); + mOrigin.set(0, 0); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // Set up camera - LLViewerCamera* camera = LLViewerCamera::getInstance(); - mCamera.setOrigin(*camera); - mCamera.setAxes(*camera); - mCamera.setAspect(camera->getAspect()); - mCamera.setView(camera->getView()); - mCamera.setNear(camera->getNear()); - - glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); - if (clear_depth) - { - glClear(GL_DEPTH_BUFFER_BIT); - } + // Set up camera + LLViewerCamera* camera = LLViewerCamera::getInstance(); + mCamera.setOrigin(*camera); + mCamera.setAxes(*camera); + mCamera.setAspect(camera->getAspect()); + mCamera.setView(camera->getView()); + mCamera.setNear(camera->getNear()); + + glViewport(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); + if (clear_depth) + { + glClear(GL_DEPTH_BUFFER_BIT); + } } //----------------------------------------------------------------------------- @@ -144,36 +144,36 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) //----------------------------------------------------------------------------- void LLViewerDynamicTexture::postRender(BOOL success) { - { - if (success) - { - if(mGLTexturep.isNull()) - { - generateGLTexture() ; - } - else if(!mGLTexturep->getHasGLTexture()) - { - generateGLTexture() ; - } - else if(mGLTexturep->getDiscardLevel() != 0)//do not know how it happens, but regenerate one if it does. - { - generateGLTexture() ; - } - - success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); - } - } - - // restore viewport - gViewerWindow->setup2DViewport(); - - // restore camera - LLViewerCamera* camera = LLViewerCamera::getInstance(); - camera->setOrigin(mCamera); - camera->setAxes(mCamera); - camera->setAspect(mCamera.getAspect()); - camera->setViewNoBroadcast(mCamera.getView()); - camera->setNear(mCamera.getNear()); + { + if (success) + { + if(mGLTexturep.isNull()) + { + generateGLTexture() ; + } + else if(!mGLTexturep->getHasGLTexture()) + { + generateGLTexture() ; + } + else if(mGLTexturep->getDiscardLevel() != 0)//do not know how it happens, but regenerate one if it does. + { + generateGLTexture() ; + } + + success = mGLTexturep->setSubImageFromFrameBuffer(0, 0, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight); + } + } + + // restore viewport + gViewerWindow->setup2DViewport(); + + // restore camera + LLViewerCamera* camera = LLViewerCamera::getInstance(); + camera->setOrigin(mCamera); + camera->setAxes(mCamera); + camera->setAspect(mCamera.getAspect()); + camera->setViewNoBroadcast(mCamera.getView()); + camera->setNear(mCamera.getNear()); } //----------------------------------------------------------------------------- @@ -185,18 +185,18 @@ BOOL LLViewerDynamicTexture::updateAllInstances() { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - sNumRenders = 0; - if (gGLManager.mIsDisabled) - { - return TRUE; - } + sNumRenders = 0; + if (gGLManager.mIsDisabled) + { + return TRUE; + } LLRenderTarget& bake_target = gPipeline.mAuxillaryRT.deferredScreen; - if (!bake_target.isComplete()) + if (!bake_target.isComplete()) { llassert(false); - return FALSE; + return FALSE; } llassert(bake_target.getWidth() >= LLPipeline::MAX_BAKE_WIDTH); llassert(bake_target.getHeight() >= LLPipeline::MAX_BAKE_WIDTH); @@ -204,47 +204,47 @@ BOOL LLViewerDynamicTexture::updateAllInstances() bake_target.bindTarget(); bake_target.clear(); - LLGLSLShader::unbind(); - LLVertexBuffer::unbind(); - - BOOL result = FALSE; - BOOL ret = FALSE ; - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); - iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) - { - LLViewerDynamicTexture *dynamicTexture = *iter; - if (dynamicTexture->needsRender()) - { + LLGLSLShader::unbind(); + LLVertexBuffer::unbind(); + + BOOL result = FALSE; + BOOL ret = FALSE ; + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); + iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) + { + LLViewerDynamicTexture *dynamicTexture = *iter; + if (dynamicTexture->needsRender()) + { llassert(dynamicTexture->getFullWidth() <= LLPipeline::MAX_BAKE_WIDTH); llassert(dynamicTexture->getFullHeight() <= LLPipeline::MAX_BAKE_WIDTH); - glClear(GL_DEPTH_BUFFER_BIT); - - gGL.color4f(1,1,1,1); + glClear(GL_DEPTH_BUFFER_BIT); + + gGL.color4f(1,1,1,1); dynamicTexture->setBoundTarget(&bake_target); - dynamicTexture->preRender(); // Must be called outside of startRender() - result = FALSE; - if (dynamicTexture->render()) - { - ret = TRUE ; - result = TRUE; - sNumRenders++; - } - gGL.flush(); - LLVertexBuffer::unbind(); - dynamicTexture->setBoundTarget(nullptr); - dynamicTexture->postRender(result); - } - } - } - - bake_target.flush(); + dynamicTexture->preRender(); // Must be called outside of startRender() + result = FALSE; + if (dynamicTexture->render()) + { + ret = TRUE ; + result = TRUE; + sNumRenders++; + } + gGL.flush(); + LLVertexBuffer::unbind(); + dynamicTexture->setBoundTarget(nullptr); + dynamicTexture->postRender(result); + } + } + } + + bake_target.flush(); gGL.flush(); - return ret; + return ret; } //----------------------------------------------------------------------------- @@ -253,15 +253,15 @@ BOOL LLViewerDynamicTexture::updateAllInstances() //----------------------------------------------------------------------------- void LLViewerDynamicTexture::destroyGL() { - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); - iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) - { - LLViewerDynamicTexture *dynamicTexture = *iter; - dynamicTexture->destroyGLTexture() ; - } - } + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); + iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) + { + LLViewerDynamicTexture *dynamicTexture = *iter; + dynamicTexture->destroyGLTexture() ; + } + } } //----------------------------------------------------------------------------- @@ -270,18 +270,18 @@ void LLViewerDynamicTexture::destroyGL() //----------------------------------------------------------------------------- void LLViewerDynamicTexture::restoreGL() { - if (gGLManager.mIsDisabled) - { - return ; - } - - for( S32 order = 0; order < ORDER_COUNT; order++ ) - { - for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); - iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) - { - LLViewerDynamicTexture *dynamicTexture = *iter; - dynamicTexture->restoreGLTexture() ; - } - } + if (gGLManager.mIsDisabled) + { + return ; + } + + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + for (instance_list_t::iterator iter = LLViewerDynamicTexture::sInstances[order].begin(); + iter != LLViewerDynamicTexture::sInstances[order].end(); ++iter) + { + LLViewerDynamicTexture *dynamicTexture = *iter; + dynamicTexture->restoreGLTexture() ; + } + } } diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 0b535e15b0..247a487ace 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2011, 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$ */ @@ -94,7 +94,7 @@ namespace const std::string KEY_ACTION("action"); const std::string KEY_ACTIONDATA("action_data"); const std::string KEY_EXPERIENCEID("public_id"); - const std::string KEY_OBJECTNAME("ObjectName"); // some of these do not conform to the '_' format. + const std::string KEY_OBJECTNAME("ObjectName"); // some of these do not conform to the '_' format. const std::string KEY_PARCELNAME("ParcelName"); // But changing these would also alter the Experience Log requirements. const std::string KEY_COUNT("Count"); @@ -370,13 +370,13 @@ namespace virtual ~LLSettingsInjected() {}; typename SETTINGT::ptr_t getSource() const { return this->mSource; } - void setSource(const typename SETTINGT::ptr_t &source) + void setSource(const typename SETTINGT::ptr_t &source) { if (source.get() == this) // do not set a source to itself. return; - this->mSource = source; - this->setDirtyFlag(true); - this->mLastSourceHash = 0; + this->mSource = source; + this->setDirtyFlag(true); + this->mLastSourceHash = 0; } virtual bool isDirty() const override { return SETTINGT::isDirty() || (this->mSource->isDirty()); } @@ -565,7 +565,7 @@ namespace if (!this->mSource) return; - // clears the dirty flag on this object. Need to prevent triggering + // clears the dirty flag on this object. Need to prevent triggering // more calls into this updateSettings LLSettingsBase::updateSettings(); @@ -824,7 +824,7 @@ const S32 LLEnvironment::NO_TRACK(-1); const S32 LLEnvironment::NO_VERSION(-3); // For viewer sided change, like ENV_LOCAL. -3 since -1 and -2 are taken by parcel initial server/viewer version const S32 LLEnvironment::VERSION_CLEANUP(-4); // for cleanups -const F32 LLEnvironment::SUN_DELTA_YAW(F_PI); // 180deg +const F32 LLEnvironment::SUN_DELTA_YAW(F_PI); // 180deg const U32 LLEnvironment::DayInstance::NO_ANIMATE_SKY(0x01); @@ -929,9 +929,9 @@ bool LLEnvironment::canEdit() const return true; } -LLSettingsSky::ptr_t LLEnvironment::getCurrentSky() const -{ - LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky(); +LLSettingsSky::ptr_t LLEnvironment::getCurrentSky() const +{ + LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky(); if (!psky && mCurrentEnvironment->getEnvironmentSelection() >= ENV_EDIT) { @@ -947,9 +947,9 @@ LLSettingsSky::ptr_t LLEnvironment::getCurrentSky() const return psky; } -LLSettingsWater::ptr_t LLEnvironment::getCurrentWater() const +LLSettingsWater::ptr_t LLEnvironment::getCurrentWater() const { - LLSettingsWater::ptr_t pwater = mCurrentEnvironment->getWater(); + LLSettingsWater::ptr_t pwater = mCurrentEnvironment->getWater(); if (!pwater && mCurrentEnvironment->getEnvironmentSelection() >= ENV_EDIT) { @@ -1235,7 +1235,7 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironm } } } - + if (fixed.second) { logEnvironment(env, fixed.second, env_version); @@ -1531,12 +1531,12 @@ void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool f { if (transition != TRANSITION_INSTANT) { - DayInstance::ptr_t trans = std::make_shared( - mCurrentEnvironment->getSky(), mCurrentEnvironment->getWater(), pinstance, transition); - - trans->animate(); - - mCurrentEnvironment = trans; + DayInstance::ptr_t trans = std::make_shared( + mCurrentEnvironment->getSky(), mCurrentEnvironment->getWater(), pinstance, transition); + + trans->animate(); + + mCurrentEnvironment = trans; } else { @@ -1696,12 +1696,12 @@ void LLEnvironment::update(const LLViewerCamera * cam) void LLEnvironment::updateCloudScroll() { - // This is a function of the environment rather than the sky, since it should + // This is a function of the environment rather than the sky, since it should // persist through sky transitions. static LLTimer s_cloud_timer; F64 delta_t = s_cloud_timer.getElapsedTimeAndResetF64(); - + if (mCurrentEnvironment->getSky() && !mCloudScrollPaused) { LLVector2 rate = mCurrentEnvironment->getSky()->getCloudScrollRate(); @@ -1786,7 +1786,7 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con }; switch (it.second.getShaderKey()) - { + { case LLShaderMgr::BLUE_HORIZON: case LLShaderMgr::BLUE_DENSITY: vect4 = max_vec(vect4); @@ -2188,7 +2188,7 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf query << "&"; } if (track_no != NO_TRACK) - { + { query << "trackno=" << track_no; } url += query.str(); @@ -2271,7 +2271,7 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url); // results that come back may contain the new settings - LLSD notify; + LLSD notify; LLSD httpResults = result["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); @@ -2551,7 +2551,7 @@ void LLEnvironment::onAgentPositionHasChanged(const LLVector3 &localpos) S32 LLEnvironment::calculateSkyTrackForAltitude(F64 altitude) { auto it = std::find_if_not(mTrackAltitudes.begin(), mTrackAltitudes.end(), [altitude](F32 test) { return altitude > test; }); - + if (it == mTrackAltitudes.begin()) return 1; else if (it == mTrackAltitudes.end()) @@ -2575,19 +2575,19 @@ void LLEnvironment::handleEnvironmentPush(LLSD &message) if (action == ACTION_CLEARENVIRONMENT) - { + { handleEnvironmentPushClear(experience_id, action_data, transition_time); } else if (action == ACTION_PUSHFULLENVIRONMENT) - { + { handleEnvironmentPushFull(experience_id, action_data, transition_time); } else if (action == ACTION_PUSHPARTIALENVIRONMENT) - { + { handleEnvironmentPushPartial(experience_id, action_data, transition_time); } else - { + { LL_WARNS("ENVIRONMENT", "GENERICMESSAGES") << "Unknown environment push action '" << action << "'" << LL_ENDL; } } @@ -2801,9 +2801,9 @@ bool LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky) mInitialized = false; bool changed = psky == nullptr || mSky == nullptr || mSky->getHash() != psky->getHash(); - + bool different_sky = mSky != psky; - + mSky = psky; mSky->mReplaced |= different_sky; mSky->update(); @@ -2938,7 +2938,7 @@ LLEnvironment::DayTransition::DayTransition(const LLSettingsSky::ptr_t &skystart mNextInstance(end), mTransitionTime(time) { - + } bool LLEnvironment::DayTransition::applyTimeDelta(const LLSettingsBase::Seconds& delta) @@ -2950,14 +2950,14 @@ bool LLEnvironment::DayTransition::applyTimeDelta(const LLSettingsBase::Seconds& return changed; } -void LLEnvironment::DayTransition::animate() +void LLEnvironment::DayTransition::animate() { mNextInstance->animate(); mWater = mStartWater->buildClone(); mBlenderWater = std::make_shared(mWater, mStartWater, mNextInstance->getWater(), mTransitionTime); mBlenderWater->setOnFinished( - [this](LLSettingsBlender::ptr_t blender) { + [this](LLSettingsBlender::ptr_t blender) { mBlenderWater.reset(); if (!mBlenderSky && !mBlenderWater) @@ -3366,8 +3366,8 @@ namespace return changed; } - void DayInjection::setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday) - { + void DayInjection::setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday) + { mBaseDayInstance = baseday; if (mSkyExperience.isNull()) @@ -3576,7 +3576,7 @@ namespace mBlenderSky = std::make_shared(target_sky, start_sky, psky, transition); mBlenderSky->setOnFinished( - [this, psky](LLSettingsBlender::ptr_t blender) + [this, psky](LLSettingsBlender::ptr_t blender) { mBlenderSky.reset(); mInjectedSky->setSource(psky); @@ -3600,7 +3600,7 @@ namespace return; } if (transition == LLEnvironment::TRANSITION_INSTANT) - { + { mBlenderWater.reset(); mInjectedWater->setSource(pwater); } @@ -3612,7 +3612,7 @@ namespace mBlenderWater = std::make_shared(scratch_Water, start_Water, pwater, transition); mBlenderWater->setOnFinished( - [this, pwater](LLSettingsBlender::ptr_t blender) + [this, pwater](LLSettingsBlender::ptr_t blender) { mBlenderWater.reset(); mInjectedWater->setSource(pwater); @@ -3633,7 +3633,7 @@ namespace LLEnvironment::EnvSelection_t base_env(mBaseDayInstance->getEnvironmentSelection()); LLEnvironment::DayInstance::ptr_t nextbase = LLEnvironment::instance().getSharedEnvironmentInstance(); - if ((base_env == LLEnvironment::ENV_NONE) || (nextbase == mBaseDayInstance) || + if ((base_env == LLEnvironment::ENV_NONE) || (nextbase == mBaseDayInstance) || (!mSkyExperience.isNull() && !mWaterExperience.isNull())) { // base instance completely overridden, or not changed no transition will happen return; @@ -3665,7 +3665,7 @@ namespace void DayInjection::checkExperience() { if ((!mDayExperience.isNull()) && (mSkyExperience != mDayExperience) && (mWaterExperience != mDayExperience)) - { // There was a day experience but we've replaced it with a water and a sky experience. + { // There was a day experience but we've replaced it with a water and a sky experience. mDayExperience.setNull(); mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance(); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index ccee57cf69..0b1ceaa977 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llface.cpp * @brief LLFace class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -75,49 +75,49 @@ BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE /* For each vertex, given: - B - binormal - T - tangent - N - normal - P - position + B - binormal + T - tangent + N - normal + P - position The resulting texture coordinate is: - u = 2(B dot P) - v = 2(T dot P) + u = 2(B dot P) + v = 2(T dot P) */ void planarProjection(LLVector2 &tc, const LLVector4a& normal, - const LLVector4a ¢er, const LLVector4a& vec) -{ - LLVector4a binormal; - F32 d = normal[0]; - - if (d >= 0.5f || d <= -0.5f) - { - if (d < 0) - { - binormal.set(0,-1,0); - } - else - { - binormal.set(0, 1, 0); - } - } - else - { + const LLVector4a ¢er, const LLVector4a& vec) +{ + LLVector4a binormal; + F32 d = normal[0]; + + if (d >= 0.5f || d <= -0.5f) + { + if (d < 0) + { + binormal.set(0,-1,0); + } + else + { + binormal.set(0, 1, 0); + } + } + else + { if (normal[1] > 0) - { - binormal.set(-1,0,0); - } - else - { - binormal.set(1,0,0); - } - } - LLVector4a tangent; - tangent.setCross3(binormal,normal); - - tc.mV[1] = -((tangent.dot3(vec).getF32())*2 - 0.5f); - tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f); + { + binormal.set(-1,0,0); + } + else + { + binormal.set(1,0,0); + } + } + LLVector4a tangent; + tangent.setCross3(binormal,normal); + + tc.mV[1] = -((tangent.dot3(vec).getF32())*2 - 0.5f); + tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f); } //////////////////// @@ -128,174 +128,174 @@ void planarProjection(LLVector2 &tc, const LLVector4a& normal, void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) { LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; - mLastUpdateTime = gFrameTimeSeconds; - mLastMoveTime = 0.f; - mLastSkinTime = gFrameTimeSeconds; - mVSize = 0.f; - mPixelArea = 16.f; - mState = GLOBAL; - mDrawPoolp = NULL; - mPoolType = 0; - mCenterLocal = objp->getPosition(); - mCenterAgent = drawablep->getPositionAgent(); - mDistance = 0.f; - - mGeomCount = 0; - mGeomIndex = 0; - mIndicesCount = 0; - - //special value to indicate uninitialized position - mIndicesIndex = 0xFFFFFFFF; - - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - mIndexInTex[i] = 0; - mTexture[i] = NULL; - } - - mTEOffset = -1; - mTextureIndex = FACE_DO_NOT_BATCH_TEXTURES; - - setDrawable(drawablep); - mVObjp = objp; - - mReferenceIndex = -1; - - mTextureMatrix = NULL; - mDrawInfo = NULL; - - mFaceColor = LLColor4(1,0,0,1); - - mImportanceToCamera = 0.f ; - mBoundingSphereRadius = 0.0f ; - - mHasMedia = false ; - mIsMediaAllowed = true; + mLastUpdateTime = gFrameTimeSeconds; + mLastMoveTime = 0.f; + mLastSkinTime = gFrameTimeSeconds; + mVSize = 0.f; + mPixelArea = 16.f; + mState = GLOBAL; + mDrawPoolp = NULL; + mPoolType = 0; + mCenterLocal = objp->getPosition(); + mCenterAgent = drawablep->getPositionAgent(); + mDistance = 0.f; + + mGeomCount = 0; + mGeomIndex = 0; + mIndicesCount = 0; + + //special value to indicate uninitialized position + mIndicesIndex = 0xFFFFFFFF; + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + mIndexInTex[i] = 0; + mTexture[i] = NULL; + } + + mTEOffset = -1; + mTextureIndex = FACE_DO_NOT_BATCH_TEXTURES; + + setDrawable(drawablep); + mVObjp = objp; + + mReferenceIndex = -1; + + mTextureMatrix = NULL; + mDrawInfo = NULL; + + mFaceColor = LLColor4(1,0,0,1); + + mImportanceToCamera = 0.f ; + mBoundingSphereRadius = 0.0f ; + + mHasMedia = false ; + mIsMediaAllowed = true; } void LLFace::destroy() { - if (gDebugGL) - { - gPipeline.checkReferences(this); - } - - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - if(mTexture[i].notNull()) - { - mTexture[i]->removeFace(i, this) ; - mTexture[i] = NULL; - } - } - - if (isState(LLFace::PARTICLE)) - { - clearState(LLFace::PARTICLE); - } - - if (mDrawPoolp) - { - mDrawPoolp->removeFace(this); - mDrawPoolp = NULL; - } - - if (mTextureMatrix) - { - delete mTextureMatrix; - mTextureMatrix = NULL; - - if (mDrawablep) - { - LLSpatialGroup* group = mDrawablep->getSpatialGroup(); - if (group) - { - group->dirtyGeom(); - gPipeline.markRebuild(group); - } - } - } - - setDrawInfo(NULL); - - mDrawablep = NULL; - mVObjp = NULL; + if (gDebugGL) + { + gPipeline.checkReferences(this); + } + + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + if(mTexture[i].notNull()) + { + mTexture[i]->removeFace(i, this) ; + mTexture[i] = NULL; + } + } + + if (isState(LLFace::PARTICLE)) + { + clearState(LLFace::PARTICLE); + } + + if (mDrawPoolp) + { + mDrawPoolp->removeFace(this); + mDrawPoolp = NULL; + } + + if (mTextureMatrix) + { + delete mTextureMatrix; + mTextureMatrix = NULL; + + if (mDrawablep) + { + LLSpatialGroup* group = mDrawablep->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + gPipeline.markRebuild(group); + } + } + } + + setDrawInfo(NULL); + + mDrawablep = NULL; + mVObjp = NULL; } void LLFace::setWorldMatrix(const LLMatrix4 &mat) { - LL_ERRS() << "Faces on this drawable are not independently modifiable\n" << LL_ENDL; + LL_ERRS() << "Faces on this drawable are not independently modifiable\n" << LL_ENDL; } void LLFace::setPool(LLFacePool* pool) { - mDrawPoolp = pool; + mDrawPoolp = pool; } void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE - - if (!new_pool) - { - LL_ERRS() << "Setting pool to null!" << LL_ENDL; - } - - if (new_pool != mDrawPoolp) - { - // Remove from old pool - if (mDrawPoolp) - { - mDrawPoolp->removeFace(this); - - if (mDrawablep) - { - gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL); - } - } - mGeomIndex = 0; - - // Add to new pool - if (new_pool) - { - new_pool->addFace(this); - } - mDrawPoolp = new_pool; - } - - setTexture(texturep) ; + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE + + if (!new_pool) + { + LL_ERRS() << "Setting pool to null!" << LL_ENDL; + } + + if (new_pool != mDrawPoolp) + { + // Remove from old pool + if (mDrawPoolp) + { + mDrawPoolp->removeFace(this); + + if (mDrawablep) + { + gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL); + } + } + mGeomIndex = 0; + + // Add to new pool + if (new_pool) + { + new_pool->addFace(this); + } + mDrawPoolp = new_pool; + } + + setTexture(texturep) ; } -void LLFace::setTexture(U32 ch, LLViewerTexture* tex) +void LLFace::setTexture(U32 ch, LLViewerTexture* tex) { - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - - if(mTexture[ch] == tex) - { - return ; - } - - if(mTexture[ch].notNull()) - { - mTexture[ch]->removeFace(ch, this) ; - } - - if(tex) - { - tex->addFace(ch, this) ; - } - - mTexture[ch] = tex ; + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + + if(mTexture[ch] == tex) + { + return ; + } + + if(mTexture[ch].notNull()) + { + mTexture[ch]->removeFace(ch, this) ; + } + + if(tex) + { + tex->addFace(ch, this) ; + } + + mTexture[ch] = tex ; } -void LLFace::setTexture(LLViewerTexture* tex) +void LLFace::setTexture(LLViewerTexture* tex) { - setDiffuseMap(tex); + setDiffuseMap(tex); } void LLFace::setDiffuseMap(LLViewerTexture* tex) { - setTexture(LLRender::DIFFUSE_MAP, tex); + setTexture(LLRender::DIFFUSE_MAP, tex); } void LLFace::setAlternateDiffuseMap(LLViewerTexture* tex) @@ -305,278 +305,278 @@ void LLFace::setAlternateDiffuseMap(LLViewerTexture* tex) void LLFace::setNormalMap(LLViewerTexture* tex) { - setTexture(LLRender::NORMAL_MAP, tex); + setTexture(LLRender::NORMAL_MAP, tex); } void LLFace::setSpecularMap(LLViewerTexture* tex) { - setTexture(LLRender::SPECULAR_MAP, tex); + setTexture(LLRender::SPECULAR_MAP, tex); } void LLFace::dirtyTexture() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE - LLDrawable* drawablep = getDrawable(); + LLDrawable* drawablep = getDrawable(); - if (mVObjp.notNull() && mVObjp->getVolume()) - { - for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) - { - if (mTexture[ch].notNull() && mTexture[ch]->getComponents() == 4) - { //dirty texture on an alpha object should be treated as an LoD update - LLVOVolume* vobj = drawablep->getVOVolume(); - if (vobj) - { - vobj->mLODChanged = TRUE; + if (mVObjp.notNull() && mVObjp->getVolume()) + { + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + if (mTexture[ch].notNull() && mTexture[ch]->getComponents() == 4) + { //dirty texture on an alpha object should be treated as an LoD update + LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj) + { + vobj->mLODChanged = TRUE; vobj->updateVisualComplexity(); - } - gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); - } - } - } + } + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + } + } + } - gPipeline.markTextured(drawablep); + gPipeline.markTextured(drawablep); } void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture) { - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - if(mTexture[ch] == new_texture) - { - return ; - } + if(mTexture[ch] == new_texture) + { + return ; + } - if(!new_texture) - { - LL_ERRS() << "Can not switch to a null texture." << LL_ENDL; - return; - } + if(!new_texture) + { + LL_ERRS() << "Can not switch to a null texture." << LL_ENDL; + return; + } - llassert(mTexture[ch].notNull()); + llassert(mTexture[ch].notNull()); - if (ch == LLRender::DIFFUSE_MAP) - { - getViewerObject()->changeTEImage(mTEOffset, new_texture) ; - } + if (ch == LLRender::DIFFUSE_MAP) + { + getViewerObject()->changeTEImage(mTEOffset, new_texture) ; + } - setTexture(ch, new_texture) ; - dirtyTexture(); + setTexture(ch, new_texture) ; + dirtyTexture(); } void LLFace::setTEOffset(const S32 te_offset) { - mTEOffset = te_offset; + mTEOffset = te_offset; } void LLFace::setFaceColor(const LLColor4& color) { - mFaceColor = color; - setState(USE_FACE_COLOR); + mFaceColor = color; + setState(USE_FACE_COLOR); } void LLFace::unsetFaceColor() { - clearState(USE_FACE_COLOR); + clearState(USE_FACE_COLOR); } void LLFace::setDrawable(LLDrawable *drawable) { - mDrawablep = drawable; - mXform = &drawable->mXform; + mDrawablep = drawable; + mXform = &drawable->mXform; } void LLFace::setSize(S32 num_vertices, S32 num_indices, bool align) { - if (align) - { - //allocate vertices in blocks of 4 for alignment - num_vertices = (num_vertices + 0x3) & ~0x3; - } - - if (mGeomCount != num_vertices || - mIndicesCount != num_indices) - { - mGeomCount = num_vertices; - mIndicesCount = num_indices; - mVertexBuffer = NULL; - } - - llassert(verify()); + if (align) + { + //allocate vertices in blocks of 4 for alignment + num_vertices = (num_vertices + 0x3) & ~0x3; + } + + if (mGeomCount != num_vertices || + mIndicesCount != num_indices) + { + mGeomCount = num_vertices; + mIndicesCount = num_indices; + mVertexBuffer = NULL; + } + + llassert(verify()); } -void LLFace::setGeomIndex(U16 idx) -{ - if (mGeomIndex != idx) - { - mGeomIndex = idx; - mVertexBuffer = NULL; - } +void LLFace::setGeomIndex(U16 idx) +{ + if (mGeomIndex != idx) + { + mGeomIndex = idx; + mVertexBuffer = NULL; + } } void LLFace::setTextureIndex(U8 index) { - if (index != mTextureIndex) - { - mTextureIndex = index; - - if (mTextureIndex != FACE_DO_NOT_BATCH_TEXTURES) - { - mDrawablep->setState(LLDrawable::REBUILD_POSITION); - } - else - { - if (mDrawInfo && !mDrawInfo->mTextureList.empty()) - { - LL_ERRS() << "Face with no texture index references indexed texture draw info." << LL_ENDL; - } - } - } + if (index != mTextureIndex) + { + mTextureIndex = index; + + if (mTextureIndex != FACE_DO_NOT_BATCH_TEXTURES) + { + mDrawablep->setState(LLDrawable::REBUILD_POSITION); + } + else + { + if (mDrawInfo && !mDrawInfo->mTextureList.empty()) + { + LL_ERRS() << "Face with no texture index references indexed texture draw info." << LL_ENDL; + } + } + } } -void LLFace::setIndicesIndex(S32 idx) -{ - if (mIndicesIndex != idx) - { - mIndicesIndex = idx; - mVertexBuffer = NULL; - } +void LLFace::setIndicesIndex(S32 idx) +{ + if (mIndicesIndex != idx) + { + mIndicesIndex = idx; + mVertexBuffer = NULL; + } } - + //============================================================================ U16 LLFace::getGeometryAvatar( - LLStrider &vertices, - LLStrider &normals, - LLStrider &tex_coords, - LLStrider &vertex_weights, - LLStrider &clothing_weights) + LLStrider &vertices, + LLStrider &normals, + LLStrider &tex_coords, + LLStrider &vertex_weights, + LLStrider &clothing_weights) { - if (mVertexBuffer.notNull()) - { - mVertexBuffer->getVertexStrider (vertices, mGeomIndex, mGeomCount); - mVertexBuffer->getNormalStrider (normals, mGeomIndex, mGeomCount); - mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex, mGeomCount); - mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex, mGeomCount); - mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex, mGeomCount); - } - - return mGeomIndex; + if (mVertexBuffer.notNull()) + { + mVertexBuffer->getVertexStrider (vertices, mGeomIndex, mGeomCount); + mVertexBuffer->getNormalStrider (normals, mGeomIndex, mGeomCount); + mVertexBuffer->getTexCoord0Strider (tex_coords, mGeomIndex, mGeomCount); + mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex, mGeomCount); + mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex, mGeomCount); + } + + return mGeomIndex; } U16 LLFace::getGeometry(LLStrider &vertices, LLStrider &normals, - LLStrider &tex_coords, LLStrider &indicesp) + LLStrider &tex_coords, LLStrider &indicesp) { - if (mVertexBuffer.notNull()) - { - mVertexBuffer->getVertexStrider(vertices, mGeomIndex, mGeomCount); - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { - mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); - } - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0)) - { - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); - } - - mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); - } - - return mGeomIndex; + if (mVertexBuffer.notNull()) + { + mVertexBuffer->getVertexStrider(vertices, mGeomIndex, mGeomCount); + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + { + mVertexBuffer->getNormalStrider(normals, mGeomIndex, mGeomCount); + } + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD0)) + { + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount); + } + + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); + } + + return mGeomIndex; } void LLFace::updateCenterAgent() { - if (mDrawablep->isActive()) - { - mCenterAgent = mCenterLocal * getRenderMatrix(); - } - else - { - mCenterAgent = mCenterLocal; - } + if (mDrawablep->isActive()) + { + mCenterAgent = mCenterLocal * getRenderMatrix(); + } + else + { + mCenterAgent = mCenterLocal; + } } void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE - - if (mDrawablep == NULL || mDrawablep->getSpatialGroup() == NULL) - { - return; - } - - mDrawablep->getSpatialGroup()->rebuildGeom(); - mDrawablep->getSpatialGroup()->rebuildMesh(); - - if(mVertexBuffer.isNull()) - { - return; - } - - if (mGeomCount > 0 && mIndicesCount > 0) - { - gGL.getTexUnit(0)->bind(imagep); - - gGL.pushMatrix(); - if (mDrawablep->isActive()) - { - gGL.multMatrix((GLfloat*)mDrawablep->getRenderMatrix().mMatrix); - } - else - { - gGL.multMatrix((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); - } - - gGL.diffuseColor4fv(color.mV); - - if (mDrawablep->isState(LLDrawable::RIGGED)) - { + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE + + if (mDrawablep == NULL || mDrawablep->getSpatialGroup() == NULL) + { + return; + } + + mDrawablep->getSpatialGroup()->rebuildGeom(); + mDrawablep->getSpatialGroup()->rebuildMesh(); + + if(mVertexBuffer.isNull()) + { + return; + } + + if (mGeomCount > 0 && mIndicesCount > 0) + { + gGL.getTexUnit(0)->bind(imagep); + + gGL.pushMatrix(); + if (mDrawablep->isActive()) + { + gGL.multMatrix((GLfloat*)mDrawablep->getRenderMatrix().mMatrix); + } + else + { + gGL.multMatrix((GLfloat*)mDrawablep->getRegion()->mRenderMatrix.mMatrix); + } + + gGL.diffuseColor4fv(color.mV); + + if (mDrawablep->isState(LLDrawable::RIGGED)) + { #if 0 // TODO -- there is no way this won't destroy our GL machine as implemented, rewrite it to not rely on software skinning - LLVOVolume* volume = mDrawablep->getVOVolume(); - if (volume) - { - LLRiggedVolume* rigged = volume->getRiggedVolume(); - if (rigged) - { + LLVOVolume* volume = mDrawablep->getVOVolume(); + if (volume) + { + LLRiggedVolume* rigged = volume->getRiggedVolume(); + if (rigged) + { // called when selecting a face during edit of a mesh object - LLGLEnable offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f, -1.f); - gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); - const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset()); - LLVertexBuffer::unbind(); - glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions); - if (vol_face.mTexCoords) - { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords); - } - gGL.syncMatrices(); - glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - } + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, -1.f); + gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); + const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset()); + LLVertexBuffer::unbind(); + glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions); + if (vol_face.mTexCoords) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords); + } + gGL.syncMatrices(); + glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } #endif - } - else - { - // cheaters sometimes prosper... - // - mVertexBuffer->setBuffer(); - mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - } - - gGL.popMatrix(); - } + } + else + { + // cheaters sometimes prosper... + // + mVertexBuffer->setBuffer(); + mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); + } + + gGL.popMatrix(); + } } void renderFace(LLDrawable* drawable, LLFace *face) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE LLVOVolume* vobj = drawable->getVOVolume(); if (vobj) @@ -646,234 +646,234 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram void LLFace::setDrawInfo(LLDrawInfo* draw_info) { - mDrawInfo = draw_info; + mDrawInfo = draw_info; } void LLFace::printDebugInfo() const { - LLFacePool *poolp = getPool(); - LL_INFOS() << "Object: " << getViewerObject()->mID << LL_ENDL; - if (getDrawable()) - { - LL_INFOS() << "Type: " << LLPrimitive::pCodeToString(getDrawable()->getVObj()->getPCode()) << LL_ENDL; - } - if (getTexture()) - { - LL_INFOS() << "Texture: " << getTexture() << " Comps: " << (U32)getTexture()->getComponents() << LL_ENDL; - } - else - { - LL_INFOS() << "No texture: " << LL_ENDL; - } - - LL_INFOS() << "Face: " << this << LL_ENDL; - LL_INFOS() << "State: " << getState() << LL_ENDL; - LL_INFOS() << "Geom Index Data:" << LL_ENDL; - LL_INFOS() << "--------------------" << LL_ENDL; - LL_INFOS() << "GI: " << mGeomIndex << " Count:" << mGeomCount << LL_ENDL; - LL_INFOS() << "Face Index Data:" << LL_ENDL; - LL_INFOS() << "--------------------" << LL_ENDL; - LL_INFOS() << "II: " << mIndicesIndex << " Count:" << mIndicesCount << LL_ENDL; - LL_INFOS() << LL_ENDL; - - if (poolp) - { - poolp->printDebugInfo(); - - S32 pool_references = 0; - for (std::vector::iterator iter = poolp->mReferences.begin(); - iter != poolp->mReferences.end(); iter++) - { - LLFace *facep = *iter; - if (facep == this) - { - LL_INFOS() << "Pool reference: " << pool_references << LL_ENDL; - pool_references++; - } - } - - if (pool_references != 1) - { - LL_INFOS() << "Incorrect number of pool references!" << LL_ENDL; - } - } + LLFacePool *poolp = getPool(); + LL_INFOS() << "Object: " << getViewerObject()->mID << LL_ENDL; + if (getDrawable()) + { + LL_INFOS() << "Type: " << LLPrimitive::pCodeToString(getDrawable()->getVObj()->getPCode()) << LL_ENDL; + } + if (getTexture()) + { + LL_INFOS() << "Texture: " << getTexture() << " Comps: " << (U32)getTexture()->getComponents() << LL_ENDL; + } + else + { + LL_INFOS() << "No texture: " << LL_ENDL; + } + + LL_INFOS() << "Face: " << this << LL_ENDL; + LL_INFOS() << "State: " << getState() << LL_ENDL; + LL_INFOS() << "Geom Index Data:" << LL_ENDL; + LL_INFOS() << "--------------------" << LL_ENDL; + LL_INFOS() << "GI: " << mGeomIndex << " Count:" << mGeomCount << LL_ENDL; + LL_INFOS() << "Face Index Data:" << LL_ENDL; + LL_INFOS() << "--------------------" << LL_ENDL; + LL_INFOS() << "II: " << mIndicesIndex << " Count:" << mIndicesCount << LL_ENDL; + LL_INFOS() << LL_ENDL; + + if (poolp) + { + poolp->printDebugInfo(); + + S32 pool_references = 0; + for (std::vector::iterator iter = poolp->mReferences.begin(); + iter != poolp->mReferences.end(); iter++) + { + LLFace *facep = *iter; + if (facep == this) + { + LL_INFOS() << "Pool reference: " << pool_references << LL_ENDL; + pool_references++; + } + } + + if (pool_references != 1) + { + LL_INFOS() << "Incorrect number of pool references!" << LL_ENDL; + } + } #if 0 - LL_INFOS() << "Indices:" << LL_ENDL; - LL_INFOS() << "--------------------" << LL_ENDL; - - const U32 *indicesp = getRawIndices(); - S32 indices_count = getIndicesCount(); - S32 geom_start = getGeomStart(); - - for (S32 i = 0; i < indices_count; i++) - { - LL_INFOS() << i << ":" << indicesp[i] << ":" << (S32)(indicesp[i] - geom_start) << LL_ENDL; - } - LL_INFOS() << LL_ENDL; - - LL_INFOS() << "Vertices:" << LL_ENDL; - LL_INFOS() << "--------------------" << LL_ENDL; - for (S32 i = 0; i < mGeomCount; i++) - { - LL_INFOS() << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << LL_ENDL; - } - LL_INFOS() << LL_ENDL; + LL_INFOS() << "Indices:" << LL_ENDL; + LL_INFOS() << "--------------------" << LL_ENDL; + + const U32 *indicesp = getRawIndices(); + S32 indices_count = getIndicesCount(); + S32 geom_start = getGeomStart(); + + for (S32 i = 0; i < indices_count; i++) + { + LL_INFOS() << i << ":" << indicesp[i] << ":" << (S32)(indicesp[i] - geom_start) << LL_ENDL; + } + LL_INFOS() << LL_ENDL; + + LL_INFOS() << "Vertices:" << LL_ENDL; + LL_INFOS() << "--------------------" << LL_ENDL; + for (S32 i = 0; i < mGeomCount; i++) + { + LL_INFOS() << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << LL_ENDL; + } + LL_INFOS() << LL_ENDL; #endif } // Transform the texture coordinates for this face. static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 offT, F32 magS, F32 magT) { - // New, good way - F32 s = tex_coord.mV[0]; - F32 t = tex_coord.mV[1]; + // New, good way + F32 s = tex_coord.mV[0]; + F32 t = tex_coord.mV[1]; - // Texture transforms are done about the center of the face. - s -= 0.5; - t -= 0.5; + // Texture transforms are done about the center of the face. + s -= 0.5; + t -= 0.5; - // Handle rotation - F32 temp = s; - s = s * cosAng + t * sinAng; - t = -temp * sinAng + t * cosAng; + // Handle rotation + F32 temp = s; + s = s * cosAng + t * sinAng; + t = -temp * sinAng + t * cosAng; - // Then scale - s *= magS; - t *= magT; + // Then scale + s *= magS; + t *= magT; - // Then offset - s += offS + 0.5f; - t += offT + 0.5f; + // Then offset + s += offS + 0.5f; + t += offT + 0.5f; - tex_coord.mV[0] = s; - tex_coord.mV[1] = t; + tex_coord.mV[0] = s; + tex_coord.mV[1] = t; } // Transform the texture coordinates for this face. -static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) +static void xform4a(LLVector4a &tex_coord, const LLVector4a& trans, const LLVector4Logical& mask, const LLVector4a& rot0, const LLVector4a& rot1, const LLVector4a& offset, const LLVector4a& scale) { - //tex coord is two coords, - LLVector4a st; - - // Texture transforms are done about the center of the face. - st.setAdd(tex_coord, trans); - - // Handle rotation - LLVector4a rot_st; - - // - LLVector4a s0; - s0.splat(st, 0); - LLVector4a s1; - s1.splat(st, 2); - LLVector4a ss; - ss.setSelectWithMask(mask, s1, s0); - - LLVector4a a; - a.setMul(rot0, ss); - - // - LLVector4a t0; - t0.splat(st, 1); - LLVector4a t1; - t1.splat(st, 3); - LLVector4a tt; - tt.setSelectWithMask(mask, t1, t0); - - LLVector4a b; - b.setMul(rot1, tt); - - st.setAdd(a,b); - - // Then scale - st.mul(scale); - - // Then offset - tex_coord.setAdd(st, offset); + //tex coord is two coords, + LLVector4a st; + + // Texture transforms are done about the center of the face. + st.setAdd(tex_coord, trans); + + // Handle rotation + LLVector4a rot_st; + + // + LLVector4a s0; + s0.splat(st, 0); + LLVector4a s1; + s1.splat(st, 2); + LLVector4a ss; + ss.setSelectWithMask(mask, s1, s0); + + LLVector4a a; + a.setMul(rot0, ss); + + // + LLVector4a t0; + t0.splat(st, 1); + LLVector4a t1; + t1.splat(st, 3); + LLVector4a tt; + tt.setSelectWithMask(mask, t1, t0); + + LLVector4a b; + b.setMul(rot1, tt); + + st.setAdd(a,b); + + // Then scale + st.mul(scale); + + // Then offset + tex_coord.setAdd(st, offset); } bool less_than_max_mag(const LLVector4a& vec) { - LLVector4a MAX_MAG; - MAX_MAG.splat(1024.f*1024.f); + LLVector4a MAX_MAG; + MAX_MAG.splat(1024.f*1024.f); - LLVector4a val; - val.setAbs(vec); + LLVector4a val; + val.setAbs(vec); - S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; - - return lt == 0x7; + S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; + + return lt == 0x7; } BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat_vert_in, BOOL global_volume) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE - - //get bounding box - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) - { - if (f >= volume.getNumVolumeFaces()) - { - LL_WARNS() << "Generating bounding box for invalid face index!" << LL_ENDL; - f = 0; - } - - const LLVolumeFace &face = volume.getVolumeFace(f); - - LL_DEBUGS("RiggedBox") << "updating extents for face " << f - << " starting extents " << mExtents[0] << ", " << mExtents[1] - << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1] + LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE + + //get bounding box + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) + { + if (f >= volume.getNumVolumeFaces()) + { + LL_WARNS() << "Generating bounding box for invalid face index!" << LL_ENDL; + f = 0; + } + + const LLVolumeFace &face = volume.getVolumeFace(f); + + LL_DEBUGS("RiggedBox") << "updating extents for face " << f + << " starting extents " << mExtents[0] << ", " << mExtents[1] + << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1] << " num verts " << face.mNumVertices << LL_ENDL; // MAINT-8264 - stray vertices, especially in low LODs, cause bounding box errors. - if (face.mNumVertices < 3) + if (face.mNumVertices < 3) { - LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices " + LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices " << face.mNumVertices << " " << face.mNumIndices << " " << face.mWeights << LL_ENDL; return FALSE; } - - //VECTORIZE THIS - LLMatrix4a mat_vert; - mat_vert.loadu(mat_vert_in); + + //VECTORIZE THIS + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); LLVector4a new_extents[2]; - llassert(less_than_max_mag(face.mExtents[0])); - llassert(less_than_max_mag(face.mExtents[1])); + llassert(less_than_max_mag(face.mExtents[0])); + llassert(less_than_max_mag(face.mExtents[1])); - matMulBoundBox(mat_vert, face.mExtents, mExtents); + matMulBoundBox(mat_vert, face.mExtents, mExtents); - LL_DEBUGS("RiggedBox") << "updated extents for face " << f + LL_DEBUGS("RiggedBox") << "updated extents for face " << f << " bbox gave extents " << mExtents[0] << ", " << mExtents[1] << LL_ENDL; - if (!mDrawablep->isActive()) - { // Shift position for region - LLVector4a offset; - offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); - mExtents[0].add(offset); - mExtents[1].add(offset); - LL_DEBUGS("RiggedBox") << "updating extents for face " << f + if (!mDrawablep->isActive()) + { // Shift position for region + LLVector4a offset; + offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); + mExtents[0].add(offset); + mExtents[1].add(offset); + LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " not active, added offset " << offset << LL_ENDL; - } + } - LL_DEBUGS("RiggedBox") << "updated extents for face " << f + LL_DEBUGS("RiggedBox") << "updated extents for face " << f << " to " << mExtents[0] << ", " << mExtents[1] << LL_ENDL; - LLVector4a t; - t.setAdd(mExtents[0],mExtents[1]); - t.mul(0.5f); + LLVector4a t; + t.setAdd(mExtents[0],mExtents[1]); + t.mul(0.5f); - mCenterLocal.set(t.getF32ptr()); + mCenterLocal.set(t.getF32ptr()); - t.setSub(mExtents[1],mExtents[0]); - mBoundingSphereRadius = t.getLength3().getF32()*0.5f; + t.setSub(mExtents[1],mExtents[0]); + mBoundingSphereRadius = t.getLength3().getF32()*0.5f; - updateCenterAgent(); - } + updateCenterAgent(); + } - return TRUE; + return TRUE; } @@ -885,113 +885,113 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, // with the implications. LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal) { - LLVector2 tc = surface_coord; - - const LLTextureEntry *tep = getTextureEntry(); - - if (tep == NULL) - { - // can't do much without the texture entry - return surface_coord; - } - - //VECTORIZE THIS - // see if we have a non-default mapping + LLVector2 tc = surface_coord; + + const LLTextureEntry *tep = getTextureEntry(); + + if (tep == NULL) + { + // can't do much without the texture entry + return surface_coord; + } + + //VECTORIZE THIS + // see if we have a non-default mapping U8 texgen = getTextureEntry()->getTexGen(); - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter); - - LLVector4a volume_position; - LLVector3 v_position(position.getF32ptr()); - - volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(v_position).mV); - - if (!mDrawablep->getVOVolume()->isVolumeGlobal()) - { - LLVector4a scale; - scale.load3(mVObjp->getScale().mV); - volume_position.mul(scale); - } - - LLVector4a volume_normal; - LLVector3 v_normal(normal.getF32ptr()); - volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(v_normal).mV); - volume_normal.normalize3fast(); - - if (texgen == LLTextureEntry::TEX_GEN_PLANAR) - { - planarProjection(tc, volume_normal, center, volume_position); - } - } - - if (mTextureMatrix) // if we have a texture matrix, use it - { - LLVector3 tc3(tc); - tc3 = tc3 * *mTextureMatrix; - tc = LLVector2(tc3); - } - - else // otherwise use the texture entry parameters - { - xform(tc, cos(tep->getRotation()), sin(tep->getRotation()), - tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT); - } - - - return tc; + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter); + + LLVector4a volume_position; + LLVector3 v_position(position.getF32ptr()); + + volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(v_position).mV); + + if (!mDrawablep->getVOVolume()->isVolumeGlobal()) + { + LLVector4a scale; + scale.load3(mVObjp->getScale().mV); + volume_position.mul(scale); + } + + LLVector4a volume_normal; + LLVector3 v_normal(normal.getF32ptr()); + volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(v_normal).mV); + volume_normal.normalize3fast(); + + if (texgen == LLTextureEntry::TEX_GEN_PLANAR) + { + planarProjection(tc, volume_normal, center, volume_position); + } + } + + if (mTextureMatrix) // if we have a texture matrix, use it + { + LLVector3 tc3(tc); + tc3 = tc3 * *mTextureMatrix; + tc = LLVector2(tc3); + } + + else // otherwise use the texture entry parameters + { + xform(tc, cos(tep->getRotation()), sin(tep->getRotation()), + tep->mOffsetS, tep->mOffsetT, tep->mScaleS, tep->mScaleT); + } + + + return tc; } // Returns scale compared to default texgen, and face orientation as calculated // by planarProjection(). This is needed to match planar texgen parameters. void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const { - const LLMatrix4& vol_mat = getWorldMatrix(); - const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); - if (! (vf.mNormals && vf.mTangents)) - { - return; - } - const LLVector4a& normal4a = *vf.mNormals; - const LLVector4a& tangent = *vf.mTangents; - - LLVector4a binormal4a; - binormal4a.setCross3(normal4a, tangent); - binormal4a.mul(tangent.getF32ptr()[3]); - - LLVector2 projected_binormal; - planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a); - projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform() - *scale = projected_binormal.length(); - // rotate binormal to match what planarProjection() thinks it is, - // then find rotation from that: - projected_binormal.normalize(); - F32 ang = acos(projected_binormal.mV[VY]); - ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang; - - //VECTORIZE THIS - LLVector3 binormal(binormal4a.getF32ptr()); - LLVector3 normal(normal4a.getF32ptr()); - binormal.rotVec(ang, normal); - LLQuaternion local_rot( binormal % normal, binormal, normal ); - *face_rot = local_rot * vol_mat.quaternion(); - *face_pos = vol_mat.getTranslation(); + const LLMatrix4& vol_mat = getWorldMatrix(); + const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); + if (! (vf.mNormals && vf.mTangents)) + { + return; + } + const LLVector4a& normal4a = *vf.mNormals; + const LLVector4a& tangent = *vf.mTangents; + + LLVector4a binormal4a; + binormal4a.setCross3(normal4a, tangent); + binormal4a.mul(tangent.getF32ptr()[3]); + + LLVector2 projected_binormal; + planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a); + projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform() + *scale = projected_binormal.length(); + // rotate binormal to match what planarProjection() thinks it is, + // then find rotation from that: + projected_binormal.normalize(); + F32 ang = acos(projected_binormal.mV[VY]); + ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang; + + //VECTORIZE THIS + LLVector3 binormal(binormal4a.getF32ptr()); + LLVector3 normal(normal4a.getF32ptr()); + binormal.rotVec(ang, normal); + LLQuaternion local_rot( binormal % normal, binormal, normal ); + *face_rot = local_rot * vol_mat.quaternion(); + *face_pos = vol_mat.getTranslation(); } // Returns the necessary texture transform to align this face's TE to align_to's TE -bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offset, - LLVector2* res_st_scale, F32* res_st_rot, LLRender::eTexIndex map) const +bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offset, + LLVector2* res_st_scale, F32* res_st_rot, LLRender::eTexIndex map) const { - if (!align_to) - { - return false; - } - const LLTextureEntry *orig_tep = align_to->getTextureEntry(); - if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) || - (getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) - { - return false; - } + if (!align_to) + { + return false; + } + const LLTextureEntry *orig_tep = align_to->getTextureEntry(); + if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) || + (getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) + { + return false; + } F32 map_rot = 0.f, map_scaleS = 0.f, map_scaleT = 0.f, map_offsS = 0.f, map_offsT = 0.f; @@ -1037,55 +1037,55 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs break; } - LLVector3 orig_pos, this_pos; - LLQuaternion orig_face_rot, this_face_rot; - F32 orig_proj_scale, this_proj_scale; - align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale); - getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale); - - // The rotation of "this face's" texture: - LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot; - LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot; - F32 x_ang, y_ang, z_ang; - this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang); - *res_st_rot = z_ang; - - // Offset and scale of "this face's" texture: - LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot; - LLVector3 st_scale(map_scaleS, map_scaleT, 1.f); - st_scale *= orig_proj_scale; - centers_dist.scaleVec(st_scale); - LLVector2 orig_st_offset(map_offsS, map_offsT); - - *res_st_offset = orig_st_offset + (LLVector2)centers_dist; - res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX]; - res_st_offset->mV[VY] -= (S32)res_st_offset->mV[VY]; - - st_scale /= this_proj_scale; - *res_st_scale = (LLVector2)st_scale; - return true; + LLVector3 orig_pos, this_pos; + LLQuaternion orig_face_rot, this_face_rot; + F32 orig_proj_scale, this_proj_scale; + align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale); + getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale); + + // The rotation of "this face's" texture: + LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot; + LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot; + F32 x_ang, y_ang, z_ang; + this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang); + *res_st_rot = z_ang; + + // Offset and scale of "this face's" texture: + LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot; + LLVector3 st_scale(map_scaleS, map_scaleT, 1.f); + st_scale *= orig_proj_scale; + centers_dist.scaleVec(st_scale); + LLVector2 orig_st_offset(map_offsS, map_offsT); + + *res_st_offset = orig_st_offset + (LLVector2)centers_dist; + res_st_offset->mV[VX] -= (S32)res_st_offset->mV[VX]; + res_st_offset->mV[VY] -= (S32)res_st_offset->mV[VY]; + + st_scale /= this_proj_scale; + *res_st_scale = (LLVector2)st_scale; + return true; } void LLFace::updateRebuildFlags() { - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) - { //this rebuild is zero overhead (direct consequence of some change that affects this face) - mLastUpdateTime = gFrameTimeSeconds; - } - else - { //this rebuild is overhead (side effect of some change that does not affect this face) - mLastMoveTime = gFrameTimeSeconds; - } + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { //this rebuild is zero overhead (direct consequence of some change that affects this face) + mLastUpdateTime = gFrameTimeSeconds; + } + else + { //this rebuild is overhead (side effect of some change that does not affect this face) + mLastMoveTime = gFrameTimeSeconds; + } } bool LLFace::canRenderAsMask() { - const LLTextureEntry* te = getTextureEntry(); - if( !te || !getViewerObject() || !getTexture() ) - { - return false; - } + const LLTextureEntry* te = getTextureEntry(); + if( !te || !getViewerObject() || !getTexture() ) + { + return false; + } if (te->getGLTFRenderMaterial()) { @@ -1102,45 +1102,45 @@ bool LLFace::canRenderAsMask() return false; } - - LLMaterial* mat = te->getMaterialParams(); - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) - { - return false; - } - - if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha - (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask - getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) - { - if (getViewerObject()->isHUDAttachment() || te->getFullbright()) - { //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe - return LLPipeline::sAutoMaskAlphaNonDeferred; - } - else - { - return LLPipeline::sAutoMaskAlphaDeferred; - } - } - - return false; + + LLMaterial* mat = te->getMaterialParams(); + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) + { + return false; + } + + if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha + (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask + getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) + { + if (getViewerObject()->isHUDAttachment() || te->getFullbright()) + { //hud attachments and fullbright objects are NOT subject to the deferred rendering pipe + return LLPipeline::sAutoMaskAlphaNonDeferred; + } + else + { + return LLPipeline::sAutoMaskAlphaDeferred; + } + } + + return false; } //helper function for pushing primitives for transform shaders and cleaning up //uninitialized data on the tail, plus tracking number of expected primitives void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count) { - if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping - { - //push source primitives - buff->drawArrays(LLRender::POINTS, 0, source_count); - U32 tail = dest_count-source_count; - for (U32 i = 0; i < tail; ++i) - { //copy last source primitive into each element in tail - buff->drawArrays(LLRender::POINTS, source_count-1, 1); - } - gPipeline.mTransformFeedbackPrimitives += dest_count; - } + if (source_count > 0 && dest_count >= source_count) //protect against possible U32 wrapping + { + //push source primitives + buff->drawArrays(LLRender::POINTS, 0, source_count); + U32 tail = dest_count-source_count; + for (U32 i = 0; i < tail; ++i) + { //copy last source primitive into each element in tail + buff->drawArrays(LLRender::POINTS, source_count-1, 1); + } + gPipeline.mTransformFeedbackPrimitives += dest_count; + } } BOOL LLFace::getGeometryVolume(const LLVolume& volume, @@ -1152,7 +1152,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bool no_debug_assert) { LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; - llassert(verify()); + llassert(verify()); if (face_index < 0 || face_index >= volume.getNumVolumeFaces()) { @@ -1170,163 +1170,163 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bool rigged = isState(RIGGED); const LLVolumeFace &vf = volume.getVolumeFace(face_index); - S32 num_vertices = (S32)vf.mNumVertices; - S32 num_indices = (S32) vf.mNumIndices; - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) - { - updateRebuildFlags(); - } - - if (mVertexBuffer.notNull()) - { - if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) - { - if (gDebugGL) - { - LL_WARNS() << "Index buffer overflow!" << LL_ENDL; - LL_WARNS() << "Indices Count: " << mIndicesCount - << " VF Num Indices: " << num_indices - << " Indices Index: " << mIndicesIndex - << " VB Num Indices: " << mVertexBuffer->getNumIndices() << LL_ENDL; - LL_WARNS() << " Face Index: " << face_index - << " Pool Type: " << mPoolType << LL_ENDL; - llassert(no_debug_assert); - } - return FALSE; - } - - if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) - { - if (gDebugGL) - { - LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; - llassert(no_debug_assert); - } - return FALSE; - } - } - - LLStrider vert; - LLStrider tex_coords0; - LLStrider tex_coords1; - LLStrider tex_coords2; - LLStrider norm; - LLStrider colors; - LLStrider tangent; - LLStrider indicesp; - LLStrider wght; - - BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); - - BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); - LLVector3 scale; - if (global_volume) - { - scale.setVec(1,1,1); - } - else - { - scale = mVObjp->getScale(); - } - - bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); - bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); - bool rebuild_emissive = rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE); - bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); - bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - bool rebuild_tangent = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT); - bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); - - const LLTextureEntry *tep = mVObjp->getTE(face_index); - const U8 bump_code = tep ? tep->getBumpmap() : 0; - - BOOL is_static = mDrawablep->isStatic(); - BOOL is_global = is_static; - - LLVector3 center_sum(0.f, 0.f, 0.f); - - if (is_global) - { - setState(GLOBAL); - } - else - { - clearState(GLOBAL); - } - - LLColor4U color = tep->getColor(); + S32 num_vertices = (S32)vf.mNumVertices; + S32 num_indices = (S32) vf.mNumIndices; - if (tep->getGLTFRenderMaterial()) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) + { + updateRebuildFlags(); + } + + if (mVertexBuffer.notNull()) + { + if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) + { + if (gDebugGL) + { + LL_WARNS() << "Index buffer overflow!" << LL_ENDL; + LL_WARNS() << "Indices Count: " << mIndicesCount + << " VF Num Indices: " << num_indices + << " Indices Index: " << mIndicesIndex + << " VB Num Indices: " << mVertexBuffer->getNumIndices() << LL_ENDL; + LL_WARNS() << " Face Index: " << face_index + << " Pool Type: " << mPoolType << LL_ENDL; + llassert(no_debug_assert); + } + return FALSE; + } + + if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) + { + if (gDebugGL) + { + LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL; + llassert(no_debug_assert); + } + return FALSE; + } + } + + LLStrider vert; + LLStrider tex_coords0; + LLStrider tex_coords1; + LLStrider tex_coords2; + LLStrider norm; + LLStrider colors; + LLStrider tangent; + LLStrider indicesp; + LLStrider wght; + + BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); + + BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); + LLVector3 scale; + if (global_volume) + { + scale.setVec(1,1,1); + } + else + { + scale = mVObjp->getScale(); + } + + bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); + bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); + bool rebuild_emissive = rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE); + bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + bool rebuild_tangent = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TANGENT); + bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); + + const LLTextureEntry *tep = mVObjp->getTE(face_index); + const U8 bump_code = tep ? tep->getBumpmap() : 0; + + BOOL is_static = mDrawablep->isStatic(); + BOOL is_global = is_static; + + LLVector3 center_sum(0.f, 0.f, 0.f); + + if (is_global) + { + setState(GLOBAL); + } + else + { + clearState(GLOBAL); + } + + LLColor4U color = tep->getColor(); + + if (tep->getGLTFRenderMaterial()) { color = tep->getGLTFRenderMaterial()->mBaseColor; } - if (rebuild_color) - { //decide if shiny goes in alpha channel of color - if (tep && - !isInAlphaPool()) // <--- alpha channel MUST contain transparency, not shiny - { - LLMaterial* mat = tep->getMaterialParams().get(); - - bool shiny_in_alpha = false; - - //store shiny in alpha if we don't have a specular map - if (!mat || mat->getSpecularID().isNull()) - { - shiny_in_alpha = true; - } - - if (shiny_in_alpha) - { - static const GLfloat SHININESS_TO_ALPHA[4] = - { - 0.0000f, - 0.25f, - 0.5f, - 0.75f - }; - - llassert(tep->getShiny() <= 3); - color.mV[3] = U8 (SHININESS_TO_ALPHA[tep->getShiny()] * 255); - } - } - } - - // INDICES - if (full_rebuild) - { + if (rebuild_color) + { //decide if shiny goes in alpha channel of color + if (tep && + !isInAlphaPool()) // <--- alpha channel MUST contain transparency, not shiny + { + LLMaterial* mat = tep->getMaterialParams().get(); + + bool shiny_in_alpha = false; + + //store shiny in alpha if we don't have a specular map + if (!mat || mat->getSpecularID().isNull()) + { + shiny_in_alpha = true; + } + + if (shiny_in_alpha) + { + static const GLfloat SHININESS_TO_ALPHA[4] = + { + 0.0000f, + 0.25f, + 0.5f, + 0.75f + }; + + llassert(tep->getShiny() <= 3); + color.mV[3] = U8 (SHININESS_TO_ALPHA[tep->getShiny()] * 255); + } + } + } + + // INDICES + if (full_rebuild) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - indices"); - mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); - volatile __m128i* dst = (__m128i*) indicesp.get(); - __m128i* src = (__m128i*) vf.mIndices; - __m128i offset = _mm_set1_epi16(index_offset); + volatile __m128i* dst = (__m128i*) indicesp.get(); + __m128i* src = (__m128i*) vf.mIndices; + __m128i offset = _mm_set1_epi16(index_offset); - S32 end = num_indices/8; - - for (S32 i = 0; i < end; i++) - { - __m128i res = _mm_add_epi16(src[i], offset); - _mm_storeu_si128((__m128i*) dst++, res); - } + S32 end = num_indices/8; - { + for (S32 i = 0; i < end; i++) + { + __m128i res = _mm_add_epi16(src[i], offset); + _mm_storeu_si128((__m128i*) dst++, res); + } + + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - indices tail"); - U16* idx = (U16*) dst; + U16* idx = (U16*) dst; + + for (S32 i = end*8; i < num_indices; ++i) + { + *idx++ = vf.mIndices[i]+index_offset; + } + } + } - for (S32 i = end*8; i < num_indices; ++i) - { - *idx++ = vf.mIndices[i]+index_offset; - } - } - } - LLMaterial* mat = tep->getMaterialParams().get(); LLGLTFMaterial* gltf_mat = tep->getGLTFRenderMaterial(); - F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; + F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; constexpr S32 XFORM_NONE = 0; constexpr S32 XFORM_BLINNPHONG_COLOR = 1; @@ -1391,7 +1391,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } } - + const LLMeshSkinInfo* skin = nullptr; LLMatrix4a mat_vert; LLMatrix4a mat_normal; @@ -1431,334 +1431,334 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - { - //if it's not fullbright and has no normals, bake sunlight based on face normal - //bool bake_sunlight = !getTextureEntry()->getFullbright() && - // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + { + //if it's not fullbright and has no normals, bake sunlight based on face normal + //bool bake_sunlight = !getTextureEntry()->getFullbright() && + // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - if (rebuild_tcoord) - { + if (rebuild_tcoord) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tcoord"); - - //bump setup - LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); - LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); - LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); - - LLQuaternion bump_quat; - if (mDrawablep->isActive()) - { - bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); - } - - if (bump_code) - { - mVObjp->getVolume()->genTangents(face_index); - F32 offset_multiple; - switch( bump_code ) - { - case BE_NO_BUMP: - offset_multiple = 0.f; - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - if( mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->hasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture[LLRender::DIFFUSE_MAP]->getDiscardLevel(); - S32 max_size = llmax( mTexture[LLRender::DIFFUSE_MAP]->getWidth(), mTexture[LLRender::DIFFUSE_MAP]->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; - - default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } - - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) - { - tep->getScale( &s_scale, &t_scale ); - } - // Use the nudged south when coming from above sun angle, such - // that emboss mapping always shows up on the upward faces of cubes when - // it's noon (since a lot of builders build with the sun forced to noon). - LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; - LLVector3 moon_ray = gSky.mVOSkyp->getMoon().getDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - - bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); - bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); - } - - U8 texgen = getTextureEntry()->getTexGen(); - if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { //planar texgen needs binormals - mVObjp->getVolume()->genTangents(face_index); - } - - U8 tex_mode = 0; - - bool tex_anim = false; - - LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; - tex_mode = vobj->mTexAnimMode; - - if (vobj->mTextureAnimp) - { //texture animation is in play, override specular and normal map tex coords with diffuse texcoords - tex_anim = true; - } - - if (isState(TEXTURE_ANIM)) - { - if (!tex_mode) - { - clearState(TEXTURE_ANIM); - } - else - { - os = ot = 0.f; - r = 0.f; - cos_ang = 1.f; - sin_ang = 0.f; - ms = mt = 1.f; + + //bump setup + LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); + LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); + LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); + + LLQuaternion bump_quat; + if (mDrawablep->isActive()) + { + bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); + } + + if (bump_code) + { + mVObjp->getVolume()->genTangents(face_index); + F32 offset_multiple; + switch( bump_code ) + { + case BE_NO_BUMP: + offset_multiple = 0.f; + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + if( mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->hasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture[LLRender::DIFFUSE_MAP]->getDiscardLevel(); + S32 max_size = llmax( mTexture[LLRender::DIFFUSE_MAP]->getWidth(), mTexture[LLRender::DIFFUSE_MAP]->getHeight() ); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; + } + else + { + offset_multiple = 1.f/256; + } + break; + + default: // Standard bumpmap textures. Assumed to be 256x256 + offset_multiple = 1.f / 256; + break; + } + + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if( tep ) + { + tep->getScale( &s_scale, &t_scale ); + } + // Use the nudged south when coming from above sun angle, such + // that emboss mapping always shows up on the upward faces of cubes when + // it's noon (since a lot of builders build with the sun forced to noon). + LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; + LLVector3 moon_ray = gSky.mVOSkyp->getMoon().getDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + + bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); + bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); + } + + U8 texgen = getTextureEntry()->getTexGen(); + if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { //planar texgen needs binormals + mVObjp->getVolume()->genTangents(face_index); + } + + U8 tex_mode = 0; + + bool tex_anim = false; + + LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; + tex_mode = vobj->mTexAnimMode; + + if (vobj->mTextureAnimp) + { //texture animation is in play, override specular and normal map tex coords with diffuse texcoords + tex_anim = true; + } + + if (isState(TEXTURE_ANIM)) + { + if (!tex_mode) + { + clearState(TEXTURE_ANIM); + } + else + { + os = ot = 0.f; + r = 0.f; + cos_ang = 1.f; + sin_ang = 0.f; + ms = mt = 1.f; xforms = XFORM_NONE; - } + } + + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) // || isState(LLFace::RIGGED)) + { //don't override texture transform during tc bake + tex_mode = 0; + } + } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) // || isState(LLFace::RIGGED)) - { //don't override texture transform during tc bake - tex_mode = 0; - } - } + LLVector4a scalea; + scalea.load3(scale.mV); - LLVector4a scalea; - scalea.load3(scale.mV); + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); - bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); + if ((mat || gltf_mat) && !do_bump) + { + do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1) + || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2); + } - if ((mat || gltf_mat) && !do_bump) - { - do_bump = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1) - || mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2); - } - // For GLTF materials: Transforms will be applied later - bool do_tex_mat = tex_mode && mTextureMatrix && !gltf_mat; + bool do_tex_mat = tex_mode && mTextureMatrix && !gltf_mat; - if (!do_bump) - { //not bump mapped, might be able to do a cheap update - mVertexBuffer->getTexCoord0Strider(tex_coords0, mGeomIndex, mGeomCount); + if (!do_bump) + { //not bump mapped, might be able to do a cheap update + mVertexBuffer->getTexCoord0Strider(tex_coords0, mGeomIndex, mGeomCount); - if (texgen != LLTextureEntry::TEX_GEN_PLANAR) - { + if (texgen != LLTextureEntry::TEX_GEN_PLANAR) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen"); - if (!do_tex_mat) - { - if (xforms == XFORM_NONE) - { + if (!do_tex_mat) + { + if (xforms == XFORM_NONE) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("ggv - texgen 1"); - S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; - LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size); - } - else - { + S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size); + } + else + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("ggv - texgen 2"); - F32* dst = (F32*) tex_coords0.get(); - LLVector4a* src = (LLVector4a*) vf.mTexCoords; - - LLVector4a trans; - trans.splat(-0.5f); - - LLVector4a rot0; - rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); - - LLVector4a rot1; - rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); - - LLVector4a scale; - scale.set(ms, mt, ms, mt); - - LLVector4a offset; - offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<2>(); - mask.setElement<3>(); - - U32 count = num_vertices/2 + num_vertices%2; - - for (S32 i = 0; i < count; i++) - { - LLVector4a res = *src++; - xform4a(res, trans, mask, rot0, rot1, offset, scale); - res.store4a(dst); - dst += 4; - } - } - } - else - { //do tex mat, no texgen, no bump - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; - *tex_coords0++ = tc; - } - } - } - else - { //no bump, tex gen planar + F32* dst = (F32*) tex_coords0.get(); + LLVector4a* src = (LLVector4a*) vf.mTexCoords; + + LLVector4a trans; + trans.splat(-0.5f); + + LLVector4a rot0; + rot0.set(cos_ang, -sin_ang, cos_ang, -sin_ang); + + LLVector4a rot1; + rot1.set(sin_ang, cos_ang, sin_ang, cos_ang); + + LLVector4a scale; + scale.set(ms, mt, ms, mt); + + LLVector4a offset; + offset.set(os+0.5f, ot+0.5f, os+0.5f, ot+0.5f); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<2>(); + mask.setElement<3>(); + + U32 count = num_vertices/2 + num_vertices%2; + + for (S32 i = 0; i < count; i++) + { + LLVector4a res = *src++; + xform4a(res, trans, mask, rot0, rot1, offset, scale); + res.store4a(dst); + dst += 4; + } + } + } + else + { //do tex mat, no texgen, no bump + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + *tex_coords0++ = tc; + } + } + } + else + { //no bump, tex gen planar LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen planar"); - if (do_tex_mat) - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); - - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; - - *tex_coords0++ = tc; - } - } - else if (xforms != XFORM_NONE) - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); - - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - - *tex_coords0++ = tc; - } - } - else - { - for (S32 i = 0; i < num_vertices; i++) - { - LLVector2 tc(vf.mTexCoords[i]); - LLVector4a& norm = vf.mNormals[i]; - LLVector4a& center = *(vf.mCenter); - LLVector4a vec = vf.mPositions[i]; - vec.mul(scalea); - planarProjection(tc, norm, center, vec); - - *tex_coords0++ = tc; - } - } - } - } - else - { //bump mapped or has material, just do the whole expensive loop + if (do_tex_mat) + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + + *tex_coords0++ = tc; + } + } + else if (xforms != XFORM_NONE) + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + + *tex_coords0++ = tc; + } + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + *tex_coords0++ = tc; + } + } + } + } + else + { //bump mapped or has material, just do the whole expensive loop LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - texgen default"); - std::vector bump_tc; - - if (mat && !mat->getNormalID().isNull()) - { //writing out normal and specular texture coordinates, not bump offsets - do_bump = false; - } + std::vector bump_tc; - LLStrider dst; + if (mat && !mat->getNormalID().isNull()) + { //writing out normal and specular texture coordinates, not bump offsets + do_bump = false; + } - for (U32 ch = 0; ch < 3; ++ch) - { + LLStrider dst; + + for (U32 ch = 0; ch < 3; ++ch) + { S32 xform_channel = XFORM_NONE; - switch (ch) - { - case 0: + switch (ch) + { + case 0: xform_channel = XFORM_BLINNPHONG_COLOR; - mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount); - break; - case 1: + mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount); + break; + case 1: xform_channel = XFORM_BLINNPHONG_NORMAL; - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) - { - mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount); - if (mat && !tex_anim) - { - r = mat->getNormalRotation(); - mat->getNormalOffset(os, ot); - mat->getNormalRepeat(ms, mt); - - cos_ang = cos(r); - sin_ang = sin(r); - - } - } - else - { - continue; - } - break; - case 2: + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) + { + mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount); + if (mat && !tex_anim) + { + r = mat->getNormalRotation(); + mat->getNormalOffset(os, ot); + mat->getNormalRepeat(ms, mt); + + cos_ang = cos(r); + sin_ang = sin(r); + + } + } + else + { + continue; + } + break; + case 2: xform_channel = XFORM_BLINNPHONG_SPECULAR; - if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2)) - { - mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount); - if (mat && !tex_anim) - { - r = mat->getSpecularRotation(); - mat->getSpecularOffset(os, ot); - mat->getSpecularRepeat(ms, mt); - - cos_ang = cos(r); - sin_ang = sin(r); - } - } - else - { - continue; - } - break; - } + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2)) + { + mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount); + if (mat && !tex_anim) + { + r = mat->getSpecularRotation(); + mat->getSpecularOffset(os, ot); + mat->getSpecularRepeat(ms, mt); + + cos_ang = cos(r); + sin_ang = sin(r); + } + } + else + { + continue; + } + break; + } const bool do_xform = (xforms & xform_channel) != XFORM_NONE; - + for (S32 i = 0; i < num_vertices; i++) - { + { LLVector2 tc(vf.mTexCoords[i]); - + LLVector4a& norm = vf.mNormals[i]; - + LLVector4a& center = *(vf.mCenter); - + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { LLVector4a vec = vf.mPositions[i]; - + vec.mul(scalea); if (texgen == LLTextureEntry::TEX_GEN_PLANAR) { planarProjection(tc, norm, center, vec); - } + } } if (tex_mode && mTextureMatrix) @@ -1779,239 +1779,239 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, bump_tc.push_back(tc); } } - } + } + + if ((!mat && !gltf_mat) && do_bump) + { + mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount); - if ((!mat && !gltf_mat) && do_bump) - { - mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount); - mVObjp->getVolume()->genTangents(face_index); - for (S32 i = 0; i < num_vertices; i++) - { - LLVector4a tangent = vf.mTangents[i]; - - LLVector4a binorm; - binorm.setCross3(vf.mNormals[i], tangent); - binorm.mul(tangent.getF32ptr()[3]); - - LLMatrix4a tangent_to_object; - tangent_to_object.setRows(tangent, binorm, vf.mNormals[i]); - LLVector4a t; - tangent_to_object.rotate(binormal_dir, t); - LLVector4a binormal; - mat_normal.rotate(t, binormal); - - //VECTORIZE THIS - if (mDrawablep->isActive()) - { - LLVector3 t; - t.set(binormal.getF32ptr()); - t *= bump_quat; - binormal.load3(t.mV); - } - - binormal.normalize3fast(); - - LLVector2 tc = bump_tc[i]; - tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); - - *tex_coords1++ = tc; - } - } - } - } - - if (rebuild_pos) - { - LLVector4a* src = vf.mPositions; - - //_mm_prefetch((char*)src, _MM_HINT_T0); - - LLVector4a* end = src+num_vertices; - //LLVector4a* end_64 = end-4; - - llassert(num_vertices > 0); - - mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount); - - - F32* dst = (F32*) vert.get(); - F32* end_f32 = dst+mGeomCount*4; - - //_mm_prefetch((char*)dst, _MM_HINT_NTA); - //_mm_prefetch((char*)src, _MM_HINT_NTA); - - //_mm_prefetch((char*)dst, _MM_HINT_NTA); - - - LLVector4a res0; //,res1,res2,res3; - - LLVector4a texIdx; - - S32 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0; - - F32 val = 0.f; - S32* vp = (S32*) &val; - *vp = index; - - llassert(index < LLGLSLShader::sIndexedTextureChannels); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); - - texIdx.set(0,0,0,val); - - LLVector4a tmp; - - - while (src < end) - { - mat_vert.affineTransform(*src++, res0); - tmp.setSelectWithMask(mask, texIdx, res0); - tmp.store4a((F32*) dst); - dst += 4; - } - - while (dst < end_f32) - { - res0.store4a((F32*) dst); - dst += 4; - } - } - - if (rebuild_normal) - { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a tangent = vf.mTangents[i]; + + LLVector4a binorm; + binorm.setCross3(vf.mNormals[i], tangent); + binorm.mul(tangent.getF32ptr()[3]); + + LLMatrix4a tangent_to_object; + tangent_to_object.setRows(tangent, binorm, vf.mNormals[i]); + LLVector4a t; + tangent_to_object.rotate(binormal_dir, t); + LLVector4a binormal; + mat_normal.rotate(t, binormal); + + //VECTORIZE THIS + if (mDrawablep->isActive()) + { + LLVector3 t; + t.set(binormal.getF32ptr()); + t *= bump_quat; + binormal.load3(t.mV); + } + + binormal.normalize3fast(); + + LLVector2 tc = bump_tc[i]; + tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); + + *tex_coords1++ = tc; + } + } + } + } + + if (rebuild_pos) + { + LLVector4a* src = vf.mPositions; + + //_mm_prefetch((char*)src, _MM_HINT_T0); + + LLVector4a* end = src+num_vertices; + //LLVector4a* end_64 = end-4; + + llassert(num_vertices > 0); + + mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount); + + + F32* dst = (F32*) vert.get(); + F32* end_f32 = dst+mGeomCount*4; + + //_mm_prefetch((char*)dst, _MM_HINT_NTA); + //_mm_prefetch((char*)src, _MM_HINT_NTA); + + //_mm_prefetch((char*)dst, _MM_HINT_NTA); + + + LLVector4a res0; //,res1,res2,res3; + + LLVector4a texIdx; + + S32 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0; + + F32 val = 0.f; + S32* vp = (S32*) &val; + *vp = index; + + llassert(index < LLGLSLShader::sIndexedTextureChannels); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + texIdx.set(0,0,0,val); + + LLVector4a tmp; + + + while (src < end) + { + mat_vert.affineTransform(*src++, res0); + tmp.setSelectWithMask(mask, texIdx, res0); + tmp.store4a((F32*) dst); + dst += 4; + } + + while (dst < end_f32) + { + res0.store4a((F32*) dst); + dst += 4; + } + } + + if (rebuild_normal) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - normal"); - mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount); - F32* normals = (F32*) norm.get(); - LLVector4a* src = vf.mNormals; - LLVector4a* end = src+num_vertices; - - while (src < end) - { - LLVector4a normal; - mat_normal.rotate(*src++, normal); - normal.store4a(normals); - normals += 4; - } - } - - if (rebuild_tangent) - { + mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount); + F32* normals = (F32*) norm.get(); + LLVector4a* src = vf.mNormals; + LLVector4a* end = src+num_vertices; + + while (src < end) + { + LLVector4a normal; + mat_normal.rotate(*src++, normal); + normal.store4a(normals); + normals += 4; + } + } + + if (rebuild_tangent) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tangent"); - mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount); - F32* tangents = (F32*) tangent.get(); - + mVertexBuffer->getTangentStrider(tangent, mGeomIndex, mGeomCount); + F32* tangents = (F32*) tangent.get(); + mVObjp->getVolume()->genTangents(face_index); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); - - LLVector4a* src = vf.mTangents; - LLVector4a* end = vf.mTangents +num_vertices; - - while (src < end) - { - LLVector4a tangent_out; - mat_normal.rotate(*src, tangent_out); - tangent_out.setSelectWithMask(mask, *src, tangent_out); - tangent_out.store4a(tangents); - - src++; - tangents += 4; - } - } - - if (rebuild_weights && vf.mWeights) - { + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + LLVector4a* src = vf.mTangents; + LLVector4a* end = vf.mTangents +num_vertices; + + while (src < end) + { + LLVector4a tangent_out; + mat_normal.rotate(*src, tangent_out); + tangent_out.setSelectWithMask(mask, *src, tangent_out); + tangent_out.store4a(tangents); + + src++; + tangents += 4; + } + } + + if (rebuild_weights && vf.mWeights) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - weight"); - mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount); - F32* weights = (F32*) wght.get(); - LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); - } + mVertexBuffer->getWeight4Strider(wght, mGeomIndex, mGeomCount); + F32* weights = (F32*) wght.get(); + LLVector4a::memcpyNonAliased16(weights, (F32*) vf.mWeights, num_vertices*4*sizeof(F32)); + } - if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) - { + if (rebuild_color && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_COLOR) ) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - color"); - mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount); - - LLVector4a src; - - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = color.asRGBA(); - - src.loadua((F32*) vec); - - F32* dst = (F32*) colors.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } - - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } - } - - if (rebuild_emissive) - { + mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount); + + LLVector4a src; + + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = color.asRGBA(); + + src.loadua((F32*) vec); + + F32* dst = (F32*) colors.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } + + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } + } + + if (rebuild_emissive) + { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - emissive"); - LLStrider emissive; - mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount); - - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); - - LLVector4a src; - - - LLColor4U glow4u = LLColor4U(0,0,0,glow); - - U32 glow32 = glow4u.asRGBA(); - - U32 vec[4]; - vec[0] = vec[1] = vec[2] = vec[3] = glow32; - - src.loadua((F32*) vec); - - F32* dst = (F32*) emissive.get(); - S32 num_vecs = num_vertices/4; - if (num_vertices%4 > 0) - { - ++num_vecs; - } - - for (S32 i = 0; i < num_vecs; i++) - { - src.store4a(dst); - dst += 4; - } - } - } - - if (rebuild_tcoord) - { - mTexExtents[0].setVec(0,0); - mTexExtents[1].setVec(1,1); - xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); - xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); - - F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; - F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; - mTexExtents[0][0] *= es ; - mTexExtents[1][0] *= es ; - mTexExtents[0][1] *= et ; - mTexExtents[1][1] *= et ; - } - - - return TRUE; + LLStrider emissive; + mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount); + + U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + + LLVector4a src; + + + LLColor4U glow4u = LLColor4U(0,0,0,glow); + + U32 glow32 = glow4u.asRGBA(); + + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = glow32; + + src.loadua((F32*) vec); + + F32* dst = (F32*) emissive.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } + + for (S32 i = 0; i < num_vecs; i++) + { + src.store4a(dst); + dst += 4; + } + } + } + + if (rebuild_tcoord) + { + mTexExtents[0].setVec(0,0); + mTexExtents[1].setVec(1,1); + xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); + xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); + + F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; + F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; + mTexExtents[0][0] *= es ; + mTexExtents[1][0] *= es ; + mTexExtents[0][1] *= et ; + mTexExtents[1][1] *= et ; + } + + + return TRUE; } void LLFace::renderIndexed() @@ -2024,18 +2024,18 @@ void LLFace::renderIndexed() } //check if the face has a media -BOOL LLFace::hasMedia() const +BOOL LLFace::hasMedia() const { - if(mHasMedia) - { - return TRUE ; - } - if(mTexture[LLRender::DIFFUSE_MAP].notNull()) - { - return mTexture[LLRender::DIFFUSE_MAP]->hasParcelMedia() ; //if has a parcel media - } - - return FALSE ; //no media. + if(mHasMedia) + { + return TRUE ; + } + if(mTexture[LLRender::DIFFUSE_MAP].notNull()) + { + return mTexture[LLRender::DIFFUSE_MAP]->hasParcelMedia() ; //if has a parcel media + } + + return FALSE ; //no media. } const F32 LEAST_IMPORTANCE = 0.05f ; @@ -2043,65 +2043,65 @@ const F32 LEAST_IMPORTANCE_FOR_LARGE_IMAGE = 0.3f ; void LLFace::resetVirtualSize() { - setVirtualSize(0.f); - mImportanceToCamera = 0.f; + setVirtualSize(0.f); + mImportanceToCamera = 0.f; } F32 LLFace::getTextureVirtualSize() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - F32 radius; - F32 cos_angle_to_view_dir; - BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius); - - if (mPixelArea < F_ALMOST_ZERO || !in_frustum) - { - setVirtualSize(0.f) ; - return 0.f; - } - - //get area of circle in texture space - LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; - F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; - if (texel_area <= 0) - { - // Probably animated, use default - texel_area = 1.f; - } - - F32 face_area; - if (mVObjp->isSculpted() && texel_area > 1.f) - { - //sculpts can break assumptions about texel area - face_area = mPixelArea; - } - else - { - //apply texel area to face area to get accurate ratio - //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); - face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f); - } - - face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area) ; - if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. - { - if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->isLargeImage()) - { - face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); - } - } - - setVirtualSize(face_area) ; - - return face_area; + F32 radius; + F32 cos_angle_to_view_dir; + BOOL in_frustum = calcPixelArea(cos_angle_to_view_dir, radius); + + if (mPixelArea < F_ALMOST_ZERO || !in_frustum) + { + setVirtualSize(0.f) ; + return 0.f; + } + + //get area of circle in texture space + LLVector2 tdim = mTexExtents[1] - mTexExtents[0]; + F32 texel_area = (tdim * 0.5f).lengthSquared()*3.14159f; + if (texel_area <= 0) + { + // Probably animated, use default + texel_area = 1.f; + } + + F32 face_area; + if (mVObjp->isSculpted() && texel_area > 1.f) + { + //sculpts can break assumptions about texel area + face_area = mPixelArea; + } + else + { + //apply texel area to face area to get accurate ratio + //face_area /= llclamp(texel_area, 1.f/64.f, 16.f); + face_area = mPixelArea / llclamp(texel_area, 0.015625f, 128.f); + } + + face_area = LLFace::adjustPixelArea(mImportanceToCamera, face_area) ; + if(face_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + { + if(mImportanceToCamera > LEAST_IMPORTANCE_FOR_LARGE_IMAGE && mTexture[LLRender::DIFFUSE_MAP].notNull() && mTexture[LLRender::DIFFUSE_MAP]->isLargeImage()) + { + face_area *= adjustPartialOverlapPixelArea(cos_angle_to_view_dir, radius ); + } + } + + setVirtualSize(face_area) ; + + return face_area; } BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE; - //VECTORIZE THIS - //get area of circle around face + //VECTORIZE THIS + //get area of circle around face LLVector4a center; LLVector4a size; @@ -2127,237 +2127,237 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) center.load3(getPositionAgent().mV); size.setSub(mExtents[1], mExtents[0]); } - size.mul(0.5f); - - LLViewerCamera* camera = LLViewerCamera::getInstance(); - - F32 size_squared = size.dot3(size).getF32(); - LLVector4a lookAt; - LLVector4a t; - t.load3(camera->getOrigin().mV); - lookAt.setSub(center, t); - - F32 dist = lookAt.getLength3().getF32(); - dist = llmax(dist-size.getLength3().getF32(), 0.001f); - //ramp down distance for nearby objects - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } - - lookAt.normalize3fast() ; - - //get area of circle around node - F32 app_angle = atanf((F32) sqrt(size_squared) / dist); - radius = app_angle*LLDrawable::sCurPixelAngle; - mPixelArea = radius*radius * 3.14159f; - LLVector4a x_axis; - x_axis.load3(camera->getXAxis().mV); - cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); - - //if has media, check if the face is out of the view frustum. - if(hasMedia()) - { - if(!camera->AABBInFrustum(center, size)) - { - mImportanceToCamera = 0.f ; - return false ; - } - if(cos_angle_to_view_dir > camera->getCosHalfFov()) //the center is within the view frustum - { - cos_angle_to_view_dir = 1.0f ; - } - else - { - LLVector4a d; - d.setSub(lookAt, x_axis); - - if(dist * dist * d.dot3(d) < size_squared) - { - cos_angle_to_view_dir = 1.0f ; - } - } - } - - if(dist < mBoundingSphereRadius) //camera is very close - { - cos_angle_to_view_dir = 1.0f ; - mImportanceToCamera = 1.0f ; - } - else - { - mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; - } - - return true ; + size.mul(0.5f); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + + F32 size_squared = size.dot3(size).getF32(); + LLVector4a lookAt; + LLVector4a t; + t.load3(camera->getOrigin().mV); + lookAt.setSub(center, t); + + F32 dist = lookAt.getLength3().getF32(); + dist = llmax(dist-size.getLength3().getF32(), 0.001f); + //ramp down distance for nearby objects + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } + + lookAt.normalize3fast() ; + + //get area of circle around node + F32 app_angle = atanf((F32) sqrt(size_squared) / dist); + radius = app_angle*LLDrawable::sCurPixelAngle; + mPixelArea = radius*radius * 3.14159f; + LLVector4a x_axis; + x_axis.load3(camera->getXAxis().mV); + cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); + + //if has media, check if the face is out of the view frustum. + if(hasMedia()) + { + if(!camera->AABBInFrustum(center, size)) + { + mImportanceToCamera = 0.f ; + return false ; + } + if(cos_angle_to_view_dir > camera->getCosHalfFov()) //the center is within the view frustum + { + cos_angle_to_view_dir = 1.0f ; + } + else + { + LLVector4a d; + d.setSub(lookAt, x_axis); + + if(dist * dist * d.dot3(d) < size_squared) + { + cos_angle_to_view_dir = 1.0f ; + } + } + } + + if(dist < mBoundingSphereRadius) //camera is very close + { + cos_angle_to_view_dir = 1.0f ; + mImportanceToCamera = 1.0f ; + } + else + { + mImportanceToCamera = LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist) ; + } + + return true ; } //the projection of the face partially overlaps with the screen F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) { - F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()) ; - F32 center_angle = acosf(cos_angle_to_view_dir) ; - F32 d = center_angle * LLDrawable::sCurPixelAngle ; - - if(d + radius > screen_radius + 5.f) - { - //---------------------------------------------- - //calculate the intersection area of two circles - //F32 radius_square = radius * radius ; - //F32 d_square = d * d ; - //F32 screen_radius_square = screen_radius * screen_radius ; - //face_area = - // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + - // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - - // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; - //---------------------------------------------- - - //the above calculation is too expensive - //the below is a good estimation: bounding box of the bounding sphere: - F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; - alpha = llclamp(alpha, 0.f, 1.f) ; - return alpha * alpha ; - } - return 1.0f ; + F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()) ; + F32 center_angle = acosf(cos_angle_to_view_dir) ; + F32 d = center_angle * LLDrawable::sCurPixelAngle ; + + if(d + radius > screen_radius + 5.f) + { + //---------------------------------------------- + //calculate the intersection area of two circles + //F32 radius_square = radius * radius ; + //F32 d_square = d * d ; + //F32 screen_radius_square = screen_radius * screen_radius ; + //face_area = + // radius_square * acosf((d_square + radius_square - screen_radius_square)/(2 * d * radius)) + + // screen_radius_square * acosf((d_square + screen_radius_square - radius_square)/(2 * d * screen_radius)) - + // 0.5f * sqrtf((-d + radius + screen_radius) * (d + radius - screen_radius) * (d - radius + screen_radius) * (d + radius + screen_radius)) ; + //---------------------------------------------- + + //the above calculation is too expensive + //the below is a good estimation: bounding box of the bounding sphere: + F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; + alpha = llclamp(alpha, 0.f, 1.f) ; + return alpha * alpha ; + } + return 1.0f ; } const S8 FACE_IMPORTANCE_LEVEL = 4 ; const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL][2] = //{distance, importance_weight} - {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; + {{16.1f, 1.0f}, {32.1f, 0.5f}, {48.1f, 0.2f}, {96.1f, 0.05f} } ; const F32 FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[FACE_IMPORTANCE_LEVEL][2] = //{cos(angle), importance_weight} - {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; + {{0.985f /*cos(10 degrees)*/, 1.0f}, {0.94f /*cos(20 degrees)*/, 0.8f}, {0.866f /*cos(30 degrees)*/, 0.64f}, {0.0f, 0.36f}} ; -//static +//static F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) { - F32 importance = 0.f ; - - if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && - dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) - { - LLViewerCamera* camera = LLViewerCamera::getInstance(); - F32 camera_moving_speed = camera->getAverageSpeed() ; - F32 camera_angular_speed = camera->getAverageAngularSpeed(); - - if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) - { - //if camera moves or rotates too fast, ignore the importance factor - return 0.f ; - } - - S32 i = 0 ; - for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); - i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; - F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; - - for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; - i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; - importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; - } - - return importance ; + F32 importance = 0.f ; + + if(cos_angle_to_view_dir > LLViewerCamera::getInstance()->getCosHalfFov() && + dist < FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[FACE_IMPORTANCE_LEVEL - 1][0]) + { + LLViewerCamera* camera = LLViewerCamera::getInstance(); + F32 camera_moving_speed = camera->getAverageSpeed() ; + F32 camera_angular_speed = camera->getAverageAngularSpeed(); + + if(camera_moving_speed > 10.0f || camera_angular_speed > 1.0f) + { + //if camera moves or rotates too fast, ignore the importance factor + return 0.f ; + } + + S32 i = 0 ; + for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + F32 dist_factor = FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][1] ; + + for(i = 0; i < FACE_IMPORTANCE_LEVEL && cos_angle_to_view_dir < FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][0] ; ++i) ; + i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; + importance = dist_factor * FACE_IMPORTANCE_TO_CAMERA_OVER_ANGLE[i][1] ; + } + + return importance ; } -//static +//static F32 LLFace::adjustPixelArea(F32 importance, F32 pixel_area) { - if(pixel_area > LLViewerTexture::sMaxSmallImageSize) - { - if(importance < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. - { - static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ; - pixel_area = llmin(pixel_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ; - } - else if(pixel_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. - { - if(importance < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. - { - pixel_area = LLViewerTexture::sMinLargeImageSize ; - } - } - } - - return pixel_area ; + if(pixel_area > LLViewerTexture::sMaxSmallImageSize) + { + if(importance < LEAST_IMPORTANCE) //if the face is not important, do not load hi-res. + { + static const F32 MAX_LEAST_IMPORTANCE_IMAGE_SIZE = 128.0f * 128.0f ; + pixel_area = llmin(pixel_area * 0.5f, MAX_LEAST_IMPORTANCE_IMAGE_SIZE) ; + } + else if(pixel_area > LLViewerTexture::sMinLargeImageSize) //if is large image, shrink face_area by considering the partial overlapping. + { + if(importance < LEAST_IMPORTANCE_FOR_LARGE_IMAGE)//if the face is not important, do not load hi-res. + { + pixel_area = LLViewerTexture::sMinLargeImageSize ; + } + } + } + + return pixel_area ; } BOOL LLFace::verify(const U32* indices_array) const { - BOOL ok = TRUE; - - if( mVertexBuffer.isNull() ) - { //no vertex buffer, face is implicitly valid - return TRUE; - } - - // First, check whether the face data fits within the pool's range. - if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts()) - { - ok = FALSE; - LL_INFOS() << "Face references invalid vertices!" << LL_ENDL; - } - - S32 indices_count = (S32)getIndicesCount(); - - if (!indices_count) - { - return TRUE; - } - - if (indices_count > LL_MAX_INDICES_COUNT) - { - ok = FALSE; - LL_INFOS() << "Face has bogus indices count" << LL_ENDL; - } - - if (mIndicesIndex + mIndicesCount > mVertexBuffer->getNumIndices()) - { - ok = FALSE; - LL_INFOS() << "Face references invalid indices!" << LL_ENDL; - } + BOOL ok = TRUE; + + if( mVertexBuffer.isNull() ) + { //no vertex buffer, face is implicitly valid + return TRUE; + } + + // First, check whether the face data fits within the pool's range. + if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts()) + { + ok = FALSE; + LL_INFOS() << "Face references invalid vertices!" << LL_ENDL; + } + + S32 indices_count = (S32)getIndicesCount(); + + if (!indices_count) + { + return TRUE; + } + + if (indices_count > LL_MAX_INDICES_COUNT) + { + ok = FALSE; + LL_INFOS() << "Face has bogus indices count" << LL_ENDL; + } + + if (mIndicesIndex + mIndicesCount > mVertexBuffer->getNumIndices()) + { + ok = FALSE; + LL_INFOS() << "Face references invalid indices!" << LL_ENDL; + } #if 0 - S32 geom_start = getGeomStart(); - S32 geom_count = mGeomCount; - - const U32 *indicesp = indices_array ? indices_array + mIndicesIndex : getRawIndices(); - - for (S32 i = 0; i < indices_count; i++) - { - S32 delta = indicesp[i] - geom_start; - if (0 > delta) - { - LL_WARNS() << "Face index too low!" << LL_ENDL; - LL_INFOS() << "i:" << i << " Index:" << indicesp[i] << " GStart: " << geom_start << LL_ENDL; - ok = FALSE; - } - else if (delta >= geom_count) - { - LL_WARNS() << "Face index too high!" << LL_ENDL; - LL_INFOS() << "i:" << i << " Index:" << indicesp[i] << " GEnd: " << geom_start + geom_count << LL_ENDL; - ok = FALSE; - } - } + S32 geom_start = getGeomStart(); + S32 geom_count = mGeomCount; + + const U32 *indicesp = indices_array ? indices_array + mIndicesIndex : getRawIndices(); + + for (S32 i = 0; i < indices_count; i++) + { + S32 delta = indicesp[i] - geom_start; + if (0 > delta) + { + LL_WARNS() << "Face index too low!" << LL_ENDL; + LL_INFOS() << "i:" << i << " Index:" << indicesp[i] << " GStart: " << geom_start << LL_ENDL; + ok = FALSE; + } + else if (delta >= geom_count) + { + LL_WARNS() << "Face index too high!" << LL_ENDL; + LL_INFOS() << "i:" << i << " Index:" << indicesp[i] << " GEnd: " << geom_start + geom_count << LL_ENDL; + ok = FALSE; + } + } #endif - if (!ok) - { - printDebugInfo(); - } - return ok; + if (!ok) + { + printDebugInfo(); + } + return ok; } void LLFace::setViewerObject(LLViewerObject* objp) { - mVObjp = objp; + mVObjp = objp; } const LLMatrix4& LLFace::getRenderMatrix() const { - return mDrawablep->getRenderMatrix(); + return mDrawablep->getRenderMatrix(); } //============================================================================ @@ -2365,78 +2365,78 @@ const LLMatrix4& LLFace::getRenderMatrix() const S32 LLFace::getColors(LLStrider &colors) { - if (!mGeomCount) - { - return -1; - } - - // llassert(mGeomIndex >= 0); - mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount); - return mGeomIndex; + if (!mGeomCount) + { + return -1; + } + + // llassert(mGeomIndex >= 0); + mVertexBuffer->getColorStrider(colors, mGeomIndex, mGeomCount); + return mGeomIndex; } -S32 LLFace::getIndices(LLStrider &indicesp) +S32 LLFace::getIndices(LLStrider &indicesp) { - mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); - llassert(indicesp[0] != indicesp[1]); - return mIndicesIndex; + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex, mIndicesCount); + llassert(indicesp[0] != indicesp[1]); + return mIndicesIndex; } LLVector3 LLFace::getPositionAgent() const { - if (mDrawablep->isStatic()) - { - return mCenterAgent; - } - else - { - return mCenterLocal * getRenderMatrix(); - } + if (mDrawablep->isStatic()) + { + return mCenterAgent; + } + else + { + return mCenterLocal * getRenderMatrix(); + } } LLViewerTexture* LLFace::getTexture(U32 ch) const { - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - return mTexture[ch] ; + return mTexture[ch] ; } void LLFace::setVertexBuffer(LLVertexBuffer* buffer) { - if (buffer) - { - LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize()); - } - - if (mVertexBuffer) - { - LLSculptIDSize::instance().dec(mDrawablep); - } - - mVertexBuffer = buffer; - llassert(verify()); + if (buffer) + { + LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize()); + } + + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } + + mVertexBuffer = buffer; + llassert(verify()); } void LLFace::clearVertexBuffer() { - if (mVertexBuffer) - { - LLSculptIDSize::instance().dec(mDrawablep); - } + if (mVertexBuffer) + { + LLSculptIDSize::instance().dec(mDrawablep); + } - mVertexBuffer = NULL; + mVertexBuffer = NULL; } S32 LLFace::getRiggedIndex(U32 type) const { - if (mRiggedIndex.empty()) - { - return -1; - } + if (mRiggedIndex.empty()) + { + return -1; + } - llassert(type < mRiggedIndex.size()); + llassert(type < mRiggedIndex.size()); - return mRiggedIndex[type]; + return mRiggedIndex[type]; } U64 LLFace::getSkinHash() diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 9fff505c2a..9f12648470 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfeaturemanager.cpp * @brief LLFeatureManager class implementation * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -71,12 +71,12 @@ const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; #if 0 // consuming code in #if 0 below #endif LLFeatureInfo::LLFeatureInfo(const std::string& name, const BOOL available, const F32 level) - : mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level) + : mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level) { } LLFeatureList::LLFeatureList(const std::string& name) - : mName(name) + : mName(name) { } @@ -86,293 +86,293 @@ LLFeatureList::~LLFeatureList() void LLFeatureList::addFeature(const std::string& name, const BOOL available, const F32 level) { - if (mFeatures.count(name)) - { - LL_WARNS("RenderInit") << "LLFeatureList::Attempting to add preexisting feature " << name << LL_ENDL; - } + if (mFeatures.count(name)) + { + LL_WARNS("RenderInit") << "LLFeatureList::Attempting to add preexisting feature " << name << LL_ENDL; + } - LLFeatureInfo fi(name, available, level); + LLFeatureInfo fi(name, available, level); LL_DEBUGS_ONCE("RenderInit") << "Feature '" << name << "' " << (available ? "" : "not " ) << "available" << " at " << level << LL_ENDL; - mFeatures[name] = fi; + mFeatures[name] = fi; } BOOL LLFeatureList::isFeatureAvailable(const std::string& name) { - if (mFeatures.count(name)) - { - return mFeatures[name].mAvailable; - } - - LL_WARNS_ONCE("RenderInit") << "Feature " << name << " not on feature list!" << LL_ENDL; - - // changing this to TRUE so you have to explicitly disable - // something for it to be disabled - return TRUE; + if (mFeatures.count(name)) + { + return mFeatures[name].mAvailable; + } + + LL_WARNS_ONCE("RenderInit") << "Feature " << name << " not on feature list!" << LL_ENDL; + + // changing this to TRUE so you have to explicitly disable + // something for it to be disabled + return TRUE; } F32 LLFeatureList::getRecommendedValue(const std::string& name) { - if (mFeatures.count(name) && isFeatureAvailable(name)) - { + if (mFeatures.count(name) && isFeatureAvailable(name)) + { LL_DEBUGS_ONCE("RenderInit") << "Setting '" << name << "' to recommended value " << mFeatures[name].mRecommendedLevel << LL_ENDL; - return mFeatures[name].mRecommendedLevel; - } + return mFeatures[name].mRecommendedLevel; + } - LL_WARNS_ONCE("RenderInit") << "Feature " << name << " not on feature list or not available!" << LL_ENDL; - return 0; + LL_WARNS_ONCE("RenderInit") << "Feature " << name << " not on feature list or not available!" << LL_ENDL; + return 0; } BOOL LLFeatureList::maskList(LLFeatureList &mask) { - LL_DEBUGS_ONCE() << "Masking with " << mask.mName << LL_ENDL; - // - // Lookup the specified feature mask, and overlay it on top of the - // current feature mask. - // - - LLFeatureInfo mask_fi; - - feature_map_t::iterator feature_it; - for (feature_it = mask.mFeatures.begin(); feature_it != mask.mFeatures.end(); ++feature_it) - { - mask_fi = feature_it->second; - // - // Look for the corresponding feature - // - if (!mFeatures.count(mask_fi.mName)) - { - LL_WARNS("RenderInit") << "Feature " << mask_fi.mName << " in mask not in top level!" << LL_ENDL; - continue; - } - - LLFeatureInfo &cur_fi = mFeatures[mask_fi.mName]; - if (mask_fi.mAvailable && !cur_fi.mAvailable) - { - LL_WARNS("RenderInit") << "Mask attempting to reenabling disabled feature, ignoring " << cur_fi.mName << LL_ENDL; - continue; - } - cur_fi.mAvailable = mask_fi.mAvailable; - cur_fi.mRecommendedLevel = llmin(cur_fi.mRecommendedLevel, mask_fi.mRecommendedLevel); - LL_DEBUGS("RenderInit") << "Feature mask " << mask.mName - << " Feature " << mask_fi.mName - << " Mask: " << mask_fi.mRecommendedLevel - << " Now: " << cur_fi.mRecommendedLevel << LL_ENDL; - } - - LL_DEBUGS("RenderInit") << "After applying mask " << mask.mName << std::endl; - // Will conditionally call dump only if the above message will be logged, thanks - // to it being wrapped by the LL_DEBUGS and LL_ENDL macros. - dump(); - LL_CONT << LL_ENDL; - - return TRUE; + LL_DEBUGS_ONCE() << "Masking with " << mask.mName << LL_ENDL; + // + // Lookup the specified feature mask, and overlay it on top of the + // current feature mask. + // + + LLFeatureInfo mask_fi; + + feature_map_t::iterator feature_it; + for (feature_it = mask.mFeatures.begin(); feature_it != mask.mFeatures.end(); ++feature_it) + { + mask_fi = feature_it->second; + // + // Look for the corresponding feature + // + if (!mFeatures.count(mask_fi.mName)) + { + LL_WARNS("RenderInit") << "Feature " << mask_fi.mName << " in mask not in top level!" << LL_ENDL; + continue; + } + + LLFeatureInfo &cur_fi = mFeatures[mask_fi.mName]; + if (mask_fi.mAvailable && !cur_fi.mAvailable) + { + LL_WARNS("RenderInit") << "Mask attempting to reenabling disabled feature, ignoring " << cur_fi.mName << LL_ENDL; + continue; + } + cur_fi.mAvailable = mask_fi.mAvailable; + cur_fi.mRecommendedLevel = llmin(cur_fi.mRecommendedLevel, mask_fi.mRecommendedLevel); + LL_DEBUGS("RenderInit") << "Feature mask " << mask.mName + << " Feature " << mask_fi.mName + << " Mask: " << mask_fi.mRecommendedLevel + << " Now: " << cur_fi.mRecommendedLevel << LL_ENDL; + } + + LL_DEBUGS("RenderInit") << "After applying mask " << mask.mName << std::endl; + // Will conditionally call dump only if the above message will be logged, thanks + // to it being wrapped by the LL_DEBUGS and LL_ENDL macros. + dump(); + LL_CONT << LL_ENDL; + + return TRUE; } void LLFeatureList::dump() { - LL_DEBUGS("RenderInit") << "Feature list: " << mName << LL_ENDL; - - LLFeatureInfo fi; - feature_map_t::iterator feature_it; - for (feature_it = mFeatures.begin(); feature_it != mFeatures.end(); ++feature_it) - { - fi = feature_it->second; - LL_DEBUGS("RenderInit") << "With " << mName << " feature " << fi.mName << " " << fi.mAvailable << ":" << fi.mRecommendedLevel << LL_ENDL; - } + LL_DEBUGS("RenderInit") << "Feature list: " << mName << LL_ENDL; + + LLFeatureInfo fi; + feature_map_t::iterator feature_it; + for (feature_it = mFeatures.begin(); feature_it != mFeatures.end(); ++feature_it) + { + fi = feature_it->second; + LL_DEBUGS("RenderInit") << "With " << mName << " feature " << fi.mName << " " << fi.mAvailable << ":" << fi.mRecommendedLevel << LL_ENDL; + } } static const std::vector sGraphicsLevelNames = boost::assign::list_of - ("Low") - ("LowMid") - ("Mid") - ("MidHigh") - ("High") - ("HighUltra") - ("Ultra") + ("Low") + ("LowMid") + ("Mid") + ("MidHigh") + ("High") + ("HighUltra") + ("Ultra") ; U32 LLFeatureManager::getMaxGraphicsLevel() const { - return sGraphicsLevelNames.size() - 1; + return sGraphicsLevelNames.size() - 1; } bool LLFeatureManager::isValidGraphicsLevel(U32 level) const { - return (level <= getMaxGraphicsLevel()); + return (level <= getMaxGraphicsLevel()); } std::string LLFeatureManager::getNameForGraphicsLevel(U32 level) const { - if (isValidGraphicsLevel(level)) - { - return sGraphicsLevelNames[level]; - } - return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. " - << getMaxGraphicsLevel()); + if (isValidGraphicsLevel(level)) + { + return sGraphicsLevelNames[level]; + } + return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. " + << getMaxGraphicsLevel()); } S32 LLFeatureManager::getGraphicsLevelForName(const std::string& name) const { - const std::string FixedFunction("FixedFunction"); - std::string rname(name); - if (LLStringUtil::endsWith(rname, FixedFunction)) - { - // chop off any "FixedFunction" suffix - rname = rname.substr(0, rname.length() - FixedFunction.length()); - } - for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i) - { - if (sGraphicsLevelNames[i] == rname) - { - return i; - } - } - return -1; + const std::string FixedFunction("FixedFunction"); + std::string rname(name); + if (LLStringUtil::endsWith(rname, FixedFunction)) + { + // chop off any "FixedFunction" suffix + rname = rname.substr(0, rname.length() - FixedFunction.length()); + } + for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i) + { + if (sGraphicsLevelNames[i] == rname) + { + return i; + } + } + return -1; } LLFeatureList *LLFeatureManager::findMask(const std::string& name) { - if (mMaskList.count(name)) - { - return mMaskList[name]; - } + if (mMaskList.count(name)) + { + return mMaskList[name]; + } - return NULL; + return NULL; } BOOL LLFeatureManager::maskFeatures(const std::string& name) { - LLFeatureList *maskp = findMask(name); - if (!maskp) - { - LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL; - return FALSE; - } - LL_INFOS("RenderInit") << "Applying GPU Feature list: " << name << LL_ENDL; - return maskList(*maskp); + LLFeatureList *maskp = findMask(name); + if (!maskp) + { + LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL; + return FALSE; + } + LL_INFOS("RenderInit") << "Applying GPU Feature list: " << name << LL_ENDL; + return maskList(*maskp); } bool LLFeatureManager::loadFeatureTables() { - // *TODO - if I or anyone else adds something else to the skipped list - // make this data driven. Put it in the feature table and parse it - // correctly - mSkippedFeatures.insert("RenderAnisotropic"); - mSkippedFeatures.insert("RenderGamma"); - mSkippedFeatures.insert("RenderVBOEnable"); - mSkippedFeatures.insert("RenderFogRatio"); + // *TODO - if I or anyone else adds something else to the skipped list + // make this data driven. Put it in the feature table and parse it + // correctly + mSkippedFeatures.insert("RenderAnisotropic"); + mSkippedFeatures.insert("RenderGamma"); + mSkippedFeatures.insert("RenderVBOEnable"); + mSkippedFeatures.insert("RenderFogRatio"); - // first table is install with app - std::string app_path = gDirUtilp->getAppRODataDir(); - app_path += gDirUtilp->getDirDelimiter(); + // first table is install with app + std::string app_path = gDirUtilp->getAppRODataDir(); + app_path += gDirUtilp->getDirDelimiter(); - std::string filename; - filename = FEATURE_TABLE_FILENAME; + std::string filename; + filename = FEATURE_TABLE_FILENAME; - app_path += filename; + app_path += filename; - bool parse_ok = parseFeatureTable(app_path); + bool parse_ok = parseFeatureTable(app_path); - return parse_ok; + return parse_ok; } bool LLFeatureManager::parseFeatureTable(std::string filename) { - LL_INFOS("RenderInit") << "Attempting to parse feature table from " << filename << LL_ENDL; - - llifstream file; - std::string name; - U32 version; - - cleanupFeatureTables(); // in case an earlier attempt left partial results - file.open(filename.c_str()); /*Flawfinder: ignore*/ - - if (!file) - { - LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL; - return FALSE; - } - - // Check file version - file >> name; - if (name != "version") - { - LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL; - return false; - } - file >> version; - - mTableVersion = version; - LL_INFOS("RenderInit") << "Found feature table version " << version << LL_ENDL; - - LLFeatureList *flp = NULL; - bool parse_ok = true; - while (parse_ok && file >> name ) - { - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - - if (name.substr(0,2) == "//") - { - // This is a comment. - file.getline(buffer, MAX_STRING); - continue; - } - - if (name == "list") - { - LL_DEBUGS("RenderInit") << "Before new list" << std::endl; - if (flp) - { - flp->dump(); - } - else - { - LL_CONT << "No current list"; - } - LL_CONT << LL_ENDL; - - // It's a new mask, create it. - file >> name; - if (!mMaskList.count(name)) - { + LL_INFOS("RenderInit") << "Attempting to parse feature table from " << filename << LL_ENDL; + + llifstream file; + std::string name; + U32 version; + + cleanupFeatureTables(); // in case an earlier attempt left partial results + file.open(filename.c_str()); /*Flawfinder: ignore*/ + + if (!file) + { + LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL; + return FALSE; + } + + // Check file version + file >> name; + if (name != "version") + { + LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL; + return false; + } + file >> version; + + mTableVersion = version; + LL_INFOS("RenderInit") << "Found feature table version " << version << LL_ENDL; + + LLFeatureList *flp = NULL; + bool parse_ok = true; + while (parse_ok && file >> name ) + { + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + + if (name.substr(0,2) == "//") + { + // This is a comment. + file.getline(buffer, MAX_STRING); + continue; + } + + if (name == "list") + { + LL_DEBUGS("RenderInit") << "Before new list" << std::endl; + if (flp) + { + flp->dump(); + } + else + { + LL_CONT << "No current list"; + } + LL_CONT << LL_ENDL; + + // It's a new mask, create it. + file >> name; + if (!mMaskList.count(name)) + { flp = new LLFeatureList(name); mMaskList[name] = flp; } else { - LL_WARNS("RenderInit") << "Overriding mask '" << name << "'; this is invalid!" << LL_ENDL; - parse_ok = false; - } - } - else - { - if (flp) - { + LL_WARNS("RenderInit") << "Overriding mask '" << name << "'; this is invalid!" << LL_ENDL; + parse_ok = false; + } + } + else + { + if (flp) + { S32 available; F32 recommended; file >> available >> recommended; flp->addFeature(name, available, recommended); } - else - { - LL_WARNS("RenderInit") << "Specified parameter before keyword!" << LL_ENDL; - parse_ok = false; - } - } - } - file.close(); - - if (!parse_ok) - { - LL_WARNS("RenderInit") << "Discarding feature table data from " << filename << LL_ENDL; - cleanupFeatureTables(); - } - - return parse_ok; + else + { + LL_WARNS("RenderInit") << "Specified parameter before keyword!" << LL_ENDL; + parse_ok = false; + } + } + } + file.close(); + + if (!parse_ok) + { + LL_WARNS("RenderInit") << "Discarding feature table data from " << filename << LL_ENDL; + cleanupFeatureTables(); + } + + return parse_ok; } F32 gpu_benchmark(); @@ -382,9 +382,9 @@ F32 gpu_benchmark(); F32 logExceptionBenchmark() { // FIXME: gpu_benchmark uses many C++ classes on the stack to control state. - // SEH exceptions with our current exception handling options do not call + // SEH exceptions with our current exception handling options do not call // destructors for these classes, resulting in an undefined state should - // this handler be invoked. + // this handler be invoked. F32 gbps = -1; __try { @@ -406,25 +406,25 @@ F32 logExceptionBenchmark() bool LLFeatureManager::loadGPUClass() { - if (!gSavedSettings.getBOOL("SkipBenchmark")) - { - F32 class1_gbps = gSavedSettings.getF32("RenderClass1MemoryBandwidth"); - //get memory bandwidth from benchmark - F32 gbps; - try - { + if (!gSavedSettings.getBOOL("SkipBenchmark")) + { + F32 class1_gbps = gSavedSettings.getF32("RenderClass1MemoryBandwidth"); + //get memory bandwidth from benchmark + F32 gbps; + try + { #if LL_WINDOWS - gbps = logExceptionBenchmark(); + gbps = logExceptionBenchmark(); #else - gbps = gpu_benchmark(); + gbps = gpu_benchmark(); #endif - } - catch (const std::exception& e) - { - gbps = -1.f; - LL_WARNS("RenderInit") << "GPU benchmark failed: " << e.what() << LL_ENDL; - } - + } + catch (const std::exception& e) + { + gbps = -1.f; + LL_WARNS("RenderInit") << "GPU benchmark failed: " << e.what() << LL_ENDL; + } + mGPUMemoryBandwidth = gbps; // bias by CPU speed @@ -433,36 +433,36 @@ bool LLFeatureManager::loadGPUClass() F32 cpu_bias = llclamp(cpu_mhz / cpu_basis_mhz, 0.5f, 1.f); gbps *= cpu_bias; - if (gbps < 0.f) - { //couldn't bench, default to Low - #if LL_DARWIN - //GLVersion is misleading on OSX, just default to class 3 if we can't bench - LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL; - mGPUClass = GPU_CLASS_3; - #else - mGPUClass = GPU_CLASS_0; - #endif - } - else if (gbps <= class1_gbps) - { - mGPUClass = GPU_CLASS_1; - } - else if (gbps <= class1_gbps *2.f) - { - mGPUClass = GPU_CLASS_2; - } - else if (gbps <= class1_gbps*4.f) - { - mGPUClass = GPU_CLASS_3; - } - else if (gbps <= class1_gbps*8.f) - { - mGPUClass = GPU_CLASS_4; - } - else - { - mGPUClass = GPU_CLASS_5; - } + if (gbps < 0.f) + { //couldn't bench, default to Low + #if LL_DARWIN + //GLVersion is misleading on OSX, just default to class 3 if we can't bench + LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL; + mGPUClass = GPU_CLASS_3; + #else + mGPUClass = GPU_CLASS_0; + #endif + } + else if (gbps <= class1_gbps) + { + mGPUClass = GPU_CLASS_1; + } + else if (gbps <= class1_gbps *2.f) + { + mGPUClass = GPU_CLASS_2; + } + else if (gbps <= class1_gbps*4.f) + { + mGPUClass = GPU_CLASS_3; + } + else if (gbps <= class1_gbps*8.f) + { + mGPUClass = GPU_CLASS_4; + } + else + { + mGPUClass = GPU_CLASS_5; + } #if LL_WINDOWS const F32Gigabytes MIN_PHYSICAL_MEMORY(2); @@ -475,118 +475,118 @@ bool LLFeatureManager::loadGPUClass() mGPUClass = (EGPUClass)(mGPUClass - 1); } #endif //LL_WINDOWS - } //end if benchmark - else - { - //setting says don't benchmark MAINT-7558 + } //end if benchmark + else + { + //setting says don't benchmark MAINT-7558 LL_WARNS("RenderInit") << "Setting 'SkipBenchmark' is true; defaulting to class 1 (may be required for some GPUs)" << LL_ENDL; - - mGPUClass = GPU_CLASS_1; - } - // defaults - mGPUString = gGLManager.getRawGLString(); - mGPUSupported = TRUE; + mGPUClass = GPU_CLASS_1; + } + + // defaults + mGPUString = gGLManager.getRawGLString(); + mGPUSupported = TRUE; - return true; // indicates that a gpu value was established + return true; // indicates that a gpu value was established } void LLFeatureManager::cleanupFeatureTables() { - std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer()); - mMaskList.clear(); + std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer()); + mMaskList.clear(); } void LLFeatureManager::initSingleton() { - // load the tables - loadFeatureTables(); + // load the tables + loadFeatureTables(); - // get the gpu class - loadGPUClass(); + // get the gpu class + loadGPUClass(); - // apply the base masks, so we know if anything is disabled - applyBaseMasks(); + // apply the base masks, so we know if anything is disabled + applyBaseMasks(); } void LLFeatureManager::applyRecommendedSettings() { - // apply saved settings - // cap the level at 2 (high) - U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); - - LL_INFOS("RenderInit") << "Applying Recommended Features for level " << level << LL_ENDL; - - setGraphicsLevel(level, false); - gSavedSettings.setU32("RenderQualityPerformance", level); - - // now apply the tweaks to draw distance - // these are double negatives, because feature masks only work by - // downgrading values, so i needed to make a true value go to false - // for certain cards, thus the awkward name, "Disregard..." - if(!gSavedSettings.getBOOL("Disregard96DefaultDrawDistance")) - { - gSavedSettings.setF32("RenderFarClip", 96.0f); - } - else if(!gSavedSettings.getBOOL("Disregard128DefaultDrawDistance")) - { - gSavedSettings.setF32("RenderFarClip", 128.0f); - } + // apply saved settings + // cap the level at 2 (high) + U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); + + LL_INFOS("RenderInit") << "Applying Recommended Features for level " << level << LL_ENDL; + + setGraphicsLevel(level, false); + gSavedSettings.setU32("RenderQualityPerformance", level); + + // now apply the tweaks to draw distance + // these are double negatives, because feature masks only work by + // downgrading values, so i needed to make a true value go to false + // for certain cards, thus the awkward name, "Disregard..." + if(!gSavedSettings.getBOOL("Disregard96DefaultDrawDistance")) + { + gSavedSettings.setF32("RenderFarClip", 96.0f); + } + else if(!gSavedSettings.getBOOL("Disregard128DefaultDrawDistance")) + { + gSavedSettings.setF32("RenderFarClip", 128.0f); + } } void LLFeatureManager::applyFeatures(bool skipFeatures) { - // see featuretable.txt / featuretable_linux.txt / featuretable_mac.txt + // see featuretable.txt / featuretable_linux.txt / featuretable_mac.txt #ifndef LL_RELEASE_FOR_DOWNLOAD - dump(); + dump(); #endif - // scroll through all of these and set their corresponding control value - for(feature_map_t::iterator mIt = mFeatures.begin(); - mIt != mFeatures.end(); - ++mIt) - { - // skip features you want to skip - // do this for when you don't want to change certain settings - if(skipFeatures) - { - if(mSkippedFeatures.find(mIt->first) != mSkippedFeatures.end()) - { - continue; - } - } - - // get the control setting - LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first); - if(ctrl == NULL) - { - LL_WARNS("RenderInit") << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL; - continue; - } - - // handle all the different types - if(ctrl->isType(TYPE_BOOLEAN)) - { - gSavedSettings.setBOOL(mIt->first, (BOOL)getRecommendedValue(mIt->first)); - } - else if (ctrl->isType(TYPE_S32)) - { - gSavedSettings.setS32(mIt->first, (S32)getRecommendedValue(mIt->first)); - } - else if (ctrl->isType(TYPE_U32)) - { - gSavedSettings.setU32(mIt->first, (U32)getRecommendedValue(mIt->first)); - } - else if (ctrl->isType(TYPE_F32)) - { - gSavedSettings.setF32(mIt->first, (F32)getRecommendedValue(mIt->first)); - } - else - { - LL_WARNS("RenderInit") << "AHHH! Control variable is not a numeric type!" << LL_ENDL; - } - } + // scroll through all of these and set their corresponding control value + for(feature_map_t::iterator mIt = mFeatures.begin(); + mIt != mFeatures.end(); + ++mIt) + { + // skip features you want to skip + // do this for when you don't want to change certain settings + if(skipFeatures) + { + if(mSkippedFeatures.find(mIt->first) != mSkippedFeatures.end()) + { + continue; + } + } + + // get the control setting + LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first); + if(ctrl == NULL) + { + LL_WARNS("RenderInit") << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL; + continue; + } + + // handle all the different types + if(ctrl->isType(TYPE_BOOLEAN)) + { + gSavedSettings.setBOOL(mIt->first, (BOOL)getRecommendedValue(mIt->first)); + } + else if (ctrl->isType(TYPE_S32)) + { + gSavedSettings.setS32(mIt->first, (S32)getRecommendedValue(mIt->first)); + } + else if (ctrl->isType(TYPE_U32)) + { + gSavedSettings.setU32(mIt->first, (U32)getRecommendedValue(mIt->first)); + } + else if (ctrl->isType(TYPE_F32)) + { + gSavedSettings.setF32(mIt->first, (F32)getRecommendedValue(mIt->first)); + } + else + { + LL_WARNS("RenderInit") << "AHHH! Control variable is not a numeric type!" << LL_ENDL; + } + } } void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures) @@ -609,69 +609,69 @@ void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures) void LLFeatureManager::applyBaseMasks() { - // reapply masks - mFeatures.clear(); - - LLFeatureList* maskp = findMask("all"); - if(maskp == NULL) - { - LL_WARNS("RenderInit") << "AHH! No \"all\" in feature table!" << LL_ENDL; - return; - } - - mFeatures = maskp->getFeatures(); - - // mask class - if (mGPUClass >= 0 && mGPUClass < 6) - { - const char* class_table[] = - { - "Class0", - "Class1", - "Class2", - "Class3", - "Class4", - "Class5", - }; - - LL_INFOS("RenderInit") << "Setting GPU Class to " << class_table[mGPUClass] << LL_ENDL; - maskFeatures(class_table[mGPUClass]); - } - else - { - LL_INFOS("RenderInit") << "Setting GPU Class to Unknown" << LL_ENDL; - maskFeatures("Unknown"); - } - - // now all those wacky ones - if (gGLManager.mIsNVIDIA) - { - maskFeatures("NVIDIA"); - } - if (gGLManager.mIsAMD) - { - maskFeatures("AMD"); - } - if (gGLManager.mIsIntel) - { - maskFeatures("Intel"); - } - if (gGLManager.mGLVersion < 3.f) - { - maskFeatures("OpenGLPre30"); - } - if (gGLManager.mNumTextureImageUnits <= 8) - { - maskFeatures("TexUnit8orLess"); - } - if (gGLManager.mNumTextureImageUnits <= 16) - { - maskFeatures("TexUnit16orLess"); - } - if (gGLManager.mVRAM > 512) - { - maskFeatures("VRAMGT512"); - } + // reapply masks + mFeatures.clear(); + + LLFeatureList* maskp = findMask("all"); + if(maskp == NULL) + { + LL_WARNS("RenderInit") << "AHH! No \"all\" in feature table!" << LL_ENDL; + return; + } + + mFeatures = maskp->getFeatures(); + + // mask class + if (mGPUClass >= 0 && mGPUClass < 6) + { + const char* class_table[] = + { + "Class0", + "Class1", + "Class2", + "Class3", + "Class4", + "Class5", + }; + + LL_INFOS("RenderInit") << "Setting GPU Class to " << class_table[mGPUClass] << LL_ENDL; + maskFeatures(class_table[mGPUClass]); + } + else + { + LL_INFOS("RenderInit") << "Setting GPU Class to Unknown" << LL_ENDL; + maskFeatures("Unknown"); + } + + // now all those wacky ones + if (gGLManager.mIsNVIDIA) + { + maskFeatures("NVIDIA"); + } + if (gGLManager.mIsAMD) + { + maskFeatures("AMD"); + } + if (gGLManager.mIsIntel) + { + maskFeatures("Intel"); + } + if (gGLManager.mGLVersion < 3.f) + { + maskFeatures("OpenGLPre30"); + } + if (gGLManager.mNumTextureImageUnits <= 8) + { + maskFeatures("TexUnit8orLess"); + } + if (gGLManager.mNumTextureImageUnits <= 16) + { + maskFeatures("TexUnit16orLess"); + } + if (gGLManager.mVRAM > 512) + { + maskFeatures("VRAMGT512"); + } if (gGLManager.mVRAM < 2048) { maskFeatures("VRAMLT2GB"); @@ -681,79 +681,79 @@ void LLFeatureManager::applyBaseMasks() maskFeatures("GL3"); } - // now mask by gpu string - // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces - std::string gpustr = mGPUString; - for (std::string::iterator iter = gpustr.begin(); iter != gpustr.end(); ++iter) - { - if (*iter == ' ') - { - *iter = '_'; - } - } - - //LL_INFOS() << "Masking features from gpu table match: " << gpustr << LL_ENDL; - maskFeatures(gpustr); - - if (isSafe()) - { - maskFeatures("safe"); - } + // now mask by gpu string + // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces + std::string gpustr = mGPUString; + for (std::string::iterator iter = gpustr.begin(); iter != gpustr.end(); ++iter) + { + if (*iter == ' ') + { + *iter = '_'; + } + } + + //LL_INFOS() << "Masking features from gpu table match: " << gpustr << LL_ENDL; + maskFeatures(gpustr); + + if (isSafe()) + { + maskFeatures("safe"); + } } LLSD LLFeatureManager::getRecommendedSettingsMap() { - // Create the map and fill it with the hardware recommended settings. - // It's needed to create an initial Default graphics preset (MAINT-6435). - // The process is similar to the one LLFeatureManager::applyRecommendedSettings() does. - - LLSD map(LLSD::emptyMap()); - - U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); - LL_INFOS("RenderInit") << "Getting the map of recommended settings for level " << level << LL_ENDL; - - std::string features(isValidGraphicsLevel(level) ? getNameForGraphicsLevel(level) : "Low"); - - maskFeatures(features); - - LLControlVariable* ctrl = gSavedSettings.getControl("RenderQualityPerformance"); // include the quality value for correct preset loading - map["RenderQualityPerformance"]["Value"] = (LLSD::Integer)level; - map["RenderQualityPerformance"]["Comment"] = ctrl->getComment();; - map["RenderQualityPerformance"]["Persist"] = 1; - map["RenderQualityPerformance"]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); - - - - for (feature_map_t::iterator mIt = mFeatures.begin(); mIt != mFeatures.end(); ++mIt) - { - LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first); - if (ctrl == NULL) - { - LL_WARNS("RenderInit") << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL; - continue; - } - - if (ctrl->isType(TYPE_BOOLEAN)) - { - map[mIt->first]["Value"] = (LLSD::Boolean)getRecommendedValue(mIt->first); - } - else if (ctrl->isType(TYPE_S32) || ctrl->isType(TYPE_U32)) - { - map[mIt->first]["Value"] = (LLSD::Integer)getRecommendedValue(mIt->first); - } - else if (ctrl->isType(TYPE_F32)) - { - map[mIt->first]["Value"] = (LLSD::Real)getRecommendedValue(mIt->first); - } - else - { - LL_WARNS("RenderInit") << "AHHH! Control variable is not a numeric type!" << LL_ENDL; - continue; - } - map[mIt->first]["Comment"] = ctrl->getComment();; - map[mIt->first]["Persist"] = 1; - map[mIt->first]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); - } - - return map; + // Create the map and fill it with the hardware recommended settings. + // It's needed to create an initial Default graphics preset (MAINT-6435). + // The process is similar to the one LLFeatureManager::applyRecommendedSettings() does. + + LLSD map(LLSD::emptyMap()); + + U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); + LL_INFOS("RenderInit") << "Getting the map of recommended settings for level " << level << LL_ENDL; + + std::string features(isValidGraphicsLevel(level) ? getNameForGraphicsLevel(level) : "Low"); + + maskFeatures(features); + + LLControlVariable* ctrl = gSavedSettings.getControl("RenderQualityPerformance"); // include the quality value for correct preset loading + map["RenderQualityPerformance"]["Value"] = (LLSD::Integer)level; + map["RenderQualityPerformance"]["Comment"] = ctrl->getComment();; + map["RenderQualityPerformance"]["Persist"] = 1; + map["RenderQualityPerformance"]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); + + + + for (feature_map_t::iterator mIt = mFeatures.begin(); mIt != mFeatures.end(); ++mIt) + { + LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first); + if (ctrl == NULL) + { + LL_WARNS("RenderInit") << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL; + continue; + } + + if (ctrl->isType(TYPE_BOOLEAN)) + { + map[mIt->first]["Value"] = (LLSD::Boolean)getRecommendedValue(mIt->first); + } + else if (ctrl->isType(TYPE_S32) || ctrl->isType(TYPE_U32)) + { + map[mIt->first]["Value"] = (LLSD::Integer)getRecommendedValue(mIt->first); + } + else if (ctrl->isType(TYPE_F32)) + { + map[mIt->first]["Value"] = (LLSD::Real)getRecommendedValue(mIt->first); + } + else + { + LL_WARNS("RenderInit") << "AHHH! Control variable is not a numeric type!" << LL_ENDL; + continue; + } + map[mIt->first]["Comment"] = ctrl->getComment();; + map[mIt->first]["Persist"] = 1; + map[mIt->first]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); + } + + return map; } diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index b82172c506..96ab5da318 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfilepicker.cpp * @brief OS-specific file picker * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -34,7 +34,7 @@ #include "llframetimer.h" #include "lltrans.h" #include "llviewercontrol.h" -#include "llwindow.h" // beforeDialog() +#include "llwindow.h" // beforeDialog() #if LL_SDL #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers @@ -76,149 +76,149 @@ LLFilePicker LLFilePicker::sInstance; // Implementation // LLFilePicker::LLFilePicker() - : mCurrentFile(0), - mLocked(false) + : mCurrentFile(0), + mLocked(false) { - reset(); + reset(); #if LL_WINDOWS - mOFN.lStructSize = sizeof(OPENFILENAMEW); - mOFN.hwndOwner = NULL; // Set later - mOFN.hInstance = NULL; - mOFN.lpstrCustomFilter = NULL; - mOFN.nMaxCustFilter = 0; - mOFN.lpstrFile = NULL; // set in open and close - mOFN.nMaxFile = LL_MAX_PATH; - mOFN.lpstrFileTitle = NULL; - mOFN.nMaxFileTitle = 0; - mOFN.lpstrInitialDir = NULL; - mOFN.lpstrTitle = NULL; - mOFN.Flags = 0; // set in open and close - mOFN.nFileOffset = 0; - mOFN.nFileExtension = 0; - mOFN.lpstrDefExt = NULL; - mOFN.lCustData = 0L; - mOFN.lpfnHook = NULL; - mOFN.lpTemplateName = NULL; - mFilesW[0] = '\0'; + mOFN.lStructSize = sizeof(OPENFILENAMEW); + mOFN.hwndOwner = NULL; // Set later + mOFN.hInstance = NULL; + mOFN.lpstrCustomFilter = NULL; + mOFN.nMaxCustFilter = 0; + mOFN.lpstrFile = NULL; // set in open and close + mOFN.nMaxFile = LL_MAX_PATH; + mOFN.lpstrFileTitle = NULL; + mOFN.nMaxFileTitle = 0; + mOFN.lpstrInitialDir = NULL; + mOFN.lpstrTitle = NULL; + mOFN.Flags = 0; // set in open and close + mOFN.nFileOffset = 0; + mOFN.nFileExtension = 0; + mOFN.lpstrDefExt = NULL; + mOFN.lCustData = 0L; + mOFN.lpfnHook = NULL; + mOFN.lpTemplateName = NULL; + mFilesW[0] = '\0'; #elif LL_DARWIN - mPickOptions = 0; + mPickOptions = 0; #endif } LLFilePicker::~LLFilePicker() { - // nothing + // nothing } -// utility function to check if access to local file system via file browser +// utility function to check if access to local file system via file browser // is enabled and if not, tidy up and indicate we're not allowed to do this. bool LLFilePicker::check_local_file_access_enabled() { - // if local file browsing is turned off, return without opening dialog - bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled"); - if ( ! local_file_system_browsing_enabled ) - { - mFiles.clear(); - return false; - } - - return true; + // if local file browsing is turned off, return without opening dialog + bool local_file_system_browsing_enabled = gSavedSettings.getBOOL("LocalFileSystemBrowsingEnabled"); + if ( ! local_file_system_browsing_enabled ) + { + mFiles.clear(); + return false; + } + + return true; } const std::string LLFilePicker::getFirstFile() { - mCurrentFile = 0; - return getNextFile(); + mCurrentFile = 0; + return getNextFile(); } const std::string LLFilePicker::getNextFile() { - if (mCurrentFile >= getFileCount()) - { - mLocked = false; - return std::string(); - } - else - { - return mFiles[mCurrentFile++]; - } + if (mCurrentFile >= getFileCount()) + { + mLocked = false; + return std::string(); + } + else + { + return mFiles[mCurrentFile++]; + } } const std::string LLFilePicker::getCurFile() { - if (mCurrentFile >= getFileCount()) - { - mLocked = false; - return std::string(); - } - else - { - return mFiles[mCurrentFile]; - } + if (mCurrentFile >= getFileCount()) + { + mLocked = false; + return std::string(); + } + else + { + return mFiles[mCurrentFile]; + } } void LLFilePicker::reset() { - mLocked = false; - mFiles.clear(); - mCurrentFile = 0; + mLocked = false; + mFiles.clear(); + mCurrentFile = 0; } #if LL_WINDOWS BOOL LLFilePicker::setupFilter(ELoadFilter filter) { - BOOL res = TRUE; - switch (filter) - { + BOOL res = TRUE; + switch (filter) + { case FFLOAD_ALL: case FFLOAD_EXE: - mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \ - SOUND_FILTER \ - IMAGE_FILTER \ - ANIM_FILTER \ - MATERIAL_FILTER \ - L"\0"; - break; - case FFLOAD_WAV: - mOFN.lpstrFilter = SOUND_FILTER \ - L"\0"; - break; - case FFLOAD_IMAGE: - mOFN.lpstrFilter = IMAGE_FILTER \ - L"\0"; - break; - case FFLOAD_ANIM: - mOFN.lpstrFilter = ANIM_FILTER \ - L"\0"; - break; - case FFLOAD_GLTF: - mOFN.lpstrFilter = GLTF_FILTER \ - L"\0"; - break; - case FFLOAD_COLLADA: - mOFN.lpstrFilter = COLLADA_FILTER \ - L"\0"; - break; - case FFLOAD_XML: - mOFN.lpstrFilter = XML_FILTER \ - L"\0"; - break; - case FFLOAD_SLOBJECT: - mOFN.lpstrFilter = SLOBJECT_FILTER \ - L"\0"; - break; - case FFLOAD_RAW: - mOFN.lpstrFilter = RAW_FILTER \ - L"\0"; - break; - case FFLOAD_MODEL: - mOFN.lpstrFilter = MODEL_FILTER \ - L"\0"; - break; + mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \ + SOUND_FILTER \ + IMAGE_FILTER \ + ANIM_FILTER \ + MATERIAL_FILTER \ + L"\0"; + break; + case FFLOAD_WAV: + mOFN.lpstrFilter = SOUND_FILTER \ + L"\0"; + break; + case FFLOAD_IMAGE: + mOFN.lpstrFilter = IMAGE_FILTER \ + L"\0"; + break; + case FFLOAD_ANIM: + mOFN.lpstrFilter = ANIM_FILTER \ + L"\0"; + break; + case FFLOAD_GLTF: + mOFN.lpstrFilter = GLTF_FILTER \ + L"\0"; + break; + case FFLOAD_COLLADA: + mOFN.lpstrFilter = COLLADA_FILTER \ + L"\0"; + break; + case FFLOAD_XML: + mOFN.lpstrFilter = XML_FILTER \ + L"\0"; + break; + case FFLOAD_SLOBJECT: + mOFN.lpstrFilter = SLOBJECT_FILTER \ + L"\0"; + break; + case FFLOAD_RAW: + mOFN.lpstrFilter = RAW_FILTER \ + L"\0"; + break; + case FFLOAD_MODEL: + mOFN.lpstrFilter = MODEL_FILTER \ + L"\0"; + break; case FFLOAD_MATERIAL: mOFN.lpstrFilter = MATERIAL_FILTER \ L"\0"; @@ -233,70 +233,70 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = HDRI_FILTER \ L"\0"; break; - case FFLOAD_SCRIPT: - mOFN.lpstrFilter = SCRIPT_FILTER \ - L"\0"; - break; - case FFLOAD_DICTIONARY: - mOFN.lpstrFilter = DICTIONARY_FILTER \ - L"\0"; - break; - default: - res = FALSE; - break; - } - return res; + case FFLOAD_SCRIPT: + mOFN.lpstrFilter = SCRIPT_FILTER \ + L"\0"; + break; + case FFLOAD_DICTIONARY: + mOFN.lpstrFilter = DICTIONARY_FILTER \ + L"\0"; + break; + default: + res = FALSE; + break; + } + return res; } BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking) { - if( mLocked ) - { - return FALSE; - } - BOOL success = FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - // don't provide default file selection - mFilesW[0] = '\0'; - - mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); - mOFN.lpstrFile = mFilesW; - mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; - mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ; - mOFN.nFilterIndex = 1; - - setupFilter(filter); - - if (blocking) - { - // Modal, so pause agent - send_agent_pause(); - } - - reset(); - - // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! - success = GetOpenFileName(&mOFN); - if (success) - { - std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); - mFiles.push_back(filename); - } - - if (blocking) - { - send_agent_resume(); - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - } - - return success; + if( mLocked ) + { + return FALSE; + } + BOOL success = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + // don't provide default file selection + mFilesW[0] = '\0'; + + mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); + mOFN.lpstrFile = mFilesW; + mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR ; + mOFN.nFilterIndex = 1; + + setupFilter(filter); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + reset(); + + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + success = GetOpenFileName(&mOFN); + if (success) + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + + if (blocking) + { + send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + } + + return success; } BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, @@ -310,79 +310,79 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking) { - if( mLocked ) - { - return FALSE; - } - BOOL success = FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - // don't provide default file selection - mFilesW[0] = '\0'; - - mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); - mOFN.lpstrFile = mFilesW; - mOFN.nFilterIndex = 1; - mOFN.nMaxFile = FILENAME_BUFFER_SIZE; - mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | - OFN_EXPLORER | OFN_ALLOWMULTISELECT; - - setupFilter(filter); - - reset(); - - if (blocking) - { - // Modal, so pause agent - send_agent_pause(); - } - - // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! - success = GetOpenFileName(&mOFN); // pauses until ok or cancel. - if( success ) - { - // The getopenfilename api doesn't tell us if we got more than - // one file, so we have to test manually by checking string - // lengths. - if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/ - { - std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); - mFiles.push_back(filename); - } - else - { - mLocked = true; - WCHAR* tptrw = mFilesW; - std::string dirname; - while(1) - { - if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0' - break; - if (*tptrw == 0) - tptrw++; // shouldn't happen? - std::string filename = utf16str_to_utf8str(llutf16string(tptrw)); - if (dirname.empty()) - dirname = filename + "\\"; - else - mFiles.push_back(dirname + filename); - tptrw += wcslen(tptrw); - } - } - } - - if (blocking) - { - send_agent_resume(); - } - - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - return success; + if( mLocked ) + { + return FALSE; + } + BOOL success = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + // don't provide default file selection + mFilesW[0] = '\0'; + + mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); + mOFN.lpstrFile = mFilesW; + mOFN.nFilterIndex = 1; + mOFN.nMaxFile = FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | + OFN_EXPLORER | OFN_ALLOWMULTISELECT; + + setupFilter(filter); + + reset(); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + success = GetOpenFileName(&mOFN); // pauses until ok or cancel. + if( success ) + { + // The getopenfilename api doesn't tell us if we got more than + // one file, so we have to test manually by checking string + // lengths. + if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/ + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + else + { + mLocked = true; + WCHAR* tptrw = mFilesW; + std::string dirname; + while(1) + { + if (*tptrw == 0 && *(tptrw+1) == 0) // double '\0' + break; + if (*tptrw == 0) + tptrw++; // shouldn't happen? + std::string filename = utf16str_to_utf8str(llutf16string(tptrw)); + if (dirname.empty()) + dirname = filename + "\\"; + else + mFiles.push_back(dirname + filename); + tptrw += wcslen(tptrw); + } + } + } + + if (blocking) + { + send_agent_resume(); + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; } BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, @@ -396,222 +396,222 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking) { - if( mLocked ) - { - return FALSE; - } - BOOL success = FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - mOFN.lpstrFile = mFilesW; - if (!filename.empty()) - { - llutf16string tstring = utf8str_to_utf16str(filename); - wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/ - else - { - mFilesW[0] = '\0'; - } - mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); - - switch( filter ) - { - case FFSAVE_ALL: - mOFN.lpstrDefExt = NULL; - mOFN.lpstrFilter = - L"All Files (*.*)\0*.*\0" \ - L"WAV Sounds (*.wav)\0*.wav\0" \ - L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \ - L"\0"; - break; - case FFSAVE_WAV: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"wav"; - mOFN.lpstrFilter = - L"WAV Sounds (*.wav)\0*.wav\0" \ - L"\0"; - break; - case FFSAVE_TGA: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"tga"; - mOFN.lpstrFilter = - L"Targa Images (*.tga)\0*.tga\0" \ - L"\0"; - break; - case FFSAVE_BMP: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"bmp"; - mOFN.lpstrFilter = - L"Bitmap Images (*.bmp)\0*.bmp\0" \ - L"\0"; - break; - case FFSAVE_PNG: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"png"; - mOFN.lpstrFilter = - L"PNG Images (*.png)\0*.png\0" \ - L"\0"; - break; - case FFSAVE_TGAPNG: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - //PNG by default - } - mOFN.lpstrDefExt = L"png"; - mOFN.lpstrFilter = - L"PNG Images (*.png)\0*.png\0" \ - L"Targa Images (*.tga)\0*.tga\0" \ - L"\0"; - break; - - case FFSAVE_JPEG: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"jpg"; - mOFN.lpstrFilter = - L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \ - L"\0"; - break; - case FFSAVE_AVI: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"avi"; - mOFN.lpstrFilter = - L"AVI Movie File (*.avi)\0*.avi\0" \ - L"\0"; - break; - case FFSAVE_ANIM: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"xaf"; - mOFN.lpstrFilter = - L"XAF Anim File (*.xaf)\0*.xaf\0" \ - L"\0"; - break; - case FFSAVE_GLTF: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"glb"; - mOFN.lpstrFilter = - L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \ - L"\0"; - break; - case FFSAVE_XML: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - - mOFN.lpstrDefExt = L"xml"; - mOFN.lpstrFilter = - L"XML File (*.xml)\0*.xml\0" \ - L"\0"; - break; - case FFSAVE_COLLADA: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"collada"; - mOFN.lpstrFilter = - L"COLLADA File (*.collada)\0*.collada\0" \ - L"\0"; - break; - case FFSAVE_RAW: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"raw"; - mOFN.lpstrFilter = RAW_FILTER \ - L"\0"; - break; - case FFSAVE_J2C: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE); - } - mOFN.lpstrDefExt = L"j2c"; - mOFN.lpstrFilter = - L"Compressed Images (*.j2c)\0*.j2c\0" \ - L"\0"; - break; - case FFSAVE_SCRIPT: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE); - } - mOFN.lpstrDefExt = L"txt"; - mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0"; - break; - default: - return FALSE; - } - - - mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; - mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST; - - reset(); - - if (blocking) - { - // Modal, so pause agent - send_agent_pause(); - } - - { - // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! - try - { - success = GetSaveFileName(&mOFN); - if (success) - { - std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); - mFiles.push_back(filename); - } - } - catch (...) - { - LOG_UNHANDLED_EXCEPTION(""); - } - gKeyboard->resetKeys(); - } - - if (blocking) - { - send_agent_resume(); - } - - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - return success; + if( mLocked ) + { + return FALSE; + } + BOOL success = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + mOFN.lpstrFile = mFilesW; + if (!filename.empty()) + { + llutf16string tstring = utf8str_to_utf16str(filename); + wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/ + else + { + mFilesW[0] = '\0'; + } + mOFN.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); + + switch( filter ) + { + case FFSAVE_ALL: + mOFN.lpstrDefExt = NULL; + mOFN.lpstrFilter = + L"All Files (*.*)\0*.*\0" \ + L"WAV Sounds (*.wav)\0*.wav\0" \ + L"Targa, Bitmap Images (*.tga; *.bmp)\0*.tga;*.bmp\0" \ + L"\0"; + break; + case FFSAVE_WAV: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"wav"; + mOFN.lpstrFilter = + L"WAV Sounds (*.wav)\0*.wav\0" \ + L"\0"; + break; + case FFSAVE_TGA: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"tga"; + mOFN.lpstrFilter = + L"Targa Images (*.tga)\0*.tga\0" \ + L"\0"; + break; + case FFSAVE_BMP: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"bmp"; + mOFN.lpstrFilter = + L"Bitmap Images (*.bmp)\0*.bmp\0" \ + L"\0"; + break; + case FFSAVE_PNG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"png"; + mOFN.lpstrFilter = + L"PNG Images (*.png)\0*.png\0" \ + L"\0"; + break; + case FFSAVE_TGAPNG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.png", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + //PNG by default + } + mOFN.lpstrDefExt = L"png"; + mOFN.lpstrFilter = + L"PNG Images (*.png)\0*.png\0" \ + L"Targa Images (*.tga)\0*.tga\0" \ + L"\0"; + break; + + case FFSAVE_JPEG: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.jpeg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"jpg"; + mOFN.lpstrFilter = + L"JPEG Images (*.jpg *.jpeg)\0*.jpg;*.jpeg\0" \ + L"\0"; + break; + case FFSAVE_AVI: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"avi"; + mOFN.lpstrFilter = + L"AVI Movie File (*.avi)\0*.avi\0" \ + L"\0"; + break; + case FFSAVE_ANIM: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"xaf"; + mOFN.lpstrFilter = + L"XAF Anim File (*.xaf)\0*.xaf\0" \ + L"\0"; + break; + case FFSAVE_GLTF: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.glb", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"glb"; + mOFN.lpstrFilter = + L"glTF Asset File (*.gltf *.glb)\0*.gltf;*.glb\0" \ + L"\0"; + break; + case FFSAVE_XML: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + + mOFN.lpstrDefExt = L"xml"; + mOFN.lpstrFilter = + L"XML File (*.xml)\0*.xml\0" \ + L"\0"; + break; + case FFSAVE_COLLADA: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"collada"; + mOFN.lpstrFilter = + L"COLLADA File (*.collada)\0*.collada\0" \ + L"\0"; + break; + case FFSAVE_RAW: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ + } + mOFN.lpstrDefExt = L"raw"; + mOFN.lpstrFilter = RAW_FILTER \ + L"\0"; + break; + case FFSAVE_J2C: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE); + } + mOFN.lpstrDefExt = L"j2c"; + mOFN.lpstrFilter = + L"Compressed Images (*.j2c)\0*.j2c\0" \ + L"\0"; + break; + case FFSAVE_SCRIPT: + if (filename.empty()) + { + wcsncpy( mFilesW,L"untitled.lsl", FILENAME_BUFFER_SIZE); + } + mOFN.lpstrDefExt = L"txt"; + mOFN.lpstrFilter = L"LSL Files (*.lsl)\0*.lsl\0" L"\0"; + break; + default: + return FALSE; + } + + + mOFN.nMaxFile = SINGLE_FILENAME_BUFFER_SIZE; + mOFN.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST; + + reset(); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } + + { + // NOTA BENE: hitting the file dialog triggers a window focus event, destroying the selection manager!! + try + { + success = GetSaveFileName(&mOFN); + if (success) + { + std::string filename = utf16str_to_utf8str(llutf16string(mFilesW)); + mFiles.push_back(filename); + } + } + catch (...) + { + LOG_UNHANDLED_EXCEPTION(""); + } + gKeyboard->resetKeys(); + } + + if (blocking) + { + send_agent_resume(); + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; } BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, @@ -692,25 +692,25 @@ std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadF LL_WARNS() << "Unsupported format." << LL_ENDL; } - return allowedv; + return allowedv; } -bool LLFilePicker::doNavChooseDialog(ELoadFilter filter) +bool LLFilePicker::doNavChooseDialog(ELoadFilter filter) { - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return false; - } - - gViewerWindow->getWindow()->beforeDialog(); - + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } + + gViewerWindow->getWindow()->beforeDialog(); + std::unique_ptr> allowed_types = navOpenFilterProc(filter); - + std::unique_ptr> filev = doLoadDialog(allowed_types.get(), mPickOptions); - gViewerWindow->getWindow()->afterDialog(); + gViewerWindow->getWindow()->afterDialog(); if (filev && filev->size() > 0) @@ -718,8 +718,8 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter) mFiles.insert(mFiles.end(), filev->begin(), filev->end()); return true; } - - return false; + + return false; } bool LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter, @@ -731,14 +731,14 @@ bool LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter, { return false; } - + std::unique_ptr> allowed_types=navOpenFilterProc(filter); - + doLoadDialogModeless(allowed_types.get(), mPickOptions, callback, userdata); - + return true; } @@ -792,13 +792,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension, creator = "\?\?\?\?"; extension = "glb"; break; - + case LLFilePicker::FFSAVE_XML: type = "\?\?\?\?"; creator = "\?\?\?\?"; extension = "xml"; break; - + case LLFilePicker::FFSAVE_RAW: type = "\?\?\?\?"; creator = "\?\?\?\?"; @@ -810,13 +810,13 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension, creator = "prvw"; extension = "j2c"; break; - + case LLFilePicker::FFSAVE_SCRIPT: type = "LSL "; creator = "\?\?\?\?"; extension = "lsl"; break; - + case LLFilePicker::FFSAVE_ALL: default: type = "\?\?\?\?"; @@ -826,34 +826,34 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension, } } -bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename) +bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename) { - // Setup the type, creator, and extension - std::string extension, type, creator; - + // Setup the type, creator, and extension + std::string extension, type, creator; + set_nav_save_data(filter, extension, type, creator); - + std::string namestring = filename; if (namestring.empty()) namestring="Untitled"; - - gViewerWindow->getWindow()->beforeDialog(); - // Run the dialog - std::unique_ptr filev = doSaveDialog(&namestring, + gViewerWindow->getWindow()->beforeDialog(); + + // Run the dialog + std::unique_ptr filev = doSaveDialog(&namestring, &type, &creator, &extension, mPickOptions); - gViewerWindow->getWindow()->afterDialog(); + gViewerWindow->getWindow()->afterDialog(); - if ( filev && !filev->empty() ) - { + if ( filev && !filev->empty() ) + { mFiles.push_back(*filev); - return true; + return true; } - - return false; + + return false; } bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter, @@ -863,9 +863,9 @@ bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter, { // Setup the type, creator, and extension std::string extension, type, creator; - + set_nav_save_data(filter, extension, type, creator); - + std::string namestring = filename; if (namestring.empty()) namestring="Untitled"; @@ -882,57 +882,57 @@ bool LLFilePicker::doNavSaveDialogModeless(ESaveFilter filter, BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking) { - if( mLocked ) - return FALSE; + if( mLocked ) + return FALSE; - BOOL success = FALSE; + BOOL success = FALSE; - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + reset(); - reset(); - mPickOptions &= ~F_MULTIPLE; mPickOptions |= F_FILE; - - if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker. + + if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker. { mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY ); mPickOptions &= ~F_FILE; } - if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful - { + if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful + { mPickOptions |= F_NAV_SUPPORT; - } - - if (blocking) // always true for linux/mac - { - // Modal, so pause agent - send_agent_pause(); - } - - - success = doNavChooseDialog(filter); - - if (success) - { - if (!getFileCount()) - success = false; - } - - if (blocking) - { - send_agent_resume(); - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - } - - return success; + } + + if (blocking) // always true for linux/mac + { + // Modal, so pause agent + send_agent_pause(); + } + + + success = doNavChooseDialog(filter); + + if (success) + { + if (!getFileCount()) + success = false; + } + + if (blocking) + { + send_agent_resume(); + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + } + + return success; } @@ -950,10 +950,10 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, } reset(); - + mPickOptions &= ~F_MULTIPLE; mPickOptions |= F_FILE; - + if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker. { @@ -971,47 +971,47 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking) { - if( mLocked ) - return FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - + if( mLocked ) + return FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + BOOL success = FALSE; - reset(); - + reset(); + mPickOptions |= F_FILE; mPickOptions |= F_MULTIPLE; - if (blocking) // always true for linux/mac - { - // Modal, so pause agent - send_agent_pause(); - } - - success = doNavChooseDialog(filter); - - if (blocking) - { - send_agent_resume(); - } - - if (success) - { - if (!getFileCount()) - success = false; - if (getFileCount() > 1) - mLocked = true; - } - - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - return success; + if (blocking) // always true for linux/mac + { + // Modal, so pause agent + send_agent_pause(); + } + + success = doNavChooseDialog(filter); + + if (blocking) + { + send_agent_resume(); + } + + if (success) + { + if (!getFileCount()) + success = false; + if (getFileCount() > 1) + mLocked = true; + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; } @@ -1029,7 +1029,7 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, } reset(); - + mPickOptions |= F_FILE; mPickOptions |= F_MULTIPLE; @@ -1040,42 +1040,42 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking) { - if( mLocked ) - return false; - BOOL success = false; + if( mLocked ) + return false; + BOOL success = false; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return false; + } - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return false; - } + reset(); - reset(); - mPickOptions &= ~F_MULTIPLE; - if (blocking) - { - // Modal, so pause agent - send_agent_pause(); - } + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } success = doNavSaveDialog(filter, filename); if (success) - { - if (!getFileCount()) - success = false; - } - - if (blocking) - { - send_agent_resume(); - } - - // Account for the fact that the app has been stalled. - LLFrameTimer::updateFrameTime(); - return success; + { + if (!getFileCount()) + success = false; + } + + if (blocking) + { + send_agent_resume(); + } + + // Account for the fact that the app has been stalled. + LLFrameTimer::updateFrameTime(); + return success; } BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, @@ -1085,7 +1085,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, { if( mLocked ) return false; - + // if local file browsing is turned off, return without opening dialog if ( check_local_file_access_enabled() == false ) { @@ -1093,7 +1093,7 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, } reset(); - + mPickOptions &= ~F_MULTIPLE; return doNavSaveDialogModeless(filter, filename, callback, userdata); @@ -1107,414 +1107,414 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, // static void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data) { - // We need to run g_filename_to_utf8 in the user's locale - std::string saved_locale(setlocale(LC_ALL, NULL)); - setlocale(LC_ALL, ""); - - LLFilePicker* picker = (LLFilePicker*) user_data; - GError *error = NULL; - gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, - -1, NULL, NULL, &error); - if (error) - { - // *FIXME. - // This condition should really be notified to the user, e.g. - // through a message box. Just logging it is inappropriate. - - // g_filename_display_name is ideal, but >= glib 2.6, so: - // a hand-rolled hacky makeASCII which disallows control chars - std::string display_name; - for (const gchar *str = (const gchar *)data; *str; str++) - { - display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?'); - } - LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL; - } - - if (filename_utf8) - { - picker->mFiles.push_back(std::string(filename_utf8)); - LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL; - g_free(filename_utf8); - } - - setlocale(LC_ALL, saved_locale.c_str()); + // We need to run g_filename_to_utf8 in the user's locale + std::string saved_locale(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, ""); + + LLFilePicker* picker = (LLFilePicker*) user_data; + GError *error = NULL; + gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, + -1, NULL, NULL, &error); + if (error) + { + // *FIXME. + // This condition should really be notified to the user, e.g. + // through a message box. Just logging it is inappropriate. + + // g_filename_display_name is ideal, but >= glib 2.6, so: + // a hand-rolled hacky makeASCII which disallows control chars + std::string display_name; + for (const gchar *str = (const gchar *)data; *str; str++) + { + display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?'); + } + LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL; + } + + if (filename_utf8) + { + picker->mFiles.push_back(std::string(filename_utf8)); + LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL; + g_free(filename_utf8); + } + + setlocale(LC_ALL, saved_locale.c_str()); } // static void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data) { - LLFilePicker* picker = (LLFilePicker*)user_data; - - LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL; - - if (response == GTK_RESPONSE_ACCEPT) - { - GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); - g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data); - g_slist_foreach(file_list, (GFunc)g_free, NULL); - g_slist_free (file_list); - } - - // let's save the extension of the last added file(considering current filter) - GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget)); - if(gfilter) - { - std::string filter = gtk_file_filter_get_name(gfilter); - - if(filter == LLTrans::getString("png_image_files")) - { - picker->mCurrentExtension = ".png"; - } - else if(filter == LLTrans::getString("targa_image_files")) - { - picker->mCurrentExtension = ".tga"; - } - } - - // set the default path for this usage context. - const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); - if (cur_folder != NULL) - { - picker->mContextToPathMap[picker->mCurContextName] = cur_folder; - } - - gtk_widget_destroy(widget); - gtk_main_quit(); + LLFilePicker* picker = (LLFilePicker*)user_data; + + LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL; + + if (response == GTK_RESPONSE_ACCEPT) + { + GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); + g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data); + g_slist_foreach(file_list, (GFunc)g_free, NULL); + g_slist_free (file_list); + } + + // let's save the extension of the last added file(considering current filter) + GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget)); + if(gfilter) + { + std::string filter = gtk_file_filter_get_name(gfilter); + + if(filter == LLTrans::getString("png_image_files")) + { + picker->mCurrentExtension = ".png"; + } + else if(filter == LLTrans::getString("targa_image_files")) + { + picker->mCurrentExtension = ".tga"; + } + } + + // set the default path for this usage context. + const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); + if (cur_folder != NULL) + { + picker->mContextToPathMap[picker->mCurContextName] = cur_folder; + } + + gtk_widget_destroy(widget); + gtk_main_quit(); } GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context) { #ifndef LL_MESA_HEADLESS - if (LLWindowSDL::ll_try_gtk_init()) - { - GtkWidget *win = NULL; - GtkFileChooserAction pickertype = - is_save? - (is_folder? - GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER : - GTK_FILE_CHOOSER_ACTION_SAVE) : - (is_folder? - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : - GTK_FILE_CHOOSER_ACTION_OPEN); - - win = gtk_file_chooser_dialog_new(NULL, NULL, - pickertype, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - is_folder ? - GTK_STOCK_APPLY : - (is_save ? - GTK_STOCK_SAVE : - GTK_STOCK_OPEN), - GTK_RESPONSE_ACCEPT, - (gchar *)NULL); - mCurContextName = context; - - // get the default path for this usage context if it's been - // seen before. - std::map::iterator - this_path = mContextToPathMap.find(context); - if (this_path != mContextToPathMap.end()) - { - gtk_file_chooser_set_current_folder - (GTK_FILE_CHOOSER(win), - this_path->second.c_str()); - } + if (LLWindowSDL::ll_try_gtk_init()) + { + GtkWidget *win = NULL; + GtkFileChooserAction pickertype = + is_save? + (is_folder? + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER : + GTK_FILE_CHOOSER_ACTION_SAVE) : + (is_folder? + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : + GTK_FILE_CHOOSER_ACTION_OPEN); + + win = gtk_file_chooser_dialog_new(NULL, NULL, + pickertype, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, + is_folder ? + GTK_STOCK_APPLY : + (is_save ? + GTK_STOCK_SAVE : + GTK_STOCK_OPEN), + GTK_RESPONSE_ACCEPT, + (gchar *)NULL); + mCurContextName = context; + + // get the default path for this usage context if it's been + // seen before. + std::map::iterator + this_path = mContextToPathMap.find(context); + if (this_path != mContextToPathMap.end()) + { + gtk_file_chooser_set_current_folder + (GTK_FILE_CHOOSER(win), + this_path->second.c_str()); + } # if LL_X11 - // Make GTK tell the window manager to associate this - // dialog with our non-GTK raw X11 window, which should try - // to keep it on top etc. - Window XWindowID = LLWindowSDL::get_SDL_XWindowID(); - if (None != XWindowID) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } - else - { - LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL; - } + // Make GTK tell the window manager to associate this + // dialog with our non-GTK raw X11 window, which should try + // to keep it on top etc. + Window XWindowID = LLWindowSDL::get_SDL_XWindowID(); + if (None != XWindowID) + { + gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin + GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID); + gdk_window_set_transient_for(GTK_WIDGET(win)->window, + gdkwin); + } + else + { + LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL; + } # endif //LL_X11 - g_signal_connect (GTK_FILE_CHOOSER(win), - "response", - G_CALLBACK(LLFilePicker::chooser_responder), - this); + g_signal_connect (GTK_FILE_CHOOSER(win), + "response", + G_CALLBACK(LLFilePicker::chooser_responder), + this); - gtk_window_set_modal(GTK_WINDOW(win), TRUE); + gtk_window_set_modal(GTK_WINDOW(win), TRUE); - /* GTK 2.6: if (is_folder) - gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win), - TRUE); */ + /* GTK 2.6: if (is_folder) + gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win), + TRUE); */ - return GTK_WINDOW(win); - } - else - { - return NULL; - } + return GTK_WINDOW(win); + } + else + { + return NULL; + } #else - return NULL; + return NULL; #endif //LL_MESA_HEADLESS } static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter, - GtkWindow *picker, - std::string filtername) -{ - gtk_file_filter_set_name(gfilter, filtername.c_str()); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter); - GtkFileFilter *allfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(allfilter, "*"); - gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str()); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter); - gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter); + GtkWindow *picker, + std::string filtername) +{ + gtk_file_filter_set_name(gfilter, filtername.c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), + gfilter); + GtkFileFilter *allfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(allfilter, "*"); + gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str()); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter); + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter); } static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker, - std::string pattern, - std::string filtername) + std::string pattern, + std::string filtername) { - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, pattern.c_str()); - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, pattern.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; } static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker, - std::string mime, - std::string filtername) + std::string mime, + std::string filtername) { - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_mime_type(gfilter, mime.c_str()); - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_mime_type(gfilter, mime.c_str()); + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; } static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav", - LLTrans::getString("sound_files") + " (*.wav)"); + return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav", + LLTrans::getString("sound_files") + " (*.wav)"); } static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker) { - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, "*.bvh"); - gtk_file_filter_add_pattern(gfilter, "*.anim"); - std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)"; - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.bvh"); + gtk_file_filter_add_pattern(gfilter, "*.anim"); + std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; } static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml", - LLTrans::getString("xml_files") + " (*.xml)"); + return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml", + LLTrans::getString("xml_files") + " (*.xml)"); } static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae", - LLTrans::getString("scene_files") + " (*.dae)"); + return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae", + LLTrans::getString("scene_files") + " (*.dae)"); } static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) { - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, "*.tga"); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str()); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str()); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str()); - std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; + GtkFileFilter *gfilter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(gfilter, "*.tga"); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str()); + gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str()); + std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; + add_common_filters_to_gtkchooser(gfilter, picker, filtername); + return filtername; } - + static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, - LLTrans::getString("script_files") + " (*.lsl)"); + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, + LLTrans::getString("script_files") + " (*.lsl)"); } static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) { - return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, - LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); + return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, + LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); } static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker) { - GtkFileFilter *gfilter_tga = gtk_file_filter_new(); - GtkFileFilter *gfilter_png = gtk_file_filter_new(); - - gtk_file_filter_add_pattern(gfilter_tga, "*.tga"); - gtk_file_filter_add_mime_type(gfilter_png, "image/png"); - std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)"; - gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str()); - gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str()); - - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter_png); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter_tga); - return caption; + GtkFileFilter *gfilter_tga = gtk_file_filter_new(); + GtkFileFilter *gfilter_png = gtk_file_filter_new(); + + gtk_file_filter_add_pattern(gfilter_tga, "*.tga"); + gtk_file_filter_add_mime_type(gfilter_png, "image/png"); + std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)"; + gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str()); + gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str()); + + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), + gfilter_png); + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), + gfilter_tga); + return caption; } BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) { - BOOL rtn = FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - gViewerWindow->getWindow()->beforeDialog(); - - reset(); - - GtkWindow* picker = buildFilePicker(true, false, "savefile"); - - if (picker) - { - std::string suggest_name = "untitled"; - std::string suggest_ext = ""; - std::string caption = LLTrans::getString("save_file_verb") + " "; - switch (filter) - { - case FFSAVE_WAV: - caption += add_wav_filter_to_gtkchooser(picker); - suggest_ext = ".wav"; - break; - case FFSAVE_TGA: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)"); - suggest_ext = ".tga"; - break; - case FFSAVE_BMP: - caption += add_simple_mime_filter_to_gtkchooser - (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)"); - suggest_ext = ".bmp"; - break; - case FFSAVE_PNG: - caption += add_simple_mime_filter_to_gtkchooser - (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)"); - suggest_ext = ".png"; - break; - case FFSAVE_TGAPNG: - caption += add_save_texture_filter_to_gtkchooser(picker); - suggest_ext = ".png"; - break; - case FFSAVE_AVI: - caption += add_simple_mime_filter_to_gtkchooser - (picker, "video/x-msvideo", - LLTrans::getString("avi_movie_file") + " (*.avi)"); - suggest_ext = ".avi"; - break; - case FFSAVE_ANIM: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)"); - suggest_ext = ".xaf"; - break; - case FFSAVE_XML: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)"); - suggest_ext = ".xml"; - break; - case FFSAVE_RAW: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)"); - suggest_ext = ".raw"; - break; - case FFSAVE_J2C: - // *TODO: Should this be 'image/j2c' ? - caption += add_simple_mime_filter_to_gtkchooser - (picker, "images/jp2", - LLTrans::getString("compressed_image_files") + " (*.j2c)"); - suggest_ext = ".j2c"; - break; - case FFSAVE_SCRIPT: - caption += add_script_filter_to_gtkchooser(picker); - suggest_ext = ".lsl"; - break; - default:; - break; - } - - gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); - - if (filename.empty()) - { - suggest_name += suggest_ext; - - gtk_file_chooser_set_current_name - (GTK_FILE_CHOOSER(picker), - suggest_name.c_str()); - } - else - { - gtk_file_chooser_set_current_name - (GTK_FILE_CHOOSER(picker), filename.c_str()); - } - - gtk_widget_show_all(GTK_WIDGET(picker)); - - gtk_main(); - - rtn = (getFileCount() == 1); - - if(rtn && filter == FFSAVE_TGAPNG) - { - std::string selected_file = mFiles.back(); - mFiles.pop_back(); - mFiles.push_back(selected_file + mCurrentExtension); - } - } - - gViewerWindow->getWindow()->afterDialog(); - - return rtn; + BOOL rtn = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + gViewerWindow->getWindow()->beforeDialog(); + + reset(); + + GtkWindow* picker = buildFilePicker(true, false, "savefile"); + + if (picker) + { + std::string suggest_name = "untitled"; + std::string suggest_ext = ""; + std::string caption = LLTrans::getString("save_file_verb") + " "; + switch (filter) + { + case FFSAVE_WAV: + caption += add_wav_filter_to_gtkchooser(picker); + suggest_ext = ".wav"; + break; + case FFSAVE_TGA: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)"); + suggest_ext = ".tga"; + break; + case FFSAVE_BMP: + caption += add_simple_mime_filter_to_gtkchooser + (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)"); + suggest_ext = ".bmp"; + break; + case FFSAVE_PNG: + caption += add_simple_mime_filter_to_gtkchooser + (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)"); + suggest_ext = ".png"; + break; + case FFSAVE_TGAPNG: + caption += add_save_texture_filter_to_gtkchooser(picker); + suggest_ext = ".png"; + break; + case FFSAVE_AVI: + caption += add_simple_mime_filter_to_gtkchooser + (picker, "video/x-msvideo", + LLTrans::getString("avi_movie_file") + " (*.avi)"); + suggest_ext = ".avi"; + break; + case FFSAVE_ANIM: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)"); + suggest_ext = ".xaf"; + break; + case FFSAVE_XML: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)"); + suggest_ext = ".xml"; + break; + case FFSAVE_RAW: + caption += add_simple_pattern_filter_to_gtkchooser + (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)"); + suggest_ext = ".raw"; + break; + case FFSAVE_J2C: + // *TODO: Should this be 'image/j2c' ? + caption += add_simple_mime_filter_to_gtkchooser + (picker, "images/jp2", + LLTrans::getString("compressed_image_files") + " (*.j2c)"); + suggest_ext = ".j2c"; + break; + case FFSAVE_SCRIPT: + caption += add_script_filter_to_gtkchooser(picker); + suggest_ext = ".lsl"; + break; + default:; + break; + } + + gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); + + if (filename.empty()) + { + suggest_name += suggest_ext; + + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), + suggest_name.c_str()); + } + else + { + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER(picker), filename.c_str()); + } + + gtk_widget_show_all(GTK_WIDGET(picker)); + + gtk_main(); + + rtn = (getFileCount() == 1); + + if(rtn && filter == FFSAVE_TGAPNG) + { + std::string selected_file = mFiles.back(); + mFiles.pop_back(); + mFiles.push_back(selected_file + mCurrentExtension); + } + } + + gViewerWindow->getWindow()->afterDialog(); + + return rtn; } BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) { - BOOL rtn = FALSE; - - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - gViewerWindow->getWindow()->beforeDialog(); - - reset(); - - GtkWindow* picker = buildFilePicker(false, false, "openfile"); - - if (picker) - { - std::string caption = LLTrans::getString("load_file_verb") + " "; - std::string filtername = ""; - switch (filter) - { - case FFLOAD_WAV: - filtername = add_wav_filter_to_gtkchooser(picker); - break; - case FFLOAD_ANIM: - filtername = add_anim_filter_to_gtkchooser(picker); - break; - case FFLOAD_XML: - filtername = add_xml_filter_to_gtkchooser(picker); - break; + BOOL rtn = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + gViewerWindow->getWindow()->beforeDialog(); + + reset(); + + GtkWindow* picker = buildFilePicker(false, false, "openfile"); + + if (picker) + { + std::string caption = LLTrans::getString("load_file_verb") + " "; + std::string filtername = ""; + switch (filter) + { + case FFLOAD_WAV: + filtername = add_wav_filter_to_gtkchooser(picker); + break; + case FFLOAD_ANIM: + filtername = add_anim_filter_to_gtkchooser(picker); + break; + case FFLOAD_XML: + filtername = add_xml_filter_to_gtkchooser(picker); + break; case FFLOAD_GLTF: filtername = dead_code_should_blow_up_here(picker); break; @@ -1522,64 +1522,64 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) filtername = add_collada_filter_to_gtkchooser(picker); break; case FFLOAD_IMAGE: - filtername = add_imageload_filter_to_gtkchooser(picker); - break; - case FFLOAD_SCRIPT: - filtername = add_script_filter_to_gtkchooser(picker); - break; - case FFLOAD_DICTIONARY: - filtername = add_dictionary_filter_to_gtkchooser(picker); - break; - default:; - break; - } - - caption += filtername; - - gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); - - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - - rtn = (getFileCount() == 1); - } - - gViewerWindow->getWindow()->afterDialog(); - - return rtn; + filtername = add_imageload_filter_to_gtkchooser(picker); + break; + case FFLOAD_SCRIPT: + filtername = add_script_filter_to_gtkchooser(picker); + break; + case FFLOAD_DICTIONARY: + filtername = add_dictionary_filter_to_gtkchooser(picker); + break; + default:; + break; + } + + caption += filtername; + + gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); + + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + + rtn = (getFileCount() == 1); + } + + gViewerWindow->getWindow()->afterDialog(); + + return rtn; } BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) { - BOOL rtn = FALSE; + BOOL rtn = FALSE; + + // if local file browsing is turned off, return without opening dialog + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } - // if local file browsing is turned off, return without opening dialog - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } + gViewerWindow->getWindow()->beforeDialog(); - gViewerWindow->getWindow()->beforeDialog(); + reset(); - reset(); - - GtkWindow* picker = buildFilePicker(false, false, "openfile"); + GtkWindow* picker = buildFilePicker(false, false, "openfile"); - if (picker) - { - gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker), - TRUE); + if (picker) + { + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker), + TRUE); - gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str()); + gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str()); - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - rtn = !mFiles.empty(); - } + gtk_widget_show_all(GTK_WIDGET(picker)); + gtk_main(); + rtn = !mFiles.empty(); + } - gViewerWindow->getWindow()->afterDialog(); + gViewerWindow->getWindow()->afterDialog(); - return rtn; + return rtn; } # else // LL_GTK @@ -1589,23 +1589,23 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) { - // if local file browsing is turned off, return without opening dialog - // (Even though this is a stub, I think we still should not return anything at all) - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - reset(); - - LL_INFOS() << "getSaveFile suggested filename is [" << filename - << "]" << LL_ENDL; - if (!filename.empty()) - { - mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename); - return TRUE; - } - return FALSE; + // if local file browsing is turned off, return without opening dialog + // (Even though this is a stub, I think we still should not return anything at all) + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + reset(); + + LL_INFOS() << "getSaveFile suggested filename is [" << filename + << "]" << LL_ENDL; + if (!filename.empty()) + { + mFiles.push_back(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + filename); + return TRUE; + } + return FALSE; } BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, @@ -1619,27 +1619,27 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) { - // if local file browsing is turned off, return without opening dialog - // (Even though this is a stub, I think we still should not return anything at all) - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - reset(); - - // HACK: Static filenames for 'open' until we implement filepicker - std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload"; - switch (filter) - { - case FFLOAD_WAV: filename += ".wav"; break; - case FFLOAD_IMAGE: filename += ".tga"; break; - case FFLOAD_ANIM: filename += ".bvh"; break; - default: break; - } - mFiles.push_back(filename); - LL_INFOS() << "getOpenFile: Will try to open file: " << filename << LL_ENDL; - return TRUE; + // if local file browsing is turned off, return without opening dialog + // (Even though this is a stub, I think we still should not return anything at all) + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + reset(); + + // HACK: Static filenames for 'open' until we implement filepicker + std::string filename = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + "upload"; + switch (filter) + { + case FFLOAD_WAV: filename += ".wav"; break; + case FFLOAD_IMAGE: filename += ".tga"; break; + case FFLOAD_ANIM: filename += ".bvh"; break; + default: break; + } + mFiles.push_back(filename); + LL_INFOS() << "getOpenFile: Will try to open file: " << filename << LL_ENDL; + return TRUE; } BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, @@ -1652,15 +1652,15 @@ BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter, BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) { - // if local file browsing is turned off, return without opening dialog - // (Even though this is a stub, I think we still should not return anything at all) - if ( check_local_file_access_enabled() == false ) - { - return FALSE; - } - - reset(); - return FALSE; + // if local file browsing is turned off, return without opening dialog + // (Even though this is a stub, I think we still should not return anything at all) + if ( check_local_file_access_enabled() == false ) + { + return FALSE; + } + + reset(); + return FALSE; } BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, @@ -1677,20 +1677,20 @@ BOOL LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) { - reset(); - return FALSE; + reset(); + return FALSE; } BOOL LLFilePicker::getOpenFile( ELoadFilter filter ) { - reset(); - return FALSE; + reset(); + return FALSE; } BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) { - reset(); - return FALSE; + reset(); + return FALSE; } #endif // LL_LINUX diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 891c0c0482..994e7458d3 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -1,25 +1,25 @@ -/** +/** * @file llfilepicker.h * @brief OS-specific file picker * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -64,119 +64,119 @@ extern "C" { class LLFilePicker { #ifdef LL_GTK - friend class LLDirPicker; - friend void chooser_responder(GtkWidget *, gint, gpointer); + friend class LLDirPicker; + friend void chooser_responder(GtkWidget *, gint, gpointer); #endif // LL_GTK public: - // calling this before main() is undefined - static LLFilePicker& instance( void ) { return sInstance; } - - enum ELoadFilter - { - FFLOAD_ALL = 1, - FFLOAD_WAV = 2, - FFLOAD_IMAGE = 3, - FFLOAD_ANIM = 4, - FFLOAD_GLTF = 5, - FFLOAD_XML = 6, - FFLOAD_SLOBJECT = 7, - FFLOAD_RAW = 8, - FFLOAD_MODEL = 9, - FFLOAD_COLLADA = 10, - FFLOAD_SCRIPT = 11, - FFLOAD_DICTIONARY = 12, + // calling this before main() is undefined + static LLFilePicker& instance( void ) { return sInstance; } + + enum ELoadFilter + { + FFLOAD_ALL = 1, + FFLOAD_WAV = 2, + FFLOAD_IMAGE = 3, + FFLOAD_ANIM = 4, + FFLOAD_GLTF = 5, + FFLOAD_XML = 6, + FFLOAD_SLOBJECT = 7, + FFLOAD_RAW = 8, + FFLOAD_MODEL = 9, + FFLOAD_COLLADA = 10, + FFLOAD_SCRIPT = 11, + FFLOAD_DICTIONARY = 12, FFLOAD_DIRECTORY = 13, // To call from lldirpicker. FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin FFLOAD_MATERIAL = 15, FFLOAD_MATERIAL_TEXTURE = 16, FFLOAD_HDRI = 17, - }; - - enum ESaveFilter - { - FFSAVE_ALL = 1, - FFSAVE_WAV = 3, - FFSAVE_TGA = 4, - FFSAVE_BMP = 5, - FFSAVE_AVI = 6, - FFSAVE_ANIM = 7, - FFSAVE_GLTF = 8, - FFSAVE_XML = 9, - FFSAVE_COLLADA = 10, - FFSAVE_RAW = 11, - FFSAVE_J2C = 12, - FFSAVE_PNG = 13, - FFSAVE_JPEG = 14, - FFSAVE_SCRIPT = 15, - FFSAVE_TGAPNG = 16 - }; - - // open the dialog. This is a modal operation - BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true); + }; + + enum ESaveFilter + { + FFSAVE_ALL = 1, + FFSAVE_WAV = 3, + FFSAVE_TGA = 4, + FFSAVE_BMP = 5, + FFSAVE_AVI = 6, + FFSAVE_ANIM = 7, + FFSAVE_GLTF = 8, + FFSAVE_XML = 9, + FFSAVE_COLLADA = 10, + FFSAVE_RAW = 11, + FFSAVE_J2C = 12, + FFSAVE_PNG = 13, + FFSAVE_JPEG = 14, + FFSAVE_SCRIPT = 15, + FFSAVE_TGAPNG = 16 + }; + + // open the dialog. This is a modal operation + BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true); BOOL getSaveFileModeless(ESaveFilter filter, const std::string& filename, void (*callback)(bool, std::string&, void*), void *userdata); - BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true ); + BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true ); // Todo: implement getOpenFileModeless and getMultipleOpenFilesModeless // for windows and use directly instead of ugly LLFilePickerThread BOOL getOpenFileModeless( ELoadFilter filter, void (*callback)(bool, std::vector &, void*), void *userdata); // MAC only. - BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true ); + BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true ); BOOL getMultipleOpenFilesModeless( ELoadFilter filter, void (*callback)(bool, std::vector &, void*), void *userdata ); // MAC only - // Get the filename(s) found. getFirstFile() sets the pointer to - // the start of the structure and allows the start of iteration. - const std::string getFirstFile(); + // Get the filename(s) found. getFirstFile() sets the pointer to + // the start of the structure and allows the start of iteration. + const std::string getFirstFile(); + + // getNextFile() increments the internal representation and + // returns the next file specified by the user. Returns NULL when + // no more files are left. Further calls to getNextFile() are + // undefined. + const std::string getNextFile(); - // getNextFile() increments the internal representation and - // returns the next file specified by the user. Returns NULL when - // no more files are left. Further calls to getNextFile() are - // undefined. - const std::string getNextFile(); + // This utility function extracts the current file name without + // doing any incrementing. + const std::string getCurFile(); - // This utility function extracts the current file name without - // doing any incrementing. - const std::string getCurFile(); + // Returns the index of the current file. + S32 getCurFileNum() const { return mCurrentFile; } - // Returns the index of the current file. - S32 getCurFileNum() const { return mCurrentFile; } + S32 getFileCount() const { return (S32)mFiles.size(); } - S32 getFileCount() const { return (S32)mFiles.size(); } + // see lldir.h : getBaseFileName and getDirName to extract base or directory names - // see lldir.h : getBaseFileName and getDirName to extract base or directory names - - // clear any lists of buffers or whatever, and make sure the file - // picker isn't locked. - void reset(); + // clear any lists of buffers or whatever, and make sure the file + // picker isn't locked. + void reset(); private: - enum - { - SINGLE_FILENAME_BUFFER_SIZE = 1024, - //FILENAME_BUFFER_SIZE = 65536 - FILENAME_BUFFER_SIZE = 65000 - }; - - // utility function to check if access to local file system via file browser - // is enabled and if not, tidy up and indicate we're not allowed to do this. - bool check_local_file_access_enabled(); - + enum + { + SINGLE_FILENAME_BUFFER_SIZE = 1024, + //FILENAME_BUFFER_SIZE = 65536 + FILENAME_BUFFER_SIZE = 65000 + }; + + // utility function to check if access to local file system via file browser + // is enabled and if not, tidy up and indicate we're not allowed to do this. + bool check_local_file_access_enabled(); + #if LL_WINDOWS - OPENFILENAMEW mOFN; // for open and save dialogs - WCHAR mFilesW[FILENAME_BUFFER_SIZE]; + OPENFILENAMEW mOFN; // for open and save dialogs + WCHAR mFilesW[FILENAME_BUFFER_SIZE]; - BOOL setupFilter(ELoadFilter filter); + BOOL setupFilter(ELoadFilter filter); #endif #if LL_DARWIN S32 mPickOptions; - std::vector mFileVector; - - bool doNavChooseDialog(ELoadFilter filter); - bool doNavChooseDialogModeless(ELoadFilter filter, + std::vector mFileVector; + + bool doNavChooseDialog(ELoadFilter filter); + bool doNavChooseDialogModeless(ELoadFilter filter, void (*callback)(bool, std::vector&, void*), void *userdata); - bool doNavSaveDialog(ESaveFilter filter, const std::string& filename); + bool doNavSaveDialog(ESaveFilter filter, const std::string& filename); std::unique_ptr> navOpenFilterProc(ELoadFilter filter); bool doNavSaveDialogModeless(ESaveFilter filter, const std::string& filename, @@ -185,31 +185,31 @@ private: #endif #if LL_GTK - static void add_to_selectedfiles(gpointer data, gpointer user_data); - static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data); - // we remember the last path that was accessed for a particular usage - std::map mContextToPathMap; - std::string mCurContextName; - // we also remember the extension of the last added file. - std::string mCurrentExtension; + static void add_to_selectedfiles(gpointer data, gpointer user_data); + static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data); + // we remember the last path that was accessed for a particular usage + std::map mContextToPathMap; + std::string mCurContextName; + // we also remember the extension of the last added file. + std::string mCurrentExtension; #endif - std::vector mFiles; - S32 mCurrentFile; - bool mLocked; + std::vector mFiles; + S32 mCurrentFile; + bool mLocked; + + static LLFilePicker sInstance; - static LLFilePicker sInstance; - protected: #if LL_GTK GtkWindow* buildFilePicker(bool is_save, bool is_folder, - std::string context = "generic"); + std::string context = "generic"); #endif public: - // don't call these directly please. - LLFilePicker(); - ~LLFilePicker(); + // don't call these directly please. + LLFilePicker(); + ~LLFilePicker(); }; #endif diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 2a5106f79e..98842eed77 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llfloaterimagepreview.cpp * @brief LLFloaterImagePreview class implementation * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -65,23 +65,23 @@ const S32 PREVIEW_BORDER_WIDTH = 2; const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; -const S32 PREVIEW_VPAD = -24 + 35; // yuk, hard coded +const S32 PREVIEW_VPAD = -24 + 35; // yuk, hard coded const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16 + 35; const S32 PREVIEW_TEXTURE_HEIGHT = 320; //----------------------------------------------------------------------------- // LLFloaterImagePreview() //----------------------------------------------------------------------------- -LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : - LLFloaterNameDesc(filename), +LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : + LLFloaterNameDesc(filename), - mAvatarPreview(NULL), - mSculptedPreview(NULL), - mLastMouseX(0), - mLastMouseY(0), - mImagep(NULL) + mAvatarPreview(NULL), + mSculptedPreview(NULL), + mLastMouseX(0), + mLastMouseY(0), + mImagep(NULL) { - loadImage(mFilenameAndPath); + loadImage(mFilenameAndPath); } //----------------------------------------------------------------------------- @@ -89,33 +89,33 @@ LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : //----------------------------------------------------------------------------- BOOL LLFloaterImagePreview::postBuild() { - if (!LLFloaterNameDesc::postBuild()) - { - return FALSE; - } - - LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); - if (iface) - { - iface->selectFirstItem(); - } - childSetCommitCallback("clothing_type_combo", onPreviewTypeCommit, this); - - mPreviewRect.set(PREVIEW_HPAD, - PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD, - getRect().getWidth() - PREVIEW_HPAD, - PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); - - getChildView("bad_image_text")->setVisible(FALSE); - - if (mRawImagep.notNull() && gAgent.getRegion() != NULL) - { - mAvatarPreview = new LLImagePreviewAvatar(256, 256); - mAvatarPreview->setPreviewTarget("mPelvis", "mUpperBodyMesh0", mRawImagep, 2.f, FALSE); - - mSculptedPreview = new LLImagePreviewSculpted(256, 256); - mSculptedPreview->setPreviewTarget(mRawImagep, 2.0f); + if (!LLFloaterNameDesc::postBuild()) + { + return FALSE; + } + + LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); + if (iface) + { + iface->selectFirstItem(); + } + childSetCommitCallback("clothing_type_combo", onPreviewTypeCommit, this); + + mPreviewRect.set(PREVIEW_HPAD, + PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD, + getRect().getWidth() - PREVIEW_HPAD, + PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); + + getChildView("bad_image_text")->setVisible(FALSE); + + if (mRawImagep.notNull() && gAgent.getRegion() != NULL) + { + mAvatarPreview = new LLImagePreviewAvatar(256, 256); + mAvatarPreview->setPreviewTarget("mPelvis", "mUpperBodyMesh0", mRawImagep, 2.f, FALSE); + + mSculptedPreview = new LLImagePreviewSculpted(256, 256); + mSculptedPreview->setPreviewTarget(mRawImagep, 2.0f); if (mRawImagep->getWidth() * mRawImagep->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF) { @@ -125,24 +125,24 @@ BOOL LLFloaterImagePreview::postBuild() check_box->setEnabled(TRUE); check_box->setControlVariable(gSavedSettings.getControl("LosslessJ2CUpload")); } - } - else - { - mAvatarPreview = NULL; - mSculptedPreview = NULL; - getChildView("bad_image_text")->setVisible(TRUE); - getChildView("clothing_type_combo")->setEnabled(FALSE); - getChildView("ok_btn")->setEnabled(FALSE); + } + else + { + mAvatarPreview = NULL; + mSculptedPreview = NULL; + getChildView("bad_image_text")->setVisible(TRUE); + getChildView("clothing_type_combo")->setEnabled(FALSE); + getChildView("ok_btn")->setEnabled(FALSE); + + if(!mImageLoadError.empty()) + { + getChild("bad_image_text")->setValue(mImageLoadError.c_str()); + } + } - if(!mImageLoadError.empty()) - { - getChild("bad_image_text")->setValue(mImageLoadError.c_str()); - } - } - - getChild("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this)); - - return TRUE; + getChild("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this)); + + return TRUE; } @@ -159,70 +159,70 @@ S32 LLFloaterImagePreview::getExpectedUploadCost() const //----------------------------------------------------------------------------- LLFloaterImagePreview::~LLFloaterImagePreview() { - clearAllPreviewTextures(); + clearAllPreviewTextures(); - mRawImagep = NULL; - mImagep = NULL ; + mRawImagep = NULL; + mImagep = NULL ; } -//static +//static //----------------------------------------------------------------------------- // onPreviewTypeCommit() //----------------------------------------------------------------------------- -void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata) -{ - LLFloaterImagePreview *fp =(LLFloaterImagePreview *)userdata; - - if (!fp->mAvatarPreview || !fp->mSculptedPreview) - { - return; - } - - S32 which_mode = 0; - - LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface("clothing_type_combo"); - if (iface) - { - which_mode = iface->getFirstSelectedIndex(); - } - - switch(which_mode) - { - case 0: - break; - case 1: - fp->mAvatarPreview->setPreviewTarget("mSkull", "mHairMesh0", fp->mRawImagep, 0.4f, FALSE); - break; - case 2: - fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, FALSE); - break; - case 3: - fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.0f, FALSE); - break; - case 4: - fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, FALSE); - break; - case 5: - fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, TRUE); - break; - case 6: - fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.2f, TRUE); - break; - case 7: - fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, TRUE); - break; - case 8: - fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mSkirtMesh0", fp->mRawImagep, 1.3f, FALSE); - break; - case 9: - fp->mSculptedPreview->setPreviewTarget(fp->mRawImagep, 2.0f); - break; - default: - break; - } - - fp->mAvatarPreview->refresh(); - fp->mSculptedPreview->refresh(); +void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata) +{ + LLFloaterImagePreview *fp =(LLFloaterImagePreview *)userdata; + + if (!fp->mAvatarPreview || !fp->mSculptedPreview) + { + return; + } + + S32 which_mode = 0; + + LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface("clothing_type_combo"); + if (iface) + { + which_mode = iface->getFirstSelectedIndex(); + } + + switch(which_mode) + { + case 0: + break; + case 1: + fp->mAvatarPreview->setPreviewTarget("mSkull", "mHairMesh0", fp->mRawImagep, 0.4f, FALSE); + break; + case 2: + fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, FALSE); + break; + case 3: + fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.0f, FALSE); + break; + case 4: + fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, FALSE); + break; + case 5: + fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, TRUE); + break; + case 6: + fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.2f, TRUE); + break; + case 7: + fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, TRUE); + break; + case 8: + fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mSkirtMesh0", fp->mRawImagep, 1.3f, FALSE); + break; + case 9: + fp->mSculptedPreview->setPreviewTarget(fp->mRawImagep, 2.0f); + break; + default: + break; + } + + fp->mAvatarPreview->refresh(); + fp->mSculptedPreview->refresh(); } @@ -231,16 +231,16 @@ void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata) //----------------------------------------------------------------------------- void LLFloaterImagePreview::clearAllPreviewTextures() { - if (mAvatarPreview) - { - mAvatarPreview->clearPreviewTexture("mHairMesh0"); - mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0"); - mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0"); - mAvatarPreview->clearPreviewTexture("mHeadMesh0"); - mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0"); - mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0"); - mAvatarPreview->clearPreviewTexture("mSkirtMesh0"); - } + if (mAvatarPreview) + { + mAvatarPreview->clearPreviewTexture("mHairMesh0"); + mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0"); + mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0"); + mAvatarPreview->clearPreviewTexture("mHeadMesh0"); + mAvatarPreview->clearPreviewTexture("mUpperBodyMesh0"); + mAvatarPreview->clearPreviewTexture("mLowerBodyMesh0"); + mAvatarPreview->clearPreviewTexture("mSkirtMesh0"); + } } //----------------------------------------------------------------------------- @@ -248,92 +248,92 @@ void LLFloaterImagePreview::clearAllPreviewTextures() //----------------------------------------------------------------------------- void LLFloaterImagePreview::draw() { - LLFloater::draw(); - LLRect r = getRect(); - - if (mRawImagep.notNull()) - { - LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); - U32 selected = 0; - if (iface) - selected = iface->getFirstSelectedIndex(); - - if (selected <= 0) - { - gl_rect_2d_checkerboard(mPreviewRect); - - if(mImagep.notNull()) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); - } - else - { - mImagep = LLViewerTextureManager::getLocalTexture(mRawImagep.get(), FALSE) ; - - gGL.getTexUnit(0)->unbind(mImagep->getTarget()) ; - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); - stop_glerror(); - - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - if (mAvatarPreview) - { - mAvatarPreview->setTexture(mImagep->getTexName()); - mSculptedPreview->setTexture(mImagep->getTexName()); - } - } - - gGL.color3f(1.f, 1.f, 1.f); - gGL.begin( LLRender::QUADS ); - { - gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); - gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); - } - gGL.end(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - stop_glerror(); - } - else - { - if ((mAvatarPreview) && (mSculptedPreview)) - { - gGL.color3f(1.f, 1.f, 1.f); - - if (selected == 9) - { - gGL.getTexUnit(0)->bind(mSculptedPreview); - } - else - { - gGL.getTexUnit(0)->bind(mAvatarPreview); - } - - gGL.begin( LLRender::QUADS ); - { - gGL.texCoord2f(0.f, 1.f); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); - gGL.texCoord2f(0.f, 0.f); - gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 0.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); - gGL.texCoord2f(1.f, 1.f); - gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); - } - gGL.end(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } - } + LLFloater::draw(); + LLRect r = getRect(); + + if (mRawImagep.notNull()) + { + LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); + U32 selected = 0; + if (iface) + selected = iface->getFirstSelectedIndex(); + + if (selected <= 0) + { + gl_rect_2d_checkerboard(mPreviewRect); + + if(mImagep.notNull()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); + } + else + { + mImagep = LLViewerTextureManager::getLocalTexture(mRawImagep.get(), FALSE) ; + + gGL.getTexUnit(0)->unbind(mImagep->getTarget()) ; + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); + stop_glerror(); + + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + if (mAvatarPreview) + { + mAvatarPreview->setTexture(mImagep->getTexName()); + mSculptedPreview->setTexture(mImagep->getTexName()); + } + } + + gGL.color3f(1.f, 1.f, 1.f); + gGL.begin( LLRender::QUADS ); + { + gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); + gGL.texCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); + } + gGL.end(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + stop_glerror(); + } + else + { + if ((mAvatarPreview) && (mSculptedPreview)) + { + gGL.color3f(1.f, 1.f, 1.f); + + if (selected == 9) + { + gGL.getTexUnit(0)->bind(mSculptedPreview); + } + else + { + gGL.getTexUnit(0)->bind(mAvatarPreview); + } + + gGL.begin( LLRender::QUADS ); + { + gGL.texCoord2f(0.f, 1.f); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(1.f, 0.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD); + } + gGL.end(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + } + } } @@ -342,56 +342,56 @@ void LLFloaterImagePreview::draw() //----------------------------------------------------------------------------- bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { - std::string exten = gDirUtilp->getExtension(src_filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); - - LLImageDimensionsInfo image_info; - if (!image_info.load(src_filename,codec)) - { - mImageLoadError = image_info.getLastError(); - return false; - } - - S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); - S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); - - if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) - { - LLStringUtil::format_map_t args; - args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_height); - - mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); - return false; - } - - // Load the image - LLPointer image = LLImageFormatted::createFromType(codec); - if (image.isNull()) - { - return false; - } - if (!image->load(src_filename)) - { - return false; - } - // Decompress or expand it in a raw image structure - LLPointer raw_image = new LLImageRaw; - if (!image->decode(raw_image, 0.0f)) - { - return false; - } - // Check the image constraints - if ((image->getComponents() != 3) && (image->getComponents() != 4)) - { - image->setLastError("Image files with less than 3 or more than 4 components are not supported."); - return false; - } - - raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); - mRawImagep = raw_image; - - return true; + std::string exten = gDirUtilp->getExtension(src_filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); + + LLImageDimensionsInfo image_info; + if (!image_info.load(src_filename,codec)) + { + mImageLoadError = image_info.getLastError(); + return false; + } + + S32 max_width = gSavedSettings.getS32("max_texture_dimension_X"); + S32 max_height = gSavedSettings.getS32("max_texture_dimension_Y"); + + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); + + mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args); + return false; + } + + // Load the image + LLPointer image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + return false; + } + if (!image->load(src_filename)) + { + return false; + } + // Decompress or expand it in a raw image structure + LLPointer raw_image = new LLImageRaw; + if (!image->decode(raw_image, 0.0f)) + { + return false; + } + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return false; + } + + raw_image->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + mRawImagep = raw_image; + + return true; } //----------------------------------------------------------------------------- @@ -399,17 +399,17 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename) //----------------------------------------------------------------------------- BOOL LLFloaterImagePreview::handleMouseDown(S32 x, S32 y, MASK mask) { - if (mPreviewRect.pointInRect(x, y)) - { - bringToFront( x, y ); - gFocusMgr.setMouseCapture(this); - gViewerWindow->hideCursor(); - mLastMouseX = x; - mLastMouseY = y; - return TRUE; - } + if (mPreviewRect.pointInRect(x, y)) + { + bringToFront( x, y ); + gFocusMgr.setMouseCapture(this); + gViewerWindow->hideCursor(); + mLastMouseX = x; + mLastMouseY = y; + return TRUE; + } - return LLFloater::handleMouseDown(x, y, mask); + return LLFloater::handleMouseDown(x, y, mask); } //----------------------------------------------------------------------------- @@ -417,9 +417,9 @@ BOOL LLFloaterImagePreview::handleMouseDown(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- BOOL LLFloaterImagePreview::handleMouseUp(S32 x, S32 y, MASK mask) { - gFocusMgr.setMouseCapture(FALSE); - gViewerWindow->showCursor(); - return LLFloater::handleMouseUp(x, y, mask); + gFocusMgr.setMouseCapture(FALSE); + gViewerWindow->showCursor(); + return LLFloater::handleMouseUp(x, y, mask); } //----------------------------------------------------------------------------- @@ -427,119 +427,119 @@ BOOL LLFloaterImagePreview::handleMouseUp(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask) { - MASK local_mask = mask & ~MASK_ALT; - - if (mAvatarPreview && hasMouseCapture()) - { - if (local_mask == MASK_PAN) - { - // pan here - LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); - if (iface && iface->getFirstSelectedIndex() <= 0) - { - mPreviewImageRect.translate((F32)(x - mLastMouseX) * -0.005f * mPreviewImageRect.getWidth(), - (F32)(y - mLastMouseY) * -0.005f * mPreviewImageRect.getHeight()); - } - else - { - mAvatarPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); - mSculptedPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); - } - } - else if (local_mask == MASK_ORBIT) - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; - - mAvatarPreview->rotate(yaw_radians, pitch_radians); - mSculptedPreview->rotate(yaw_radians, pitch_radians); - } - else - { - LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); - if (iface && iface->getFirstSelectedIndex() <= 0) - { - F32 zoom_amt = (F32)(y - mLastMouseY) * -0.002f; - mPreviewImageRect.stretch(zoom_amt); - } - else - { - F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; - F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; - - mAvatarPreview->rotate(yaw_radians, 0.f); - mAvatarPreview->zoom(zoom_amt); - mSculptedPreview->rotate(yaw_radians, 0.f); - mSculptedPreview->zoom(zoom_amt); - } - } - - LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); - if (iface && iface->getFirstSelectedIndex() <= 0) - { - if (mPreviewImageRect.getWidth() > 1.f) - { - mPreviewImageRect.stretch((1.f - mPreviewImageRect.getWidth()) * 0.5f); - } - else if (mPreviewImageRect.getWidth() < 0.1f) - { - mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getWidth()) * 0.5f); - } - - if (mPreviewImageRect.getHeight() > 1.f) - { - mPreviewImageRect.stretch((1.f - mPreviewImageRect.getHeight()) * 0.5f); - } - else if (mPreviewImageRect.getHeight() < 0.1f) - { - mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getHeight()) * 0.5f); - } - - if (mPreviewImageRect.mLeft < 0.f) - { - mPreviewImageRect.translate(-mPreviewImageRect.mLeft, 0.f); - } - else if (mPreviewImageRect.mRight > 1.f) - { - mPreviewImageRect.translate(1.f - mPreviewImageRect.mRight, 0.f); - } - - if (mPreviewImageRect.mBottom < 0.f) - { - mPreviewImageRect.translate(0.f, -mPreviewImageRect.mBottom); - } - else if (mPreviewImageRect.mTop > 1.f) - { - mPreviewImageRect.translate(0.f, 1.f - mPreviewImageRect.mTop); - } - } - else - { - mAvatarPreview->refresh(); - mSculptedPreview->refresh(); - } - - LLUI::getInstance()->setMousePositionLocal(this, mLastMouseX, mLastMouseY); - } - - if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview) - { - return LLFloater::handleHover(x, y, mask); - } - else if (local_mask == MASK_ORBIT) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); - } - else if (local_mask == MASK_PAN) - { - gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); - } - else - { - gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); - } - - return TRUE; + MASK local_mask = mask & ~MASK_ALT; + + if (mAvatarPreview && hasMouseCapture()) + { + if (local_mask == MASK_PAN) + { + // pan here + LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); + if (iface && iface->getFirstSelectedIndex() <= 0) + { + mPreviewImageRect.translate((F32)(x - mLastMouseX) * -0.005f * mPreviewImageRect.getWidth(), + (F32)(y - mLastMouseY) * -0.005f * mPreviewImageRect.getHeight()); + } + else + { + mAvatarPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); + mSculptedPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); + } + } + else if (local_mask == MASK_ORBIT) + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; + + mAvatarPreview->rotate(yaw_radians, pitch_radians); + mSculptedPreview->rotate(yaw_radians, pitch_radians); + } + else + { + LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); + if (iface && iface->getFirstSelectedIndex() <= 0) + { + F32 zoom_amt = (F32)(y - mLastMouseY) * -0.002f; + mPreviewImageRect.stretch(zoom_amt); + } + else + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; + + mAvatarPreview->rotate(yaw_radians, 0.f); + mAvatarPreview->zoom(zoom_amt); + mSculptedPreview->rotate(yaw_radians, 0.f); + mSculptedPreview->zoom(zoom_amt); + } + } + + LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); + if (iface && iface->getFirstSelectedIndex() <= 0) + { + if (mPreviewImageRect.getWidth() > 1.f) + { + mPreviewImageRect.stretch((1.f - mPreviewImageRect.getWidth()) * 0.5f); + } + else if (mPreviewImageRect.getWidth() < 0.1f) + { + mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getWidth()) * 0.5f); + } + + if (mPreviewImageRect.getHeight() > 1.f) + { + mPreviewImageRect.stretch((1.f - mPreviewImageRect.getHeight()) * 0.5f); + } + else if (mPreviewImageRect.getHeight() < 0.1f) + { + mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getHeight()) * 0.5f); + } + + if (mPreviewImageRect.mLeft < 0.f) + { + mPreviewImageRect.translate(-mPreviewImageRect.mLeft, 0.f); + } + else if (mPreviewImageRect.mRight > 1.f) + { + mPreviewImageRect.translate(1.f - mPreviewImageRect.mRight, 0.f); + } + + if (mPreviewImageRect.mBottom < 0.f) + { + mPreviewImageRect.translate(0.f, -mPreviewImageRect.mBottom); + } + else if (mPreviewImageRect.mTop > 1.f) + { + mPreviewImageRect.translate(0.f, 1.f - mPreviewImageRect.mTop); + } + } + else + { + mAvatarPreview->refresh(); + mSculptedPreview->refresh(); + } + + LLUI::getInstance()->setMousePositionLocal(this, mLastMouseX, mLastMouseY); + } + + if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview || !mSculptedPreview) + { + return LLFloater::handleHover(x, y, mask); + } + else if (local_mask == MASK_ORBIT) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); + } + else if (local_mask == MASK_PAN) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); + } + + return TRUE; } //----------------------------------------------------------------------------- @@ -547,16 +547,16 @@ BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask) //----------------------------------------------------------------------------- BOOL LLFloaterImagePreview::handleScrollWheel(S32 x, S32 y, S32 clicks) { - if (mPreviewRect.pointInRect(x, y) && mAvatarPreview) - { - mAvatarPreview->zoom((F32)clicks * -0.2f); - mAvatarPreview->refresh(); + if (mPreviewRect.pointInRect(x, y) && mAvatarPreview) + { + mAvatarPreview->zoom((F32)clicks * -0.2f); + mAvatarPreview->refresh(); - mSculptedPreview->zoom((F32)clicks * -0.2f); - mSculptedPreview->refresh(); - } + mSculptedPreview->zoom((F32)clicks * -0.2f); + mSculptedPreview->refresh(); + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -565,7 +565,7 @@ BOOL LLFloaterImagePreview::handleScrollWheel(S32 x, S32 y, S32 clicks) // static void LLFloaterImagePreview::onMouseCaptureLostImagePreview(LLMouseHandler* handler) { - gViewerWindow->showCursor(); + gViewerWindow->showCursor(); } @@ -574,63 +574,63 @@ void LLFloaterImagePreview::onMouseCaptureLostImagePreview(LLMouseHandler* handl //----------------------------------------------------------------------------- LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) { - mNeedsUpdate = TRUE; - mTargetJoint = NULL; - mTargetMesh = NULL; - mCameraDistance = 0.f; - mCameraYaw = 0.f; - mCameraPitch = 0.f; - mCameraZoom = 1.f; + mNeedsUpdate = TRUE; + mTargetJoint = NULL; + mTargetMesh = NULL; + mCameraDistance = 0.f; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; - mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR); - mDummyAvatar->mSpecialRenderMode = 2; + mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), LLViewerObject::CO_FLAG_UI_AVATAR); + mDummyAvatar->mSpecialRenderMode = 2; - mTextureName = 0; + mTextureName = 0; } LLImagePreviewAvatar::~LLImagePreviewAvatar() { - mDummyAvatar->markDead(); + mDummyAvatar->markDead(); } //virtual S8 LLImagePreviewAvatar::getType() const { - return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_AVATAR ; -} - -void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) -{ - mTargetJoint = mDummyAvatar->mRoot->findJoint(joint_name); - // clear out existing test mesh - if (mTargetMesh) - { - mTargetMesh->setTestTexture(0); - } - - if (male) - { - mDummyAvatar->setVisualParamWeight( "male", 1.f ); - mDummyAvatar->updateVisualParams(); - mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); - } - else - { - mDummyAvatar->setVisualParamWeight( "male", 0.f ); - mDummyAvatar->updateVisualParams(); - mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); - } - mDummyAvatar->mRoot->setVisible(FALSE, TRUE); - - mTargetMesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); - mTargetMesh->setTestTexture(mTextureName); - mTargetMesh->setVisible(TRUE, FALSE); - mCameraDistance = distance; - mCameraZoom = 1.f; - mCameraPitch = 0.f; - mCameraYaw = 0.f; - mCameraOffset.clearVec(); + return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_AVATAR ; +} + +void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) +{ + mTargetJoint = mDummyAvatar->mRoot->findJoint(joint_name); + // clear out existing test mesh + if (mTargetMesh) + { + mTargetMesh->setTestTexture(0); + } + + if (male) + { + mDummyAvatar->setVisualParamWeight( "male", 1.f ); + mDummyAvatar->updateVisualParams(); + mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); + } + else + { + mDummyAvatar->setVisualParamWeight( "male", 0.f ); + mDummyAvatar->updateVisualParams(); + mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); + } + mDummyAvatar->mRoot->setVisible(FALSE, TRUE); + + mTargetMesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); + mTargetMesh->setTestTexture(mTextureName); + mTargetMesh->setVisible(TRUE, FALSE); + mCameraDistance = distance; + mCameraZoom = 1.f; + mCameraPitch = 0.f; + mCameraYaw = 0.f; + mCameraOffset.clearVec(); } //----------------------------------------------------------------------------- @@ -638,15 +638,15 @@ void LLImagePreviewAvatar::setPreviewTarget(const std::string& joint_name, const //----------------------------------------------------------------------------- void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name) { - if (mDummyAvatar) - { - LLViewerJointMesh *mesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); - // clear out existing test mesh - if (mesh) - { - mesh->setTestTexture(0); - } - } + if (mDummyAvatar) + { + LLViewerJointMesh *mesh = dynamic_cast(mDummyAvatar->mRoot->findJoint(mesh_name)); + // clear out existing test mesh + if (mesh) + { + mesh->setTestTexture(0); + } + } } //----------------------------------------------------------------------------- @@ -654,82 +654,82 @@ void LLImagePreviewAvatar::clearPreviewTexture(const std::string& mesh_name) //----------------------------------------------------------------------------- BOOL LLImagePreviewAvatar::render() { - mNeedsUpdate = FALSE; - LLVOAvatar* avatarp = mDummyAvatar; + mNeedsUpdate = FALSE; + LLVOAvatar* avatarp = mDummyAvatar; + + gGL.pushUIMatrix(); + gGL.loadUIIdentity(); - gGL.pushUIMatrix(); - gGL.loadUIIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); - - LLGLSUIDefault def; - gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); + LLGLSUIDefault def; + gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); - gUIProgram.bind(); + gUIProgram.bind(); - gl_rect_2d_simple( mFullWidth, mFullHeight ); + gl_rect_2d_simple( mFullWidth, mFullHeight ); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); - gGL.flush(); - LLVector3 target_pos = mTargetJoint->getWorldPosition(); + gGL.flush(); + LLVector3 target_pos = mTargetJoint->getWorldPosition(); - LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * - LLQuaternion(mCameraYaw, LLVector3::z_axis); + LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * + LLQuaternion(mCameraYaw, LLVector3::z_axis); - LLQuaternion av_rot = avatarp->mPelvisp->getWorldRotation() * camera_rot; - LLViewerCamera::getInstance()->setOriginAndLookAt( - target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera - LLVector3::z_axis, // up - target_pos + (mCameraOffset * av_rot) ); // point of interest + LLQuaternion av_rot = avatarp->mPelvisp->getWorldRotation() * camera_rot; + LLViewerCamera::getInstance()->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos + (mCameraOffset * av_rot) ); // point of interest - stop_glerror(); + stop_glerror(); - LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / mFullHeight); - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); - LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); + LLViewerCamera::getInstance()->setAspect((F32)mFullWidth / mFullHeight); + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - LLVertexBuffer::unbind(); - avatarp->updateLOD(); - - if (avatarp->mDrawable.notNull()) - { - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - // make sure alpha=0 shows avatar material color - LLGLDisable no_blend(GL_BLEND); + LLVertexBuffer::unbind(); + avatarp->updateLOD(); - LLFace* face = avatarp->mDrawable->getFace(0); - if (face) - { - LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); - gPipeline.enableLightsPreview(); - avatarPoolp->renderAvatars(avatarp); // renders only one avatar - } - } + if (avatarp->mDrawable.notNull()) + { + LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); + // make sure alpha=0 shows avatar material color + LLGLDisable no_blend(GL_BLEND); - gGL.popUIMatrix(); - gGL.color4f(1,1,1,1); - return TRUE; + LLFace* face = avatarp->mDrawable->getFace(0); + if (face) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)face->getPool(); + gPipeline.enableLightsPreview(); + avatarPoolp->renderAvatars(avatarp); // renders only one avatar + } + } + + gGL.popUIMatrix(); + gGL.color4f(1,1,1,1); + return TRUE; } //----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- void LLImagePreviewAvatar::refresh() -{ - mNeedsUpdate = TRUE; +{ + mNeedsUpdate = TRUE; } //----------------------------------------------------------------------------- @@ -737,9 +737,9 @@ void LLImagePreviewAvatar::refresh() //----------------------------------------------------------------------------- void LLImagePreviewAvatar::rotate(F32 yaw_radians, F32 pitch_radians) { - mCameraYaw = mCameraYaw + yaw_radians; + mCameraYaw = mCameraYaw + yaw_radians; - mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); + mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); } //----------------------------------------------------------------------------- @@ -747,13 +747,13 @@ void LLImagePreviewAvatar::rotate(F32 yaw_radians, F32 pitch_radians) //----------------------------------------------------------------------------- void LLImagePreviewAvatar::zoom(F32 zoom_amt) { - mCameraZoom = llclamp(mCameraZoom + zoom_amt, 1.f, 10.f); + mCameraZoom = llclamp(mCameraZoom + zoom_amt, 1.f, 10.f); } void LLImagePreviewAvatar::pan(F32 right, F32 up) { - mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); - mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); } @@ -763,19 +763,19 @@ void LLImagePreviewAvatar::pan(F32 right, F32 up) LLImagePreviewSculpted::LLImagePreviewSculpted(S32 width, S32 height) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) { - mNeedsUpdate = TRUE; - mCameraDistance = 0.f; - mCameraYaw = 0.f; - mCameraPitch = 0.f; - mCameraZoom = 1.f; - mTextureName = 0; + mNeedsUpdate = TRUE; + mCameraDistance = 0.f; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; + mTextureName = 0; + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE); + volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_SPHERE); - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE); - volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_SPHERE); - - F32 const HIGHEST_LOD = 4.0f; - mVolume = new LLVolume(volume_params, HIGHEST_LOD); + F32 const HIGHEST_LOD = 4.0f; + mVolume = new LLVolume(volume_params, HIGHEST_LOD); } @@ -786,67 +786,67 @@ LLImagePreviewSculpted::~LLImagePreviewSculpted() //virtual S8 LLImagePreviewSculpted::getType() const { - return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_SCULPTED ; + return LLViewerDynamicTexture::LL_IMAGE_PREVIEW_SCULPTED ; } void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) -{ - mCameraDistance = distance; - mCameraZoom = 1.f; - mCameraPitch = 0.f; - mCameraYaw = 0.f; - mCameraOffset.clearVec(); - - if (imagep) - { - mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false); - } - - const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mNumIndices; - U32 num_vertices = vf.mNumVertices; - - mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); - if (!mVertexBuffer->allocateBuffer(num_vertices, num_indices)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer for image preview to" - << num_vertices << " vertices and " - << num_indices << " indices" << LL_ENDL; - // We are likely to crash on getTexCoord0Strider() - } - - LLStrider vertex_strider; - LLStrider normal_strider; - LLStrider tc_strider; - LLStrider index_strider; - - mVertexBuffer->getVertexStrider(vertex_strider); - mVertexBuffer->getNormalStrider(normal_strider); - mVertexBuffer->getTexCoord0Strider(tc_strider); - mVertexBuffer->getIndexStrider(index_strider); - - // build vertices and normals - LLStrider pos; - pos = (LLVector3*) vf.mPositions; pos.setStride(16); - LLStrider norm; - norm = (LLVector3*) vf.mNormals; norm.setStride(16); - LLStrider tc; - tc = (LLVector2*) vf.mTexCoords; tc.setStride(8); - - for (U32 i = 0; i < num_vertices; i++) - { - *(vertex_strider++) = *pos++; - LLVector3 normal = *norm++; - normal.normalize(); - *(normal_strider++) = normal; - *(tc_strider++) = *tc++; - } - - // build indices - for (U16 i = 0; i < num_indices; i++) - { - *(index_strider++) = vf.mIndices[i]; - } +{ + mCameraDistance = distance; + mCameraZoom = 1.f; + mCameraPitch = 0.f; + mCameraYaw = 0.f; + mCameraOffset.clearVec(); + + if (imagep) + { + mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false); + } + + const LLVolumeFace &vf = mVolume->getVolumeFace(0); + U32 num_indices = vf.mNumIndices; + U32 num_vertices = vf.mNumVertices; + + mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); + if (!mVertexBuffer->allocateBuffer(num_vertices, num_indices)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer for image preview to" + << num_vertices << " vertices and " + << num_indices << " indices" << LL_ENDL; + // We are likely to crash on getTexCoord0Strider() + } + + LLStrider vertex_strider; + LLStrider normal_strider; + LLStrider tc_strider; + LLStrider index_strider; + + mVertexBuffer->getVertexStrider(vertex_strider); + mVertexBuffer->getNormalStrider(normal_strider); + mVertexBuffer->getTexCoord0Strider(tc_strider); + mVertexBuffer->getIndexStrider(index_strider); + + // build vertices and normals + LLStrider pos; + pos = (LLVector3*) vf.mPositions; pos.setStride(16); + LLStrider norm; + norm = (LLVector3*) vf.mNormals; norm.setStride(16); + LLStrider tc; + tc = (LLVector2*) vf.mTexCoords; tc.setStride(8); + + for (U32 i = 0; i < num_vertices; i++) + { + *(vertex_strider++) = *pos++; + LLVector3 normal = *norm++; + normal.normalize(); + *(normal_strider++) = normal; + *(tc_strider++) = *tc++; + } + + // build indices + for (U16 i = 0; i < num_indices; i++) + { + *(index_strider++) = vf.mIndices[i]; + } mVertexBuffer->unmapBuffer(); } @@ -857,82 +857,82 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) //----------------------------------------------------------------------------- BOOL LLImagePreviewSculpted::render() { - mNeedsUpdate = FALSE; - LLGLSUIDefault def; - LLGLDisable no_blend(GL_BLEND); - LLGLEnable cull(GL_CULL_FACE); - LLGLDepthTest depth(GL_TRUE); + mNeedsUpdate = FALSE; + LLGLSUIDefault def; + LLGLDisable no_blend(GL_BLEND); + LLGLEnable cull(GL_CULL_FACE); + LLGLDepthTest depth(GL_TRUE); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, mFullWidth, 0.0f, mFullHeight, -1.0f, 1.0f); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); - - gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); - gUIProgram.bind(); + gGL.color4f(0.15f, 0.2f, 0.3f, 1.f); - gl_rect_2d_simple( mFullWidth, mFullHeight ); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); + gUIProgram.bind(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gl_rect_2d_simple( mFullWidth, mFullHeight ); - glClear(GL_DEPTH_BUFFER_BIT); - - LLVector3 target_pos(0, 0, 0); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); - LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * - LLQuaternion(mCameraYaw, LLVector3::z_axis); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); - LLQuaternion av_rot = camera_rot; - LLViewerCamera::getInstance()->setOriginAndLookAt( - target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera - LLVector3::z_axis, // up - target_pos + (mCameraOffset * av_rot) ); // point of interest + glClear(GL_DEPTH_BUFFER_BIT); - stop_glerror(); + LLVector3 target_pos(0, 0, 0); - LLViewerCamera::getInstance()->setAspect((F32) mFullWidth / mFullHeight); - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); - LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); + LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * + LLQuaternion(mCameraYaw, LLVector3::z_axis); - const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mNumIndices; - - gPipeline.enableLightsAvatar(); + LLQuaternion av_rot = camera_rot; + LLViewerCamera::getInstance()->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos + (mCameraOffset * av_rot) ); // point of interest - gObjectPreviewProgram.bind(); - gPipeline.enableLightsPreview(); + stop_glerror(); - gGL.pushMatrix(); - const F32 SCALE = 1.25f; - gGL.scalef(SCALE, SCALE, SCALE); - const F32 BRIGHTNESS = 0.9f; - gGL.diffuseColor3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + LLViewerCamera::getInstance()->setAspect((F32) mFullWidth / mFullHeight); + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom); + LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); - mVertexBuffer->setBuffer(); - mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); + const LLVolumeFace &vf = mVolume->getVolumeFace(0); + U32 num_indices = vf.mNumIndices; - gGL.popMatrix(); + gPipeline.enableLightsAvatar(); - gObjectPreviewProgram.unbind(); + gObjectPreviewProgram.bind(); + gPipeline.enableLightsPreview(); - return TRUE; + gGL.pushMatrix(); + const F32 SCALE = 1.25f; + gGL.scalef(SCALE, SCALE, SCALE); + const F32 BRIGHTNESS = 0.9f; + gGL.diffuseColor3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + + mVertexBuffer->setBuffer(); + mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); + + gGL.popMatrix(); + + gObjectPreviewProgram.unbind(); + + return TRUE; } //----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- void LLImagePreviewSculpted::refresh() -{ - mNeedsUpdate = TRUE; +{ + mNeedsUpdate = TRUE; } //----------------------------------------------------------------------------- @@ -940,9 +940,9 @@ void LLImagePreviewSculpted::refresh() //----------------------------------------------------------------------------- void LLImagePreviewSculpted::rotate(F32 yaw_radians, F32 pitch_radians) { - mCameraYaw = mCameraYaw + yaw_radians; + mCameraYaw = mCameraYaw + yaw_radians; - mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); + mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); } //----------------------------------------------------------------------------- @@ -950,11 +950,11 @@ void LLImagePreviewSculpted::rotate(F32 yaw_radians, F32 pitch_radians) //----------------------------------------------------------------------------- void LLImagePreviewSculpted::zoom(F32 zoom_amt) { - mCameraZoom = llclamp(mCameraZoom + zoom_amt, 1.f, 10.f); + mCameraZoom = llclamp(mCameraZoom + zoom_amt, 1.f, 10.f); } void LLImagePreviewSculpted::pan(F32 right, F32 up) { - mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); - mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); } diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h index 426dd926ae..6cd5bb4ca7 100644 --- a/indra/newview/llfloaterimagepreview.h +++ b/indra/newview/llfloaterimagepreview.h @@ -1,25 +1,25 @@ -/** +/** * @file llfloaterimagepreview.h * @brief LLFloaterImagePreview class definition * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -43,104 +43,104 @@ class LLVolume; class LLImagePreviewSculpted : public LLViewerDynamicTexture { protected: - virtual ~LLImagePreviewSculpted(); + virtual ~LLImagePreviewSculpted(); public: - LLImagePreviewSculpted(S32 width, S32 height); + LLImagePreviewSculpted(S32 width, S32 height); - S8 getType() const override; + S8 getType() const override; - void setPreviewTarget(LLImageRaw *imagep, F32 distance); - void setTexture(U32 name) { mTextureName = name; } + void setPreviewTarget(LLImageRaw *imagep, F32 distance); + void setTexture(U32 name) { mTextureName = name; } - BOOL render() override; - void refresh(); - void rotate(F32 yaw_radians, F32 pitch_radians); - void zoom(F32 zoom_amt); - void pan(F32 right, F32 up); - virtual BOOL needsRender() override { return mNeedsUpdate; } + BOOL render() override; + void refresh(); + void rotate(F32 yaw_radians, F32 pitch_radians); + void zoom(F32 zoom_amt); + void pan(F32 right, F32 up); + virtual BOOL needsRender() override { return mNeedsUpdate; } protected: - BOOL mNeedsUpdate; - U32 mTextureName; - F32 mCameraDistance; - F32 mCameraYaw; - F32 mCameraPitch; - F32 mCameraZoom; - LLVector3 mCameraOffset; - LLPointer mVolume; - LLPointer mVertexBuffer; + BOOL mNeedsUpdate; + U32 mTextureName; + F32 mCameraDistance; + F32 mCameraYaw; + F32 mCameraPitch; + F32 mCameraZoom; + LLVector3 mCameraOffset; + LLPointer mVolume; + LLPointer mVertexBuffer; }; class LLImagePreviewAvatar : public LLViewerDynamicTexture { protected: - virtual ~LLImagePreviewAvatar(); + virtual ~LLImagePreviewAvatar(); public: - LLImagePreviewAvatar(S32 width, S32 height); + LLImagePreviewAvatar(S32 width, S32 height); - S8 getType() const override; + S8 getType() const override; - void setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male); - void setTexture(U32 name) { mTextureName = name; } - void clearPreviewTexture(const std::string& mesh_name); + void setPreviewTarget(const std::string& joint_name, const std::string& mesh_name, LLImageRaw* imagep, F32 distance, BOOL male); + void setTexture(U32 name) { mTextureName = name; } + void clearPreviewTexture(const std::string& mesh_name); - BOOL render() override; - void refresh(); - void rotate(F32 yaw_radians, F32 pitch_radians); - void zoom(F32 zoom_amt); - void pan(F32 right, F32 up); - virtual BOOL needsRender() override { return mNeedsUpdate; } + BOOL render() override; + void refresh(); + void rotate(F32 yaw_radians, F32 pitch_radians); + void zoom(F32 zoom_amt); + void pan(F32 right, F32 up); + virtual BOOL needsRender() override { return mNeedsUpdate; } protected: - BOOL mNeedsUpdate; - LLJoint* mTargetJoint; - LLViewerJointMesh* mTargetMesh; - F32 mCameraDistance; - F32 mCameraYaw; - F32 mCameraPitch; - F32 mCameraZoom; - LLVector3 mCameraOffset; - LLPointer mDummyAvatar; - U32 mTextureName; + BOOL mNeedsUpdate; + LLJoint* mTargetJoint; + LLViewerJointMesh* mTargetMesh; + F32 mCameraDistance; + F32 mCameraYaw; + F32 mCameraPitch; + F32 mCameraZoom; + LLVector3 mCameraOffset; + LLPointer mDummyAvatar; + U32 mTextureName; }; class LLFloaterImagePreview : public LLFloaterNameDesc { public: - LLFloaterImagePreview(const std::string& filename); - virtual ~LLFloaterImagePreview(); + LLFloaterImagePreview(const std::string& filename); + virtual ~LLFloaterImagePreview(); - BOOL postBuild() override; + BOOL postBuild() override; S32 getExpectedUploadCost() const override; - - BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; - BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; - BOOL handleHover(S32 x, S32 y, MASK mask) override; - BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; - static void onMouseCaptureLostImagePreview(LLMouseHandler*); + BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleHover(S32 x, S32 y, MASK mask) override; + BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override; + + static void onMouseCaptureLostImagePreview(LLMouseHandler*); - void clearAllPreviewTextures(); + void clearAllPreviewTextures(); protected: - static void onPreviewTypeCommit(LLUICtrl*,void*); - void draw() override; - bool loadImage(const std::string& filename); - - LLPointer mRawImagep; - LLPointer mAvatarPreview; - LLPointer mSculptedPreview; - S32 mLastMouseX; - S32 mLastMouseY; - LLRect mPreviewRect; - LLRectf mPreviewImageRect; - LLPointer mImagep ; - - std::string mImageLoadError; + static void onPreviewTypeCommit(LLUICtrl*,void*); + void draw() override; + bool loadImage(const std::string& filename); + + LLPointer mRawImagep; + LLPointer mAvatarPreview; + LLPointer mSculptedPreview; + S32 mLastMouseX; + S32 mLastMouseY; + LLRect mPreviewRect; + LLRectf mPreviewImageRect; + LLPointer mImagep ; + + std::string mImageLoadError; }; #endif // LL_LLFLOATERIMAGEPREVIEW_H diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h index cf3b512fab..4b3a9b536d 100644 --- a/indra/newview/llfloaternamedesc.h +++ b/indra/newview/llfloaternamedesc.h @@ -1,25 +1,25 @@ -/** +/** * @file llfloaternamedesc.h * @brief LLFloaterNameDesc class definition * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -39,46 +39,46 @@ class LLRadioGroup; class LLFloaterNameDesc : public LLFloater { public: - LLFloaterNameDesc(const LLSD& filename); - virtual ~LLFloaterNameDesc(); - virtual BOOL postBuild(); - - void onBtnOK(); - void onBtnCancel(); - void doCommit(); + LLFloaterNameDesc(const LLSD& filename); + virtual ~LLFloaterNameDesc(); + virtual BOOL postBuild(); + + void onBtnOK(); + void onBtnCancel(); + void doCommit(); + + virtual S32 getExpectedUploadCost() const; - virtual S32 getExpectedUploadCost() const; - protected: - virtual void onCommit(); + virtual void onCommit(); protected: - BOOL mIsAudio; - bool mIsText; + BOOL mIsAudio; + bool mIsText; - std::string mFilenameAndPath; - std::string mFilename; + std::string mFilenameAndPath; + std::string mFilename; }; class LLFloaterSoundPreview : public LLFloaterNameDesc { public: - LLFloaterSoundPreview(const LLSD& filename ); - virtual BOOL postBuild(); + LLFloaterSoundPreview(const LLSD& filename ); + virtual BOOL postBuild(); }; class LLFloaterAnimPreview : public LLFloaterNameDesc { public: - LLFloaterAnimPreview(const LLSD& filename ); - virtual BOOL postBuild(); + LLFloaterAnimPreview(const LLSD& filename ); + virtual BOOL postBuild(); }; class LLFloaterScriptPreview : public LLFloaterNameDesc { public: - LLFloaterScriptPreview(const LLSD& filename ); - virtual BOOL postBuild(); + LLFloaterScriptPreview(const LLSD& filename ); + virtual BOOL postBuild(); }; #endif // LL_LLFLOATERNAMEDESC_H diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 9ce7a07ee4..8d2efc79db 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfloaterregioninfo.cpp * @author Aaron Brashears * @brief Implementation of the region info and controls floater and panels. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -50,13 +50,13 @@ #include "llavataractions.h" #include "llavatarname.h" #include "llfloateravatarpicker.h" -#include "llbutton.h" +#include "llbutton.h" #include "llcheckboxctrl.h" #include "llclipboard.h" #include "llcombobox.h" #include "llestateinfomodel.h" #include "llfilepicker.h" -#include "llfloatergodtools.h" // for send_sim_wide_deletes() +#include "llfloatergodtools.h" // for send_sim_wide_deletes() #include "llfloatertopobjects.h" // added to fix SL-32336 #include "llfloatergroups.h" #include "llfloaterreg.h" @@ -113,70 +113,70 @@ const U32 MAX_LISTED_NAMES = 100; class LLDispatchEstateUpdateInfo : public LLDispatchHandler { public: - LLDispatchEstateUpdateInfo() {} - virtual ~LLDispatchEstateUpdateInfo() {} - virtual bool operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings); + LLDispatchEstateUpdateInfo() {} + virtual ~LLDispatchEstateUpdateInfo() {} + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings); }; class LLDispatchSetEstateAccess : public LLDispatchHandler { public: - LLDispatchSetEstateAccess() {} - virtual ~LLDispatchSetEstateAccess() {} - virtual bool operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings); + LLDispatchSetEstateAccess() {} + virtual ~LLDispatchSetEstateAccess() {} + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings); }; class LLDispatchSetEstateExperience : public LLDispatchHandler { public: - virtual bool operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings); + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings); - static LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); + static LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); }; /* void unpack_request_params( - LLMessageSystem* msg, - LLDispatcher::sparam_t& strings, - LLDispatcher::iparam_t& integers) -{ - char str_buf[MAX_STRING]; - S32 str_count = msg->getNumberOfBlocksFast(_PREHASH_StringData); - S32 i; - for (i = 0; i < str_count; ++i) - { - // we treat the SParam as binary data (since it might be an - // LLUUID in compressed form which may have embedded \0's,) - str_buf[0] = '\0'; - S32 data_size = msg->getSizeFast(_PREHASH_StringData, i, _PREHASH_SParam); - if (data_size >= 0) - { - msg->getBinaryDataFast(_PREHASH_StringData, _PREHASH_SParam, - str_buf, data_size, i, MAX_STRING - 1); - strings.push_back(std::string(str_buf, data_size)); - } - } - - U32 int_buf; - S32 int_count = msg->getNumberOfBlocksFast(_PREHASH_IntegerData); - for (i = 0; i < int_count; ++i) - { - msg->getU32("IntegerData", "IParam", int_buf, i); - integers.push_back(int_buf); - } + LLMessageSystem* msg, + LLDispatcher::sparam_t& strings, + LLDispatcher::iparam_t& integers) +{ + char str_buf[MAX_STRING]; + S32 str_count = msg->getNumberOfBlocksFast(_PREHASH_StringData); + S32 i; + for (i = 0; i < str_count; ++i) + { + // we treat the SParam as binary data (since it might be an + // LLUUID in compressed form which may have embedded \0's,) + str_buf[0] = '\0'; + S32 data_size = msg->getSizeFast(_PREHASH_StringData, i, _PREHASH_SParam); + if (data_size >= 0) + { + msg->getBinaryDataFast(_PREHASH_StringData, _PREHASH_SParam, + str_buf, data_size, i, MAX_STRING - 1); + strings.push_back(std::string(str_buf, data_size)); + } + } + + U32 int_buf; + S32 int_count = msg->getNumberOfBlocksFast(_PREHASH_IntegerData); + for (i = 0; i < int_count; ++i) + { + msg->getU32("IntegerData", "IParam", int_buf, i); + integers.push_back(int_buf); + } } */ @@ -228,75 +228,75 @@ LLUUID LLFloaterRegionInfo::sRequestInvoice; LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed) - : LLFloater(seed), + : LLFloater(seed), mEnvironmentPanel(NULL), mRegionChangedCallback() {} BOOL LLFloaterRegionInfo::postBuild() { - mTab = getChild("region_panels"); - mTab->setCommitCallback(boost::bind(&LLFloaterRegionInfo::onTabSelected, this, _2)); - - // contruct the panels - LLPanelRegionInfo* panel; - panel = new LLPanelEstateInfo; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_estate.xml"); - mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true)); - - panel = new LLPanelEstateAccess; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_access.xml"); - mTab->addTabPanel(panel); - - panel = new LLPanelEstateCovenant; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_covenant.xml"); - mTab->addTabPanel(panel); - - panel = new LLPanelRegionGeneralInfo; - mInfoPanels.push_back(panel); - panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel)); - panel->buildFromFile("panel_region_general.xml"); - mTab->addTabPanel(panel); - - panel = new LLPanelRegionTerrainInfo; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_terrain.xml"); - mTab->addTabPanel(panel); + mTab = getChild("region_panels"); + mTab->setCommitCallback(boost::bind(&LLFloaterRegionInfo::onTabSelected, this, _2)); + + // contruct the panels + LLPanelRegionInfo* panel; + panel = new LLPanelEstateInfo; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_estate.xml"); + mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true)); + + panel = new LLPanelEstateAccess; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_access.xml"); + mTab->addTabPanel(panel); + + panel = new LLPanelEstateCovenant; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_covenant.xml"); + mTab->addTabPanel(panel); + + panel = new LLPanelRegionGeneralInfo; + mInfoPanels.push_back(panel); + panel->getCommitCallbackRegistrar().add("RegionInfo.ManageTelehub", boost::bind(&LLPanelRegionInfo::onClickManageTelehub, panel)); + panel->buildFromFile("panel_region_general.xml"); + mTab->addTabPanel(panel); + + panel = new LLPanelRegionTerrainInfo; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_terrain.xml"); + mTab->addTabPanel(panel); mEnvironmentPanel = new LLPanelRegionEnvironment; mEnvironmentPanel->buildFromFile("panel_region_environment.xml"); // mEnvironmentPanel->configureForRegion(); mTab->addTabPanel(mEnvironmentPanel); - panel = new LLPanelRegionDebugInfo; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_debug.xml"); - mTab->addTabPanel(panel); + panel = new LLPanelRegionDebugInfo; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_debug.xml"); + mTab->addTabPanel(panel); + + if(gDisconnected) + { + return TRUE; + } - if(gDisconnected) - { - return TRUE; - } + if(!gAgent.getRegionCapability("RegionExperiences").empty()) + { + panel = new LLPanelRegionExperiences; + mInfoPanels.push_back(panel); + panel->buildFromFile("panel_region_experiences.xml"); + mTab->addTabPanel(panel); + } - if(!gAgent.getRegionCapability("RegionExperiences").empty()) - { - panel = new LLPanelRegionExperiences; - mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_experiences.xml"); - mTab->addTabPanel(panel); - } - - gMessageSystem->setHandlerFunc( - "EstateOwnerMessage", - &processEstateOwnerRequest); + gMessageSystem->setHandlerFunc( + "EstateOwnerMessage", + &processEstateOwnerRequest); - // Request region info when agent region changes. - mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::onRegionChanged, this)); + // Request region info when agent region changes. + mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::onRegionChanged, this)); - return TRUE; + return TRUE; } LLFloaterRegionInfo::~LLFloaterRegionInfo() @@ -309,26 +309,26 @@ LLFloaterRegionInfo::~LLFloaterRegionInfo() void LLFloaterRegionInfo::onOpen(const LLSD& key) { - if(gDisconnected) - { - disableTabCtrls(); - return; - } - refreshFromRegion(gAgent.getRegion()); - requestRegionInfo(); + if(gDisconnected) + { + disableTabCtrls(); + return; + } + refreshFromRegion(gAgent.getRegion()); + requestRegionInfo(); - if (!mGodLevelChangeSlot.connected()) - { - mGodLevelChangeSlot = gAgent.registerGodLevelChanageListener(boost::bind(&LLFloaterRegionInfo::onGodLevelChange, this, _1)); - } + if (!mGodLevelChangeSlot.connected()) + { + mGodLevelChangeSlot = gAgent.registerGodLevelChanageListener(boost::bind(&LLFloaterRegionInfo::onGodLevelChange, this, _1)); + } } void LLFloaterRegionInfo::onClose(bool app_quitting) { - if (mGodLevelChangeSlot.connected()) - { - mGodLevelChangeSlot.disconnect(); - } + if (mGodLevelChangeSlot.connected()) + { + mGodLevelChangeSlot.disconnect(); + } } void LLFloaterRegionInfo::onRegionChanged() @@ -341,266 +341,266 @@ void LLFloaterRegionInfo::onRegionChanged() void LLFloaterRegionInfo::requestRegionInfo() { - LLTabContainer* tab = findChild("region_panels"); - if (tab) - { - tab->getChild("General")->setCtrlsEnabled(FALSE); - tab->getChild("Debug")->setCtrlsEnabled(FALSE); - tab->getChild("Terrain")->setCtrlsEnabled(FALSE); - tab->getChild("Estate")->setCtrlsEnabled(FALSE); + LLTabContainer* tab = findChild("region_panels"); + if (tab) + { + tab->getChild("General")->setCtrlsEnabled(FALSE); + tab->getChild("Debug")->setCtrlsEnabled(FALSE); + tab->getChild("Terrain")->setCtrlsEnabled(FALSE); + tab->getChild("Estate")->setCtrlsEnabled(FALSE); tab->getChild("Access")->setCtrlsEnabled(FALSE); - } + } - // Must allow anyone to request the RegionInfo data - // so non-owners/non-gods can see the values. - // Therefore can't use an EstateOwnerMessage JC - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RequestRegionInfo"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - gAgent.sendReliableMessage(); + // Must allow anyone to request the RegionInfo data + // so non-owners/non-gods can see the values. + // Therefore can't use an EstateOwnerMessage JC + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("RequestRegionInfo"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + gAgent.sendReliableMessage(); } // static void LLFloaterRegionInfo::processEstateOwnerRequest(LLMessageSystem* msg,void**) { - static LLDispatcher dispatch; - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if(!floater) - { - return; - } - - if (!estate_dispatch_initialized) - { - LLPanelEstateInfo::initDispatch(dispatch); - } - - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - - // unpack the message - std::string request; - LLUUID invoice; - LLDispatcher::sparam_t strings; - LLDispatcher::unpackMessage(msg, request, invoice, strings); - if(invoice != getLastInvoice()) - { - LL_WARNS() << "Mismatched Estate message: " << request << LL_ENDL; - return; - } - - //dispatch the message - dispatch.dispatch(request, invoice, strings); - - if (panel) - { - panel->updateControls(gAgent.getRegion()); - } + static LLDispatcher dispatch; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if(!floater) + { + return; + } + + if (!estate_dispatch_initialized) + { + LLPanelEstateInfo::initDispatch(dispatch); + } + + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + + // unpack the message + std::string request; + LLUUID invoice; + LLDispatcher::sparam_t strings; + LLDispatcher::unpackMessage(msg, request, invoice, strings); + if(invoice != getLastInvoice()) + { + LL_WARNS() << "Mismatched Estate message: " << request << LL_ENDL; + return; + } + + //dispatch the message + dispatch.dispatch(request, invoice, strings); + + if (panel) + { + panel->updateControls(gAgent.getRegion()); + } } // static void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) { - LLPanel* panel; - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if(!floater) - { - return; - } + LLPanel* panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if(!floater) + { + return; + } #if 0 - // We need to re-request environment setting here, - // otherwise after we apply (send) updated region settings we won't get them back, - // so our environment won't be updated. - // This is also the way to know about externally changed region environment. - LLEnvManagerNew::instance().requestRegionSettings(); -#endif - LLTabContainer* tab = floater->getChild("region_panels"); - - LLViewerRegion* region = gAgent.getRegion(); - BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); - - // *TODO: Replace parsing msg with accessing the region info model. - LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); - - // extract message - std::string sim_name; - std::string sim_type = LLTrans::getString("land_type_unknown"); - U64 region_flags; - U8 agent_limit; - S32 hard_agent_limit; - F32 object_bonus_factor; - U8 sim_access; - F32 water_height; - F32 terrain_raise_limit; - F32 terrain_lower_limit; - BOOL use_estate_sun; - F32 sun_hour; - msg->getString("RegionInfo", "SimName", sim_name); - msg->getU8("RegionInfo", "MaxAgents", agent_limit); - msg->getS32("RegionInfo2", "HardMaxAgents", hard_agent_limit); - msg->getF32("RegionInfo", "ObjectBonusFactor", object_bonus_factor); - msg->getU8("RegionInfo", "SimAccess", sim_access); - msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); - msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit); - msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit); - msg->getBOOL("RegionInfo", "UseEstateSun", use_estate_sun); - // actually the "last set" sun hour, not the current sun hour. JC - msg->getF32("RegionInfo", "SunHour", sun_hour); - // the only reasonable way to decide if we actually have any data is to - // check to see if any of these fields have nonzero sizes - if (msg->getSize("RegionInfo2", "ProductSKU") > 0 || - msg->getSize("RegionInfo2", "ProductName") > 0) - { - msg->getString("RegionInfo2", "ProductName", sim_type); - LLTrans::findString(sim_type, sim_type); // try localizing sim product name - } - - if (msg->has(_PREHASH_RegionInfo3)) - { - msg->getU64("RegionInfo3", "RegionFlagsExtended", region_flags); - } - else - { - U32 flags = 0; - msg->getU32("RegionInfo", "RegionFlags", flags); - region_flags = flags; - } - - if (msg->has(_PREHASH_RegionInfo5)) - { - F32 chat_whisper_range; - F32 chat_normal_range; - F32 chat_shout_range; - F32 chat_whisper_offset; - F32 chat_normal_offset; - F32 chat_shout_offset; - U32 chat_flags; - - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range); - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range); - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range); - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset); - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset); - msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset); - msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags); - - LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range - << " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset - << " chat flags: " << chat_flags << LL_ENDL; - } - - // GENERAL PANEL - panel = tab->getChild("General"); - panel->getChild("region_text")->setValue(LLSD(sim_name)); - panel->getChild("region_type")->setValue(LLSD(sim_type)); - panel->getChild("version_channel_text")->setValue(gLastVersionChannel); - - panel->getChild("block_terraform_check")->setValue((region_flags & REGION_FLAGS_BLOCK_TERRAFORM) ? TRUE : FALSE ); - panel->getChild("block_fly_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLY) ? TRUE : FALSE ); - panel->getChild("block_fly_over_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLYOVER) ? TRUE : FALSE ); - panel->getChild("allow_damage_check")->setValue((region_flags & REGION_FLAGS_ALLOW_DAMAGE) ? TRUE : FALSE ); - panel->getChild("restrict_pushobject")->setValue((region_flags & REGION_FLAGS_RESTRICT_PUSHOBJECT) ? TRUE : FALSE ); - panel->getChild("allow_land_resell_check")->setValue((region_flags & REGION_FLAGS_BLOCK_LAND_RESELL) ? FALSE : TRUE ); - panel->getChild("allow_parcel_changes_check")->setValue((region_flags & REGION_FLAGS_ALLOW_PARCEL_CHANGES) ? TRUE : FALSE ); - panel->getChild("block_parcel_search_check")->setValue((region_flags & REGION_FLAGS_BLOCK_PARCEL_SEARCH) ? TRUE : FALSE ); - panel->getChild("agent_limit_spin")->setValue(LLSD((F32)agent_limit) ); - panel->getChild("object_bonus_spin")->setValue(LLSD(object_bonus_factor) ); - panel->getChild("access_combo")->setValue(LLSD(sim_access) ); - - panel->getChild("agent_limit_spin")->setMaxValue(hard_agent_limit); - - LLPanelRegionGeneralInfo* panel_general = LLFloaterRegionInfo::getPanelGeneral(); - if (panel) - { - panel_general->setObjBonusFactor(object_bonus_factor); - } - - // detect teen grid for maturity - - U32 parent_estate_id; - msg->getU32("RegionInfo", "ParentEstateID", parent_estate_id); - BOOL teen_grid = (parent_estate_id == 5); // *TODO add field to estate table and test that - panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); - panel->setCtrlsEnabled(allow_modify); - - - // DEBUG PANEL - panel = tab->getChild("Debug"); - - panel->getChild("region_text")->setValue(LLSD(sim_name) ); - panel->getChild("disable_scripts_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_SCRIPTS) ? TRUE : FALSE )) ); - panel->getChild("disable_collisions_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_COLLISIONS) ? TRUE : FALSE )) ); - panel->getChild("disable_physics_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_PHYSICS) ? TRUE : FALSE )) ); - panel->setCtrlsEnabled(allow_modify); - - // TERRAIN PANEL - panel = tab->getChild("Terrain"); - - panel->getChild("region_text")->setValue(LLSD(sim_name)); - panel->getChild("water_height_spin")->setValue(region_info.mWaterHeight); - panel->getChild("terrain_raise_spin")->setValue(region_info.mTerrainRaiseLimit); - panel->getChild("terrain_lower_spin")->setValue(region_info.mTerrainLowerLimit); - - panel->setCtrlsEnabled(allow_modify); - - if (floater->getVisible()) - { - // Note: region info also causes LLRegionInfoModel::instance().update(msg); -> requestRegion(); -> changed message - // we need to know env version here and in update(msg) to know when to request and when not to, when to filter 'changed' - floater->refreshFromRegion(gAgent.getRegion()); - } // else will rerequest on onOpen either way + // We need to re-request environment setting here, + // otherwise after we apply (send) updated region settings we won't get them back, + // so our environment won't be updated. + // This is also the way to know about externally changed region environment. + LLEnvManagerNew::instance().requestRegionSettings(); +#endif + LLTabContainer* tab = floater->getChild("region_panels"); + + LLViewerRegion* region = gAgent.getRegion(); + BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); + + // *TODO: Replace parsing msg with accessing the region info model. + LLRegionInfoModel& region_info = LLRegionInfoModel::instance(); + + // extract message + std::string sim_name; + std::string sim_type = LLTrans::getString("land_type_unknown"); + U64 region_flags; + U8 agent_limit; + S32 hard_agent_limit; + F32 object_bonus_factor; + U8 sim_access; + F32 water_height; + F32 terrain_raise_limit; + F32 terrain_lower_limit; + BOOL use_estate_sun; + F32 sun_hour; + msg->getString("RegionInfo", "SimName", sim_name); + msg->getU8("RegionInfo", "MaxAgents", agent_limit); + msg->getS32("RegionInfo2", "HardMaxAgents", hard_agent_limit); + msg->getF32("RegionInfo", "ObjectBonusFactor", object_bonus_factor); + msg->getU8("RegionInfo", "SimAccess", sim_access); + msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); + msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit); + msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit); + msg->getBOOL("RegionInfo", "UseEstateSun", use_estate_sun); + // actually the "last set" sun hour, not the current sun hour. JC + msg->getF32("RegionInfo", "SunHour", sun_hour); + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have nonzero sizes + if (msg->getSize("RegionInfo2", "ProductSKU") > 0 || + msg->getSize("RegionInfo2", "ProductName") > 0) + { + msg->getString("RegionInfo2", "ProductName", sim_type); + LLTrans::findString(sim_type, sim_type); // try localizing sim product name + } + + if (msg->has(_PREHASH_RegionInfo3)) + { + msg->getU64("RegionInfo3", "RegionFlagsExtended", region_flags); + } + else + { + U32 flags = 0; + msg->getU32("RegionInfo", "RegionFlags", flags); + region_flags = flags; + } + + if (msg->has(_PREHASH_RegionInfo5)) + { + F32 chat_whisper_range; + F32 chat_normal_range; + F32 chat_shout_range; + F32 chat_whisper_offset; + F32 chat_normal_offset; + F32 chat_shout_offset; + U32 chat_flags; + + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range); + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range); + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range); + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset); + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset); + msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset); + msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags); + + LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range + << " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset + << " chat flags: " << chat_flags << LL_ENDL; + } + + // GENERAL PANEL + panel = tab->getChild("General"); + panel->getChild("region_text")->setValue(LLSD(sim_name)); + panel->getChild("region_type")->setValue(LLSD(sim_type)); + panel->getChild("version_channel_text")->setValue(gLastVersionChannel); + + panel->getChild("block_terraform_check")->setValue((region_flags & REGION_FLAGS_BLOCK_TERRAFORM) ? TRUE : FALSE ); + panel->getChild("block_fly_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLY) ? TRUE : FALSE ); + panel->getChild("block_fly_over_check")->setValue((region_flags & REGION_FLAGS_BLOCK_FLYOVER) ? TRUE : FALSE ); + panel->getChild("allow_damage_check")->setValue((region_flags & REGION_FLAGS_ALLOW_DAMAGE) ? TRUE : FALSE ); + panel->getChild("restrict_pushobject")->setValue((region_flags & REGION_FLAGS_RESTRICT_PUSHOBJECT) ? TRUE : FALSE ); + panel->getChild("allow_land_resell_check")->setValue((region_flags & REGION_FLAGS_BLOCK_LAND_RESELL) ? FALSE : TRUE ); + panel->getChild("allow_parcel_changes_check")->setValue((region_flags & REGION_FLAGS_ALLOW_PARCEL_CHANGES) ? TRUE : FALSE ); + panel->getChild("block_parcel_search_check")->setValue((region_flags & REGION_FLAGS_BLOCK_PARCEL_SEARCH) ? TRUE : FALSE ); + panel->getChild("agent_limit_spin")->setValue(LLSD((F32)agent_limit) ); + panel->getChild("object_bonus_spin")->setValue(LLSD(object_bonus_factor) ); + panel->getChild("access_combo")->setValue(LLSD(sim_access) ); + + panel->getChild("agent_limit_spin")->setMaxValue(hard_agent_limit); + + LLPanelRegionGeneralInfo* panel_general = LLFloaterRegionInfo::getPanelGeneral(); + if (panel) + { + panel_general->setObjBonusFactor(object_bonus_factor); + } + + // detect teen grid for maturity + + U32 parent_estate_id; + msg->getU32("RegionInfo", "ParentEstateID", parent_estate_id); + BOOL teen_grid = (parent_estate_id == 5); // *TODO add field to estate table and test that + panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); + panel->setCtrlsEnabled(allow_modify); + + + // DEBUG PANEL + panel = tab->getChild("Debug"); + + panel->getChild("region_text")->setValue(LLSD(sim_name) ); + panel->getChild("disable_scripts_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_SCRIPTS) ? TRUE : FALSE )) ); + panel->getChild("disable_collisions_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_COLLISIONS) ? TRUE : FALSE )) ); + panel->getChild("disable_physics_check")->setValue(LLSD((BOOL)((region_flags & REGION_FLAGS_SKIP_PHYSICS) ? TRUE : FALSE )) ); + panel->setCtrlsEnabled(allow_modify); + + // TERRAIN PANEL + panel = tab->getChild("Terrain"); + + panel->getChild("region_text")->setValue(LLSD(sim_name)); + panel->getChild("water_height_spin")->setValue(region_info.mWaterHeight); + panel->getChild("terrain_raise_spin")->setValue(region_info.mTerrainRaiseLimit); + panel->getChild("terrain_lower_spin")->setValue(region_info.mTerrainLowerLimit); + + panel->setCtrlsEnabled(allow_modify); + + if (floater->getVisible()) + { + // Note: region info also causes LLRegionInfoModel::instance().update(msg); -> requestRegion(); -> changed message + // we need to know env version here and in update(msg) to know when to request and when not to, when to filter 'changed' + floater->refreshFromRegion(gAgent.getRegion()); + } // else will rerequest on onOpen either way } // static LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild("Estate"); - return panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelEstateInfo* panel = (LLPanelEstateInfo*)tab->getChild("Estate"); + return panel; } // static LLPanelEstateAccess* LLFloaterRegionInfo::getPanelAccess() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelEstateAccess* panel = (LLPanelEstateAccess*)tab->getChild("Access"); - return panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelEstateAccess* panel = (LLPanelEstateAccess*)tab->getChild("Access"); + return panel; } // static LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild("Covenant"); - return panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelEstateCovenant* panel = (LLPanelEstateCovenant*)tab->getChild("Covenant"); + return panel; } // static LLPanelRegionGeneralInfo* LLFloaterRegionInfo::getPanelGeneral() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelRegionGeneralInfo* panel = (LLPanelRegionGeneralInfo*)tab->getChild("General"); - return panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelRegionGeneralInfo* panel = (LLPanelRegionGeneralInfo*)tab->getChild("General"); + return panel; } // static LLPanelRegionEnvironment* LLFloaterRegionInfo::getPanelEnvironment() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - LLPanelRegionEnvironment* panel = (LLPanelRegionEnvironment*)tab->getChild("panel_env_info"); - return panel; + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + LLPanelRegionEnvironment* panel = (LLPanelRegionEnvironment*)tab->getChild("panel_env_info"); + return panel; } LLTerrainMaterials::Type material_type_from_ctrl(LLCheckBoxCtrl* ctrl) @@ -616,91 +616,91 @@ void material_type_to_ctrl(LLCheckBoxCtrl* ctrl, LLTerrainMaterials::Type new_ty // static LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) - { - llassert(floater); - return NULL; - } + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) + { + llassert(floater); + return NULL; + } - LLTabContainer* tab_container = floater->getChild("region_panels"); - LLPanelRegionTerrainInfo* panel = - dynamic_cast(tab_container->getChild("Terrain")); - llassert(panel); - return panel; + LLTabContainer* tab_container = floater->getChild("region_panels"); + LLPanelRegionTerrainInfo* panel = + dynamic_cast(tab_container->getChild("Terrain")); + llassert(panel); + return panel; } LLPanelRegionExperiences* LLFloaterRegionInfo::getPanelExperiences() { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (!floater) return NULL; - LLTabContainer* tab = floater->getChild("region_panels"); - return (LLPanelRegionExperiences*)tab->getChild("Experiences"); + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild("region_panels"); + return (LLPanelRegionExperiences*)tab->getChild("Experiences"); } void LLFloaterRegionInfo::disableTabCtrls() { - LLTabContainer* tab = getChild("region_panels"); + LLTabContainer* tab = getChild("region_panels"); - tab->getChild("General")->setCtrlsEnabled(FALSE); - tab->getChild("Debug")->setCtrlsEnabled(FALSE); - tab->getChild("Terrain")->setCtrlsEnabled(FALSE); - tab->getChild("panel_env_info")->setCtrlsEnabled(FALSE); - tab->getChild("Estate")->setCtrlsEnabled(FALSE); - tab->getChild("Access")->setCtrlsEnabled(FALSE); + tab->getChild("General")->setCtrlsEnabled(FALSE); + tab->getChild("Debug")->setCtrlsEnabled(FALSE); + tab->getChild("Terrain")->setCtrlsEnabled(FALSE); + tab->getChild("panel_env_info")->setCtrlsEnabled(FALSE); + tab->getChild("Estate")->setCtrlsEnabled(FALSE); + tab->getChild("Access")->setCtrlsEnabled(FALSE); } void LLFloaterRegionInfo::onTabSelected(const LLSD& param) { - LLPanel* active_panel = getChild(param.asString()); - active_panel->onOpen(LLSD()); + LLPanel* active_panel = getChild(param.asString()); + active_panel->onOpen(LLSD()); } void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region) { - if (!region) - { - return; - } + if (!region) + { + return; + } - // call refresh from region on all panels - for (const auto& infoPanel : mInfoPanels) - { - infoPanel->refreshFromRegion(region); - } - mEnvironmentPanel->refreshFromRegion(region); + // call refresh from region on all panels + for (const auto& infoPanel : mInfoPanels) + { + infoPanel->refreshFromRegion(region); + } + mEnvironmentPanel->refreshFromRegion(region); } // public void LLFloaterRegionInfo::refresh() { - for(info_panels_t::iterator iter = mInfoPanels.begin(); - iter != mInfoPanels.end(); ++iter) - { - (*iter)->refresh(); - } + for(info_panels_t::iterator iter = mInfoPanels.begin(); + iter != mInfoPanels.end(); ++iter) + { + (*iter)->refresh(); + } mEnvironmentPanel->refresh(); } void LLFloaterRegionInfo::enableTopButtons() { - getChildView("top_colliders_btn")->setEnabled(true); - getChildView("top_scripts_btn")->setEnabled(true); + getChildView("top_colliders_btn")->setEnabled(true); + getChildView("top_scripts_btn")->setEnabled(true); } void LLFloaterRegionInfo::disableTopButtons() { - getChildView("top_colliders_btn")->setEnabled(false); - getChildView("top_scripts_btn")->setEnabled(false); + getChildView("top_colliders_btn")->setEnabled(false); + getChildView("top_scripts_btn")->setEnabled(false); } void LLFloaterRegionInfo::onGodLevelChange(U8 god_level) { - LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); - if (floater && floater->getVisible()) - { - refreshFromRegion(gAgent.getRegion()); - } + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (floater && floater->getVisible()) + { + refreshFromRegion(gAgent.getRegion()); + } } ///---------------------------------------------------------------------------- @@ -712,58 +712,58 @@ void LLFloaterRegionInfo::onGodLevelChange(U8 god_level) // LLPanelRegionInfo::LLPanelRegionInfo() - : LLPanel() + : LLPanel() { } void LLPanelRegionInfo::onBtnSet() { - if (sendUpdate()) - { - disableButton("apply_btn"); - } + if (sendUpdate()) + { + disableButton("apply_btn"); + } } void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl) { - updateChild(ctrl); // virtual function + updateChild(ctrl); // virtual function } // Enables the "set" button if it is not already enabled void LLPanelRegionInfo::onChangeAnything() { - enableButton("apply_btn"); - refresh(); + enableButton("apply_btn"); + refresh(); } // static // Enables set button on change to line editor void LLPanelRegionInfo::onChangeText(LLLineEditor* caller, void* user_data) { - LLPanelRegionInfo* panel = dynamic_cast(caller->getParent()); - if(panel) - { - panel->enableButton("apply_btn"); - panel->refresh(); - } + LLPanelRegionInfo* panel = dynamic_cast(caller->getParent()); + if(panel) + { + panel->enableButton("apply_btn"); + panel->refresh(); + } } // virtual BOOL LLPanelRegionInfo::postBuild() { - // If the panel has an Apply button, set a callback for it. - LLUICtrl* apply_btn = findChild("apply_btn"); - if (apply_btn) - { - apply_btn->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this)); - } + // If the panel has an Apply button, set a callback for it. + LLUICtrl* apply_btn = findChild("apply_btn"); + if (apply_btn) + { + apply_btn->setCommitCallback(boost::bind(&LLPanelRegionInfo::onBtnSet, this)); + } - refresh(); - return TRUE; + refresh(); + return TRUE; } -// virtual +// virtual void LLPanelRegionInfo::updateChild(LLUICtrl* child_ctr) { } @@ -771,64 +771,64 @@ void LLPanelRegionInfo::updateChild(LLUICtrl* child_ctr) // virtual bool LLPanelRegionInfo::refreshFromRegion(LLViewerRegion* region) { - if (region) mHost = region->getHost(); - return true; + if (region) mHost = region->getHost(); + return true; } void LLPanelRegionInfo::sendEstateOwnerMessage( - LLMessageSystem* msg, - const std::string& request, - const LLUUID& invoice, - const strings_t& strings) -{ - LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", request); - msg->addUUID("Invoice", invoice); - if(strings.empty()) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", NULL); - } - else - { - strings_t::const_iterator it = strings.begin(); - strings_t::const_iterator end = strings.end(); - for(; it != end; ++it) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", *it); - } - } - msg->sendReliable(mHost); + LLMessageSystem* msg, + const std::string& request, + const LLUUID& invoice, + const strings_t& strings) +{ + LL_INFOS() << "Sending estate request '" << request << "'" << LL_ENDL; + msg->newMessage("EstateOwnerMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + msg->nextBlock("MethodData"); + msg->addString("Method", request); + msg->addUUID("Invoice", invoice); + if(strings.empty()) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", NULL); + } + else + { + strings_t::const_iterator it = strings.begin(); + strings_t::const_iterator end = strings.end(); + for(; it != end; ++it) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", *it); + } + } + msg->sendReliable(mHost); } void LLPanelRegionInfo::enableButton(const std::string& btn_name, BOOL enable) { - LLView* button = findChildView(btn_name); - if (button) button->setEnabled(enable); + LLView* button = findChildView(btn_name); + if (button) button->setEnabled(enable); } void LLPanelRegionInfo::disableButton(const std::string& btn_name) { - LLView* button = findChildView(btn_name); - if (button) button->setEnabled(FALSE); + LLView* button = findChildView(btn_name); + if (button) button->setEnabled(FALSE); } void LLPanelRegionInfo::initCtrl(const std::string& name) { - getChild(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this)); + getChild(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this)); } void LLPanelRegionInfo::onClickManageTelehub() { - LLFloaterReg::hideInstance("region_info"); - LLFloaterReg::showInstance("telehubs"); + LLFloaterReg::hideInstance("region_info"); + LLFloaterReg::showInstance("telehubs"); } ///////////////////////////////////////////////////////////////////////////// @@ -836,181 +836,181 @@ void LLPanelRegionInfo::onClickManageTelehub() // bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) { - BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); - setCtrlsEnabled(allow_modify); - getChildView("apply_btn")->setEnabled(FALSE); - getChildView("access_text")->setEnabled(allow_modify); - // getChildView("access_combo")->setEnabled(allow_modify); - // now set in processRegionInfo for teen grid detection - getChildView("kick_btn")->setEnabled(allow_modify); - getChildView("kick_all_btn")->setEnabled(allow_modify); - getChildView("im_btn")->setEnabled(allow_modify); - getChildView("manage_telehub_btn")->setEnabled(allow_modify); + BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); + setCtrlsEnabled(allow_modify); + getChildView("apply_btn")->setEnabled(FALSE); + getChildView("access_text")->setEnabled(allow_modify); + // getChildView("access_combo")->setEnabled(allow_modify); + // now set in processRegionInfo for teen grid detection + getChildView("kick_btn")->setEnabled(allow_modify); + getChildView("kick_all_btn")->setEnabled(allow_modify); + getChildView("im_btn")->setEnabled(allow_modify); + getChildView("manage_telehub_btn")->setEnabled(allow_modify); - // Data gets filled in by processRegionInfo + // Data gets filled in by processRegionInfo - return LLPanelRegionInfo::refreshFromRegion(region); + return LLPanelRegionInfo::refreshFromRegion(region); } BOOL LLPanelRegionGeneralInfo::postBuild() { - // Enable the "Apply" button if something is changed. JC - initCtrl("block_terraform_check"); - initCtrl("block_fly_check"); - initCtrl("block_fly_over_check"); - initCtrl("allow_damage_check"); - initCtrl("allow_land_resell_check"); - initCtrl("allow_parcel_changes_check"); - initCtrl("agent_limit_spin"); - initCtrl("object_bonus_spin"); - initCtrl("access_combo"); - initCtrl("restrict_pushobject"); - initCtrl("block_parcel_search_check"); - - childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this)); - childSetAction("kick_all_btn", onClickKickAll, this); - childSetAction("im_btn", onClickMessage, this); -// childSetAction("manage_telehub_btn", onClickManageTelehub, this); - - LLUICtrl* apply_btn = findChild("apply_btn"); - if (apply_btn) - { - apply_btn->setCommitCallback(boost::bind(&LLPanelRegionGeneralInfo::onBtnSet, this)); - } - - refresh(); - return TRUE; + // Enable the "Apply" button if something is changed. JC + initCtrl("block_terraform_check"); + initCtrl("block_fly_check"); + initCtrl("block_fly_over_check"); + initCtrl("allow_damage_check"); + initCtrl("allow_land_resell_check"); + initCtrl("allow_parcel_changes_check"); + initCtrl("agent_limit_spin"); + initCtrl("object_bonus_spin"); + initCtrl("access_combo"); + initCtrl("restrict_pushobject"); + initCtrl("block_parcel_search_check"); + + childSetAction("kick_btn", boost::bind(&LLPanelRegionGeneralInfo::onClickKick, this)); + childSetAction("kick_all_btn", onClickKickAll, this); + childSetAction("im_btn", onClickMessage, this); +// childSetAction("manage_telehub_btn", onClickManageTelehub, this); + + LLUICtrl* apply_btn = findChild("apply_btn"); + if (apply_btn) + { + apply_btn->setCommitCallback(boost::bind(&LLPanelRegionGeneralInfo::onBtnSet, this)); + } + + refresh(); + return TRUE; } void LLPanelRegionGeneralInfo::onBtnSet() { - if(mObjBonusFactor == getChild("object_bonus_spin")->getValue().asReal()) - { - if (sendUpdate()) - { - disableButton("apply_btn"); - } - } - else - { - LLNotificationsUtil::add("ChangeObjectBonusFactor", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onChangeObjectBonus, this, _1, _2)); - } + if(mObjBonusFactor == getChild("object_bonus_spin")->getValue().asReal()) + { + if (sendUpdate()) + { + disableButton("apply_btn"); + } + } + else + { + LLNotificationsUtil::add("ChangeObjectBonusFactor", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onChangeObjectBonus, this, _1, _2)); + } } bool LLPanelRegionGeneralInfo::onChangeObjectBonus(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - if (sendUpdate()) - { - disableButton("apply_btn"); - } - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + if (sendUpdate()) + { + disableButton("apply_btn"); + } + } + return false; } void LLPanelRegionGeneralInfo::onClickKick() { - LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKick" << LL_ENDL; + LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKick" << LL_ENDL; - // this depends on the grandparent view being a floater - // in order to set up floater dependency + // this depends on the grandparent view being a floater + // in order to set up floater dependency LLView * button = findChild("kick_btn"); - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionGeneralInfo::onKickCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName(), button); - if (child_floater) - { - parent_floater->addDependentFloater(child_floater); - } + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } void LLPanelRegionGeneralInfo::onKickCommit(const uuid_vec_t& ids) { - if (ids.empty()) return; - if(ids[0].notNull()) - { - strings_t strings; - // [0] = our agent id - // [1] = target agent id - std::string buffer; - gAgent.getID().toString(buffer); - strings.push_back(buffer); + if (ids.empty()) return; + if(ids[0].notNull()) + { + strings_t strings; + // [0] = our agent id + // [1] = target agent id + std::string buffer; + gAgent.getID().toString(buffer); + strings.push_back(buffer); - ids[0].toString(buffer); - strings.push_back(strings_t::value_type(buffer)); + ids[0].toString(buffer); + strings.push_back(strings_t::value_type(buffer)); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); - } + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "teleporthomeuser", invoice, strings); + } } // static void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata) { - LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKickAll" << LL_ENDL; - LLNotificationsUtil::add("KickUsersFromRegion", - LLSD(), - LLSD(), - boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); + LL_INFOS() << "LLPanelRegionGeneralInfo::onClickKickAll" << LL_ENDL; + LLNotificationsUtil::add("KickUsersFromRegion", + LLSD(), + LLSD(), + boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); } bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - strings_t strings; - // [0] = our agent id - std::string buffer; - gAgent.getID().toString(buffer); - strings.push_back(buffer); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + strings_t strings; + // [0] = our agent id + std::string buffer; + gAgent.getID().toString(buffer); + strings.push_back(buffer); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - // historical message name - sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings); - } - return false; + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + // historical message name + sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings); + } + return false; } // static void LLPanelRegionGeneralInfo::onClickMessage(void* userdata) { - LL_INFOS() << "LLPanelRegionGeneralInfo::onClickMessage" << LL_ENDL; - LLNotificationsUtil::add("MessageRegion", - LLSD(), - LLSD(), - boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); + LL_INFOS() << "LLPanelRegionGeneralInfo::onClickMessage" << LL_ENDL; + LLNotificationsUtil::add("MessageRegion", + LLSD(), + LLSD(), + boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); } // static bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const LLSD& response) { - if(LLNotificationsUtil::getSelectedOption(notification, response) != 0) return false; - - std::string text = response["message"].asString(); - if (text.empty()) return false; - - LL_INFOS() << "Message to everyone: " << text << LL_ENDL; - strings_t strings; - // [0] grid_x, unused here - // [1] grid_y, unused here - // [2] agent_id of sender - // [3] sender name - // [4] message - strings.push_back("-1"); - strings.push_back("-1"); - std::string buffer; - gAgent.getID().toString(buffer); - strings.push_back(buffer); - std::string name; - LLAgentUI::buildFullname(name); - strings.push_back(strings_t::value_type(name)); - strings.push_back(strings_t::value_type(text)); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings); - return false; + if(LLNotificationsUtil::getSelectedOption(notification, response) != 0) return false; + + std::string text = response["message"].asString(); + if (text.empty()) return false; + + LL_INFOS() << "Message to everyone: " << text << LL_ENDL; + strings_t strings; + // [0] grid_x, unused here + // [1] grid_y, unused here + // [2] agent_id of sender + // [3] sender name + // [4] message + strings.push_back("-1"); + strings.push_back("-1"); + std::string buffer; + gAgent.getID().toString(buffer); + strings.push_back(buffer); + std::string name; + LLAgentUI::buildFullname(name); + strings.push_back(strings_t::value_type(name)); + strings.push_back(strings_t::value_type(text)); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings); + return false; } // setregioninfo @@ -1026,74 +1026,74 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L // strings[9] = 'Y' - block parcel search, 'N' - allow BOOL LLPanelRegionGeneralInfo::sendUpdate() { - LL_INFOS() << "LLPanelRegionGeneralInfo::sendUpdate()" << LL_ENDL; - - // First try using a Cap. If that fails use the old method. - LLSD body; - std::string url = gAgent.getRegionCapability("DispatchRegionInfo"); - if (!url.empty()) - { - body["block_terraform"] = getChild("block_terraform_check")->getValue(); - body["block_fly"] = getChild("block_fly_check")->getValue(); - body["block_fly_over"] = getChild("block_fly_over_check")->getValue(); - body["allow_damage"] = getChild("allow_damage_check")->getValue(); - body["allow_land_resell"] = getChild("allow_land_resell_check")->getValue(); - body["agent_limit"] = getChild("agent_limit_spin")->getValue(); - body["prim_bonus"] = getChild("object_bonus_spin")->getValue(); - body["sim_access"] = getChild("access_combo")->getValue(); - body["restrict_pushobject"] = getChild("restrict_pushobject")->getValue(); - body["allow_parcel_changes"] = getChild("allow_parcel_changes_check")->getValue(); - body["block_parcel_search"] = getChild("block_parcel_search_check")->getValue(); + LL_INFOS() << "LLPanelRegionGeneralInfo::sendUpdate()" << LL_ENDL; + + // First try using a Cap. If that fails use the old method. + LLSD body; + std::string url = gAgent.getRegionCapability("DispatchRegionInfo"); + if (!url.empty()) + { + body["block_terraform"] = getChild("block_terraform_check")->getValue(); + body["block_fly"] = getChild("block_fly_check")->getValue(); + body["block_fly_over"] = getChild("block_fly_over_check")->getValue(); + body["allow_damage"] = getChild("allow_damage_check")->getValue(); + body["allow_land_resell"] = getChild("allow_land_resell_check")->getValue(); + body["agent_limit"] = getChild("agent_limit_spin")->getValue(); + body["prim_bonus"] = getChild("object_bonus_spin")->getValue(); + body["sim_access"] = getChild("access_combo")->getValue(); + body["restrict_pushobject"] = getChild("restrict_pushobject")->getValue(); + body["allow_parcel_changes"] = getChild("allow_parcel_changes_check")->getValue(); + body["block_parcel_search"] = getChild("block_parcel_search_check")->getValue(); LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, "Region info update posted.", "Region info update not posted."); - } - else - { - strings_t strings; - std::string buffer; + } + else + { + strings_t strings; + std::string buffer; - buffer = llformat("%s", (getChild("block_terraform_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("block_terraform_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%s", (getChild("block_fly_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("block_fly_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%s", (getChild("allow_damage_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("allow_damage_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%s", (getChild("allow_land_resell_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("allow_land_resell_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - F32 value = (F32)getChild("agent_limit_spin")->getValue().asReal(); - buffer = llformat("%f", value); - strings.push_back(strings_t::value_type(buffer)); + F32 value = (F32)getChild("agent_limit_spin")->getValue().asReal(); + buffer = llformat("%f", value); + strings.push_back(strings_t::value_type(buffer)); - value = (F32)getChild("object_bonus_spin")->getValue().asReal(); - buffer = llformat("%f", value); - strings.push_back(strings_t::value_type(buffer)); + value = (F32)getChild("object_bonus_spin")->getValue().asReal(); + buffer = llformat("%f", value); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%d", getChild("access_combo")->getValue().asInteger()); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%d", getChild("access_combo")->getValue().asInteger()); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%s", (getChild("restrict_pushobject")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("restrict_pushobject")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - buffer = llformat("%s", (getChild("allow_parcel_changes_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(strings_t::value_type(buffer)); + buffer = llformat("%s", (getChild("allow_parcel_changes_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(strings_t::value_type(buffer)); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings); - } + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "setregioninfo", invoice, strings); + } - // if we changed access levels, tell user about it - LLViewerRegion* region = gAgent.getRegion(); - if (region && (getChild("access_combo")->getValue().asInteger() != region->getSimAccess()) ) - { - LLNotificationsUtil::add("RegionMaturityChange"); - } + // if we changed access levels, tell user about it + LLViewerRegion* region = gAgent.getRegion(); + if (region && (getChild("access_combo")->getValue().asInteger() != region->getSimAccess()) ) + { + LLNotificationsUtil::add("RegionMaturityChange"); + } - return TRUE; + return TRUE; } ///////////////////////////////////////////////////////////////////////////// @@ -1101,216 +1101,216 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() ///////////////////////////////////////////////////////////////////////////// BOOL LLPanelRegionDebugInfo::postBuild() { - LLPanelRegionInfo::postBuild(); - initCtrl("disable_scripts_check"); - initCtrl("disable_collisions_check"); - initCtrl("disable_physics_check"); + LLPanelRegionInfo::postBuild(); + initCtrl("disable_scripts_check"); + initCtrl("disable_collisions_check"); + initCtrl("disable_physics_check"); - childSetAction("choose_avatar_btn", boost::bind(&LLPanelRegionDebugInfo::onClickChooseAvatar, this)); - childSetAction("return_btn", onClickReturn, this); - childSetAction("top_colliders_btn", onClickTopColliders, this); - childSetAction("top_scripts_btn", onClickTopScripts, this); - childSetAction("restart_btn", onClickRestart, this); - childSetAction("cancel_restart_btn", onClickCancelRestart, this); - childSetAction("region_debug_console_btn", onClickDebugConsole, this); + childSetAction("choose_avatar_btn", boost::bind(&LLPanelRegionDebugInfo::onClickChooseAvatar, this)); + childSetAction("return_btn", onClickReturn, this); + childSetAction("top_colliders_btn", onClickTopColliders, this); + childSetAction("top_scripts_btn", onClickTopScripts, this); + childSetAction("restart_btn", onClickRestart, this); + childSetAction("cancel_restart_btn", onClickCancelRestart, this); + childSetAction("region_debug_console_btn", onClickDebugConsole, this); - return TRUE; + return TRUE; } // virtual bool LLPanelRegionDebugInfo::refreshFromRegion(LLViewerRegion* region) { - BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); - setCtrlsEnabled(allow_modify); - getChildView("apply_btn")->setEnabled(FALSE); - getChildView("target_avatar_name")->setEnabled(FALSE); - - getChildView("choose_avatar_btn")->setEnabled(allow_modify); - getChildView("return_scripts")->setEnabled(allow_modify && !mTargetAvatar.isNull()); - getChildView("return_other_land")->setEnabled(allow_modify && !mTargetAvatar.isNull()); - getChildView("return_estate_wide")->setEnabled(allow_modify && !mTargetAvatar.isNull()); - getChildView("return_btn")->setEnabled(allow_modify && !mTargetAvatar.isNull()); - getChildView("top_colliders_btn")->setEnabled(allow_modify); - getChildView("top_scripts_btn")->setEnabled(allow_modify); - getChildView("restart_btn")->setEnabled(allow_modify); - getChildView("cancel_restart_btn")->setEnabled(allow_modify); - getChildView("region_debug_console_btn")->setEnabled(allow_modify); - - return LLPanelRegionInfo::refreshFromRegion(region); + BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); + setCtrlsEnabled(allow_modify); + getChildView("apply_btn")->setEnabled(FALSE); + getChildView("target_avatar_name")->setEnabled(FALSE); + + getChildView("choose_avatar_btn")->setEnabled(allow_modify); + getChildView("return_scripts")->setEnabled(allow_modify && !mTargetAvatar.isNull()); + getChildView("return_other_land")->setEnabled(allow_modify && !mTargetAvatar.isNull()); + getChildView("return_estate_wide")->setEnabled(allow_modify && !mTargetAvatar.isNull()); + getChildView("return_btn")->setEnabled(allow_modify && !mTargetAvatar.isNull()); + getChildView("top_colliders_btn")->setEnabled(allow_modify); + getChildView("top_scripts_btn")->setEnabled(allow_modify); + getChildView("restart_btn")->setEnabled(allow_modify); + getChildView("cancel_restart_btn")->setEnabled(allow_modify); + getChildView("region_debug_console_btn")->setEnabled(allow_modify); + + return LLPanelRegionInfo::refreshFromRegion(region); } // virtual BOOL LLPanelRegionDebugInfo::sendUpdate() { - LL_INFOS() << "LLPanelRegionDebugInfo::sendUpdate" << LL_ENDL; - strings_t strings; - std::string buffer; + LL_INFOS() << "LLPanelRegionDebugInfo::sendUpdate" << LL_ENDL; + strings_t strings; + std::string buffer; - buffer = llformat("%s", (getChild("disable_scripts_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(buffer); + buffer = llformat("%s", (getChild("disable_scripts_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(buffer); - buffer = llformat("%s", (getChild("disable_collisions_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(buffer); + buffer = llformat("%s", (getChild("disable_collisions_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(buffer); - buffer = llformat("%s", (getChild("disable_physics_check")->getValue().asBoolean() ? "Y" : "N")); - strings.push_back(buffer); + buffer = llformat("%s", (getChild("disable_physics_check")->getValue().asBoolean() ? "Y" : "N")); + strings.push_back(buffer); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "setregiondebug", invoice, strings); - return TRUE; + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "setregiondebug", invoice, strings); + return TRUE; } void LLPanelRegionDebugInfo::onClickChooseAvatar() { LLView * button = findChild("choose_avatar_btn"); LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), + LLFloater * child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelRegionDebugInfo::callbackAvatarID, this, _1, _2), FALSE, TRUE, FALSE, parent_floater->getName(), button); - if (child_floater) - { - parent_floater->addDependentFloater(child_floater); - } + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } void LLPanelRegionDebugInfo::callbackAvatarID(const uuid_vec_t& ids, const std::vector names) { - if (ids.empty() || names.empty()) return; - mTargetAvatar = ids[0]; - getChild("target_avatar_name")->setValue(LLSD(names[0].getCompleteName())); - refreshFromRegion( gAgent.getRegion() ); + if (ids.empty() || names.empty()) return; + mTargetAvatar = ids[0]; + getChild("target_avatar_name")->setValue(LLSD(names[0].getCompleteName())); + refreshFromRegion( gAgent.getRegion() ); } // static void LLPanelRegionDebugInfo::onClickReturn(void* data) { - LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data; - if (panelp->mTargetAvatar.isNull()) return; - - LLSD args; - args["USER_NAME"] = panelp->getChild("target_avatar_name")->getValue().asString(); - LLSD payload; - payload["avatar_id"] = panelp->mTargetAvatar; - - U32 flags = SWD_ALWAYS_RETURN_OBJECTS; - - if (panelp->getChild("return_scripts")->getValue().asBoolean()) - { - flags |= SWD_SCRIPTED_ONLY; - } - - if (panelp->getChild("return_other_land")->getValue().asBoolean()) - { - flags |= SWD_OTHERS_LAND_ONLY; - } - payload["flags"] = int(flags); - payload["return_estate_wide"] = panelp->getChild("return_estate_wide")->getValue().asBoolean(); - LLNotificationsUtil::add("EstateObjectReturn", args, payload, - boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2)); + LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data; + if (panelp->mTargetAvatar.isNull()) return; + + LLSD args; + args["USER_NAME"] = panelp->getChild("target_avatar_name")->getValue().asString(); + LLSD payload; + payload["avatar_id"] = panelp->mTargetAvatar; + + U32 flags = SWD_ALWAYS_RETURN_OBJECTS; + + if (panelp->getChild("return_scripts")->getValue().asBoolean()) + { + flags |= SWD_SCRIPTED_ONLY; + } + + if (panelp->getChild("return_other_land")->getValue().asBoolean()) + { + flags |= SWD_OTHERS_LAND_ONLY; + } + payload["flags"] = int(flags); + payload["return_estate_wide"] = panelp->getChild("return_estate_wide")->getValue().asBoolean(); + LLNotificationsUtil::add("EstateObjectReturn", args, payload, + boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2)); } bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return false; - - LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID(); - if (!target_avatar.isNull()) - { - U32 flags = notification["payload"]["flags"].asInteger(); - bool return_estate_wide = notification["payload"]["return_estate_wide"]; - if (return_estate_wide) - { - // send as estate message - routed by spaceserver to all regions in estate - strings_t strings; - strings.push_back(llformat("%d", flags)); - strings.push_back(target_avatar.asString()); - - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - - sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings); - } - else - { - // send to this simulator only - send_sim_wide_deletes(target_avatar, flags); - } - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return false; + + LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID(); + if (!target_avatar.isNull()) + { + U32 flags = notification["payload"]["flags"].asInteger(); + bool return_estate_wide = notification["payload"]["return_estate_wide"]; + if (return_estate_wide) + { + // send as estate message - routed by spaceserver to all regions in estate + strings_t strings; + strings.push_back(llformat("%d", flags)); + strings.push_back(target_avatar.asString()); + + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + + sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings); + } + else + { + // send to this simulator only + send_sim_wide_deletes(target_avatar, flags); + } + } + return false; } // static void LLPanelRegionDebugInfo::onClickTopColliders(void* data) { - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; - strings_t strings; - strings.push_back("1"); // one physics step - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance("top_objects"); - if(!instance) return; - LLFloaterReg::showInstance("top_objects"); - instance->clearList(); - instance->disableRefreshBtn(); + LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; + strings_t strings; + strings.push_back("1"); // one physics step + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance("top_objects"); + if(!instance) return; + LLFloaterReg::showInstance("top_objects"); + instance->clearList(); + instance->disableRefreshBtn(); - self->getChildView("top_colliders_btn")->setEnabled(false); - self->getChildView("top_scripts_btn")->setEnabled(false); + self->getChildView("top_colliders_btn")->setEnabled(false); + self->getChildView("top_scripts_btn")->setEnabled(false); - self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings); + self->sendEstateOwnerMessage(gMessageSystem, "colliders", invoice, strings); } // static void LLPanelRegionDebugInfo::onClickTopScripts(void* data) { - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; - strings_t strings; - strings.push_back("6"); // top 5 scripts - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance("top_objects"); - if(!instance) return; - LLFloaterReg::showInstance("top_objects"); - instance->clearList(); - instance->disableRefreshBtn(); + LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; + strings_t strings; + strings.push_back("6"); // top 5 scripts + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + LLFloaterTopObjects* instance = LLFloaterReg::getTypedInstance("top_objects"); + if(!instance) return; + LLFloaterReg::showInstance("top_objects"); + instance->clearList(); + instance->disableRefreshBtn(); - self->getChildView("top_colliders_btn")->setEnabled(false); - self->getChildView("top_scripts_btn")->setEnabled(false); + self->getChildView("top_colliders_btn")->setEnabled(false); + self->getChildView("top_scripts_btn")->setEnabled(false); - self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings); + self->sendEstateOwnerMessage(gMessageSystem, "scripts", invoice, strings); } // static void LLPanelRegionDebugInfo::onClickRestart(void* data) { - LLNotificationsUtil::add("ConfirmRestart", LLSD(), LLSD(), - boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2)); + LLNotificationsUtil::add("ConfirmRestart", LLSD(), LLSD(), + boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2)); } bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return false; - strings_t strings; - strings.push_back("120"); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings); - return false; + strings_t strings; + strings.push_back("120"); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings); + return false; } // static void LLPanelRegionDebugInfo::onClickCancelRestart(void* data) { - LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; - strings_t strings; - strings.push_back("-1"); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings); + LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data; + strings_t strings; + strings.push_back("-1"); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + self->sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings); } // static void LLPanelRegionDebugInfo::onClickDebugConsole(void* data) { - LLFloaterReg::showInstance("region_debug_console"); + LLFloaterReg::showInstance("region_debug_console"); } bool LLPanelRegionTerrainInfo::validateTextureSizes() @@ -1325,30 +1325,30 @@ bool LLPanelRegionTerrainInfo::validateTextureSizes() bool valid = true; static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); const S32 max_terrain_texture_size = (S32)max_texture_resolution; - for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { LLTextureCtrl* texture_ctrl = mTextureDetailCtrl[i]; - if (!texture_ctrl) continue; - - LLUUID image_asset_id = texture_ctrl->getImageAssetID(); - LLViewerFetchedTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id); - S32 components = img->getComponents(); - // Must ask for highest resolution version's width. JC - S32 width = img->getFullWidth(); - S32 height = img->getFullHeight(); - - //LL_INFOS() << "texture detail " << i << " is " << width << "x" << height << "x" << components << LL_ENDL; - - if (components != 3 && components != 4) - { - LLSD args; - args["TEXTURE_NUM"] = i+1; - args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); + if (!texture_ctrl) continue; + + LLUUID image_asset_id = texture_ctrl->getImageAssetID(); + LLViewerFetchedTexture* img = LLViewerTextureManager::getFetchedTexture(image_asset_id); + S32 components = img->getComponents(); + // Must ask for highest resolution version's width. JC + S32 width = img->getFullWidth(); + S32 height = img->getFullHeight(); + + //LL_INFOS() << "texture detail " << i << " is " << width << "x" << height << "x" << components << LL_ENDL; + + if (components != 3 && components != 4) + { + LLSD args; + args["TEXTURE_NUM"] = i+1; + args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); args["MAX_SIZE"] = max_terrain_texture_size; - LLNotificationsUtil::add("InvalidTerrainBitDepth", args); + LLNotificationsUtil::add("InvalidTerrainBitDepth", args); valid = false; - continue; - } + continue; + } if (components == 4) { @@ -1380,20 +1380,20 @@ bool LLPanelRegionTerrainInfo::validateTextureSizes() } } - if (width > max_terrain_texture_size || height > max_terrain_texture_size) - { + if (width > max_terrain_texture_size || height > max_terrain_texture_size) + { - LLSD args; - args["TEXTURE_NUM"] = i+1; - args["TEXTURE_SIZE_X"] = width; - args["TEXTURE_SIZE_Y"] = height; + LLSD args; + args["TEXTURE_NUM"] = i+1; + args["TEXTURE_SIZE_X"] = width; + args["TEXTURE_SIZE_Y"] = height; args["MAX_SIZE"] = max_terrain_texture_size; - LLNotificationsUtil::add("InvalidTerrainSize", args); - valid = false; - } - } + LLNotificationsUtil::add("InvalidTerrainSize", args); + valid = false; + } + } - return valid; + return valid; } bool LLPanelRegionTerrainInfo::validateMaterials() @@ -1470,18 +1470,18 @@ bool LLPanelRegionTerrainInfo::validateMaterials() BOOL LLPanelRegionTerrainInfo::validateTextureHeights() { - for (S32 i = 0; i < CORNER_COUNT; ++i) - { - std::string low = llformat("height_start_spin_%d", i); - std::string high = llformat("height_range_spin_%d", i); + for (S32 i = 0; i < CORNER_COUNT; ++i) + { + std::string low = llformat("height_start_spin_%d", i); + std::string high = llformat("height_range_spin_%d", i); - if (getChild(low)->getValue().asReal() > getChild(high)->getValue().asReal()) - { - return FALSE; - } - } + if (getChild(low)->getValue().asReal() > getChild(high)->getValue().asReal()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } ///////////////////////////////////////////////////////////////////////////// @@ -1506,46 +1506,46 @@ LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo() BOOL LLPanelRegionTerrainInfo::postBuild() { - LLPanelRegionInfo::postBuild(); - - initCtrl("water_height_spin"); - initCtrl("terrain_raise_spin"); - initCtrl("terrain_lower_spin"); + LLPanelRegionInfo::postBuild(); + + initCtrl("water_height_spin"); + initCtrl("terrain_raise_spin"); + initCtrl("terrain_lower_spin"); mMaterialTypeCtrl = findChild("terrain_material_type"); if (mMaterialTypeCtrl) { mMaterialTypeCtrl->setCommitCallback(boost::bind(&LLPanelRegionTerrainInfo::onSelectMaterialType, this)); } - std::string buffer; + std::string buffer; - for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { - buffer = llformat("texture_detail_%d", i); - initCtrl(buffer); + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + buffer = llformat("texture_detail_%d", i); + initCtrl(buffer); mTextureDetailCtrl[i] = findChild(buffer); - } - for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - initCtrl(buffer); + } + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + buffer = llformat("material_detail_%d", i); + initCtrl(buffer); mMaterialDetailCtrl[i] = findChild(buffer); - } + } - for(S32 i = 0; i < CORNER_COUNT; ++i) - { - buffer = llformat("height_start_spin_%d", i); - initCtrl(buffer); - buffer = llformat("height_range_spin_%d", i); - initCtrl(buffer); - } + for(S32 i = 0; i < CORNER_COUNT; ++i) + { + buffer = llformat("height_start_spin_%d", i); + initCtrl(buffer); + buffer = llformat("height_range_spin_%d", i); + initCtrl(buffer); + } - childSetAction("download_raw_btn", onClickDownloadRaw, this); - childSetAction("upload_raw_btn", onClickUploadRaw, this); - childSetAction("bake_terrain_btn", onClickBakeTerrain, this); + childSetAction("download_raw_btn", onClickDownloadRaw, this); + childSetAction("upload_raw_btn", onClickUploadRaw, this); + childSetAction("bake_terrain_btn", onClickBakeTerrain, this); - mAskedTextureHeights = false; - mConfirmedTextureHeights = false; + mAskedTextureHeights = false; + mConfirmedTextureHeights = false; - return LLPanelRegionInfo::postBuild(); + return LLPanelRegionInfo::postBuild(); } void LLPanelRegionTerrainInfo::onSelectMaterialType() @@ -1581,9 +1581,9 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() // Toggle visibility of labels LLUICtrl* texture_label = findChild("detail_texture_text"); - if (texture_label) { texture_label->setVisible(show_texture_controls); } + if (texture_label) { texture_label->setVisible(show_texture_controls); } LLUICtrl* material_label = findChild("detail_material_text"); - if (material_label) { material_label->setVisible(show_material_controls); } + if (material_label) { material_label->setVisible(show_material_controls); } // Toggle visibility of documentation labels for terrain blending ranges const std::vector doc_suffixes { "5", "10", "11" }; @@ -1602,19 +1602,19 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() // virtual bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) { - BOOL owner_or_god = gAgent.isGodlike() - || (region && (region->getOwner() == gAgent.getID())); - BOOL owner_or_god_or_manager = owner_or_god - || (region && region->isEstateManager()); - setCtrlsEnabled(owner_or_god_or_manager); + BOOL owner_or_god = gAgent.isGodlike() + || (region && (region->getOwner() == gAgent.getID())); + BOOL owner_or_god_or_manager = owner_or_god + || (region && region->isEstateManager()); + setCtrlsEnabled(owner_or_god_or_manager); - getChildView("apply_btn")->setEnabled(FALSE); + getChildView("apply_btn")->setEnabled(FALSE); - if (region) - { - getChild("region_text")->setValue(LLSD(region->getName())); + if (region) + { + getChild("region_text")->setValue(LLSD(region->getName())); - LLVLComposition* compp = region->getComposition(); + LLVLComposition* compp = region->getComposition(); static LLCachedControl feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); @@ -1707,42 +1707,42 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) } } - std::string buffer; - for(S32 i = 0; i < CORNER_COUNT; ++i) - { - buffer = llformat("height_start_spin_%d", i); - getChild(buffer)->setValue(LLSD(compp->getStartHeight(i))); - buffer = llformat("height_range_spin_%d", i); - getChild(buffer)->setValue(LLSD(compp->getHeightRange(i))); - } - } - else - { - LL_DEBUGS() << "no region set" << LL_ENDL; - getChild("region_text")->setValue(LLSD("")); - } - + std::string buffer; + for(S32 i = 0; i < CORNER_COUNT; ++i) + { + buffer = llformat("height_start_spin_%d", i); + getChild(buffer)->setValue(LLSD(compp->getStartHeight(i))); + buffer = llformat("height_range_spin_%d", i); + getChild(buffer)->setValue(LLSD(compp->getHeightRange(i))); + } + } + else + { + LL_DEBUGS() << "no region set" << LL_ENDL; + getChild("region_text")->setValue(LLSD("")); + } + // Update visibility of terrain swatches, etc refresh(); - getChildView("download_raw_btn")->setEnabled(owner_or_god); - getChildView("upload_raw_btn")->setEnabled(owner_or_god); - getChildView("bake_terrain_btn")->setEnabled(owner_or_god); + getChildView("download_raw_btn")->setEnabled(owner_or_god); + getChildView("upload_raw_btn")->setEnabled(owner_or_god); + getChildView("bake_terrain_btn")->setEnabled(owner_or_god); - return LLPanelRegionInfo::refreshFromRegion(region); + return LLPanelRegionInfo::refreshFromRegion(region); } // virtual BOOL LLPanelRegionTerrainInfo::sendUpdate() { - LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL; + LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL; - // Make sure user hasn't chosen wacky textures. - if (!validateTextureSizes()) - { - return FALSE; - } + // Make sure user hasn't chosen wacky textures. + if (!validateTextureSizes()) + { + return FALSE; + } // Prevent applying unsupported alpha blend/double-sided materials if (!validateMaterials()) @@ -1750,20 +1750,20 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() return FALSE; } - // Check if terrain Elevation Ranges are correct - if (gSavedSettings.getBOOL("RegionCheckTextureHeights") && !validateTextureHeights()) - { - if (!mAskedTextureHeights) - { - LLNotificationsUtil::add("ConfirmTextureHeights", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackTextureHeights, this, _1, _2)); - mAskedTextureHeights = true; - return FALSE; - } - else if (!mConfirmedTextureHeights) - { - return FALSE; - } - } + // Check if terrain Elevation Ranges are correct + if (gSavedSettings.getBOOL("RegionCheckTextureHeights") && !validateTextureHeights()) + { + if (!mAskedTextureHeights) + { + LLNotificationsUtil::add("ConfirmTextureHeights", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackTextureHeights, this, _1, _2)); + mAskedTextureHeights = true; + return FALSE; + } + else if (!mConfirmedTextureHeights) + { + return FALSE; + } + } std::string buffer; strings_t strings; @@ -1781,8 +1781,8 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() // ======================================= // Assemble and send texturedetail message - std::string id_str; - LLMessageSystem* msg = gMessageSystem; + std::string id_str; + LLMessageSystem* msg = gMessageSystem; // Send either material IDs instead of texture IDs depending on // material_type - they both occupy the same slot. @@ -1816,145 +1816,145 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() mLastSetTextures[i] = tmp_id; } } - sendEstateOwnerMessage(msg, "texturedetail", invoice, strings); - strings.clear(); + sendEstateOwnerMessage(msg, "texturedetail", invoice, strings); + strings.clear(); - // ======================================== - // Assemble and send textureheights message + // ======================================== + // Assemble and send textureheights message - for(S32 i = 0; i < CORNER_COUNT; ++i) - { - buffer = llformat("height_start_spin_%d", i); - std::string buffer2 = llformat("height_range_spin_%d", i); - std::string buffer3 = llformat("%d %f %f", i, (F32)getChild(buffer)->getValue().asReal(), (F32)getChild(buffer2)->getValue().asReal()); - strings.push_back(buffer3); - } - sendEstateOwnerMessage(msg, "textureheights", invoice, strings); - strings.clear(); + for(S32 i = 0; i < CORNER_COUNT; ++i) + { + buffer = llformat("height_start_spin_%d", i); + std::string buffer2 = llformat("height_range_spin_%d", i); + std::string buffer3 = llformat("%d %f %f", i, (F32)getChild(buffer)->getValue().asReal(), (F32)getChild(buffer2)->getValue().asReal()); + strings.push_back(buffer3); + } + sendEstateOwnerMessage(msg, "textureheights", invoice, strings); + strings.clear(); - // ======================================== - // Send texturecommit message + // ======================================== + // Send texturecommit message - sendEstateOwnerMessage(msg, "texturecommit", invoice, strings); + sendEstateOwnerMessage(msg, "texturecommit", invoice, strings); - return TRUE; + return TRUE; } bool LLPanelRegionTerrainInfo::callbackTextureHeights(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) // ok - { - mConfirmedTextureHeights = true; - } - else if (option == 1) // cancel - { - mConfirmedTextureHeights = false; - } - else if (option == 2) // don't ask - { - gSavedSettings.setBOOL("RegionCheckTextureHeights", FALSE); - mConfirmedTextureHeights = true; - } + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // ok + { + mConfirmedTextureHeights = true; + } + else if (option == 1) // cancel + { + mConfirmedTextureHeights = false; + } + else if (option == 2) // don't ask + { + gSavedSettings.setBOOL("RegionCheckTextureHeights", FALSE); + mConfirmedTextureHeights = true; + } - onBtnSet(); + onBtnSet(); - mAskedTextureHeights = false; - return false; + mAskedTextureHeights = false; + return false; } // static void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(LLFilePicker::FFSAVE_RAW, "terrain.raw")) - { - LL_WARNS() << "No file" << LL_ENDL; - return; - } - std::string filepath = picker.getFirstFile(); - gXferManager->expectFileForRequest(filepath); + LLFilePicker& picker = LLFilePicker::instance(); + if (!picker.getSaveFile(LLFilePicker::FFSAVE_RAW, "terrain.raw")) + { + LL_WARNS() << "No file" << LL_ENDL; + return; + } + std::string filepath = picker.getFirstFile(); + gXferManager->expectFileForRequest(filepath); - LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; - strings_t strings; - strings.push_back("download filename"); - strings.push_back(filepath); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); + LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; + strings_t strings; + strings.push_back("download filename"); + strings.push_back(filepath); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); } // static void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(LLFilePicker::FFLOAD_RAW)) - { - LL_WARNS() << "No file" << LL_ENDL; - return; - } - std::string filepath = picker.getFirstFile(); - gXferManager->expectFileForTransfer(filepath); + LLFilePicker& picker = LLFilePicker::instance(); + if (!picker.getOpenFile(LLFilePicker::FFLOAD_RAW)) + { + LL_WARNS() << "No file" << LL_ENDL; + return; + } + std::string filepath = picker.getFirstFile(); + gXferManager->expectFileForTransfer(filepath); - LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; - strings_t strings; - strings.push_back("upload filename"); - strings.push_back(filepath); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); + LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; + strings_t strings; + strings.push_back("upload filename"); + strings.push_back(filepath); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); - LLNotificationsUtil::add("RawUploadStarted"); + LLNotificationsUtil::add("RawUploadStarted"); } // static void LLPanelRegionTerrainInfo::onClickBakeTerrain(void* data) { - LLNotificationsUtil::add("ConfirmBakeTerrain", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2)); + LLNotificationsUtil::add("ConfirmBakeTerrain", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2)); } bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return false; - strings_t strings; - strings.push_back("bake"); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); + strings_t strings; + strings.push_back("bake"); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); - return false; + return false; } ///////////////////////////////////////////////////////////////////////////// // LLPanelEstateInfo // -LLPanelEstateInfo::LLPanelEstateInfo() -: LLPanelRegionInfo(), - mEstateID(0) // invalid +LLPanelEstateInfo::LLPanelEstateInfo() +: LLPanelRegionInfo(), + mEstateID(0) // invalid { - LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - estate_info.setCommitCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this)); - estate_info.setUpdateCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this)); + LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + estate_info.setCommitCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this)); + estate_info.setUpdateCallback(boost::bind(&LLPanelEstateInfo::refreshFromEstate, this)); } // static void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch) { - std::string name; - - name.assign("estateupdateinfo"); - static LLDispatchEstateUpdateInfo estate_update_info; - dispatch.addHandler(name, &estate_update_info); + std::string name; + + name.assign("estateupdateinfo"); + static LLDispatchEstateUpdateInfo estate_update_info; + dispatch.addHandler(name, &estate_update_info); - name.assign("setaccess"); - static LLDispatchSetEstateAccess set_access; - dispatch.addHandler(name, &set_access); + name.assign("setaccess"); + static LLDispatchSetEstateAccess set_access; + dispatch.addHandler(name, &set_access); - name.assign("setexperience"); - static LLDispatchSetEstateExperience set_experience; - dispatch.addHandler(name, &set_experience); + name.assign("setexperience"); + static LLDispatchSetEstateExperience set_experience; + dispatch.addHandler(name, &set_experience); - estate_dispatch_initialized = true; + estate_dispatch_initialized = true; } //--------------------------------------------------------------------------- @@ -1963,49 +1963,49 @@ void LLPanelEstateInfo::initDispatch(LLDispatcher& dispatch) void LLPanelEstateInfo::onClickKickUser() { - // this depends on the grandparent view being a floater - // in order to set up floater dependency + // this depends on the grandparent view being a floater + // in order to set up floater dependency LLView * button = findChild("kick_user_from_estate_btn"); - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateInfo::onKickUserCommit, this, _1), FALSE, TRUE, FALSE, parent_floater->getName(), button); - if (child_floater) - { - parent_floater->addDependentFloater(child_floater); - } + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } } void LLPanelEstateInfo::onKickUserCommit(const uuid_vec_t& ids) { - if (ids.empty()) return; - - //Bring up a confirmation dialog - LLSD args; - args["EVIL_USER"] = LLSLURL("agent", ids[0], "completename").getSLURLString(); - LLSD payload; - payload["agent_id"] = ids[0]; - LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2)); + if (ids.empty()) return; + + //Bring up a confirmation dialog + LLSD args; + args["EVIL_USER"] = LLSLURL("agent", ids[0], "completename").getSLURLString(); + LLSD payload; + payload["agent_id"] = ids[0]; + LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, this, _1, _2)); } bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch(option) - { - case 0: - { - //Kick User - strings_t strings; - strings.push_back(notification["payload"]["agent_id"].asString()); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: + { + //Kick User + strings_t strings; + strings.push_back(notification["payload"]["agent_id"].asString()); - sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings); - break; - } - default: - break; - } - return false; + sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings); + break; + } + default: + break; + } + return false; } //--------------------------------------------------------------------------- @@ -2016,270 +2016,270 @@ bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& re //--------------------------------------------------------------------------- std::string all_estates_text() { - LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); - if (!panel) return "(" + LLTrans::getString("RegionInfoError") + ")"; - - LLStringUtil::format_map_t args; - std::string owner = panel->getOwnerName(); - - LLViewerRegion* region = gAgent.getRegion(); - if (gAgent.isGodlike()) - { - args["[OWNER]"] = owner.c_str(); - return LLTrans::getString("RegionInfoAllEstatesOwnedBy", args); - } - else if (region && region->getOwner() == gAgent.getID()) - { - return LLTrans::getString("RegionInfoAllEstatesYouOwn"); - } - else if (region && region->isEstateManager()) - { - args["[OWNER]"] = owner.c_str(); - return LLTrans::getString("RegionInfoAllEstatesYouManage", args); - } - else - { - return "(" + LLTrans::getString("RegionInfoError") + ")"; - } + LLPanelEstateInfo* panel = LLFloaterRegionInfo::getPanelEstate(); + if (!panel) return "(" + LLTrans::getString("RegionInfoError") + ")"; + + LLStringUtil::format_map_t args; + std::string owner = panel->getOwnerName(); + + LLViewerRegion* region = gAgent.getRegion(); + if (gAgent.isGodlike()) + { + args["[OWNER]"] = owner.c_str(); + return LLTrans::getString("RegionInfoAllEstatesOwnedBy", args); + } + else if (region && region->getOwner() == gAgent.getID()) + { + return LLTrans::getString("RegionInfoAllEstatesYouOwn"); + } + else if (region && region->isEstateManager()) + { + args["[OWNER]"] = owner.c_str(); + return LLTrans::getString("RegionInfoAllEstatesYouManage", args); + } + else + { + return "(" + LLTrans::getString("RegionInfoError") + ")"; + } } // static bool LLPanelEstateInfo::isLindenEstate() { - U32 estate_id = LLEstateInfoModel::instance().getID(); - return (estate_id <= ESTATE_LAST_LINDEN); + U32 estate_id = LLEstateInfoModel::instance().getID(); + return (estate_id <= ESTATE_LAST_LINDEN); } struct LLEstateAccessChangeInfo { - LLEstateAccessChangeInfo(const LLSD& sd) - { - mDialogName = sd["dialog_name"].asString(); - mOperationFlag = (U32)sd["operation"].asInteger(); - LLSD::array_const_iterator end_it = sd["allowed_ids"].endArray(); - for (LLSD::array_const_iterator id_it = sd["allowed_ids"].beginArray(); - id_it != end_it; - ++id_it) - { - mAgentOrGroupIDs.push_back(id_it->asUUID()); - } - } - - const LLSD asLLSD() const - { - LLSD sd; - sd["name"] = mDialogName; - sd["operation"] = (S32)mOperationFlag; - for (U32 i = 0; i < mAgentOrGroupIDs.size(); ++i) - { - sd["allowed_ids"].append(mAgentOrGroupIDs[i]); - if (mAgentNames.size() > i) - { - sd["allowed_names"].append(mAgentNames[i].asLLSD()); - } - } - return sd; - } - - U32 mOperationFlag; // ESTATE_ACCESS_BANNED_AGENT_ADD, _REMOVE, etc. - std::string mDialogName; - uuid_vec_t mAgentOrGroupIDs; // List of agent IDs to apply to this change - std::vector mAgentNames; // Optional list of the agent names for notifications + LLEstateAccessChangeInfo(const LLSD& sd) + { + mDialogName = sd["dialog_name"].asString(); + mOperationFlag = (U32)sd["operation"].asInteger(); + LLSD::array_const_iterator end_it = sd["allowed_ids"].endArray(); + for (LLSD::array_const_iterator id_it = sd["allowed_ids"].beginArray(); + id_it != end_it; + ++id_it) + { + mAgentOrGroupIDs.push_back(id_it->asUUID()); + } + } + + const LLSD asLLSD() const + { + LLSD sd; + sd["name"] = mDialogName; + sd["operation"] = (S32)mOperationFlag; + for (U32 i = 0; i < mAgentOrGroupIDs.size(); ++i) + { + sd["allowed_ids"].append(mAgentOrGroupIDs[i]); + if (mAgentNames.size() > i) + { + sd["allowed_names"].append(mAgentNames[i].asLLSD()); + } + } + return sd; + } + + U32 mOperationFlag; // ESTATE_ACCESS_BANNED_AGENT_ADD, _REMOVE, etc. + std::string mDialogName; + uuid_vec_t mAgentOrGroupIDs; // List of agent IDs to apply to this change + std::vector mAgentNames; // Optional list of the agent names for notifications }; // static void LLPanelEstateInfo::updateEstateOwnerName(const std::string& name) { - LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); - if (panelp) - { - panelp->setOwnerName(name); - } + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) + { + panelp->setOwnerName(name); + } } // static void LLPanelEstateInfo::updateEstateName(const std::string& name) { - LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); - if (panelp) - { - panelp->getChildRef("estate_name").setText(name); - } + LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate(); + if (panelp) + { + panelp->getChildRef("estate_name").setText(name); + } } void LLPanelEstateInfo::updateControls(LLViewerRegion* region) { - BOOL god = gAgent.isGodlike(); - BOOL owner = (region && (region->getOwner() == gAgent.getID())); - BOOL manager = (region && region->isEstateManager()); - setCtrlsEnabled(god || owner || manager); - - getChildView("apply_btn")->setEnabled(FALSE); + BOOL god = gAgent.isGodlike(); + BOOL owner = (region && (region->getOwner() == gAgent.getID())); + BOOL manager = (region && region->isEstateManager()); + setCtrlsEnabled(god || owner || manager); + + getChildView("apply_btn")->setEnabled(FALSE); getChildView("estate_owner")->setEnabled(TRUE); - getChildView("message_estate_btn")->setEnabled(god || owner || manager); - getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); + getChildView("message_estate_btn")->setEnabled(god || owner || manager); + getChildView("kick_user_from_estate_btn")->setEnabled(god || owner || manager); - refresh(); + refresh(); } bool LLPanelEstateInfo::refreshFromRegion(LLViewerRegion* region) { - updateControls(region); - - // let the parent class handle the general data collection. - bool rv = LLPanelRegionInfo::refreshFromRegion(region); + updateControls(region); + + // let the parent class handle the general data collection. + bool rv = LLPanelRegionInfo::refreshFromRegion(region); + + // We want estate info. To make sure it works across region + // boundaries and multiple packets, we add a serial number to the + // integers and track against that on update. + strings_t strings; + //integers_t integers; + //LLFloaterRegionInfo::incrementSerial(); + LLFloaterRegionInfo::nextInvoice(); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + //integers.push_back(LLFloaterRegionInfo::());::getPanelEstate(); - // We want estate info. To make sure it works across region - // boundaries and multiple packets, we add a serial number to the - // integers and track against that on update. - strings_t strings; - //integers_t integers; - //LLFloaterRegionInfo::incrementSerial(); - LLFloaterRegionInfo::nextInvoice(); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - //integers.push_back(LLFloaterRegionInfo::());::getPanelEstate(); - - sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings); + sendEstateOwnerMessage(gMessageSystem, "getinfo", invoice, strings); - refresh(); + refresh(); - return rv; + return rv; } void LLPanelEstateInfo::updateChild(LLUICtrl* child_ctrl) { - // Ensure appropriate state of the management ui. - updateControls(gAgent.getRegion()); + // Ensure appropriate state of the management ui. + updateControls(gAgent.getRegion()); } bool LLPanelEstateInfo::estateUpdate(LLMessageSystem* msg) { - LL_INFOS() << "LLPanelEstateInfo::estateUpdate()" << LL_ENDL; - return false; + LL_INFOS() << "LLPanelEstateInfo::estateUpdate()" << LL_ENDL; + return false; } BOOL LLPanelEstateInfo::postBuild() { - // set up the callbacks for the generic controls - initCtrl("externally_visible_radio"); - initCtrl("allow_direct_teleport"); - initCtrl("limit_payment"); - initCtrl("limit_age_verified"); + // set up the callbacks for the generic controls + initCtrl("externally_visible_radio"); + initCtrl("allow_direct_teleport"); + initCtrl("limit_payment"); + initCtrl("limit_age_verified"); initCtrl("limit_bots"); - initCtrl("voice_chat_check"); + initCtrl("voice_chat_check"); initCtrl("parcel_access_override"); - childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this)); - childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this)); + childSetAction("message_estate_btn", boost::bind(&LLPanelEstateInfo::onClickMessageEstate, this)); + childSetAction("kick_user_from_estate_btn", boost::bind(&LLPanelEstateInfo::onClickKickUser, this)); - getChild("parcel_access_override")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAccessOverride, this)); + getChild("parcel_access_override")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAccessOverride, this)); - getChild("externally_visible_radio")->setFocus(TRUE); + getChild("externally_visible_radio")->setFocus(TRUE); getChild("estate_owner")->setIsFriendCallback(LLAvatarActions::isFriend); - return LLPanelRegionInfo::postBuild(); + return LLPanelRegionInfo::postBuild(); } void LLPanelEstateInfo::refresh() { - // Disable access restriction controls if they make no sense. - bool public_access = ("estate_public_access" == getChild("externally_visible_radio")->getValue().asString()); + // Disable access restriction controls if they make no sense. + bool public_access = ("estate_public_access" == getChild("externally_visible_radio")->getValue().asString()); - getChildView("Only Allow")->setEnabled(public_access); - getChildView("limit_payment")->setEnabled(public_access); - getChildView("limit_age_verified")->setEnabled(public_access); + getChildView("Only Allow")->setEnabled(public_access); + getChildView("limit_payment")->setEnabled(public_access); + getChildView("limit_age_verified")->setEnabled(public_access); getChildView("limit_bots")->setEnabled(public_access); - // if this is set to false, then the limit fields are meaningless and should be turned off - if (public_access == false) - { - getChild("limit_payment")->setValue(false); - getChild("limit_age_verified")->setValue(false); + // if this is set to false, then the limit fields are meaningless and should be turned off + if (public_access == false) + { + getChild("limit_payment")->setValue(false); + getChild("limit_age_verified")->setValue(false); getChild("limit_bots")->setValue(false); - } + } } void LLPanelEstateInfo::refreshFromEstate() { - const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + const LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - getChild("estate_name")->setValue(estate_info.getName()); - setOwnerName(LLSLURL("agent", estate_info.getOwnerID(), "inspect").getSLURLString()); + getChild("estate_name")->setValue(estate_info.getName()); + setOwnerName(LLSLURL("agent", estate_info.getOwnerID(), "inspect").getSLURLString()); - getChild("externally_visible_radio")->setValue(estate_info.getIsExternallyVisible() ? "estate_public_access" : "estate_restricted_access"); - getChild("voice_chat_check")->setValue(estate_info.getAllowVoiceChat()); - getChild("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport()); - getChild("limit_payment")->setValue(estate_info.getDenyAnonymous()); - getChild("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); + getChild("externally_visible_radio")->setValue(estate_info.getIsExternallyVisible() ? "estate_public_access" : "estate_restricted_access"); + getChild("voice_chat_check")->setValue(estate_info.getAllowVoiceChat()); + getChild("allow_direct_teleport")->setValue(estate_info.getAllowDirectTeleport()); + getChild("limit_payment")->setValue(estate_info.getDenyAnonymous()); + getChild("limit_age_verified")->setValue(estate_info.getDenyAgeUnverified()); getChild("parcel_access_override")->setValue(estate_info.getAllowAccessOverride()); getChild("limit_bots")->setValue(estate_info.getDenyScriptedAgents()); - // Ensure appriopriate state of the management UI - updateControls(gAgent.getRegion()); - refresh(); + // Ensure appriopriate state of the management UI + updateControls(gAgent.getRegion()); + refresh(); } BOOL LLPanelEstateInfo::sendUpdate() { - LL_INFOS() << "LLPanelEsateInfo::sendUpdate()" << LL_ENDL; + LL_INFOS() << "LLPanelEsateInfo::sendUpdate()" << LL_ENDL; - LLNotification::Params params("ChangeLindenEstate"); - params.functor.function(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); + LLNotification::Params params("ChangeLindenEstate"); + params.functor.function(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2)); - if (isLindenEstate()) - { - // trying to change reserved estate, warn - LLNotifications::instance().add(params); - } - else - { - // for normal estates, just make the change - LLNotifications::instance().forceResponse(params, 0); - } - return TRUE; + if (isLindenEstate()) + { + // trying to change reserved estate, warn + LLNotifications::instance().add(params); + } + else + { + // for normal estates, just make the change + LLNotifications::instance().forceResponse(params, 0); + } + return TRUE; } bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch(option) - { - case 0: - { - LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); - - // update model - estate_info.setUseFixedSun(false); // we don't support fixed sun estates anymore - estate_info.setIsExternallyVisible("estate_public_access" == getChild("externally_visible_radio")->getValue().asString()); - estate_info.setAllowDirectTeleport(getChild("allow_direct_teleport")->getValue().asBoolean()); - estate_info.setDenyAnonymous(getChild("limit_payment")->getValue().asBoolean()); - estate_info.setDenyAgeUnverified(getChild("limit_age_verified")->getValue().asBoolean()); - estate_info.setAllowVoiceChat(getChild("voice_chat_check")->getValue().asBoolean()); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: + { + LLEstateInfoModel& estate_info = LLEstateInfoModel::instance(); + + // update model + estate_info.setUseFixedSun(false); // we don't support fixed sun estates anymore + estate_info.setIsExternallyVisible("estate_public_access" == getChild("externally_visible_radio")->getValue().asString()); + estate_info.setAllowDirectTeleport(getChild("allow_direct_teleport")->getValue().asBoolean()); + estate_info.setDenyAnonymous(getChild("limit_payment")->getValue().asBoolean()); + estate_info.setDenyAgeUnverified(getChild("limit_age_verified")->getValue().asBoolean()); + estate_info.setAllowVoiceChat(getChild("voice_chat_check")->getValue().asBoolean()); estate_info.setAllowAccessOverride(getChild("parcel_access_override")->getValue().asBoolean()); estate_info.setDenyScriptedAgents(getChild("limit_bots")->getValue().asBoolean()); // JIGGLYPUFF //estate_info.setAllowAccessOverride(getChild("")->getValue().asBoolean()); - // send the update to sim - estate_info.sendEstateInfo(); - } - - // we don't want to do this because we'll get it automatically from the sim - // after the spaceserver processes it -// else -// { -// // caps method does not automatically send this info -// LLFloaterRegionInfo::requestRegionInfo(); -// } - break; - case 1: - default: - // do nothing - break; - } - return false; + // send the update to sim + estate_info.sendEstateInfo(); + } + + // we don't want to do this because we'll get it automatically from the sim + // after the spaceserver processes it +// else +// { +// // caps method does not automatically send this info +// LLFloaterRegionInfo::requestRegionInfo(); +// } + break; + case 1: + default: + // do nothing + break; + } + return false; } @@ -2289,326 +2289,326 @@ bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, con // IParam[0] = serial void LLPanelEstateInfo::getEstateOwner() { - // TODO -- disable the panel - // and call this function whenever we cross a region boundary - // re-enable when owner matches, and get new estate info - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_EstateOwnerRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + // TODO -- disable the panel + // and call this function whenever we cross a region boundary + // re-enable when owner matches, and get new estate info + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_EstateOwnerRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->nextBlockFast(_PREHASH_RequestData); - msg->addStringFast(_PREHASH_Request, "getowner"); + msg->nextBlockFast(_PREHASH_RequestData); + msg->addStringFast(_PREHASH_Request, "getowner"); - // we send an empty string so that the variable block is not empty - msg->nextBlockFast(_PREHASH_StringData); - msg->addStringFast(_PREHASH_SParam, ""); + // we send an empty string so that the variable block is not empty + msg->nextBlockFast(_PREHASH_StringData); + msg->addStringFast(_PREHASH_SParam, ""); - msg->nextBlockFast(_PREHASH_IntegerData); - msg->addS32Fast(_PREHASH_IParam, LLFloaterRegionInfo::getSerial()); + msg->nextBlockFast(_PREHASH_IntegerData); + msg->addS32Fast(_PREHASH_IParam, LLFloaterRegionInfo::getSerial()); - gAgent.sendMessage(); + gAgent.sendMessage(); } */ const std::string LLPanelEstateInfo::getOwnerName() const { - return getChild("estate_owner")->getValue().asString(); + return getChild("estate_owner")->getValue().asString(); } void LLPanelEstateInfo::setOwnerName(const std::string& name) { - getChild("estate_owner")->setValue(LLSD(name)); + getChild("estate_owner")->setValue(LLSD(name)); } // static void LLPanelEstateInfo::onClickMessageEstate(void* userdata) { - LL_INFOS() << "LLPanelEstateInfo::onClickMessageEstate" << LL_ENDL; - LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); + LL_INFOS() << "LLPanelEstateInfo::onClickMessageEstate" << LL_ENDL; + LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); } bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - std::string text = response["message"].asString(); - if(option != 0) return false; - if(text.empty()) return false; - LL_INFOS() << "Message to everyone: " << text << LL_ENDL; - strings_t strings; - //integers_t integers; - std::string name; - LLAgentUI::buildFullname(name); - strings.push_back(strings_t::value_type(name)); - strings.push_back(strings_t::value_type(text)); - LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings); - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + std::string text = response["message"].asString(); + if(option != 0) return false; + if(text.empty()) return false; + LL_INFOS() << "Message to everyone: " << text << LL_ENDL; + strings_t strings; + //integers_t integers; + std::string name; + LLAgentUI::buildFullname(name); + strings.push_back(strings_t::value_type(name)); + strings.push_back(strings_t::value_type(text)); + LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); + sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings); + return false; } void LLPanelEstateInfo::onChangeAccessOverride() { - if (!getChild("parcel_access_override")->getValue().asBoolean()) - { - LLNotificationsUtil::add("EstateParcelAccessOverride"); - } + if (!getChild("parcel_access_override")->getValue().asBoolean()) + { + LLNotificationsUtil::add("EstateParcelAccessOverride"); + } } LLPanelEstateCovenant::LLPanelEstateCovenant() - : - mCovenantID(LLUUID::null), - mAssetStatus(ASSET_ERROR) + : + mCovenantID(LLUUID::null), + mAssetStatus(ASSET_ERROR) { } -// virtual +// virtual bool LLPanelEstateCovenant::refreshFromRegion(LLViewerRegion* region) { - LLTextBox* region_name = getChild("region_name_text"); - if (region_name) - { - region_name->setText(region->getName()); - } - - LLTextBox* resellable_clause = getChild("resellable_clause"); - if (resellable_clause) - { - if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) - { - resellable_clause->setText(getString("can_not_resell")); - } - else - { - resellable_clause->setText(getString("can_resell")); - } - } - - LLTextBox* changeable_clause = getChild("changeable_clause"); - if (changeable_clause) - { - if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) - { - changeable_clause->setText(getString("can_change")); - } - else - { - changeable_clause->setText(getString("can_not_change")); - } - } - - LLTextBox* region_maturity = getChild("region_maturity_text"); - if (region_maturity) - { - region_maturity->setText(region->getSimAccessString()); - } - - LLTextBox* region_landtype = getChild("region_landtype_text"); - region_landtype->setText(region->getLocalizedSimProductName()); + LLTextBox* region_name = getChild("region_name_text"); + if (region_name) + { + region_name->setText(region->getName()); + } + + LLTextBox* resellable_clause = getChild("resellable_clause"); + if (resellable_clause) + { + if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL)) + { + resellable_clause->setText(getString("can_not_resell")); + } + else + { + resellable_clause->setText(getString("can_resell")); + } + } + + LLTextBox* changeable_clause = getChild("changeable_clause"); + if (changeable_clause) + { + if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES)) + { + changeable_clause->setText(getString("can_change")); + } + else + { + changeable_clause->setText(getString("can_not_change")); + } + } + + LLTextBox* region_maturity = getChild("region_maturity_text"); + if (region_maturity) + { + region_maturity->setText(region->getSimAccessString()); + } + + LLTextBox* region_landtype = getChild("region_landtype_text"); + region_landtype->setText(region->getLocalizedSimProductName()); getChild("reset_covenant")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate())); - - // let the parent class handle the general data collection. - bool rv = LLPanelRegionInfo::refreshFromRegion(region); - LLMessageSystem *msg = gMessageSystem; - msg->newMessage("EstateCovenantRequest"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); - msg->sendReliable(region->getHost()); - return rv; -} - -// virtual + + // let the parent class handle the general data collection. + bool rv = LLPanelRegionInfo::refreshFromRegion(region); + LLMessageSystem *msg = gMessageSystem; + msg->newMessage("EstateCovenantRequest"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID()); + msg->sendReliable(region->getHost()); + return rv; +} + +// virtual bool LLPanelEstateCovenant::estateUpdate(LLMessageSystem* msg) { - LL_INFOS() << "LLPanelEstateCovenant::estateUpdate()" << LL_ENDL; - return true; + LL_INFOS() << "LLPanelEstateCovenant::estateUpdate()" << LL_ENDL; + return true; } - -// virtual + +// virtual BOOL LLPanelEstateCovenant::postBuild() { - mEstateNameText = getChild("estate_name_text"); - mEstateOwnerText = getChild("estate_owner_text"); + mEstateNameText = getChild("estate_name_text"); + mEstateOwnerText = getChild("estate_owner_text"); mEstateOwnerText->setIsFriendCallback(LLAvatarActions::isFriend); - mLastModifiedText = getChild("covenant_timestamp_text"); - mEditor = getChild("covenant_editor"); - LLButton* reset_button = getChild("reset_covenant"); - reset_button->setEnabled(gAgent.canManageEstate()); - reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL); + mLastModifiedText = getChild("covenant_timestamp_text"); + mEditor = getChild("covenant_editor"); + LLButton* reset_button = getChild("reset_covenant"); + reset_button->setEnabled(gAgent.canManageEstate()); + reset_button->setClickedCallback(LLPanelEstateCovenant::resetCovenantID, NULL); - return LLPanelRegionInfo::postBuild(); + return LLPanelRegionInfo::postBuild(); } -// virtual +// virtual void LLPanelEstateCovenant::updateChild(LLUICtrl* child_ctrl) { } // virtual BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - LLInventoryItem* item = (LLInventoryItem*)cargo_data; - - if (!gAgent.canManageEstate()) - { - *accept = ACCEPT_NO; - return TRUE; - } - - switch(cargo_type) - { - case DAD_NOTECARD: - *accept = ACCEPT_YES_COPY_SINGLE; - if (item && drop) - { - LLSD payload; - payload["item_id"] = item->getUUID(); - LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload, - LLPanelEstateCovenant::confirmChangeCovenantCallback); - } - break; - default: - *accept = ACCEPT_NO; - break; - } - - return TRUE; -} - -// static + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLInventoryItem* item = (LLInventoryItem*)cargo_data; + + if (!gAgent.canManageEstate()) + { + *accept = ACCEPT_NO; + return TRUE; + } + + switch(cargo_type) + { + case DAD_NOTECARD: + *accept = ACCEPT_YES_COPY_SINGLE; + if (item && drop) + { + LLSD payload; + payload["item_id"] = item->getUUID(); + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload, + LLPanelEstateCovenant::confirmChangeCovenantCallback); + } + break; + default: + *accept = ACCEPT_NO; + break; + } + + return TRUE; +} + +// static bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); - if (!item || !self) return false; + if (!item || !self) return false; - switch(option) - { - case 0: - self->loadInvItem(item); - break; - default: - break; - } - return false; + switch(option) + { + case 0: + self->loadInvItem(item); + break; + default: + break; + } + return false; } // static void LLPanelEstateCovenant::resetCovenantID(void* userdata) { - LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); } // static bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notification, const LLSD& response) { - LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); - if (!self) return false; + LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); + if (!self) return false; - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - switch(option) - { - case 0: - self->loadInvItem(NULL); - break; - default: - break; - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch(option) + { + case 0: + self->loadInvItem(NULL); + break; + default: + break; + } + return false; } void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp) { - const BOOL high_priority = TRUE; - if (itemp) - { - gAssetStorage->getInvItemAsset(gAgent.getRegionHost(), - gAgent.getID(), - gAgent.getSessionID(), - itemp->getPermissions().getOwner(), - LLUUID::null, - itemp->getUUID(), - itemp->getAssetUUID(), - itemp->getType(), + const BOOL high_priority = TRUE; + if (itemp) + { + gAssetStorage->getInvItemAsset(gAgent.getRegionHost(), + gAgent.getID(), + gAgent.getSessionID(), + itemp->getPermissions().getOwner(), + LLUUID::null, + itemp->getUUID(), + itemp->getAssetUUID(), + itemp->getType(), onLoadComplete, - (void*)this, - high_priority); - mAssetStatus = ASSET_LOADING; - } - else - { - mAssetStatus = ASSET_LOADED; - setCovenantTextEditor(LLTrans::getString("RegionNoCovenant")); - sendChangeCovenantID(LLUUID::null); - } + (void*)this, + high_priority); + mAssetStatus = ASSET_LOADING; + } + else + { + mAssetStatus = ASSET_LOADED; + setCovenantTextEditor(LLTrans::getString("RegionNoCovenant")); + sendChangeCovenantID(LLUUID::null); + } } // static void LLPanelEstateCovenant::onLoadComplete(const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - LL_INFOS() << "LLPanelEstateCovenant::onLoadComplete()" << LL_ENDL; - LLPanelEstateCovenant* panelp = (LLPanelEstateCovenant*)user_data; - if( panelp ) - { - if(0 == status) - { - LLFileSystem file(asset_uuid, type, LLFileSystem::READ); - - S32 file_length = file.getSize(); - - std::vector buffer(file_length+1); - file.read((U8*)&buffer[0], file_length); - // put a EOS at the end - buffer[file_length] = 0; - - if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) ) - { - if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) ) - { - LL_WARNS() << "Problem importing estate covenant." << LL_ENDL; - LLNotificationsUtil::add("ProblemImportingEstateCovenant"); - } - else - { - panelp->sendChangeCovenantID(asset_uuid); - } - } - else - { - // Version 0 (just text, doesn't include version number) - panelp->sendChangeCovenantID(asset_uuid); - } - } - else - { - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || - LL_ERR_FILE_EMPTY == status) - { - LLNotificationsUtil::add("MissingNotecardAssetID"); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - LLNotificationsUtil::add("NotAllowedToViewNotecard"); - } - else - { - LLNotificationsUtil::add("UnableToLoadNotecardAsset"); - } - - LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL; - } - panelp->mAssetStatus = ASSET_LOADED; - panelp->setCovenantID(asset_uuid); - } + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + LL_INFOS() << "LLPanelEstateCovenant::onLoadComplete()" << LL_ENDL; + LLPanelEstateCovenant* panelp = (LLPanelEstateCovenant*)user_data; + if( panelp ) + { + if(0 == status) + { + LLFileSystem file(asset_uuid, type, LLFileSystem::READ); + + S32 file_length = file.getSize(); + + std::vector buffer(file_length+1); + file.read((U8*)&buffer[0], file_length); + // put a EOS at the end + buffer[file_length] = 0; + + if( (file_length > 19) && !strncmp( &buffer[0], "Linden text version", 19 ) ) + { + if( !panelp->mEditor->importBuffer( &buffer[0], file_length+1 ) ) + { + LL_WARNS() << "Problem importing estate covenant." << LL_ENDL; + LLNotificationsUtil::add("ProblemImportingEstateCovenant"); + } + else + { + panelp->sendChangeCovenantID(asset_uuid); + } + } + else + { + // Version 0 (just text, doesn't include version number) + panelp->sendChangeCovenantID(asset_uuid); + } + } + else + { + if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || + LL_ERR_FILE_EMPTY == status) + { + LLNotificationsUtil::add("MissingNotecardAssetID"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + LLNotificationsUtil::add("NotAllowedToViewNotecard"); + } + else + { + LLNotificationsUtil::add("UnableToLoadNotecardAsset"); + } + + LL_WARNS() << "Problem loading notecard: " << status << LL_ENDL; + } + panelp->mAssetStatus = ASSET_LOADED; + panelp->setCovenantID(asset_uuid); + } } // key = "estatechangecovenantid" @@ -2616,97 +2616,97 @@ void LLPanelEstateCovenant::onLoadComplete(const LLUUID& asset_uuid, // strings[1] = str(covenant_id) void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id) { - if (asset_id != getCovenantID()) - { + if (asset_id != getCovenantID()) + { setCovenantID(asset_id); - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("EstateOwnerMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", "estatechangecovenantid"); - msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); + msg->nextBlock("MethodData"); + msg->addString("Method", "estatechangecovenantid"); + msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); - msg->nextBlock("ParamList"); - msg->addString("Parameter", getCovenantID().asString()); - gAgent.sendReliableMessage(); - } + msg->nextBlock("ParamList"); + msg->addString("Parameter", getCovenantID().asString()); + gAgent.sendReliableMessage(); + } } -// virtual +// virtual BOOL LLPanelEstateCovenant::sendUpdate() { - return TRUE; + return TRUE; } std::string LLPanelEstateCovenant::getEstateName() const { - return mEstateNameText->getText(); + return mEstateNameText->getText(); } void LLPanelEstateCovenant::setEstateName(const std::string& name) { - mEstateNameText->setText(name); + mEstateNameText->setText(name); } // static void LLPanelEstateCovenant::updateCovenantText(const std::string& string, const LLUUID& asset_id) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mEditor->setText(string); - panelp->setCovenantID(asset_id); - } + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) + { + panelp->mEditor->setText(string); + panelp->setCovenantID(asset_id); + } } // static void LLPanelEstateCovenant::updateEstateName(const std::string& name) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mEstateNameText->setText(name); - } + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) + { + panelp->mEstateNameText->setText(name); + } } // static void LLPanelEstateCovenant::updateLastModified(const std::string& text) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mLastModifiedText->setText(text); - } + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) + { + panelp->mLastModifiedText->setText(text); + } } // static void LLPanelEstateCovenant::updateEstateOwnerName(const std::string& name) { - LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); - if( panelp ) - { - panelp->mEstateOwnerText->setText(name); - } + LLPanelEstateCovenant* panelp = LLFloaterRegionInfo::getPanelCovenant(); + if( panelp ) + { + panelp->mEstateOwnerText->setText(name); + } } std::string LLPanelEstateCovenant::getOwnerName() const { - return mEstateOwnerText->getText(); + return mEstateOwnerText->getText(); } void LLPanelEstateCovenant::setOwnerName(const std::string& name) { - mEstateOwnerText->setText(name); + mEstateOwnerText->setText(name); } void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text) { - mEditor->setText(text); + mEditor->setText(text); } // key = "estateupdateinfo" @@ -2721,47 +2721,47 @@ void LLPanelEstateCovenant::setCovenantTextEditor(const std::string& text) // strings[8] = str(send_to_agent_only) // strings[9] = str(abuse_email_addr) bool LLDispatchEstateUpdateInfo::operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings) + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) { - LL_DEBUGS() << "Received estate update" << LL_ENDL; + LL_DEBUGS() << "Received estate update" << LL_ENDL; - // Update estate info model. - // This will call LLPanelEstateInfo::refreshFromEstate(). - // *TODO: Move estate message handling stuff to llestateinfomodel.cpp. - LLEstateInfoModel::instance().update(strings); + // Update estate info model. + // This will call LLPanelEstateInfo::refreshFromEstate(). + // *TODO: Move estate message handling stuff to llestateinfomodel.cpp. + LLEstateInfoModel::instance().update(strings); - return true; + return true; } bool LLDispatchSetEstateAccess::operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings) + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (panel && panel->getPendingUpdate()) - { - panel->setPendingUpdate(false); - panel->updateLists(); - } - return true; + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (panel && panel->getPendingUpdate()) + { + panel->setPendingUpdate(false); + panel->updateLists(); + } + return true; } // static LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ) { - LLSD idList = LLSD::emptyArray(); - LLUUID id; - while (count-- > 0 && it < end) - { - memcpy(id.mData, (*(it++)).data(), UUID_BYTES); - idList.append(id); - } - return idList; + LLSD idList = LLSD::emptyArray(); + LLUUID id; + while (count-- > 0 && it < end) + { + memcpy(id.mData, (*(it++)).data(), UUID_BYTES); + idList.append(id); + } + return idList; } // key = "setexperience" @@ -2773,92 +2773,92 @@ LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_ // strings[5] = bin(uuid) ... // ... bool LLDispatchSetEstateExperience::operator()( - const LLDispatcher* dispatcher, - const std::string& key, - const LLUUID& invoice, - const sparam_t& strings) + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) { - LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); - if (!panel) - return true; + LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); + if (!panel) + return true; - const sparam_t::size_type MIN_SIZE = 5; - if (strings.size() < MIN_SIZE) - return true; + const sparam_t::size_type MIN_SIZE = 5; + if (strings.size() < MIN_SIZE) + return true; - // Skip 2 parameters - sparam_t::const_iterator it = strings.begin(); - ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); - ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); + // Skip 2 parameters + sparam_t::const_iterator it = strings.begin(); + ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); + ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); - // Read 3 parameters - LLUUID id; - S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10); - S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10); - S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10); + // Read 3 parameters + LLUUID id; + S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10); + S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10); + S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10); - LLSD ids = LLSD::emptyMap() - .with("blocked", getIDs(it, strings.end(), num_blocked)) - .with("trusted", getIDs(it + num_blocked, strings.end(), num_trusted)) - .with("allowed", getIDs(it + num_blocked + num_trusted, strings.end(), num_allowed)); + LLSD ids = LLSD::emptyMap() + .with("blocked", getIDs(it, strings.end(), num_blocked)) + .with("trusted", getIDs(it + num_blocked, strings.end(), num_trusted)) + .with("allowed", getIDs(it + num_blocked + num_trusted, strings.end(), num_allowed)); - panel->processResponse(ids); + panel->processResponse(ids); - return true; + return true; } BOOL LLPanelRegionExperiences::postBuild() { - mAllowed = setupList("panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE); - mTrusted = setupList("panel_trusted", ESTATE_EXPERIENCE_TRUSTED_ADD, ESTATE_EXPERIENCE_TRUSTED_REMOVE); - mBlocked = setupList("panel_blocked", ESTATE_EXPERIENCE_BLOCKED_ADD, ESTATE_EXPERIENCE_BLOCKED_REMOVE); + mAllowed = setupList("panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE); + mTrusted = setupList("panel_trusted", ESTATE_EXPERIENCE_TRUSTED_ADD, ESTATE_EXPERIENCE_TRUSTED_REMOVE); + mBlocked = setupList("panel_blocked", ESTATE_EXPERIENCE_BLOCKED_ADD, ESTATE_EXPERIENCE_BLOCKED_REMOVE); - getChild("trusted_layout_panel")->setVisible(TRUE); - getChild("experiences_help_text")->setText(getString("estate_caption")); - getChild("trusted_text_help")->setText(getString("trusted_estate_text")); - getChild("allowed_text_help")->setText(getString("allowed_estate_text")); - getChild("blocked_text_help")->setText(getString("blocked_estate_text")); + getChild("trusted_layout_panel")->setVisible(TRUE); + getChild("experiences_help_text")->setText(getString("estate_caption")); + getChild("trusted_text_help")->setText(getString("trusted_estate_text")); + getChild("allowed_text_help")->setText(getString("allowed_estate_text")); + getChild("blocked_text_help")->setText(getString("blocked_estate_text")); - return LLPanelRegionInfo::postBuild(); + return LLPanelRegionInfo::postBuild(); } LLPanelExperienceListEditor* LLPanelRegionExperiences::setupList( const char* control_name, U32 add_id, U32 remove_id ) { - LLPanelExperienceListEditor* child = findChild(control_name); - if(child) - { - child->getChild("text_name")->setText(child->getString(control_name)); - child->setMaxExperienceIDs(ESTATE_MAX_EXPERIENCE_IDS); - child->setAddedCallback( boost::bind(&LLPanelRegionExperiences::itemChanged, this, add_id, _1)); - child->setRemovedCallback(boost::bind(&LLPanelRegionExperiences::itemChanged, this, remove_id, _1)); - } + LLPanelExperienceListEditor* child = findChild(control_name); + if(child) + { + child->getChild("text_name")->setText(child->getString(control_name)); + child->setMaxExperienceIDs(ESTATE_MAX_EXPERIENCE_IDS); + child->setAddedCallback( boost::bind(&LLPanelRegionExperiences::itemChanged, this, add_id, _1)); + child->setRemovedCallback(boost::bind(&LLPanelRegionExperiences::itemChanged, this, remove_id, _1)); + } - return child; + return child; } void LLPanelRegionExperiences::processResponse( const LLSD& content ) { - if(content.has("default")) - { - mDefaultExperience = content["default"].asUUID(); - } + if(content.has("default")) + { + mDefaultExperience = content["default"].asUUID(); + } + + mAllowed->setExperienceIds(content["allowed"]); + mBlocked->setExperienceIds(content["blocked"]); - mAllowed->setExperienceIds(content["allowed"]); - mBlocked->setExperienceIds(content["blocked"]); + LLSD trusted = content["trusted"]; + if(mDefaultExperience.notNull()) + { + mTrusted->setStickyFunction(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + trusted.append(mDefaultExperience); + } - LLSD trusted = content["trusted"]; - if(mDefaultExperience.notNull()) - { - mTrusted->setStickyFunction(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); - trusted.append(mDefaultExperience); - } + mTrusted->setExperienceIds(trusted); - mTrusted->setExperienceIds(trusted); - - mAllowed->refreshExperienceCounter(); - mBlocked->refreshExperienceCounter(); - mTrusted->refreshExperienceCounter(); + mAllowed->refreshExperienceCounter(); + mBlocked->refreshExperienceCounter(); + mTrusted->refreshExperienceCounter(); } @@ -2867,81 +2867,81 @@ void LLPanelRegionExperiences::processResponse( const LLSD& content ) // static bool LLPanelRegionExperiences::experienceCoreConfirm(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); - - LLViewerRegion* region = gAgent.getRegion(); - - LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray(); - - for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray(); - iter != end_it; - iter++) - { - U32 flags = originalFlags; - if (iter + 1 != end_it) - flags |= ESTATE_ACCESS_NO_REPLY; - - const LLUUID id = iter->asUUID(); - switch(option) - { - case 0: - // This estate - sendEstateExperienceDelta(flags, id); - break; - case 1: - { - // All estates, either than I own or manage for this owner. - // This will be verified on simulator. JC - if (!region) break; - if (region->getOwner() == gAgent.getID() - || gAgent.isGodlike()) - { - flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; - sendEstateExperienceDelta(flags, id); - } - else if (region->isEstateManager()) - { - flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; - sendEstateExperienceDelta(flags, id); - } - break; - } - case 2: - default: - break; - } - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); + + LLViewerRegion* region = gAgent.getRegion(); + + LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray(); + + for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray(); + iter != end_it; + iter++) + { + U32 flags = originalFlags; + if (iter + 1 != end_it) + flags |= ESTATE_ACCESS_NO_REPLY; + + const LLUUID id = iter->asUUID(); + switch(option) + { + case 0: + // This estate + sendEstateExperienceDelta(flags, id); + break; + case 1: + { + // All estates, either than I own or manage for this owner. + // This will be verified on simulator. JC + if (!region) break; + if (region->getOwner() == gAgent.getID() + || gAgent.isGodlike()) + { + flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; + sendEstateExperienceDelta(flags, id); + } + else if (region->isEstateManager()) + { + flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; + sendEstateExperienceDelta(flags, id); + } + break; + } + case 2: + default: + break; + } + } + return false; } // Send the actual "estateexperiencedelta" message void LLPanelRegionExperiences::sendEstateExperienceDelta(U32 flags, const LLUUID& experience_id) { - strings_t str(3, std::string()); - gAgent.getID().toString(str[0]); - str[1] = llformat("%u", flags); - experience_id.toString(str[2]); + strings_t str(3, std::string()); + gAgent.getID().toString(str[0]); + str[1] = llformat("%u", flags); + experience_id.toString(str[2]); - LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); - if (panel) - { - panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str); - } + LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); + if (panel) + { + panel->sendEstateOwnerMessage(gMessageSystem, "estateexperiencedelta", LLFloaterRegionInfo::getLastInvoice(), str); + } } void LLPanelRegionExperiences::infoCallback(LLHandle handle, const LLSD& content) -{ - if(handle.isDead()) - return; +{ + if(handle.isDead()) + return; - LLPanelRegionExperiences* floater = handle.get(); - if (floater) - { - floater->processResponse(content); - } + LLPanelRegionExperiences* floater = handle.get(); + if (floater) + { + floater->processResponse(content); + } } /*static*/ @@ -2954,26 +2954,26 @@ std::string LLPanelRegionExperiences::regionCapabilityQuery(LLViewerRegion* regi bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region) { - BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); + BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); - mAllowed->loading(); - mAllowed->setReadonly(!allow_modify); - // remove grid-wide experiences - mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID)); - // remove default experience - mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + mAllowed->loading(); + mAllowed->setReadonly(!allow_modify); + // remove grid-wide experiences + mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_GRID)); + // remove default experience + mAllowed->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); - mBlocked->loading(); - mBlocked->setReadonly(!allow_modify); - // only grid-wide experiences - mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID)); - // but not privileged ones - mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED)); - // remove default experience - mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); + mBlocked->loading(); + mBlocked->setReadonly(!allow_modify); + // only grid-wide experiences + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithoutProperty, _1, LLExperienceCache::PROPERTY_GRID)); + // but not privileged ones + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterWithProperty, _1, LLExperienceCache::PROPERTY_PRIVILEGED)); + // remove default experience + mBlocked->addFilter(boost::bind(LLPanelExperiencePicker::FilterMatching, _1, mDefaultExperience)); - mTrusted->loading(); - mTrusted->setReadonly(!allow_modify); + mTrusted->loading(); + mTrusted->setReadonly(!allow_modify); LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); @@ -2983,87 +2983,87 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region) LLSD LLPanelRegionExperiences::addIds(LLPanelExperienceListEditor* panel) { - LLSD ids; - const uuid_list_t& id_list = panel->getExperienceIds(); - for(uuid_list_t::const_iterator it = id_list.begin(); it != id_list.end(); ++it) - { - ids.append(*it); - } - return ids; + LLSD ids; + const uuid_list_t& id_list = panel->getExperienceIds(); + for(uuid_list_t::const_iterator it = id_list.begin(); it != id_list.end(); ++it) + { + ids.append(*it); + } + return ids; } BOOL LLPanelRegionExperiences::sendUpdate() { - LLViewerRegion* region = gAgent.getRegion(); + LLViewerRegion* region = gAgent.getRegion(); LLSD content; - content["allowed"]=addIds(mAllowed); - content["blocked"]=addIds(mBlocked); - content["trusted"]=addIds(mTrusted); + content["allowed"]=addIds(mAllowed); + content["blocked"]=addIds(mBlocked); + content["trusted"]=addIds(mTrusted); LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); - return TRUE; + return TRUE; } void LLPanelRegionExperiences::itemChanged( U32 event_type, const LLUUID& id ) { - std::string dialog_name; - switch (event_type) - { - case ESTATE_EXPERIENCE_ALLOWED_ADD: - dialog_name = "EstateAllowedExperienceAdd"; - break; + std::string dialog_name; + switch (event_type) + { + case ESTATE_EXPERIENCE_ALLOWED_ADD: + dialog_name = "EstateAllowedExperienceAdd"; + break; - case ESTATE_EXPERIENCE_ALLOWED_REMOVE: - dialog_name = "EstateAllowedExperienceRemove"; - break; + case ESTATE_EXPERIENCE_ALLOWED_REMOVE: + dialog_name = "EstateAllowedExperienceRemove"; + break; - case ESTATE_EXPERIENCE_TRUSTED_ADD: - dialog_name = "EstateTrustedExperienceAdd"; - break; + case ESTATE_EXPERIENCE_TRUSTED_ADD: + dialog_name = "EstateTrustedExperienceAdd"; + break; - case ESTATE_EXPERIENCE_TRUSTED_REMOVE: - dialog_name = "EstateTrustedExperienceRemove"; - break; + case ESTATE_EXPERIENCE_TRUSTED_REMOVE: + dialog_name = "EstateTrustedExperienceRemove"; + break; - case ESTATE_EXPERIENCE_BLOCKED_ADD: - dialog_name = "EstateBlockedExperienceAdd"; - break; + case ESTATE_EXPERIENCE_BLOCKED_ADD: + dialog_name = "EstateBlockedExperienceAdd"; + break; - case ESTATE_EXPERIENCE_BLOCKED_REMOVE: - dialog_name = "EstateBlockedExperienceRemove"; - break; + case ESTATE_EXPERIENCE_BLOCKED_REMOVE: + dialog_name = "EstateBlockedExperienceRemove"; + break; - default: - return; - } + default: + return; + } - LLSD payload; - payload["operation"] = (S32)event_type; - payload["dialog_name"] = dialog_name; - payload["allowed_ids"].append(id); + LLSD payload; + payload["operation"] = (S32)event_type; + payload["dialog_name"] = dialog_name; + payload["allowed_ids"].append(id); - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); - LLNotification::Params params(dialog_name); - params.payload(payload) - .substitutions(args) - .functor.function(LLPanelRegionExperiences::experienceCoreConfirm); - if (LLPanelEstateInfo::isLindenEstate()) - { - LLNotifications::instance().forceResponse(params, 0); - } - else - { - LLNotifications::instance().add(params); - } + LLNotification::Params params(dialog_name); + params.payload(payload) + .substitutions(args) + .functor.function(LLPanelRegionExperiences::experienceCoreConfirm); + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().forceResponse(params, 0); + } + else + { + LLNotifications::instance().add(params); + } - onChangeAnything(); + onChangeAnything(); } @@ -3073,583 +3073,583 @@ LLPanelEstateAccess::LLPanelEstateAccess() BOOL LLPanelEstateAccess::postBuild() { - getChild("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl *avatar_name_list = getChild("allowed_avatar_name_list"); - if (avatar_name_list) - { - avatar_name_list->setCommitOnSelectionChange(TRUE); - avatar_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); - } - - getChild("allowed_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedSearchEdit, this, _2)); - childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddAllowedAgent, this)); - childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedAgent, this)); - childSetAction("copy_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedList, this)); - - getChild("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* group_name_list = getChild("allowed_group_name_list"); - if (group_name_list) - { - group_name_list->setCommitOnSelectionChange(TRUE); - group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); - } - - getChild("allowed_group_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedGroupsSearchEdit, this, _2)); - getChild("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onClickAddAllowedGroup, this)); - childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedGroup, this)); - childSetAction("copy_allowed_group_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedGroupList, this)); - - getChild("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* banned_name_list = getChild("banned_avatar_name_list"); - if (banned_name_list) - { - banned_name_list->setCommitOnSelectionChange(TRUE); - banned_name_list->setMaxItemCount(ESTATE_MAX_BANNED_IDS); - } - - getChild("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2)); - childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddBannedAgent, this)); - childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveBannedAgent, this)); - childSetAction("copy_banned_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyBannedList, this)); - - getChild("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); - LLNameListCtrl* manager_name_list = getChild("estate_manager_name_list"); - if (manager_name_list) - { - manager_name_list->setCommitOnSelectionChange(TRUE); - manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue - } - - childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this)); - childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveEstateManager, this)); - - return TRUE; -} - -void LLPanelEstateAccess::updateControls(LLViewerRegion* region) -{ - BOOL god = gAgent.isGodlike(); - BOOL owner = (region && (region->getOwner() == gAgent.getID())); - BOOL manager = (region && region->isEstateManager()); - BOOL enable_cotrols = god || owner || manager; - setCtrlsEnabled(enable_cotrols); - - BOOL has_allowed_avatar = getChild("allowed_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_allowed_group = getChild("allowed_group_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_banned_agent = getChild("banned_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; - BOOL has_estate_manager = getChild("estate_manager_name_list")->getFirstSelected() ? TRUE : FALSE; - - getChildView("add_allowed_avatar_btn")->setEnabled(enable_cotrols); - getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && enable_cotrols); - getChildView("allowed_avatar_name_list")->setEnabled(enable_cotrols); - - getChildView("add_allowed_group_btn")->setEnabled(enable_cotrols); - getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && enable_cotrols); - getChildView("allowed_group_name_list")->setEnabled(enable_cotrols); - - // Can't ban people from mainland, orientation islands, etc. because this - // creates much network traffic and server load. - // Disable their accounts in CSR tool instead. - bool linden_estate = LLPanelEstateInfo::isLindenEstate(); - bool enable_ban = enable_cotrols && !linden_estate; - getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); - getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban); - getChildView("banned_avatar_name_list")->setEnabled(enable_cotrols); - - // estate managers can't add estate managers - getChildView("add_estate_manager_btn")->setEnabled(god || owner); - getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner)); - getChildView("estate_manager_name_list")->setEnabled(god || owner); - - if (enable_cotrols != mCtrlsEnabled) - { - mCtrlsEnabled = enable_cotrols; - updateLists(); // update the lists on the agent's access level change - } -} + getChild("allowed_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl *avatar_name_list = getChild("allowed_avatar_name_list"); + if (avatar_name_list) + { + avatar_name_list->setCommitOnSelectionChange(TRUE); + avatar_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + } -//--------------------------------------------------------------------------- -// Add/Remove estate access button callbacks -//--------------------------------------------------------------------------- -void LLPanelEstateAccess::onClickAddAllowedAgent() -{ - LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) - { - //args + getChild("allowed_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedSearchEdit, this, _2)); + childSetAction("add_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddAllowedAgent, this)); + childSetAction("remove_allowed_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedAgent, this)); + childSetAction("copy_allowed_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedList, this)); - LLSD args; - args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args); - return; - } - accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd"); + getChild("allowed_group_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl* group_name_list = getChild("allowed_group_name_list"); + if (group_name_list) + { + group_name_list->setCommitOnSelectionChange(TRUE); + group_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS); + } + + getChild("allowed_group_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onAllowedGroupsSearchEdit, this, _2)); + getChild("add_allowed_group_btn")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onClickAddAllowedGroup, this)); + childSetAction("remove_allowed_group_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveAllowedGroup, this)); + childSetAction("copy_allowed_group_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyAllowedGroupList, this)); + + getChild("banned_avatar_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl* banned_name_list = getChild("banned_avatar_name_list"); + if (banned_name_list) + { + banned_name_list->setCommitOnSelectionChange(TRUE); + banned_name_list->setMaxItemCount(ESTATE_MAX_BANNED_IDS); + } + + getChild("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2)); + childSetAction("add_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickAddBannedAgent, this)); + childSetAction("remove_banned_avatar_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveBannedAgent, this)); + childSetAction("copy_banned_list_btn", boost::bind(&LLPanelEstateAccess::onClickCopyBannedList, this)); + + getChild("estate_manager_name_list")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeChildCtrl, this, _1)); + LLNameListCtrl* manager_name_list = getChild("estate_manager_name_list"); + if (manager_name_list) + { + manager_name_list->setCommitOnSelectionChange(TRUE); + manager_name_list->setMaxItemCount(ESTATE_MAX_MANAGERS * 4); // Allow extras for dupe issue + } + + childSetAction("add_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickAddEstateManager, this)); + childSetAction("remove_estate_manager_btn", boost::bind(&LLPanelEstateAccess::onClickRemoveEstateManager, this)); + + return TRUE; +} + +void LLPanelEstateAccess::updateControls(LLViewerRegion* region) +{ + BOOL god = gAgent.isGodlike(); + BOOL owner = (region && (region->getOwner() == gAgent.getID())); + BOOL manager = (region && region->isEstateManager()); + BOOL enable_cotrols = god || owner || manager; + setCtrlsEnabled(enable_cotrols); + + BOOL has_allowed_avatar = getChild("allowed_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_allowed_group = getChild("allowed_group_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_banned_agent = getChild("banned_avatar_name_list")->getFirstSelected() ? TRUE : FALSE; + BOOL has_estate_manager = getChild("estate_manager_name_list")->getFirstSelected() ? TRUE : FALSE; + + getChildView("add_allowed_avatar_btn")->setEnabled(enable_cotrols); + getChildView("remove_allowed_avatar_btn")->setEnabled(has_allowed_avatar && enable_cotrols); + getChildView("allowed_avatar_name_list")->setEnabled(enable_cotrols); + + getChildView("add_allowed_group_btn")->setEnabled(enable_cotrols); + getChildView("remove_allowed_group_btn")->setEnabled(has_allowed_group && enable_cotrols); + getChildView("allowed_group_name_list")->setEnabled(enable_cotrols); + + // Can't ban people from mainland, orientation islands, etc. because this + // creates much network traffic and server load. + // Disable their accounts in CSR tool instead. + bool linden_estate = LLPanelEstateInfo::isLindenEstate(); + bool enable_ban = enable_cotrols && !linden_estate; + getChildView("add_banned_avatar_btn")->setEnabled(enable_ban); + getChildView("remove_banned_avatar_btn")->setEnabled(has_banned_agent && enable_ban); + getChildView("banned_avatar_name_list")->setEnabled(enable_cotrols); + + // estate managers can't add estate managers + getChildView("add_estate_manager_btn")->setEnabled(god || owner); + getChildView("remove_estate_manager_btn")->setEnabled(has_estate_manager && (god || owner)); + getChildView("estate_manager_name_list")->setEnabled(god || owner); + + if (enable_cotrols != mCtrlsEnabled) + { + mCtrlsEnabled = enable_cotrols; + updateLists(); // update the lists on the agent's access level change + } +} + +//--------------------------------------------------------------------------- +// Add/Remove estate access button callbacks +//--------------------------------------------------------------------------- +void LLPanelEstateAccess::onClickAddAllowedAgent() +{ + LLCtrlListInterface *list = childGetListInterface("allowed_avatar_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) + { + //args + + LLSD args; + args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args); + return; + } + accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd"); } void LLPanelEstateAccess::onClickRemoveAllowedAgent() { - accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list"); + accessRemoveCore(ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, "EstateAllowedAgentRemove", "allowed_avatar_name_list"); } void LLPanelEstateAccess::onClickAddAllowedGroup() { - LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) - { - LLSD args; - args["MAX_GROUPS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args); - return; - } - - LLNotification::Params params("ChangeLindenAccess"); - params.functor.function(boost::bind(&LLPanelEstateAccess::addAllowedGroup, this, _1, _2)); - if (LLPanelEstateInfo::isLindenEstate()) - { - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } + LLCtrlListInterface *list = childGetListInterface("allowed_group_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS) + { + LLSD args; + args["MAX_GROUPS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args); + return; + } + + LLNotification::Params params("ChangeLindenAccess"); + params.functor.function(boost::bind(&LLPanelEstateAccess::addAllowedGroup, this, _1, _2)); + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } } bool LLPanelEstateAccess::addAllowedGroup(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return false; - LLFloater* parent_floater = gFloaterView->getParentFloater(this); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); - LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance("group_picker", LLSD(gAgent.getID())); - if (widget) - { - widget->removeNoneOption(); - widget->setSelectGroupCallback(boost::bind(&LLPanelEstateAccess::addAllowedGroup2, this, _1)); - if (parent_floater) - { - LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); - widget->setOrigin(new_rect.mLeft, new_rect.mBottom); - parent_floater->addDependentFloater(widget); - } - } + LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance("group_picker", LLSD(gAgent.getID())); + if (widget) + { + widget->removeNoneOption(); + widget->setSelectGroupCallback(boost::bind(&LLPanelEstateAccess::addAllowedGroup2, this, _1)); + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget); + widget->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(widget); + } + } - return false; + return false; } void LLPanelEstateAccess::onClickRemoveAllowedGroup() { - accessRemoveCore(ESTATE_ACCESS_ALLOWED_GROUP_REMOVE, "EstateAllowedGroupRemove", "allowed_group_name_list"); + accessRemoveCore(ESTATE_ACCESS_ALLOWED_GROUP_REMOVE, "EstateAllowedGroupRemove", "allowed_group_name_list"); } void LLPanelEstateAccess::onClickAddBannedAgent() { - LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_BANNED_IDS) - { - LLSD args; - args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_BANNED_IDS); - LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); - return; - } - accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd"); + LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_BANNED_IDS) + { + LLSD args; + args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_BANNED_IDS); + LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); + return; + } + accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd"); } void LLPanelEstateAccess::onClickRemoveBannedAgent() { - accessRemoveCore(ESTATE_ACCESS_BANNED_AGENT_REMOVE, "EstateBannedAgentRemove", "banned_avatar_name_list"); + accessRemoveCore(ESTATE_ACCESS_BANNED_AGENT_REMOVE, "EstateBannedAgentRemove", "banned_avatar_name_list"); } void LLPanelEstateAccess::onClickCopyAllowedList() { - copyListToClipboard("allowed_avatar_name_list"); + copyListToClipboard("allowed_avatar_name_list"); } void LLPanelEstateAccess::onClickCopyAllowedGroupList() { - copyListToClipboard("allowed_group_name_list"); + copyListToClipboard("allowed_group_name_list"); } void LLPanelEstateAccess::onClickCopyBannedList() { - copyListToClipboard("banned_avatar_name_list"); + copyListToClipboard("banned_avatar_name_list"); } // static void LLPanelEstateAccess::onClickAddEstateManager() { - LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list"); - if (!list) return; - if (list->getItemCount() >= ESTATE_MAX_MANAGERS) - { // Tell user they can't add more managers - LLSD args; - args["MAX_MANAGER"] = llformat("%d", ESTATE_MAX_MANAGERS); - LLNotificationsUtil::add("MaxManagersOnRegion", args); - } - else - { // Go pick managers to add - accessAddCore(ESTATE_ACCESS_MANAGER_ADD, "EstateManagerAdd"); - } + LLCtrlListInterface *list = childGetListInterface("estate_manager_name_list"); + if (!list) return; + if (list->getItemCount() >= ESTATE_MAX_MANAGERS) + { // Tell user they can't add more managers + LLSD args; + args["MAX_MANAGER"] = llformat("%d", ESTATE_MAX_MANAGERS); + LLNotificationsUtil::add("MaxManagersOnRegion", args); + } + else + { // Go pick managers to add + accessAddCore(ESTATE_ACCESS_MANAGER_ADD, "EstateManagerAdd"); + } } // static void LLPanelEstateAccess::onClickRemoveEstateManager() { - accessRemoveCore(ESTATE_ACCESS_MANAGER_REMOVE, "EstateManagerRemove", "estate_manager_name_list"); + accessRemoveCore(ESTATE_ACCESS_MANAGER_REMOVE, "EstateManagerRemove", "estate_manager_name_list"); } // Special case callback for groups, since it has different callback format than names void LLPanelEstateAccess::addAllowedGroup2(LLUUID id) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (panel) - { - LLNameListCtrl* group_list = panel->getChild("allowed_group_name_list"); - LLScrollListItem* item = group_list->getNameItemByAgentId(id); - if (item) - { - LLSD args; - args["GROUP"] = item->getColumn(0)->getValue().asString(); - LLNotificationsUtil::add("GroupIsAlreadyInList", args); - return; - } - } - - LLSD payload; - payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD; - payload["dialog_name"] = "EstateAllowedGroupAdd"; - payload["allowed_ids"].append(id); - - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - - LLNotification::Params params("EstateAllowedGroupAdd"); - params.payload(payload) - .substitutions(args) - .functor.function(accessCoreConfirm); - if (LLPanelEstateInfo::isLindenEstate()) - { - LLNotifications::instance().forceResponse(params, 0); - } - else - { - LLNotifications::instance().add(params); - } + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (panel) + { + LLNameListCtrl* group_list = panel->getChild("allowed_group_name_list"); + LLScrollListItem* item = group_list->getNameItemByAgentId(id); + if (item) + { + LLSD args; + args["GROUP"] = item->getColumn(0)->getValue().asString(); + LLNotificationsUtil::add("GroupIsAlreadyInList", args); + return; + } + } + + LLSD payload; + payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD; + payload["dialog_name"] = "EstateAllowedGroupAdd"; + payload["allowed_ids"].append(id); + + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + + LLNotification::Params params("EstateAllowedGroupAdd"); + params.payload(payload) + .substitutions(args) + .functor.function(accessCoreConfirm); + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().forceResponse(params, 0); + } + else + { + LLNotifications::instance().add(params); + } } // static void LLPanelEstateAccess::accessAddCore(U32 operation_flag, const std::string& dialog_name) { - LLSD payload; - payload["operation"] = (S32)operation_flag; - payload["dialog_name"] = dialog_name; - // agent id filled in after avatar picker + LLSD payload; + payload["operation"] = (S32)operation_flag; + payload["dialog_name"] = dialog_name; + // agent id filled in after avatar picker - LLNotification::Params params("ChangeLindenAccess"); - params.payload(payload) - .functor.function(accessAddCore2); + LLNotification::Params params("ChangeLindenAccess"); + params.payload(payload) + .functor.function(accessAddCore2); - if (LLPanelEstateInfo::isLindenEstate()) - { - LLNotifications::instance().add(params); - } - else - { - // same as clicking "OK" - LLNotifications::instance().forceResponse(params, 0); - } + if (LLPanelEstateInfo::isLindenEstate()) + { + LLNotifications::instance().add(params); + } + else + { + // same as clicking "OK" + LLNotifications::instance().forceResponse(params, 0); + } } // static bool LLPanelEstateAccess::accessAddCore2(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) - { - // abort change - return false; - } - - LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); - //Get parent floater name - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; - const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; - - //Determine the button that triggered opening of the avatar picker - //(so that a shadow frustum from the button to the avatar picker can be created) - LLView * button = NULL; - switch (change_info->mOperationFlag) - { - case ESTATE_ACCESS_ALLOWED_AGENT_ADD: - button = panel->findChild("add_allowed_avatar_btn"); - break; - - case ESTATE_ACCESS_BANNED_AGENT_ADD: - button = panel->findChild("add_banned_avatar_btn"); - break; - - case ESTATE_ACCESS_MANAGER_ADD: - button = panel->findChild("add_estate_manager_btn"); - break; - } - - // avatar picker yes multi-select, yes close-on-select - LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateAccess::accessAddCore3, _1, _2, (void*)change_info), - TRUE, TRUE, FALSE, parent_floater_name, button); - - //Allows the closed parent floater to close the child floater (avatar picker) - if (child_floater) - { - parent_floater->addDependentFloater(child_floater); - } - - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + // abort change + return false; + } + + LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]); + //Get parent floater name + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + LLFloater* parent_floater = panel ? gFloaterView->getParentFloater(panel) : NULL; + const std::string& parent_floater_name = parent_floater ? parent_floater->getName() : ""; + + //Determine the button that triggered opening of the avatar picker + //(so that a shadow frustum from the button to the avatar picker can be created) + LLView * button = NULL; + switch (change_info->mOperationFlag) + { + case ESTATE_ACCESS_ALLOWED_AGENT_ADD: + button = panel->findChild("add_allowed_avatar_btn"); + break; + + case ESTATE_ACCESS_BANNED_AGENT_ADD: + button = panel->findChild("add_banned_avatar_btn"); + break; + + case ESTATE_ACCESS_MANAGER_ADD: + button = panel->findChild("add_estate_manager_btn"); + break; + } + + // avatar picker yes multi-select, yes close-on-select + LLFloater* child_floater = LLFloaterAvatarPicker::show(boost::bind(&LLPanelEstateAccess::accessAddCore3, _1, _2, (void*)change_info), + TRUE, TRUE, FALSE, parent_floater_name, button); + + //Allows the closed parent floater to close the child floater (avatar picker) + if (child_floater) + { + parent_floater->addDependentFloater(child_floater); + } + + return false; } // static void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, std::vector names, void* data) { - LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data; - if (!change_info) return; - if (ids.empty()) - { - // User didn't select a name. - delete change_info; - change_info = NULL; - return; - } - // User did select a name. - change_info->mAgentOrGroupIDs = ids; - // Can't put estate owner on ban list - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; - - if (change_info->mOperationFlag & ESTATE_ACCESS_ALLOWED_AGENT_ADD) - { - LLNameListCtrl* name_list = panel->getChild("allowed_avatar_name_list"); - int currentCount = (name_list ? name_list->getItemCount() : 0); - if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) - { - LLSD args; - args["NUM_ADDED"] = llformat("%d", ids.size()); - args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); - args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_ACCESS_IDS); - LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); - delete change_info; - return; - } - - uuid_vec_t ids_allowed; - std::vector names_allowed; - std::string already_allowed; - bool single = true; - for (U32 i = 0; i < ids.size(); ++i) - { - LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); - if (item) - { - if (!already_allowed.empty()) - { - already_allowed += ", "; - single = false; - } - already_allowed += item->getColumn(0)->getValue().asString(); - } - else - { - ids_allowed.push_back(ids[i]); - names_allowed.push_back(names[i]); - } - } - if (!already_allowed.empty()) - { - LLSD args; - args["AGENT"] = already_allowed; - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); - LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); - if (ids_allowed.empty()) - { - delete change_info; - return; - } - } - change_info->mAgentOrGroupIDs = ids_allowed; - change_info->mAgentNames = names_allowed; - } - if (change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD) - { - LLNameListCtrl* name_list = panel->getChild("banned_avatar_name_list"); - LLNameListCtrl* em_list = panel->getChild("estate_manager_name_list"); - int currentCount = (name_list ? name_list->getItemCount() : 0); - if (ids.size() + currentCount > ESTATE_MAX_BANNED_IDS) - { - LLSD args; - args["NUM_ADDED"] = llformat("%d", ids.size()); - args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_BANNED_IDS); - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); - args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_BANNED_IDS); - LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); - delete change_info; - return; - } - - uuid_vec_t ids_allowed; - std::vector names_allowed; - std::string already_banned; - std::string em_ban; - bool single = true; - for (U32 i = 0; i < ids.size(); ++i) - { - bool is_allowed = true; - LLScrollListItem* em_item = em_list->getNameItemByAgentId(ids[i]); - if (em_item) - { - if (!em_ban.empty()) - { - em_ban += ", "; - } - em_ban += em_item->getColumn(0)->getValue().asString(); - is_allowed = false; - } - - LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); - if (item) - { - if (!already_banned.empty()) - { - already_banned += ", "; - single = false; - } - already_banned += item->getColumn(0)->getValue().asString(); - is_allowed = false; - } - - if (is_allowed) - { - ids_allowed.push_back(ids[i]); - names_allowed.push_back(names[i]); - } - } - if (!em_ban.empty()) - { - LLSD args; - args["AGENT"] = em_ban; - LLNotificationsUtil::add("ProblemBanningEstateManager", args); - if (ids_allowed.empty()) - { - delete change_info; - return; - } - } - if (!already_banned.empty()) - { - LLSD args; - args["AGENT"] = already_banned; - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); - LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); - if (ids_allowed.empty()) - { - delete change_info; - return; - } - } - change_info->mAgentOrGroupIDs = ids_allowed; - change_info->mAgentNames = names_allowed; - } - - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - LLNotification::Params params(change_info->mDialogName); - params.substitutions(args) - .payload(change_info->asLLSD()) - .functor.function(accessCoreConfirm); - - if (LLPanelEstateInfo::isLindenEstate()) - { - // just apply to this estate - LLNotifications::instance().forceResponse(params, 0); - } - else - { - // ask if this estate or all estates with this owner - LLNotifications::instance().add(params); - } + LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data; + if (!change_info) return; + if (ids.empty()) + { + // User didn't select a name. + delete change_info; + change_info = NULL; + return; + } + // User did select a name. + change_info->mAgentOrGroupIDs = ids; + // Can't put estate owner on ban list + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLViewerRegion* region = gAgent.getRegion(); + if (!region) return; + + if (change_info->mOperationFlag & ESTATE_ACCESS_ALLOWED_AGENT_ADD) + { + LLNameListCtrl* name_list = panel->getChild("allowed_avatar_name_list"); + int currentCount = (name_list ? name_list->getItemCount() : 0); + if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS) + { + LLSD args; + args["NUM_ADDED"] = llformat("%d", ids.size()); + args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_ACCESS_IDS); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); + delete change_info; + return; + } + + uuid_vec_t ids_allowed; + std::vector names_allowed; + std::string already_allowed; + bool single = true; + for (U32 i = 0; i < ids.size(); ++i) + { + LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); + if (item) + { + if (!already_allowed.empty()) + { + already_allowed += ", "; + single = false; + } + already_allowed += item->getColumn(0)->getValue().asString(); + } + else + { + ids_allowed.push_back(ids[i]); + names_allowed.push_back(names[i]); + } + } + if (!already_allowed.empty()) + { + LLSD args; + args["AGENT"] = already_allowed; + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + change_info->mAgentOrGroupIDs = ids_allowed; + change_info->mAgentNames = names_allowed; + } + if (change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD) + { + LLNameListCtrl* name_list = panel->getChild("banned_avatar_name_list"); + LLNameListCtrl* em_list = panel->getChild("estate_manager_name_list"); + int currentCount = (name_list ? name_list->getItemCount() : 0); + if (ids.size() + currentCount > ESTATE_MAX_BANNED_IDS) + { + LLSD args; + args["NUM_ADDED"] = llformat("%d", ids.size()); + args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_BANNED_IDS); + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); + args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_BANNED_IDS); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); + delete change_info; + return; + } + + uuid_vec_t ids_allowed; + std::vector names_allowed; + std::string already_banned; + std::string em_ban; + bool single = true; + for (U32 i = 0; i < ids.size(); ++i) + { + bool is_allowed = true; + LLScrollListItem* em_item = em_list->getNameItemByAgentId(ids[i]); + if (em_item) + { + if (!em_ban.empty()) + { + em_ban += ", "; + } + em_ban += em_item->getColumn(0)->getValue().asString(); + is_allowed = false; + } + + LLScrollListItem* item = name_list->getNameItemByAgentId(ids[i]); + if (item) + { + if (!already_banned.empty()) + { + already_banned += ", "; + single = false; + } + already_banned += item->getColumn(0)->getValue().asString(); + is_allowed = false; + } + + if (is_allowed) + { + ids_allowed.push_back(ids[i]); + names_allowed.push_back(names[i]); + } + } + if (!em_ban.empty()) + { + LLSD args; + args["AGENT"] = em_ban; + LLNotificationsUtil::add("ProblemBanningEstateManager", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + if (!already_banned.empty()) + { + LLSD args; + args["AGENT"] = already_banned; + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); + LLNotificationsUtil::add(single ? "AgentIsAlreadyInList" : "AgentsAreAlreadyInList", args); + if (ids_allowed.empty()) + { + delete change_info; + return; + } + } + change_info->mAgentOrGroupIDs = ids_allowed; + change_info->mAgentNames = names_allowed; + } + + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + LLNotification::Params params(change_info->mDialogName); + params.substitutions(args) + .payload(change_info->asLLSD()) + .functor.function(accessCoreConfirm); + + if (LLPanelEstateInfo::isLindenEstate()) + { + // just apply to this estate + LLNotifications::instance().forceResponse(params, 0); + } + else + { + // ask if this estate or all estates with this owner + LLNotifications::instance().add(params); + } } // static void LLPanelEstateAccess::accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLNameListCtrl* name_list = panel->getChild(list_ctrl_name); - if (!name_list) return; - - std::vector list_vector = name_list->getAllSelected(); - if (list_vector.size() == 0) - return; - - LLSD payload; - payload["operation"] = (S32)operation_flag; - payload["dialog_name"] = dialog_name; - - for (std::vector::const_iterator iter = list_vector.begin(); - iter != list_vector.end(); - iter++) - { - LLScrollListItem *item = (*iter); - payload["allowed_ids"].append(item->getUUID()); - } - - LLNotification::Params params("ChangeLindenAccess"); - params.payload(payload) - .functor.function(accessRemoveCore2); - - if (LLPanelEstateInfo::isLindenEstate()) - { - // warn on change linden estate - LLNotifications::instance().add(params); - } - else - { - // just proceed, as if clicking OK - LLNotifications::instance().forceResponse(params, 0); - } + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* name_list = panel->getChild(list_ctrl_name); + if (!name_list) return; + + std::vector list_vector = name_list->getAllSelected(); + if (list_vector.size() == 0) + return; + + LLSD payload; + payload["operation"] = (S32)operation_flag; + payload["dialog_name"] = dialog_name; + + for (std::vector::const_iterator iter = list_vector.begin(); + iter != list_vector.end(); + iter++) + { + LLScrollListItem *item = (*iter); + payload["allowed_ids"].append(item->getUUID()); + } + + LLNotification::Params params("ChangeLindenAccess"); + params.payload(payload) + .functor.function(accessRemoveCore2); + + if (LLPanelEstateInfo::isLindenEstate()) + { + // warn on change linden estate + LLNotifications::instance().add(params); + } + else + { + // just proceed, as if clicking OK + LLNotifications::instance().forceResponse(params, 0); + } } // static bool LLPanelEstateAccess::accessRemoveCore2(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) - { - // abort - return false; - } - - // If Linden estate, can only apply to "this" estate, not all estates - // owned by NULL. - if (LLPanelEstateInfo::isLindenEstate()) - { - accessCoreConfirm(notification, response); - } - else - { - LLSD args; - args["ALL_ESTATES"] = all_estates_text(); - LLNotificationsUtil::add(notification["payload"]["dialog_name"], - args, - notification["payload"], - accessCoreConfirm); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + // abort + return false; + } + + // If Linden estate, can only apply to "this" estate, not all estates + // owned by NULL. + if (LLPanelEstateInfo::isLindenEstate()) + { + accessCoreConfirm(notification, response); + } + else + { + LLSD args; + args["ALL_ESTATES"] = all_estates_text(); + LLNotificationsUtil::add(notification["payload"]["dialog_name"], + args, + notification["payload"], + accessCoreConfirm); + } + return false; } // Used for both access add and remove operations, depending on the mOperationFlag @@ -3657,133 +3657,133 @@ bool LLPanelEstateAccess::accessRemoveCore2(const LLSD& notification, const LLSD // static bool LLPanelEstateAccess::accessCoreConfirm(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); - U32 flags = originalFlags; - - LLViewerRegion* region = gAgent.getRegion(); - - if (option == 2) // cancel - { - return false; - } - else if (option == 1) - { - // All estates, either than I own or manage for this owner. - // This will be verified on simulator. JC - if (!region) return false; - if (region->getOwner() == gAgent.getID() - || gAgent.isGodlike()) - { - flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; - } - else if (region->isEstateManager()) - { - flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; - } - } - - std::string names; - U32 listed_names = 0; - for (U32 i = 0; i < notification["payload"]["allowed_ids"].size(); ++i) - { - if (i + 1 != notification["payload"]["allowed_ids"].size()) - { - flags |= ESTATE_ACCESS_NO_REPLY; - } - else - { - flags &= ~ESTATE_ACCESS_NO_REPLY; - } - - const LLUUID id = notification["payload"]["allowed_ids"][i].asUUID(); - if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD) - && region && (region->getOwner() == id)) - { - LLNotificationsUtil::add("OwnerCanNotBeDenied"); - break; - } - - sendEstateAccessDelta(flags, id); - - if ((flags & (ESTATE_ACCESS_ALLOWED_GROUP_ADD | ESTATE_ACCESS_ALLOWED_GROUP_REMOVE)) == 0) - { - // fill the name list for confirmation - if (listed_names < MAX_LISTED_NAMES) - { - if (!names.empty()) - { - names += ", "; - } - if (!notification["payload"]["allowed_names"][i]["display_name"].asString().empty()) - { - names += notification["payload"]["allowed_names"][i]["display_name"].asString(); - } - else - { //try to get an agent name from cache - LLAvatarName av_name; - if (LLAvatarNameCache::get(id, &av_name)) - { - names += av_name.getCompleteName(); - } - } - - } - listed_names++; - } - } - if (listed_names > MAX_LISTED_NAMES) - { - LLSD args; - args["EXTRA_COUNT"] = llformat("%d", listed_names - MAX_LISTED_NAMES); - names += " " + LLTrans::getString("AndNMore", args); - } - - if (!names.empty()) // show the conirmation - { - LLSD args; - args["AGENT"] = names; - - if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE)) - { - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); - } - else if (flags & (ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) - { - args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); - } - - if (flags & ESTATE_ACCESS_APPLY_TO_ALL_ESTATES) - { - args["ESTATE"] = LLTrans::getString("RegionInfoAllEstates"); - } - else if (flags & ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES) - { - args["ESTATE"] = LLTrans::getString("RegionInfoManagedEstates"); - } - else - { - args["ESTATE"] = LLTrans::getString("RegionInfoThisEstate"); - } - - bool single = (listed_names == 1); - if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_ADD)) - { - LLNotificationsUtil::add(single ? "AgentWasAddedToList" : "AgentsWereAddedToList", args); - } - else if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) - { - LLNotificationsUtil::add(single ? "AgentWasRemovedFromList" : "AgentsWereRemovedFromList", args); - } - } - - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (panel) - { - panel->setPendingUpdate(true); - } - - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); + U32 flags = originalFlags; + + LLViewerRegion* region = gAgent.getRegion(); + + if (option == 2) // cancel + { + return false; + } + else if (option == 1) + { + // All estates, either than I own or manage for this owner. + // This will be verified on simulator. JC + if (!region) return false; + if (region->getOwner() == gAgent.getID() + || gAgent.isGodlike()) + { + flags |= ESTATE_ACCESS_APPLY_TO_ALL_ESTATES; + } + else if (region->isEstateManager()) + { + flags |= ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES; + } + } + + std::string names; + U32 listed_names = 0; + for (U32 i = 0; i < notification["payload"]["allowed_ids"].size(); ++i) + { + if (i + 1 != notification["payload"]["allowed_ids"].size()) + { + flags |= ESTATE_ACCESS_NO_REPLY; + } + else + { + flags &= ~ESTATE_ACCESS_NO_REPLY; + } + + const LLUUID id = notification["payload"]["allowed_ids"][i].asUUID(); + if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD) + && region && (region->getOwner() == id)) + { + LLNotificationsUtil::add("OwnerCanNotBeDenied"); + break; + } + + sendEstateAccessDelta(flags, id); + + if ((flags & (ESTATE_ACCESS_ALLOWED_GROUP_ADD | ESTATE_ACCESS_ALLOWED_GROUP_REMOVE)) == 0) + { + // fill the name list for confirmation + if (listed_names < MAX_LISTED_NAMES) + { + if (!names.empty()) + { + names += ", "; + } + if (!notification["payload"]["allowed_names"][i]["display_name"].asString().empty()) + { + names += notification["payload"]["allowed_names"][i]["display_name"].asString(); + } + else + { //try to get an agent name from cache + LLAvatarName av_name; + if (LLAvatarNameCache::get(id, &av_name)) + { + names += av_name.getCompleteName(); + } + } + + } + listed_names++; + } + } + if (listed_names > MAX_LISTED_NAMES) + { + LLSD args; + args["EXTRA_COUNT"] = llformat("%d", listed_names - MAX_LISTED_NAMES); + names += " " + LLTrans::getString("AndNMore", args); + } + + if (!names.empty()) // show the conirmation + { + LLSD args; + args["AGENT"] = names; + + if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_ALLOWED_AGENT_REMOVE)) + { + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeAllowedAgents"); + } + else if (flags & (ESTATE_ACCESS_BANNED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) + { + args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents"); + } + + if (flags & ESTATE_ACCESS_APPLY_TO_ALL_ESTATES) + { + args["ESTATE"] = LLTrans::getString("RegionInfoAllEstates"); + } + else if (flags & ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES) + { + args["ESTATE"] = LLTrans::getString("RegionInfoManagedEstates"); + } + else + { + args["ESTATE"] = LLTrans::getString("RegionInfoThisEstate"); + } + + bool single = (listed_names == 1); + if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_ADD | ESTATE_ACCESS_BANNED_AGENT_ADD)) + { + LLNotificationsUtil::add(single ? "AgentWasAddedToList" : "AgentsWereAddedToList", args); + } + else if (flags & (ESTATE_ACCESS_ALLOWED_AGENT_REMOVE | ESTATE_ACCESS_BANNED_AGENT_REMOVE)) + { + LLNotificationsUtil::add(single ? "AgentWasRemovedFromList" : "AgentsWereRemovedFromList", args); + } + } + + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (panel) + { + panel->setPendingUpdate(true); + } + + return false; } // key = "estateaccessdelta" @@ -3794,164 +3794,164 @@ bool LLPanelEstateAccess::accessCoreConfirm(const LLSD& notification, const LLSD // static void LLPanelEstateAccess::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_group_id) { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("EstateOwnerMessage"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("EstateOwnerMessage"); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", "estateaccessdelta"); - msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); + msg->nextBlock("MethodData"); + msg->addString("Method", "estateaccessdelta"); + msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); - std::string buf; - gAgent.getID().toString(buf); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + std::string buf; + gAgent.getID().toString(buf); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); - buf = llformat("%u", flags); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + buf = llformat("%u", flags); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); - agent_or_group_id.toString(buf); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buf); + agent_or_group_id.toString(buf); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buf); - gAgent.sendReliableMessage(); + gAgent.sendReliableMessage(); } void LLPanelEstateAccess::updateChild(LLUICtrl* child_ctrl) { - // Ensure appropriate state of the management ui. - updateControls(gAgent.getRegion()); + // Ensure appropriate state of the management ui. + updateControls(gAgent.getRegion()); } void LLPanelEstateAccess::updateLists() { - std::string cap_url = gAgent.getRegionCapability("EstateAccess"); - if (!cap_url.empty()) - { - LLCoros::instance().launch("LLFloaterRegionInfo::requestEstateGetAccessCoro", boost::bind(LLPanelEstateAccess::requestEstateGetAccessCoro, cap_url)); - } + std::string cap_url = gAgent.getRegionCapability("EstateAccess"); + if (!cap_url.empty()) + { + LLCoros::instance().launch("LLFloaterRegionInfo::requestEstateGetAccessCoro", boost::bind(LLPanelEstateAccess::requestEstateGetAccessCoro, cap_url)); + } } void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) { - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestEstateGetAccessoCoro", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - LLSD result = httpAdapter->getAndSuspend(httpRequest, url); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - - LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); - if (allowed_agent_name_list && result.has("AllowedAgents")) - { - LLStringUtil::format_map_t args; - args["[ALLOWEDAGENTS]"] = llformat("%d", result["AllowedAgents"].size()); - args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); - std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args); - panel->getChild("allow_resident_label")->setValue(LLSD(msg)); - - allowed_agent_name_list->clearSortOrder(); - allowed_agent_name_list->deleteAllItems(); - for (LLSD::array_const_iterator it = result["AllowedAgents"].beginArray(); it != result["AllowedAgents"].endArray(); ++it) - { - LLUUID id = (*it)["id"].asUUID(); - allowed_agent_name_list->addNameItem(id); - } - allowed_agent_name_list->sortByName(TRUE); - } - - LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); - if (banned_agent_name_list && result.has("BannedAgents")) - { - LLStringUtil::format_map_t args; - args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size()); - args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_BANNED_IDS); - std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); - panel->getChild("ban_resident_label")->setValue(LLSD(msg)); - - banned_agent_name_list->clearSortOrder(); - banned_agent_name_list->deleteAllItems(); - for (LLSD::array_const_iterator it = result["BannedAgents"].beginArray(); it != result["BannedAgents"].endArray(); ++it) - { - LLSD item; - item["id"] = (*it)["id"].asUUID(); - LLSD& columns = item["columns"]; - - columns[0]["column"] = "name"; // to be populated later - - columns[1]["column"] = "last_login_date"; - columns[1]["value"] = (*it)["last_login_date"].asString().substr(0, 16); // cut the seconds - - std::string ban_date = (*it)["ban_date"].asString(); - columns[2]["column"] = "ban_date"; - columns[2]["value"] = ban_date[0] != '0' ? ban_date.substr(0, 16) : LLTrans::getString("na"); // server returns the "0000-00-00 00:00:00" date in case it doesn't know it - - columns[3]["column"] = "bannedby"; - LLUUID banning_id = (*it)["banning_id"].asUUID(); - LLAvatarName av_name; - if (banning_id.isNull()) - { - columns[3]["value"] = LLTrans::getString("na"); - } - else if (LLAvatarNameCache::get(banning_id, &av_name)) - { - columns[3]["value"] = av_name.getCompleteName(); //TODO: fetch the name if it wasn't cached - } - - banned_agent_name_list->addElement(item); - } - banned_agent_name_list->sortByName(TRUE); - } - - LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); - if (allowed_group_name_list && result.has("AllowedGroups")) - { - LLStringUtil::format_map_t args; - args["[ALLOWEDGROUPS]"] = llformat("%d", result["AllowedGroups"].size()); - args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_GROUP_IDS); - std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args); - panel->getChild("allow_group_label")->setValue(LLSD(msg)); - - allowed_group_name_list->clearSortOrder(); - allowed_group_name_list->deleteAllItems(); - for (LLSD::array_const_iterator it = result["AllowedGroups"].beginArray(); it != result["AllowedGroups"].endArray(); ++it) - { - LLUUID id = (*it)["id"].asUUID(); - allowed_group_name_list->addGroupNameItem(id); - } - allowed_group_name_list->sortByName(TRUE); - } - - LLNameListCtrl* estate_manager_name_list = panel->getChild("estate_manager_name_list"); - if (estate_manager_name_list && result.has("Managers")) - { - LLStringUtil::format_map_t args; - args["[ESTATEMANAGERS]"] = llformat("%d", result["Managers"].size()); - args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); - std::string msg = LLTrans::getString("RegionInfoEstateManagers", args); - panel->getChild("estate_manager_label")->setValue(LLSD(msg)); - - estate_manager_name_list->clearSortOrder(); - estate_manager_name_list->deleteAllItems(); - for (LLSD::array_const_iterator it = result["Managers"].beginArray(); it != result["Managers"].endArray(); ++it) - { - LLUUID id = (*it)["agent_id"].asUUID(); - estate_manager_name_list->addNameItem(id); - } - estate_manager_name_list->sortByName(TRUE); - } - - - panel->updateControls(gAgent.getRegion()); + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("requestEstateGetAccessoCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + + LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); + if (allowed_agent_name_list && result.has("AllowedAgents")) + { + LLStringUtil::format_map_t args; + args["[ALLOWEDAGENTS]"] = llformat("%d", result["AllowedAgents"].size()); + args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS); + std::string msg = LLTrans::getString("RegionInfoAllowedResidents", args); + panel->getChild("allow_resident_label")->setValue(LLSD(msg)); + + allowed_agent_name_list->clearSortOrder(); + allowed_agent_name_list->deleteAllItems(); + for (LLSD::array_const_iterator it = result["AllowedAgents"].beginArray(); it != result["AllowedAgents"].endArray(); ++it) + { + LLUUID id = (*it)["id"].asUUID(); + allowed_agent_name_list->addNameItem(id); + } + allowed_agent_name_list->sortByName(TRUE); + } + + LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); + if (banned_agent_name_list && result.has("BannedAgents")) + { + LLStringUtil::format_map_t args; + args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size()); + args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_BANNED_IDS); + std::string msg = LLTrans::getString("RegionInfoBannedResidents", args); + panel->getChild("ban_resident_label")->setValue(LLSD(msg)); + + banned_agent_name_list->clearSortOrder(); + banned_agent_name_list->deleteAllItems(); + for (LLSD::array_const_iterator it = result["BannedAgents"].beginArray(); it != result["BannedAgents"].endArray(); ++it) + { + LLSD item; + item["id"] = (*it)["id"].asUUID(); + LLSD& columns = item["columns"]; + + columns[0]["column"] = "name"; // to be populated later + + columns[1]["column"] = "last_login_date"; + columns[1]["value"] = (*it)["last_login_date"].asString().substr(0, 16); // cut the seconds + + std::string ban_date = (*it)["ban_date"].asString(); + columns[2]["column"] = "ban_date"; + columns[2]["value"] = ban_date[0] != '0' ? ban_date.substr(0, 16) : LLTrans::getString("na"); // server returns the "0000-00-00 00:00:00" date in case it doesn't know it + + columns[3]["column"] = "bannedby"; + LLUUID banning_id = (*it)["banning_id"].asUUID(); + LLAvatarName av_name; + if (banning_id.isNull()) + { + columns[3]["value"] = LLTrans::getString("na"); + } + else if (LLAvatarNameCache::get(banning_id, &av_name)) + { + columns[3]["value"] = av_name.getCompleteName(); //TODO: fetch the name if it wasn't cached + } + + banned_agent_name_list->addElement(item); + } + banned_agent_name_list->sortByName(TRUE); + } + + LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); + if (allowed_group_name_list && result.has("AllowedGroups")) + { + LLStringUtil::format_map_t args; + args["[ALLOWEDGROUPS]"] = llformat("%d", result["AllowedGroups"].size()); + args["[MAXACCESS]"] = llformat("%d", ESTATE_MAX_GROUP_IDS); + std::string msg = LLTrans::getString("RegionInfoAllowedGroups", args); + panel->getChild("allow_group_label")->setValue(LLSD(msg)); + + allowed_group_name_list->clearSortOrder(); + allowed_group_name_list->deleteAllItems(); + for (LLSD::array_const_iterator it = result["AllowedGroups"].beginArray(); it != result["AllowedGroups"].endArray(); ++it) + { + LLUUID id = (*it)["id"].asUUID(); + allowed_group_name_list->addGroupNameItem(id); + } + allowed_group_name_list->sortByName(TRUE); + } + + LLNameListCtrl* estate_manager_name_list = panel->getChild("estate_manager_name_list"); + if (estate_manager_name_list && result.has("Managers")) + { + LLStringUtil::format_map_t args; + args["[ESTATEMANAGERS]"] = llformat("%d", result["Managers"].size()); + args["[MAXMANAGERS]"] = llformat("%d", ESTATE_MAX_MANAGERS); + std::string msg = LLTrans::getString("RegionInfoEstateManagers", args); + panel->getChild("estate_manager_label")->setValue(LLSD(msg)); + + estate_manager_name_list->clearSortOrder(); + estate_manager_name_list->deleteAllItems(); + for (LLSD::array_const_iterator it = result["Managers"].beginArray(); it != result["Managers"].endArray(); ++it) + { + LLUUID id = (*it)["agent_id"].asUUID(); + estate_manager_name_list->addNameItem(id); + } + estate_manager_name_list->sortByName(TRUE); + } + + + panel->updateControls(gAgent.getRegion()); } //--------------------------------------------------------------------------- @@ -3959,76 +3959,76 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url) //--------------------------------------------------------------------------- void LLPanelEstateAccess::onAllowedSearchEdit(const std::string& search_string) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); - searchAgent(allowed_agent_name_list, search_string); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* allowed_agent_name_list = panel->getChild("allowed_avatar_name_list"); + searchAgent(allowed_agent_name_list, search_string); } void LLPanelEstateAccess::onAllowedGroupsSearchEdit(const std::string& search_string) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); - searchAgent(allowed_group_name_list, search_string); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* allowed_group_name_list = panel->getChild("allowed_group_name_list"); + searchAgent(allowed_group_name_list, search_string); } void LLPanelEstateAccess::onBannedSearchEdit(const std::string& search_string) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); - searchAgent(banned_agent_name_list, search_string); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* banned_agent_name_list = panel->getChild("banned_avatar_name_list"); + searchAgent(banned_agent_name_list, search_string); } void LLPanelEstateAccess::searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string) { - if (!listCtrl) return; + if (!listCtrl) return; - if (!search_string.empty()) - { - listCtrl->setSearchColumn(0); // name column - listCtrl->searchItems(search_string, false, true); - } - else - { - listCtrl->deselectAllItems(TRUE); - } + if (!search_string.empty()) + { + listCtrl->setSearchColumn(0); // name column + listCtrl->searchItems(search_string, false, true); + } + else + { + listCtrl->deselectAllItems(TRUE); + } } void LLPanelEstateAccess::copyListToClipboard(std::string list_name) { - LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); - if (!panel) return; - LLNameListCtrl* name_list = panel->getChild(list_name); - if (!name_list) return; - - std::vector list_vector = name_list->getAllData(); - if (list_vector.size() == 0) return; - - LLSD::String list_to_copy; - for (std::vector::const_iterator iter = list_vector.begin(); - iter != list_vector.end(); - iter++) - { - LLScrollListItem *item = (*iter); - if (item) - { - list_to_copy += item->getColumn(0)->getValue().asString(); - } - if (std::next(iter) != list_vector.end()) - { - list_to_copy += "\n"; - } - } - - LLClipboard::instance().copyToClipboard(utf8str_to_wstring(list_to_copy), 0, list_to_copy.length()); + LLPanelEstateAccess* panel = LLFloaterRegionInfo::getPanelAccess(); + if (!panel) return; + LLNameListCtrl* name_list = panel->getChild(list_name); + if (!name_list) return; + + std::vector list_vector = name_list->getAllData(); + if (list_vector.size() == 0) return; + + LLSD::String list_to_copy; + for (std::vector::const_iterator iter = list_vector.begin(); + iter != list_vector.end(); + iter++) + { + LLScrollListItem *item = (*iter); + if (item) + { + list_to_copy += item->getColumn(0)->getValue().asString(); + } + if (std::next(iter) != list_vector.end()) + { + list_to_copy += "\n"; + } + } + + LLClipboard::instance().copyToClipboard(utf8str_to_wstring(list_to_copy), 0, list_to_copy.length()); } bool LLPanelEstateAccess::refreshFromRegion(LLViewerRegion* region) { - updateLists(); - return LLPanelRegionInfo::refreshFromRegion(region); + updateLists(); + return LLPanelRegionInfo::refreshFromRegion(region); } //========================================================================= @@ -4164,10 +4164,10 @@ void LLPanelRegionEnvironment::onChkAllowOverride(bool value) if (LLPanelEstateInfo::isLindenEstate()) notification = "ChangeLindenEstate"; - LLSD args; - args["ESTATENAME"] = LLEstateInfoModel::instance().getName(); - LLNotification::Params params(notification); - params.substitutions(args); + LLSD args; + args["ESTATENAME"] = LLEstateInfoModel::instance().getName(); + LLNotification::Params params(notification); + params.substitutions(args); params.functor.function([this](const LLSD& notification, const LLSD& response) { confirmUpdateEstateEnvironment(notification, response); }); if (!value || LLPanelEstateInfo::isLindenEstate()) diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index da17212016..c96e11b5be 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -1,4 +1,4 @@ -/** +/** * @file llfloaterregioninfo.h * @author Aaron Brashears * @brief Declaration of the region info and controls floater and panels. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -73,58 +73,58 @@ class LLEventTimer; class LLFloaterRegionInfo : public LLFloater { - friend class LLFloaterReg; + friend class LLFloaterReg; public: - void onOpen(const LLSD& key) override; - void onClose(bool app_quitting) override; - BOOL postBuild() override; + void onOpen(const LLSD& key) override; + void onClose(bool app_quitting) override; + BOOL postBuild() override; + + static void processEstateOwnerRequest(LLMessageSystem* msg, void**); - static void processEstateOwnerRequest(LLMessageSystem* msg, void**); + // get and process region info if necessary. + static void processRegionInfo(LLMessageSystem* msg); - // get and process region info if necessary. - static void processRegionInfo(LLMessageSystem* msg); + static const LLUUID& getLastInvoice() { return sRequestInvoice; } + static void nextInvoice() { sRequestInvoice.generate(); } + //static S32 getSerial() { return sRequestSerial; } + //static void incrementSerial() { sRequestSerial++; } - static const LLUUID& getLastInvoice() { return sRequestInvoice; } - static void nextInvoice() { sRequestInvoice.generate(); } - //static S32 getSerial() { return sRequestSerial; } - //static void incrementSerial() { sRequestSerial++; } + static LLPanelEstateInfo* getPanelEstate(); + static LLPanelEstateAccess* getPanelAccess(); + static LLPanelEstateCovenant* getPanelCovenant(); + static LLPanelRegionTerrainInfo* getPanelRegionTerrain(); + static LLPanelRegionExperiences* getPanelExperiences(); + static LLPanelRegionGeneralInfo* getPanelGeneral(); + static LLPanelRegionEnvironment* getPanelEnvironment(); - static LLPanelEstateInfo* getPanelEstate(); - static LLPanelEstateAccess* getPanelAccess(); - static LLPanelEstateCovenant* getPanelCovenant(); - static LLPanelRegionTerrainInfo* getPanelRegionTerrain(); - static LLPanelRegionExperiences* getPanelExperiences(); - static LLPanelRegionGeneralInfo* getPanelGeneral(); - static LLPanelRegionEnvironment* getPanelEnvironment(); + // from LLPanel + void refresh() override; - // from LLPanel - void refresh() override; - - void onRegionChanged(); - void requestRegionInfo(); - void enableTopButtons(); - void disableTopButtons(); + void onRegionChanged(); + void requestRegionInfo(); + void enableTopButtons(); + void disableTopButtons(); private: - - LLFloaterRegionInfo(const LLSD& seed); - ~LLFloaterRegionInfo(); + + LLFloaterRegionInfo(const LLSD& seed); + ~LLFloaterRegionInfo(); protected: - void onTabSelected(const LLSD& param); - void disableTabCtrls(); - void refreshFromRegion(LLViewerRegion* region); - void onGodLevelChange(U8 god_level); - - // member data - LLTabContainer* mTab; - typedef std::vector info_panels_t; - info_panels_t mInfoPanels; + void onTabSelected(const LLSD& param); + void disableTabCtrls(); + void refreshFromRegion(LLViewerRegion* region); + void onGodLevelChange(U8 god_level); + + // member data + LLTabContainer* mTab; + typedef std::vector info_panels_t; + info_panels_t mInfoPanels; LLPanelRegionEnvironment *mEnvironmentPanel; - //static S32 sRequestSerial; // serial # of last EstateOwnerRequest - static LLUUID sRequestInvoice; + //static S32 sRequestSerial; // serial # of last EstateOwnerRequest + static LLUUID sRequestInvoice; private: LLAgent::god_level_change_slot_t mGodLevelChangeSlot; @@ -136,42 +136,42 @@ private: class LLPanelRegionInfo : public LLPanel { public: - LLPanelRegionInfo(); - - void onBtnSet(); - void onChangeChildCtrl(LLUICtrl* ctrl); - void onChangeAnything(); - static void onChangeText(LLLineEditor* caller, void* user_data); - - virtual bool refreshFromRegion(LLViewerRegion* region); - virtual bool estateUpdate(LLMessageSystem* msg) { return true; } - - BOOL postBuild() override; - virtual void updateChild(LLUICtrl* child_ctrl); - - void enableButton(const std::string& btn_name, BOOL enable = TRUE); - void disableButton(const std::string& btn_name); - - void onClickManageTelehub(); - + LLPanelRegionInfo(); + + void onBtnSet(); + void onChangeChildCtrl(LLUICtrl* ctrl); + void onChangeAnything(); + static void onChangeText(LLLineEditor* caller, void* user_data); + + virtual bool refreshFromRegion(LLViewerRegion* region); + virtual bool estateUpdate(LLMessageSystem* msg) { return true; } + + BOOL postBuild() override; + virtual void updateChild(LLUICtrl* child_ctrl); + + void enableButton(const std::string& btn_name, BOOL enable = TRUE); + void disableButton(const std::string& btn_name); + + void onClickManageTelehub(); + protected: - void initCtrl(const std::string& name); - - // Returns TRUE if update sent and apply button should be - // disabled. - virtual BOOL sendUpdate() { return TRUE; } - - typedef std::vector strings_t; - //typedef std::vector integers_t; - void sendEstateOwnerMessage( - LLMessageSystem* msg, - const std::string& request, - const LLUUID& invoice, - const strings_t& strings); - - - // member data - LLHost mHost; + void initCtrl(const std::string& name); + + // Returns TRUE if update sent and apply button should be + // disabled. + virtual BOOL sendUpdate() { return TRUE; } + + typedef std::vector strings_t; + //typedef std::vector integers_t; + void sendEstateOwnerMessage( + LLMessageSystem* msg, + const std::string& request, + const LLUUID& invoice, + const strings_t& strings); + + + // member data + LLHost mHost; }; ///////////////////////////////////////////////////////////////////////////// @@ -180,30 +180,30 @@ protected: class LLPanelRegionGeneralInfo : public LLPanelRegionInfo { - + public: - LLPanelRegionGeneralInfo() - : LLPanelRegionInfo() {} - ~LLPanelRegionGeneralInfo() {} - - bool refreshFromRegion(LLViewerRegion* region) override; - - BOOL postBuild() override; - - void onBtnSet(); - void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} + LLPanelRegionGeneralInfo() + : LLPanelRegionInfo() {} + ~LLPanelRegionGeneralInfo() {} + + bool refreshFromRegion(LLViewerRegion* region) override; + + BOOL postBuild() override; + + void onBtnSet(); + void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} protected: - BOOL sendUpdate() override; - void onClickKick(); - void onKickCommit(const uuid_vec_t& ids); - static void onClickKickAll(void* userdata); - bool onKickAllCommit(const LLSD& notification, const LLSD& response); - static void onClickMessage(void* userdata); - bool onMessageCommit(const LLSD& notification, const LLSD& response); - bool onChangeObjectBonus(const LLSD& notification, const LLSD& response); + BOOL sendUpdate() override; + void onClickKick(); + void onKickCommit(const uuid_vec_t& ids); + static void onClickKickAll(void* userdata); + bool onKickAllCommit(const LLSD& notification, const LLSD& response); + static void onClickMessage(void* userdata); + bool onMessageCommit(const LLSD& notification, const LLSD& response); + bool onChangeObjectBonus(const LLSD& notification, const LLSD& response); - F32 mObjBonusFactor; + F32 mObjBonusFactor; }; @@ -212,68 +212,68 @@ protected: class LLPanelRegionDebugInfo : public LLPanelRegionInfo { public: - LLPanelRegionDebugInfo() - : LLPanelRegionInfo(), mTargetAvatar() {} - ~LLPanelRegionDebugInfo() {} - - BOOL postBuild() override; - - bool refreshFromRegion(LLViewerRegion* region) override; - + LLPanelRegionDebugInfo() + : LLPanelRegionInfo(), mTargetAvatar() {} + ~LLPanelRegionDebugInfo() {} + + BOOL postBuild() override; + + bool refreshFromRegion(LLViewerRegion* region) override; + protected: - BOOL sendUpdate() override; - - void onClickChooseAvatar(); - void callbackAvatarID(const uuid_vec_t& ids, const std::vector names); - static void onClickReturn(void *); - bool callbackReturn(const LLSD& notification, const LLSD& response); - static void onClickTopColliders(void*); - static void onClickTopScripts(void*); - static void onClickRestart(void* data); - bool callbackRestart(const LLSD& notification, const LLSD& response); - static void onClickCancelRestart(void* data); - static void onClickDebugConsole(void* data); - + BOOL sendUpdate() override; + + void onClickChooseAvatar(); + void callbackAvatarID(const uuid_vec_t& ids, const std::vector names); + static void onClickReturn(void *); + bool callbackReturn(const LLSD& notification, const LLSD& response); + static void onClickTopColliders(void*); + static void onClickTopScripts(void*); + static void onClickRestart(void* data); + bool callbackRestart(const LLSD& notification, const LLSD& response); + static void onClickCancelRestart(void* data); + static void onClickDebugConsole(void* data); + private: - LLUUID mTargetAvatar; + LLUUID mTargetAvatar; }; ///////////////////////////////////////////////////////////////////////////// class LLPanelRegionTerrainInfo : public LLPanelRegionInfo { - LOG_CLASS(LLPanelRegionTerrainInfo); + LOG_CLASS(LLPanelRegionTerrainInfo); public: - LLPanelRegionTerrainInfo(); - ~LLPanelRegionTerrainInfo() {} - - BOOL postBuild() override; - + LLPanelRegionTerrainInfo(); + ~LLPanelRegionTerrainInfo() {} + + BOOL postBuild() override; + bool refreshFromRegion(LLViewerRegion* region) override; // refresh local settings from region update from simulator - void setEnvControls(bool available); // Whether environment settings are available for this region + void setEnvControls(bool available); // Whether environment settings are available for this region bool validateTextureSizes(); bool validateMaterials(); - BOOL validateTextureHeights(); + BOOL validateTextureHeights(); + + //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button - //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button - void onSelectMaterialType(); void updateForMaterialType(); - static void onClickDownloadRaw(void*); - static void onClickUploadRaw(void*); - static void onClickBakeTerrain(void*); - bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); - bool callbackTextureHeights(const LLSD& notification, const LLSD& response); + static void onClickDownloadRaw(void*); + static void onClickUploadRaw(void*); + static void onClickBakeTerrain(void*); + bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); + bool callbackTextureHeights(const LLSD& notification, const LLSD& response); protected: - BOOL sendUpdate() override; + BOOL sendUpdate() override; private: - bool mConfirmedTextureHeights; - bool mAskedTextureHeights; + bool mConfirmedTextureHeights; + bool mAskedTextureHeights; LLCheckBoxCtrl* mMaterialTypeCtrl = nullptr; LLTextureCtrl* mTextureDetailCtrl[LLTerrainMaterials::ASSET_COUNT]; LLTextureCtrl* mMaterialDetailCtrl[LLTerrainMaterials::ASSET_COUNT]; @@ -286,59 +286,59 @@ private: class LLPanelEstateInfo : public LLPanelRegionInfo { public: - static void initDispatch(LLDispatcher& dispatch); - - void onChangeFixedSun(); - void onChangeUseGlobalTime(); - void onChangeAccessOverride(); - - void onClickEditSky(); - void onClickEditSkyHelp(); - void onClickEditDayCycle(); - void onClickEditDayCycleHelp(); - - void onClickKickUser(); - - - bool kickUserConfirm(const LLSD& notification, const LLSD& response); - - void onKickUserCommit(const uuid_vec_t& ids); - static void onClickMessageEstate(void* data); - bool onMessageCommit(const LLSD& notification, const LLSD& response); - - LLPanelEstateInfo(); - ~LLPanelEstateInfo() {} - - void updateControls(LLViewerRegion* region); - - static void updateEstateName(const std::string& name); - static void updateEstateOwnerName(const std::string& name); - - bool refreshFromRegion(LLViewerRegion* region) override; - bool estateUpdate(LLMessageSystem* msg) override; - - BOOL postBuild() override; - void updateChild(LLUICtrl* child_ctrl) override; - void refresh() override; - - void refreshFromEstate(); - - static bool isLindenEstate(); - - const std::string getOwnerName() const; - void setOwnerName(const std::string& name); + static void initDispatch(LLDispatcher& dispatch); + + void onChangeFixedSun(); + void onChangeUseGlobalTime(); + void onChangeAccessOverride(); + + void onClickEditSky(); + void onClickEditSkyHelp(); + void onClickEditDayCycle(); + void onClickEditDayCycleHelp(); + + void onClickKickUser(); + + + bool kickUserConfirm(const LLSD& notification, const LLSD& response); + + void onKickUserCommit(const uuid_vec_t& ids); + static void onClickMessageEstate(void* data); + bool onMessageCommit(const LLSD& notification, const LLSD& response); + + LLPanelEstateInfo(); + ~LLPanelEstateInfo() {} + + void updateControls(LLViewerRegion* region); + + static void updateEstateName(const std::string& name); + static void updateEstateOwnerName(const std::string& name); + + bool refreshFromRegion(LLViewerRegion* region) override; + bool estateUpdate(LLMessageSystem* msg) override; + + BOOL postBuild() override; + void updateChild(LLUICtrl* child_ctrl) override; + void refresh() override; + + void refreshFromEstate(); + + static bool isLindenEstate(); + + const std::string getOwnerName() const; + void setOwnerName(const std::string& name); protected: - BOOL sendUpdate() override; - // confirmation dialog callback - bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response); + BOOL sendUpdate() override; + // confirmation dialog callback + bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response); + + void commitEstateAccess(); + void commitEstateManagers(); - void commitEstateAccess(); - void commitEstateManagers(); - - BOOL checkSunHourSlider(LLUICtrl* child_ctrl); + BOOL checkSunHourSlider(LLUICtrl* child_ctrl); - U32 mEstateID; + U32 mEstateID; }; ///////////////////////////////////////////////////////////////////////////// @@ -346,59 +346,59 @@ protected: class LLPanelEstateCovenant : public LLPanelRegionInfo { public: - LLPanelEstateCovenant(); - ~LLPanelEstateCovenant() {} - - BOOL postBuild() override; - void updateChild(LLUICtrl* child_ctrl) override; - bool refreshFromRegion(LLViewerRegion* region) override; - bool estateUpdate(LLMessageSystem* msg) override; - - // LLView overrides - BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, - void *cargo_data, EAcceptance *accept, - std::string& tooltip_msg) override; - static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response); - static void resetCovenantID(void* userdata); - static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response); - void sendChangeCovenantID(const LLUUID &asset_id); - void loadInvItem(LLInventoryItem *itemp); - static void onLoadComplete(const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); - - // Accessor functions - static void updateCovenantText(const std::string& string, const LLUUID& asset_id); - static void updateEstateName(const std::string& name); - static void updateLastModified(const std::string& text); - static void updateEstateOwnerName(const std::string& name); - - const LLUUID& getCovenantID() const { return mCovenantID; } - void setCovenantID(const LLUUID& id) { mCovenantID = id; } - std::string getEstateName() const; - void setEstateName(const std::string& name); - std::string getOwnerName() const; - void setOwnerName(const std::string& name); - void setCovenantTextEditor(const std::string& text); - - typedef enum e_asset_status - { - ASSET_ERROR, - ASSET_UNLOADED, - ASSET_LOADING, - ASSET_LOADED - } EAssetStatus; + LLPanelEstateCovenant(); + ~LLPanelEstateCovenant() {} + + BOOL postBuild() override; + void updateChild(LLUICtrl* child_ctrl) override; + bool refreshFromRegion(LLViewerRegion* region) override; + bool estateUpdate(LLMessageSystem* msg) override; + + // LLView overrides + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, + void *cargo_data, EAcceptance *accept, + std::string& tooltip_msg) override; + static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response); + static void resetCovenantID(void* userdata); + static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response); + void sendChangeCovenantID(const LLUUID &asset_id); + void loadInvItem(LLInventoryItem *itemp); + static void onLoadComplete(const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + + // Accessor functions + static void updateCovenantText(const std::string& string, const LLUUID& asset_id); + static void updateEstateName(const std::string& name); + static void updateLastModified(const std::string& text); + static void updateEstateOwnerName(const std::string& name); + + const LLUUID& getCovenantID() const { return mCovenantID; } + void setCovenantID(const LLUUID& id) { mCovenantID = id; } + std::string getEstateName() const; + void setEstateName(const std::string& name); + std::string getOwnerName() const; + void setOwnerName(const std::string& name); + void setCovenantTextEditor(const std::string& text); + + typedef enum e_asset_status + { + ASSET_ERROR, + ASSET_UNLOADED, + ASSET_LOADING, + ASSET_LOADED + } EAssetStatus; protected: - BOOL sendUpdate() override; - LLTextBox* mEstateNameText; - LLTextBox* mEstateOwnerText; - LLTextBox* mLastModifiedText; - // CovenantID from sim - LLUUID mCovenantID; - LLViewerTextEditor* mEditor; - EAssetStatus mAssetStatus; + BOOL sendUpdate() override; + LLTextBox* mEstateNameText; + LLTextBox* mEstateOwnerText; + LLTextBox* mLastModifiedText; + // CovenantID from sim + LLUUID mCovenantID; + LLViewerTextEditor* mEditor; + EAssetStatus mAssetStatus; }; ///////////////////////////////////////////////////////////////////////////// @@ -409,96 +409,96 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo LOG_CLASS(LLPanelRegionExperiences); public: - LLPanelRegionExperiences(){} - BOOL postBuild() override; - - static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); - static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); + LLPanelRegionExperiences(){} + BOOL postBuild() override; - static void infoCallback(LLHandle handle, const LLSD& content); - bool refreshFromRegion(LLViewerRegion* region) override; - void sendPurchaseRequest()const; - void processResponse( const LLSD& content ); + static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); + static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); + + static void infoCallback(LLHandle handle, const LLSD& content); + bool refreshFromRegion(LLViewerRegion* region) override; + void sendPurchaseRequest()const; + void processResponse( const LLSD& content ); protected: - BOOL sendUpdate() override; + BOOL sendUpdate() override; private: - void refreshRegionExperiences(); + void refreshRegionExperiences(); static std::string regionCapabilityQuery(LLViewerRegion* region, const std::string &cap); - LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id); - static LLSD addIds( LLPanelExperienceListEditor* panel ); + LLPanelExperienceListEditor* setupList(const char* control_name, U32 add_id, U32 remove_id); + static LLSD addIds( LLPanelExperienceListEditor* panel ); - void itemChanged(U32 event_type, const LLUUID& id); + void itemChanged(U32 event_type, const LLUUID& id); - LLPanelExperienceListEditor* mTrusted; - LLPanelExperienceListEditor* mAllowed; - LLPanelExperienceListEditor* mBlocked; - LLUUID mDefaultExperience; + LLPanelExperienceListEditor* mTrusted; + LLPanelExperienceListEditor* mAllowed; + LLPanelExperienceListEditor* mBlocked; + LLUUID mDefaultExperience; }; class LLPanelEstateAccess : public LLPanelRegionInfo { - LOG_CLASS(LLPanelEstateAccess); + LOG_CLASS(LLPanelEstateAccess); public: - LLPanelEstateAccess(); + LLPanelEstateAccess(); - BOOL postBuild() override; - void updateChild(LLUICtrl* child_ctrl) override; + BOOL postBuild() override; + void updateChild(LLUICtrl* child_ctrl) override; - void updateControls(LLViewerRegion* region); - void updateLists(); + void updateControls(LLViewerRegion* region); + void updateLists(); - void setPendingUpdate(bool pending) { mPendingUpdate = pending; } - bool getPendingUpdate() { return mPendingUpdate; } + void setPendingUpdate(bool pending) { mPendingUpdate = pending; } + bool getPendingUpdate() { return mPendingUpdate; } - bool refreshFromRegion(LLViewerRegion* region) override; + bool refreshFromRegion(LLViewerRegion* region) override; private: - void onClickAddAllowedAgent(); - void onClickRemoveAllowedAgent(); - void onClickCopyAllowedList(); - void onClickAddAllowedGroup(); - void onClickRemoveAllowedGroup(); - void onClickCopyAllowedGroupList(); - void onClickAddBannedAgent(); - void onClickRemoveBannedAgent(); + void onClickAddAllowedAgent(); + void onClickRemoveAllowedAgent(); + void onClickCopyAllowedList(); + void onClickAddAllowedGroup(); + void onClickRemoveAllowedGroup(); + void onClickCopyAllowedGroupList(); + void onClickAddBannedAgent(); + void onClickRemoveBannedAgent(); void onClickCopyBannedList(); - void onClickAddEstateManager(); - void onClickRemoveEstateManager(); - void onAllowedSearchEdit(const std::string& search_string); - void onAllowedGroupsSearchEdit(const std::string& search_string); - void onBannedSearchEdit(const std::string& search_string); - - // Group picker callback is different, can't use core methods below - bool addAllowedGroup(const LLSD& notification, const LLSD& response); - void addAllowedGroup2(LLUUID id); + void onClickAddEstateManager(); + void onClickRemoveEstateManager(); + void onAllowedSearchEdit(const std::string& search_string); + void onAllowedGroupsSearchEdit(const std::string& search_string); + void onBannedSearchEdit(const std::string& search_string); + + // Group picker callback is different, can't use core methods below + bool addAllowedGroup(const LLSD& notification, const LLSD& response); + void addAllowedGroup2(LLUUID id); - // Core methods for all above add/remove button clicks - static void accessAddCore(U32 operation_flag, const std::string& dialog_name); - static bool accessAddCore2(const LLSD& notification, const LLSD& response); - static void accessAddCore3(const uuid_vec_t& ids, std::vector names, void* data); + // Core methods for all above add/remove button clicks + static void accessAddCore(U32 operation_flag, const std::string& dialog_name); + static bool accessAddCore2(const LLSD& notification, const LLSD& response); + static void accessAddCore3(const uuid_vec_t& ids, std::vector names, void* data); - static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name); - static bool accessRemoveCore2(const LLSD& notification, const LLSD& response); + static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name); + static bool accessRemoveCore2(const LLSD& notification, const LLSD& response); - // used for both add and remove operations - static bool accessCoreConfirm(const LLSD& notification, const LLSD& response); + // used for both add and remove operations + static bool accessCoreConfirm(const LLSD& notification, const LLSD& response); - // Send the actual EstateOwnerRequest "estateaccessdelta" message - static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); + // Send the actual EstateOwnerRequest "estateaccessdelta" message + static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id); - static void requestEstateGetAccessCoro(std::string url); + static void requestEstateGetAccessCoro(std::string url); - void searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string); - void copyListToClipboard(std::string list_name); + void searchAgent(LLNameListCtrl* listCtrl, const std::string& search_string); + void copyListToClipboard(std::string list_name); - bool mPendingUpdate; - BOOL mCtrlsEnabled; + bool mPendingUpdate; + BOOL mCtrlsEnabled; }; #endif diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index 1c39f1ae7d..730a625879 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -302,12 +302,12 @@ PreviewSphere create_preview_sphere(LLPointer& material, LLStrider texcoords; LLStrider colors; LLStrider tangents; - buf->getIndexStrider(indices); - buf->getVertexStrider(positions); - buf->getNormalStrider(normals); - buf->getTexCoord0Strider(texcoords); - buf->getColorStrider(colors); - buf->getTangentStrider(tangents); + buf->getIndexStrider(indices); + buf->getVertexStrider(positions); + buf->getNormalStrider(normals); + buf->getTexCoord0Strider(texcoords); + buf->getColorStrider(colors); + buf->getTangentStrider(tangents); U32 index_offset = 0; U32 vertex_offset = 0; for (const LLVolumeFace& face : volume->getVolumeFaces()) @@ -427,7 +427,7 @@ BOOL LLGLTFPreviewTexture::render() glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + LLGLDepthTest(GL_FALSE); LLGLDisable stencil(GL_STENCIL_TEST); LLGLDisable scissor(GL_SCISSOR_TEST); @@ -527,27 +527,27 @@ BOOL LLGLTFPreviewTexture::render() LLVertexBuffer::unbind(); gPipeline.generateGlow(&gPipeline.mPostMap); gPipeline.combineGlow(&gPipeline.mPostMap, &screen); - gPipeline.renderDoF(&screen, &gPipeline.mPostMap); - gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); + gPipeline.renderDoF(&screen, &gPipeline.mPostMap); + gPipeline.applyFXAA(&gPipeline.mPostMap, &screen); // *HACK: Restore mExposureMap (it will be consumed by generateExposure next frame) gPipeline.mExposureMap.swapFBORefs(gPipeline.mLastExposure); // Final render - gDeferredPostNoDoFProgram.bind(); + gDeferredPostNoDoFProgram.bind(); - // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems." - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen); - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true); + // From LLPipeline::renderFinalize: "Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems." + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &screen); + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, mBoundTarget, true); - { - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); - gPipeline.mScreenTriangleVB->setBuffer(); - gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + gPipeline.mScreenTriangleVB->setBuffer(); + gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } - gDeferredPostNoDoFProgram.unbind(); + gDeferredPostNoDoFProgram.unbind(); // Clean up gPipeline.setupHWLights(); diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 55539a49d8..208dfe45bd 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -66,7 +66,7 @@ LLHeroProbeManager::LLHeroProbeManager() LLHeroProbeManager::~LLHeroProbeManager() { - cleanup(); + cleanup(); mHeroVOList.clear(); mNearestHero = nullptr; @@ -130,7 +130,7 @@ void LLHeroProbeManager::update() float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); if (distance > LLViewerCamera::instance().getFar()) - continue; + continue; LLVector4a center; center.load3(vo->getPositionAgent().mV); @@ -142,18 +142,18 @@ void LLHeroProbeManager::update() if (distance < last_distance && center_distance < camera_center_distance && visible) { - probe_present = true; - mNearestHero = vo; - last_distance = distance; + probe_present = true; + mNearestHero = vo; + last_distance = distance; camera_center_distance = center_distance; - } + } } else { unregisterViewerObject(vo); } } - + // Don't even try to do anything if we didn't find a single mirror present. if (!probe_present) return; @@ -162,7 +162,7 @@ void LLHeroProbeManager::update() { LLVector3 hero_pos = mNearestHero->getPositionAgent(); LLVector3 face_normal = LLVector3(0, 0, 1); - + face_normal *= mNearestHero->mDrawable->getWorldRotation(); face_normal.normalize(); @@ -180,8 +180,8 @@ void LLHeroProbeManager::update() // Detect visible faces of a cube based on camera direction and distance // Define the cube faces - static LLVector3 cubeFaces[6] = { - LLVector3(1, 0, 0), + static LLVector3 cubeFaces[6] = { + LLVector3(1, 0, 0), LLVector3(-1, 0, 0), LLVector3(0, 1, 0), LLVector3(0, -1, 0), @@ -193,7 +193,7 @@ void LLHeroProbeManager::update() for (int i = 0; i < 6; i++) { float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; - + float updateRate; if (cube_facing < 0.1f) { @@ -208,18 +208,18 @@ void LLHeroProbeManager::update() } } else - { + { mNearestHero = nullptr; } - + mHeroProbeStrength = 1; } else { probe_pos.load3(camera_pos.mV); } - - + + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); @@ -228,9 +228,9 @@ void LLHeroProbeManager::update() LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); // Probe 0 is always our mirror probe. mProbes[0]->mOrigin = probe_pos; - + bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); - + gPipeline.mReflectionMapManager.mRadiancePass = true; mRenderingMirror = true; @@ -249,19 +249,19 @@ void LLHeroProbeManager::update() generateRadiance(mProbes[j]); } mRenderingMirror = false; - + gPipeline.mReflectionMapManager.mRadiancePass = radiance_pass; mProbes[0]->mViewerObject = mNearestHero; mProbes[0]->autoAdjustOrigin(); } - + mCurrentProbeUpdateFrame++; } // Do the reflection map update render passes. // For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated -// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate +// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate // a simple mip chain (not convolution filter). // At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe // The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain. @@ -273,11 +273,11 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool gPipeline.mRT = &gPipeline.mHeroProbeRT; probe->update(mRenderTarget.getWidth(), face, is_dynamic, near_clip); - + gPipeline.mRT = &gPipeline.mMainRT; S32 sourceIdx = mReflectionProbeCount; - + // Unlike the reflectionmap manager, all probes are considered "realtime" for hero probes. sourceIdx += 1; @@ -285,7 +285,7 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool LLGLDepthTest depth(GL_FALSE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); LLGLDisable blend(GL_BLEND); - + // downsample to placeholder map { gGL.matrixMode(gGL.MM_MODELVIEW); @@ -351,14 +351,14 @@ void LLHeroProbeManager::updateProbeFace(LLReflectionMap* probe, U32 face, bool } gGL.getTexUnit(depthChannel)->bind(depth_rt, true); - + gReflectionMipProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2)); gReflectionMipProgram.uniform1f(znear, probe->getNearClip()); gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP); - + gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - + res /= 2; S32 mip = i - (mMipChain.size() - mips); @@ -459,13 +459,13 @@ void LLHeroProbeManager::updateUniforms() } LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - + LLMatrix4a modelview; modelview.loadu(gGLModelView); LLVector4a oa; // scratch space for transformed origin oa.set(0, 0, 0, 0); mHeroData.heroProbeCount = 1; - + if (mNearestHero != nullptr && !mNearestHero->isDead()) { if (mNearestHero->getReflectionProbeIsBox()) @@ -477,18 +477,18 @@ void LLHeroProbeManager::updateUniforms() { mProbes[0]->mRadius = mNearestHero->getScale().mV[0] * 0.5f; } - + modelview.affineTransform(mProbes[0]->mOrigin, oa); mHeroData.heroShape = 0; if (!mProbes[0]->getBox(mHeroData.heroBox)) { mHeroData.heroShape = 1; } - + mHeroData.heroSphere.set(oa.getF32ptr()); mHeroData.heroSphere.mV[3] = mProbes[0]->mRadius; } - + mHeroData.heroMipCount = mMipChain.size(); } @@ -537,14 +537,14 @@ void LLHeroProbeManager::initReflectionMaps() llassert(mProbes[0] == mDefaultProbe); // For hero probes, we treat this as the main mirror probe. - + mDefaultProbe->mCubeIndex = 0; mDefaultProbe->mCubeArray = mTexture; mDefaultProbe->mDistance = gSavedSettings.getF32("RenderHeroProbeDistance"); mDefaultProbe->mRadius = 4096.f; mDefaultProbe->mProbeIndex = 0; touch_default_probe(mDefaultProbe); - + mProbes.push_back(mDefaultProbe); } @@ -555,9 +555,9 @@ void LLHeroProbeManager::initReflectionMaps() buff->allocateBuffer(4, 0); LLStrider v; - + buff->getVertexStrider(v); - + v[0] = LLVector3(-1, -1, -1); v[1] = LLVector3(1, -1, -1); v[2] = LLVector3(-1, 1, -1); @@ -569,8 +569,8 @@ void LLHeroProbeManager::initReflectionMaps() } } -void LLHeroProbeManager::cleanup() -{ +void LLHeroProbeManager::cleanup() +{ mVertexBuffer = nullptr; mRenderTarget.release(); mHeroRenderTarget.release(); @@ -582,7 +582,7 @@ void LLHeroProbeManager::cleanup() mProbes.clear(); mReflectionMaps.clear(); - + mDefaultProbe = nullptr; mUpdatingProbe = nullptr; /* @@ -618,7 +618,7 @@ bool LLHeroProbeManager::registerViewerObject(LLVOVolume* drawablep) mHeroVOList.push_back(drawablep); return true; } - + return false; } diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index 8a284686ad..f43613be9f 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmanip.cpp * @brief LLManip class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -49,7 +49,7 @@ #include "llviewerobject.h" #include "llviewerwindow.h" #include "llvoavatar.h" -#include "llworld.h" // for LLWorld::getInstance() +#include "llworld.h" // for LLWorld::getInstance() #include "llresmgr.h" #include "pipeline.h" #include "llglheaders.h" @@ -57,39 +57,39 @@ // Local constants... const S32 VERTICAL_OFFSET = 50; -F32 LLManip::sHelpTextVisibleTime = 2.f; -F32 LLManip::sHelpTextFadeTime = 2.f; -S32 LLManip::sNumTimesHelpTextShown = 0; -S32 LLManip::sMaxTimesShowHelpText = 5; -F32 LLManip::sGridMaxSubdivisionLevel = 32.f; -F32 LLManip::sGridMinSubdivisionLevel = 1.f / 32.f; +F32 LLManip::sHelpTextVisibleTime = 2.f; +F32 LLManip::sHelpTextFadeTime = 2.f; +S32 LLManip::sNumTimesHelpTextShown = 0; +S32 LLManip::sMaxTimesShowHelpText = 5; +F32 LLManip::sGridMaxSubdivisionLevel = 32.f; +F32 LLManip::sGridMinSubdivisionLevel = 1.f / 32.f; LLVector2 LLManip::sTickLabelSpacing(60.f, 25.f); //static void LLManip::rebuild(LLViewerObject* vobj) { - LLDrawable* drawablep = vobj->mDrawable; - if (drawablep && drawablep->getVOVolume()) - { - gPipeline.markRebuild(drawablep,LLDrawable::REBUILD_VOLUME); - drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED - drawablep->updateMove(); - LLSpatialGroup* group = drawablep->getSpatialGroup(); - if (group) - { - group->dirtyGeom(); - gPipeline.markRebuild(group); - } - - LLViewerObject::const_child_list_t& child_list = vobj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(), endIter = child_list.end(); - iter != endIter; ++iter) - { - LLViewerObject* child = *iter; - rebuild(child); - } - } + LLDrawable* drawablep = vobj->mDrawable; + if (drawablep && drawablep->getVOVolume()) + { + gPipeline.markRebuild(drawablep,LLDrawable::REBUILD_VOLUME); + drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED + drawablep->updateMove(); + LLSpatialGroup* group = drawablep->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + gPipeline.markRebuild(group); + } + + LLViewerObject::const_child_list_t& child_list = vobj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(), endIter = child_list.end(); + iter != endIter; ++iter) + { + LLViewerObject* child = *iter; + rebuild(child); + } + } } ////////////////////////////////////////////////////////////////////////////// @@ -97,204 +97,204 @@ void LLManip::rebuild(LLViewerObject* vobj) LLManip::LLManip( const std::string& name, LLToolComposite* composite ) - : - LLTool( name, composite ), - mInSnapRegime(FALSE), - mHighlightedPart(LL_NO_PART), - mManipPart(LL_NO_PART) + : + LLTool( name, composite ), + mInSnapRegime(FALSE), + mHighlightedPart(LL_NO_PART), + mManipPart(LL_NO_PART) { } void LLManip::getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal) { - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - if (manip >= LL_X_ARROW && manip <= LL_Z_ARROW) - { - LLVector3 arrow_axis; - getManipAxis(object, manip, arrow_axis); - - LLVector3 cross = arrow_axis % LLViewerCamera::getInstance()->getAtAxis(); - normal = cross % arrow_axis; - normal.normVec(); - } - else if (manip >= LL_YZ_PLANE && manip <= LL_XY_PLANE) - { - switch (manip) - { - case LL_YZ_PLANE: - normal = LLVector3::x_axis; - break; - case LL_XZ_PLANE: - normal = LLVector3::y_axis; - break; - case LL_XY_PLANE: - normal = LLVector3::z_axis; - break; - default: - break; - } - normal.rotVec(grid_rotation); - } - else - { - normal.clearVec(); - } + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + if (manip >= LL_X_ARROW && manip <= LL_Z_ARROW) + { + LLVector3 arrow_axis; + getManipAxis(object, manip, arrow_axis); + + LLVector3 cross = arrow_axis % LLViewerCamera::getInstance()->getAtAxis(); + normal = cross % arrow_axis; + normal.normVec(); + } + else if (manip >= LL_YZ_PLANE && manip <= LL_XY_PLANE) + { + switch (manip) + { + case LL_YZ_PLANE: + normal = LLVector3::x_axis; + break; + case LL_XZ_PLANE: + normal = LLVector3::y_axis; + break; + case LL_XY_PLANE: + normal = LLVector3::z_axis; + break; + default: + break; + } + normal.rotVec(grid_rotation); + } + else + { + normal.clearVec(); + } } BOOL LLManip::getManipAxis(LLViewerObject* object, EManipPart manip, LLVector3 &axis) { - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - if (manip == LL_X_ARROW) - { - axis = LLVector3::x_axis; - } - else if (manip == LL_Y_ARROW) - { - axis = LLVector3::y_axis; - } - else if (manip == LL_Z_ARROW) - { - axis = LLVector3::z_axis; - } - else - { - return FALSE; - } - - axis.rotVec( grid_rotation ); - return TRUE; + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + if (manip == LL_X_ARROW) + { + axis = LLVector3::x_axis; + } + else if (manip == LL_Y_ARROW) + { + axis = LLVector3::y_axis; + } + else if (manip == LL_Z_ARROW) + { + axis = LLVector3::z_axis; + } + else + { + return FALSE; + } + + axis.rotVec( grid_rotation ); + return TRUE; } F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVector3 &translate_axis, F32 grid_scale, S32 min_pixel_spacing, F32 min_subdivisions, F32 max_subdivisions) { - //update current snap subdivision level - LLVector3 cam_to_reference; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_to_reference = LLVector3(1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f); - } - else - { - cam_to_reference = reference_point - LLViewerCamera::getInstance()->getOrigin(); - } - F32 current_range = cam_to_reference.normVec(); - - F32 projected_translation_axis_length = (translate_axis % cam_to_reference).magVec(); - F32 subdivisions = llmax(projected_translation_axis_length * grid_scale / (current_range / LLViewerCamera::getInstance()->getPixelMeterRatio() * min_pixel_spacing), 0.f); - // figure out nearest power of 2 that subdivides grid_scale with result > min_pixel_spacing - subdivisions = llclamp((F32)pow(2.f, llfloor(log(subdivisions) / log(2.f))), min_subdivisions, max_subdivisions); - - return subdivisions; + //update current snap subdivision level + LLVector3 cam_to_reference; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_to_reference = LLVector3(1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f); + } + else + { + cam_to_reference = reference_point - LLViewerCamera::getInstance()->getOrigin(); + } + F32 current_range = cam_to_reference.normVec(); + + F32 projected_translation_axis_length = (translate_axis % cam_to_reference).magVec(); + F32 subdivisions = llmax(projected_translation_axis_length * grid_scale / (current_range / LLViewerCamera::getInstance()->getPixelMeterRatio() * min_pixel_spacing), 0.f); + // figure out nearest power of 2 that subdivides grid_scale with result > min_pixel_spacing + subdivisions = llclamp((F32)pow(2.f, llfloor(log(subdivisions) / log(2.f))), min_subdivisions, max_subdivisions); + + return subdivisions; } void LLManip::handleSelect() { - mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); } void LLManip::handleDeselect() { - mHighlightedPart = LL_NO_PART; - mManipPart = LL_NO_PART; - mObjectSelection = NULL; + mHighlightedPart = LL_NO_PART; + mManipPart = LL_NO_PART; + mObjectSelection = NULL; } LLObjectSelectionHandle LLManip::getSelection() { - return mObjectSelection; + return mObjectSelection; } BOOL LLManip::handleHover(S32 x, S32 y, MASK mask) { - // We only handle the event if mousedown started with us - if( hasMouseCapture() ) - { - if( mObjectSelection->isEmpty() ) - { - // Somehow the object got deselected while we were dragging it. - // Release the mouse - setMouseCapture( FALSE ); - } - - LL_DEBUGS("UserInput") << "hover handled by LLManip (active)" << LL_ENDL; - } - else - { - LL_DEBUGS("UserInput") << "hover handled by LLManip (inactive)" << LL_ENDL; - } - gViewerWindow->setCursor(UI_CURSOR_ARROW); - return TRUE; + // We only handle the event if mousedown started with us + if( hasMouseCapture() ) + { + if( mObjectSelection->isEmpty() ) + { + // Somehow the object got deselected while we were dragging it. + // Release the mouse + setMouseCapture( FALSE ); + } + + LL_DEBUGS("UserInput") << "hover handled by LLManip (active)" << LL_ENDL; + } + else + { + LL_DEBUGS("UserInput") << "hover handled by LLManip (inactive)" << LL_ENDL; + } + gViewerWindow->setCursor(UI_CURSOR_ARROW); + return TRUE; } BOOL LLManip::handleMouseUp(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - if( hasMouseCapture() ) - { - handled = TRUE; - setMouseCapture( FALSE ); - } - return handled; + BOOL handled = FALSE; + if( hasMouseCapture() ) + { + handled = TRUE; + setMouseCapture( FALSE ); + } + return handled; } void LLManip::updateGridSettings() { - sGridMaxSubdivisionLevel = gSavedSettings.getBOOL("GridSubUnit") ? (F32)gSavedSettings.getS32("GridSubdivision") : 1.f; + sGridMaxSubdivisionLevel = gSavedSettings.getBOOL("GridSubUnit") ? (F32)gSavedSettings.getS32("GridSubdivision") : 1.f; } BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal) { - LLVector3d origin_double = gAgent.getPosGlobalFromAgent(origin); - LLVector3d global_point; - BOOL result = getMousePointOnPlaneGlobal(global_point, x, y, origin_double, normal); - point = gAgent.getPosAgentFromGlobal(global_point); - return result; + LLVector3d origin_double = gAgent.getPosGlobalFromAgent(origin); + LLVector3d global_point; + BOOL result = getMousePointOnPlaneGlobal(global_point, x, y, origin_double, normal); + point = gAgent.getPosAgentFromGlobal(global_point); + return result; } BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) const { - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - BOOL result = FALSE; - F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; - F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgentCamera.mHUDCurZoom; - - LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin); - LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y); - if (llabs(normal.mV[VX]) < 0.001f) - { - // use largish value that should be outside HUD manipulation range - mouse_pos.mV[VX] = 10.f; - } - else - { - mouse_pos.mV[VX] = (normal * (origin_agent - mouse_pos)) - / (normal.mV[VX]); - result = TRUE; - } - - point = gAgent.getPosGlobalFromAgent(mouse_pos); - return result; - } - else - { - return gViewerWindow->mousePointOnPlaneGlobal( - point, x, y, origin, normal ); - } - - //return FALSE; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + BOOL result = FALSE; + F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; + F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgentCamera.mHUDCurZoom; + + LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin); + LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y); + if (llabs(normal.mV[VX]) < 0.001f) + { + // use largish value that should be outside HUD manipulation range + mouse_pos.mV[VX] = 10.f; + } + else + { + mouse_pos.mV[VX] = (normal * (origin_agent - mouse_pos)) + / (normal.mV[VX]); + result = TRUE; + } + + point = gAgent.getPosGlobalFromAgent(mouse_pos); + return result; + } + else + { + return gViewerWindow->mousePointOnPlaneGlobal( + point, x, y, origin, normal ); + } + + //return FALSE; } // Given the line defined by mouse cursor (a1 + a_param*(a2-a1)) and the line defined by b1 + b_param*(b2-b1), @@ -302,159 +302,159 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect // Returns false if the two lines are parallel. BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) { - LLVector3 a1; - LLVector3 a2; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; - F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgentCamera.mHUDCurZoom; - a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y); - a2 = a1 + LLVector3(1.f, 0.f, 0.f); - } - else - { - a1 = gAgentCamera.getCameraPositionAgent(); - a2 = gAgentCamera.getCameraPositionAgent() + LLVector3(gViewerWindow->mouseDirectionGlobal(x, y)); - } - - BOOL parallel = TRUE; - LLVector3 a = a2 - a1; - LLVector3 b = b2 - b1; - - LLVector3 normal; - F32 dist, denom; - normal = (b % a) % b; // normal to plane (P) through b and (shortest line between a and b) - normal.normVec(); - dist = b1 * normal; // distance from origin to P - - denom = normal * a; - if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) ) - { - a_param = (dist - normal * a1) / denom; - parallel = FALSE; - } - - normal = (a % b) % a; // normal to plane (P) through a and (shortest line between a and b) - normal.normVec(); - dist = a1 * normal; // distance from origin to P - denom = normal * b; - if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) ) - { - b_param = (dist - normal * b1) / denom; - parallel = FALSE; - } - - return parallel; + LLVector3 a1; + LLVector3 a2; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; + F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgentCamera.mHUDCurZoom; + a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y); + a2 = a1 + LLVector3(1.f, 0.f, 0.f); + } + else + { + a1 = gAgentCamera.getCameraPositionAgent(); + a2 = gAgentCamera.getCameraPositionAgent() + LLVector3(gViewerWindow->mouseDirectionGlobal(x, y)); + } + + BOOL parallel = TRUE; + LLVector3 a = a2 - a1; + LLVector3 b = b2 - b1; + + LLVector3 normal; + F32 dist, denom; + normal = (b % a) % b; // normal to plane (P) through b and (shortest line between a and b) + normal.normVec(); + dist = b1 * normal; // distance from origin to P + + denom = normal * a; + if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) ) + { + a_param = (dist - normal * a1) / denom; + parallel = FALSE; + } + + normal = (a % b) % a; // normal to plane (P) through a and (shortest line between a and b) + normal.normVec(); + dist = a1 * normal; // distance from origin to P + denom = normal * b; + if( (denom < -F_APPROXIMATELY_ZERO) || (F_APPROXIMATELY_ZERO < denom) ) + { + b_param = (dist - normal * b1) / denom; + parallel = FALSE; + } + + return parallel; } LLVector3 LLManip::getSavedPivotPoint() const { - return LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + return LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); } LLVector3 LLManip::getPivotPoint() { LLViewerObject* object = mObjectSelection->getFirstObject(); - if (object && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { + if (object && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { LLSelectNode* select_node = mObjectSelection->getFirstNode(); if (select_node->mSelectedGLTFNode != -1) { return object->getGLTFNodePositionAgent(select_node->mSelectedGLTFNode); } - return mObjectSelection->getFirstObject()->getPivotPositionAgent(); - } - return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); + return mObjectSelection->getFirstObject()->getPivotPositionAgent(); + } + return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); } void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z) { - LLVector3 grid_origin; - LLQuaternion grid_rot; - LLVector3 grid_scale; - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rot, grid_scale); - - const BOOL children_ok = TRUE; - LLViewerObject* object = mObjectSelection->getFirstRootObject(children_ok); - if (!object) - { - return; - } - - //LLVector3 center_agent = LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); - LLVector3 center_agent = getPivotPoint(); - - gGL.pushMatrix(); - { - gGL.translatef(center_agent.mV[VX], center_agent.mV[VY], center_agent.mV[VZ]); - - F32 angle_radians, x, y, z; - - grid_rot.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - F32 region_size = LLWorld::getInstance()->getRegionWidthInMeters(); - - const F32 LINE_ALPHA = 0.33f; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLUI::setLineWidth(1.5f); - - if (draw_x) - { - gGL.color4f(1.f, 0.f, 0.f, LINE_ALPHA); - gGL.begin(LLRender::LINES); - gGL.vertex3f( -region_size, 0.f, 0.f ); - gGL.vertex3f( region_size, 0.f, 0.f ); - gGL.end(); - } - - if (draw_y) - { - gGL.color4f(0.f, 1.f, 0.f, LINE_ALPHA); - gGL.begin(LLRender::LINES); - gGL.vertex3f( 0.f, -region_size, 0.f ); - gGL.vertex3f( 0.f, region_size, 0.f ); - gGL.end(); - } - - if (draw_z) - { - gGL.color4f(0.f, 0.f, 1.f, LINE_ALPHA); - gGL.begin(LLRender::LINES); - gGL.vertex3f( 0.f, 0.f, -region_size ); - gGL.vertex3f( 0.f, 0.f, region_size ); - gGL.end(); - } - LLUI::setLineWidth(1.0f); - } - gGL.popMatrix(); + LLVector3 grid_origin; + LLQuaternion grid_rot; + LLVector3 grid_scale; + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rot, grid_scale); + + const BOOL children_ok = TRUE; + LLViewerObject* object = mObjectSelection->getFirstRootObject(children_ok); + if (!object) + { + return; + } + + //LLVector3 center_agent = LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); + LLVector3 center_agent = getPivotPoint(); + + gGL.pushMatrix(); + { + gGL.translatef(center_agent.mV[VX], center_agent.mV[VY], center_agent.mV[VZ]); + + F32 angle_radians, x, y, z; + + grid_rot.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 region_size = LLWorld::getInstance()->getRegionWidthInMeters(); + + const F32 LINE_ALPHA = 0.33f; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLUI::setLineWidth(1.5f); + + if (draw_x) + { + gGL.color4f(1.f, 0.f, 0.f, LINE_ALPHA); + gGL.begin(LLRender::LINES); + gGL.vertex3f( -region_size, 0.f, 0.f ); + gGL.vertex3f( region_size, 0.f, 0.f ); + gGL.end(); + } + + if (draw_y) + { + gGL.color4f(0.f, 1.f, 0.f, LINE_ALPHA); + gGL.begin(LLRender::LINES); + gGL.vertex3f( 0.f, -region_size, 0.f ); + gGL.vertex3f( 0.f, region_size, 0.f ); + gGL.end(); + } + + if (draw_z) + { + gGL.color4f(0.f, 0.f, 1.f, LINE_ALPHA); + gGL.begin(LLRender::LINES); + gGL.vertex3f( 0.f, 0.f, -region_size ); + gGL.vertex3f( 0.f, 0.f, region_size ); + gGL.end(); + } + LLUI::setLineWidth(1.0f); + } + gGL.popMatrix(); } -void LLManip::renderXYZ(const LLVector3 &vec) +void LLManip::renderXYZ(const LLVector3 &vec) { - const S32 PAD = 10; - std::string feedback_string; - S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2; - S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2; - S32 vertical_offset = window_center_y - VERTICAL_OFFSET; - - - gGL.pushMatrix(); - { - LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); - gViewerWindow->setup2DRender(); - const LLVector2& display_scale = gViewerWindow->getDisplayScale(); - gGL.color4f(0.f, 0.f, 0.f, 0.7f); - - imagep->draw( - (window_center_x - 115) * display_scale.mV[VX], - (window_center_y + vertical_offset - PAD) * display_scale.mV[VY], - 235 * display_scale.mV[VX], - (PAD * 2 + 10) * display_scale.mV[VY], - LLColor4(0.f, 0.f, 0.f, 0.7f) ); + const S32 PAD = 10; + std::string feedback_string; + S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2; + S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2; + S32 vertical_offset = window_center_y - VERTICAL_OFFSET; + + + gGL.pushMatrix(); + { + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); + gViewerWindow->setup2DRender(); + const LLVector2& display_scale = gViewerWindow->getDisplayScale(); + gGL.color4f(0.f, 0.f, 0.f, 0.7f); + + imagep->draw( + (window_center_x - 115) * display_scale.mV[VX], + (window_center_y + vertical_offset - PAD) * display_scale.mV[VY], + 235 * display_scale.mV[VX], + (PAD * 2 + 10) * display_scale.mV[VY], + LLColor4(0.f, 0.f, 0.f, 0.7f) ); LLFontGL* font = LLFontGL::getFontSansSerif(); LLLocale locale(LLLocale::USER_LOCALE); @@ -500,129 +500,129 @@ void LLManip::renderXYZ(const LLVector3 &vec) void LLManip::renderTickText(const LLVector3& pos, const std::string& text, const LLColor4 &color) { - const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - - BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - LLVector3 render_pos = pos; - if (hud_selection) - { - F32 zoom_amt = gAgentCamera.mHUDCurZoom; - F32 inv_zoom_amt = 1.f / zoom_amt; - // scale text back up to counter-act zoom level - render_pos = pos * zoom_amt; - gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); - } - - // render shadow first - LLColor4 shadow_color = LLColor4::black; - shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; - gViewerWindow->setup3DViewport(1, -1); - hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); - gViewerWindow->setup3DViewport(); - hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); - - gGL.popMatrix(); + const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); + + BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + LLVector3 render_pos = pos; + if (hud_selection) + { + F32 zoom_amt = gAgentCamera.mHUDCurZoom; + F32 inv_zoom_amt = 1.f / zoom_amt; + // scale text back up to counter-act zoom level + render_pos = pos * zoom_amt; + gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); + } + + // render shadow first + LLColor4 shadow_color = LLColor4::black; + shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; + gViewerWindow->setup3DViewport(1, -1); + hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); + gViewerWindow->setup3DViewport(); + hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); + + gGL.popMatrix(); } void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string& suffix, const LLColor4 &color) { - LLLocale locale(LLLocale::USER_LOCALE); - - const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall(); - - std::string val_string; - std::string fraction_string; - F32 val_to_print = ll_round(value, 0.001f); - S32 fractional_portion = ll_round(fmodf(llabs(val_to_print), 1.f) * 100.f); - if (val_to_print < 0.f) - { - if (fractional_portion == 0) - { - val_string = llformat("-%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); - } - else - { - val_string = llformat("-%d", lltrunc(llabs(val_to_print))); - } - } - else - { - if (fractional_portion == 0) - { - val_string = llformat("%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); - } - else - { - val_string = llformat("%d", lltrunc(val_to_print)); - } - } - - BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - { - LLVector3 render_pos = pos; - if (hud_selection) - { - F32 zoom_amt = gAgentCamera.mHUDCurZoom; - F32 inv_zoom_amt = 1.f / zoom_amt; - // scale text back up to counter-act zoom level - render_pos = pos * zoom_amt; - gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); - } - - LLColor4 shadow_color = LLColor4::black; - shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; - - if (fractional_portion != 0) - { - fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str()); - - hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); - hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, 1.f, 3.f, color, hud_selection); - } - else - { - hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); - } - } - gGL.popMatrix(); + LLLocale locale(LLLocale::USER_LOCALE); + + const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); + const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall(); + + std::string val_string; + std::string fraction_string; + F32 val_to_print = ll_round(value, 0.001f); + S32 fractional_portion = ll_round(fmodf(llabs(val_to_print), 1.f) * 100.f); + if (val_to_print < 0.f) + { + if (fractional_portion == 0) + { + val_string = llformat("-%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); + } + else + { + val_string = llformat("-%d", lltrunc(llabs(val_to_print))); + } + } + else + { + if (fractional_portion == 0) + { + val_string = llformat("%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); + } + else + { + val_string = llformat("%d", lltrunc(val_to_print)); + } + } + + BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + { + LLVector3 render_pos = pos; + if (hud_selection) + { + F32 zoom_amt = gAgentCamera.mHUDCurZoom; + F32 inv_zoom_amt = 1.f / zoom_amt; + // scale text back up to counter-act zoom level + render_pos = pos * zoom_amt; + gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); + } + + LLColor4 shadow_color = LLColor4::black; + shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; + + if (fractional_portion != 0) + { + fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str()); + + hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); + hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, 1.f, 3.f, color, hud_selection); + } + else + { + hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); + } + } + gGL.popMatrix(); } LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass) { - static LLColor4 grid_color_fg = LLUIColorTable::instance().getColor("GridlineColor"); - static LLColor4 grid_color_bg = LLUIColorTable::instance().getColor("GridlineBGColor"); - static LLColor4 grid_color_shadow = LLUIColorTable::instance().getColor("GridlineShadowColor"); - - LLColor4 line_color; - F32 line_alpha = gSavedSettings.getF32("GridOpacity"); - - switch(pass) - { - case 0: - // shadow - gViewerWindow->setup3DViewport(1, -1); - line_color = grid_color_shadow; - line_color.mV[VALPHA] *= line_alpha; - LLUI::setLineWidth(2.f); - break; - case 1: - // hidden lines - gViewerWindow->setup3DViewport(); - line_color = grid_color_bg; - line_color.mV[VALPHA] *= line_alpha; - LLUI::setLineWidth(1.f); - break; - case 2: - // visible lines - line_color = grid_color_fg; - line_color.mV[VALPHA] *= line_alpha; - break; - } - - return line_color; + static LLColor4 grid_color_fg = LLUIColorTable::instance().getColor("GridlineColor"); + static LLColor4 grid_color_bg = LLUIColorTable::instance().getColor("GridlineBGColor"); + static LLColor4 grid_color_shadow = LLUIColorTable::instance().getColor("GridlineShadowColor"); + + LLColor4 line_color; + F32 line_alpha = gSavedSettings.getF32("GridOpacity"); + + switch(pass) + { + case 0: + // shadow + gViewerWindow->setup3DViewport(1, -1); + line_color = grid_color_shadow; + line_color.mV[VALPHA] *= line_alpha; + LLUI::setLineWidth(2.f); + break; + case 1: + // hidden lines + gViewerWindow->setup3DViewport(); + line_color = grid_color_bg; + line_color.mV[VALPHA] *= line_alpha; + LLUI::setLineWidth(1.f); + break; + case 2: + // visible lines + line_color = grid_color_fg; + line_color.mV[VALPHA] *= line_alpha; + break; + } + + return line_color; } diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 1ac1992fe0..54aa22be2b 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmaniprotate.cpp * @brief LLManipRotate class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -63,7 +63,7 @@ #include "llvoavatarself.h" #include "llhudrender.h" -const F32 RADIUS_PIXELS = 100.f; // size in screen space +const F32 RADIUS_PIXELS = 100.f; // size in screen space const F32 SQ_RADIUS = RADIUS_PIXELS * RADIUS_PIXELS; const F32 WIDTH_PIXELS = 8; const S32 CIRCLE_STEPS = 100; @@ -83,493 +83,493 @@ const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f; extern void handle_reset_rotation(void*); // in LLViewerWindow LLManipRotate::LLManipRotate( LLToolComposite* composite ) -: LLManip( std::string("Rotate"), composite ), - mRotationCenter(), - mCenterScreen(), - mRotation(), - mMouseDown(), - mMouseCur(), - mRadiusMeters(0.f), - mCenterToCam(), - mCenterToCamNorm(), - mCenterToCamMag(0.f), - mCenterToProfilePlane(), - mCenterToProfilePlaneMag(0.f), - mSendUpdateOnMouseUp( FALSE ), - mSmoothRotate( FALSE ), - mCamEdgeOn(FALSE), - mManipulatorScales(1.f, 1.f, 1.f, 1.f) +: LLManip( std::string("Rotate"), composite ), + mRotationCenter(), + mCenterScreen(), + mRotation(), + mMouseDown(), + mMouseCur(), + mRadiusMeters(0.f), + mCenterToCam(), + mCenterToCamNorm(), + mCenterToCamMag(0.f), + mCenterToProfilePlane(), + mCenterToProfilePlaneMag(0.f), + mSendUpdateOnMouseUp( FALSE ), + mSmoothRotate( FALSE ), + mCamEdgeOn(FALSE), + mManipulatorScales(1.f, 1.f, 1.f, 1.f) { } void LLManipRotate::handleSelect() { - // *FIX: put this in mouseDown? - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + // *FIX: put this in mouseDown? + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); if (gFloaterTools) { gFloaterTools->setStatusText("rotate"); } - LLManip::handleSelect(); + LLManip::handleSelect(); } void LLManipRotate::render() { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - LLGLDepthTest gls_depth(GL_TRUE); - LLGLEnable gl_blend(GL_BLEND); - - // You can rotate if you can move - LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); - if( !first_object ) - { - return; - } - - if( !updateVisiblity() ) - { - return; - } - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom, zoom, zoom); - } - - - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - LLColor4 highlight_outside( 1.f, 1.f, 0.f, 1.f ); - LLColor4 highlight_inside( 0.7f, 0.7f, 0.f, 0.5f ); - F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS; - - gGL.pushMatrix(); - { - - // are we in the middle of a constrained drag? - if (mManipPart >= LL_ROT_X && mManipPart <= LL_ROT_Z) - { - renderSnapGuides(); - } - else - { - gDebugProgram.bind(); - - LLGLEnable cull_face(GL_CULL_FACE); - LLGLDepthTest gls_depth(GL_FALSE); - gGL.pushMatrix(); - { - // Draw "sphere" (intersection of sphere with tangent cone that has apex at camera) - gGL.translatef( mCenterToProfilePlane.mV[VX], mCenterToProfilePlane.mV[VY], mCenterToProfilePlane.mV[VZ] ); - gGL.translatef( center.mV[VX], center.mV[VY], center.mV[VZ] ); - - // Inverse change of basis vectors - LLVector3 forward = mCenterToCamNorm; - LLVector3 left = gAgent.getUpAxis() % forward; - left.normVec(); - LLVector3 up = forward % left; - - LLVector4 a(-forward); - a.mV[3] = 0; - LLVector4 b(up); - b.mV[3] = 0; - LLVector4 c(left); - c.mV[3] = 0; - LLMatrix4 mat; - mat.initRows(a, b, c, LLVector4(0.f, 0.f, 0.f, 1.f)); - - gGL.multMatrix( &mat.mMatrix[0][0] ); - - gGL.rotatef( -90, 0.f, 1.f, 0.f); - LLColor4 color; - if (mManipPart == LL_ROT_ROLL || mHighlightedPart == LL_ROT_ROLL) - { - color.setVec(0.8f, 0.8f, 0.8f, 0.8f); - gGL.scalef(mManipulatorScales.mV[VW], mManipulatorScales.mV[VW], mManipulatorScales.mV[VW]); - } - else - { - color.setVec( 0.7f, 0.7f, 0.7f, 0.6f ); - } - gGL.diffuseColor4fv(color.mV); - gl_washer_2d(mRadiusMeters + width_meters, mRadiusMeters, CIRCLE_STEPS, color, color); - - - if (mManipPart == LL_NO_PART) - { - gGL.color4f( 0.7f, 0.7f, 0.7f, 0.3f ); - gGL.diffuseColor4f(0.7f, 0.7f, 0.7f, 0.3f); - gl_circle_2d( 0, 0, mRadiusMeters, CIRCLE_STEPS, TRUE ); - } - - gGL.flush(); - } - gGL.popMatrix(); - - gUIProgram.bind(); - } - - gGL.translatef( center.mV[VX], center.mV[VY], center.mV[VZ] ); - - LLQuaternion rot; - F32 angle_radians, x, y, z; - - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - - gDebugProgram.bind(); - - if (mManipPart == LL_ROT_Z) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.pushMatrix(); - { - // selected part - gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); - renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f) , LLColor4( 0.f, 0.f, 1.f, 0.3f )); - } - gGL.popMatrix(); - } - else if (mManipPart == LL_ROT_Y) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.pushMatrix(); - { - gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); - gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); - renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f), LLColor4( 0.f, 1.f, 0.f, 0.3f)); - } - gGL.popMatrix(); - } - else if (mManipPart == LL_ROT_X) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.pushMatrix(); - { - gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); - gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); - renderActiveRing( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f), LLColor4( 1.f, 0.f, 0.f, 0.3f)); - } - gGL.popMatrix(); - } - else if (mManipPart == LL_ROT_ROLL) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - } - else if (mManipPart == LL_NO_PART) - { - if (mHighlightedPart == LL_NO_PART) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - } - - LLGLEnable cull_face(GL_CULL_FACE); - LLGLEnable clip_plane0(GL_CLIP_PLANE0); - LLGLDepthTest gls_depth(GL_FALSE); - //LLGLDisable gls_stencil(GL_STENCIL_TEST); - - // First pass: centers. Second pass: sides. - for( S32 i=0; i<2; i++ ) - { - - gGL.pushMatrix(); - { - if (mHighlightedPart == LL_ROT_Z) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); - // hovering over part - gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f ), LLColor4( 0.f, 0.f, 1.f, 0.5f ), CIRCLE_STEPS, i); - } - else - { - // default - gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 0.8f, 0.8f ), LLColor4( 0.f, 0.f, 0.8f, 0.4f ), CIRCLE_STEPS, i); - } - } - gGL.popMatrix(); - - gGL.pushMatrix(); - { - gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); - if (mHighlightedPart == LL_ROT_Y) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); - // hovering over part - gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f ), LLColor4( 0.f, 1.f, 0.f, 0.5f ), CIRCLE_STEPS, i); - } - else - { - // default - gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.8f, 0.f, 0.8f ), LLColor4( 0.f, 0.8f, 0.f, 0.4f ), CIRCLE_STEPS, i); - } - } - gGL.popMatrix(); - - gGL.pushMatrix(); - { - gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); - if (mHighlightedPart == LL_ROT_X) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); - - // hovering over part - gl_ring( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f ), LLColor4( 1.f, 0.f, 0.f, 0.5f ), CIRCLE_STEPS, i); - } - else - { - // default - gl_ring( mRadiusMeters, width_meters, LLColor4( 0.8f, 0.f, 0.f, 0.8f ), LLColor4( 0.8f, 0.f, 0.f, 0.4f ), CIRCLE_STEPS, i); - } - } - gGL.popMatrix(); - - if (mHighlightedPart == LL_ROT_ROLL) - { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); - } - - } - - } - - gUIProgram.bind(); - } - gGL.popMatrix(); - gGL.popMatrix(); - - - LLVector3 euler_angles; - LLQuaternion object_rot = first_object->getRotationEdit(); - object_rot.getEulerAngles(&(euler_angles.mV[VX]), &(euler_angles.mV[VY]), &(euler_angles.mV[VZ])); - euler_angles *= RAD_TO_DEG; - euler_angles.mV[VX] = ll_round(fmodf(euler_angles.mV[VX] + 360.f, 360.f), 0.05f); - euler_angles.mV[VY] = ll_round(fmodf(euler_angles.mV[VY] + 360.f, 360.f), 0.05f); - euler_angles.mV[VZ] = ll_round(fmodf(euler_angles.mV[VZ] + 360.f, 360.f), 0.05f); - - renderXYZ(euler_angles); + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + LLGLDepthTest gls_depth(GL_TRUE); + LLGLEnable gl_blend(GL_BLEND); + + // You can rotate if you can move + LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); + if( !first_object ) + { + return; + } + + if( !updateVisiblity() ) + { + return; + } + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom, zoom, zoom); + } + + + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + + LLColor4 highlight_outside( 1.f, 1.f, 0.f, 1.f ); + LLColor4 highlight_inside( 0.7f, 0.7f, 0.f, 0.5f ); + F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS; + + gGL.pushMatrix(); + { + + // are we in the middle of a constrained drag? + if (mManipPart >= LL_ROT_X && mManipPart <= LL_ROT_Z) + { + renderSnapGuides(); + } + else + { + gDebugProgram.bind(); + + LLGLEnable cull_face(GL_CULL_FACE); + LLGLDepthTest gls_depth(GL_FALSE); + gGL.pushMatrix(); + { + // Draw "sphere" (intersection of sphere with tangent cone that has apex at camera) + gGL.translatef( mCenterToProfilePlane.mV[VX], mCenterToProfilePlane.mV[VY], mCenterToProfilePlane.mV[VZ] ); + gGL.translatef( center.mV[VX], center.mV[VY], center.mV[VZ] ); + + // Inverse change of basis vectors + LLVector3 forward = mCenterToCamNorm; + LLVector3 left = gAgent.getUpAxis() % forward; + left.normVec(); + LLVector3 up = forward % left; + + LLVector4 a(-forward); + a.mV[3] = 0; + LLVector4 b(up); + b.mV[3] = 0; + LLVector4 c(left); + c.mV[3] = 0; + LLMatrix4 mat; + mat.initRows(a, b, c, LLVector4(0.f, 0.f, 0.f, 1.f)); + + gGL.multMatrix( &mat.mMatrix[0][0] ); + + gGL.rotatef( -90, 0.f, 1.f, 0.f); + LLColor4 color; + if (mManipPart == LL_ROT_ROLL || mHighlightedPart == LL_ROT_ROLL) + { + color.setVec(0.8f, 0.8f, 0.8f, 0.8f); + gGL.scalef(mManipulatorScales.mV[VW], mManipulatorScales.mV[VW], mManipulatorScales.mV[VW]); + } + else + { + color.setVec( 0.7f, 0.7f, 0.7f, 0.6f ); + } + gGL.diffuseColor4fv(color.mV); + gl_washer_2d(mRadiusMeters + width_meters, mRadiusMeters, CIRCLE_STEPS, color, color); + + + if (mManipPart == LL_NO_PART) + { + gGL.color4f( 0.7f, 0.7f, 0.7f, 0.3f ); + gGL.diffuseColor4f(0.7f, 0.7f, 0.7f, 0.3f); + gl_circle_2d( 0, 0, mRadiusMeters, CIRCLE_STEPS, TRUE ); + } + + gGL.flush(); + } + gGL.popMatrix(); + + gUIProgram.bind(); + } + + gGL.translatef( center.mV[VX], center.mV[VY], center.mV[VZ] ); + + LLQuaternion rot; + F32 angle_radians, x, y, z; + + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + + gDebugProgram.bind(); + + if (mManipPart == LL_ROT_Z) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.pushMatrix(); + { + // selected part + gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); + renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f) , LLColor4( 0.f, 0.f, 1.f, 0.3f )); + } + gGL.popMatrix(); + } + else if (mManipPart == LL_ROT_Y) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.pushMatrix(); + { + gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); + gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); + renderActiveRing( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f), LLColor4( 0.f, 1.f, 0.f, 0.3f)); + } + gGL.popMatrix(); + } + else if (mManipPart == LL_ROT_X) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.pushMatrix(); + { + gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); + gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); + renderActiveRing( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f), LLColor4( 1.f, 0.f, 0.f, 0.3f)); + } + gGL.popMatrix(); + } + else if (mManipPart == LL_ROT_ROLL) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + } + else if (mManipPart == LL_NO_PART) + { + if (mHighlightedPart == LL_NO_PART) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + } + + LLGLEnable cull_face(GL_CULL_FACE); + LLGLEnable clip_plane0(GL_CLIP_PLANE0); + LLGLDepthTest gls_depth(GL_FALSE); + //LLGLDisable gls_stencil(GL_STENCIL_TEST); + + // First pass: centers. Second pass: sides. + for( S32 i=0; i<2; i++ ) + { + + gGL.pushMatrix(); + { + if (mHighlightedPart == LL_ROT_Z) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); + // hovering over part + gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f ), LLColor4( 0.f, 0.f, 1.f, 0.5f ), CIRCLE_STEPS, i); + } + else + { + // default + gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 0.8f, 0.8f ), LLColor4( 0.f, 0.f, 0.8f, 0.4f ), CIRCLE_STEPS, i); + } + } + gGL.popMatrix(); + + gGL.pushMatrix(); + { + gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); + if (mHighlightedPart == LL_ROT_Y) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); + // hovering over part + gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f ), LLColor4( 0.f, 1.f, 0.f, 0.5f ), CIRCLE_STEPS, i); + } + else + { + // default + gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.8f, 0.f, 0.8f ), LLColor4( 0.f, 0.8f, 0.f, 0.4f ), CIRCLE_STEPS, i); + } + } + gGL.popMatrix(); + + gGL.pushMatrix(); + { + gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); + if (mHighlightedPart == LL_ROT_X) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); + + // hovering over part + gl_ring( mRadiusMeters, width_meters, LLColor4( 1.f, 0.f, 0.f, 1.f ), LLColor4( 1.f, 0.f, 0.f, 0.5f ), CIRCLE_STEPS, i); + } + else + { + // default + gl_ring( mRadiusMeters, width_meters, LLColor4( 0.8f, 0.f, 0.f, 0.8f ), LLColor4( 0.8f, 0.f, 0.f, 0.4f ), CIRCLE_STEPS, i); + } + } + gGL.popMatrix(); + + if (mHighlightedPart == LL_ROT_ROLL) + { + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + } + + } + + } + + gUIProgram.bind(); + } + gGL.popMatrix(); + gGL.popMatrix(); + + + LLVector3 euler_angles; + LLQuaternion object_rot = first_object->getRotationEdit(); + object_rot.getEulerAngles(&(euler_angles.mV[VX]), &(euler_angles.mV[VY]), &(euler_angles.mV[VZ])); + euler_angles *= RAD_TO_DEG; + euler_angles.mV[VX] = ll_round(fmodf(euler_angles.mV[VX] + 360.f, 360.f), 0.05f); + euler_angles.mV[VY] = ll_round(fmodf(euler_angles.mV[VY] + 360.f, 360.f), 0.05f); + euler_angles.mV[VZ] = ll_round(fmodf(euler_angles.mV[VZ] + 360.f, 360.f), 0.05f); + + renderXYZ(euler_angles); } BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); - if( first_object ) - { - if( mHighlightedPart != LL_NO_PART ) - { - handled = handleMouseDownOnPart( x, y, mask ); - } - } - - return handled; + BOOL handled = FALSE; + + LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); + if( first_object ) + { + if( mHighlightedPart != LL_NO_PART ) + { + handled = handleMouseDownOnPart( x, y, mask ); + } + } + + return handled; } // Assumes that one of the parts of the manipulator was hit. BOOL LLManipRotate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_rotate = canAffectSelection(); - if (!can_rotate) - { - return FALSE; - } - - highlightManipulators(x, y); - S32 hit_part = mHighlightedPart; - // we just started a drag, so save initial object positions - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_ROTATE); - - // save selection center - mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() ); //LLSelectMgr::getInstance()->getSelectionCenterGlobal(); - - mManipPart = (EManipPart)hit_part; - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - if( mManipPart == LL_ROT_GENERAL) - { - mMouseDown = intersectMouseWithSphere( x, y, center, mRadiusMeters); - } - else - { - // Project onto the plane of the ring - LLVector3 axis = getConstraintAxis(); - - F32 axis_onto_cam = llabs( axis * mCenterToCamNorm ); - const F32 AXIS_ONTO_CAM_TOL = cos( 85.f * DEG_TO_RAD ); - if( axis_onto_cam < AXIS_ONTO_CAM_TOL ) - { - LLVector3 up_from_axis = mCenterToCamNorm % axis; - up_from_axis.normVec(); - LLVector3 cur_intersection; - getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam); - cur_intersection -= center; - mMouseDown = projected_vec(cur_intersection, up_from_axis); - F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; - F32 mouse_dist_sqrd = mMouseDown.magVecSquared(); - if (mouse_dist_sqrd > 0.0001f) - { - mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - - mouse_dist_sqrd); - } - LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, axis); - mMouseDown += mouse_depth * projected_center_to_cam; - - } - else - { - mMouseDown = findNearestPointOnRing( x, y, center, axis ) - center; - mMouseDown.normVec(); - } - } - - mMouseCur = mMouseDown; - mAgentSelfAtAxis = gAgent.getAtAxis(); // no point checking if avatar was selected, just save the value - - // Route future Mouse messages here preemptively. (Release on mouse up.) - setMouseCapture( TRUE ); - LLSelectMgr::getInstance()->enableSilhouette(FALSE); - - mHelpTextTimer.reset(); - sNumTimesHelpTextShown++; - return TRUE; + BOOL can_rotate = canAffectSelection(); + if (!can_rotate) + { + return FALSE; + } + + highlightManipulators(x, y); + S32 hit_part = mHighlightedPart; + // we just started a drag, so save initial object positions + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_ROTATE); + + // save selection center + mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() ); //LLSelectMgr::getInstance()->getSelectionCenterGlobal(); + + mManipPart = (EManipPart)hit_part; + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + + if( mManipPart == LL_ROT_GENERAL) + { + mMouseDown = intersectMouseWithSphere( x, y, center, mRadiusMeters); + } + else + { + // Project onto the plane of the ring + LLVector3 axis = getConstraintAxis(); + + F32 axis_onto_cam = llabs( axis * mCenterToCamNorm ); + const F32 AXIS_ONTO_CAM_TOL = cos( 85.f * DEG_TO_RAD ); + if( axis_onto_cam < AXIS_ONTO_CAM_TOL ) + { + LLVector3 up_from_axis = mCenterToCamNorm % axis; + up_from_axis.normVec(); + LLVector3 cur_intersection; + getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam); + cur_intersection -= center; + mMouseDown = projected_vec(cur_intersection, up_from_axis); + F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; + F32 mouse_dist_sqrd = mMouseDown.magVecSquared(); + if (mouse_dist_sqrd > 0.0001f) + { + mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - + mouse_dist_sqrd); + } + LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, axis); + mMouseDown += mouse_depth * projected_center_to_cam; + + } + else + { + mMouseDown = findNearestPointOnRing( x, y, center, axis ) - center; + mMouseDown.normVec(); + } + } + + mMouseCur = mMouseDown; + mAgentSelfAtAxis = gAgent.getAtAxis(); // no point checking if avatar was selected, just save the value + + // Route future Mouse messages here preemptively. (Release on mouse up.) + setMouseCapture( TRUE ); + LLSelectMgr::getInstance()->enableSilhouette(FALSE); + + mHelpTextTimer.reset(); + sNumTimesHelpTextShown++; + return TRUE; } LLVector3 LLManipRotate::findNearestPointOnRing( S32 x, S32 y, const LLVector3& center, const LLVector3& axis ) { - // Project the delta onto the ring and rescale it by the radius so that it's _on_ the ring. - LLVector3 proj_onto_ring; - getMousePointOnPlaneAgent(proj_onto_ring, x, y, center, axis); - proj_onto_ring -= center; - proj_onto_ring.normVec(); + // Project the delta onto the ring and rescale it by the radius so that it's _on_ the ring. + LLVector3 proj_onto_ring; + getMousePointOnPlaneAgent(proj_onto_ring, x, y, center, axis); + proj_onto_ring -= center; + proj_onto_ring.normVec(); - return center + proj_onto_ring * mRadiusMeters; + return center + proj_onto_ring * mRadiusMeters; } BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask) { - // first, perform normal processing in case this was a quick-click - handleHover(x, y, mask); - - if( hasMouseCapture() ) - { - for (LLObjectSelection::iterator iter = mObjectSelection->begin(); - iter != mObjectSelection->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); - - // have permission to move and object is root of selection or individually selected - if (object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (object->isRootEdit() || selectNode->mIndividualSelection)) - { - object->mUnselectedChildrenPositions.clear() ; - } - } - - mManipPart = LL_NO_PART; - - // Might have missed last update due to timing. - LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION ); - LLSelectMgr::getInstance()->enableSilhouette(TRUE); - //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); - - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - } - - return LLManip::handleMouseUp(x, y, mask); + // first, perform normal processing in case this was a quick-click + handleHover(x, y, mask); + + if( hasMouseCapture() ) + { + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); + iter != mObjectSelection->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + + // have permission to move and object is root of selection or individually selected + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->isRootEdit() || selectNode->mIndividualSelection)) + { + object->mUnselectedChildrenPositions.clear() ; + } + } + + mManipPart = LL_NO_PART; + + // Might have missed last update due to timing. + LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION ); + LLSelectMgr::getInstance()->enableSilhouette(TRUE); + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); + + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + } + + return LLManip::handleMouseUp(x, y, mask); } BOOL LLManipRotate::handleHover(S32 x, S32 y, MASK mask) { - if( hasMouseCapture() ) - { - if( mObjectSelection->isEmpty() ) - { - // Somehow the object got deselected while we were dragging it. - setMouseCapture( FALSE ); - } - else - { - drag(x, y); - } - - LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (active)" << LL_ENDL; - } - else - { - highlightManipulators(x, y); - LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (inactive)" << LL_ENDL; - } - - gViewerWindow->setCursor(UI_CURSOR_TOOLROTATE); - return TRUE; + if( hasMouseCapture() ) + { + if( mObjectSelection->isEmpty() ) + { + // Somehow the object got deselected while we were dragging it. + setMouseCapture( FALSE ); + } + else + { + drag(x, y); + } + + LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (active)" << LL_ENDL; + } + else + { + highlightManipulators(x, y); + LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (inactive)" << LL_ENDL; + } + + gViewerWindow->setCursor(UI_CURSOR_TOOLROTATE); + return TRUE; } -LLVector3 LLManipRotate::projectToSphere( F32 x, F32 y, BOOL* on_sphere ) +LLVector3 LLManipRotate::projectToSphere( F32 x, F32 y, BOOL* on_sphere ) { - F32 z = 0.f; - F32 dist_squared = x*x + y*y; + F32 z = 0.f; + F32 dist_squared = x*x + y*y; - *on_sphere = dist_squared <= SQ_RADIUS; + *on_sphere = dist_squared <= SQ_RADIUS; if( *on_sphere ) - { + { z = sqrt(SQ_RADIUS - dist_squared); } - return LLVector3( x, y, z ); + return LLVector3( x, y, z ); } // Freeform rotation void LLManipRotate::drag( S32 x, S32 y ) { - if( !updateVisiblity() ) - { - return; - } - - if( mManipPart == LL_ROT_GENERAL ) - { - mRotation = dragUnconstrained(x, y); - } - else - { - mRotation = dragConstrained(x, y); - } - - BOOL damped = mSmoothRotate; - mSmoothRotate = FALSE; - bool gltf_mode = false; + if( !updateVisiblity() ) + { + return; + } + + if( mManipPart == LL_ROT_GENERAL ) + { + mRotation = dragUnconstrained(x, y); + } + else + { + mRotation = dragConstrained(x, y); + } - for (LLObjectSelection::iterator iter = mObjectSelection->begin(); - iter != mObjectSelection->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + BOOL damped = mSmoothRotate; + mSmoothRotate = FALSE; + bool gltf_mode = false; - // have permission to move and object is root of selection or individually selected - if (object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (object->isRootEdit() || selectNode->mIndividualSelection)) - { + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); + iter != mObjectSelection->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + + // have permission to move and object is root of selection or individually selected + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->isRootEdit() || selectNode->mIndividualSelection)) + { if (selectNode->mSelectedGLTFNode != -1) { @@ -643,10 +643,10 @@ void LLManipRotate::drag( S32 x, S32 y ) object->resetChildrenRotationAndPosition(child_rotations, child_positions); } } - } - } + } + } - // update positions + // update positions if (!gltf_mode) { for (LLObjectSelection::iterator iter = mObjectSelection->begin(); @@ -674,7 +674,7 @@ void LLManipRotate::drag( S32 x, S32 y ) { if (object->isAttachment() && object->mDrawable.notNull()) { - // need to work in drawable space to handle selected items from multiple attachments + // need to work in drawable space to handle selected items from multiple attachments // (which have no shared frame of reference other than their render positions) LLXform* parent_xform = object->mDrawable->getXform()->getParent(); new_position = (selectNode->mSavedPositionLocal * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); @@ -686,7 +686,7 @@ void LLManipRotate::drag( S32 x, S32 y ) old_position = object->getPositionAgent(); } - new_position = (new_position - center) * mRotation; // new relative rotated position + new_position = (new_position - center) * mRotation; // new relative rotated position new_position += center; if (object->isRootEdit() && !object->isAttachment()) @@ -742,1234 +742,1234 @@ void LLManipRotate::drag( S32 x, S32 y ) } } - // store changes to override updates - for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); - iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject*cur = selectNode->getObject(); - LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + // store changes to override updates + for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin(); + iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject*cur = selectNode->getObject(); + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (!cur->isAvatar() || LLSelectMgr::getInstance()->mAllowSelectAvatar)) - { + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (!cur->isAvatar() || LLSelectMgr::getInstance()->mAllowSelectAvatar)) + { selectNode->mLastRotation = cur->getRotation(); selectNode->mLastPositionLocal = cur->getPosition(); - } - } + } + } - LLSelectMgr::getInstance()->updateSelectionCenter(); + LLSelectMgr::getInstance()->updateSelectionCenter(); - // RN: just clear focus so camera doesn't follow spurious object updates - gAgentCamera.clearFocusObject(); - dialog_refresh_all(); + // RN: just clear focus so camera doesn't follow spurious object updates + gAgentCamera.clearFocusObject(); + dialog_refresh_all(); } void LLManipRotate::renderActiveRing( F32 radius, F32 width, const LLColor4& front_color, const LLColor4& back_color) { - LLGLEnable cull_face(GL_CULL_FACE); - { - gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, FALSE); - gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, TRUE); - } - { - LLGLDepthTest gls_depth(GL_FALSE); - gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, FALSE); - gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, TRUE); - } + LLGLEnable cull_face(GL_CULL_FACE); + { + gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, FALSE); + gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, TRUE); + } + { + LLGLDepthTest gls_depth(GL_FALSE); + gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, FALSE); + gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS, TRUE); + } } void LLManipRotate::renderSnapGuides() { - static LLCachedControl snap_enabled(gSavedSettings, "SnapEnabled", true); - if (!snap_enabled) - { - return; - } - - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale, true); - - LLVector3 constraint_axis = getConstraintAxis(); - - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - LLVector3 cam_at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_at_axis.setVec(1.f, 0.f, 0.f); - } - else - { - cam_at_axis = center - gAgentCamera.getCameraPositionAgent(); - cam_at_axis.normVec(); - } - - LLVector3 world_snap_axis; - LLVector3 test_axis = constraint_axis; - - BOOL constrain_to_ref_object = FALSE; - if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) - { - test_axis = test_axis * ~grid_rotation; - } - else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) - { - test_axis = test_axis * ~grid_rotation; - constrain_to_ref_object = TRUE; - } - - test_axis.abs(); - - // find closest global/reference axis to local constraint axis; - if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ]) - { - world_snap_axis = LLVector3::y_axis; - } - else if (test_axis.mV[VY] > test_axis.mV[VZ]) - { - world_snap_axis = LLVector3::z_axis; - } - else - { - world_snap_axis = LLVector3::x_axis; - } - - LLVector3 projected_snap_axis = world_snap_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) - { - projected_snap_axis = projected_snap_axis * grid_rotation; - } - else if (constrain_to_ref_object) - { - projected_snap_axis = projected_snap_axis * grid_rotation; - } - - // project world snap axis onto constraint plane - projected_snap_axis -= projected_vec(projected_snap_axis, constraint_axis); - projected_snap_axis.normVec(); - - S32 num_rings = mCamEdgeOn ? 2 : 1; - for (S32 ring_num = 0; ring_num < num_rings; ring_num++) - { - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - if (mCamEdgeOn) - { - // draw two opposing rings - if (ring_num == 0) - { - center += constraint_axis * mRadiusMeters * 0.5f; - } - else - { - center -= constraint_axis * mRadiusMeters * 0.5f; - } - } - - LLGLDepthTest gls_depth(GL_FALSE); - for (S32 pass = 0; pass < 3; pass++) - { - // render snap guide ring - gGL.pushMatrix(); - - LLQuaternion snap_guide_rot; - F32 angle_radians, x, y, z; - snap_guide_rot.shortestArc(LLVector3::z_axis, getConstraintAxis()); - snap_guide_rot.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - LLColor4 line_color = setupSnapGuideRenderPass(pass); - - gGL.color4fv(line_color.mV); - - if (mCamEdgeOn) - { - // render an arc - LLVector3 edge_normal = cam_at_axis % constraint_axis; - edge_normal.normVec(); - LLVector3 x_axis_snap = LLVector3::x_axis * snap_guide_rot; - LLVector3 y_axis_snap = LLVector3::y_axis * snap_guide_rot; - - F32 end_angle = atan2(y_axis_snap * edge_normal, x_axis_snap * edge_normal); - //F32 start_angle = angle_between((-1.f * LLVector3::x_axis) * snap_guide_rot, edge_normal); - F32 start_angle = end_angle - F_PI; - gl_arc_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE, start_angle, end_angle); - } - else - { - gl_circle_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE); - } - gGL.popMatrix(); - - for (S32 i = 0; i < 64; i++) - { - BOOL render_text = TRUE; - F32 deg = 5.625f * (F32)i; - LLVector3 inner_point; - LLVector3 outer_point; - LLVector3 text_point; - LLQuaternion rot(deg * DEG_TO_RAD, constraint_axis); - gGL.begin(LLRender::LINES); - { - inner_point = (projected_snap_axis * mRadiusMeters * SNAP_GUIDE_INNER_RADIUS * rot) + center; - F32 tick_length = 0.f; - if (i % 16 == 0) - { - tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_1 - SNAP_GUIDE_INNER_RADIUS); - } - else if (i % 8 == 0) - { - tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_2 - SNAP_GUIDE_INNER_RADIUS); - } - else if (i % 4 == 0) - { - tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_3 - SNAP_GUIDE_INNER_RADIUS); - } - else if (i % 2 == 0) - { - tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_4 - SNAP_GUIDE_INNER_RADIUS); - } - else - { - tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_5 - SNAP_GUIDE_INNER_RADIUS); - } - - if (mCamEdgeOn) - { - // don't draw ticks that are on back side of circle - F32 dot = cam_at_axis * (projected_snap_axis * rot); - if (dot > 0.f) - { - outer_point = inner_point; - render_text = FALSE; - } - else - { - if (ring_num == 0) - { - outer_point = inner_point + (constraint_axis * tick_length) * rot; - } - else - { - outer_point = inner_point - (constraint_axis * tick_length) * rot; - } - } - } - else - { - outer_point = inner_point + (projected_snap_axis * tick_length) * rot; - } - - text_point = outer_point + (projected_snap_axis * mRadiusMeters * 0.1f) * rot; - - gGL.vertex3fv(inner_point.mV); - gGL.vertex3fv(outer_point.mV); - } - gGL.end(); - - //RN: text rendering does own shadow pass, so only render once - if (pass == 1 && render_text && i % 16 == 0) - { - if (world_snap_axis.mV[VX]) - { - if (i == 0) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); - } - else if (i == 16) - { - if (constraint_axis.mV[VZ] > 0.f) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); - } - else - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); - } - } - else if (i == 32) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); - } - else - { - if (constraint_axis.mV[VZ] > 0.f) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); - } - else - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); - } - } - } - else if (world_snap_axis.mV[VY]) - { - if (i == 0) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); - } - else if (i == 16) - { - if (constraint_axis.mV[VX] > 0.f) - { - renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); - } - else - { - renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); - } - } - else if (i == 32) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); - } - else - { - if (constraint_axis.mV[VX] > 0.f) - { - renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); - } - else - { - renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); - } - } - } - else if (world_snap_axis.mV[VZ]) - { - if (i == 0) - { - renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); - } - else if (i == 16) - { - if (constraint_axis.mV[VY] > 0.f) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); - } - else - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); - } - } - else if (i == 32) - { - renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); - } - else - { - if (constraint_axis.mV[VY] > 0.f) - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); - } - else - { - renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); - } - } - } - } - gGL.color4fv(line_color.mV); - } - - // now render projected object axis - if (mInSnapRegime) - { - LLVector3 object_axis; - getObjectAxisClosestToMouse(object_axis); - - // project onto constraint plane - LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); - object_axis = object_axis * first_node->getObject()->getRenderRotation(); - object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); - object_axis.normVec(); - object_axis = object_axis * SNAP_GUIDE_INNER_RADIUS * mRadiusMeters + center; - LLVector3 line_start = center; - - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv(line_start.mV); - gGL.vertex3fv(object_axis.mV); - } - gGL.end(); - - // draw snap guide arrow - gGL.begin(LLRender::TRIANGLES); - { - LLVector3 arrow_dir; - LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis(); - arrow_span.normVec(); - - arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start; - arrow_dir.normVec(); - if (ring_num == 1) - { - arrow_dir *= -1.f; - } - gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV); - gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV); - gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV); - } - gGL.end(); - - { - LLGLDepthTest gls_depth(GL_TRUE); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv(line_start.mV); - gGL.vertex3fv(object_axis.mV); - } - gGL.end(); - - // draw snap guide arrow - gGL.begin(LLRender::TRIANGLES); - { - LLVector3 arrow_dir; - LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis(); - arrow_span.normVec(); - - arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start; - arrow_dir.normVec(); - if (ring_num == 1) - { - arrow_dir *= -1.f; - } - - gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV); - gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV); - gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV); - } - gGL.end(); - } - } - } - } - - - // render help text - if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { - if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) - { - LLVector3 selection_center_start = LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); - - LLVector3 offset_dir = LLViewerCamera::getInstance()->getUpAxis(); - - F32 line_alpha = gSavedSettings.getF32("GridOpacity"); - - LLVector3 help_text_pos = selection_center_start + (mRadiusMeters * 3.f * offset_dir); - const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - - std::string help_text = LLTrans::getString("manip_hint1"); - LLColor4 help_text_color = LLColor4::white; - help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f); - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); - help_text = LLTrans::getString("manip_hint2"); - help_text_pos -= offset_dir * mRadiusMeters * 0.4f; - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); - } - } -} + static LLCachedControl snap_enabled(gSavedSettings, "SnapEnabled", true); + if (!snap_enabled) + { + return; + } -// Returns TRUE if center of sphere is visible. Also sets a bunch of member variables that are used later (e.g. mCenterToCam) -BOOL LLManipRotate::updateVisiblity() -{ - // Don't want to recalculate the center of the selection during a drag. - // Due to packet delays, sometimes half the objects in the selection have their - // new position and half have their old one. This creates subtle errors in the - // computed center position for that frame. Unfortunately, these errors - // accumulate. The result is objects seem to "fly apart" during rotations. - // JC - 03.26.2002 - if (!hasMouseCapture()) - { - mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() );//LLSelectMgr::getInstance()->getSelectionCenterGlobal(); - } - - BOOL visible = FALSE; - - //Assume that UI scale factor is equivalent for X and Y axis - F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; - - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - mCenterToCam = LLVector3(-1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f); - mCenterToCamNorm = mCenterToCam; - mCenterToCamMag = mCenterToCamNorm.normVec(); - - mRadiusMeters = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - mRadiusMeters /= gAgentCamera.mHUDCurZoom; - mRadiusMeters *= ui_scale_factor; - - mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; - mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; - - // x axis range is (-aspect * 0.5f, +aspect * 0.5) - // y axis range is (-0.5, 0.5) - // so use getWorldViewHeightRaw as scale factor when converting to pixel coordinates - mCenterScreen.set((S32)((0.5f - center.mV[VY]) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()), - (S32)((center.mV[VZ] + 0.5f) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled())); - visible = TRUE; - } - else - { - visible = LLViewerCamera::getInstance()->projectPosAgentToScreen(center, mCenterScreen ); - if( visible ) - { - mCenterToCam = gAgentCamera.getCameraPositionAgent() - center; - mCenterToCamNorm = mCenterToCam; - mCenterToCamMag = mCenterToCamNorm.normVec(); - LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis(); - cameraAtAxis.normVec(); - - F32 z_dist = -1.f * (mCenterToCam * cameraAtAxis); - - // Don't drag manip if object too far away - if (gSavedSettings.getBOOL("LimitSelectDistance")) - { - F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); - if (dist_vec_squared(gAgent.getPositionAgent(), center) > (max_select_distance * max_select_distance)) - { - visible = FALSE; - } - } - - if (mCenterToCamMag > 0.001f) - { - F32 fraction_of_fov = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - mRadiusMeters = z_dist * tan(apparent_angle); - mRadiusMeters *= ui_scale_factor; - - mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; - mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; - } - else - { - visible = FALSE; - } - } - } - - mCamEdgeOn = FALSE; - F32 axis_onto_cam = mManipPart >= LL_ROT_X ? llabs( getConstraintAxis() * mCenterToCamNorm ) : 0.f; - if( axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE ) - { - mCamEdgeOn = TRUE; - } - - return visible; -} + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; -LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y ) -{ - LLVector3 cam = gAgentCamera.getCameraPositionAgent(); - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - mMouseCur = intersectMouseWithSphere( x, y, center, mRadiusMeters); - - F32 delta_x = (F32)(mCenterScreen.mX - x); - F32 delta_y = (F32)(mCenterScreen.mY - y); - - F32 dist_from_sphere_center = sqrt(delta_x * delta_x + delta_y * delta_y); - - LLVector3 axis = mMouseDown % mMouseCur; - F32 angle = atan2(sqrtf(axis * axis), mMouseDown * mMouseCur); - axis.normVec(); - LLQuaternion sphere_rot( angle, axis ); - - if (is_approx_zero(1.f - mMouseDown * mMouseCur)) - { - return LLQuaternion::DEFAULT; - } - else if (dist_from_sphere_center < RADIUS_PIXELS) - { - return sphere_rot; - } - else - { - LLVector3 intersection; - getMousePointOnPlaneAgent( intersection, x, y, center + mCenterToProfilePlane, mCenterToCamNorm ); - - // amount dragging in sphere from center to periphery would rotate object - F32 in_sphere_angle = F_PI_BY_TWO; - F32 dist_to_tangent_point = mRadiusMeters; - if( !is_approx_zero( mCenterToProfilePlaneMag ) ) - { - dist_to_tangent_point = sqrt( mRadiusMeters * mRadiusMeters - mCenterToProfilePlaneMag * mCenterToProfilePlaneMag ); - in_sphere_angle = atan2( dist_to_tangent_point, mCenterToProfilePlaneMag ); - } - - LLVector3 profile_center_to_intersection = intersection - (center + mCenterToProfilePlane); - F32 dist_to_intersection = profile_center_to_intersection.normVec(); - F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) * in_sphere_angle; - - LLVector3 axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection; - } - else - { - axis = (cam - center) % profile_center_to_intersection; - axis.normVec(); - } - return sphere_rot * LLQuaternion( angle, axis ); - } -} + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale, true); -LLVector3 LLManipRotate::getConstraintAxis() -{ - LLVector3 axis; - if( LL_ROT_ROLL == mManipPart ) - { - axis = mCenterToCamNorm; - } - else - { - S32 axis_dir = mManipPart - LL_ROT_X; - if ((axis_dir >= LL_NO_PART) && (axis_dir < LL_Z_ARROW)) - { - axis.mV[axis_dir] = 1.f; - } - else - { -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_ERRS() << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << LL_ENDL; -#else - LL_WARNS() << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << LL_ENDL; -#endif - axis.mV[0] = 1.f; - } + LLVector3 constraint_axis = getConstraintAxis(); + + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + LLVector3 cam_at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_at_axis.setVec(1.f, 0.f, 0.f); + } + else + { + cam_at_axis = center - gAgentCamera.getCameraPositionAgent(); + cam_at_axis.normVec(); + } - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; + LLVector3 world_snap_axis; + LLVector3 test_axis = constraint_axis; - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + BOOL constrain_to_ref_object = FALSE; + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) + { + test_axis = test_axis * ~grid_rotation; + } + else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) + { + test_axis = test_axis * ~grid_rotation; + constrain_to_ref_object = TRUE; + } - LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); - if (first_node) - { - // *FIX: get agent local attachment grid working - // Put rotation into frame of first selected root object - axis = axis * grid_rotation; - } - } + test_axis.abs(); - return axis; -} + // find closest global/reference axis to local constraint axis; + if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ]) + { + world_snap_axis = LLVector3::y_axis; + } + else if (test_axis.mV[VY] > test_axis.mV[VZ]) + { + world_snap_axis = LLVector3::z_axis; + } + else + { + world_snap_axis = LLVector3::x_axis; + } -LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) -{ - LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); - LLVector3 constraint_axis = getConstraintAxis(); - LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - - F32 angle = 0.f; - - // build snap axes - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - LLVector3 axis1; - LLVector3 axis2; - - LLVector3 test_axis = constraint_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) - { - test_axis = test_axis * ~grid_rotation; - } - else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) - { - test_axis = test_axis * ~grid_rotation; - } - test_axis.abs(); - - // find closest global axis to constraint axis; - if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ]) - { - axis1 = LLVector3::y_axis; - } - else if (test_axis.mV[VY] > test_axis.mV[VZ]) - { - axis1 = LLVector3::z_axis; - } - else - { - axis1 = LLVector3::x_axis; - } - - if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) - { - axis1 = axis1 * grid_rotation; - } - else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) - { - axis1 = axis1 * grid_rotation; - } - - //project axis onto constraint plane - axis1 -= (axis1 * constraint_axis) * constraint_axis; - axis1.normVec(); - - // calculate third and final axis - axis2 = constraint_axis % axis1; - - //F32 axis_onto_cam = llabs( constraint_axis * mCenterToCamNorm ); - if( mCamEdgeOn ) - { - // We're looking at the ring edge-on. - LLVector3 snap_plane_center = (center + (constraint_axis * mRadiusMeters * 0.5f)); - LLVector3 cam_to_snap_plane; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_to_snap_plane.setVec(1.f, 0.f, 0.f); - } - else - { - cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_to_snap_plane.normVec(); - } - - LLVector3 projected_mouse; - BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); - projected_mouse -= snap_plane_center; - - if (gSavedSettings.getBOOL("SnapEnabled")) { - S32 snap_plane = 0; - - F32 dot = cam_to_snap_plane * constraint_axis; - if (llabs(dot) < 0.01f) - { - // looking at ring edge on, project onto view plane and check if mouse is past ring - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); - projected_mouse -= snap_plane_center; - dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis > 0) - { - snap_plane = 1; - } - projected_mouse -= dot * constraint_axis; - } - else if (dot > 0.f) - { - // look for mouse position outside and in front of snap circle - if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) - { - snap_plane = 1; - } - } - else - { - // look for mouse position inside or in back of snap circle - if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) - { - snap_plane = 1; - } - } - - if (snap_plane == 0) - { - // try other plane - snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_to_snap_plane.setVec(1.f, 0.f, 0.f); - } - else - { - cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_to_snap_plane.normVec(); - } - - hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); - projected_mouse -= snap_plane_center; - - dot = cam_to_snap_plane * constraint_axis; - if (llabs(dot) < 0.01f) - { - // looking at ring edge on, project onto view plane and check if mouse is past ring - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); - projected_mouse -= snap_plane_center; - dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis < 0) - { - snap_plane = 2; - } - projected_mouse -= dot * constraint_axis; - } - else if (dot < 0.f) - { - // look for mouse position outside and in front of snap circle - if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) - { - snap_plane = 2; - } - } - else - { - // look for mouse position inside or in back of snap circle - if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) - { - snap_plane = 2; - } - } - } - - if (snap_plane > 0) - { - LLVector3 cam_at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_at_axis.setVec(1.f, 0.f, 0.f); - } - else - { - cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_at_axis.normVec(); - } - - // first, project mouse onto screen plane at point tangent to rotation radius. - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); - // project that point onto rotation plane - projected_mouse -= snap_plane_center; - projected_mouse -= projected_vec(projected_mouse, constraint_axis); - - F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); - F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; - if (llabs(mouse_lateral_dist) > 0.01f) - { - mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - - (mouse_lateral_dist * mouse_lateral_dist)); - } - LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); - projected_mouse -= mouse_depth * projected_camera_at; - - if (!mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = TRUE; - // 0 to 360 deg - F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); - - F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); - - LLVector3 object_axis; - getObjectAxisClosestToMouse(object_axis); - if (first_object_node) - { - object_axis = object_axis * first_object_node->mSavedRotation; - } - - // project onto constraint plane - object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); - object_axis.normVec(); - - if (relative_mouse_angle < SNAP_ANGLE_DETENTE) - { - F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); - angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); - } - else - { - angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); - } - return LLQuaternion( -angle, constraint_axis ); - } - else - { - if (mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = FALSE; - } - } - else { - if (mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = FALSE; - } - - if (!mInSnapRegime) - { - LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis; - up_from_axis.normVec(); - LLVector3 cur_intersection; - getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam); - cur_intersection -= center; - mMouseCur = projected_vec(cur_intersection, up_from_axis); - F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; - F32 mouse_dist_sqrd = mMouseCur.magVecSquared(); - if (mouse_dist_sqrd > 0.0001f) - { - mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - - mouse_dist_sqrd); - } - LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, constraint_axis); - mMouseCur += mouse_depth * projected_center_to_cam; - - F32 dist = (cur_intersection * up_from_axis) - (mMouseDown * up_from_axis); - angle = dist / (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * -F_PI_BY_TWO; - } - } - else - { - LLVector3 projected_mouse; - getMousePointOnPlaneAgent(projected_mouse, x, y, center, constraint_axis); - projected_mouse -= center; - mMouseCur = projected_mouse; - mMouseCur.normVec(); - - if (!first_object_node) - { - return LLQuaternion::DEFAULT; - } - - if (gSavedSettings.getBOOL("SnapEnabled") && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - { - if (!mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = TRUE; - // 0 to 360 deg - F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); - - F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); - - LLVector3 object_axis; - getObjectAxisClosestToMouse(object_axis); - object_axis = object_axis * first_object_node->mSavedRotation; - - // project onto constraint plane - object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); - object_axis.normVec(); - - if (relative_mouse_angle < SNAP_ANGLE_DETENTE) - { - F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); - angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); - } - else - { - angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); - } - return LLQuaternion( -angle, constraint_axis ); - } - else - { - if (mInSnapRegime) - { - mSmoothRotate = TRUE; - } - mInSnapRegime = FALSE; - } - - LLVector3 cross_product = mMouseDown % mMouseCur; - angle = atan2(sqrtf(cross_product * cross_product), mMouseCur * mMouseDown); - F32 dir = cross_product * constraint_axis; // cross product - if( dir < 0.f ) - { - angle *= -1.f; - } - } - - F32 rot_step = gSavedSettings.getF32("RotationStep"); - F32 step_size = DEG_TO_RAD * rot_step; - angle -= fmod(angle, step_size); - - return LLQuaternion( angle, constraint_axis ); -} + LLVector3 projected_snap_axis = world_snap_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) + { + projected_snap_axis = projected_snap_axis * grid_rotation; + } + else if (constrain_to_ref_object) + { + projected_snap_axis = projected_snap_axis * grid_rotation; + } + // project world snap axis onto constraint plane + projected_snap_axis -= projected_vec(projected_snap_axis, constraint_axis); + projected_snap_axis.normVec(); + S32 num_rings = mCamEdgeOn ? 2 : 1; + for (S32 ring_num = 0; ring_num < num_rings; ring_num++) + { + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); -LLVector3 LLManipRotate::intersectMouseWithSphere( S32 x, S32 y, const LLVector3& sphere_center, F32 sphere_radius) -{ - LLVector3 ray_pt; - LLVector3 ray_dir; - mouseToRay( x, y, &ray_pt, &ray_dir); - return intersectRayWithSphere( ray_pt, ray_dir, sphere_center, sphere_radius ); -} + if (mCamEdgeOn) + { + // draw two opposing rings + if (ring_num == 0) + { + center += constraint_axis * mRadiusMeters * 0.5f; + } + else + { + center -= constraint_axis * mRadiusMeters * 0.5f; + } + } -LLVector3 LLManipRotate::intersectRayWithSphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius) -{ - LLVector3 ray_pt_to_center = sphere_center - ray_pt; - F32 center_distance = ray_pt_to_center.normVec(); - - F32 dot = ray_dir * ray_pt_to_center; - - if (dot == 0.f) - { - return LLVector3::zero; - } - - // point which ray hits plane centered on sphere origin, facing ray origin - LLVector3 intersection_sphere_plane = ray_pt + (ray_dir * center_distance / dot); - // vector from sphere origin to the point, normalized to sphere radius - LLVector3 sphere_center_to_intersection = (intersection_sphere_plane - sphere_center) / sphere_radius; - - F32 dist_squared = sphere_center_to_intersection.magVecSquared(); - LLVector3 result; - - if (dist_squared > 1.f) - { - result = sphere_center_to_intersection; - result.normVec(); - } - else - { - result = sphere_center_to_intersection - ray_dir * sqrt(1.f - dist_squared); - } - - return result; -} + LLGLDepthTest gls_depth(GL_FALSE); + for (S32 pass = 0; pass < 3; pass++) + { + // render snap guide ring + gGL.pushMatrix(); -// Utility function. Should probably be moved to another class. -// x,y - mouse position in scaled window coordinates (NOT GL viewport coordinates) -//static -void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_dir ) -{ - if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) - { - F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewRectScaled().getWidth()) - 0.5f) / gAgentCamera.mHUDCurZoom; - F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewRectScaled().getHeight()) - 0.5f) / gAgentCamera.mHUDCurZoom; - - *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y); - *ray_dir = LLVector3(1.f, 0.f, 0.f); - } - else - { - *ray_pt = gAgentCamera.getCameraPositionAgent(); - *ray_dir = gViewerWindow->mouseDirectionGlobal(x, y); - } -} + LLQuaternion snap_guide_rot; + F32 angle_radians, x, y, z; + snap_guide_rot.shortestArc(LLVector3::z_axis, getConstraintAxis()); + snap_guide_rot.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); -void LLManipRotate::highlightManipulators( S32 x, S32 y ) -{ - mHighlightedPart = LL_NO_PART; - - //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); - - if (!first_object) - { - return; - } - - LLVector3 rotation_center = gAgent.getPosAgentFromGlobal(mRotationCenter); - LLVector3 mouse_dir_x; - LLVector3 mouse_dir_y; - LLVector3 mouse_dir_z; - LLVector3 intersection_roll; - - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - LLVector3 rot_x_axis = LLVector3::x_axis * grid_rotation; - LLVector3 rot_y_axis = LLVector3::y_axis * grid_rotation; - LLVector3 rot_z_axis = LLVector3::z_axis * grid_rotation; - - F32 proj_rot_x_axis = llabs(rot_x_axis * mCenterToCamNorm); - F32 proj_rot_y_axis = llabs(rot_y_axis * mCenterToCamNorm); - F32 proj_rot_z_axis = llabs(rot_z_axis * mCenterToCamNorm); - - F32 min_select_distance = 0.f; - F32 cur_select_distance = 0.f; - - // test x - getMousePointOnPlaneAgent(mouse_dir_x, x, y, rotation_center, rot_x_axis); - mouse_dir_x -= rotation_center; - // push intersection point out when working at obtuse angle to make ring easier to hit - mouse_dir_x *= 1.f + (1.f - llabs(rot_x_axis * mCenterToCamNorm)) * 0.1f; - - // test y - getMousePointOnPlaneAgent(mouse_dir_y, x, y, rotation_center, rot_y_axis); - mouse_dir_y -= rotation_center; - mouse_dir_y *= 1.f + (1.f - llabs(rot_y_axis * mCenterToCamNorm)) * 0.1f; - - // test z - getMousePointOnPlaneAgent(mouse_dir_z, x, y, rotation_center, rot_z_axis); - mouse_dir_z -= rotation_center; - mouse_dir_z *= 1.f + (1.f - llabs(rot_z_axis * mCenterToCamNorm)) * 0.1f; - - // test roll - getMousePointOnPlaneAgent(intersection_roll, x, y, rotation_center, mCenterToCamNorm); - intersection_roll -= rotation_center; - - F32 dist_x = mouse_dir_x.normVec(); - F32 dist_y = mouse_dir_y.normVec(); - F32 dist_z = mouse_dir_z.normVec(); - - F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightScaled(); - - if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold) - { - // selected x - cur_select_distance = dist_x * mouse_dir_x * mCenterToCamNorm; - if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) - { - min_select_distance = cur_select_distance; - mHighlightedPart = LL_ROT_X; - } - } - if (llabs(dist_y - mRadiusMeters) * llmax(0.05f, proj_rot_y_axis) < distance_threshold) - { - // selected y - cur_select_distance = dist_y * mouse_dir_y * mCenterToCamNorm; - if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) - { - min_select_distance = cur_select_distance; - mHighlightedPart = LL_ROT_Y; - } - } - if (llabs(dist_z - mRadiusMeters) * llmax(0.05f, proj_rot_z_axis) < distance_threshold) - { - // selected z - cur_select_distance = dist_z * mouse_dir_z * mCenterToCamNorm; - if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) - { - min_select_distance = cur_select_distance; - mHighlightedPart = LL_ROT_Z; - } - } - - // test for edge-on intersections - if (proj_rot_x_axis < 0.05f) - { - if ((proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_x_axis) < distance_threshold) && dist_y < mRadiusMeters) || - (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_x_axis) < distance_threshold) && dist_z < mRadiusMeters)) - { - mHighlightedPart = LL_ROT_X; - } - } - - if (proj_rot_y_axis < 0.05f) - { - if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_y_axis) < distance_threshold) && dist_x < mRadiusMeters) || - (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_y_axis) < distance_threshold) && dist_z < mRadiusMeters)) - { - mHighlightedPart = LL_ROT_Y; - } - } - - if (proj_rot_z_axis < 0.05f) - { - if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_z_axis) < distance_threshold) && dist_x < mRadiusMeters) || - (proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_z_axis) < distance_threshold) && dist_y < mRadiusMeters)) - { - mHighlightedPart = LL_ROT_Z; - } - } - - // test for roll - if (mHighlightedPart == LL_NO_PART) - { - F32 roll_distance = intersection_roll.magVec(); - F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS; - - // use larger distance threshold for roll as it is checked only if something else wasn't highlighted - if (llabs(roll_distance - (mRadiusMeters + (width_meters * 2.f))) < distance_threshold * 2.f) - { - mHighlightedPart = LL_ROT_ROLL; - } - else if (roll_distance < mRadiusMeters) - { - mHighlightedPart = LL_ROT_GENERAL; - } - } -} + LLColor4 line_color = setupSnapGuideRenderPass(pass); -S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis) -{ - LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); - - if (!first_object_node) - { - object_axis.clearVec(); - return -1; - } - - LLQuaternion obj_rotation = first_object_node->mSavedRotation; - LLVector3 mouse_down_object = mMouseDown * ~obj_rotation; - LLVector3 mouse_down_abs = mouse_down_object; - mouse_down_abs.abs(); - - S32 axis_index = 0; - if (mouse_down_abs.mV[VX] > mouse_down_abs.mV[VY] && mouse_down_abs.mV[VX] > mouse_down_abs.mV[VZ]) - { - if (mouse_down_object.mV[VX] > 0.f) - { - object_axis = LLVector3::x_axis; - } - else - { - object_axis = LLVector3::x_axis_neg; - } - axis_index = VX; - } - else if (mouse_down_abs.mV[VY] > mouse_down_abs.mV[VZ]) - { - if (mouse_down_object.mV[VY] > 0.f) - { - object_axis = LLVector3::y_axis; - } - else - { - object_axis = LLVector3::y_axis_neg; - } - axis_index = VY; - } - else - { - if (mouse_down_object.mV[VZ] > 0.f) - { - object_axis = LLVector3::z_axis; - } - else - { - object_axis = LLVector3::z_axis_neg; - } - axis_index = VZ; - } - - return axis_index; -} + gGL.color4fv(line_color.mV); -//virtual -BOOL LLManipRotate::canAffectSelection() -{ - BOOL can_rotate = mObjectSelection->getObjectCount() != 0; - if (can_rotate) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* objectp) - { - LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); - return objectp->permMove() && !objectp->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); - } - } func; - can_rotate = mObjectSelection->applyToObjects(&func); - } - return can_rotate; + if (mCamEdgeOn) + { + // render an arc + LLVector3 edge_normal = cam_at_axis % constraint_axis; + edge_normal.normVec(); + LLVector3 x_axis_snap = LLVector3::x_axis * snap_guide_rot; + LLVector3 y_axis_snap = LLVector3::y_axis * snap_guide_rot; + + F32 end_angle = atan2(y_axis_snap * edge_normal, x_axis_snap * edge_normal); + //F32 start_angle = angle_between((-1.f * LLVector3::x_axis) * snap_guide_rot, edge_normal); + F32 start_angle = end_angle - F_PI; + gl_arc_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE, start_angle, end_angle); + } + else + { + gl_circle_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS, CIRCLE_STEPS, FALSE); + } + gGL.popMatrix(); + + for (S32 i = 0; i < 64; i++) + { + BOOL render_text = TRUE; + F32 deg = 5.625f * (F32)i; + LLVector3 inner_point; + LLVector3 outer_point; + LLVector3 text_point; + LLQuaternion rot(deg * DEG_TO_RAD, constraint_axis); + gGL.begin(LLRender::LINES); + { + inner_point = (projected_snap_axis * mRadiusMeters * SNAP_GUIDE_INNER_RADIUS * rot) + center; + F32 tick_length = 0.f; + if (i % 16 == 0) + { + tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_1 - SNAP_GUIDE_INNER_RADIUS); + } + else if (i % 8 == 0) + { + tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_2 - SNAP_GUIDE_INNER_RADIUS); + } + else if (i % 4 == 0) + { + tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_3 - SNAP_GUIDE_INNER_RADIUS); + } + else if (i % 2 == 0) + { + tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_4 - SNAP_GUIDE_INNER_RADIUS); + } + else + { + tick_length = mRadiusMeters * (SNAP_GUIDE_RADIUS_5 - SNAP_GUIDE_INNER_RADIUS); + } + + if (mCamEdgeOn) + { + // don't draw ticks that are on back side of circle + F32 dot = cam_at_axis * (projected_snap_axis * rot); + if (dot > 0.f) + { + outer_point = inner_point; + render_text = FALSE; + } + else + { + if (ring_num == 0) + { + outer_point = inner_point + (constraint_axis * tick_length) * rot; + } + else + { + outer_point = inner_point - (constraint_axis * tick_length) * rot; + } + } + } + else + { + outer_point = inner_point + (projected_snap_axis * tick_length) * rot; + } + + text_point = outer_point + (projected_snap_axis * mRadiusMeters * 0.1f) * rot; + + gGL.vertex3fv(inner_point.mV); + gGL.vertex3fv(outer_point.mV); + } + gGL.end(); + + //RN: text rendering does own shadow pass, so only render once + if (pass == 1 && render_text && i % 16 == 0) + { + if (world_snap_axis.mV[VX]) + { + if (i == 0) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); + } + else if (i == 16) + { + if (constraint_axis.mV[VZ] > 0.f) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); + } + else + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); + } + } + else if (i == 32) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); + } + else + { + if (constraint_axis.mV[VZ] > 0.f) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); + } + else + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); + } + } + } + else if (world_snap_axis.mV[VY]) + { + if (i == 0) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Left") : LLTrans::getString("Direction_North"), LLColor4::white); + } + else if (i == 16) + { + if (constraint_axis.mV[VX] > 0.f) + { + renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); + } + else + { + renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); + } + } + else if (i == 32) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Right") : LLTrans::getString("Direction_South"), LLColor4::white); + } + else + { + if (constraint_axis.mV[VX] > 0.f) + { + renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); + } + else + { + renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); + } + } + } + else if (world_snap_axis.mV[VZ]) + { + if (i == 0) + { + renderTickText(text_point, LLTrans::getString("Direction_Up"), LLColor4::white); + } + else if (i == 16) + { + if (constraint_axis.mV[VY] > 0.f) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); + } + else + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); + } + } + else if (i == 32) + { + renderTickText(text_point, LLTrans::getString("Direction_Down"), LLColor4::white); + } + else + { + if (constraint_axis.mV[VY] > 0.f) + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Back") : LLTrans::getString("Direction_West"), LLColor4::white); + } + else + { + renderTickText(text_point, mObjectSelection->isAttachment() ? LLTrans::getString("Direction_Forward") : LLTrans::getString("Direction_East"), LLColor4::white); + } + } + } + } + gGL.color4fv(line_color.mV); + } + + // now render projected object axis + if (mInSnapRegime) + { + LLVector3 object_axis; + getObjectAxisClosestToMouse(object_axis); + + // project onto constraint plane + LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); + object_axis = object_axis * first_node->getObject()->getRenderRotation(); + object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); + object_axis.normVec(); + object_axis = object_axis * SNAP_GUIDE_INNER_RADIUS * mRadiusMeters + center; + LLVector3 line_start = center; + + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv(line_start.mV); + gGL.vertex3fv(object_axis.mV); + } + gGL.end(); + + // draw snap guide arrow + gGL.begin(LLRender::TRIANGLES); + { + LLVector3 arrow_dir; + LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis(); + arrow_span.normVec(); + + arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start; + arrow_dir.normVec(); + if (ring_num == 1) + { + arrow_dir *= -1.f; + } + gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV); + gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV); + gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV); + } + gGL.end(); + + { + LLGLDepthTest gls_depth(GL_TRUE); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv(line_start.mV); + gGL.vertex3fv(object_axis.mV); + } + gGL.end(); + + // draw snap guide arrow + gGL.begin(LLRender::TRIANGLES); + { + LLVector3 arrow_dir; + LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis(); + arrow_span.normVec(); + + arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start; + arrow_dir.normVec(); + if (ring_num == 1) + { + arrow_dir *= -1.f; + } + + gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV); + gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV); + gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV); + } + gGL.end(); + } + } + } + } + + + // render help text + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { + if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) + { + LLVector3 selection_center_start = LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + + LLVector3 offset_dir = LLViewerCamera::getInstance()->getUpAxis(); + + F32 line_alpha = gSavedSettings.getF32("GridOpacity"); + + LLVector3 help_text_pos = selection_center_start + (mRadiusMeters * 3.f * offset_dir); + const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); + + std::string help_text = LLTrans::getString("manip_hint1"); + LLColor4 help_text_color = LLColor4::white; + help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); + help_text = LLTrans::getString("manip_hint2"); + help_text_pos -= offset_dir * mRadiusMeters * 0.4f; + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); + } + } +} + +// Returns TRUE if center of sphere is visible. Also sets a bunch of member variables that are used later (e.g. mCenterToCam) +BOOL LLManipRotate::updateVisiblity() +{ + // Don't want to recalculate the center of the selection during a drag. + // Due to packet delays, sometimes half the objects in the selection have their + // new position and half have their old one. This creates subtle errors in the + // computed center position for that frame. Unfortunately, these errors + // accumulate. The result is objects seem to "fly apart" during rotations. + // JC - 03.26.2002 + if (!hasMouseCapture()) + { + mRotationCenter = gAgent.getPosGlobalFromAgent( getPivotPoint() );//LLSelectMgr::getInstance()->getSelectionCenterGlobal(); + } + + BOOL visible = FALSE; + + //Assume that UI scale factor is equivalent for X and Y axis + F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; + + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + mCenterToCam = LLVector3(-1.f / gAgentCamera.mHUDCurZoom, 0.f, 0.f); + mCenterToCamNorm = mCenterToCam; + mCenterToCamMag = mCenterToCamNorm.normVec(); + + mRadiusMeters = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + mRadiusMeters /= gAgentCamera.mHUDCurZoom; + mRadiusMeters *= ui_scale_factor; + + mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; + mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; + + // x axis range is (-aspect * 0.5f, +aspect * 0.5) + // y axis range is (-0.5, 0.5) + // so use getWorldViewHeightRaw as scale factor when converting to pixel coordinates + mCenterScreen.set((S32)((0.5f - center.mV[VY]) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()), + (S32)((center.mV[VZ] + 0.5f) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled())); + visible = TRUE; + } + else + { + visible = LLViewerCamera::getInstance()->projectPosAgentToScreen(center, mCenterScreen ); + if( visible ) + { + mCenterToCam = gAgentCamera.getCameraPositionAgent() - center; + mCenterToCamNorm = mCenterToCam; + mCenterToCamMag = mCenterToCamNorm.normVec(); + LLVector3 cameraAtAxis = LLViewerCamera::getInstance()->getAtAxis(); + cameraAtAxis.normVec(); + + F32 z_dist = -1.f * (mCenterToCam * cameraAtAxis); + + // Don't drag manip if object too far away + if (gSavedSettings.getBOOL("LimitSelectDistance")) + { + F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); + if (dist_vec_squared(gAgent.getPositionAgent(), center) > (max_select_distance * max_select_distance)) + { + visible = FALSE; + } + } + + if (mCenterToCamMag > 0.001f) + { + F32 fraction_of_fov = RADIUS_PIXELS / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + mRadiusMeters = z_dist * tan(apparent_angle); + mRadiusMeters *= ui_scale_factor; + + mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; + mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; + } + else + { + visible = FALSE; + } + } + } + + mCamEdgeOn = FALSE; + F32 axis_onto_cam = mManipPart >= LL_ROT_X ? llabs( getConstraintAxis() * mCenterToCamNorm ) : 0.f; + if( axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE ) + { + mCamEdgeOn = TRUE; + } + + return visible; +} + +LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y ) +{ + LLVector3 cam = gAgentCamera.getCameraPositionAgent(); + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + + mMouseCur = intersectMouseWithSphere( x, y, center, mRadiusMeters); + + F32 delta_x = (F32)(mCenterScreen.mX - x); + F32 delta_y = (F32)(mCenterScreen.mY - y); + + F32 dist_from_sphere_center = sqrt(delta_x * delta_x + delta_y * delta_y); + + LLVector3 axis = mMouseDown % mMouseCur; + F32 angle = atan2(sqrtf(axis * axis), mMouseDown * mMouseCur); + axis.normVec(); + LLQuaternion sphere_rot( angle, axis ); + + if (is_approx_zero(1.f - mMouseDown * mMouseCur)) + { + return LLQuaternion::DEFAULT; + } + else if (dist_from_sphere_center < RADIUS_PIXELS) + { + return sphere_rot; + } + else + { + LLVector3 intersection; + getMousePointOnPlaneAgent( intersection, x, y, center + mCenterToProfilePlane, mCenterToCamNorm ); + + // amount dragging in sphere from center to periphery would rotate object + F32 in_sphere_angle = F_PI_BY_TWO; + F32 dist_to_tangent_point = mRadiusMeters; + if( !is_approx_zero( mCenterToProfilePlaneMag ) ) + { + dist_to_tangent_point = sqrt( mRadiusMeters * mRadiusMeters - mCenterToProfilePlaneMag * mCenterToProfilePlaneMag ); + in_sphere_angle = atan2( dist_to_tangent_point, mCenterToProfilePlaneMag ); + } + + LLVector3 profile_center_to_intersection = intersection - (center + mCenterToProfilePlane); + F32 dist_to_intersection = profile_center_to_intersection.normVec(); + F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) * in_sphere_angle; + + LLVector3 axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection; + } + else + { + axis = (cam - center) % profile_center_to_intersection; + axis.normVec(); + } + return sphere_rot * LLQuaternion( angle, axis ); + } +} + +LLVector3 LLManipRotate::getConstraintAxis() +{ + LLVector3 axis; + if( LL_ROT_ROLL == mManipPart ) + { + axis = mCenterToCamNorm; + } + else + { + S32 axis_dir = mManipPart - LL_ROT_X; + if ((axis_dir >= LL_NO_PART) && (axis_dir < LL_Z_ARROW)) + { + axis.mV[axis_dir] = 1.f; + } + else + { +#ifndef LL_RELEASE_FOR_DOWNLOAD + LL_ERRS() << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << LL_ENDL; +#else + LL_WARNS() << "Got bogus hit part in LLManipRotate::getConstraintAxis():" << mManipPart << LL_ENDL; +#endif + axis.mV[0] = 1.f; + } + + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); + if (first_node) + { + // *FIX: get agent local attachment grid working + // Put rotation into frame of first selected root object + axis = axis * grid_rotation; + } + } + + return axis; +} + +LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) +{ + LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); + LLVector3 constraint_axis = getConstraintAxis(); + LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); + + F32 angle = 0.f; + + // build snap axes + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + LLVector3 axis1; + LLVector3 axis2; + + LLVector3 test_axis = constraint_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) + { + test_axis = test_axis * ~grid_rotation; + } + else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) + { + test_axis = test_axis * ~grid_rotation; + } + test_axis.abs(); + + // find closest global axis to constraint axis; + if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ]) + { + axis1 = LLVector3::y_axis; + } + else if (test_axis.mV[VY] > test_axis.mV[VZ]) + { + axis1 = LLVector3::z_axis; + } + else + { + axis1 = LLVector3::x_axis; + } + + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) + { + axis1 = axis1 * grid_rotation; + } + else if (LLSelectMgr::getInstance()->getGridMode() == GRID_MODE_REF_OBJECT) + { + axis1 = axis1 * grid_rotation; + } + + //project axis onto constraint plane + axis1 -= (axis1 * constraint_axis) * constraint_axis; + axis1.normVec(); + + // calculate third and final axis + axis2 = constraint_axis % axis1; + + //F32 axis_onto_cam = llabs( constraint_axis * mCenterToCamNorm ); + if( mCamEdgeOn ) + { + // We're looking at the ring edge-on. + LLVector3 snap_plane_center = (center + (constraint_axis * mRadiusMeters * 0.5f)); + LLVector3 cam_to_snap_plane; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_to_snap_plane.setVec(1.f, 0.f, 0.f); + } + else + { + cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_to_snap_plane.normVec(); + } + + LLVector3 projected_mouse; + BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); + projected_mouse -= snap_plane_center; + + if (gSavedSettings.getBOOL("SnapEnabled")) { + S32 snap_plane = 0; + + F32 dot = cam_to_snap_plane * constraint_axis; + if (llabs(dot) < 0.01f) + { + // looking at ring edge on, project onto view plane and check if mouse is past ring + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); + projected_mouse -= snap_plane_center; + dot = projected_mouse * constraint_axis; + if (projected_mouse * constraint_axis > 0) + { + snap_plane = 1; + } + projected_mouse -= dot * constraint_axis; + } + else if (dot > 0.f) + { + // look for mouse position outside and in front of snap circle + if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) + { + snap_plane = 1; + } + } + else + { + // look for mouse position inside or in back of snap circle + if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) + { + snap_plane = 1; + } + } + + if (snap_plane == 0) + { + // try other plane + snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_to_snap_plane.setVec(1.f, 0.f, 0.f); + } + else + { + cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_to_snap_plane.normVec(); + } + + hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); + projected_mouse -= snap_plane_center; + + dot = cam_to_snap_plane * constraint_axis; + if (llabs(dot) < 0.01f) + { + // looking at ring edge on, project onto view plane and check if mouse is past ring + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); + projected_mouse -= snap_plane_center; + dot = projected_mouse * constraint_axis; + if (projected_mouse * constraint_axis < 0) + { + snap_plane = 2; + } + projected_mouse -= dot * constraint_axis; + } + else if (dot < 0.f) + { + // look for mouse position outside and in front of snap circle + if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) + { + snap_plane = 2; + } + } + else + { + // look for mouse position inside or in back of snap circle + if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) + { + snap_plane = 2; + } + } + } + + if (snap_plane > 0) + { + LLVector3 cam_at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_at_axis.setVec(1.f, 0.f, 0.f); + } + else + { + cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_at_axis.normVec(); + } + + // first, project mouse onto screen plane at point tangent to rotation radius. + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); + // project that point onto rotation plane + projected_mouse -= snap_plane_center; + projected_mouse -= projected_vec(projected_mouse, constraint_axis); + + F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); + F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; + if (llabs(mouse_lateral_dist) > 0.01f) + { + mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - + (mouse_lateral_dist * mouse_lateral_dist)); + } + LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); + projected_mouse -= mouse_depth * projected_camera_at; + + if (!mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = TRUE; + // 0 to 360 deg + F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); + + F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); + + LLVector3 object_axis; + getObjectAxisClosestToMouse(object_axis); + if (first_object_node) + { + object_axis = object_axis * first_object_node->mSavedRotation; + } + + // project onto constraint plane + object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); + object_axis.normVec(); + + if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + { + F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); + angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + else + { + angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + return LLQuaternion( -angle, constraint_axis ); + } + else + { + if (mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = FALSE; + } + } + else { + if (mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = FALSE; + } + + if (!mInSnapRegime) + { + LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis; + up_from_axis.normVec(); + LLVector3 cur_intersection; + getMousePointOnPlaneAgent(cur_intersection, x, y, center, mCenterToCam); + cur_intersection -= center; + mMouseCur = projected_vec(cur_intersection, up_from_axis); + F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; + F32 mouse_dist_sqrd = mMouseCur.magVecSquared(); + if (mouse_dist_sqrd > 0.0001f) + { + mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - + mouse_dist_sqrd); + } + LLVector3 projected_center_to_cam = mCenterToCamNorm - projected_vec(mCenterToCamNorm, constraint_axis); + mMouseCur += mouse_depth * projected_center_to_cam; + + F32 dist = (cur_intersection * up_from_axis) - (mMouseDown * up_from_axis); + angle = dist / (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * -F_PI_BY_TWO; + } + } + else + { + LLVector3 projected_mouse; + getMousePointOnPlaneAgent(projected_mouse, x, y, center, constraint_axis); + projected_mouse -= center; + mMouseCur = projected_mouse; + mMouseCur.normVec(); + + if (!first_object_node) + { + return LLQuaternion::DEFAULT; + } + + if (gSavedSettings.getBOOL("SnapEnabled") && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) + { + if (!mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = TRUE; + // 0 to 360 deg + F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); + + F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); + + LLVector3 object_axis; + getObjectAxisClosestToMouse(object_axis); + object_axis = object_axis * first_object_node->mSavedRotation; + + // project onto constraint plane + object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); + object_axis.normVec(); + + if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + { + F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); + angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + else + { + angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + return LLQuaternion( -angle, constraint_axis ); + } + else + { + if (mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = FALSE; + } + + LLVector3 cross_product = mMouseDown % mMouseCur; + angle = atan2(sqrtf(cross_product * cross_product), mMouseCur * mMouseDown); + F32 dir = cross_product * constraint_axis; // cross product + if( dir < 0.f ) + { + angle *= -1.f; + } + } + + F32 rot_step = gSavedSettings.getF32("RotationStep"); + F32 step_size = DEG_TO_RAD * rot_step; + angle -= fmod(angle, step_size); + + return LLQuaternion( angle, constraint_axis ); +} + + + +LLVector3 LLManipRotate::intersectMouseWithSphere( S32 x, S32 y, const LLVector3& sphere_center, F32 sphere_radius) +{ + LLVector3 ray_pt; + LLVector3 ray_dir; + mouseToRay( x, y, &ray_pt, &ray_dir); + return intersectRayWithSphere( ray_pt, ray_dir, sphere_center, sphere_radius ); +} + +LLVector3 LLManipRotate::intersectRayWithSphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius) +{ + LLVector3 ray_pt_to_center = sphere_center - ray_pt; + F32 center_distance = ray_pt_to_center.normVec(); + + F32 dot = ray_dir * ray_pt_to_center; + + if (dot == 0.f) + { + return LLVector3::zero; + } + + // point which ray hits plane centered on sphere origin, facing ray origin + LLVector3 intersection_sphere_plane = ray_pt + (ray_dir * center_distance / dot); + // vector from sphere origin to the point, normalized to sphere radius + LLVector3 sphere_center_to_intersection = (intersection_sphere_plane - sphere_center) / sphere_radius; + + F32 dist_squared = sphere_center_to_intersection.magVecSquared(); + LLVector3 result; + + if (dist_squared > 1.f) + { + result = sphere_center_to_intersection; + result.normVec(); + } + else + { + result = sphere_center_to_intersection - ray_dir * sqrt(1.f - dist_squared); + } + + return result; +} + +// Utility function. Should probably be moved to another class. +// x,y - mouse position in scaled window coordinates (NOT GL viewport coordinates) +//static +void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_dir ) +{ + if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) + { + F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewRectScaled().getWidth()) - 0.5f) / gAgentCamera.mHUDCurZoom; + F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewRectScaled().getHeight()) - 0.5f) / gAgentCamera.mHUDCurZoom; + + *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y); + *ray_dir = LLVector3(1.f, 0.f, 0.f); + } + else + { + *ray_pt = gAgentCamera.getCameraPositionAgent(); + *ray_dir = gViewerWindow->mouseDirectionGlobal(x, y); + } +} + +void LLManipRotate::highlightManipulators( S32 x, S32 y ) +{ + mHighlightedPart = LL_NO_PART; + + //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); + + if (!first_object) + { + return; + } + + LLVector3 rotation_center = gAgent.getPosAgentFromGlobal(mRotationCenter); + LLVector3 mouse_dir_x; + LLVector3 mouse_dir_y; + LLVector3 mouse_dir_z; + LLVector3 intersection_roll; + + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + + LLVector3 rot_x_axis = LLVector3::x_axis * grid_rotation; + LLVector3 rot_y_axis = LLVector3::y_axis * grid_rotation; + LLVector3 rot_z_axis = LLVector3::z_axis * grid_rotation; + + F32 proj_rot_x_axis = llabs(rot_x_axis * mCenterToCamNorm); + F32 proj_rot_y_axis = llabs(rot_y_axis * mCenterToCamNorm); + F32 proj_rot_z_axis = llabs(rot_z_axis * mCenterToCamNorm); + + F32 min_select_distance = 0.f; + F32 cur_select_distance = 0.f; + + // test x + getMousePointOnPlaneAgent(mouse_dir_x, x, y, rotation_center, rot_x_axis); + mouse_dir_x -= rotation_center; + // push intersection point out when working at obtuse angle to make ring easier to hit + mouse_dir_x *= 1.f + (1.f - llabs(rot_x_axis * mCenterToCamNorm)) * 0.1f; + + // test y + getMousePointOnPlaneAgent(mouse_dir_y, x, y, rotation_center, rot_y_axis); + mouse_dir_y -= rotation_center; + mouse_dir_y *= 1.f + (1.f - llabs(rot_y_axis * mCenterToCamNorm)) * 0.1f; + + // test z + getMousePointOnPlaneAgent(mouse_dir_z, x, y, rotation_center, rot_z_axis); + mouse_dir_z -= rotation_center; + mouse_dir_z *= 1.f + (1.f - llabs(rot_z_axis * mCenterToCamNorm)) * 0.1f; + + // test roll + getMousePointOnPlaneAgent(intersection_roll, x, y, rotation_center, mCenterToCamNorm); + intersection_roll -= rotation_center; + + F32 dist_x = mouse_dir_x.normVec(); + F32 dist_y = mouse_dir_y.normVec(); + F32 dist_z = mouse_dir_z.normVec(); + + F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightScaled(); + + if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold) + { + // selected x + cur_select_distance = dist_x * mouse_dir_x * mCenterToCamNorm; + if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) + { + min_select_distance = cur_select_distance; + mHighlightedPart = LL_ROT_X; + } + } + if (llabs(dist_y - mRadiusMeters) * llmax(0.05f, proj_rot_y_axis) < distance_threshold) + { + // selected y + cur_select_distance = dist_y * mouse_dir_y * mCenterToCamNorm; + if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) + { + min_select_distance = cur_select_distance; + mHighlightedPart = LL_ROT_Y; + } + } + if (llabs(dist_z - mRadiusMeters) * llmax(0.05f, proj_rot_z_axis) < distance_threshold) + { + // selected z + cur_select_distance = dist_z * mouse_dir_z * mCenterToCamNorm; + if (cur_select_distance >= -0.05f && (min_select_distance == 0.f || cur_select_distance > min_select_distance)) + { + min_select_distance = cur_select_distance; + mHighlightedPart = LL_ROT_Z; + } + } + + // test for edge-on intersections + if (proj_rot_x_axis < 0.05f) + { + if ((proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_x_axis) < distance_threshold) && dist_y < mRadiusMeters) || + (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_x_axis) < distance_threshold) && dist_z < mRadiusMeters)) + { + mHighlightedPart = LL_ROT_X; + } + } + + if (proj_rot_y_axis < 0.05f) + { + if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_y_axis) < distance_threshold) && dist_x < mRadiusMeters) || + (proj_rot_z_axis > 0.05f && (dist_z * llabs(mouse_dir_z * rot_y_axis) < distance_threshold) && dist_z < mRadiusMeters)) + { + mHighlightedPart = LL_ROT_Y; + } + } + + if (proj_rot_z_axis < 0.05f) + { + if ((proj_rot_x_axis > 0.05f && (dist_x * llabs(mouse_dir_x * rot_z_axis) < distance_threshold) && dist_x < mRadiusMeters) || + (proj_rot_y_axis > 0.05f && (dist_y * llabs(mouse_dir_y * rot_z_axis) < distance_threshold) && dist_y < mRadiusMeters)) + { + mHighlightedPart = LL_ROT_Z; + } + } + + // test for roll + if (mHighlightedPart == LL_NO_PART) + { + F32 roll_distance = intersection_roll.magVec(); + F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS; + + // use larger distance threshold for roll as it is checked only if something else wasn't highlighted + if (llabs(roll_distance - (mRadiusMeters + (width_meters * 2.f))) < distance_threshold * 2.f) + { + mHighlightedPart = LL_ROT_ROLL; + } + else if (roll_distance < mRadiusMeters) + { + mHighlightedPart = LL_ROT_GENERAL; + } + } +} + +S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis) +{ + LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); + + if (!first_object_node) + { + object_axis.clearVec(); + return -1; + } + + LLQuaternion obj_rotation = first_object_node->mSavedRotation; + LLVector3 mouse_down_object = mMouseDown * ~obj_rotation; + LLVector3 mouse_down_abs = mouse_down_object; + mouse_down_abs.abs(); + + S32 axis_index = 0; + if (mouse_down_abs.mV[VX] > mouse_down_abs.mV[VY] && mouse_down_abs.mV[VX] > mouse_down_abs.mV[VZ]) + { + if (mouse_down_object.mV[VX] > 0.f) + { + object_axis = LLVector3::x_axis; + } + else + { + object_axis = LLVector3::x_axis_neg; + } + axis_index = VX; + } + else if (mouse_down_abs.mV[VY] > mouse_down_abs.mV[VZ]) + { + if (mouse_down_object.mV[VY] > 0.f) + { + object_axis = LLVector3::y_axis; + } + else + { + object_axis = LLVector3::y_axis_neg; + } + axis_index = VY; + } + else + { + if (mouse_down_object.mV[VZ] > 0.f) + { + object_axis = LLVector3::z_axis; + } + else + { + object_axis = LLVector3::z_axis_neg; + } + axis_index = VZ; + } + + return axis_index; +} + +//virtual +BOOL LLManipRotate::canAffectSelection() +{ + BOOL can_rotate = mObjectSelection->getObjectCount() != 0; + if (can_rotate) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + } + } func; + can_rotate = mObjectSelection->applyToObjects(&func); + } + return can_rotate; } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 9fc5ad502c..b3ecb6403b 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmaniptranslate.cpp * @brief LLManipTranslate class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -76,202 +76,202 @@ const F32 SNAP_ARROW_SCALE = 0.7f; static LLPointer sGridTex = NULL ; -const LLManip::EManipPart MANIPULATOR_IDS[9] = +const LLManip::EManipPart MANIPULATOR_IDS[9] = { - LLManip::LL_X_ARROW, - LLManip::LL_Y_ARROW, - LLManip::LL_Z_ARROW, - LLManip::LL_X_ARROW, - LLManip::LL_Y_ARROW, - LLManip::LL_Z_ARROW, - LLManip::LL_YZ_PLANE, - LLManip::LL_XZ_PLANE, - LLManip::LL_XY_PLANE + LLManip::LL_X_ARROW, + LLManip::LL_Y_ARROW, + LLManip::LL_Z_ARROW, + LLManip::LL_X_ARROW, + LLManip::LL_Y_ARROW, + LLManip::LL_Z_ARROW, + LLManip::LL_YZ_PLANE, + LLManip::LL_XZ_PLANE, + LLManip::LL_XY_PLANE }; -const U32 ARROW_TO_AXIS[4] = +const U32 ARROW_TO_AXIS[4] = { - VX, - VX, - VY, - VZ + VX, + VX, + VY, + VZ }; // Sort manipulator handles by their screen-space projection struct ClosestToCamera { - bool operator()(const LLManipTranslate::ManipulatorHandle& a, - const LLManipTranslate::ManipulatorHandle& b) const - { - return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; - } + bool operator()(const LLManipTranslate::ManipulatorHandle& a, + const LLManipTranslate::ManipulatorHandle& b) const + { + return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; + } }; LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) -: LLManip( std::string("Move"), composite ), - mLastHoverMouseX(-1), - mLastHoverMouseY(-1), - mMouseOutsideSlop(FALSE), - mCopyMadeThisDrag(FALSE), - mMouseDownX(-1), - mMouseDownY(-1), - mAxisArrowLength(50), - mConeSize(0), - mArrowLengthMeters(0.f), - mGridSizeMeters(1.f), - mPlaneManipOffsetMeters(0.f), - mUpdateTimer(), - mSnapOffsetMeters(0.f), - mSubdivisions(10.f), - mInSnapRegime(FALSE), - mArrowScales(1.f, 1.f, 1.f), - mPlaneScales(1.f, 1.f, 1.f), - mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) -{ - if (sGridTex.isNull()) - { - restoreGL(); - } +: LLManip( std::string("Move"), composite ), + mLastHoverMouseX(-1), + mLastHoverMouseY(-1), + mMouseOutsideSlop(FALSE), + mCopyMadeThisDrag(FALSE), + mMouseDownX(-1), + mMouseDownY(-1), + mAxisArrowLength(50), + mConeSize(0), + mArrowLengthMeters(0.f), + mGridSizeMeters(1.f), + mPlaneManipOffsetMeters(0.f), + mUpdateTimer(), + mSnapOffsetMeters(0.f), + mSubdivisions(10.f), + mInSnapRegime(FALSE), + mArrowScales(1.f, 1.f, 1.f), + mPlaneScales(1.f, 1.f, 1.f), + mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) +{ + if (sGridTex.isNull()) + { + restoreGL(); + } } //static U32 LLManipTranslate::getGridTexName() { - if(sGridTex.isNull()) - { - restoreGL() ; - } + if(sGridTex.isNull()) + { + restoreGL() ; + } - return sGridTex.isNull() ? 0 : sGridTex->getTexName() ; + return sGridTex.isNull() ? 0 : sGridTex->getTexName() ; } //static void LLManipTranslate::destroyGL() { - if (sGridTex) - { - sGridTex = NULL ; - } + if (sGridTex) + { + sGridTex = NULL ; + } } //static void LLManipTranslate::restoreGL() { - //generate grid texture - U32 rez = 512; - U32 mip = 0; - - destroyGL() ; - sGridTex = LLViewerTextureManager::getLocalTexture() ; - if(!sGridTex->createGLTexture()) - { - sGridTex = NULL ; - return ; - } - - GLuint* d = new GLuint[rez*rez]; - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - - while (rez >= 1) - { - for (U32 i = 0; i < rez*rez; i++) - { - d[i] = 0x00FFFFFF; - } - - U32 subcol = 0xFFFFFFFF; - if (rez >= 4) - { //large grain grid - for (U32 i = 0; i < rez; i++) - { - if (rez <= 16) - { - if (rez == 16) - { - subcol = 0xA0FFFFFF; - } - else if (rez == 8) - { - subcol = 0x80FFFFFF; - } - else - { - subcol = 0x40FFFFFF; - } - } - else - { - subcol = 0xFFFFFFFF; - } - d[i *rez+ 0 ] = subcol; - d[0 *rez+ i ] = subcol; - if (rez >= 32) - { - d[i *rez+ (rez-1)] = subcol; - d[(rez-1) *rez+ i ] = subcol; - } - - if (rez >= 64) - { - subcol = 0xFFFFFFFF; - - if (i > 0 && i < (rez-1)) - { - d[i *rez+ 1 ] = subcol; - d[i *rez+ (rez-2)] = subcol; - d[1 *rez+ i ] = subcol; - d[(rez-2) *rez+ i ] = subcol; - } - } - } - } - - subcol = 0x50A0A0A0; - if (rez >= 128) - { //small grain grid - for (U32 i = 8; i < rez; i+=8) - { - for (U32 j = 2; j < rez-2; j++) - { - d[i *rez+ j] = subcol; - d[j *rez+ i] = subcol; - } - } - } - if (rez >= 64) - { //medium grain grid - if (rez == 64) - { - subcol = 0x50A0A0A0; - } - else - { - subcol = 0xA0D0D0D0; - } - - for (U32 i = 32; i < rez; i+=32) - { - U32 pi = i-1; - for (U32 j = 2; j < rez-2; j++) - { - d[i *rez+ j] = subcol; - d[j *rez+ i] = subcol; - - if (rez > 128) - { - d[pi *rez+ j] = subcol; - d[j *rez+ pi] = subcol; - } - } - } - } - LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); - rez = rez >> 1; - mip++; - } - delete [] d; + //generate grid texture + U32 rez = 512; + U32 mip = 0; + + destroyGL() ; + sGridTex = LLViewerTextureManager::getLocalTexture() ; + if(!sGridTex->createGLTexture()) + { + sGridTex = NULL ; + return ; + } + + GLuint* d = new GLuint[rez*rez]; + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName(), true); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + + while (rez >= 1) + { + for (U32 i = 0; i < rez*rez; i++) + { + d[i] = 0x00FFFFFF; + } + + U32 subcol = 0xFFFFFFFF; + if (rez >= 4) + { //large grain grid + for (U32 i = 0; i < rez; i++) + { + if (rez <= 16) + { + if (rez == 16) + { + subcol = 0xA0FFFFFF; + } + else if (rez == 8) + { + subcol = 0x80FFFFFF; + } + else + { + subcol = 0x40FFFFFF; + } + } + else + { + subcol = 0xFFFFFFFF; + } + d[i *rez+ 0 ] = subcol; + d[0 *rez+ i ] = subcol; + if (rez >= 32) + { + d[i *rez+ (rez-1)] = subcol; + d[(rez-1) *rez+ i ] = subcol; + } + + if (rez >= 64) + { + subcol = 0xFFFFFFFF; + + if (i > 0 && i < (rez-1)) + { + d[i *rez+ 1 ] = subcol; + d[i *rez+ (rez-2)] = subcol; + d[1 *rez+ i ] = subcol; + d[(rez-2) *rez+ i ] = subcol; + } + } + } + } + + subcol = 0x50A0A0A0; + if (rez >= 128) + { //small grain grid + for (U32 i = 8; i < rez; i+=8) + { + for (U32 j = 2; j < rez-2; j++) + { + d[i *rez+ j] = subcol; + d[j *rez+ i] = subcol; + } + } + } + if (rez >= 64) + { //medium grain grid + if (rez == 64) + { + subcol = 0x50A0A0A0; + } + else + { + subcol = 0xA0D0D0D0; + } + + for (U32 i = 32; i < rez; i+=32) + { + U32 pi = i-1; + for (U32 j = 2; j < rez-2; j++) + { + d[i *rez+ j] = subcol; + d[j *rez+ i] = subcol; + + if (rez > 128) + { + d[pi *rez+ j] = subcol; + d[j *rez+ pi] = subcol; + } + } + } + } + LLImageGL::setManualImage(GL_TEXTURE_2D, mip, GL_RGBA, rez, rez, GL_RGBA, GL_UNSIGNED_BYTE, d); + rez = rez >> 1; + mip++; + } + delete [] d; } @@ -282,379 +282,379 @@ LLManipTranslate::~LLManipTranslate() void LLManipTranslate::handleSelect() { - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); if (gFloaterTools) { gFloaterTools->setStatusText("move"); } - LLManip::handleSelect(); + LLManip::handleSelect(); } BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = FALSE; - - // didn't click in any UI object, so must have clicked in the world - if( (mHighlightedPart == LL_X_ARROW || - mHighlightedPart == LL_Y_ARROW || - mHighlightedPart == LL_Z_ARROW || - mHighlightedPart == LL_YZ_PLANE || - mHighlightedPart == LL_XZ_PLANE || - mHighlightedPart == LL_XY_PLANE ) ) - { - handled = handleMouseDownOnPart( x, y, mask ); - } - - return handled; + BOOL handled = FALSE; + + // didn't click in any UI object, so must have clicked in the world + if( (mHighlightedPart == LL_X_ARROW || + mHighlightedPart == LL_Y_ARROW || + mHighlightedPart == LL_Z_ARROW || + mHighlightedPart == LL_YZ_PLANE || + mHighlightedPart == LL_XZ_PLANE || + mHighlightedPart == LL_XY_PLANE ) ) + { + handled = handleMouseDownOnPart( x, y, mask ); + } + + return handled; } // Assumes that one of the arrows on an object was hit. BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_move = canAffectSelection(); - if (!can_move) - { - return FALSE; - } - - highlightManipulators(x, y); - S32 hit_part = mHighlightedPart; - - if( (hit_part != LL_X_ARROW) && - (hit_part != LL_Y_ARROW) && - (hit_part != LL_Z_ARROW) && - (hit_part != LL_YZ_PLANE) && - (hit_part != LL_XZ_PLANE) && - (hit_part != LL_XY_PLANE) ) - { - return TRUE; - } - - mHelpTextTimer.reset(); - sNumTimesHelpTextShown++; - - LLSelectMgr::getInstance()->getGrid(mGridOrigin, mGridRotation, mGridScale); - - LLSelectMgr::getInstance()->enableSilhouette(FALSE); - - // we just started a drag, so save initial object positions - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE); - - mManipPart = (EManipPart)hit_part; - mMouseDownX = x; - mMouseDownY = y; - mMouseOutsideSlop = FALSE; - - LLVector3 axis; - - LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE); - - if (!selectNode) - { - // didn't find the object in our selection...oh well - LL_WARNS() << "Trying to translate an unselected object" << LL_ENDL; - return TRUE; - } - - LLViewerObject *selected_object = selectNode->getObject(); - if (!selected_object) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no selected object" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - // Compute unit vectors for arrow hit and a plane through that vector - BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis); - getManipNormal(selected_object, mManipPart, mManipNormal); - - //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); - // TomY: The above should (?) be identical to the below - LLVector3 select_center_agent = getPivotPoint(); - mSubdivisions = getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()); - - // if we clicked on a planar manipulator, recenter mouse cursor - if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) - { - LLCoordGL mouse_pos; - if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(select_center_agent, mouse_pos)) - { - // mouse_pos may be nonsense - LL_WARNS() << "Failed to project object center to screen" << LL_ENDL; - } - else if (gSavedSettings.getBOOL("SnapToMouseCursor")) - { - LLUI::getInstance()->setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); - x = mouse_pos.mX; - y = mouse_pos.mY; - } - } - - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); - getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal); - mDragSelectionStartGlobal = object_start_global; - mCopyMadeThisDrag = FALSE; - - // Route future Mouse messages here preemptively. (Release on mouse up.) - setMouseCapture( TRUE ); - - return TRUE; + BOOL can_move = canAffectSelection(); + if (!can_move) + { + return FALSE; + } + + highlightManipulators(x, y); + S32 hit_part = mHighlightedPart; + + if( (hit_part != LL_X_ARROW) && + (hit_part != LL_Y_ARROW) && + (hit_part != LL_Z_ARROW) && + (hit_part != LL_YZ_PLANE) && + (hit_part != LL_XZ_PLANE) && + (hit_part != LL_XY_PLANE) ) + { + return TRUE; + } + + mHelpTextTimer.reset(); + sNumTimesHelpTextShown++; + + LLSelectMgr::getInstance()->getGrid(mGridOrigin, mGridRotation, mGridScale); + + LLSelectMgr::getInstance()->enableSilhouette(FALSE); + + // we just started a drag, so save initial object positions + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_MOVE); + + mManipPart = (EManipPart)hit_part; + mMouseDownX = x; + mMouseDownY = y; + mMouseOutsideSlop = FALSE; + + LLVector3 axis; + + LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE); + + if (!selectNode) + { + // didn't find the object in our selection...oh well + LL_WARNS() << "Trying to translate an unselected object" << LL_ENDL; + return TRUE; + } + + LLViewerObject *selected_object = selectNode->getObject(); + if (!selected_object) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no selected object" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + // Compute unit vectors for arrow hit and a plane through that vector + BOOL axis_exists = getManipAxis(selected_object, mManipPart, axis); + getManipNormal(selected_object, mManipPart, mManipNormal); + + //LLVector3 select_center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); + // TomY: The above should (?) be identical to the below + LLVector3 select_center_agent = getPivotPoint(); + mSubdivisions = getSubdivisionLevel(select_center_agent, axis_exists ? axis : LLVector3::z_axis, getMinGridScale()); + + // if we clicked on a planar manipulator, recenter mouse cursor + if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) + { + LLCoordGL mouse_pos; + if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(select_center_agent, mouse_pos)) + { + // mouse_pos may be nonsense + LL_WARNS() << "Failed to project object center to screen" << LL_ENDL; + } + else if (gSavedSettings.getBOOL("SnapToMouseCursor")) + { + LLUI::getInstance()->setMousePositionScreen(mouse_pos.mX, mouse_pos.mY); + x = mouse_pos.mX; + y = mouse_pos.mY; + } + } + + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLVector3d object_start_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); + getMousePointOnPlaneGlobal(mDragCursorStartGlobal, x, y, object_start_global, mManipNormal); + mDragSelectionStartGlobal = object_start_global; + mCopyMadeThisDrag = FALSE; + + // Route future Mouse messages here preemptively. (Release on mouse up.) + setMouseCapture( TRUE ); + + return TRUE; } BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) { - // Translation tool only works if mouse button is down. - // Bail out if mouse not down. - if( !hasMouseCapture() ) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (inactive)" << LL_ENDL; - // Always show cursor - // gViewerWindow->setCursor(UI_CURSOR_ARROW); - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - - highlightManipulators(x, y); - return TRUE; - } - - // Handle auto-rotation if necessary. - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); - const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20; - const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; - BOOL rotated = FALSE; - - // ...build mode moves camera about focus point - if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { - if (x < ROTATE_H_MARGIN) - { - gAgentCamera.cameraOrbitAround(rotate_angle); - rotated = TRUE; - } - else if (x > world_rect.getWidth() - ROTATE_H_MARGIN) - { - gAgentCamera.cameraOrbitAround(-rotate_angle); - rotated = TRUE; - } - } - - // Suppress processing if mouse hasn't actually moved. - // This may cause problems if the camera moves outside of the - // rotation above. - if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse unmoved)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - mLastHoverMouseX = x; - mLastHoverMouseY = y; - - // Suppress if mouse hasn't moved past the initial slop region - // Reset once we start moving - if( !mMouseOutsideSlop ) - { - if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP ) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse inside slop)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - else - { - // ...just went outside the slop region - mMouseOutsideSlop = TRUE; - // If holding down shift, leave behind a copy. - if (mask == MASK_COPY) - { - // ...we're trying to make a copy - LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); - mCopyMadeThisDrag = TRUE; - - // When we make the copy, we don't want to do any other processing. - // If so, the object will also be moved, and the copy will be offset. - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (made copy)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - } - } - } - - // Throttle updates to 10 per second. - - LLVector3 axis_f; - LLVector3d axis_d; - - // pick the first object to constrain to grid w/ common origin - // this is so we don't screw up groups - LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE); - if (!selectNode) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no selectNode" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - LLViewerObject* object = selectNode->getObject(); - if (!object) - { - // somehow we lost the object! - LL_WARNS() << "Translate manip lost the object, no object in selectNode" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; - } - - // Compute unit vectors for arrow hit and a plane through that vector - BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this - - axis_d.setVec(axis_f); - - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); - - mSubdivisions = getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()); - - // Project the cursor onto that plane - LLVector3d relative_move; - getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\ - relative_move -= mDragCursorStartGlobal; - - // You can't move more than some distance from your original mousedown point. - if (gSavedSettings.getBOOL("LimitDragDistance")) - { - F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance"); - - if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance) - { - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (too far)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); - return TRUE; - } - } - - F64 axis_magnitude = relative_move * axis_d; // dot product - LLVector3d cursor_point_snap_line; - - F64 off_axis_magnitude; - - getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f); - off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f; - - if (gSavedSettings.getBOOL("SnapEnabled")) - { - if (off_axis_magnitude > mSnapOffsetMeters) - { - mInSnapRegime = TRUE; - LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); - - F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; - - F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions); - F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions); - if (relative_snap_dist < snap_dist * 2.f) - { - if (cursor_grid_dist > 0.f) - { - cursor_grid_dist -= relative_snap_dist - snap_dist; - } - else - { - cursor_grid_dist += relative_snap_dist - snap_dist; - } - } - - F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f; - axis_magnitude = cursor_grid_dist - object_start_on_axis; - } - else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) - { - // subtract offset from object center - LLVector3d cursor_point_global; - getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal ); - cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal); - - // snap to planar grid - LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global); - LLVector3 camera_plane_projection = LLViewerCamera::getInstance()->getAtAxis(); - camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal); - camera_plane_projection.normVec(); - LLVector3 camera_projected_dir = camera_plane_projection; - camera_plane_projection.rotVec(~mGridRotation); - camera_plane_projection.scaleVec(mGridScale); - camera_plane_projection.abs(); - F32 max_grid_scale; - if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] && - camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ]) - { - max_grid_scale = mGridScale.mV[VX]; - } - else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ]) - { - max_grid_scale = mGridScale.mV[VY]; - } - else - { - max_grid_scale = mGridScale.mV[VZ]; - } - - F32 num_subdivisions = getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale); - - F32 grid_scale_a; - F32 grid_scale_b; - LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation; - - switch (mManipPart) - { - case LL_YZ_PLANE: - grid_scale_a = mGridScale.mV[VY] / num_subdivisions; - grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; - cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - case LL_XZ_PLANE: - grid_scale_a = mGridScale.mV[VX] / num_subdivisions; - grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; - cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - case LL_XY_PLANE: - grid_scale_a = mGridScale.mV[VX] / num_subdivisions; - grid_scale_b = mGridScale.mV[VY] / num_subdivisions; - cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; - cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; - break; - default: - break; - } - cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin; - relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal)); - mInSnapRegime = TRUE; - } - else - { - mInSnapRegime = FALSE; - } - } - else - { - mInSnapRegime = FALSE; - } - - // Clamp to arrow direction - // *FIX: does this apply anymore? - if (!axis_exists) - { - axis_magnitude = relative_move.normVec(); - axis_d.setVec(relative_move); - axis_d.normVec(); - axis_f.setVec(axis_d); - } - - LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply - LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply - + // Translation tool only works if mouse button is down. + // Bail out if mouse not down. + if( !hasMouseCapture() ) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (inactive)" << LL_ENDL; + // Always show cursor + // gViewerWindow->setCursor(UI_CURSOR_ARROW); + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + + highlightManipulators(x, y); + return TRUE; + } + + // Handle auto-rotation if necessary. + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; + const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20; + const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; + BOOL rotated = FALSE; + + // ...build mode moves camera about focus point + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { + if (x < ROTATE_H_MARGIN) + { + gAgentCamera.cameraOrbitAround(rotate_angle); + rotated = TRUE; + } + else if (x > world_rect.getWidth() - ROTATE_H_MARGIN) + { + gAgentCamera.cameraOrbitAround(-rotate_angle); + rotated = TRUE; + } + } + + // Suppress processing if mouse hasn't actually moved. + // This may cause problems if the camera moves outside of the + // rotation above. + if( x == mLastHoverMouseX && y == mLastHoverMouseY && !rotated) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse unmoved)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + mLastHoverMouseX = x; + mLastHoverMouseY = y; + + // Suppress if mouse hasn't moved past the initial slop region + // Reset once we start moving + if( !mMouseOutsideSlop ) + { + if (abs(mMouseDownX - x) < MOUSE_DRAG_SLOP && abs(mMouseDownY - y) < MOUSE_DRAG_SLOP ) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (mouse inside slop)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + else + { + // ...just went outside the slop region + mMouseOutsideSlop = TRUE; + // If holding down shift, leave behind a copy. + if (mask == MASK_COPY) + { + // ...we're trying to make a copy + LLSelectMgr::getInstance()->selectDuplicate(LLVector3::zero, FALSE); + mCopyMadeThisDrag = TRUE; + + // When we make the copy, we don't want to do any other processing. + // If so, the object will also be moved, and the copy will be offset. + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (made copy)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + } + } + } + + // Throttle updates to 10 per second. + + LLVector3 axis_f; + LLVector3d axis_d; + + // pick the first object to constrain to grid w/ common origin + // this is so we don't screw up groups + LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE); + if (!selectNode) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no selectNode" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + LLViewerObject* object = selectNode->getObject(); + if (!object) + { + // somehow we lost the object! + LL_WARNS() << "Translate manip lost the object, no object in selectNode" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; + } + + // Compute unit vectors for arrow hit and a plane through that vector + BOOL axis_exists = getManipAxis(object, mManipPart, axis_f); // TODO: move this + + axis_d.setVec(axis_f); + + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLVector3d current_pos_global = gAgent.getPosGlobalFromAgent(getPivotPoint()); + + mSubdivisions = getSubdivisionLevel(getPivotPoint(), axis_f, getMinGridScale()); + + // Project the cursor onto that plane + LLVector3d relative_move; + getMousePointOnPlaneGlobal(relative_move, x, y, current_pos_global, mManipNormal);\ + relative_move -= mDragCursorStartGlobal; + + // You can't move more than some distance from your original mousedown point. + if (gSavedSettings.getBOOL("LimitDragDistance")) + { + F32 max_drag_distance = gSavedSettings.getF32("MaxDragDistance"); + + if (relative_move.magVecSquared() > max_drag_distance * max_drag_distance) + { + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (too far)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_NOLOCKED); + return TRUE; + } + } + + F64 axis_magnitude = relative_move * axis_d; // dot product + LLVector3d cursor_point_snap_line; + + F64 off_axis_magnitude; + + getMousePointOnPlaneGlobal(cursor_point_snap_line, x, y, current_pos_global, mSnapOffsetAxis % axis_f); + off_axis_magnitude = axis_exists ? llabs((cursor_point_snap_line - current_pos_global) * LLVector3d(mSnapOffsetAxis)) : 0.f; + + if (gSavedSettings.getBOOL("SnapEnabled")) + { + if (off_axis_magnitude > mSnapOffsetMeters) + { + mInSnapRegime = TRUE; + LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); + + F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; + + F32 snap_dist = getMinGridScale() / (2.f * mSubdivisions); + F32 relative_snap_dist = fmodf(llabs(cursor_grid_dist) + snap_dist, getMinGridScale() / mSubdivisions); + if (relative_snap_dist < snap_dist * 2.f) + { + if (cursor_grid_dist > 0.f) + { + cursor_grid_dist -= relative_snap_dist - snap_dist; + } + else + { + cursor_grid_dist += relative_snap_dist - snap_dist; + } + } + + F32 object_start_on_axis = (gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal) - mGridOrigin) * axis_f; + axis_magnitude = cursor_grid_dist - object_start_on_axis; + } + else if (mManipPart >= LL_YZ_PLANE && mManipPart <= LL_XY_PLANE) + { + // subtract offset from object center + LLVector3d cursor_point_global; + getMousePointOnPlaneGlobal( cursor_point_global, x, y, current_pos_global, mManipNormal ); + cursor_point_global -= (mDragCursorStartGlobal - mDragSelectionStartGlobal); + + // snap to planar grid + LLVector3 cursor_point_agent = gAgent.getPosAgentFromGlobal(cursor_point_global); + LLVector3 camera_plane_projection = LLViewerCamera::getInstance()->getAtAxis(); + camera_plane_projection -= projected_vec(camera_plane_projection, mManipNormal); + camera_plane_projection.normVec(); + LLVector3 camera_projected_dir = camera_plane_projection; + camera_plane_projection.rotVec(~mGridRotation); + camera_plane_projection.scaleVec(mGridScale); + camera_plane_projection.abs(); + F32 max_grid_scale; + if (camera_plane_projection.mV[VX] > camera_plane_projection.mV[VY] && + camera_plane_projection.mV[VX] > camera_plane_projection.mV[VZ]) + { + max_grid_scale = mGridScale.mV[VX]; + } + else if (camera_plane_projection.mV[VY] > camera_plane_projection.mV[VZ]) + { + max_grid_scale = mGridScale.mV[VY]; + } + else + { + max_grid_scale = mGridScale.mV[VZ]; + } + + F32 num_subdivisions = getSubdivisionLevel(getPivotPoint(), camera_projected_dir, max_grid_scale); + + F32 grid_scale_a; + F32 grid_scale_b; + LLVector3 cursor_point_grid = (cursor_point_agent - mGridOrigin) * ~mGridRotation; + + switch (mManipPart) + { + case LL_YZ_PLANE: + grid_scale_a = mGridScale.mV[VY] / num_subdivisions; + grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; + cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + case LL_XZ_PLANE: + grid_scale_a = mGridScale.mV[VX] / num_subdivisions; + grid_scale_b = mGridScale.mV[VZ] / num_subdivisions; + cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VZ] -= fmod(cursor_point_grid.mV[VZ] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + case LL_XY_PLANE: + grid_scale_a = mGridScale.mV[VX] / num_subdivisions; + grid_scale_b = mGridScale.mV[VY] / num_subdivisions; + cursor_point_grid.mV[VX] -= fmod(cursor_point_grid.mV[VX] + grid_scale_a * 0.5f, grid_scale_a) - grid_scale_a * 0.5f; + cursor_point_grid.mV[VY] -= fmod(cursor_point_grid.mV[VY] + grid_scale_b * 0.5f, grid_scale_b) - grid_scale_b * 0.5f; + break; + default: + break; + } + cursor_point_agent = (cursor_point_grid * mGridRotation) + mGridOrigin; + relative_move.setVec(cursor_point_agent - gAgent.getPosAgentFromGlobal(mDragSelectionStartGlobal)); + mInSnapRegime = TRUE; + } + else + { + mInSnapRegime = FALSE; + } + } + else + { + mInSnapRegime = FALSE; + } + + // Clamp to arrow direction + // *FIX: does this apply anymore? + if (!axis_exists) + { + axis_magnitude = relative_move.normVec(); + axis_d.setVec(relative_move); + axis_d.normVec(); + axis_f.setVec(axis_d); + } + + LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply + LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply + for (LLObjectSelection::iterator iter = mObjectSelection->begin(); iter != mObjectSelection->end(); iter++) { @@ -775,1536 +775,1536 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } - LLSelectMgr::getInstance()->updateSelectionCenter(); - gAgentCamera.clearFocusObject(); - dialog_refresh_all(); // ??? is this necessary? + LLSelectMgr::getInstance()->updateSelectionCenter(); + gAgentCamera.clearFocusObject(); + dialog_refresh_all(); // ??? is this necessary? - LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (active)" << LL_ENDL; - gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); - return TRUE; + LL_DEBUGS("UserInput") << "hover handled by LLManipTranslate (active)" << LL_ENDL; + gViewerWindow->setCursor(UI_CURSOR_TOOLTRANSLATE); + return TRUE; } void LLManipTranslate::highlightManipulators(S32 x, S32 y) { - mHighlightedPart = LL_NO_PART; - - if (!mObjectSelection->getObjectCount()) - { - return; - } - - //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection(); - LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview(); - - LLVector3 object_position = getPivotPoint(); - - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - - LLVector3 relative_camera_dir; - - LLMatrix4 transform; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation; - LLVector4 translation(object_position); - transform.initRotTrans(grid_rotation, translation); - LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - transform *= cfr; - LLMatrix4 window_scale; - F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom; - window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), - LLQuaternion::DEFAULT, - LLVector3::zero); - transform *= window_scale; - } - else - { - relative_camera_dir = (object_position - LLViewerCamera::getInstance()->getOrigin()) * ~grid_rotation; - relative_camera_dir.normVec(); - - transform.initRotTrans(grid_rotation, LLVector4(object_position)); - transform *= modelView; - transform *= projMatrix; - } - - S32 numManips = 0; - - // edges - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f); - - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f); - mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f); - - S32 num_arrow_manips = numManips; - - // planar manipulators - BOOL planar_manip_yz_visible = FALSE; - BOOL planar_manip_xz_visible = FALSE; - BOOL planar_manip_xy_visible = FALSE; - - mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_yz_visible = TRUE; - } - - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_xz_visible = TRUE; - } - - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); - mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); - if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - planar_manip_xy_visible = TRUE; - } - - // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes - std::vector projected_manipulators; - projected_manipulators.reserve(9); - - for (S32 i = 0; i < num_arrow_manips; i+= 2) - { - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 10.f); // 10 pixel hotspot for arrows - projected_manipulators.push_back(projected_manip); - } - - if (planar_manip_yz_visible) - { - S32 i = num_arrow_manips; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); - } - - if (planar_manip_xz_visible) - { - S32 i = num_arrow_manips + 2; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); - } - - if (planar_manip_xy_visible) - { - S32 i = num_arrow_manips + 4; - LLVector4 projected_start = mManipulatorVertices[i] * transform; - projected_start = projected_start * (1.f / projected_start.mV[VW]); - - LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; - projected_end = projected_end * (1.f / projected_end.mV[VW]); - - ManipulatorHandle projected_manip( - LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), - LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), - MANIPULATOR_IDS[i / 2], - 20.f); // 20 pixels for planar manipulators - projected_manipulators.push_back(projected_manip); - } - - LLVector2 manip_start_2d; - LLVector2 manip_end_2d; - LLVector2 manip_dir; - LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); - F32 half_width = (F32)world_view_rect.getWidth() / 2.f; - F32 half_height = (F32)world_view_rect.getHeight() / 2.f; - LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); - LLVector2 mouse_delta; - - // Keep order consistent with insertion via stable_sort - std::stable_sort( projected_manipulators.begin(), - projected_manipulators.end(), - ClosestToCamera() ); - - std::vector::iterator it = projected_manipulators.begin(); - for ( ; it != projected_manipulators.end(); ++it) - { - ManipulatorHandle& manipulator = *it; - { - manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); - manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); - manip_dir = manip_end_2d - manip_start_2d; - - mouse_delta = mousePos - manip_start_2d; - - F32 manip_length = manip_dir.normVec(); - - F32 mouse_pos_manip = mouse_delta * manip_dir; - F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip); - - if (mouse_pos_manip > 0.f && - mouse_pos_manip < manip_length && - mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) - { - mHighlightedPart = manipulator.mManipID; - break; - } - } - } -} + mHighlightedPart = LL_NO_PART; -F32 LLManipTranslate::getMinGridScale() -{ - F32 scale; - switch (mManipPart) - { - case LL_NO_PART: - default: - scale = 1.f; - break; - case LL_X_ARROW: - scale = mGridScale.mV[VX]; - break; - case LL_Y_ARROW: - scale = mGridScale.mV[VY]; - break; - case LL_Z_ARROW: - scale = mGridScale.mV[VZ]; - break; - case LL_YZ_PLANE: - scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]); - break; - case LL_XZ_PLANE: - scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]); - break; - case LL_XY_PLANE: - scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]); - break; - } - - return scale; -} + if (!mObjectSelection->getObjectCount()) + { + return; + } + //LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + LLMatrix4 projMatrix = LLViewerCamera::getInstance()->getProjection(); + LLMatrix4 modelView = LLViewerCamera::getInstance()->getModelview(); -BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask) -{ - // first, perform normal processing in case this was a quick-click - handleHover(x, y, mask); - - if(hasMouseCapture()) - { - // make sure arrow colors go back to normal - mManipPart = LL_NO_PART; - LLSelectMgr::getInstance()->enableSilhouette(TRUE); - - // Might have missed last update due to UPDATE_DELAY timing. - LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_POSITION ); - - mInSnapRegime = FALSE; - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); - } - - return LLManip::handleMouseUp(x, y, mask); -} + LLVector3 object_position = getPivotPoint(); + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; -void LLManipTranslate::render() -{ - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom, zoom, zoom); - } - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderGuidelines(); - } - { - //LLGLDisable gls_stencil(GL_STENCIL_TEST); - renderTranslationHandles(); - renderSnapGuides(); - } - gGL.popMatrix(); - - renderText(); -} + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); -void LLManipTranslate::renderSnapGuides() -{ - if (!gSavedSettings.getBOOL("SnapEnabled")) - { - return; - } - - F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision"); - F32 line_alpha = gSavedSettings.getF32("GridOpacity"); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(GL_TRUE); - LLGLDisable gls_cull(GL_CULL_FACE); - LLVector3 translate_axis; - - if (mManipPart == LL_NO_PART) - { - return; - } - - LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE); - if (!first_node) - { - return; - } - - updateGridSettings(); - - F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions; - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - LLVector3 saved_selection_center = getSavedPivotPoint(); //LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); - LLVector3 selection_center = getPivotPoint(); - - LLViewerObject *first_object = first_node->getObject(); - - //pick appropriate projection plane for snap rulers according to relative camera position - if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW) - { - LLVector3 normal; - LLColor4 inner_color; - LLManip::EManipPart temp_manip = mManipPart; - switch (mManipPart) - { - case LL_X_ARROW: - normal.setVec(1,0,0); - inner_color.setVec(0,1,1,line_alpha); - mManipPart = LL_YZ_PLANE; - break; - case LL_Y_ARROW: - normal.setVec(0,1,0); - inner_color.setVec(1,0,1,line_alpha); - mManipPart = LL_XZ_PLANE; - break; - case LL_Z_ARROW: - normal.setVec(0,0,1); - inner_color.setVec(1,1,0,line_alpha); - mManipPart = LL_XY_PLANE; - break; - default: - break; - } - - highlightIntersection(normal, selection_center, grid_rotation, inner_color); - mManipPart = temp_manip; - getManipAxis(first_object, mManipPart, translate_axis); - - LLVector3 at_axis_abs; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - at_axis_abs = LLVector3::x_axis * ~grid_rotation; - } - else - { - at_axis_abs = saved_selection_center - LLViewerCamera::getInstance()->getOrigin(); - at_axis_abs.normVec(); - - at_axis_abs = at_axis_abs * ~grid_rotation; - } - at_axis_abs.abs(); - - if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) - { - if (mManipPart == LL_Y_ARROW) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else if (mManipPart == LL_Z_ARROW) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else - { - mSnapOffsetAxis = LLVector3::y_axis; - } - } - else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) - { - if (mManipPart == LL_X_ARROW) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else if (mManipPart == LL_Z_ARROW) - { - mSnapOffsetAxis = LLVector3::x_axis; - } - else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) - { - mSnapOffsetAxis = LLVector3::z_axis; - } - else - { - mSnapOffsetAxis = LLVector3::x_axis; - } - } - else - { - if (mManipPart == LL_X_ARROW) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else if (mManipPart == LL_Y_ARROW) - { - mSnapOffsetAxis = LLVector3::x_axis; - } - else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY]) - { - mSnapOffsetAxis = LLVector3::y_axis; - } - else - { - mSnapOffsetAxis = LLVector3::x_axis; - } - } - - mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation; - - F32 guide_size_meters; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - guide_size_meters = 1.f / gAgentCamera.mHUDCurZoom; - mSnapOffsetMeters = mArrowLengthMeters * 1.5f; - } - else - { - LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin(); - F32 current_range = cam_to_selection.normVec(); - guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); - - F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - F32 offset_at_camera = tan(apparent_angle) * 1.5f; - F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), LLViewerCamera::getInstance()->getOrigin()); - mSnapOffsetMeters = range * offset_at_camera; - } - - LLVector3 tick_start; - LLVector3 tick_end; - - // how far away from grid origin is the selection along the axis of translation? - F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis; - // find distance to nearest smallest grid unit - F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale); - // how many smallest grid units are we away from largest grid scale? - S32 sub_div_offset = ll_round(fmodf(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale); - S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale)); - - LLGLDepthTest gls_depth(GL_FALSE); - - for (S32 pass = 0; pass < 3; pass++) - { - LLColor4 line_color = setupSnapGuideRenderPass(pass); - LLGLDepthTest gls_depth(pass != 1); - - gGL.begin(LLRender::LINES); - { - LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); - LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); - LLVector3 line_mid = (line_start + line_end) * 0.5f; - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_start.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(line_mid.mV); - gGL.vertex3fv(line_mid.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_end.mV); - - line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f)); - line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f)); - line_mid = (line_start + line_end) * 0.5f; - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_start.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(line_mid.mV); - gGL.vertex3fv(line_mid.mV); - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); - gGL.vertex3fv(line_end.mV); - - for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) - { - tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); - - //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) - //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); - /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) - { - continue; - }*/ - - // add in off-axis offset - tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); - - F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) - { - if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) - { - break; - } - tick_scale *= 0.7f; - } - -// S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side; -// F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade))); - - tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); - - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - gGL.vertex3fv(tick_start.mV); - gGL.vertex3fv(tick_end.mV); - - tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + - (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit)); - tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); - - gGL.vertex3fv(tick_start.mV); - gGL.vertex3fv(tick_end.mV); - } - } - gGL.end(); - - if (mInSnapRegime) - { - LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters; - LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters; - - gGL.begin(LLRender::LINES); - { - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - - gGL.vertex3fv(line_start.mV); - gGL.vertex3fv(line_end.mV); - } - gGL.end(); - - // draw snap guide arrow - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); - - LLVector3 arrow_dir; - LLVector3 arrow_span = translate_axis; - - arrow_dir = -mSnapOffsetAxis; - gGL.vertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - - arrow_dir = mSnapOffsetAxis; - gGL.vertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - gGL.vertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); - } - gGL.end(); - } - } - - sub_div_offset = ll_round(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale); - - LLVector2 screen_translate_axis(llabs(translate_axis * LLViewerCamera::getInstance()->getLeftAxis()), llabs(translate_axis * LLViewerCamera::getInstance()->getUpAxis())); - screen_translate_axis.normVec(); - - S32 tick_label_spacing = ll_round(screen_translate_axis * sTickLabelSpacing); - - // render tickmark values - for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) - { - LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)); - F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side))); - - F32 tick_scale = 1.f; - for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) - { - if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) - { - break; - } - tick_scale *= 0.7f; - } - - if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing))) == 0.f) - { - F32 snap_offset_meters; - - if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) - { - snap_offset_meters = mSnapOffsetMeters; - } - else - { - snap_offset_meters = -mSnapOffsetMeters; - } - LLVector3 text_origin = selection_center + - (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) + - (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale)); - - LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation; - F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale(); - EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); - F32 text_highlight = 0.8f; - if(i - ll_round(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime) - { - text_highlight = 1.f; - } - - if (grid_mode == GRID_MODE_WORLD) - { - // rescale units to meters from multiple of grid scale - offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]]; - renderTickValue(text_origin, offset_val, std::string("m"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); - } - else - { - renderTickValue(text_origin, offset_val, std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); - } - } - } - if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) - { - // render helpful text - if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) - { - F32 snap_offset_meters_up; - if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) - { - snap_offset_meters_up = mSnapOffsetMeters; - } - else - { - snap_offset_meters_up = -mSnapOffsetMeters; - } - - LLVector3 selection_center_start = getSavedPivotPoint();//LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); - - LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis); - const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); - - std::string help_text = LLTrans::getString("manip_hint1"); - LLColor4 help_text_color = LLColor4::white; - help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f); - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); - help_text = LLTrans::getString("manip_hint2"); - help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f; - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); - } - } - } - else - { - // render gridlines for planar snapping - - F32 u = 0, v = 0; - LLColor4 inner_color; - LLVector3 normal; - LLVector3 grid_center = selection_center - grid_origin; - F32 usc = 1; - F32 vsc = 1; - - grid_center *= ~grid_rotation; - - switch (mManipPart) - { - case LL_YZ_PLANE: - u = grid_center.mV[VY]; - v = grid_center.mV[VZ]; - usc = grid_scale.mV[VY]; - vsc = grid_scale.mV[VZ]; - inner_color.setVec(0,1,1,line_alpha); - normal.setVec(1,0,0); - break; - case LL_XZ_PLANE: - u = grid_center.mV[VX]; - v = grid_center.mV[VZ]; - usc = grid_scale.mV[VX]; - vsc = grid_scale.mV[VZ]; - inner_color.setVec(1,0,1,line_alpha); - normal.setVec(0,1,0); - break; - case LL_XY_PLANE: - u = grid_center.mV[VX]; - v = grid_center.mV[VY]; - usc = grid_scale.mV[VX]; - vsc = grid_scale.mV[VY]; - inner_color.setVec(1,1,0,line_alpha); - normal.setVec(0,0,1); - break; - default: - break; - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - highlightIntersection(normal, selection_center, grid_rotation, inner_color); - - gGL.pushMatrix(); - - F32 x,y,z,angle_radians; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - F32 sz = mGridSizeMeters; - F32 tiles = sz; - - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.pushMatrix(); - usc = 1.0f/usc; - vsc = 1.0f/vsc; - - while (usc > vsc*4.0f) - { - usc *= 0.5f; - } - while (vsc > usc * 4.0f) - { - vsc *= 0.5f; - } - - gGL.scalef(usc, vsc, 1.0f); - gGL.translatef(u, v, 0); - - float a = line_alpha; - - { - //draw grid behind objects - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - { - //LLGLDisable stencil(GL_STENCIL_TEST); - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); - gGL.flush(); - gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f); - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } - - { - //draw black overlay - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); - - //draw grid top - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); - renderGrid(u,v,tiles,1,1,1,a); - - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - } - - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderGuidelines(); - } - - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.flush(); - - switch (mManipPart) - { - case LL_YZ_PLANE: - renderGuidelines(FALSE, TRUE, TRUE); - break; - case LL_XZ_PLANE: - renderGuidelines(TRUE, FALSE, TRUE); - break; - case LL_XY_PLANE: - renderGuidelines(TRUE, TRUE, FALSE); - break; - default: - break; - } - gGL.flush(); - } - } - } - } -} + LLVector3 relative_camera_dir; -void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a) -{ - F32 d = size*0.5f; - - for (F32 xx = -size-d; xx < size+d; xx += d) - { - gGL.begin(LLRender::TRIANGLE_STRIP); - for (F32 yy = -size-d; yy < size+d; yy += d) - { - float dx, dy, da; - - dx = xx; dy = yy; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx+d; dy = yy; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx; dy = yy+d; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - - dx = xx+d; dy = yy+d; - da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; - gGL.texCoord2f(dx, dy); - renderGridVert(dx,dy,r,g,b,da); - } - gGL.end(); - } - - -} + LLMatrix4 transform; -void LLManipTranslate::highlightIntersection(LLVector3 normal, - LLVector3 selection_center, - LLQuaternion grid_rotation, - LLColor4 inner_color) -{ -#if 0 // DEPRECATED - if (!gSavedSettings.getBOOL("GridCrossSections")) - { - return; - } - - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - - static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; - static const U32 num_types = LL_ARRAY_SIZE(types); - - GLuint stencil_mask = 0xFFFFFFFF; - //stencil in volumes - - gGL.flush(); - - if (shader) - { - gClipProgram.bind(); - } - - { - //glStencilMask(stencil_mask); //deprecated - //glClearStencil(1); - //glClear(GL_STENCIL_BUFFER_BIT); - LLGLEnable cull_face(GL_CULL_FACE); - //LLGLEnable stencil(GL_STENCIL_TEST); - LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); - //glStencilFunc(GL_ALWAYS, 0, stencil_mask); - gGL.setColorMask(false, false); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.diffuseColor4f(1,1,1,1); - - //setup clip plane - normal = normal * grid_rotation; - if (normal * (LLViewerCamera::getInstance()->getOrigin()-selection_center) < 0) - { - normal = -normal; - } - F32 d = -(selection_center * normal); - glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); - - gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); - - static LLStaticHashedString sClipPlane("clip_plane"); - gClipProgram.uniform4fv(sClipPlane, 1, plane.v); - - BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - - if (particles) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } - if (clouds) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - } - - //stencil in volumes - //glStencilOp(GL_INCR, GL_INCR, GL_INCR); - glCullFace(GL_FRONT); - for (U32 i = 0; i < num_types; i++) - { - gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - - //glStencilOp(GL_DECR, GL_DECR, GL_DECR); - glCullFace(GL_BACK); - for (U32 i = 0; i < num_types; i++) - { - gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - - if (particles) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } - if (clouds) - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - } - - gGL.setColorMask(true, false); - } - gGL.color4f(1,1,1,1); - - gGL.pushMatrix(); - - F32 x,y,z,angle_radians; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - F32 sz = mGridSizeMeters; - F32 tiles = sz; - - if (shader) - { - shader->bind(); - } - - if (shader) - { - shader->bind(); - } - - //draw volume/plane intersections - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_FALSE); - //LLGLEnable stencil(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc(GL_EQUAL, 0, stencil_mask); - renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); - } - - glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); - glStencilMask(0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - gGL.popMatrix(); -#endif -} + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation; + LLVector4 translation(object_position); + transform.initRotTrans(grid_rotation, translation); + LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + transform *= cfr; + LLMatrix4 window_scale; + F32 zoom_level = 2.f * gAgentCamera.mHUDCurZoom; + window_scale.initAll(LLVector3(zoom_level / LLViewerCamera::getInstance()->getAspect(), zoom_level, 0.f), + LLQuaternion::DEFAULT, + LLVector3::zero); + transform *= window_scale; + } + else + { + relative_camera_dir = (object_position - LLViewerCamera::getInstance()->getOrigin()) * ~grid_rotation; + relative_camera_dir.normVec(); -void LLManipTranslate::renderText() -{ - if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment()) - { - LLVector3 pos = getPivotPoint(); - renderXYZ(pos); - } - else - { - const BOOL children_ok = TRUE; - LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok); - if (objectp) - { - renderXYZ(objectp->getPositionEdit()); - } - } -} + transform.initRotTrans(grid_rotation, LLVector4(object_position)); + transform *= modelView; + transform *= projMatrix; + } -void LLManipTranslate::renderTranslationHandles() -{ - LLVector3 grid_origin; - LLVector3 grid_scale; - LLQuaternion grid_rotation; - LLGLDepthTest gls_depth(GL_FALSE); - - LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); - LLVector3 at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - at_axis = LLVector3::x_axis * ~grid_rotation; - } - else - { - at_axis = LLViewerCamera::getInstance()->getAtAxis() * ~grid_rotation; - } - - if (at_axis.mV[VX] > 0.f) - { - mPlaneManipPositions.mV[VX] = 1.f; - } - else - { - mPlaneManipPositions.mV[VX] = -1.f; - } - - if (at_axis.mV[VY] > 0.f) - { - mPlaneManipPositions.mV[VY] = 1.f; - } - else - { - mPlaneManipPositions.mV[VY] = -1.f; - } - - if (at_axis.mV[VZ] > 0.f) - { - mPlaneManipPositions.mV[VZ] = 1.f; - } - else - { - mPlaneManipPositions.mV[VZ] = -1.f; - } - - LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); - if (!first_object) return; - - LLVector3 selection_center = getPivotPoint(); - - // Drag handles - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw(); - mArrowLengthMeters /= gAgentCamera.mHUDCurZoom; - } - else - { - LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); - F32 range = dist_vec(camera_pos_agent, selection_center); - F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center); - - // Don't draw handles if you're too far away - if (gSavedSettings.getBOOL("LimitSelectDistance")) - { - if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance")) - { - return; - } - } - - if (range > 0.001f) - { - // range != zero - F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - mArrowLengthMeters = range * tan(apparent_angle); - } - else - { - // range == zero - mArrowLengthMeters = 1.0f; - } - } - //Assume that UI scale factor is equivalent for X and Y axis - F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; - mArrowLengthMeters *= ui_scale_factor; - - mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f; - mGridSizeMeters = gSavedSettings.getF32("GridDrawSize"); - mConeSize = mArrowLengthMeters / 4.f; - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - { - gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - - F32 angle_radians, x, y, z; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - - gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); - - LLQuaternion invRotation = grid_rotation; - invRotation.conjQuat(); - - LLVector3 relative_camera_dir; - - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - relative_camera_dir = LLVector3::x_axis * invRotation; - } - else - { - relative_camera_dir = (selection_center - LLViewerCamera::getInstance()->getOrigin()) * invRotation; - } - relative_camera_dir.normVec(); - - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDisable cull_face(GL_CULL_FACE); - - LLColor4 color1; - LLColor4 color2; - - // update manipulator sizes - for (S32 index = 0; index < 3; index++) - { - if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - else - { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - } - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render YZ plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - gGL.translatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters); - gGL.scalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]); - if (mHighlightedPart == LL_YZ_PLANE) - { - color1.setVec(0.f, 1.f, 0.f, 1.f); - color2.setVec(0.f, 0.f, 1.f, 1.f); - } - else - { - color1.setVec(0.f, 1.f, 0.f, 0.6f); - color2.setVec(0.f, 0.f, 1.f, 0.6f); - } - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - - gGL.color4fv(color2.mV); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); - - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - gGL.popMatrix(); - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render XZ plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - gGL.translatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters); - gGL.scalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]); - if (mHighlightedPart == LL_XZ_PLANE) - { - color1.setVec(0.f, 0.f, 1.f, 1.f); - color2.setVec(1.f, 0.f, 0.f, 1.f); - } - else - { - color1.setVec(0.f, 0.f, 1.f, 0.6f); - color2.setVec(1.f, 0.f, 0.f, 0.6f); - } - - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - - gGL.color4fv(color2.mV); - gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); - gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); - - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); - gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - - gGL.popMatrix(); - } - - if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) - { - // render XY plane manipulator - gGL.pushMatrix(); - gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); - -/* Y - ^ - v1 - | \ - |<- v0 - | /| \ - v2__v__v3 > X -*/ - LLVector3 v0,v1,v2,v3; -#if 0 - // This should theoretically work but looks off; could be tuned later -SJB - gGL.translatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f); - v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); - v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f); - v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); - v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); -#else - gGL.translatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f); - v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); - v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f); - v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); - v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); -#endif - gGL.scalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]); - if (mHighlightedPart == LL_XY_PLANE) - { - color1.setVec(1.f, 0.f, 0.f, 1.f); - color2.setVec(0.f, 1.f, 0.f, 1.f); - } - else - { - color1.setVec(0.8f, 0.f, 0.f, 0.6f); - color2.setVec(0.f, 0.8f, 0.f, 0.6f); - } - - gGL.begin(LLRender::TRIANGLES); - { - gGL.color4fv(color1.mV); - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v1.mV); - gGL.vertex3fv(v2.mV); - - gGL.color4fv(color2.mV); - gGL.vertex3fv(v2.mV); - gGL.vertex3fv(v3.mV); - gGL.vertex3fv(v0.mV); - } - gGL.end(); - - LLUI::setLineWidth(3.0f); - gGL.begin(LLRender::LINES); - { - gGL.color4f(0.f, 0.f, 0.f, 0.3f); - LLVector3 v12 = (v1 + v2) * .5f; - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV); - gGL.vertex3fv(v12.mV); - gGL.vertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV); - - LLVector3 v23 = (v2 + v3) * .5f; - gGL.vertex3fv(v0.mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV); - gGL.vertex3fv(v23.mV); - gGL.vertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV); - } - gGL.end(); - LLUI::setLineWidth(1.0f); - - gGL.popMatrix(); - } - } - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Since we draw handles with depth testing off, we need to draw them in the - // proper depth order. - - // Copied from LLDrawable::updateGeometry - LLVector3 pos_agent = first_object->getPositionAgent(); - LLVector3 camera_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 headPos = pos_agent - camera_agent; - - LLVector3 orientWRTHead = headPos * invRotation; - - // Find nearest vertex - U32 nearest = (orientWRTHead.mV[0] < 0.0f ? 1 : 0) + - (orientWRTHead.mV[1] < 0.0f ? 2 : 0) + - (orientWRTHead.mV[2] < 0.0f ? 4 : 0); - - // opposite faces on Linden cubes: - // 0 & 5 - // 1 & 3 - // 2 & 4 - - // Table of order to draw faces, based on nearest vertex - static U32 face_list[8][NUM_AXES*2] = { - { 2,0,1, 4,5,3 }, // v6 F201 F453 - { 2,0,3, 4,5,1 }, // v7 F203 F451 - { 4,0,1, 2,5,3 }, // v5 F401 F253 - { 4,0,3, 2,5,1 }, // v4 F403 F251 - { 2,5,1, 4,0,3 }, // v2 F251 F403 - { 2,5,3, 4,0,1 }, // v3 F253 F401 - { 4,5,1, 2,0,3 }, // v1 F451 F203 - { 4,5,3, 2,0,1 }, // v0 F453 F201 - }; - static const EManipPart which_arrow[6] = { - LL_Z_ARROW, - LL_X_ARROW, - LL_Y_ARROW, - LL_X_ARROW, - LL_Y_ARROW, - LL_Z_ARROW}; - - // draw arrows for deeper faces first, closer faces last - LLVector3 camera_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - camera_axis = LLVector3::x_axis; - } - else - { - camera_axis.setVec(gAgentCamera.getCameraPositionAgent() - first_object->getPositionAgent()); - } - - for (U32 i = 0; i < NUM_AXES*2; i++) - { - U32 face = face_list[nearest][i]; - - LLVector3 arrow_axis; - getManipAxis(first_object, which_arrow[face], arrow_axis); - - renderArrow(which_arrow[face], - mManipPart, - (face >= 3) ? -mConeSize : mConeSize, - (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters, - mConeSize, - FALSE); - } - } - } - gGL.popMatrix(); -} + S32 numManips = 0; + // edges + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); -void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction) -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable gls_blend(GL_BLEND); - - for (S32 pass = 1; pass <= 2; pass++) - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER); - gGL.pushMatrix(); - - S32 index = 0; - - index = ARROW_TO_AXIS[which_arrow]; - - // assign a color for this arrow - LLColor4 color; // black - if (which_arrow == selected_arrow || which_arrow == mHighlightedPart) - { - color.mV[index] = (pass == 1) ? 1.f : 0.5f; - } - else if (selected_arrow != LL_NO_PART) - { - color.mV[VALPHA] = 0.f; - } - else - { - color.mV[index] = pass == 1 ? .8f : .35f ; // red, green, or blue - color.mV[VALPHA] = 0.6f; - } - gGL.color4fv( color.mV ); - - LLVector3 vec; - - { - LLUI::setLineWidth(2.0f); - gGL.begin(LLRender::LINES); - vec.mV[index] = box_size; - gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); - - vec.mV[index] = arrow_size; - gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); - gGL.end(); - LLUI::setLineWidth(1.0f); - } - - gGL.translatef(vec.mV[0], vec.mV[1], vec.mV[2]); - gGL.scalef(handle_size, handle_size, handle_size); - - F32 rot = 0.0f; - LLVector3 axis; - - switch(which_arrow) - { - case LL_X_ARROW: - rot = reverse_direction ? -90.0f : 90.0f; - axis.mV[1] = 1.0f; - break; - case LL_Y_ARROW: - rot = reverse_direction ? 90.0f : -90.0f; - axis.mV[0] = 1.0f; - break; - case LL_Z_ARROW: - rot = reverse_direction ? 180.0f : 0.0f; - axis.mV[0] = 1.0f; - break; - default: - LL_ERRS() << "renderArrow called with bad arrow " << which_arrow << LL_ENDL; - break; - } - - gGL.diffuseColor4fv(color.mV); - gGL.rotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]); - gGL.scalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f); - - gCone.render(); - - gGL.popMatrix(); - } -} + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 0.f, 1.f); -void LLManipTranslate::renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha) -{ - gGL.color4f(r, g, b, alpha); - switch (mManipPart) - { - case LL_YZ_PLANE: - gGL.vertex3f(0, x_trans, y_trans); - break; - case LL_XZ_PLANE: - gGL.vertex3f(x_trans, 0, y_trans); - break; - case LL_XY_PLANE: - gGL.vertex3f(x_trans, y_trans, 0); - break; - default: - gGL.vertex3f(0,0,0); - break; - } + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_START, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * MANIPULATOR_HOTSPOT_END, 1.f); -} + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 0.f, 1.f); -// virtual -BOOL LLManipTranslate::canAffectSelection() -{ - BOOL can_move = mObjectSelection->getObjectCount() != 0; - if (can_move) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* objectp) - { - LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); - return objectp->permMove() && !objectp->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); - } - } func; - can_move = mObjectSelection->applyToObjects(&func); - } - return can_move; + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 0.f, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 0.f, 1.f); + + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_START, 1.f); + mManipulatorVertices[numManips++] = LLVector4(0.f, 0.f, mArrowLengthMeters * -MANIPULATOR_HOTSPOT_END, 1.f); + + S32 num_arrow_manips = numManips; + + // planar manipulators + BOOL planar_manip_yz_visible = FALSE; + BOOL planar_manip_xz_visible = FALSE; + BOOL planar_manip_xy_visible = FALSE; + + mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_yz_visible = TRUE; + } + + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_xz_visible = TRUE; + } + + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f - PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + mManipulatorVertices[numManips] = LLVector4(mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), mPlaneManipOffsetMeters * (1.f + PLANE_TICK_SIZE * 0.5f), 0.f, 1.f); + mManipulatorVertices[numManips++].scaleVec(mPlaneManipPositions); + if (llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + planar_manip_xy_visible = TRUE; + } + + // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes + std::vector projected_manipulators; + projected_manipulators.reserve(9); + + for (S32 i = 0; i < num_arrow_manips; i+= 2) + { + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 10.f); // 10 pixel hotspot for arrows + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_yz_visible) + { + S32 i = num_arrow_manips; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_xz_visible) + { + S32 i = num_arrow_manips + 2; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + if (planar_manip_xy_visible) + { + S32 i = num_arrow_manips + 4; + LLVector4 projected_start = mManipulatorVertices[i] * transform; + projected_start = projected_start * (1.f / projected_start.mV[VW]); + + LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; + projected_end = projected_end * (1.f / projected_end.mV[VW]); + + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), + MANIPULATOR_IDS[i / 2], + 20.f); // 20 pixels for planar manipulators + projected_manipulators.push_back(projected_manip); + } + + LLVector2 manip_start_2d; + LLVector2 manip_end_2d; + LLVector2 manip_dir; + LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); + F32 half_width = (F32)world_view_rect.getWidth() / 2.f; + F32 half_height = (F32)world_view_rect.getHeight() / 2.f; + LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); + LLVector2 mouse_delta; + + // Keep order consistent with insertion via stable_sort + std::stable_sort( projected_manipulators.begin(), + projected_manipulators.end(), + ClosestToCamera() ); + + std::vector::iterator it = projected_manipulators.begin(); + for ( ; it != projected_manipulators.end(); ++it) + { + ManipulatorHandle& manipulator = *it; + { + manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); + manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); + manip_dir = manip_end_2d - manip_start_2d; + + mouse_delta = mousePos - manip_start_2d; + + F32 manip_length = manip_dir.normVec(); + + F32 mouse_pos_manip = mouse_delta * manip_dir; + F32 mouse_dist_manip_squared = mouse_delta.magVecSquared() - (mouse_pos_manip * mouse_pos_manip); + + if (mouse_pos_manip > 0.f && + mouse_pos_manip < manip_length && + mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) + { + mHighlightedPart = manipulator.mManipID; + break; + } + } + } +} + +F32 LLManipTranslate::getMinGridScale() +{ + F32 scale; + switch (mManipPart) + { + case LL_NO_PART: + default: + scale = 1.f; + break; + case LL_X_ARROW: + scale = mGridScale.mV[VX]; + break; + case LL_Y_ARROW: + scale = mGridScale.mV[VY]; + break; + case LL_Z_ARROW: + scale = mGridScale.mV[VZ]; + break; + case LL_YZ_PLANE: + scale = llmin(mGridScale.mV[VY], mGridScale.mV[VZ]); + break; + case LL_XZ_PLANE: + scale = llmin(mGridScale.mV[VX], mGridScale.mV[VZ]); + break; + case LL_XY_PLANE: + scale = llmin(mGridScale.mV[VX], mGridScale.mV[VY]); + break; + } + + return scale; +} + + +BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask) +{ + // first, perform normal processing in case this was a quick-click + handleHover(x, y, mask); + + if(hasMouseCapture()) + { + // make sure arrow colors go back to normal + mManipPart = LL_NO_PART; + LLSelectMgr::getInstance()->enableSilhouette(TRUE); + + // Might have missed last update due to UPDATE_DELAY timing. + LLSelectMgr::getInstance()->sendMultipleUpdate( UPD_POSITION ); + + mInSnapRegime = FALSE; + LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); + } + + return LLManip::handleMouseUp(x, y, mask); +} + + +void LLManipTranslate::render() +{ + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom, zoom, zoom); + } + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + renderGuidelines(); + } + { + //LLGLDisable gls_stencil(GL_STENCIL_TEST); + renderTranslationHandles(); + renderSnapGuides(); + } + gGL.popMatrix(); + + renderText(); +} + +void LLManipTranslate::renderSnapGuides() +{ + if (!gSavedSettings.getBOOL("SnapEnabled")) + { + return; + } + + F32 max_subdivisions = sGridMaxSubdivisionLevel;//(F32)gSavedSettings.getS32("GridSubdivision"); + F32 line_alpha = gSavedSettings.getF32("GridOpacity"); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest gls_depth(GL_TRUE); + LLGLDisable gls_cull(GL_CULL_FACE); + LLVector3 translate_axis; + + if (mManipPart == LL_NO_PART) + { + return; + } + + LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE); + if (!first_node) + { + return; + } + + updateGridSettings(); + + F32 smallest_grid_unit_scale = getMinGridScale() / max_subdivisions; + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + LLVector3 saved_selection_center = getSavedPivotPoint(); //LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + LLVector3 selection_center = getPivotPoint(); + + LLViewerObject *first_object = first_node->getObject(); + + //pick appropriate projection plane for snap rulers according to relative camera position + if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW) + { + LLVector3 normal; + LLColor4 inner_color; + LLManip::EManipPart temp_manip = mManipPart; + switch (mManipPart) + { + case LL_X_ARROW: + normal.setVec(1,0,0); + inner_color.setVec(0,1,1,line_alpha); + mManipPart = LL_YZ_PLANE; + break; + case LL_Y_ARROW: + normal.setVec(0,1,0); + inner_color.setVec(1,0,1,line_alpha); + mManipPart = LL_XZ_PLANE; + break; + case LL_Z_ARROW: + normal.setVec(0,0,1); + inner_color.setVec(1,1,0,line_alpha); + mManipPart = LL_XY_PLANE; + break; + default: + break; + } + + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + mManipPart = temp_manip; + getManipAxis(first_object, mManipPart, translate_axis); + + LLVector3 at_axis_abs; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + at_axis_abs = LLVector3::x_axis * ~grid_rotation; + } + else + { + at_axis_abs = saved_selection_center - LLViewerCamera::getInstance()->getOrigin(); + at_axis_abs.normVec(); + + at_axis_abs = at_axis_abs * ~grid_rotation; + } + at_axis_abs.abs(); + + if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY] && at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) + { + if (mManipPart == LL_Y_ARROW) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else if (mManipPart == LL_Z_ARROW) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else + { + mSnapOffsetAxis = LLVector3::y_axis; + } + } + else if (at_axis_abs.mV[VY] > at_axis_abs.mV[VZ]) + { + if (mManipPart == LL_X_ARROW) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else if (mManipPart == LL_Z_ARROW) + { + mSnapOffsetAxis = LLVector3::x_axis; + } + else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VZ]) + { + mSnapOffsetAxis = LLVector3::z_axis; + } + else + { + mSnapOffsetAxis = LLVector3::x_axis; + } + } + else + { + if (mManipPart == LL_X_ARROW) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else if (mManipPart == LL_Y_ARROW) + { + mSnapOffsetAxis = LLVector3::x_axis; + } + else if (at_axis_abs.mV[VX] > at_axis_abs.mV[VY]) + { + mSnapOffsetAxis = LLVector3::y_axis; + } + else + { + mSnapOffsetAxis = LLVector3::x_axis; + } + } + + mSnapOffsetAxis = mSnapOffsetAxis * grid_rotation; + + F32 guide_size_meters; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + guide_size_meters = 1.f / gAgentCamera.mHUDCurZoom; + mSnapOffsetMeters = mArrowLengthMeters * 1.5f; + } + else + { + LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin(); + F32 current_range = cam_to_selection.normVec(); + guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); + + F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + F32 offset_at_camera = tan(apparent_angle) * 1.5f; + F32 range = dist_vec(gAgent.getPosAgentFromGlobal(first_node->mSavedPositionGlobal), LLViewerCamera::getInstance()->getOrigin()); + mSnapOffsetMeters = range * offset_at_camera; + } + + LLVector3 tick_start; + LLVector3 tick_end; + + // how far away from grid origin is the selection along the axis of translation? + F32 dist_grid_axis = (selection_center - mGridOrigin) * translate_axis; + // find distance to nearest smallest grid unit + F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale); + // how many smallest grid units are we away from largest grid scale? + S32 sub_div_offset = ll_round(fmodf(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale); + S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale)); + + LLGLDepthTest gls_depth(GL_FALSE); + + for (S32 pass = 0; pass < 3; pass++) + { + LLColor4 line_color = setupSnapGuideRenderPass(pass); + LLGLDepthTest gls_depth(pass != 1); + + gGL.begin(LLRender::LINES); + { + LLVector3 line_start = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) + (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); + LLVector3 line_end = selection_center + (mSnapOffsetMeters * mSnapOffsetAxis) - (translate_axis * (guide_size_meters * 0.5f + offset_nearest_grid_unit)); + LLVector3 line_mid = (line_start + line_end) * 0.5f; + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_start.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(line_mid.mV); + gGL.vertex3fv(line_mid.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_end.mV); + + line_start.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + (translate_axis * guide_size_meters * 0.5f)); + line_end.setVec(selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) - (translate_axis * guide_size_meters * 0.5f)); + line_mid = (line_start + line_end) * 0.5f; + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_start.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(line_mid.mV); + gGL.vertex3fv(line_mid.mV); + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW] * 0.2f); + gGL.vertex3fv(line_end.mV); + + for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) + { + tick_start = selection_center + (translate_axis * (smallest_grid_unit_scale * (F32)i - offset_nearest_grid_unit)); + + //No need check this condition to prevent tick position scaling (FIX MAINT-5207/5208) + //F32 cur_subdivisions = getSubdivisionLevel(tick_start, translate_axis, getMinGridScale()); + /*if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / cur_subdivisions)) != 0.f) + { + continue; + }*/ + + // add in off-axis offset + tick_start += (mSnapOffsetAxis * mSnapOffsetMeters); + + F32 tick_scale = 1.f; + for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + { + if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) + { + break; + } + tick_scale *= 0.7f; + } + +// S32 num_ticks_to_fade = is_sub_tick ? num_ticks_per_side / 2 : num_ticks_per_side; +// F32 alpha = line_alpha * (1.f - (0.8f * ((F32)llabs(i) / (F32)num_ticks_to_fade))); + + tick_end = tick_start + (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); + + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + gGL.vertex3fv(tick_start.mV); + gGL.vertex3fv(tick_end.mV); + + tick_start = selection_center + (mSnapOffsetAxis * -mSnapOffsetMeters) + + (translate_axis * (getMinGridScale() / (F32)(max_subdivisions) * (F32)i - offset_nearest_grid_unit)); + tick_end = tick_start - (mSnapOffsetAxis * mSnapOffsetMeters * tick_scale); + + gGL.vertex3fv(tick_start.mV); + gGL.vertex3fv(tick_end.mV); + } + } + gGL.end(); + + if (mInSnapRegime) + { + LLVector3 line_start = selection_center - mSnapOffsetAxis * mSnapOffsetMeters; + LLVector3 line_end = selection_center + mSnapOffsetAxis * mSnapOffsetMeters; + + gGL.begin(LLRender::LINES); + { + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + + gGL.vertex3fv(line_start.mV); + gGL.vertex3fv(line_end.mV); + } + gGL.end(); + + // draw snap guide arrow + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4f(line_color.mV[VX], line_color.mV[VY], line_color.mV[VZ], line_color.mV[VW]); + + LLVector3 arrow_dir; + LLVector3 arrow_span = translate_axis; + + arrow_dir = -mSnapOffsetAxis; + gGL.vertex3fv((line_start + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_start + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_start - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + + arrow_dir = mSnapOffsetAxis; + gGL.vertex3fv((line_end + arrow_dir * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_end + arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + gGL.vertex3fv((line_end - arrow_span * mConeSize * SNAP_ARROW_SCALE).mV); + } + gGL.end(); + } + } + + sub_div_offset = ll_round(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() * 32.f) / smallest_grid_unit_scale); + + LLVector2 screen_translate_axis(llabs(translate_axis * LLViewerCamera::getInstance()->getLeftAxis()), llabs(translate_axis * LLViewerCamera::getInstance()->getUpAxis())); + screen_translate_axis.normVec(); + + S32 tick_label_spacing = ll_round(screen_translate_axis * sTickLabelSpacing); + + // render tickmark values + for (S32 i = -num_ticks_per_side; i <= num_ticks_per_side; i++) + { + LLVector3 tick_pos = selection_center + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)); + F32 alpha = line_alpha * (1.f - (0.5f * ((F32)llabs(i) / (F32)num_ticks_per_side))); + + F32 tick_scale = 1.f; + for (F32 division_level = max_subdivisions; division_level >= sGridMinSubdivisionLevel; division_level /= 2.f) + { + if (fmodf((F32)(i + sub_div_offset), division_level) == 0.f) + { + break; + } + tick_scale *= 0.7f; + } + + if (fmodf((F32)(i + sub_div_offset), (max_subdivisions / getSubdivisionLevel(tick_pos, translate_axis, getMinGridScale(), tick_label_spacing))) == 0.f) + { + F32 snap_offset_meters; + + if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) + { + snap_offset_meters = mSnapOffsetMeters; + } + else + { + snap_offset_meters = -mSnapOffsetMeters; + } + LLVector3 text_origin = selection_center + + (translate_axis * ((smallest_grid_unit_scale * (F32)i) - offset_nearest_grid_unit)) + + (mSnapOffsetAxis * snap_offset_meters * (1.f + tick_scale)); + + LLVector3 tick_offset = (tick_pos - mGridOrigin) * ~mGridRotation; + F32 offset_val = 0.5f * tick_offset.mV[ARROW_TO_AXIS[mManipPart]] / getMinGridScale(); + EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode(); + F32 text_highlight = 0.8f; + if(i - ll_round(offset_nearest_grid_unit / smallest_grid_unit_scale) == 0 && mInSnapRegime) + { + text_highlight = 1.f; + } + + if (grid_mode == GRID_MODE_WORLD) + { + // rescale units to meters from multiple of grid scale + offset_val *= 2.f * grid_scale[ARROW_TO_AXIS[mManipPart]]; + renderTickValue(text_origin, offset_val, std::string("m"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + } + else + { + renderTickValue(text_origin, offset_val, std::string("x"), LLColor4(text_highlight, text_highlight, text_highlight, alpha)); + } + } + } + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + { + // render helpful text + if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) + { + F32 snap_offset_meters_up; + if (mSnapOffsetAxis * LLViewerCamera::getInstance()->getUpAxis() > 0.f) + { + snap_offset_meters_up = mSnapOffsetMeters; + } + else + { + snap_offset_meters_up = -mSnapOffsetMeters; + } + + LLVector3 selection_center_start = getSavedPivotPoint();//LLSelectMgr::getInstance()->getSavedBBoxOfSelection().getCenterAgent(); + + LLVector3 help_text_pos = selection_center_start + (snap_offset_meters_up * 3.f * mSnapOffsetAxis); + const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); + + std::string help_text = LLTrans::getString("manip_hint1"); + LLColor4 help_text_color = LLColor4::white; + help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); + help_text = LLTrans::getString("manip_hint2"); + help_text_pos -= LLViewerCamera::getInstance()->getUpAxis() * mSnapOffsetMeters * 0.2f; + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, false); + } + } + } + else + { + // render gridlines for planar snapping + + F32 u = 0, v = 0; + LLColor4 inner_color; + LLVector3 normal; + LLVector3 grid_center = selection_center - grid_origin; + F32 usc = 1; + F32 vsc = 1; + + grid_center *= ~grid_rotation; + + switch (mManipPart) + { + case LL_YZ_PLANE: + u = grid_center.mV[VY]; + v = grid_center.mV[VZ]; + usc = grid_scale.mV[VY]; + vsc = grid_scale.mV[VZ]; + inner_color.setVec(0,1,1,line_alpha); + normal.setVec(1,0,0); + break; + case LL_XZ_PLANE: + u = grid_center.mV[VX]; + v = grid_center.mV[VZ]; + usc = grid_scale.mV[VX]; + vsc = grid_scale.mV[VZ]; + inner_color.setVec(1,0,1,line_alpha); + normal.setVec(0,1,0); + break; + case LL_XY_PLANE: + u = grid_center.mV[VX]; + v = grid_center.mV[VY]; + usc = grid_scale.mV[VX]; + vsc = grid_scale.mV[VY]; + inner_color.setVec(1,1,0,line_alpha); + normal.setVec(0,0,1); + break; + default: + break; + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + + gGL.pushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 sz = mGridSizeMeters; + F32 tiles = sz; + + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.pushMatrix(); + usc = 1.0f/usc; + vsc = 1.0f/vsc; + + while (usc > vsc*4.0f) + { + usc *= 0.5f; + } + while (vsc > usc * 4.0f) + { + vsc *= 0.5f; + } + + gGL.scalef(usc, vsc, 1.0f); + gGL.translatef(u, v, 0); + + float a = line_alpha; + + { + //draw grid behind objects + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + + { + //LLGLDisable stencil(GL_STENCIL_TEST); + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); + gGL.flush(); + gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f); + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } + + { + //draw black overlay + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); + + //draw grid top + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); + renderGrid(u,v,tiles,1,1,1,a); + + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } + + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + renderGuidelines(); + } + + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.flush(); + + switch (mManipPart) + { + case LL_YZ_PLANE: + renderGuidelines(FALSE, TRUE, TRUE); + break; + case LL_XZ_PLANE: + renderGuidelines(TRUE, FALSE, TRUE); + break; + case LL_XY_PLANE: + renderGuidelines(TRUE, TRUE, FALSE); + break; + default: + break; + } + gGL.flush(); + } + } + } + } +} + +void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a) +{ + F32 d = size*0.5f; + + for (F32 xx = -size-d; xx < size+d; xx += d) + { + gGL.begin(LLRender::TRIANGLE_STRIP); + for (F32 yy = -size-d; yy < size+d; yy += d) + { + float dx, dy, da; + + dx = xx; dy = yy; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx+d; dy = yy; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx; dy = yy+d; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + + dx = xx+d; dy = yy+d; + da = sqrtf(llmax(0.0f, 1.0f-sqrtf(dx*dx+dy*dy)/size))*a; + gGL.texCoord2f(dx, dy); + renderGridVert(dx,dy,r,g,b,da); + } + gGL.end(); + } + + +} + +void LLManipTranslate::highlightIntersection(LLVector3 normal, + LLVector3 selection_center, + LLQuaternion grid_rotation, + LLColor4 inner_color) +{ +#if 0 // DEPRECATED + if (!gSavedSettings.getBOOL("GridCrossSections")) + { + return; + } + + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + + static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; + static const U32 num_types = LL_ARRAY_SIZE(types); + + GLuint stencil_mask = 0xFFFFFFFF; + //stencil in volumes + + gGL.flush(); + + if (shader) + { + gClipProgram.bind(); + } + + { + //glStencilMask(stencil_mask); //deprecated + //glClearStencil(1); + //glClear(GL_STENCIL_BUFFER_BIT); + LLGLEnable cull_face(GL_CULL_FACE); + //LLGLEnable stencil(GL_STENCIL_TEST); + LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); + //glStencilFunc(GL_ALWAYS, 0, stencil_mask); + gGL.setColorMask(false, false); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.diffuseColor4f(1,1,1,1); + + //setup clip plane + normal = normal * grid_rotation; + if (normal * (LLViewerCamera::getInstance()->getOrigin()-selection_center) < 0) + { + normal = -normal; + } + F32 d = -(selection_center * normal); + glh::vec4f plane(normal.mV[0], normal.mV[1], normal.mV[2], d ); + + gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); + + static LLStaticHashedString sClipPlane("clip_plane"); + gClipProgram.uniform4fv(sClipPlane, 1, plane.v); + + BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + //stencil in volumes + //glStencilOp(GL_INCR, GL_INCR, GL_INCR); + glCullFace(GL_FRONT); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + //glStencilOp(GL_DECR, GL_DECR, GL_DECR); + glCullFace(GL_BACK); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + gGL.setColorMask(true, false); + } + gGL.color4f(1,1,1,1); + + gGL.pushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 sz = mGridSizeMeters; + F32 tiles = sz; + + if (shader) + { + shader->bind(); + } + + if (shader) + { + shader->bind(); + } + + //draw volume/plane intersections + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest depth(GL_FALSE); + //LLGLEnable stencil(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_EQUAL, 0, stencil_mask); + renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); + } + + glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); + glStencilMask(0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + gGL.popMatrix(); +#endif +} + +void LLManipTranslate::renderText() +{ + if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment()) + { + LLVector3 pos = getPivotPoint(); + renderXYZ(pos); + } + else + { + const BOOL children_ok = TRUE; + LLViewerObject* objectp = mObjectSelection->getFirstRootObject(children_ok); + if (objectp) + { + renderXYZ(objectp->getPositionEdit()); + } + } +} + +void LLManipTranslate::renderTranslationHandles() +{ + LLVector3 grid_origin; + LLVector3 grid_scale; + LLQuaternion grid_rotation; + LLGLDepthTest gls_depth(GL_FALSE); + + LLSelectMgr::getInstance()->getGrid(grid_origin, grid_rotation, grid_scale); + LLVector3 at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + at_axis = LLVector3::x_axis * ~grid_rotation; + } + else + { + at_axis = LLViewerCamera::getInstance()->getAtAxis() * ~grid_rotation; + } + + if (at_axis.mV[VX] > 0.f) + { + mPlaneManipPositions.mV[VX] = 1.f; + } + else + { + mPlaneManipPositions.mV[VX] = -1.f; + } + + if (at_axis.mV[VY] > 0.f) + { + mPlaneManipPositions.mV[VY] = 1.f; + } + else + { + mPlaneManipPositions.mV[VY] = -1.f; + } + + if (at_axis.mV[VZ] > 0.f) + { + mPlaneManipPositions.mV[VZ] = 1.f; + } + else + { + mPlaneManipPositions.mV[VZ] = -1.f; + } + + LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); + if (!first_object) return; + + LLVector3 selection_center = getPivotPoint(); + + // Drag handles + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw(); + mArrowLengthMeters /= gAgentCamera.mHUDCurZoom; + } + else + { + LLVector3 camera_pos_agent = gAgentCamera.getCameraPositionAgent(); + F32 range = dist_vec(camera_pos_agent, selection_center); + F32 range_from_agent = dist_vec(gAgent.getPositionAgent(), selection_center); + + // Don't draw handles if you're too far away + if (gSavedSettings.getBOOL("LimitSelectDistance")) + { + if (range_from_agent > gSavedSettings.getF32("MaxSelectDistance")) + { + return; + } + } + + if (range > 0.001f) + { + // range != zero + F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians + mArrowLengthMeters = range * tan(apparent_angle); + } + else + { + // range == zero + mArrowLengthMeters = 1.0f; + } + } + //Assume that UI scale factor is equivalent for X and Y axis + F32 ui_scale_factor = LLUI::getScaleFactor().mV[VX]; + mArrowLengthMeters *= ui_scale_factor; + + mPlaneManipOffsetMeters = mArrowLengthMeters * 1.8f; + mGridSizeMeters = gSavedSettings.getF32("GridDrawSize"); + mConeSize = mArrowLengthMeters / 4.f; + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + { + gGL.translatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + + F32 angle_radians, x, y, z; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + + gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z); + + LLQuaternion invRotation = grid_rotation; + invRotation.conjQuat(); + + LLVector3 relative_camera_dir; + + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + relative_camera_dir = LLVector3::x_axis * invRotation; + } + else + { + relative_camera_dir = (selection_center - LLViewerCamera::getInstance()->getOrigin()) * invRotation; + } + relative_camera_dir.normVec(); + + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDisable cull_face(GL_CULL_FACE); + + LLColor4 color1; + LLColor4 color2; + + // update manipulator sizes + for (S32 index = 0; index < 3; index++) + { + if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + else + { + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + } + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_YZ_PLANE) && llabs(relative_camera_dir.mV[VX]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render YZ plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + gGL.translatef(0.f, mPlaneManipOffsetMeters, mPlaneManipOffsetMeters); + gGL.scalef(mPlaneScales.mV[VX], mPlaneScales.mV[VX], mPlaneScales.mV[VX]); + if (mHighlightedPart == LL_YZ_PLANE) + { + color1.setVec(0.f, 1.f, 0.f, 1.f); + color2.setVec(0.f, 0.f, 1.f, 1.f); + } + else + { + color1.setVec(0.f, 1.f, 0.f, 0.6f); + color2.setVec(0.f, 0.f, 1.f, 0.6f); + } + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + + gGL.color4fv(color2.mV); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); + + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + gGL.popMatrix(); + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_XZ_PLANE) && llabs(relative_camera_dir.mV[VY]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render XZ plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + gGL.translatef(mPlaneManipOffsetMeters, 0.f, mPlaneManipOffsetMeters); + gGL.scalef(mPlaneScales.mV[VY], mPlaneScales.mV[VY], mPlaneScales.mV[VY]); + if (mHighlightedPart == LL_XZ_PLANE) + { + color1.setVec(0.f, 0.f, 1.f, 1.f); + color2.setVec(1.f, 0.f, 0.f, 1.f); + } + else + { + color1.setVec(0.f, 0.f, 1.f, 0.6f); + color2.setVec(1.f, 0.f, 0.f, 0.6f); + } + + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + + gGL.color4fv(color2.mV); + gGL.vertex3f(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f)); + gGL.vertex3f(mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f), 0.f, mPlaneManipOffsetMeters * (PLANE_TICK_SIZE * 0.25f)); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f); + + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.1f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.25f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.25f); + gGL.vertex3f(mPlaneManipOffsetMeters * -PLANE_TICK_SIZE * 0.4f, 0.f, mPlaneManipOffsetMeters * PLANE_TICK_SIZE * 0.1f); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + + gGL.popMatrix(); + } + + if ((mManipPart == LL_NO_PART || mManipPart == LL_XY_PLANE) && llabs(relative_camera_dir.mV[VZ]) > MIN_PLANE_MANIP_DOT_PRODUCT) + { + // render XY plane manipulator + gGL.pushMatrix(); + gGL.scalef(mPlaneManipPositions.mV[VX], mPlaneManipPositions.mV[VY], mPlaneManipPositions.mV[VZ]); + +/* Y + ^ + v1 + | \ + |<- v0 + | /| \ + v2__v__v3 > X +*/ + LLVector3 v0,v1,v2,v3; +#if 0 + // This should theoretically work but looks off; could be tuned later -SJB + gGL.translatef(-mPlaneManipOffsetMeters, -mPlaneManipOffsetMeters, 0.f); + v0 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); + v1 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), 0.f); + v2 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); + v3 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); +#else + gGL.translatef(mPlaneManipOffsetMeters, mPlaneManipOffsetMeters, 0.f); + v0 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.25f), 0.f); + v1 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), 0.f); + v2 = LLVector3(mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); + v3 = LLVector3(mPlaneManipOffsetMeters * (-PLANE_TICK_SIZE * 0.75f), mPlaneManipOffsetMeters * ( PLANE_TICK_SIZE * 0.25f), 0.f); +#endif + gGL.scalef(mPlaneScales.mV[VZ], mPlaneScales.mV[VZ], mPlaneScales.mV[VZ]); + if (mHighlightedPart == LL_XY_PLANE) + { + color1.setVec(1.f, 0.f, 0.f, 1.f); + color2.setVec(0.f, 1.f, 0.f, 1.f); + } + else + { + color1.setVec(0.8f, 0.f, 0.f, 0.6f); + color2.setVec(0.f, 0.8f, 0.f, 0.6f); + } + + gGL.begin(LLRender::TRIANGLES); + { + gGL.color4fv(color1.mV); + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v1.mV); + gGL.vertex3fv(v2.mV); + + gGL.color4fv(color2.mV); + gGL.vertex3fv(v2.mV); + gGL.vertex3fv(v3.mV); + gGL.vertex3fv(v0.mV); + } + gGL.end(); + + LLUI::setLineWidth(3.0f); + gGL.begin(LLRender::LINES); + { + gGL.color4f(0.f, 0.f, 0.f, 0.3f); + LLVector3 v12 = (v1 + v2) * .5f; + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv((v12 + (v0-v12)*.3f + (v2-v12)*.3f).mV); + gGL.vertex3fv(v12.mV); + gGL.vertex3fv((v12 + (v0-v12)*.3f + (v1-v12)*.3f).mV); + + LLVector3 v23 = (v2 + v3) * .5f; + gGL.vertex3fv(v0.mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv((v23 + (v0-v23)*.3f + (v3-v23)*.3f).mV); + gGL.vertex3fv(v23.mV); + gGL.vertex3fv((v23 + (v0-v23)*.3f + (v2-v23)*.3f).mV); + } + gGL.end(); + LLUI::setLineWidth(1.0f); + + gGL.popMatrix(); + } + } + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Since we draw handles with depth testing off, we need to draw them in the + // proper depth order. + + // Copied from LLDrawable::updateGeometry + LLVector3 pos_agent = first_object->getPositionAgent(); + LLVector3 camera_agent = gAgentCamera.getCameraPositionAgent(); + LLVector3 headPos = pos_agent - camera_agent; + + LLVector3 orientWRTHead = headPos * invRotation; + + // Find nearest vertex + U32 nearest = (orientWRTHead.mV[0] < 0.0f ? 1 : 0) + + (orientWRTHead.mV[1] < 0.0f ? 2 : 0) + + (orientWRTHead.mV[2] < 0.0f ? 4 : 0); + + // opposite faces on Linden cubes: + // 0 & 5 + // 1 & 3 + // 2 & 4 + + // Table of order to draw faces, based on nearest vertex + static U32 face_list[8][NUM_AXES*2] = { + { 2,0,1, 4,5,3 }, // v6 F201 F453 + { 2,0,3, 4,5,1 }, // v7 F203 F451 + { 4,0,1, 2,5,3 }, // v5 F401 F253 + { 4,0,3, 2,5,1 }, // v4 F403 F251 + { 2,5,1, 4,0,3 }, // v2 F251 F403 + { 2,5,3, 4,0,1 }, // v3 F253 F401 + { 4,5,1, 2,0,3 }, // v1 F451 F203 + { 4,5,3, 2,0,1 }, // v0 F453 F201 + }; + static const EManipPart which_arrow[6] = { + LL_Z_ARROW, + LL_X_ARROW, + LL_Y_ARROW, + LL_X_ARROW, + LL_Y_ARROW, + LL_Z_ARROW}; + + // draw arrows for deeper faces first, closer faces last + LLVector3 camera_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + camera_axis = LLVector3::x_axis; + } + else + { + camera_axis.setVec(gAgentCamera.getCameraPositionAgent() - first_object->getPositionAgent()); + } + + for (U32 i = 0; i < NUM_AXES*2; i++) + { + U32 face = face_list[nearest][i]; + + LLVector3 arrow_axis; + getManipAxis(first_object, which_arrow[face], arrow_axis); + + renderArrow(which_arrow[face], + mManipPart, + (face >= 3) ? -mConeSize : mConeSize, + (face >= 3) ? -mArrowLengthMeters : mArrowLengthMeters, + mConeSize, + FALSE); + } + } + } + gGL.popMatrix(); +} + + +void LLManipTranslate::renderArrow(S32 which_arrow, S32 selected_arrow, F32 box_size, F32 arrow_size, F32 handle_size, BOOL reverse_direction) +{ + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable gls_blend(GL_BLEND); + + for (S32 pass = 1; pass <= 2; pass++) + { + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, pass == 1 ? GL_LEQUAL : GL_GREATER); + gGL.pushMatrix(); + + S32 index = 0; + + index = ARROW_TO_AXIS[which_arrow]; + + // assign a color for this arrow + LLColor4 color; // black + if (which_arrow == selected_arrow || which_arrow == mHighlightedPart) + { + color.mV[index] = (pass == 1) ? 1.f : 0.5f; + } + else if (selected_arrow != LL_NO_PART) + { + color.mV[VALPHA] = 0.f; + } + else + { + color.mV[index] = pass == 1 ? .8f : .35f ; // red, green, or blue + color.mV[VALPHA] = 0.6f; + } + gGL.color4fv( color.mV ); + + LLVector3 vec; + + { + LLUI::setLineWidth(2.0f); + gGL.begin(LLRender::LINES); + vec.mV[index] = box_size; + gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); + + vec.mV[index] = arrow_size; + gGL.vertex3f(vec.mV[0], vec.mV[1], vec.mV[2]); + gGL.end(); + LLUI::setLineWidth(1.0f); + } + + gGL.translatef(vec.mV[0], vec.mV[1], vec.mV[2]); + gGL.scalef(handle_size, handle_size, handle_size); + + F32 rot = 0.0f; + LLVector3 axis; + + switch(which_arrow) + { + case LL_X_ARROW: + rot = reverse_direction ? -90.0f : 90.0f; + axis.mV[1] = 1.0f; + break; + case LL_Y_ARROW: + rot = reverse_direction ? 90.0f : -90.0f; + axis.mV[0] = 1.0f; + break; + case LL_Z_ARROW: + rot = reverse_direction ? 180.0f : 0.0f; + axis.mV[0] = 1.0f; + break; + default: + LL_ERRS() << "renderArrow called with bad arrow " << which_arrow << LL_ENDL; + break; + } + + gGL.diffuseColor4fv(color.mV); + gGL.rotatef(rot, axis.mV[0], axis.mV[1], axis.mV[2]); + gGL.scalef(mArrowScales.mV[index], mArrowScales.mV[index], mArrowScales.mV[index] * 1.5f); + + gCone.render(); + + gGL.popMatrix(); + } +} + +void LLManipTranslate::renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha) +{ + gGL.color4f(r, g, b, alpha); + switch (mManipPart) + { + case LL_YZ_PLANE: + gGL.vertex3f(0, x_trans, y_trans); + break; + case LL_XZ_PLANE: + gGL.vertex3f(x_trans, 0, y_trans); + break; + case LL_XY_PLANE: + gGL.vertex3f(x_trans, y_trans, 0); + break; + default: + gGL.vertex3f(0,0,0); + break; + } + +} + +// virtual +BOOL LLManipTranslate::canAffectSelection() +{ + BOOL can_move = mObjectSelection->getObjectCount() != 0; + if (can_move) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + } + } func; + can_move = mObjectSelection->applyToObjects(&func); + } + return can_move; } diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 84446b626a..208b289ca9 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llmaterialeditor.cpp * @brief Implementation of the gltf material editor * * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -48,7 +48,7 @@ #include "llviewertexture.h" #include "llsdutil.h" #include "llselectmgr.h" -#include "llstatusbar.h" // can_afford_transaction() +#include "llstatusbar.h" // can_afford_transaction() #include "lltoolpie.h" #include "llviewerinventory.h" #include "llinventory.h" @@ -502,7 +502,7 @@ BOOL LLMaterialEditor::postBuild() // Apply changes to object live applyToSelection(); }; - + childSetCommitCallback("double sided", changes_callback, (void*)&MATERIAL_DOUBLE_SIDED_DIRTY); // BaseColor @@ -550,7 +550,7 @@ BOOL LLMaterialEditor::postBuild() // Disable/enable setCanApplyImmediately() based on // working from inventory, upload or editing inworld - return LLPreview::postBuild(); + return LLPreview::postBuild(); } void LLMaterialEditor::onClickCloseBtn(bool app_quitting) @@ -1226,7 +1226,7 @@ std::string LLMaterialEditor::getEncodedAsset() bool LLMaterialEditor::decodeAsset(const std::vector& buffer) { LLSD asset; - + std::istrstream str(&buffer[0], buffer.size()); if (LLSDSerialize::deserialize(asset, str, buffer.size())) { @@ -1290,7 +1290,7 @@ const std::string LLMaterialEditor::buildMaterialDescription() desc << LLTrans::getString("Material Texture Name Header"); // add the texture names for each just so long as the material - // we loaded has an entry for it (i think testing the texture + // we loaded has an entry for it (i think testing the texture // control UUI for NULL is a valid metric for if it was loaded // or not but I suspect this code will change a lot so may need // to revisit @@ -1372,7 +1372,7 @@ bool LLMaterialEditor::saveIfNeeded() } } else - { + { // Make a new inventory item and set upload permissions LLPermissions local_permissions; local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); @@ -1401,7 +1401,7 @@ bool LLMaterialEditor::saveIfNeeded() // We do not update floater with uploaded asset yet, so just close it. closeFloater(); } - + return true; } @@ -1816,7 +1816,7 @@ void LLMaterialEditor::onSaveAsMsgCallback(const LLSD& notification, const LLSD& } else { - LLNotificationsUtil::add("InvalidMaterialName", LLSD(), LLSD(), [this](const LLSD& notification, const LLSD& response) + LLNotificationsUtil::add("InvalidMaterialName", LLSD(), LLSD(), [this](const LLSD& notification, const LLSD& response) { LLNotificationsUtil::add("SaveMaterialAs", LLSD().with("DESC", mMaterialName), LLSD(), boost::bind(&LLMaterialEditor::onSaveAsMsgCallback, this, _1, _2)); @@ -1976,7 +1976,7 @@ void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 ind std::list material_list; std::vector::const_iterator mat_iter = model_in.materials.begin(); std::vector::const_iterator mat_end = model_in.materials.end(); - + for (; mat_iter != mat_end; mat_iter++) { std::string mat_name = mat_iter->name; @@ -2615,28 +2615,28 @@ bool LLMaterialEditor::setFromGltfModel(const tinygltf::Model& model, S32 index, } /** - * Build a texture name from the contents of the (in tinyGLFT parlance) + * Build a texture name from the contents of the (in tinyGLFT parlance) * Image URI. This often is filepath to the original image on the users' * local file system. */ const std::string LLMaterialEditor::getImageNameFromUri(std::string image_uri, const std::string texture_type) { - // getBaseFileName() works differently on each platform and file patchs - // can contain both types of delimiter so unify them then extract the + // getBaseFileName() works differently on each platform and file patchs + // can contain both types of delimiter so unify them then extract the // base name (no path or extension) std::replace(image_uri.begin(), image_uri.end(), '\\', gDirUtilp->getDirDelimiter()[0]); std::replace(image_uri.begin(), image_uri.end(), '/', gDirUtilp->getDirDelimiter()[0]); const bool strip_extension = true; std::string stripped_uri = gDirUtilp->getBaseFileName(image_uri, strip_extension); - // sometimes they can be really long and unwieldy - 64 chars is enough for anyone :) + // sometimes they can be really long and unwieldy - 64 chars is enough for anyone :) const int max_texture_name_length = 64; if (stripped_uri.length() > max_texture_name_length) { stripped_uri = stripped_uri.substr(0, max_texture_name_length - 1); } - // We intend to append the type of texture (base color, emissive etc.) to the + // We intend to append the type of texture (base color, emissive etc.) to the // name of the texture but sometimes the creator already did that. To try // to avoid repeats (not perfect), we look for the texture type in the name // and if we find it, do not append the type, later on. One way this fails @@ -2702,15 +2702,15 @@ const std::string LLMaterialEditor::getImageNameFromUri(std::string image_uri, c /** * Update the metadata for the material based on what we find in the loaded * file (along with some assumptions and interpretations...). Fields include - * the name of the material, a material description and the names of the + * the name of the material, a material description and the names of the * composite textures. */ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index) { - // Use the name (without any path/extension) of the file that was - // uploaded as the base of the material name. Then if the name of the + // Use the name (without any path/extension) of the file that was + // uploaded as the base of the material name. Then if the name of the // scene is present and not blank, append that and use the result as - // the name of the material. This is a first pass at creating a + // the name of the material. This is a first pass at creating a // naming scheme that is useful to real content creators and hopefully // avoid 500 materials in your inventory called "scene" or "Default" const bool strip_extension = true; @@ -2741,10 +2741,10 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti // scene name isn't present so no point using it } - // If we have a valid material or scene name, use it to build the short and - // long versions of the material name. The long version is used + // If we have a valid material or scene name, use it to build the short and + // long versions of the material name. The long version is used // as you might expect, for the material name. The short version is - // used as part of the image/texture name - the theory is that will + // used as part of the image/texture name - the theory is that will // allow content creators to track the material and the corresponding // textures if (material_name.length()) @@ -2752,9 +2752,9 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti mMaterialNameShort = base_filename; mMaterialName = STRINGIZE( - base_filename << - " " << - "(" << + base_filename << + " " << + "(" << material_name << ")" ); @@ -2770,14 +2770,14 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti LLInventoryObject::correctInventoryName(mMaterialName); LLInventoryObject::correctInventoryName(mMaterialNameShort); - // We also set the title of the floater to match the + // We also set the title of the floater to match the // name of the material setTitle(mMaterialName); /** - * Extract / derive the names of each composite texture. For each, the + * Extract / derive the names of each composite texture. For each, the * index is used to to determine which of the "Images" is used. If the index - * is -1 then that texture type is not present in the material (Seems to be + * is -1 then that texture type is not present in the material (Seems to be * quite common that a material is missing 1 or more types of texture) */ if (model.materials.size() > index) @@ -2785,8 +2785,8 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti const tinygltf::Material& first_material = model.materials[index]; mBaseColorName = MATERIAL_BASE_COLOR_DEFAULT_NAME; - // note: unlike the other textures, base color doesn't have its own entry - // in the tinyGLTF Material struct. Rather, it is taken from a + // note: unlike the other textures, base color doesn't have its own entry + // in the tinyGLTF Material struct. Rather, it is taken from a // sub-texture in the pbrMetallicRoughness member int index = first_material.pbrMetallicRoughness.baseColorTexture.index; if (index > -1 && index < model.images.size()) @@ -2940,7 +2940,7 @@ public: else { // mSavedGLTFOverrideMaterials[te] being present but null - // means we need to use a default value + // means we need to use a default value revert_mat = new LLGLTFMaterial(); } } @@ -3281,7 +3281,7 @@ bool LLMaterialEditor::setFromSelection() // Ovverdired might have been updated, // refresh state of local textures in overrides - // + // // Todo: this probably shouldn't be here, but in localbitmap, // subscried to all material overrides if we want copied // objects to get properly updated as well @@ -3304,7 +3304,7 @@ void LLMaterialEditor::loadAsset() { item = getItem(); } - + bool fail = false; if (item) @@ -3508,16 +3508,16 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared( buffer, asset_id, - name, - name, + name, + name, 0, - LLFolderType::FT_TEXTURE, + LLFolderType::FT_TEXTURE, LLInventoryType::IT_TEXTURE, LLAssetType::AT_TEXTURE, LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"), - expected_upload_cost, + expected_upload_cost, false, cb, failed_upload)); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 5ee25b76a2..38af68bfff 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llpanelface.cpp * @brief Panel in the tools floater for editing face textures, colors, etc. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -28,7 +28,7 @@ // file include #include "llpanelface.h" - + // library includes #include "llcalc.h" #include "llerror.h" @@ -102,15 +102,15 @@ LLPanelFace::Selection LLPanelFace::sMaterialOverrideSelection; // Constant definitions for comboboxes // Must match the commbobox definitions in panel_tools_texture.xml // -const S32 MATMEDIA_MATERIAL = 0; // Material -const S32 MATMEDIA_PBR = 1; // PBR -const S32 MATMEDIA_MEDIA = 2; // Media -const S32 MATTYPE_DIFFUSE = 0; // Diffuse material texture -const S32 MATTYPE_NORMAL = 1; // Normal map -const S32 MATTYPE_SPECULAR = 2; // Specular map -const S32 ALPHAMODE_MASK = 2; // Alpha masking mode -const S32 BUMPY_TEXTURE = 18; // use supplied normal map -const S32 SHINY_TEXTURE = 4; // use supplied specular map +const S32 MATMEDIA_MATERIAL = 0; // Material +const S32 MATMEDIA_PBR = 1; // PBR +const S32 MATMEDIA_MEDIA = 2; // Media +const S32 MATTYPE_DIFFUSE = 0; // Diffuse material texture +const S32 MATTYPE_NORMAL = 1; // Normal map +const S32 MATTYPE_SPECULAR = 2; // Specular map +const S32 ALPHAMODE_MASK = 2; // Alpha masking mode +const S32 BUMPY_TEXTURE = 18; // use supplied normal map +const S32 SHINY_TEXTURE = 4; // use supplied specular map const S32 PBRTYPE_RENDER_MATERIAL_ID = 0; // Render Material ID const S32 PBRTYPE_BASE_COLOR = 1; // PBR Base Color const S32 PBRTYPE_METALLIC_ROUGHNESS = 2; // PBR Metallic @@ -159,7 +159,7 @@ void LLPanelFace::updateSelectedGLTFMaterials(std::function mFunc; + std::function mFunc; } select_func(func); LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func); @@ -176,7 +176,7 @@ void readSelectedGLTFMaterial(std::function func, T& v { const LLTextureEntry* tep = object->getTE(face); const LLGLTFMaterial* render_material = tep->getGLTFRenderMaterial(); - + return mFunc(render_material); } @@ -211,9 +211,9 @@ LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit() } } - channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit; - channel_to_edit = (channel_to_edit == LLRender::SPECULAR_MAP) ? (getCurrentSpecularMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit; - return channel_to_edit; + channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit; + channel_to_edit = (channel_to_edit == LLRender::SPECULAR_MAP) ? (getCurrentSpecularMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit; + return channel_to_edit; } LLRender::eTexIndex LLPanelFace::getTextureDropChannel() @@ -240,55 +240,55 @@ LLGLTFMaterial::TextureInfo LLPanelFace::getPBRDropChannel() // Things the UI provides... // -LLUUID LLPanelFace::getCurrentNormalMap() { return getChild("bumpytexture control")->getImageAssetID(); } -LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild("shinytexture control")->getImageAssetID(); } -U32 LLPanelFace::getCurrentShininess() { return getChild("combobox shininess")->getCurrentIndex(); } -U32 LLPanelFace::getCurrentBumpiness() { return getChild("combobox bumpiness")->getCurrentIndex(); } -U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild("combobox alphamode")->getCurrentIndex(); } -U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild("maskcutoff")->getValue().asInteger(); } -U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild("environment")->getValue().asInteger(); } -U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild("glossiness")->getValue().asInteger(); } -F32 LLPanelFace::getCurrentBumpyRot() { return getChild("bumpyRot")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild("bumpyScaleU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild("bumpyScaleV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild("bumpyOffsetU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild("bumpyOffsetV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyRot() { return getChild("shinyRot")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyScaleU() { return getChild("shinyScaleU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyScaleV() { return getChild("shinyScaleV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild("shinyOffsetU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild("shinyOffsetV")->getValue().asReal(); } +LLUUID LLPanelFace::getCurrentNormalMap() { return getChild("bumpytexture control")->getImageAssetID(); } +LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild("shinytexture control")->getImageAssetID(); } +U32 LLPanelFace::getCurrentShininess() { return getChild("combobox shininess")->getCurrentIndex(); } +U32 LLPanelFace::getCurrentBumpiness() { return getChild("combobox bumpiness")->getCurrentIndex(); } +U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild("combobox alphamode")->getCurrentIndex(); } +U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild("maskcutoff")->getValue().asInteger(); } +U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild("environment")->getValue().asInteger(); } +U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild("glossiness")->getValue().asInteger(); } +F32 LLPanelFace::getCurrentBumpyRot() { return getChild("bumpyRot")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild("bumpyScaleU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild("bumpyScaleV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild("bumpyOffsetU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild("bumpyOffsetV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyRot() { return getChild("shinyRot")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyScaleU() { return getChild("shinyScaleU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyScaleV() { return getChild("shinyScaleV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild("shinyOffsetU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild("shinyOffsetV")->getValue().asReal(); } // // Methods // -BOOL LLPanelFace::postBuild() -{ - childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); - childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); - childSetCommitCallback("combobox alphamode",&LLPanelFace::onCommitAlphaMode,this); - childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureScaleX, this); - childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureScaleY, this); - childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureRot, this); - childSetCommitCallback("rptctrl",&LLPanelFace::onCommitRepeatsPerMeter, this); - childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this); - childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureOffsetX, this); - childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureOffsetY, this); - - childSetCommitCallback("bumpyScaleU",&LLPanelFace::onCommitMaterialBumpyScaleX, this); - childSetCommitCallback("bumpyScaleV",&LLPanelFace::onCommitMaterialBumpyScaleY, this); - childSetCommitCallback("bumpyRot",&LLPanelFace::onCommitMaterialBumpyRot, this); - childSetCommitCallback("bumpyOffsetU",&LLPanelFace::onCommitMaterialBumpyOffsetX, this); - childSetCommitCallback("bumpyOffsetV",&LLPanelFace::onCommitMaterialBumpyOffsetY, this); - childSetCommitCallback("shinyScaleU",&LLPanelFace::onCommitMaterialShinyScaleX, this); - childSetCommitCallback("shinyScaleV",&LLPanelFace::onCommitMaterialShinyScaleY, this); - childSetCommitCallback("shinyRot",&LLPanelFace::onCommitMaterialShinyRot, this); - childSetCommitCallback("shinyOffsetU",&LLPanelFace::onCommitMaterialShinyOffsetX, this); - childSetCommitCallback("shinyOffsetV",&LLPanelFace::onCommitMaterialShinyOffsetY, this); - childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this); - childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this); - childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this); +BOOL LLPanelFace::postBuild() +{ + childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); + childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); + childSetCommitCallback("combobox alphamode",&LLPanelFace::onCommitAlphaMode,this); + childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureScaleX, this); + childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureScaleY, this); + childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureRot, this); + childSetCommitCallback("rptctrl",&LLPanelFace::onCommitRepeatsPerMeter, this); + childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this); + childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureOffsetX, this); + childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureOffsetY, this); + + childSetCommitCallback("bumpyScaleU",&LLPanelFace::onCommitMaterialBumpyScaleX, this); + childSetCommitCallback("bumpyScaleV",&LLPanelFace::onCommitMaterialBumpyScaleY, this); + childSetCommitCallback("bumpyRot",&LLPanelFace::onCommitMaterialBumpyRot, this); + childSetCommitCallback("bumpyOffsetU",&LLPanelFace::onCommitMaterialBumpyOffsetX, this); + childSetCommitCallback("bumpyOffsetV",&LLPanelFace::onCommitMaterialBumpyOffsetY, this); + childSetCommitCallback("shinyScaleU",&LLPanelFace::onCommitMaterialShinyScaleX, this); + childSetCommitCallback("shinyScaleV",&LLPanelFace::onCommitMaterialShinyScaleY, this); + childSetCommitCallback("shinyRot",&LLPanelFace::onCommitMaterialShinyRot, this); + childSetCommitCallback("shinyOffsetU",&LLPanelFace::onCommitMaterialShinyOffsetX, this); + childSetCommitCallback("shinyOffsetV",&LLPanelFace::onCommitMaterialShinyOffsetY, this); + childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this); + childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this); + childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this); childSetCommitCallback("add_media", &LLPanelFace::onClickBtnAddMedia, this); childSetCommitCallback("delete_media", &LLPanelFace::onClickBtnDeleteMedia, this); @@ -301,30 +301,30 @@ BOOL LLPanelFace::postBuild() LLGLTFMaterialList::addSelectionUpdateCallback(&LLPanelFace::onMaterialOverrideReceived); sMaterialOverrideSelection.connect(); - childSetAction("button align",&LLPanelFace::onClickAutoFix,this); - childSetAction("button align textures", &LLPanelFace::onAlignTexture, this); + childSetAction("button align",&LLPanelFace::onClickAutoFix,this); + childSetAction("button align textures", &LLPanelFace::onAlignTexture, this); childSetAction("pbr_from_inventory", &LLPanelFace::onClickBtnLoadInvPBR, this); childSetAction("edit_selected_pbr", &LLPanelFace::onClickBtnEditPBR, this); childSetAction("save_selected_pbr", &LLPanelFace::onClickBtnSavePBR, this); - LLTextureCtrl* mTextureCtrl; - LLTextureCtrl* mShinyTextureCtrl; - LLTextureCtrl* mBumpyTextureCtrl; - LLColorSwatchCtrl* mColorSwatch; - LLColorSwatchCtrl* mShinyColorSwatch; + LLTextureCtrl* mTextureCtrl; + LLTextureCtrl* mShinyTextureCtrl; + LLTextureCtrl* mBumpyTextureCtrl; + LLColorSwatchCtrl* mColorSwatch; + LLColorSwatchCtrl* mShinyColorSwatch; - LLComboBox* mComboTexGen; + LLComboBox* mComboTexGen; - LLCheckBoxCtrl *mCheckFullbright; - - LLTextBox* mLabelColorTransp; - LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha + LLCheckBoxCtrl *mCheckFullbright; - LLSpinCtrl* mCtrlGlow; + LLTextBox* mLabelColorTransp; + LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha - setMouseOpaque(FALSE); + LLSpinCtrl* mCtrlGlow; - LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); + setMouseOpaque(FALSE); + + LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); if (pbr_ctrl) { pbr_ctrl->setDefaultImageAssetID(LLUUID::null); @@ -344,117 +344,117 @@ BOOL LLPanelFace::postBuild() pbr_ctrl->setInventoryPickType(PICK_MATERIAL); } - mTextureCtrl = getChild("texture control"); - if(mTextureCtrl) - { - mTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_TEXTURE); - mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) ); - mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) ); - mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) ); - mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); - mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); - mTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); - - mTextureCtrl->setFollowsTop(); - mTextureCtrl->setFollowsLeft(); - mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); - mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); - } - - mShinyTextureCtrl = getChild("shinytexture control"); - if(mShinyTextureCtrl) - { - mShinyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_SPECULAR); - mShinyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitSpecularTexture, this, _2) ); - mShinyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelSpecularTexture, this, _2) ); - mShinyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectSpecularTexture, this, _2) ); - mShinyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); - - mShinyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); - mShinyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); - mShinyTextureCtrl->setFollowsTop(); - mShinyTextureCtrl->setFollowsLeft(); - mShinyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); - mShinyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); - } - - mBumpyTextureCtrl = getChild("bumpytexture control"); - if(mBumpyTextureCtrl) - { - mBumpyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_NORMAL); - mBumpyTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL); - mBumpyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitNormalTexture, this, _2) ); - mBumpyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelNormalTexture, this, _2) ); - mBumpyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectNormalTexture, this, _2) ); - mBumpyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); - - mBumpyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); - mBumpyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); - mBumpyTextureCtrl->setFollowsTop(); - mBumpyTextureCtrl->setFollowsLeft(); - mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); - mBumpyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); - } - - mColorSwatch = getChild("colorswatch"); - if(mColorSwatch) - { - mColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitColor, this, _2)); - mColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelColor, this, _2)); - mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2)); - mColorSwatch->setFollowsTop(); - mColorSwatch->setFollowsLeft(); - mColorSwatch->setCanApplyImmediately(TRUE); - } - - mShinyColorSwatch = getChild("shinycolorswatch"); - if(mShinyColorSwatch) - { - mShinyColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitShinyColor, this, _2)); - mShinyColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelShinyColor, this, _2)); - mShinyColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectShinyColor, this, _2)); - mShinyColorSwatch->setFollowsTop(); - mShinyColorSwatch->setFollowsLeft(); - mShinyColorSwatch->setCanApplyImmediately(TRUE); - } - - mLabelColorTransp = getChild("color trans"); - if(mLabelColorTransp) - { - mLabelColorTransp->setFollowsTop(); - mLabelColorTransp->setFollowsLeft(); - } - - mCtrlColorTransp = getChild("ColorTrans"); - if(mCtrlColorTransp) - { - mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2)); - mCtrlColorTransp->setPrecision(0); - mCtrlColorTransp->setFollowsTop(); - mCtrlColorTransp->setFollowsLeft(); - } - - mCheckFullbright = getChild("checkbox fullbright"); - if (mCheckFullbright) - { - mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this); - } - - mComboTexGen = getChild("combobox texgen"); - if(mComboTexGen) - { - mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this); - mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); - } + mTextureCtrl = getChild("texture control"); + if(mTextureCtrl) + { + mTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_TEXTURE); + mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) ); + mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) ); + mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) ); + mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); + mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); + mTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); + + mTextureCtrl->setFollowsTop(); + mTextureCtrl->setFollowsLeft(); + mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + + mShinyTextureCtrl = getChild("shinytexture control"); + if(mShinyTextureCtrl) + { + mShinyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_SPECULAR); + mShinyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitSpecularTexture, this, _2) ); + mShinyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelSpecularTexture, this, _2) ); + mShinyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectSpecularTexture, this, _2) ); + mShinyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); + + mShinyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); + mShinyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); + mShinyTextureCtrl->setFollowsTop(); + mShinyTextureCtrl->setFollowsLeft(); + mShinyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mShinyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + + mBumpyTextureCtrl = getChild("bumpytexture control"); + if(mBumpyTextureCtrl) + { + mBumpyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_NORMAL); + mBumpyTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL); + mBumpyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitNormalTexture, this, _2) ); + mBumpyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelNormalTexture, this, _2) ); + mBumpyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectNormalTexture, this, _2) ); + mBumpyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) ); + + mBumpyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); + mBumpyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1)); + mBumpyTextureCtrl->setFollowsTop(); + mBumpyTextureCtrl->setFollowsLeft(); + mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mBumpyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + + mColorSwatch = getChild("colorswatch"); + if(mColorSwatch) + { + mColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitColor, this, _2)); + mColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelColor, this, _2)); + mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2)); + mColorSwatch->setFollowsTop(); + mColorSwatch->setFollowsLeft(); + mColorSwatch->setCanApplyImmediately(TRUE); + } + + mShinyColorSwatch = getChild("shinycolorswatch"); + if(mShinyColorSwatch) + { + mShinyColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitShinyColor, this, _2)); + mShinyColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelShinyColor, this, _2)); + mShinyColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectShinyColor, this, _2)); + mShinyColorSwatch->setFollowsTop(); + mShinyColorSwatch->setFollowsLeft(); + mShinyColorSwatch->setCanApplyImmediately(TRUE); + } + + mLabelColorTransp = getChild("color trans"); + if(mLabelColorTransp) + { + mLabelColorTransp->setFollowsTop(); + mLabelColorTransp->setFollowsLeft(); + } + + mCtrlColorTransp = getChild("ColorTrans"); + if(mCtrlColorTransp) + { + mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2)); + mCtrlColorTransp->setPrecision(0); + mCtrlColorTransp->setFollowsTop(); + mCtrlColorTransp->setFollowsLeft(); + } + + mCheckFullbright = getChild("checkbox fullbright"); + if (mCheckFullbright) + { + mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this); + } + + mComboTexGen = getChild("combobox texgen"); + if(mComboTexGen) + { + mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this); + mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); + } mComboMatMedia = getChild("combobox matmedia"); - if(mComboMatMedia) - { + if(mComboMatMedia) + { mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this); mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); - } + } - LLRadioGroup* radio_mat_type = findChild("radio_material_type"); + LLRadioGroup* radio_mat_type = findChild("radio_material_type"); if(radio_mat_type) { radio_mat_type->setCommitCallback(LLPanelFace::onCommitMaterialType, this); @@ -468,25 +468,25 @@ BOOL LLPanelFace::postBuild() radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID); } - mCtrlGlow = getChild("glow"); - if(mCtrlGlow) - { - mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); - } + mCtrlGlow = getChild("glow"); + if(mCtrlGlow) + { + mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); + } mMenuClipboardColor = getChild("clipboard_color_params_btn"); mMenuClipboardTexture = getChild("clipboard_texture_params_btn"); - + mTitleMedia = getChild("title_media"); mTitleMediaText = getChild("media_info"); - clearCtrls(); + clearCtrls(); - return TRUE; + return TRUE; } LLPanelFace::LLPanelFace() -: LLPanel(), +: LLPanel(), mIsAlpha(false), mComboMatMedia(NULL), mTitleMedia(NULL), @@ -532,131 +532,131 @@ void LLPanelFace::draw() void LLPanelFace::sendTexture() { - LLTextureCtrl* mTextureCtrl = getChild("texture control"); - if(!mTextureCtrl) return; - if( !mTextureCtrl->getTentative() ) - { - // we grab the item id first, because we want to do a - // permissions check in the selection manager. ARGH! - LLUUID id = mTextureCtrl->getImageItemID(); - if(id.isNull()) - { - id = mTextureCtrl->getImageAssetID(); - } + LLTextureCtrl* mTextureCtrl = getChild("texture control"); + if(!mTextureCtrl) return; + if( !mTextureCtrl->getTentative() ) + { + // we grab the item id first, because we want to do a + // permissions check in the selection manager. ARGH! + LLUUID id = mTextureCtrl->getImageItemID(); + if(id.isNull()) + { + id = mTextureCtrl->getImageAssetID(); + } if (!LLSelectMgr::getInstance()->selectionSetImage(id)) { // need to refresh value in texture ctrl refresh(); } - } + } } void LLPanelFace::sendBump(U32 bumpiness) -{ - LLTextureCtrl* bumpytexture_ctrl = getChild("bumpytexture control"); - if (bumpiness < BUMPY_TEXTURE) -{ - LL_DEBUGS("Materials") << "clearing bumptexture control" << LL_ENDL; - bumpytexture_ctrl->clear(); - bumpytexture_ctrl->setImageAssetID(LLUUID()); - } +{ + LLTextureCtrl* bumpytexture_ctrl = getChild("bumpytexture control"); + if (bumpiness < BUMPY_TEXTURE) +{ + LL_DEBUGS("Materials") << "clearing bumptexture control" << LL_ENDL; + bumpytexture_ctrl->clear(); + bumpytexture_ctrl->setImageAssetID(LLUUID()); + } - updateBumpyControls(bumpiness == BUMPY_TEXTURE, true); + updateBumpyControls(bumpiness == BUMPY_TEXTURE, true); - LLUUID current_normal_map = bumpytexture_ctrl->getImageAssetID(); + LLUUID current_normal_map = bumpytexture_ctrl->getImageAssetID(); - U8 bump = (U8) bumpiness & TEM_BUMP_MASK; + U8 bump = (U8) bumpiness & TEM_BUMP_MASK; - // Clear legacy bump to None when using an actual normal map - // - if (!current_normal_map.isNull()) - bump = 0; + // Clear legacy bump to None when using an actual normal map + // + if (!current_normal_map.isNull()) + bump = 0; - // Set the normal map or reset it to null as appropriate - // - LLSelectedTEMaterial::setNormalID(this, current_normal_map); + // Set the normal map or reset it to null as appropriate + // + LLSelectedTEMaterial::setNormalID(this, current_normal_map); - LLSelectMgr::getInstance()->selectionSetBumpmap( bump, bumpytexture_ctrl->getImageItemID() ); + LLSelectMgr::getInstance()->selectionSetBumpmap( bump, bumpytexture_ctrl->getImageItemID() ); } void LLPanelFace::sendTexGen() { - LLComboBox* mComboTexGen = getChild("combobox texgen"); - if(!mComboTexGen)return; - U8 tex_gen = (U8) mComboTexGen->getCurrentIndex() << TEM_TEX_GEN_SHIFT; - LLSelectMgr::getInstance()->selectionSetTexGen( tex_gen ); + LLComboBox* mComboTexGen = getChild("combobox texgen"); + if(!mComboTexGen)return; + U8 tex_gen = (U8) mComboTexGen->getCurrentIndex() << TEM_TEX_GEN_SHIFT; + LLSelectMgr::getInstance()->selectionSetTexGen( tex_gen ); } void LLPanelFace::sendShiny(U32 shininess) { - LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); + LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); - if (shininess < SHINY_TEXTURE) + if (shininess < SHINY_TEXTURE) { - texture_ctrl->clear(); - texture_ctrl->setImageAssetID(LLUUID()); - } + texture_ctrl->clear(); + texture_ctrl->setImageAssetID(LLUUID()); + } + + LLUUID specmap = getCurrentSpecularMap(); - LLUUID specmap = getCurrentSpecularMap(); + U8 shiny = (U8) shininess & TEM_SHINY_MASK; + if (!specmap.isNull()) + shiny = 0; - U8 shiny = (U8) shininess & TEM_SHINY_MASK; - if (!specmap.isNull()) - shiny = 0; + LLSelectedTEMaterial::setSpecularID(this, specmap); - LLSelectedTEMaterial::setSpecularID(this, specmap); + LLSelectMgr::getInstance()->selectionSetShiny( shiny, texture_ctrl->getImageItemID() ); - LLSelectMgr::getInstance()->selectionSetShiny( shiny, texture_ctrl->getImageItemID() ); + updateShinyControls(!specmap.isNull(), true); - updateShinyControls(!specmap.isNull(), true); - } void LLPanelFace::sendFullbright() { - LLCheckBoxCtrl* mCheckFullbright = getChild("checkbox fullbright"); - if(!mCheckFullbright)return; - U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0; - LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); + LLCheckBoxCtrl* mCheckFullbright = getChild("checkbox fullbright"); + if(!mCheckFullbright)return; + U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0; + LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); } void LLPanelFace::sendColor() { - - LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); - if(!mColorSwatch)return; - LLColor4 color = mColorSwatch->get(); - LLSelectMgr::getInstance()->selectionSetColorOnly( color ); + LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); + if(!mColorSwatch)return; + LLColor4 color = mColorSwatch->get(); + + LLSelectMgr::getInstance()->selectionSetColorOnly( color ); } void LLPanelFace::sendAlpha() -{ - LLSpinCtrl* mCtrlColorTransp = getChild("ColorTrans"); - if(!mCtrlColorTransp)return; - F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f; +{ + LLSpinCtrl* mCtrlColorTransp = getChild("ColorTrans"); + if(!mCtrlColorTransp)return; + F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f; - LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha ); + LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha ); } void LLPanelFace::sendGlow() { - LLSpinCtrl* mCtrlGlow = getChild("glow"); - llassert(mCtrlGlow); - if (mCtrlGlow) - { - F32 glow = mCtrlGlow->get(); - LLSelectMgr::getInstance()->selectionSetGlow( glow ); - } + LLSpinCtrl* mCtrlGlow = getChild("glow"); + llassert(mCtrlGlow); + if (mCtrlGlow) + { + F32 glow = mCtrlGlow->get(); + LLSelectMgr::getInstance()->selectionSetGlow( glow ); + } } struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor { - LLPanelFaceSetTEFunctor(LLPanelFace* panel) : mPanel(panel) {} - virtual bool apply(LLViewerObject* object, S32 te) - { - BOOL valid; - F32 value; + LLPanelFaceSetTEFunctor(LLPanelFace* panel) : mPanel(panel) {} + virtual bool apply(LLViewerObject* object, S32 te) + { + BOOL valid; + F32 value; std::string prefix; // Effectively the same as MATMEDIA_PBR sans using different radio, @@ -674,179 +674,179 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor prefix = "shiny"; break; } - + LLSpinCtrl * ctrlTexScaleS = mPanel->getChild(prefix + "ScaleU"); LLSpinCtrl * ctrlTexScaleT = mPanel->getChild(prefix + "ScaleV"); LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild(prefix + "OffsetU"); LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild(prefix + "OffsetV"); LLSpinCtrl * ctrlTexRotation = mPanel->getChild(prefix + "Rot"); - LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); - LLCheckBoxCtrl* cb_planar_align = mPanel->getChild("checkbox planar align"); - bool align_planar = (cb_planar_align && cb_planar_align->get()); - - llassert(comboTexGen); - llassert(object); - - if (ctrlTexScaleS) - { - valid = !ctrlTexScaleS->getTentative(); // || !checkFlipScaleS->getTentative(); - if (valid || align_planar) - { - value = ctrlTexScaleS->get(); - if (comboTexGen && - comboTexGen->getCurrentIndex() == 1) - { - value *= 0.5f; - } - object->setTEScaleS( te, value ); - - if (align_planar) - { - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te, object->getID()); - } - } - } - - if (ctrlTexScaleT) - { - valid = !ctrlTexScaleT->getTentative(); // || !checkFlipScaleT->getTentative(); - if (valid || align_planar) - { - value = ctrlTexScaleT->get(); - //if( checkFlipScaleT->get() ) - //{ - // value = -value; - //} - if (comboTexGen && - comboTexGen->getCurrentIndex() == 1) - { - value *= 0.5f; - } - object->setTEScaleT( te, value ); - - if (align_planar) - { - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te, object->getID()); - } - } - } - - if (ctrlTexOffsetS) - { - valid = !ctrlTexOffsetS->getTentative(); - if (valid || align_planar) - { - value = ctrlTexOffsetS->get(); - object->setTEOffsetS( te, value ); - - if (align_planar) - { - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te, object->getID()); - } - } - } - - if (ctrlTexOffsetT) - { - valid = !ctrlTexOffsetT->getTentative(); - if (valid || align_planar) - { - value = ctrlTexOffsetT->get(); - object->setTEOffsetT( te, value ); - - if (align_planar) - { - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te, object->getID()); - } - } - } - - if (ctrlTexRotation) - { - valid = !ctrlTexRotation->getTentative(); - if (valid || align_planar) - { - value = ctrlTexRotation->get() * DEG_TO_RAD; - object->setTERotation( te, value ); - - if (align_planar) - { - LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te, object->getID()); - } - } - } - return true; - } + LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); + LLCheckBoxCtrl* cb_planar_align = mPanel->getChild("checkbox planar align"); + bool align_planar = (cb_planar_align && cb_planar_align->get()); + + llassert(comboTexGen); + llassert(object); + + if (ctrlTexScaleS) + { + valid = !ctrlTexScaleS->getTentative(); // || !checkFlipScaleS->getTentative(); + if (valid || align_planar) + { + value = ctrlTexScaleS->get(); + if (comboTexGen && + comboTexGen->getCurrentIndex() == 1) + { + value *= 0.5f; + } + object->setTEScaleS( te, value ); + + if (align_planar) + { + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te, object->getID()); + } + } + } + + if (ctrlTexScaleT) + { + valid = !ctrlTexScaleT->getTentative(); // || !checkFlipScaleT->getTentative(); + if (valid || align_planar) + { + value = ctrlTexScaleT->get(); + //if( checkFlipScaleT->get() ) + //{ + // value = -value; + //} + if (comboTexGen && + comboTexGen->getCurrentIndex() == 1) + { + value *= 0.5f; + } + object->setTEScaleT( te, value ); + + if (align_planar) + { + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te, object->getID()); + } + } + } + + if (ctrlTexOffsetS) + { + valid = !ctrlTexOffsetS->getTentative(); + if (valid || align_planar) + { + value = ctrlTexOffsetS->get(); + object->setTEOffsetS( te, value ); + + if (align_planar) + { + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te, object->getID()); + } + } + } + + if (ctrlTexOffsetT) + { + valid = !ctrlTexOffsetT->getTentative(); + if (valid || align_planar) + { + value = ctrlTexOffsetT->get(); + object->setTEOffsetT( te, value ); + + if (align_planar) + { + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te, object->getID()); + } + } + } + + if (ctrlTexRotation) + { + valid = !ctrlTexRotation->getTentative(); + if (valid || align_planar) + { + value = ctrlTexRotation->get() * DEG_TO_RAD; + object->setTERotation( te, value ); + + if (align_planar) + { + LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te, object->getID()); + } + } + } + return true; + } private: - LLPanelFace* mPanel; + LLPanelFace* mPanel; }; // Functor that aligns a face to mCenterFace struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor { - LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) : - mPanel(panel), - mCenterFace(center_face) {} - - virtual bool apply(LLViewerObject* object, S32 te) - { - LLFace* facep = object->mDrawable->getFace(te); - if (!facep) - { - return true; - } - - if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) - { - return true; - } - - bool set_aligned = true; - if (facep == mCenterFace) - { - set_aligned = false; - } - if (set_aligned) - { - LLVector2 uv_offset, uv_scale; - F32 uv_rot; - set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot); - if (set_aligned) - { - object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]); - object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]); - object->setTERotation(te, uv_rot); - - LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID()); - - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); - - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); - LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); - } - } - if (!set_aligned) - { - LLPanelFaceSetTEFunctor setfunc(mPanel); - setfunc.apply(object, te); - } - return true; - } + LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) : + mPanel(panel), + mCenterFace(center_face) {} + + virtual bool apply(LLViewerObject* object, S32 te) + { + LLFace* facep = object->mDrawable->getFace(te); + if (!facep) + { + return true; + } + + if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) + { + return true; + } + + bool set_aligned = true; + if (facep == mCenterFace) + { + set_aligned = false; + } + if (set_aligned) + { + LLVector2 uv_offset, uv_scale; + F32 uv_rot; + set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot); + if (set_aligned) + { + object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]); + object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]); + object->setTERotation(te, uv_rot); + + LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID()); + + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); + + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); + LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); + } + } + if (!set_aligned) + { + LLPanelFaceSetTEFunctor setfunc(mPanel); + setfunc.apply(object, te); + } + return true; + } private: - LLPanelFace* mPanel; - LLFace* mCenterFace; + LLPanelFace* mPanel; + LLFace* mCenterFace; }; struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor @@ -902,7 +902,7 @@ struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor } } } - + return true; } private: @@ -914,36 +914,36 @@ private: // Functor that tests if a face is aligned to mCenterFace struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor { - LLPanelFaceGetIsAlignedTEFunctor(LLFace* center_face) : - mCenterFace(center_face) {} - - virtual bool apply(LLViewerObject* object, S32 te) - { - LLFace* facep = object->mDrawable->getFace(te); - if (!facep) - { - return false; - } - - if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) - { //volume face does not exist, can't be aligned - return false; - } - - if (facep == mCenterFace) - { - return true; - } - - LLVector2 aligned_st_offset, aligned_st_scale; - F32 aligned_st_rot; - if ( facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot) ) - { - const LLTextureEntry* tep = facep->getTextureEntry(); - LLVector2 st_offset, st_scale; - tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]); - tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]); - F32 st_rot = tep->getRotation(); + LLPanelFaceGetIsAlignedTEFunctor(LLFace* center_face) : + mCenterFace(center_face) {} + + virtual bool apply(LLViewerObject* object, S32 te) + { + LLFace* facep = object->mDrawable->getFace(te); + if (!facep) + { + return false; + } + + if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) + { //volume face does not exist, can't be aligned + return false; + } + + if (facep == mCenterFace) + { + return true; + } + + LLVector2 aligned_st_offset, aligned_st_scale; + F32 aligned_st_rot; + if ( facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot) ) + { + const LLTextureEntry* tep = facep->getTextureEntry(); + LLVector2 st_offset, st_scale; + tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]); + tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]); + F32 st_rot = tep->getRotation(); bool eq_offset_x = is_approx_equal_fraction(st_offset.mV[VX], aligned_st_offset.mV[VX], 12); bool eq_offset_y = is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 12); @@ -951,49 +951,49 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor bool eq_scale_y = is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 12); bool eq_rot = is_approx_equal_fraction(st_rot, aligned_st_rot, 6); - // needs a fuzzy comparison, because of fp errors - if (eq_offset_x && - eq_offset_y && - eq_scale_x && - eq_scale_y && - eq_rot) - { - return true; - } - } - return false; - } + // needs a fuzzy comparison, because of fp errors + if (eq_offset_x && + eq_offset_y && + eq_scale_x && + eq_scale_y && + eq_rot) + { + return true; + } + } + return false; + } private: - LLFace* mCenterFace; + LLFace* mCenterFace; }; struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) - { - object->sendTEUpdate(); - return true; - } + virtual bool apply(LLViewerObject* object) + { + object->sendTEUpdate(); + return true; + } }; void LLPanelFace::sendTextureInfo() { - if ((bool)childGetValue("checkbox planar align").asBoolean()) - { - LLFace* last_face = NULL; - bool identical_face =false; - LLSelectedTE::getFace(last_face, identical_face); - LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face); - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); - } - else - { - LLPanelFaceSetTEFunctor setfunc(this); - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); - } + if ((bool)childGetValue("checkbox planar align").asBoolean()) + { + LLFace* last_face = NULL; + bool identical_face =false; + LLSelectedTE::getFace(last_face, identical_face); + LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + } + else + { + LLPanelFaceSetTEFunctor setfunc(this); + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + } - LLPanelFaceSendFunctor sendfunc; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); + LLPanelFaceSendFunctor sendfunc; + LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); } void LLPanelFace::alignTestureLayer() @@ -1009,19 +1009,19 @@ void LLPanelFace::alignTestureLayer() void LLPanelFace::getState() { - updateUI(); + updateUI(); } void LLPanelFace::updateUI(bool force_set_values /*false*/) { //set state of UI to match state of texture entry(ies) (calls setEnabled, setValue, etc, but NOT setVisible) LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); - LLViewerObject* objectp = node ? node->getObject() : NULL; + LLViewerObject* objectp = node ? node->getObject() : NULL; - if (objectp - && objectp->getPCode() == LL_PCODE_VOLUME - && objectp->permModify()) - { - BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); + if (objectp + && objectp->getPCode() == LL_PCODE_VOLUME + && objectp->permModify()) + { + BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); BOOL attachment = objectp->isAttachment(); bool has_pbr_material; @@ -1030,9 +1030,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) const bool has_material = !has_pbr_material; - // only turn on auto-adjust button if there is a media renderer and the media is loaded + // only turn on auto-adjust button if there is a media renderer and the media is loaded childSetEnabled("button align", editable); - + if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL) { // When selecting an object with a pbr and UI combo is not set, @@ -1069,8 +1069,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) static S32 selected_te = -1; static LLUUID prev_obj_id; - if ((LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()) && - !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) + if ((LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()) && + !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) { S32 new_selection = -1; // Don't use getLastSelectedTE, it could have been deselected S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); @@ -1093,11 +1093,11 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { mComboMatMedia->selectNthItem(MATMEDIA_PBR); } - else if (te_has_media) + else if (te_has_media) { mComboMatMedia->selectNthItem(MATMEDIA_MEDIA); } - else if (id.notNull() || normmap_id.notNull() || specmap_id.notNull()) + else if (id.notNull() || normmap_id.notNull() || specmap_id.notNull()) { mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); } @@ -1105,11 +1105,11 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) prev_obj_id = objectp->getID(); } } - else + else { if (prev_obj_id != objectp->getID()) { - if (has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL)) + if (has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL)) { mComboMatMedia->selectNthItem(MATMEDIA_PBR); } @@ -1138,24 +1138,24 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) const bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR; const bool texture_info_selected = pbr_selected && radio_pbr_type->getSelectedIndex() != PBRTYPE_RENDER_MATERIAL_ID; - getChildView("checkbox_sync_settings")->setEnabled(editable); - childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings")); + getChildView("checkbox_sync_settings")->setEnabled(editable); + childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings")); - updateVisibility(objectp); + updateVisibility(objectp); - // Color swatch - { - getChildView("color label")->setEnabled(editable); - } - LLColorSwatchCtrl* color_swatch = findChild("colorswatch"); + // Color swatch + { + getChildView("color label")->setEnabled(editable); + } + LLColorSwatchCtrl* color_swatch = findChild("colorswatch"); - LLColor4 color = LLColor4::white; - bool identical_color = false; + LLColor4 color = LLColor4::white; + bool identical_color = false; - if (color_swatch) - { - LLSelectedTE::getColor(color, identical_color); - LLColor4 prev_color = color_swatch->get(); + if (color_swatch) + { + LLSelectedTE::getColor(color, identical_color); + LLColor4 prev_color = color_swatch->get(); color_swatch->setOriginal(color); color_swatch->set(color, force_set_values || (prev_color != color) || !editable); @@ -1163,179 +1163,179 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) color_swatch->setValid(editable && !has_pbr_material); color_swatch->setEnabled( editable && !has_pbr_material); color_swatch->setCanApplyImmediately( editable && !has_pbr_material); - } - - // Color transparency - getChildView("color trans")->setEnabled(editable); - - F32 transparency = (1.f - color.mV[VALPHA]) * 100.f; - getChild("ColorTrans")->setValue(editable ? transparency : 0); - getChildView("ColorTrans")->setEnabled(editable && has_material); - - U8 shiny = 0; - bool identical_shiny = false; - - // Shiny - LLSelectedTE::getShiny(shiny, identical_shiny); - identical = identical && identical_shiny; - - shiny = specmap_id.isNull() ? shiny : SHINY_TEXTURE; - - LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess"); - if (combobox_shininess) - { - combobox_shininess->selectNthItem((S32)shiny); - } - - getChildView("label shininess")->setEnabled(editable); - getChildView("combobox shininess")->setEnabled(editable); - - getChildView("label glossiness")->setEnabled(editable); - getChildView("glossiness")->setEnabled(editable); - - getChildView("label environment")->setEnabled(editable); - getChildView("environment")->setEnabled(editable); - getChildView("label shinycolor")->setEnabled(editable); - - getChild("combobox shininess")->setTentative(!identical_spec); - getChild("glossiness")->setTentative(!identical_spec); - getChild("environment")->setTentative(!identical_spec); - getChild("shinycolorswatch")->setTentative(!identical_spec); - - LLColorSwatchCtrl* mShinyColorSwatch = getChild("shinycolorswatch"); - if (mShinyColorSwatch) - { - mShinyColorSwatch->setValid(editable); - mShinyColorSwatch->setEnabled( editable ); - mShinyColorSwatch->setCanApplyImmediately( editable ); - } - - U8 bumpy = 0; - // Bumpy - { - bool identical_bumpy = false; - LLSelectedTE::getBumpmap(bumpy,identical_bumpy); - - LLUUID norm_map_id = getCurrentNormalMap(); - LLCtrlSelectionInterface* combobox_bumpiness = childGetSelectionInterface("combobox bumpiness"); - - bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE; - - if (combobox_bumpiness) - { - combobox_bumpiness->selectNthItem((S32)bumpy); - } - else - { - LL_WARNS() << "failed childGetSelectionInterface for 'combobox bumpiness'" << LL_ENDL; - } - - getChildView("combobox bumpiness")->setEnabled(editable); - getChild("combobox bumpiness")->setTentative(!identical_bumpy); - getChildView("label bumpiness")->setEnabled(editable); - } - - // Texture - { - mIsAlpha = FALSE; - LLGLenum image_format = GL_RGB; - bool identical_image_format = false; - LLSelectedTE::getImageFormat(image_format, identical_image_format); - - mIsAlpha = FALSE; - switch (image_format) - { - case GL_RGBA: - case GL_ALPHA: - { - mIsAlpha = TRUE; - } - break; - - case GL_RGB: break; - default: - { - LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; - } - break; - } - - if (LLViewerMedia::getInstance()->textureHasMedia(id)) - { - getChildView("button align")->setEnabled(editable); - } - - // Diffuse Alpha Mode - - // Init to the default that is appropriate for the alpha content of the asset - // - U8 alpha_mode = mIsAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - - bool identical_alpha_mode = false; - - // See if that's been overridden by a material setting for same... - // - LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha); - - LLCtrlSelectionInterface* combobox_alphamode = childGetSelectionInterface("combobox alphamode"); - if (combobox_alphamode) - { - //it is invalid to have any alpha mode other than blend if transparency is greater than zero ... - // Want masking? Want emissive? Tough! You get BLEND! - alpha_mode = (transparency > 0.f) ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : alpha_mode; - - // ... unless there is no alpha channel in the texture, in which case alpha mode MUST be none - alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - - combobox_alphamode->selectNthItem(alpha_mode); - } - else - { - LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; - } - - updateAlphaControls(); - - if (texture_ctrl) - { - if (identical_diffuse) - { - texture_ctrl->setTentative(FALSE); - texture_ctrl->setEnabled(editable && !has_pbr_material); - texture_ctrl->setImageAssetID(id); - getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material); - getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material); - getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - - texture_ctrl->setBakeTextureEnabled(TRUE); - } - else if (id.isNull()) - { - // None selected - texture_ctrl->setTentative(FALSE); - texture_ctrl->setEnabled(FALSE); - texture_ctrl->setImageAssetID(LLUUID::null); - getChildView("combobox alphamode")->setEnabled(FALSE); - getChildView("label alphamode")->setEnabled(FALSE); - getChildView("maskcutoff")->setEnabled(FALSE); - getChildView("label maskcutoff")->setEnabled(FALSE); - - texture_ctrl->setBakeTextureEnabled(false); - } - else - { - // Tentative: multiple selected with different textures - texture_ctrl->setTentative(TRUE); - texture_ctrl->setEnabled(editable && !has_pbr_material); - texture_ctrl->setImageAssetID(id); - getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material); - getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material); - getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - - texture_ctrl->setBakeTextureEnabled(TRUE); - } + } + + // Color transparency + getChildView("color trans")->setEnabled(editable); + + F32 transparency = (1.f - color.mV[VALPHA]) * 100.f; + getChild("ColorTrans")->setValue(editable ? transparency : 0); + getChildView("ColorTrans")->setEnabled(editable && has_material); + + U8 shiny = 0; + bool identical_shiny = false; + + // Shiny + LLSelectedTE::getShiny(shiny, identical_shiny); + identical = identical && identical_shiny; + + shiny = specmap_id.isNull() ? shiny : SHINY_TEXTURE; + + LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess"); + if (combobox_shininess) + { + combobox_shininess->selectNthItem((S32)shiny); + } + + getChildView("label shininess")->setEnabled(editable); + getChildView("combobox shininess")->setEnabled(editable); + + getChildView("label glossiness")->setEnabled(editable); + getChildView("glossiness")->setEnabled(editable); + + getChildView("label environment")->setEnabled(editable); + getChildView("environment")->setEnabled(editable); + getChildView("label shinycolor")->setEnabled(editable); + + getChild("combobox shininess")->setTentative(!identical_spec); + getChild("glossiness")->setTentative(!identical_spec); + getChild("environment")->setTentative(!identical_spec); + getChild("shinycolorswatch")->setTentative(!identical_spec); + + LLColorSwatchCtrl* mShinyColorSwatch = getChild("shinycolorswatch"); + if (mShinyColorSwatch) + { + mShinyColorSwatch->setValid(editable); + mShinyColorSwatch->setEnabled( editable ); + mShinyColorSwatch->setCanApplyImmediately( editable ); + } + + U8 bumpy = 0; + // Bumpy + { + bool identical_bumpy = false; + LLSelectedTE::getBumpmap(bumpy,identical_bumpy); + + LLUUID norm_map_id = getCurrentNormalMap(); + LLCtrlSelectionInterface* combobox_bumpiness = childGetSelectionInterface("combobox bumpiness"); + + bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE; + + if (combobox_bumpiness) + { + combobox_bumpiness->selectNthItem((S32)bumpy); + } + else + { + LL_WARNS() << "failed childGetSelectionInterface for 'combobox bumpiness'" << LL_ENDL; + } + + getChildView("combobox bumpiness")->setEnabled(editable); + getChild("combobox bumpiness")->setTentative(!identical_bumpy); + getChildView("label bumpiness")->setEnabled(editable); + } + + // Texture + { + mIsAlpha = FALSE; + LLGLenum image_format = GL_RGB; + bool identical_image_format = false; + LLSelectedTE::getImageFormat(image_format, identical_image_format); + + mIsAlpha = FALSE; + switch (image_format) + { + case GL_RGBA: + case GL_ALPHA: + { + mIsAlpha = TRUE; + } + break; + + case GL_RGB: break; + default: + { + LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; + } + break; + } + + if (LLViewerMedia::getInstance()->textureHasMedia(id)) + { + getChildView("button align")->setEnabled(editable); + } + + // Diffuse Alpha Mode + + // Init to the default that is appropriate for the alpha content of the asset + // + U8 alpha_mode = mIsAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + + bool identical_alpha_mode = false; + + // See if that's been overridden by a material setting for same... + // + LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha); + + LLCtrlSelectionInterface* combobox_alphamode = childGetSelectionInterface("combobox alphamode"); + if (combobox_alphamode) + { + //it is invalid to have any alpha mode other than blend if transparency is greater than zero ... + // Want masking? Want emissive? Tough! You get BLEND! + alpha_mode = (transparency > 0.f) ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : alpha_mode; + + // ... unless there is no alpha channel in the texture, in which case alpha mode MUST be none + alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + + combobox_alphamode->selectNthItem(alpha_mode); + } + else + { + LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; + } + + updateAlphaControls(); + + if (texture_ctrl) + { + if (identical_diffuse) + { + texture_ctrl->setTentative(FALSE); + texture_ctrl->setEnabled(editable && !has_pbr_material); + texture_ctrl->setImageAssetID(id); + getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material); + getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material); + getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); + getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); + + texture_ctrl->setBakeTextureEnabled(TRUE); + } + else if (id.isNull()) + { + // None selected + texture_ctrl->setTentative(FALSE); + texture_ctrl->setEnabled(FALSE); + texture_ctrl->setImageAssetID(LLUUID::null); + getChildView("combobox alphamode")->setEnabled(FALSE); + getChildView("label alphamode")->setEnabled(FALSE); + getChildView("maskcutoff")->setEnabled(FALSE); + getChildView("label maskcutoff")->setEnabled(FALSE); + + texture_ctrl->setBakeTextureEnabled(false); + } + else + { + // Tentative: multiple selected with different textures + texture_ctrl->setTentative(TRUE); + texture_ctrl->setEnabled(editable && !has_pbr_material); + texture_ctrl->setImageAssetID(id); + getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material); + getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material); + getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); + getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); + + texture_ctrl->setBakeTextureEnabled(TRUE); + } if (attachment) { @@ -1348,13 +1348,13 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { texture_ctrl->setImmediateFilterPermMask(PERM_NONE); } - } + } - if (shinytexture_ctrl) - { - shinytexture_ctrl->setTentative( !identical_spec ); - shinytexture_ctrl->setEnabled( editable && !has_pbr_material); - shinytexture_ctrl->setImageAssetID( specmap_id ); + if (shinytexture_ctrl) + { + shinytexture_ctrl->setTentative( !identical_spec ); + shinytexture_ctrl->setEnabled( editable && !has_pbr_material); + shinytexture_ctrl->setImageAssetID( specmap_id ); if (attachment) { @@ -1364,13 +1364,13 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { shinytexture_ctrl->setImmediateFilterPermMask(PERM_NONE); } - } + } - if (bumpytexture_ctrl) - { - bumpytexture_ctrl->setTentative( !identical_norm ); - bumpytexture_ctrl->setEnabled( editable && !has_pbr_material); - bumpytexture_ctrl->setImageAssetID( normmap_id ); + if (bumpytexture_ctrl) + { + bumpytexture_ctrl->setTentative( !identical_norm ); + bumpytexture_ctrl->setEnabled( editable && !has_pbr_material); + bumpytexture_ctrl->setImageAssetID( normmap_id ); if (attachment) { @@ -1380,292 +1380,292 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { bumpytexture_ctrl->setImmediateFilterPermMask(PERM_NONE); } - } - } - - // planar align - bool align_planar = false; - bool identical_planar_aligned = false; - { - LLCheckBoxCtrl* cb_planar_align = getChild("checkbox planar align"); - align_planar = (cb_planar_align && cb_planar_align->get()); - - bool enabled = (editable && isIdenticalPlanarTexgen() && !texture_info_selected); - childSetValue("checkbox planar align", align_planar && enabled); + } + } + + // planar align + bool align_planar = false; + bool identical_planar_aligned = false; + { + LLCheckBoxCtrl* cb_planar_align = getChild("checkbox planar align"); + align_planar = (cb_planar_align && cb_planar_align->get()); + + bool enabled = (editable && isIdenticalPlanarTexgen() && !texture_info_selected); + childSetValue("checkbox planar align", align_planar && enabled); childSetVisible("checkbox planar align", enabled); - childSetEnabled("checkbox planar align", enabled); - childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1); - - if (align_planar && enabled) - { - LLFace* last_face = NULL; - bool identical_face = false; - LLSelectedTE::getFace(last_face, identical_face); - - LLPanelFaceGetIsAlignedTEFunctor get_is_aligend_func(last_face); - // this will determine if the texture param controls are tentative: - identical_planar_aligned = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&get_is_aligend_func); - } - } - - // Needs to be public and before tex scale settings below to properly reflect - // behavior when in planar vs default texgen modes in the - // NORSPEC-84 et al - // - LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT; - bool identical_texgen = true; - bool identical_planar_texgen = false; - - { - LLSelectedTE::getTexGen(selected_texgen, identical_texgen); - identical_planar_texgen = (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR)); - } - - // Texture scale - { - bool identical_diff_scale_s = false; - bool identical_spec_scale_s = false; - bool identical_norm_scale_s = false; - - identical = align_planar ? identical_planar_aligned : identical; - - F32 diff_scale_s = 1.f; - F32 spec_scale_s = 1.f; - F32 norm_scale_s = 1.f; - - LLSelectedTE::getScaleS(diff_scale_s, identical_diff_scale_s); - LLSelectedTEMaterial::getSpecularRepeatX(spec_scale_s, identical_spec_scale_s); - LLSelectedTEMaterial::getNormalRepeatX(norm_scale_s, identical_norm_scale_s); - - diff_scale_s = editable ? diff_scale_s : 1.0f; - diff_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; - - norm_scale_s = editable ? norm_scale_s : 1.0f; - norm_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; - - spec_scale_s = editable ? spec_scale_s : 1.0f; - spec_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; - - getChild("TexScaleU")->setValue(diff_scale_s); - getChild("shinyScaleU")->setValue(spec_scale_s); - getChild("bumpyScaleU")->setValue(norm_scale_s); + childSetEnabled("checkbox planar align", enabled); + childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1); + + if (align_planar && enabled) + { + LLFace* last_face = NULL; + bool identical_face = false; + LLSelectedTE::getFace(last_face, identical_face); + + LLPanelFaceGetIsAlignedTEFunctor get_is_aligend_func(last_face); + // this will determine if the texture param controls are tentative: + identical_planar_aligned = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&get_is_aligend_func); + } + } + + // Needs to be public and before tex scale settings below to properly reflect + // behavior when in planar vs default texgen modes in the + // NORSPEC-84 et al + // + LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT; + bool identical_texgen = true; + bool identical_planar_texgen = false; + + { + LLSelectedTE::getTexGen(selected_texgen, identical_texgen); + identical_planar_texgen = (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR)); + } + + // Texture scale + { + bool identical_diff_scale_s = false; + bool identical_spec_scale_s = false; + bool identical_norm_scale_s = false; + + identical = align_planar ? identical_planar_aligned : identical; + + F32 diff_scale_s = 1.f; + F32 spec_scale_s = 1.f; + F32 norm_scale_s = 1.f; + + LLSelectedTE::getScaleS(diff_scale_s, identical_diff_scale_s); + LLSelectedTEMaterial::getSpecularRepeatX(spec_scale_s, identical_spec_scale_s); + LLSelectedTEMaterial::getNormalRepeatX(norm_scale_s, identical_norm_scale_s); + + diff_scale_s = editable ? diff_scale_s : 1.0f; + diff_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; + + norm_scale_s = editable ? norm_scale_s : 1.0f; + norm_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; + + spec_scale_s = editable ? spec_scale_s : 1.0f; + spec_scale_s *= identical_planar_texgen ? 2.0f : 1.0f; + + getChild("TexScaleU")->setValue(diff_scale_s); + getChild("shinyScaleU")->setValue(spec_scale_s); + getChild("bumpyScaleU")->setValue(norm_scale_s); getChildView("TexScaleU")->setEnabled(editable && has_material); getChildView("shinyScaleU")->setEnabled(editable && has_material && specmap_id.notNull()); getChildView("bumpyScaleU")->setEnabled(editable && has_material && normmap_id.notNull()); - BOOL diff_scale_tentative = !(identical && identical_diff_scale_s); - BOOL norm_scale_tentative = !(identical && identical_norm_scale_s); - BOOL spec_scale_tentative = !(identical && identical_spec_scale_s); + BOOL diff_scale_tentative = !(identical && identical_diff_scale_s); + BOOL norm_scale_tentative = !(identical && identical_norm_scale_s); + BOOL spec_scale_tentative = !(identical && identical_spec_scale_s); - getChild("TexScaleU")->setTentative( LLSD(diff_scale_tentative)); - getChild("shinyScaleU")->setTentative(LLSD(spec_scale_tentative)); - getChild("bumpyScaleU")->setTentative(LLSD(norm_scale_tentative)); - } + getChild("TexScaleU")->setTentative( LLSD(diff_scale_tentative)); + getChild("shinyScaleU")->setTentative(LLSD(spec_scale_tentative)); + getChild("bumpyScaleU")->setTentative(LLSD(norm_scale_tentative)); + } - { - bool identical_diff_scale_t = false; - bool identical_spec_scale_t = false; - bool identical_norm_scale_t = false; + { + bool identical_diff_scale_t = false; + bool identical_spec_scale_t = false; + bool identical_norm_scale_t = false; - F32 diff_scale_t = 1.f; - F32 spec_scale_t = 1.f; - F32 norm_scale_t = 1.f; + F32 diff_scale_t = 1.f; + F32 spec_scale_t = 1.f; + F32 norm_scale_t = 1.f; - LLSelectedTE::getScaleT(diff_scale_t, identical_diff_scale_t); - LLSelectedTEMaterial::getSpecularRepeatY(spec_scale_t, identical_spec_scale_t); - LLSelectedTEMaterial::getNormalRepeatY(norm_scale_t, identical_norm_scale_t); + LLSelectedTE::getScaleT(diff_scale_t, identical_diff_scale_t); + LLSelectedTEMaterial::getSpecularRepeatY(spec_scale_t, identical_spec_scale_t); + LLSelectedTEMaterial::getNormalRepeatY(norm_scale_t, identical_norm_scale_t); - diff_scale_t = editable ? diff_scale_t : 1.0f; - diff_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; + diff_scale_t = editable ? diff_scale_t : 1.0f; + diff_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; - norm_scale_t = editable ? norm_scale_t : 1.0f; - norm_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; + norm_scale_t = editable ? norm_scale_t : 1.0f; + norm_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; - spec_scale_t = editable ? spec_scale_t : 1.0f; - spec_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; + spec_scale_t = editable ? spec_scale_t : 1.0f; + spec_scale_t *= identical_planar_texgen ? 2.0f : 1.0f; - BOOL diff_scale_tentative = !identical_diff_scale_t; - BOOL norm_scale_tentative = !identical_norm_scale_t; - BOOL spec_scale_tentative = !identical_spec_scale_t; + BOOL diff_scale_tentative = !identical_diff_scale_t; + BOOL norm_scale_tentative = !identical_norm_scale_t; + BOOL spec_scale_tentative = !identical_spec_scale_t; getChildView("TexScaleV")->setEnabled(editable && has_material); getChildView("shinyScaleV")->setEnabled(editable && has_material && specmap_id.notNull()); getChildView("bumpyScaleV")->setEnabled(editable && has_material && normmap_id.notNull()); - if (force_set_values) - { - getChild("TexScaleV")->forceSetValue(diff_scale_t); - } - else - { - getChild("TexScaleV")->setValue(diff_scale_t); - } - getChild("shinyScaleV")->setValue(norm_scale_t); - getChild("bumpyScaleV")->setValue(spec_scale_t); - - getChild("TexScaleV")->setTentative(LLSD(diff_scale_tentative)); - getChild("shinyScaleV")->setTentative(LLSD(norm_scale_tentative)); - getChild("bumpyScaleV")->setTentative(LLSD(spec_scale_tentative)); - } - - // Texture offset - { - bool identical_diff_offset_s = false; - bool identical_norm_offset_s = false; - bool identical_spec_offset_s = false; - - F32 diff_offset_s = 0.0f; - F32 norm_offset_s = 0.0f; - F32 spec_offset_s = 0.0f; - - LLSelectedTE::getOffsetS(diff_offset_s, identical_diff_offset_s); - LLSelectedTEMaterial::getNormalOffsetX(norm_offset_s, identical_norm_offset_s); - LLSelectedTEMaterial::getSpecularOffsetX(spec_offset_s, identical_spec_offset_s); - - BOOL diff_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_s); - BOOL norm_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_s); - BOOL spec_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_s); - - getChild("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f); - getChild("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f); - getChild("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f); - - getChild("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative)); - getChild("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative)); - getChild("bumpyOffsetU")->setTentative(LLSD(spec_offset_u_tentative)); + if (force_set_values) + { + getChild("TexScaleV")->forceSetValue(diff_scale_t); + } + else + { + getChild("TexScaleV")->setValue(diff_scale_t); + } + getChild("shinyScaleV")->setValue(norm_scale_t); + getChild("bumpyScaleV")->setValue(spec_scale_t); + + getChild("TexScaleV")->setTentative(LLSD(diff_scale_tentative)); + getChild("shinyScaleV")->setTentative(LLSD(norm_scale_tentative)); + getChild("bumpyScaleV")->setTentative(LLSD(spec_scale_tentative)); + } + + // Texture offset + { + bool identical_diff_offset_s = false; + bool identical_norm_offset_s = false; + bool identical_spec_offset_s = false; + + F32 diff_offset_s = 0.0f; + F32 norm_offset_s = 0.0f; + F32 spec_offset_s = 0.0f; + + LLSelectedTE::getOffsetS(diff_offset_s, identical_diff_offset_s); + LLSelectedTEMaterial::getNormalOffsetX(norm_offset_s, identical_norm_offset_s); + LLSelectedTEMaterial::getSpecularOffsetX(spec_offset_s, identical_spec_offset_s); + + BOOL diff_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_s); + BOOL norm_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_s); + BOOL spec_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_s); + + getChild("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f); + getChild("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f); + getChild("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f); + + getChild("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative)); + getChild("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative)); + getChild("bumpyOffsetU")->setTentative(LLSD(spec_offset_u_tentative)); getChildView("TexOffsetU")->setEnabled(editable && has_material); getChildView("shinyOffsetU")->setEnabled(editable && has_material && specmap_id.notNull()); getChildView("bumpyOffsetU")->setEnabled(editable && has_material && normmap_id.notNull()); - } + } + + { + bool identical_diff_offset_t = false; + bool identical_norm_offset_t = false; + bool identical_spec_offset_t = false; - { - bool identical_diff_offset_t = false; - bool identical_norm_offset_t = false; - bool identical_spec_offset_t = false; + F32 diff_offset_t = 0.0f; + F32 norm_offset_t = 0.0f; + F32 spec_offset_t = 0.0f; - F32 diff_offset_t = 0.0f; - F32 norm_offset_t = 0.0f; - F32 spec_offset_t = 0.0f; + LLSelectedTE::getOffsetT(diff_offset_t, identical_diff_offset_t); + LLSelectedTEMaterial::getNormalOffsetY(norm_offset_t, identical_norm_offset_t); + LLSelectedTEMaterial::getSpecularOffsetY(spec_offset_t, identical_spec_offset_t); - LLSelectedTE::getOffsetT(diff_offset_t, identical_diff_offset_t); - LLSelectedTEMaterial::getNormalOffsetY(norm_offset_t, identical_norm_offset_t); - LLSelectedTEMaterial::getSpecularOffsetY(spec_offset_t, identical_spec_offset_t); - - BOOL diff_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_t); - BOOL norm_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_t); - BOOL spec_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_t); + BOOL diff_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_t); + BOOL norm_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_t); + BOOL spec_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_t); - getChild("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f); - getChild("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f); - getChild("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f); + getChild("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f); + getChild("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f); + getChild("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f); - getChild("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative)); - getChild("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative)); - getChild("bumpyOffsetV")->setTentative(LLSD(spec_offset_v_tentative)); + getChild("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative)); + getChild("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative)); + getChild("bumpyOffsetV")->setTentative(LLSD(spec_offset_v_tentative)); getChildView("TexOffsetV")->setEnabled(editable && has_material); getChildView("shinyOffsetV")->setEnabled(editable && has_material && specmap_id.notNull()); getChildView("bumpyOffsetV")->setEnabled(editable && has_material && normmap_id.notNull()); - } + } - // Texture rotation - { - bool identical_diff_rotation = false; - bool identical_norm_rotation = false; - bool identical_spec_rotation = false; + // Texture rotation + { + bool identical_diff_rotation = false; + bool identical_norm_rotation = false; + bool identical_spec_rotation = false; - F32 diff_rotation = 0.f; - F32 norm_rotation = 0.f; - F32 spec_rotation = 0.f; + F32 diff_rotation = 0.f; + F32 norm_rotation = 0.f; + F32 spec_rotation = 0.f; - LLSelectedTE::getRotation(diff_rotation,identical_diff_rotation); - LLSelectedTEMaterial::getSpecularRotation(spec_rotation,identical_spec_rotation); - LLSelectedTEMaterial::getNormalRotation(norm_rotation,identical_norm_rotation); + LLSelectedTE::getRotation(diff_rotation,identical_diff_rotation); + LLSelectedTEMaterial::getSpecularRotation(spec_rotation,identical_spec_rotation); + LLSelectedTEMaterial::getNormalRotation(norm_rotation,identical_norm_rotation); - BOOL diff_rot_tentative = !(align_planar ? identical_planar_aligned : identical_diff_rotation); - BOOL norm_rot_tentative = !(align_planar ? identical_planar_aligned : identical_norm_rotation); - BOOL spec_rot_tentative = !(align_planar ? identical_planar_aligned : identical_spec_rotation); + BOOL diff_rot_tentative = !(align_planar ? identical_planar_aligned : identical_diff_rotation); + BOOL norm_rot_tentative = !(align_planar ? identical_planar_aligned : identical_norm_rotation); + BOOL spec_rot_tentative = !(align_planar ? identical_planar_aligned : identical_spec_rotation); - F32 diff_rot_deg = diff_rotation * RAD_TO_DEG; - F32 norm_rot_deg = norm_rotation * RAD_TO_DEG; - F32 spec_rot_deg = spec_rotation * RAD_TO_DEG; + F32 diff_rot_deg = diff_rotation * RAD_TO_DEG; + F32 norm_rot_deg = norm_rotation * RAD_TO_DEG; + F32 spec_rot_deg = spec_rotation * RAD_TO_DEG; getChildView("TexRot")->setEnabled(editable && has_material); getChildView("shinyRot")->setEnabled(editable && has_material && specmap_id.notNull()); getChildView("bumpyRot")->setEnabled(editable && has_material && normmap_id.notNull()); - getChild("TexRot")->setTentative(diff_rot_tentative); - getChild("shinyRot")->setTentative(LLSD(norm_rot_tentative)); - getChild("bumpyRot")->setTentative(LLSD(spec_rot_tentative)); - - getChild("TexRot")->setValue( editable ? diff_rot_deg : 0.0f); - getChild("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f); - getChild("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f); - } - - { - F32 glow = 0.f; - bool identical_glow = false; - LLSelectedTE::getGlow(glow,identical_glow); - getChild("glow")->setValue(glow); - getChild("glow")->setTentative(!identical_glow); - getChildView("glow")->setEnabled(editable); - getChildView("glow label")->setEnabled(editable); - } - - { - LLCtrlSelectionInterface* combobox_texgen = childGetSelectionInterface("combobox texgen"); - if (combobox_texgen) - { - // Maps from enum to combobox entry index - combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1); - } - else - { - LL_WARNS() << "failed childGetSelectionInterface for 'combobox texgen'" << LL_ENDL; - } - - getChildView("combobox texgen")->setEnabled(editable); - getChild("combobox texgen")->setTentative(!identical); - getChildView("tex gen")->setEnabled(editable); - } - - { - U8 fullbright_flag = 0; - bool identical_fullbright = false; - - LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright); - - getChild("checkbox fullbright")->setValue((S32)(fullbright_flag != 0)); - getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material); - getChild("checkbox fullbright")->setTentative(!identical_fullbright); + getChild("TexRot")->setTentative(diff_rot_tentative); + getChild("shinyRot")->setTentative(LLSD(norm_rot_tentative)); + getChild("bumpyRot")->setTentative(LLSD(spec_rot_tentative)); + + getChild("TexRot")->setValue( editable ? diff_rot_deg : 0.0f); + getChild("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f); + getChild("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f); + } + + { + F32 glow = 0.f; + bool identical_glow = false; + LLSelectedTE::getGlow(glow,identical_glow); + getChild("glow")->setValue(glow); + getChild("glow")->setTentative(!identical_glow); + getChildView("glow")->setEnabled(editable); + getChildView("glow label")->setEnabled(editable); + } + + { + LLCtrlSelectionInterface* combobox_texgen = childGetSelectionInterface("combobox texgen"); + if (combobox_texgen) + { + // Maps from enum to combobox entry index + combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1); + } + else + { + LL_WARNS() << "failed childGetSelectionInterface for 'combobox texgen'" << LL_ENDL; + } + + getChildView("combobox texgen")->setEnabled(editable); + getChild("combobox texgen")->setTentative(!identical); + getChildView("tex gen")->setEnabled(editable); + } + + { + U8 fullbright_flag = 0; + bool identical_fullbright = false; + + LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright); + + getChild("checkbox fullbright")->setValue((S32)(fullbright_flag != 0)); + getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material); + getChild("checkbox fullbright")->setTentative(!identical_fullbright); mComboMatMedia->setEnabledByValue("Materials", !has_pbr_material); - } - - // Repeats per meter - { - F32 repeats_diff = 1.f; - F32 repeats_norm = 1.f; - F32 repeats_spec = 1.f; - - bool identical_diff_repeats = false; - bool identical_norm_repeats = false; - bool identical_spec_repeats = false; - - LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats); - LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats); - LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats); - - LLComboBox* mComboTexGen = getChild("combobox texgen"); - if (mComboTexGen) - { - S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0; + } + + // Repeats per meter + { + F32 repeats_diff = 1.f; + F32 repeats_norm = 1.f; + F32 repeats_spec = 1.f; + + bool identical_diff_repeats = false; + bool identical_norm_repeats = false; + bool identical_spec_repeats = false; + + LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats); + LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats); + LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats); + + LLComboBox* mComboTexGen = getChild("combobox texgen"); + if (mComboTexGen) + { + S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0; bool enabled = editable && (index != 1); bool identical_repeats = true; S32 material_selection = mComboMatMedia->getCurrentIndex(); - F32 repeats = 1.0f; + F32 repeats = 1.0f; U32 material_type = MATTYPE_DIFFUSE; if (material_selection == MATMEDIA_MATERIAL) @@ -1715,195 +1715,195 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) break; } - BOOL repeats_tentative = !identical_repeats; - - LLSpinCtrl* rpt_ctrl = getChild("rptctrl"); - if (force_set_values) - { - //onCommit, previosly edited element updates related ones - rpt_ctrl->forceSetValue(editable ? repeats : 1.0f); - } - else - { - rpt_ctrl->setValue(editable ? repeats : 1.0f); - } - rpt_ctrl->setTentative(LLSD(repeats_tentative)); + BOOL repeats_tentative = !identical_repeats; + + LLSpinCtrl* rpt_ctrl = getChild("rptctrl"); + if (force_set_values) + { + //onCommit, previosly edited element updates related ones + rpt_ctrl->forceSetValue(editable ? repeats : 1.0f); + } + else + { + rpt_ctrl->setValue(editable ? repeats : 1.0f); + } + rpt_ctrl->setTentative(LLSD(repeats_tentative)); rpt_ctrl->setEnabled(has_material && !identical_planar_texgen && enabled); - } - } + } + } - // Materials - { - LLMaterialPtr material; - LLSelectedTEMaterial::getCurrent(material, identical); + // Materials + { + LLMaterialPtr material; + LLSelectedTEMaterial::getCurrent(material, identical); if (material && editable) - { - LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL; - - // Alpha - LLCtrlSelectionInterface* combobox_alphamode = - childGetSelectionInterface("combobox alphamode"); - if (combobox_alphamode) - { - U32 alpha_mode = material->getDiffuseAlphaMode(); - - if (transparency > 0.f) - { //it is invalid to have any alpha mode other than blend if transparency is greater than zero ... - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (!mIsAlpha) - { // ... unless there is no alpha channel in the texture, in which case alpha mode MUST ebe none - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - } - - combobox_alphamode->selectNthItem(alpha_mode); - } - else - { - LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; - } - getChild("maskcutoff")->setValue(material->getAlphaMaskCutoff()); - updateAlphaControls(); - - identical_planar_texgen = isIdenticalPlanarTexgen(); - - // Shiny (specular) - F32 offset_x, offset_y, repeat_x, repeat_y, rot; - LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); - texture_ctrl->setImageAssetID(material->getSpecularID()); - - if (!material->getSpecularID().isNull() && (shiny == SHINY_TEXTURE)) - { - material->getSpecularOffset(offset_x,offset_y); - material->getSpecularRepeat(repeat_x,repeat_y); - - if (identical_planar_texgen) - { - repeat_x *= 2.0f; - repeat_y *= 2.0f; - } - - rot = material->getSpecularRotation(); - getChild("shinyScaleU")->setValue(repeat_x); - getChild("shinyScaleV")->setValue(repeat_y); - getChild("shinyRot")->setValue(rot*RAD_TO_DEG); - getChild("shinyOffsetU")->setValue(offset_x); - getChild("shinyOffsetV")->setValue(offset_y); - getChild("glossiness")->setValue(material->getSpecularLightExponent()); - getChild("environment")->setValue(material->getEnvironmentIntensity()); + { + LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL; + + // Alpha + LLCtrlSelectionInterface* combobox_alphamode = + childGetSelectionInterface("combobox alphamode"); + if (combobox_alphamode) + { + U32 alpha_mode = material->getDiffuseAlphaMode(); + + if (transparency > 0.f) + { //it is invalid to have any alpha mode other than blend if transparency is greater than zero ... + alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + + if (!mIsAlpha) + { // ... unless there is no alpha channel in the texture, in which case alpha mode MUST ebe none + alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + } + + combobox_alphamode->selectNthItem(alpha_mode); + } + else + { + LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; + } + getChild("maskcutoff")->setValue(material->getAlphaMaskCutoff()); + updateAlphaControls(); + + identical_planar_texgen = isIdenticalPlanarTexgen(); + + // Shiny (specular) + F32 offset_x, offset_y, repeat_x, repeat_y, rot; + LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); + texture_ctrl->setImageAssetID(material->getSpecularID()); + + if (!material->getSpecularID().isNull() && (shiny == SHINY_TEXTURE)) + { + material->getSpecularOffset(offset_x,offset_y); + material->getSpecularRepeat(repeat_x,repeat_y); + + if (identical_planar_texgen) + { + repeat_x *= 2.0f; + repeat_y *= 2.0f; + } + + rot = material->getSpecularRotation(); + getChild("shinyScaleU")->setValue(repeat_x); + getChild("shinyScaleV")->setValue(repeat_y); + getChild("shinyRot")->setValue(rot*RAD_TO_DEG); + getChild("shinyOffsetU")->setValue(offset_x); + getChild("shinyOffsetV")->setValue(offset_y); + getChild("glossiness")->setValue(material->getSpecularLightExponent()); + getChild("environment")->setValue(material->getEnvironmentIntensity()); getChild("mirror")->setValue(material->getEnvironmentIntensity()); - updateShinyControls(!material->getSpecularID().isNull(), true); - } - - // Assert desired colorswatch color to match material AFTER updateShinyControls - // to avoid getting overwritten with the default on some UI state changes. - // - if (!material->getSpecularID().isNull()) - { - LLColorSwatchCtrl* shiny_swatch = getChild("shinycolorswatch"); - LLColor4 new_color = material->getSpecularLightColor(); - LLColor4 old_color = shiny_swatch->get(); - - shiny_swatch->setOriginal(new_color); - shiny_swatch->set(new_color, force_set_values || old_color != new_color || !editable); - } - - // Bumpy (normal) - texture_ctrl = getChild("bumpytexture control"); - texture_ctrl->setImageAssetID(material->getNormalID()); - - if (!material->getNormalID().isNull()) - { - material->getNormalOffset(offset_x,offset_y); - material->getNormalRepeat(repeat_x,repeat_y); - - if (identical_planar_texgen) - { - repeat_x *= 2.0f; - repeat_y *= 2.0f; - } - - rot = material->getNormalRotation(); - getChild("bumpyScaleU")->setValue(repeat_x); - getChild("bumpyScaleV")->setValue(repeat_y); - getChild("bumpyRot")->setValue(rot*RAD_TO_DEG); - getChild("bumpyOffsetU")->setValue(offset_x); - getChild("bumpyOffsetV")->setValue(offset_y); - - updateBumpyControls(!material->getNormalID().isNull(), true); - } - } - } + updateShinyControls(!material->getSpecularID().isNull(), true); + } + + // Assert desired colorswatch color to match material AFTER updateShinyControls + // to avoid getting overwritten with the default on some UI state changes. + // + if (!material->getSpecularID().isNull()) + { + LLColorSwatchCtrl* shiny_swatch = getChild("shinycolorswatch"); + LLColor4 new_color = material->getSpecularLightColor(); + LLColor4 old_color = shiny_swatch->get(); + + shiny_swatch->setOriginal(new_color); + shiny_swatch->set(new_color, force_set_values || old_color != new_color || !editable); + } + + // Bumpy (normal) + texture_ctrl = getChild("bumpytexture control"); + texture_ctrl->setImageAssetID(material->getNormalID()); + + if (!material->getNormalID().isNull()) + { + material->getNormalOffset(offset_x,offset_y); + material->getNormalRepeat(repeat_x,repeat_y); + + if (identical_planar_texgen) + { + repeat_x *= 2.0f; + repeat_y *= 2.0f; + } + + rot = material->getNormalRotation(); + getChild("bumpyScaleU")->setValue(repeat_x); + getChild("bumpyScaleV")->setValue(repeat_y); + getChild("bumpyRot")->setValue(rot*RAD_TO_DEG); + getChild("bumpyOffsetU")->setValue(offset_x); + getChild("bumpyOffsetV")->setValue(offset_y); + + updateBumpyControls(!material->getNormalID().isNull(), true); + } + } + } S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (selected_count == 1); mMenuClipboardColor->setEnabled(editable && single_volume); - // Set variable values for numeric expressions - LLCalc* calcp = LLCalc::getInstance(); - calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal()); - calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal()); - calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal()); - calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal()); - calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal()); - calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal()); - calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal()); - } - else - { - // Disable all UICtrls - clearCtrls(); - - // Disable non-UICtrls - LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); + // Set variable values for numeric expressions + LLCalc* calcp = LLCalc::getInstance(); + calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal()); + calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal()); + calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal()); + calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal()); + calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal()); + calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal()); + calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal()); + } + else + { + // Disable all UICtrls + clearCtrls(); + + // Disable non-UICtrls + LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); if (pbr_ctrl) { pbr_ctrl->setImageAssetID(LLUUID::null); pbr_ctrl->setEnabled(FALSE); } - LLTextureCtrl* texture_ctrl = getChild("texture control"); - if (texture_ctrl) - { - texture_ctrl->setImageAssetID( LLUUID::null ); - texture_ctrl->setEnabled( FALSE ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl. -// texture_ctrl->setValid(FALSE); - } - LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); - if (mColorSwatch) - { - mColorSwatch->setEnabled( FALSE ); - mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); - mColorSwatch->setValid(FALSE); - } - LLRadioGroup* radio_mat_type = getChild("radio_material_type"); - if (radio_mat_type) - { - radio_mat_type->setSelectedIndex(0); - } - getChildView("color trans")->setEnabled(FALSE); - getChildView("rptctrl")->setEnabled(FALSE); - getChildView("tex gen")->setEnabled(FALSE); - getChildView("label shininess")->setEnabled(FALSE); - getChildView("label bumpiness")->setEnabled(FALSE); - getChildView("button align")->setEnabled(FALSE); + LLTextureCtrl* texture_ctrl = getChild("texture control"); + if (texture_ctrl) + { + texture_ctrl->setImageAssetID( LLUUID::null ); + texture_ctrl->setEnabled( FALSE ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl. +// texture_ctrl->setValid(FALSE); + } + LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); + if (mColorSwatch) + { + mColorSwatch->setEnabled( FALSE ); + mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); + mColorSwatch->setValid(FALSE); + } + LLRadioGroup* radio_mat_type = getChild("radio_material_type"); + if (radio_mat_type) + { + radio_mat_type->setSelectedIndex(0); + } + getChildView("color trans")->setEnabled(FALSE); + getChildView("rptctrl")->setEnabled(FALSE); + getChildView("tex gen")->setEnabled(FALSE); + getChildView("label shininess")->setEnabled(FALSE); + getChildView("label bumpiness")->setEnabled(FALSE); + getChildView("button align")->setEnabled(FALSE); getChildView("pbr_from_inventory")->setEnabled(FALSE); getChildView("edit_selected_pbr")->setEnabled(FALSE); getChildView("save_selected_pbr")->setEnabled(FALSE); - - updateVisibility(); - // Set variable values for numeric expressions - LLCalc* calcp = LLCalc::getInstance(); - calcp->clearVar(LLCalc::TEX_U_SCALE); - calcp->clearVar(LLCalc::TEX_V_SCALE); - calcp->clearVar(LLCalc::TEX_U_OFFSET); - calcp->clearVar(LLCalc::TEX_V_OFFSET); - calcp->clearVar(LLCalc::TEX_ROTATION); - calcp->clearVar(LLCalc::TEX_TRANSPARENCY); - calcp->clearVar(LLCalc::TEX_GLOW); - } + updateVisibility(); + + // Set variable values for numeric expressions + LLCalc* calcp = LLCalc::getInstance(); + calcp->clearVar(LLCalc::TEX_U_SCALE); + calcp->clearVar(LLCalc::TEX_V_SCALE); + calcp->clearVar(LLCalc::TEX_U_OFFSET); + calcp->clearVar(LLCalc::TEX_V_OFFSET); + calcp->clearVar(LLCalc::TEX_ROTATION); + calcp->clearVar(LLCalc::TEX_TRANSPARENCY); + calcp->clearVar(LLCalc::TEX_GLOW); + } } // One-off listener that updates the build floater UI when the agent inventory adds or removes an item @@ -1912,7 +1912,7 @@ class PBRPickerAgentListener : public LLInventoryObserver protected: bool mChangePending = true; public: - PBRPickerAgentListener() : LLInventoryObserver() + PBRPickerAgentListener() : LLInventoryObserver() { gInventory.addObserver(this); } @@ -1922,7 +1922,7 @@ public: return mChangePending; } - void changed(U32 mask) override + void changed(U32 mask) override { if (!(mask & (ADD | REMOVE))) { @@ -2092,8 +2092,8 @@ void LLPanelFace::updateVisibilityGLTF(LLViewerObject* objectp /*= nullptr */) void LLPanelFace::updateCopyTexButton() { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify() - && !objectp->isPermanentEnforced() && !objectp->isInventoryPending() + mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify() + && !objectp->isPermanentEnforced() && !objectp->isInventoryPending() && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1) && LLMaterialEditor::canClipboardObjectsMaterial()); std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options"); @@ -2102,8 +2102,8 @@ void LLPanelFace::updateCopyTexButton() void LLPanelFace::refresh() { - LL_DEBUGS("Materials") << LL_ENDL; - getState(); + LL_DEBUGS("Materials") << LL_ENDL; + getState(); } void LLPanelFace::refreshMedia() @@ -2224,7 +2224,7 @@ void LLPanelFace::refreshMedia() // initial media title is the media URL (until we get the name) media_title = media_data_get.getHomeURL(); } - // else all faces might be empty. + // else all faces might be empty. } else // there' re Different Medias' been set on on the faces. { @@ -2296,19 +2296,19 @@ void LLPanelFace::onMaterialOverrideReceived(const LLUUID& object_id, S32 side) // void LLPanelFace::navigateToTitleMedia( const std::string url ) { - std::string multi_media_info_str = LLTrans::getString("Multiple Media"); - if (url.empty() || multi_media_info_str == url) - { - // nothing to show - mNeedMediaTitle = false; - } - else if (mTitleMedia) - { - LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); - // check if url changed or if we need a new media source - if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL) - { - mTitleMedia->navigateTo( url ); + std::string multi_media_info_str = LLTrans::getString("Multiple Media"); + if (url.empty() || multi_media_info_str == url) + { + // nothing to show + mNeedMediaTitle = false; + } + else if (mTitleMedia) + { + LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin(); + // check if url changed or if we need a new media source + if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL) + { + mTitleMedia->navigateTo( url ); LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mTitleMedia->getTextureID()); if (impl) @@ -2316,11 +2316,11 @@ void LLPanelFace::navigateToTitleMedia( const std::string url ) // if it's a page with a movie, we don't want to hear it impl->setVolume(0); }; - } + } - // flag that we need to update the title (even if no request were made) - mNeedMediaTitle = true; - } + // flag that we need to update the title (even if no request were made) + mNeedMediaTitle = true; + } } bool LLPanelFace::selectedMediaEditable() @@ -2379,7 +2379,7 @@ void LLPanelFace::updateMediaSettings() const LLMediaEntry default_media_data; - // controls + // controls U8 value_u8 = default_media_data.getControls(); struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 > { @@ -2868,58 +2868,58 @@ void LLPanelFace::updateMediaTitle() // static F32 LLPanelFace::valueGlow(LLViewerObject* object, S32 face) { - return (F32)(object->getTE(face)->getGlow()); + return (F32)(object->getTE(face)->getGlow()); } void LLPanelFace::onCommitColor(const LLSD& data) { - sendColor(); + sendColor(); } void LLPanelFace::onCommitShinyColor(const LLSD& data) { - LLSelectedTEMaterial::setSpecularLightColor(this, getChild("shinycolorswatch")->get()); + LLSelectedTEMaterial::setSpecularLightColor(this, getChild("shinycolorswatch")->get()); } void LLPanelFace::onCommitAlpha(const LLSD& data) { - sendAlpha(); + sendAlpha(); } void LLPanelFace::onCancelColor(const LLSD& data) { - LLSelectMgr::getInstance()->selectionRevertColors(); + LLSelectMgr::getInstance()->selectionRevertColors(); } void LLPanelFace::onCancelShinyColor(const LLSD& data) { - LLSelectMgr::getInstance()->selectionRevertShinyColors(); + LLSelectMgr::getInstance()->selectionRevertShinyColors(); } void LLPanelFace::onSelectColor(const LLSD& data) { - LLSelectMgr::getInstance()->saveSelectedObjectColors(); - sendColor(); + LLSelectMgr::getInstance()->saveSelectedObjectColors(); + sendColor(); } void LLPanelFace::onSelectShinyColor(const LLSD& data) { - LLSelectedTEMaterial::setSpecularLightColor(this, getChild("shinycolorswatch")->get()); - LLSelectMgr::getInstance()->saveSelectedShinyColors(); + LLSelectedTEMaterial::setSpecularLightColor(this, getChild("shinycolorswatch")->get()); + LLSelectMgr::getInstance()->saveSelectedShinyColors(); } // static void LLPanelFace::onCommitMaterialsMedia(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - // Force to default states to side-step problems with menu contents - // and generally reflecting old state when switching tabs or objects - // - self->updateShinyControls(false,true); - self->updateBumpyControls(false,true); - self->updateUI(); - self->refreshMedia(); + LLPanelFace* self = (LLPanelFace*) userdata; + // Force to default states to side-step problems with menu contents + // and generally reflecting old state when switching tabs or objects + // + self->updateShinyControls(false,true); + self->updateBumpyControls(false,true); + self->updateUI(); + self->refreshMedia(); } void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */) @@ -2928,18 +2928,18 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */) LLRadioGroup* radio_pbr_type = findChild("radio_pbr_type"); LLComboBox* combo_shininess = findChild("combobox shininess"); LLComboBox* combo_bumpiness = findChild("combobox bumpiness"); - if (!radio_mat_type || !radio_pbr_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness) - { - LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL; - return; - } - U32 materials_media = mComboMatMedia->getCurrentIndex(); - U32 material_type = radio_mat_type->getSelectedIndex(); - bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled(); + if (!radio_mat_type || !radio_pbr_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness) + { + LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL; + return; + } + U32 materials_media = mComboMatMedia->getCurrentIndex(); + U32 material_type = radio_mat_type->getSelectedIndex(); + bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled(); bool show_material = materials_media == MATMEDIA_MATERIAL; - bool show_texture = (show_media || (show_material && (material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled())); - bool show_bumpiness = show_material && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled(); - bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); + bool show_texture = (show_media || (show_material && (material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled())); + bool show_bumpiness = show_material && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled(); + bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled(); const U32 pbr_type = findChild("radio_pbr_type")->getSelectedIndex(); const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type); @@ -2953,62 +2953,62 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */) getChildView("combobox texgen")->setVisible(show_material || show_media || show_pbr_asset); getChildView("button align textures")->setVisible(show_material || show_media); - // Media controls + // Media controls mTitleMediaText->setVisible(show_media); - getChildView("add_media")->setVisible(show_media); - getChildView("delete_media")->setVisible(show_media); - getChildView("button align")->setVisible(show_media); - - // Diffuse texture controls - getChildView("texture control")->setVisible(show_texture && show_material); - getChildView("label alphamode")->setVisible(show_texture && show_material); - getChildView("combobox alphamode")->setVisible(show_texture && show_material); - getChildView("label maskcutoff")->setVisible(false); - getChildView("maskcutoff")->setVisible(false); - if (show_texture && show_material) - { - updateAlphaControls(); - } + getChildView("add_media")->setVisible(show_media); + getChildView("delete_media")->setVisible(show_media); + getChildView("button align")->setVisible(show_media); + + // Diffuse texture controls + getChildView("texture control")->setVisible(show_texture && show_material); + getChildView("label alphamode")->setVisible(show_texture && show_material); + getChildView("combobox alphamode")->setVisible(show_texture && show_material); + getChildView("label maskcutoff")->setVisible(false); + getChildView("maskcutoff")->setVisible(false); + if (show_texture && show_material) + { + updateAlphaControls(); + } // texture scale and position controls - getChildView("TexScaleU")->setVisible(show_texture); - getChildView("TexScaleV")->setVisible(show_texture); - getChildView("TexRot")->setVisible(show_texture); - getChildView("TexOffsetU")->setVisible(show_texture); - getChildView("TexOffsetV")->setVisible(show_texture); - - // Specular map controls - getChildView("shinytexture control")->setVisible(show_shininess); - getChildView("combobox shininess")->setVisible(show_shininess); - getChildView("label shininess")->setVisible(show_shininess); - getChildView("label glossiness")->setVisible(false); - getChildView("glossiness")->setVisible(false); - getChildView("label environment")->setVisible(false); - getChildView("environment")->setVisible(false); - getChildView("label shinycolor")->setVisible(false); - getChildView("shinycolorswatch")->setVisible(false); - if (show_shininess) - { - updateShinyControls(); - } - getChildView("shinyScaleU")->setVisible(show_shininess); - getChildView("shinyScaleV")->setVisible(show_shininess); - getChildView("shinyRot")->setVisible(show_shininess); - getChildView("shinyOffsetU")->setVisible(show_shininess); - getChildView("shinyOffsetV")->setVisible(show_shininess); - - // Normal map controls - if (show_bumpiness) - { - updateBumpyControls(); - } - getChildView("bumpytexture control")->setVisible(show_bumpiness); - getChildView("combobox bumpiness")->setVisible(show_bumpiness); - getChildView("label bumpiness")->setVisible(show_bumpiness); - getChildView("bumpyScaleU")->setVisible(show_bumpiness); - getChildView("bumpyScaleV")->setVisible(show_bumpiness); - getChildView("bumpyRot")->setVisible(show_bumpiness); - getChildView("bumpyOffsetU")->setVisible(show_bumpiness); - getChildView("bumpyOffsetV")->setVisible(show_bumpiness); + getChildView("TexScaleU")->setVisible(show_texture); + getChildView("TexScaleV")->setVisible(show_texture); + getChildView("TexRot")->setVisible(show_texture); + getChildView("TexOffsetU")->setVisible(show_texture); + getChildView("TexOffsetV")->setVisible(show_texture); + + // Specular map controls + getChildView("shinytexture control")->setVisible(show_shininess); + getChildView("combobox shininess")->setVisible(show_shininess); + getChildView("label shininess")->setVisible(show_shininess); + getChildView("label glossiness")->setVisible(false); + getChildView("glossiness")->setVisible(false); + getChildView("label environment")->setVisible(false); + getChildView("environment")->setVisible(false); + getChildView("label shinycolor")->setVisible(false); + getChildView("shinycolorswatch")->setVisible(false); + if (show_shininess) + { + updateShinyControls(); + } + getChildView("shinyScaleU")->setVisible(show_shininess); + getChildView("shinyScaleV")->setVisible(show_shininess); + getChildView("shinyRot")->setVisible(show_shininess); + getChildView("shinyOffsetU")->setVisible(show_shininess); + getChildView("shinyOffsetV")->setVisible(show_shininess); + + // Normal map controls + if (show_bumpiness) + { + updateBumpyControls(); + } + getChildView("bumpytexture control")->setVisible(show_bumpiness); + getChildView("combobox bumpiness")->setVisible(show_bumpiness); + getChildView("label bumpiness")->setVisible(show_bumpiness); + getChildView("bumpyScaleU")->setVisible(show_bumpiness); + getChildView("bumpyScaleV")->setVisible(show_bumpiness); + getChildView("bumpyRot")->setVisible(show_bumpiness); + getChildView("bumpyOffsetU")->setVisible(show_bumpiness); + getChildView("bumpyOffsetV")->setVisible(show_bumpiness); getChild("rptctrl")->setVisible(show_material || show_media); @@ -3020,11 +3020,11 @@ void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */) void LLPanelFace::onCommitMaterialType(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; - // Force to default states to side-step problems with menu contents - // and generally reflecting old state when switching tabs or objects - // - self->updateShinyControls(false,true); - self->updateBumpyControls(false,true); + // Force to default states to side-step problems with menu contents + // and generally reflecting old state when switching tabs or objects + // + self->updateShinyControls(false,true); + self->updateBumpyControls(false,true); self->updateUI(); } @@ -3041,149 +3041,149 @@ void LLPanelFace::onCommitPbrType(LLUICtrl* ctrl, void* userdata) // static void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; + LLPanelFace* self = (LLPanelFace*) userdata; - LLComboBox* mComboBumpiness = self->getChild("combobox bumpiness"); - if(!mComboBumpiness) - return; + LLComboBox* mComboBumpiness = self->getChild("combobox bumpiness"); + if(!mComboBumpiness) + return; - U32 bumpiness = mComboBumpiness->getCurrentIndex(); + U32 bumpiness = mComboBumpiness->getCurrentIndex(); - self->sendBump(bumpiness); + self->sendBump(bumpiness); } // static void LLPanelFace::onCommitTexGen(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendTexGen(); + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendTexGen(); } // static void LLPanelFace::updateShinyControls(bool is_setting_texture, bool mess_with_shiny_combobox) { - LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); - LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID(); - LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL; - LLComboBox* comboShiny = getChild("combobox shininess"); - - if(mess_with_shiny_combobox) - { - if (!comboShiny) - { - return; - } - if (!shiny_texture_ID.isNull() && is_setting_texture) - { - if (!comboShiny->itemExists(USE_TEXTURE)) - { - comboShiny->add(USE_TEXTURE); - } - comboShiny->setSimple(USE_TEXTURE); - } - else - { - if (comboShiny->itemExists(USE_TEXTURE)) - { - comboShiny->remove(SHINY_TEXTURE); - comboShiny->selectFirstItem(); - } - } - } - else - { - if (shiny_texture_ID.isNull() && comboShiny && comboShiny->itemExists(USE_TEXTURE)) - { - comboShiny->remove(SHINY_TEXTURE); - comboShiny->selectFirstItem(); - } - } - - - LLRadioGroup* radio_mat_type = getChild("radio_material_type"); - U32 materials_media = mComboMatMedia->getCurrentIndex(); - U32 material_type = radio_mat_type->getSelectedIndex(); - bool show_material = (materials_media == MATMEDIA_MATERIAL); - bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); - U32 shiny_value = comboShiny->getCurrentIndex(); - bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture - getChildView("label glossiness")->setVisible(show_shinyctrls); - getChildView("glossiness")->setVisible(show_shinyctrls); - getChildView("label environment")->setVisible(show_shinyctrls); - getChildView("environment")->setVisible(show_shinyctrls); - getChildView("label shinycolor")->setVisible(show_shinyctrls); - getChildView("shinycolorswatch")->setVisible(show_shinyctrls); + LLTextureCtrl* texture_ctrl = getChild("shinytexture control"); + LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID(); + LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL; + LLComboBox* comboShiny = getChild("combobox shininess"); + + if(mess_with_shiny_combobox) + { + if (!comboShiny) + { + return; + } + if (!shiny_texture_ID.isNull() && is_setting_texture) + { + if (!comboShiny->itemExists(USE_TEXTURE)) + { + comboShiny->add(USE_TEXTURE); + } + comboShiny->setSimple(USE_TEXTURE); + } + else + { + if (comboShiny->itemExists(USE_TEXTURE)) + { + comboShiny->remove(SHINY_TEXTURE); + comboShiny->selectFirstItem(); + } + } + } + else + { + if (shiny_texture_ID.isNull() && comboShiny && comboShiny->itemExists(USE_TEXTURE)) + { + comboShiny->remove(SHINY_TEXTURE); + comboShiny->selectFirstItem(); + } + } + + + LLRadioGroup* radio_mat_type = getChild("radio_material_type"); + U32 materials_media = mComboMatMedia->getCurrentIndex(); + U32 material_type = radio_mat_type->getSelectedIndex(); + bool show_material = (materials_media == MATMEDIA_MATERIAL); + bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled(); + U32 shiny_value = comboShiny->getCurrentIndex(); + bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture + getChildView("label glossiness")->setVisible(show_shinyctrls); + getChildView("glossiness")->setVisible(show_shinyctrls); + getChildView("label environment")->setVisible(show_shinyctrls); + getChildView("environment")->setVisible(show_shinyctrls); + getChildView("label shinycolor")->setVisible(show_shinyctrls); + getChildView("shinycolorswatch")->setVisible(show_shinyctrls); } // static void LLPanelFace::updateBumpyControls(bool is_setting_texture, bool mess_with_combobox) { - LLTextureCtrl* texture_ctrl = getChild("bumpytexture control"); - LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID(); - LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL; - LLComboBox* comboBumpy = getChild("combobox bumpiness"); - if (!comboBumpy) - { - return; - } - - if (mess_with_combobox) - { - LLTextureCtrl* texture_ctrl = getChild("bumpytexture control"); - LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID(); - LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL; - - if (!bumpy_texture_ID.isNull() && is_setting_texture) - { - if (!comboBumpy->itemExists(USE_TEXTURE)) - { - comboBumpy->add(USE_TEXTURE); - } - comboBumpy->setSimple(USE_TEXTURE); - } - else - { - if (comboBumpy->itemExists(USE_TEXTURE)) - { - comboBumpy->remove(BUMPY_TEXTURE); - comboBumpy->selectFirstItem(); - } - } - } + LLTextureCtrl* texture_ctrl = getChild("bumpytexture control"); + LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID(); + LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL; + LLComboBox* comboBumpy = getChild("combobox bumpiness"); + if (!comboBumpy) + { + return; + } + + if (mess_with_combobox) + { + LLTextureCtrl* texture_ctrl = getChild("bumpytexture control"); + LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID(); + LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL; + + if (!bumpy_texture_ID.isNull() && is_setting_texture) + { + if (!comboBumpy->itemExists(USE_TEXTURE)) + { + comboBumpy->add(USE_TEXTURE); + } + comboBumpy->setSimple(USE_TEXTURE); + } + else + { + if (comboBumpy->itemExists(USE_TEXTURE)) + { + comboBumpy->remove(BUMPY_TEXTURE); + comboBumpy->selectFirstItem(); + } + } + } } // static void LLPanelFace::onCommitShiny(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; + LLPanelFace* self = (LLPanelFace*) userdata; + + LLComboBox* mComboShininess = self->getChild("combobox shininess"); + if(!mComboShininess) + return; - LLComboBox* mComboShininess = self->getChild("combobox shininess"); - if(!mComboShininess) - return; - - U32 shininess = mComboShininess->getCurrentIndex(); + U32 shininess = mComboShininess->getCurrentIndex(); - self->sendShiny(shininess); + self->sendShiny(shininess); } // static void LLPanelFace::updateAlphaControls() { - LLComboBox* comboAlphaMode = getChild("combobox alphamode"); - if (!comboAlphaMode) - { - return; - } - U32 alpha_value = comboAlphaMode->getCurrentIndex(); - bool show_alphactrls = (alpha_value == ALPHAMODE_MASK); // Alpha masking - + LLComboBox* comboAlphaMode = getChild("combobox alphamode"); + if (!comboAlphaMode) + { + return; + } + U32 alpha_value = comboAlphaMode->getCurrentIndex(); + bool show_alphactrls = (alpha_value == ALPHAMODE_MASK); // Alpha masking + U32 mat_media = MATMEDIA_MATERIAL; if (mComboMatMedia) { mat_media = mComboMatMedia->getCurrentIndex(); } - + U32 mat_type = MATTYPE_DIFFUSE; LLRadioGroup* radio_mat_type = getChild("radio_material_type"); if(radio_mat_type) @@ -3193,31 +3193,31 @@ void LLPanelFace::updateAlphaControls() show_alphactrls = show_alphactrls && (mat_media == MATMEDIA_MATERIAL); show_alphactrls = show_alphactrls && (mat_type == MATTYPE_DIFFUSE); - - getChildView("label maskcutoff")->setVisible(show_alphactrls); - getChildView("maskcutoff")->setVisible(show_alphactrls); + + getChildView("label maskcutoff")->setVisible(show_alphactrls); + getChildView("maskcutoff")->setVisible(show_alphactrls); } // static void LLPanelFace::onCommitAlphaMode(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->updateAlphaControls(); - LLSelectedTEMaterial::setDiffuseAlphaMode(self,self->getCurrentDiffuseAlphaMode()); + LLPanelFace* self = (LLPanelFace*) userdata; + self->updateAlphaControls(); + LLSelectedTEMaterial::setDiffuseAlphaMode(self,self->getCurrentDiffuseAlphaMode()); } // static void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendFullbright(); + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendFullbright(); } // static void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendGlow(); + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendGlow(); } // static @@ -3306,102 +3306,102 @@ BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) void LLPanelFace::onCommitTexture( const LLSD& data ) { - add(LLStatViewer::EDIT_TEXTURE, 1); - sendTexture(); + add(LLStatViewer::EDIT_TEXTURE, 1); + sendTexture(); } void LLPanelFace::onCancelTexture(const LLSD& data) { - LLSelectMgr::getInstance()->selectionRevertTextures(); + LLSelectMgr::getInstance()->selectionRevertTextures(); } void LLPanelFace::onSelectTexture(const LLSD& data) { - LLSelectMgr::getInstance()->saveSelectedObjectTextures(); - sendTexture(); - - LLGLenum image_format; - bool identical_image_format = false; - LLSelectedTE::getImageFormat(image_format, identical_image_format); - - LLCtrlSelectionInterface* combobox_alphamode = - childGetSelectionInterface("combobox alphamode"); - - U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - if (combobox_alphamode) - { - switch (image_format) - { - case GL_RGBA: - case GL_ALPHA: - { - alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - break; - - case GL_RGB: break; - default: - { - LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; - } - break; - } - - combobox_alphamode->selectNthItem(alpha_mode); - } - LLSelectedTEMaterial::setDiffuseAlphaMode(this, getCurrentDiffuseAlphaMode()); + LLSelectMgr::getInstance()->saveSelectedObjectTextures(); + sendTexture(); + + LLGLenum image_format; + bool identical_image_format = false; + LLSelectedTE::getImageFormat(image_format, identical_image_format); + + LLCtrlSelectionInterface* combobox_alphamode = + childGetSelectionInterface("combobox alphamode"); + + U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + if (combobox_alphamode) + { + switch (image_format) + { + case GL_RGBA: + case GL_ALPHA: + { + alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + break; + + case GL_RGB: break; + default: + { + LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; + } + break; + } + + combobox_alphamode->selectNthItem(alpha_mode); + } + LLSelectedTEMaterial::setDiffuseAlphaMode(this, getCurrentDiffuseAlphaMode()); } void LLPanelFace::onCloseTexturePicker(const LLSD& data) { - LL_DEBUGS("Materials") << data << LL_ENDL; - updateUI(); + LL_DEBUGS("Materials") << data << LL_ENDL; + updateUI(); } void LLPanelFace::onCommitSpecularTexture( const LLSD& data ) { - LL_DEBUGS("Materials") << data << LL_ENDL; - sendShiny(SHINY_TEXTURE); + LL_DEBUGS("Materials") << data << LL_ENDL; + sendShiny(SHINY_TEXTURE); } void LLPanelFace::onCommitNormalTexture( const LLSD& data ) { - LL_DEBUGS("Materials") << data << LL_ENDL; - LLUUID nmap_id = getCurrentNormalMap(); - sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE); + LL_DEBUGS("Materials") << data << LL_ENDL; + LLUUID nmap_id = getCurrentNormalMap(); + sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE); } void LLPanelFace::onCancelSpecularTexture(const LLSD& data) { - U8 shiny = 0; - bool identical_shiny = false; - LLSelectedTE::getShiny(shiny, identical_shiny); - LLUUID spec_map_id = getChild("shinytexture control")->getImageAssetID(); - shiny = spec_map_id.isNull() ? shiny : SHINY_TEXTURE; - sendShiny(shiny); + U8 shiny = 0; + bool identical_shiny = false; + LLSelectedTE::getShiny(shiny, identical_shiny); + LLUUID spec_map_id = getChild("shinytexture control")->getImageAssetID(); + shiny = spec_map_id.isNull() ? shiny : SHINY_TEXTURE; + sendShiny(shiny); } void LLPanelFace::onCancelNormalTexture(const LLSD& data) { - U8 bumpy = 0; - bool identical_bumpy = false; - LLSelectedTE::getBumpmap(bumpy, identical_bumpy); - LLUUID spec_map_id = getChild("bumpytexture control")->getImageAssetID(); - bumpy = spec_map_id.isNull() ? bumpy : BUMPY_TEXTURE; - sendBump(bumpy); + U8 bumpy = 0; + bool identical_bumpy = false; + LLSelectedTE::getBumpmap(bumpy, identical_bumpy); + LLUUID spec_map_id = getChild("bumpytexture control")->getImageAssetID(); + bumpy = spec_map_id.isNull() ? bumpy : BUMPY_TEXTURE; + sendBump(bumpy); } void LLPanelFace::onSelectSpecularTexture(const LLSD& data) { - LL_DEBUGS("Materials") << data << LL_ENDL; - sendShiny(SHINY_TEXTURE); + LL_DEBUGS("Materials") << data << LL_ENDL; + sendShiny(SHINY_TEXTURE); } void LLPanelFace::onSelectNormalTexture(const LLSD& data) { - LL_DEBUGS("Materials") << data << LL_ENDL; - LLUUID nmap_id = getCurrentNormalMap(); - sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE); + LL_DEBUGS("Materials") << data << LL_ENDL; + LLUUID nmap_id = getCurrentNormalMap(); + sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE); } ////////////////////////////////////////////////////////////////////////////// @@ -3478,212 +3478,212 @@ bool LLPanelFace::multipleFacesSelectedConfirm(const LLSD& notification, const L //static void LLPanelFace::syncOffsetX(LLPanelFace* self, F32 offsetU) { - LLSelectedTEMaterial::setNormalOffsetX(self,offsetU); - LLSelectedTEMaterial::setSpecularOffsetX(self,offsetU); - self->getChild("TexOffsetU")->forceSetValue(offsetU); - self->sendTextureInfo(); + LLSelectedTEMaterial::setNormalOffsetX(self,offsetU); + LLSelectedTEMaterial::setSpecularOffsetX(self,offsetU); + self->getChild("TexOffsetU")->forceSetValue(offsetU); + self->sendTextureInfo(); } //static void LLPanelFace::syncOffsetY(LLPanelFace* self, F32 offsetV) { - LLSelectedTEMaterial::setNormalOffsetY(self,offsetV); - LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV); - self->getChild("TexOffsetV")->forceSetValue(offsetV); - self->sendTextureInfo(); + LLSelectedTEMaterial::setNormalOffsetY(self,offsetV); + LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV); + self->getChild("TexOffsetV")->forceSetValue(offsetV); + self->sendTextureInfo(); } //static void LLPanelFace::onCommitMaterialBumpyOffsetX(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetX(self,self->getCurrentBumpyOffsetU()); - } - else - { - LLSelectedTEMaterial::setNormalOffsetX(self,self->getCurrentBumpyOffsetU()); - } + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetX(self,self->getCurrentBumpyOffsetU()); + } + else + { + LLSelectedTEMaterial::setNormalOffsetX(self,self->getCurrentBumpyOffsetU()); + } } //static void LLPanelFace::onCommitMaterialBumpyOffsetY(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetY(self,self->getCurrentBumpyOffsetV()); - } - else - { - LLSelectedTEMaterial::setNormalOffsetY(self,self->getCurrentBumpyOffsetV()); - } + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetY(self,self->getCurrentBumpyOffsetV()); + } + else + { + LLSelectedTEMaterial::setNormalOffsetY(self,self->getCurrentBumpyOffsetV()); + } } //static void LLPanelFace::onCommitMaterialShinyOffsetX(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetX(self, self->getCurrentShinyOffsetU()); - } - else - { - LLSelectedTEMaterial::setSpecularOffsetX(self,self->getCurrentShinyOffsetU()); - } + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetX(self, self->getCurrentShinyOffsetU()); + } + else + { + LLSelectedTEMaterial::setSpecularOffsetX(self,self->getCurrentShinyOffsetU()); + } } //static void LLPanelFace::onCommitMaterialShinyOffsetY(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetY(self,self->getCurrentShinyOffsetV()); - } - else - { - LLSelectedTEMaterial::setSpecularOffsetY(self,self->getCurrentShinyOffsetV()); - } + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetY(self,self->getCurrentShinyOffsetV()); + } + else + { + LLSelectedTEMaterial::setSpecularOffsetY(self,self->getCurrentShinyOffsetV()); + } } //static void LLPanelFace::syncRepeatX(LLPanelFace* self, F32 scaleU) { - LLSelectedTEMaterial::setNormalRepeatX(self,scaleU); - LLSelectedTEMaterial::setSpecularRepeatX(self,scaleU); - self->sendTextureInfo(); + LLSelectedTEMaterial::setNormalRepeatX(self,scaleU); + LLSelectedTEMaterial::setSpecularRepeatX(self,scaleU); + self->sendTextureInfo(); } //static void LLPanelFace::syncRepeatY(LLPanelFace* self, F32 scaleV) { - LLSelectedTEMaterial::setNormalRepeatY(self,scaleV); - LLSelectedTEMaterial::setSpecularRepeatY(self,scaleV); - self->sendTextureInfo(); + LLSelectedTEMaterial::setNormalRepeatY(self,scaleV); + LLSelectedTEMaterial::setSpecularRepeatY(self,scaleV); + self->sendTextureInfo(); } //static void LLPanelFace::onCommitMaterialBumpyScaleX(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - F32 bumpy_scale_u = self->getCurrentBumpyScaleU(); - if (self->isIdenticalPlanarTexgen()) - { - bumpy_scale_u *= 0.5f; - } - - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexScaleU")->forceSetValue(self->getCurrentBumpyScaleU()); - syncRepeatX(self, bumpy_scale_u); - } - else - { - LLSelectedTEMaterial::setNormalRepeatX(self,bumpy_scale_u); - } + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + F32 bumpy_scale_u = self->getCurrentBumpyScaleU(); + if (self->isIdenticalPlanarTexgen()) + { + bumpy_scale_u *= 0.5f; + } + + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexScaleU")->forceSetValue(self->getCurrentBumpyScaleU()); + syncRepeatX(self, bumpy_scale_u); + } + else + { + LLSelectedTEMaterial::setNormalRepeatX(self,bumpy_scale_u); + } } //static void LLPanelFace::onCommitMaterialBumpyScaleY(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - F32 bumpy_scale_v = self->getCurrentBumpyScaleV(); - if (self->isIdenticalPlanarTexgen()) - { - bumpy_scale_v *= 0.5f; - } + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + F32 bumpy_scale_v = self->getCurrentBumpyScaleV(); + if (self->isIdenticalPlanarTexgen()) + { + bumpy_scale_v *= 0.5f; + } - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexScaleV")->forceSetValue(self->getCurrentBumpyScaleV()); - syncRepeatY(self, bumpy_scale_v); - } - else - { - LLSelectedTEMaterial::setNormalRepeatY(self,bumpy_scale_v); - } + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexScaleV")->forceSetValue(self->getCurrentBumpyScaleV()); + syncRepeatY(self, bumpy_scale_v); + } + else + { + LLSelectedTEMaterial::setNormalRepeatY(self,bumpy_scale_v); + } } //static void LLPanelFace::onCommitMaterialShinyScaleX(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - F32 shiny_scale_u = self->getCurrentShinyScaleU(); - if (self->isIdenticalPlanarTexgen()) - { - shiny_scale_u *= 0.5f; - } - - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexScaleU")->forceSetValue(self->getCurrentShinyScaleU()); - syncRepeatX(self, shiny_scale_u); - } - else - { - LLSelectedTEMaterial::setSpecularRepeatX(self,shiny_scale_u); - } + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + F32 shiny_scale_u = self->getCurrentShinyScaleU(); + if (self->isIdenticalPlanarTexgen()) + { + shiny_scale_u *= 0.5f; + } + + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexScaleU")->forceSetValue(self->getCurrentShinyScaleU()); + syncRepeatX(self, shiny_scale_u); + } + else + { + LLSelectedTEMaterial::setSpecularRepeatX(self,shiny_scale_u); + } } //static void LLPanelFace::onCommitMaterialShinyScaleY(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - F32 shiny_scale_v = self->getCurrentShinyScaleV(); - if (self->isIdenticalPlanarTexgen()) - { - shiny_scale_v *= 0.5f; - } - - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexScaleV")->forceSetValue(self->getCurrentShinyScaleV()); - syncRepeatY(self, shiny_scale_v); - } - else - { - LLSelectedTEMaterial::setSpecularRepeatY(self,shiny_scale_v); - } + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + F32 shiny_scale_v = self->getCurrentShinyScaleV(); + if (self->isIdenticalPlanarTexgen()) + { + shiny_scale_v *= 0.5f; + } + + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexScaleV")->forceSetValue(self->getCurrentShinyScaleV()); + syncRepeatY(self, shiny_scale_v); + } + else + { + LLSelectedTEMaterial::setSpecularRepeatY(self,shiny_scale_v); + } } //static void LLPanelFace::syncMaterialRot(LLPanelFace* self, F32 rot, int te) { - LLSelectedTEMaterial::setNormalRotation(self,rot * DEG_TO_RAD, te); - LLSelectedTEMaterial::setSpecularRotation(self,rot * DEG_TO_RAD, te); - self->sendTextureInfo(); + LLSelectedTEMaterial::setNormalRotation(self,rot * DEG_TO_RAD, te); + LLSelectedTEMaterial::setSpecularRotation(self,rot * DEG_TO_RAD, te); + self->sendTextureInfo(); } //static void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexRot")->forceSetValue(self->getCurrentBumpyRot()); - syncMaterialRot(self, self->getCurrentBumpyRot()); - } - else - { + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexRot")->forceSetValue(self->getCurrentBumpyRot()); + syncMaterialRot(self, self->getCurrentBumpyRot()); + } + else + { if ((bool)self->childGetValue("checkbox planar align").asBoolean()) { LLFace* last_face = NULL; @@ -3696,22 +3696,22 @@ void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata) { LLSelectedTEMaterial::setNormalRotation(self, self->getCurrentBumpyRot() * DEG_TO_RAD); } - } + } } //static void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - self->getChild("TexRot")->forceSetValue(self->getCurrentShinyRot()); - syncMaterialRot(self, self->getCurrentShinyRot()); - } - else - { + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + self->getChild("TexRot")->forceSetValue(self->getCurrentShinyRot()); + syncMaterialRot(self, self->getCurrentShinyRot()); + } + else + { if ((bool)self->childGetValue("checkbox planar align").asBoolean()) { LLFace* last_face = NULL; @@ -3724,136 +3724,136 @@ void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata) { LLSelectedTEMaterial::setSpecularRotation(self, self->getCurrentShinyRot() * DEG_TO_RAD); } - } + } } //static void LLPanelFace::onCommitMaterialGloss(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - LLSelectedTEMaterial::setSpecularLightExponent(self,self->getCurrentGlossiness()); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setSpecularLightExponent(self,self->getCurrentGlossiness()); } //static void LLPanelFace::onCommitMaterialEnv(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - llassert_always(self); - LLSelectedTEMaterial::setEnvironmentIntensity(self,self->getCurrentEnvIntensity()); + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setEnvironmentIntensity(self,self->getCurrentEnvIntensity()); } //static void LLPanelFace::onCommitMaterialMaskCutoff(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff()); + LLPanelFace* self = (LLPanelFace*) userdata; + LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff()); } // static void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->sendTextureInfo(); - // vertical scale and repeats per meter depends on each other, so force set on changes - self->updateUI(true); + LLPanelFace* self = (LLPanelFace*) userdata; + self->sendTextureInfo(); + // vertical scale and repeats per meter depends on each other, so force set on changes + self->updateUI(true); } // static void LLPanelFace::onCommitTextureScaleX( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - F32 bumpy_scale_u = self->getChild("TexScaleU")->getValue().asReal(); - if (self->isIdenticalPlanarTexgen()) - { - bumpy_scale_u *= 0.5f; - } - syncRepeatX(self, bumpy_scale_u); - } - else - { - self->sendTextureInfo(); - } - self->updateUI(true); + LLPanelFace* self = (LLPanelFace*) userdata; + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + F32 bumpy_scale_u = self->getChild("TexScaleU")->getValue().asReal(); + if (self->isIdenticalPlanarTexgen()) + { + bumpy_scale_u *= 0.5f; + } + syncRepeatX(self, bumpy_scale_u); + } + else + { + self->sendTextureInfo(); + } + self->updateUI(true); } // static void LLPanelFace::onCommitTextureScaleY( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - F32 bumpy_scale_v = self->getChild("TexScaleV")->getValue().asReal(); - if (self->isIdenticalPlanarTexgen()) - { - bumpy_scale_v *= 0.5f; - } - syncRepeatY(self, bumpy_scale_v); - } - else - { - self->sendTextureInfo(); - } - self->updateUI(true); + LLPanelFace* self = (LLPanelFace*) userdata; + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + F32 bumpy_scale_v = self->getChild("TexScaleV")->getValue().asReal(); + if (self->isIdenticalPlanarTexgen()) + { + bumpy_scale_v *= 0.5f; + } + syncRepeatY(self, bumpy_scale_v); + } + else + { + self->sendTextureInfo(); + } + self->updateUI(true); } // static void LLPanelFace::onCommitTextureRot( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; + LLPanelFace* self = (LLPanelFace*) userdata; - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncMaterialRot(self, self->getChild("TexRot")->getValue().asReal()); - } - else - { - self->sendTextureInfo(); - } - self->updateUI(true); + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncMaterialRot(self, self->getChild("TexRot")->getValue().asReal()); + } + else + { + self->sendTextureInfo(); + } + self->updateUI(true); } // static void LLPanelFace::onCommitTextureOffsetX( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetX(self, self->getChild("TexOffsetU")->getValue().asReal()); - } - else - { - self->sendTextureInfo(); - } - self->updateUI(true); + LLPanelFace* self = (LLPanelFace*) userdata; + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetX(self, self->getChild("TexOffsetU")->getValue().asReal()); + } + else + { + self->sendTextureInfo(); + } + self->updateUI(true); } // static void LLPanelFace::onCommitTextureOffsetY( LLUICtrl* ctrl, void* userdata ) { - LLPanelFace* self = (LLPanelFace*) userdata; - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - syncOffsetY(self, self->getChild("TexOffsetV")->getValue().asReal()); - } - else - { - self->sendTextureInfo(); - } - self->updateUI(true); + LLPanelFace* self = (LLPanelFace*) userdata; + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + syncOffsetY(self, self->getChild("TexOffsetV")->getValue().asReal()); + } + else + { + self->sendTextureInfo(); + } + self->updateUI(true); } // Commit the number of repeats per meter // static void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - - LLUICtrl* repeats_ctrl = self->getChild("rptctrl"); - - U32 materials_media = self->mComboMatMedia->getCurrentIndex(); + LLPanelFace* self = (LLPanelFace*) userdata; + + LLUICtrl* repeats_ctrl = self->getChild("rptctrl"); + + U32 materials_media = self->mComboMatMedia->getCurrentIndex(); U32 material_type = 0; if (materials_media == MATMEDIA_PBR) { @@ -3866,126 +3866,126 @@ void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata) material_type = radio_mat_type->getSelectedIndex(); } - F32 repeats_per_meter = repeats_ctrl->getValue().asReal(); - + F32 repeats_per_meter = repeats_ctrl->getValue().asReal(); + F32 obj_scale_s = 1.0f; F32 obj_scale_t = 1.0f; - bool identical_scale_s = false; - bool identical_scale_t = false; - - LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s); - LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t); - - LLUICtrl* bumpy_scale_u = self->getChild("bumpyScaleU"); - LLUICtrl* bumpy_scale_v = self->getChild("bumpyScaleV"); - LLUICtrl* shiny_scale_u = self->getChild("shinyScaleU"); - LLUICtrl* shiny_scale_v = self->getChild("shinyScaleV"); - - if (gSavedSettings.getBOOL("SyncMaterialSettings")) - { - LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); - - bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter); - bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter); - - LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter); - LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter); - - shiny_scale_u->setValue(obj_scale_s * repeats_per_meter); - shiny_scale_v->setValue(obj_scale_t * repeats_per_meter); - - LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter); - LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter); - } - else - { - switch (material_type) - { - case MATTYPE_DIFFUSE: - { - LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); - } - break; - - case MATTYPE_NORMAL: - { - bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter); - bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter); - - LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter); - LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter); - } - break; - - case MATTYPE_SPECULAR: - { - shiny_scale_u->setValue(obj_scale_s * repeats_per_meter); - shiny_scale_v->setValue(obj_scale_t * repeats_per_meter); - - LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter); - LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter); - } - break; - - default: - llassert(false); - break; - } - } - // vertical scale and repeats per meter depends on each other, so force set on changes - self->updateUI(true); + bool identical_scale_s = false; + bool identical_scale_t = false; + + LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s); + LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t); + + LLUICtrl* bumpy_scale_u = self->getChild("bumpyScaleU"); + LLUICtrl* bumpy_scale_v = self->getChild("bumpyScaleV"); + LLUICtrl* shiny_scale_u = self->getChild("shinyScaleU"); + LLUICtrl* shiny_scale_v = self->getChild("shinyScaleV"); + + if (gSavedSettings.getBOOL("SyncMaterialSettings")) + { + LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); + + bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter); + bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter); + + LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter); + LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter); + + shiny_scale_u->setValue(obj_scale_s * repeats_per_meter); + shiny_scale_v->setValue(obj_scale_t * repeats_per_meter); + + LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter); + LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter); + } + else + { + switch (material_type) + { + case MATTYPE_DIFFUSE: + { + LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); + } + break; + + case MATTYPE_NORMAL: + { + bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter); + bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter); + + LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter); + LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter); + } + break; + + case MATTYPE_SPECULAR: + { + shiny_scale_u->setValue(obj_scale_s * repeats_per_meter); + shiny_scale_v->setValue(obj_scale_t * repeats_per_meter); + + LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter); + LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter); + } + break; + + default: + llassert(false); + break; + } + } + // vertical scale and repeats per meter depends on each other, so force set on changes + self->updateUI(true); } struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor { - virtual bool apply(LLViewerObject* object, S32 te) - { - viewer_media_t pMediaImpl; - - const LLTextureEntry* tep = object->getTE(te); - const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; - if ( mep ) - { - pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); - } - - if ( pMediaImpl.isNull()) - { - // If we didn't find face media for this face, check whether this face is showing parcel media. - pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getID()); - } - - if ( pMediaImpl.notNull()) - { - LLPluginClassMedia *media = pMediaImpl->getMediaPlugin(); - if(media) - { - S32 media_width = media->getWidth(); - S32 media_height = media->getHeight(); - S32 texture_width = media->getTextureWidth(); - S32 texture_height = media->getTextureHeight(); - F32 scale_s = (F32)media_width / (F32)texture_width; - F32 scale_t = (F32)media_height / (F32)texture_height; - - // set scale and adjust offset - object->setTEScaleS( te, scale_s ); - object->setTEScaleT( te, scale_t ); // don't need to flip Y anymore since QT does this for us now. - object->setTEOffsetS( te, -( 1.0f - scale_s ) / 2.0f ); - object->setTEOffsetT( te, -( 1.0f - scale_t ) / 2.0f ); - } - } - return true; - }; + virtual bool apply(LLViewerObject* object, S32 te) + { + viewer_media_t pMediaImpl; + + const LLTextureEntry* tep = object->getTE(te); + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if ( mep ) + { + pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID()); + } + + if ( pMediaImpl.isNull()) + { + // If we didn't find face media for this face, check whether this face is showing parcel media. + pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getID()); + } + + if ( pMediaImpl.notNull()) + { + LLPluginClassMedia *media = pMediaImpl->getMediaPlugin(); + if(media) + { + S32 media_width = media->getWidth(); + S32 media_height = media->getHeight(); + S32 texture_width = media->getTextureWidth(); + S32 texture_height = media->getTextureHeight(); + F32 scale_s = (F32)media_width / (F32)texture_width; + F32 scale_t = (F32)media_height / (F32)texture_height; + + // set scale and adjust offset + object->setTEScaleS( te, scale_s ); + object->setTEScaleT( te, scale_t ); // don't need to flip Y anymore since QT does this for us now. + object->setTEOffsetS( te, -( 1.0f - scale_s ) / 2.0f ); + object->setTEOffsetT( te, -( 1.0f - scale_t ) / 2.0f ); + } + } + return true; + }; }; void LLPanelFace::onClickAutoFix(void* userdata) { - LLPanelFaceSetMediaFunctor setfunc; - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + LLPanelFaceSetMediaFunctor setfunc; + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); - LLPanelFaceSendFunctor sendfunc; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); + LLPanelFaceSendFunctor sendfunc; + LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); } void LLPanelFace::onAlignTexture(void* userdata) @@ -4362,7 +4362,7 @@ void LLPanelFace::onCopyTexture() { te_data["te"]["itemfullperm"] = full_perm; - te_data["te"]["fromlibrary"] = from_library; + te_data["te"]["fromlibrary"] = from_library; // If full permission object, texture is free to copy, // but otherwise we need to check inventory and extract permissions @@ -4490,7 +4490,7 @@ void LLPanelFace::onPasteTexture() } // we can copy if single face was copied in edit face mode or if face count matches - if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) + if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean()) && compare_tes != clipboard.size()) { LLSD notif_args; @@ -4872,9 +4872,9 @@ bool LLPanelFace::menuEnableItem(const LLSD& userdata) // static void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) { - LLPanelFace* self = (LLPanelFace*) userdata; - self->getState(); - self->sendTextureInfo(); + LLPanelFace* self = (LLPanelFace*) userdata; + self->getState(); + self->sendTextureInfo(); } void LLPanelFace::updateGLTFTextureTransform(float value, U32 pbr_type, std::function edit) @@ -5123,54 +5123,54 @@ void LLPanelFace::onCommitGLTFTextureOffsetV(LLUICtrl* ctrl) void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) { - LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL; - LLRadioGroup* radio_mat_type = findChild("radio_material_type"); - if(!radio_mat_type) - { - return; - } - U32 mattype = radio_mat_type->getSelectedIndex(); - std::string which_control="texture control"; - switch (mattype) - { - case MATTYPE_SPECULAR: - which_control = "shinytexture control"; - break; - case MATTYPE_NORMAL: - which_control = "bumpytexture control"; - break; - // no default needed - } - LL_DEBUGS("Materials") << "control " << which_control << LL_ENDL; - LLTextureCtrl* texture_ctrl = getChild(which_control); - if (texture_ctrl) - { - LLUUID obj_owner_id; - std::string obj_owner_name; - LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name); - - LLSaleInfo sale_info; - LLSelectMgr::instance().selectGetSaleInfo(sale_info); - - bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture? - bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture? - bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent? - bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale? - - if (can_copy && can_transfer) - { - texture_ctrl->setCanApply(true, true); - return; - } - - // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale - texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale); - - if (gSavedSettings.getBOOL("TextureLivePreview")) - { - LLNotificationsUtil::add("LivePreviewUnavailable"); - } - } + LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL; + LLRadioGroup* radio_mat_type = findChild("radio_material_type"); + if(!radio_mat_type) + { + return; + } + U32 mattype = radio_mat_type->getSelectedIndex(); + std::string which_control="texture control"; + switch (mattype) + { + case MATTYPE_SPECULAR: + which_control = "shinytexture control"; + break; + case MATTYPE_NORMAL: + which_control = "bumpytexture control"; + break; + // no default needed + } + LL_DEBUGS("Materials") << "control " << which_control << LL_ENDL; + LLTextureCtrl* texture_ctrl = getChild(which_control); + if (texture_ctrl) + { + LLUUID obj_owner_id; + std::string obj_owner_name; + LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name); + + LLSaleInfo sale_info; + LLSelectMgr::instance().selectGetSaleInfo(sale_info); + + bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture? + bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture? + bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent? + bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale? + + if (can_copy && can_transfer) + { + texture_ctrl->setCanApply(true, true); + return; + } + + // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale + texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale); + + if (gSavedSettings.getBOOL("TextureLivePreview")) + { + LLNotificationsUtil::add("LivePreviewUnavailable"); + } + } } void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp) @@ -5210,81 +5210,81 @@ void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp) bool LLPanelFace::isIdenticalPlanarTexgen() { - LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT; - bool identical_texgen = false; - LLSelectedTE::getTexGen(selected_texgen, identical_texgen); - return (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR)); + LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT; + bool identical_texgen = false; + LLSelectedTE::getTexGen(selected_texgen, identical_texgen); + return (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR)); } void LLPanelFace::LLSelectedTE::getFace(LLFace*& face_to_return, bool& identical_face) -{ - struct LLSelectedTEGetFace : public LLSelectedTEGetFunctor - { - LLFace* get(LLViewerObject* object, S32 te) - { - return (object->mDrawable) ? object->mDrawable->getFace(te): NULL; - } - } get_te_face_func; - identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, face_to_return, false, (LLFace*)nullptr); +{ + struct LLSelectedTEGetFace : public LLSelectedTEGetFunctor + { + LLFace* get(LLViewerObject* object, S32 te) + { + return (object->mDrawable) ? object->mDrawable->getFace(te): NULL; + } + } get_te_face_func; + identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, face_to_return, false, (LLFace*)nullptr); } void LLPanelFace::LLSelectedTE::getImageFormat(LLGLenum& image_format_to_return, bool& identical_face) { - LLGLenum image_format; - struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor - { - LLGLenum get(LLViewerObject* object, S32 te_index) - { - LLViewerTexture* image = object->getTEImage(te_index); - return image ? image->getPrimaryFormat() : GL_RGB; - } - } get_glenum; - identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_glenum, image_format); - image_format_to_return = image_format; + LLGLenum image_format; + struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor + { + LLGLenum get(LLViewerObject* object, S32 te_index) + { + LLViewerTexture* image = object->getTEImage(te_index); + return image ? image->getPrimaryFormat() : GL_RGB; + } + } get_glenum; + identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_glenum, image_format); + image_format_to_return = image_format; } void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical) -{ - struct LLSelectedTEGetTexId : public LLSelectedTEGetFunctor - { - LLUUID get(LLViewerObject* object, S32 te_index) - { - LLTextureEntry *te = object->getTE(te_index); - if (te) - { - if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER) - || (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3)) - { - return te->getID(); - } - } - - LLUUID id; - LLViewerTexture* image = object->getTEImage(te_index); - if (image) - { - id = image->getID(); - } - - if (!id.isNull() && LLViewerMedia::getInstance()->textureHasMedia(id)) - { - if (te) - { - LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; - if(!tex) - { - tex = LLViewerFetchedTexture::sDefaultImagep; - } - if (tex) - { - id = tex->getID(); - } - } - } - return id; - } - } func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id ); +{ + struct LLSelectedTEGetTexId : public LLSelectedTEGetFunctor + { + LLUUID get(LLViewerObject* object, S32 te_index) + { + LLTextureEntry *te = object->getTE(te_index); + if (te) + { + if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER) + || (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3)) + { + return te->getID(); + } + } + + LLUUID id; + LLViewerTexture* image = object->getTEImage(te_index); + if (image) + { + id = image->getID(); + } + + if (!id.isNull() && LLViewerMedia::getInstance()->textureHasMedia(id)) + { + if (te) + { + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; + if(!tex) + { + tex = LLViewerFetchedTexture::sDefaultImagep; + } + if (tex) + { + id = tex->getID(); + } + } + } + return id; + } + } func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id ); } void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical, bool& has_faces_with_pbr, bool& has_faces_without_pbr) @@ -5317,7 +5317,7 @@ void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical, bo { mIdenticalId = false; } - + LLGLTFMaterial* te_override = object->getTE(te_index)->getGLTFMaterialOverride(); if (te_override) { @@ -5360,140 +5360,140 @@ void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical, bo void LLPanelFace::LLSelectedTEMaterial::getCurrent(LLMaterialPtr& material_ptr, bool& identical_material) { - struct MaterialFunctor : public LLSelectedTEGetFunctor - { - LLMaterialPtr get(LLViewerObject* object, S32 te_index) - { - return object->getTE(te_index)->getMaterialParams(); - } - } func; - identical_material = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_ptr); + struct MaterialFunctor : public LLSelectedTEGetFunctor + { + LLMaterialPtr get(LLViewerObject* object, S32 te_index) + { + return object->getTE(te_index)->getMaterialParams(); + } + } func; + identical_material = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_ptr); } void LLPanelFace::LLSelectedTEMaterial::getMaxSpecularRepeats(F32& repeats, bool& identical) { - struct LLSelectedTEGetMaxSpecRepeats : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); - U32 s_axis = VX; - U32 t_axis = VY; - F32 repeats_s = 1.0f; - F32 repeats_t = 1.0f; - if (mat) - { - mat->getSpecularRepeat(repeats_s, repeats_t); - repeats_s /= object->getScale().mV[s_axis]; - repeats_t /= object->getScale().mV[t_axis]; - } - return llmax(repeats_s, repeats_t); - } - - } max_spec_repeats_func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_spec_repeats_func, repeats); + struct LLSelectedTEGetMaxSpecRepeats : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); + U32 s_axis = VX; + U32 t_axis = VY; + F32 repeats_s = 1.0f; + F32 repeats_t = 1.0f; + if (mat) + { + mat->getSpecularRepeat(repeats_s, repeats_t); + repeats_s /= object->getScale().mV[s_axis]; + repeats_t /= object->getScale().mV[t_axis]; + } + return llmax(repeats_s, repeats_t); + } + + } max_spec_repeats_func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_spec_repeats_func, repeats); } void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& identical) { - struct LLSelectedTEGetMaxNormRepeats : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); - U32 s_axis = VX; - U32 t_axis = VY; - F32 repeats_s = 1.0f; - F32 repeats_t = 1.0f; - if (mat) - { - mat->getNormalRepeat(repeats_s, repeats_t); - repeats_s /= object->getScale().mV[s_axis]; - repeats_t /= object->getScale().mV[t_axis]; - } - return llmax(repeats_s, repeats_t); - } - - } max_norm_repeats_func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats); + struct LLSelectedTEGetMaxNormRepeats : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); + U32 s_axis = VX; + U32 t_axis = VY; + F32 repeats_s = 1.0f; + F32 repeats_t = 1.0f; + if (mat) + { + mat->getNormalRepeat(repeats_s, repeats_t); + repeats_s /= object->getScale().mV[s_axis]; + repeats_t /= object->getScale().mV[t_axis]; + } + return llmax(repeats_s, repeats_t); + } + + } max_norm_repeats_func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats); } void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha) { - struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor - { - LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {} - LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {} - virtual ~LLSelectedTEGetDiffuseAlphaMode() {} - - U8 get(LLViewerObject* object, S32 face) - { - U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - - LLTextureEntry* tep = object->getTE(face); - if (tep) - { - LLMaterial* mat = tep->getMaterialParams().get(); - if (mat) - { - diffuse_mode = mat->getDiffuseAlphaMode(); - } - } - - return diffuse_mode; - } - bool _isAlpha; // whether or not the diffuse texture selected contains alpha information - } get_diff_mode(diffuse_texture_has_alpha); - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode); + struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor + { + LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {} + LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {} + virtual ~LLSelectedTEGetDiffuseAlphaMode() {} + + U8 get(LLViewerObject* object, S32 face) + { + U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + + LLTextureEntry* tep = object->getTE(face); + if (tep) + { + LLMaterial* mat = tep->getMaterialParams().get(); + if (mat) + { + diffuse_mode = mat->getDiffuseAlphaMode(); + } + } + + return diffuse_mode; + } + bool _isAlpha; // whether or not the diffuse texture selected contains alpha information + } get_diff_mode(diffuse_texture_has_alpha); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode); } void LLPanelFace::LLSelectedTE::getObjectScaleS(F32& scale_s, bool& identical) -{ - struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - U32 s_axis = VX; - U32 t_axis = VY; - LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); - return object->getScale().mV[s_axis]; - } +{ + struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + U32 s_axis = VX; + U32 t_axis = VY; + LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); + return object->getScale().mV[s_axis]; + } - } scale_s_func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_s_func, scale_s ); + } scale_s_func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_s_func, scale_s ); } void LLPanelFace::LLSelectedTE::getObjectScaleT(F32& scale_t, bool& identical) -{ - struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - U32 s_axis = VX; - U32 t_axis = VY; - LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); - return object->getScale().mV[t_axis]; - } +{ + struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + U32 s_axis = VX; + U32 t_axis = VY; + LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); + return object->getScale().mV[t_axis]; + } - } scale_t_func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_t_func, scale_t ); + } scale_t_func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_t_func, scale_t ); } void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identical) { - struct LLSelectedTEGetMaxDiffuseRepeats : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - U32 s_axis = VX; - U32 t_axis = VY; - LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); - F32 repeats_s = object->getTE(face)->mScaleS / object->getScale().mV[s_axis]; - F32 repeats_t = object->getTE(face)->mScaleT / object->getScale().mV[t_axis]; - return llmax(repeats_s, repeats_t); - } - - } max_diff_repeats_func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats ); + struct LLSelectedTEGetMaxDiffuseRepeats : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + U32 s_axis = VX; + U32 t_axis = VY; + LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); + F32 repeats_s = object->getTE(face)->mScaleS / object->getScale().mV[s_axis]; + F32 repeats_t = object->getTE(face)->mScaleT / object->getScale().mV[t_axis]; + return llmax(repeats_s, repeats_t); + } + + } max_diff_repeats_func; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats ); } diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 05860b995f..da53b4a14c 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -1,25 +1,25 @@ -/** +/** * @file llpanelface.h * @brief Panel in the tools floater for editing face textures, colors, etc. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -65,179 +65,179 @@ class PBRPickerObjectListener; // boost who? // template< - typename DataType, - typename SetValueType, - void (LLMaterial::*MaterialEditFunc)(SetValueType data) > + typename DataType, + typename SetValueType, + void (LLMaterial::*MaterialEditFunc)(SetValueType data) > class LLMaterialEditFunctor { public: - LLMaterialEditFunctor(const DataType& data) : _data(data) {} - virtual ~LLMaterialEditFunctor() {} - virtual void apply(LLMaterialPtr& material) { (material->*(MaterialEditFunc))(_data); } - DataType _data; + LLMaterialEditFunctor(const DataType& data) : _data(data) {} + virtual ~LLMaterialEditFunctor() {} + virtual void apply(LLMaterialPtr& material) { (material->*(MaterialEditFunc))(_data); } + DataType _data; }; template< - typename DataType, - DataType (LLMaterial::*MaterialGetFunc)() > + typename DataType, + DataType (LLMaterial::*MaterialGetFunc)() > class LLMaterialGetFunctor { public: - LLMaterialGetFunctor() {} - virtual DataType get(LLMaterialPtr& material) { return (material->*(MaterialGetFunc)); } + LLMaterialGetFunctor() {} + virtual DataType get(LLMaterialPtr& material) { return (material->*(MaterialGetFunc)); } }; template< - typename DataType, - DataType (LLTextureEntry::*TEGetFunc)() > + typename DataType, + DataType (LLTextureEntry::*TEGetFunc)() > class LLTEGetFunctor { public: - LLTEGetFunctor() {} - virtual DataType get(LLTextureEntry* entry) { return (entry*(TEGetFunc)); } + LLTEGetFunctor() {} + virtual DataType get(LLTextureEntry* entry) { return (entry*(TEGetFunc)); } }; class LLPanelFace : public LLPanel { public: - virtual BOOL postBuild(); - LLPanelFace(); - virtual ~LLPanelFace(); + virtual BOOL postBuild(); + LLPanelFace(); + virtual ~LLPanelFace(); - void refresh(); - void refreshMedia(); - void unloadMedia(); + void refresh(); + void refreshMedia(); + void unloadMedia(); static void onMaterialOverrideReceived(const LLUUID& object_id, S32 side); /*virtual*/ void onVisibilityChange(BOOL new_visibility); /*virtual*/ void draw(); - LLMaterialPtr createDefaultMaterial(LLMaterialPtr current_material) - { - LLMaterialPtr new_material(!current_material.isNull() ? new LLMaterial(current_material->asLLSD()) : new LLMaterial()); - llassert_always(new_material); + LLMaterialPtr createDefaultMaterial(LLMaterialPtr current_material) + { + LLMaterialPtr new_material(!current_material.isNull() ? new LLMaterial(current_material->asLLSD()) : new LLMaterial()); + llassert_always(new_material); - // Preserve old diffuse alpha mode or assert correct default blend mode as appropriate for the alpha channel content of the diffuse texture - // - new_material->setDiffuseAlphaMode(current_material.isNull() ? (isAlpha() ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE) : current_material->getDiffuseAlphaMode()); - return new_material; - } + // Preserve old diffuse alpha mode or assert correct default blend mode as appropriate for the alpha channel content of the diffuse texture + // + new_material->setDiffuseAlphaMode(current_material.isNull() ? (isAlpha() ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE) : current_material->getDiffuseAlphaMode()); + return new_material; + } - LLRender::eTexIndex getTextureChannelToEdit(); + LLRender::eTexIndex getTextureChannelToEdit(); LLRender::eTexIndex getTextureDropChannel(); LLGLTFMaterial::TextureInfo getPBRDropChannel(); protected: - void navigateToTitleMedia(const std::string url); - bool selectedMediaEditable(); - void clearMediaSettings(); - void updateMediaSettings(); - void updateMediaTitle(); - - void getState(); - - void sendTexture(); // applies and sends texture - void sendTextureInfo(); // applies and sends texture scale, offset, etc. - void sendColor(); // applies and sends color - void sendAlpha(); // applies and sends transparency - void sendBump(U32 bumpiness); // applies and sends bump map - void sendTexGen(); // applies and sends bump map - void sendShiny(U32 shininess); // applies and sends shininess - void sendFullbright(); // applies and sends full bright - - void sendGlow(); + void navigateToTitleMedia(const std::string url); + bool selectedMediaEditable(); + void clearMediaSettings(); + void updateMediaSettings(); + void updateMediaTitle(); + + void getState(); + + void sendTexture(); // applies and sends texture + void sendTextureInfo(); // applies and sends texture scale, offset, etc. + void sendColor(); // applies and sends color + void sendAlpha(); // applies and sends transparency + void sendBump(U32 bumpiness); // applies and sends bump map + void sendTexGen(); // applies and sends bump map + void sendShiny(U32 shininess); // applies and sends shininess + void sendFullbright(); // applies and sends full bright + + void sendGlow(); void alignTestureLayer(); void updateCopyTexButton(); - void onCommitPbr(const LLSD& data); - void onCancelPbr(const LLSD& data); - void onSelectPbr(const LLSD& data); + void onCommitPbr(const LLSD& data); + void onCancelPbr(const LLSD& data); + void onSelectPbr(const LLSD& data); static BOOL onDragPbr(LLUICtrl* ctrl, LLInventoryItem* item); - // this function is to return TRUE if the drag should succeed. - static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); - - void onCommitTexture(const LLSD& data); - void onCancelTexture(const LLSD& data); - void onSelectTexture(const LLSD& data); - void onCommitSpecularTexture(const LLSD& data); - void onCancelSpecularTexture(const LLSD& data); - void onSelectSpecularTexture(const LLSD& data); - void onCommitNormalTexture(const LLSD& data); - void onCancelNormalTexture(const LLSD& data); - void onSelectNormalTexture(const LLSD& data); - void onCommitColor(const LLSD& data); - void onCommitShinyColor(const LLSD& data); - void onCommitAlpha(const LLSD& data); - void onCancelColor(const LLSD& data); - void onCancelShinyColor(const LLSD& data); - void onSelectColor(const LLSD& data); - void onSelectShinyColor(const LLSD& data); - - void onCloseTexturePicker(const LLSD& data); + // this function is to return TRUE if the drag should succeed. + static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); + + void onCommitTexture(const LLSD& data); + void onCancelTexture(const LLSD& data); + void onSelectTexture(const LLSD& data); + void onCommitSpecularTexture(const LLSD& data); + void onCancelSpecularTexture(const LLSD& data); + void onSelectSpecularTexture(const LLSD& data); + void onCommitNormalTexture(const LLSD& data); + void onCancelNormalTexture(const LLSD& data); + void onSelectNormalTexture(const LLSD& data); + void onCommitColor(const LLSD& data); + void onCommitShinyColor(const LLSD& data); + void onCommitAlpha(const LLSD& data); + void onCancelColor(const LLSD& data); + void onCancelShinyColor(const LLSD& data); + void onSelectColor(const LLSD& data); + void onSelectShinyColor(const LLSD& data); + + void onCloseTexturePicker(const LLSD& data); static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response); static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response); - // Make UI reflect state of currently selected material (refresh) - // and UI mode (e.g. editing normal map v diffuse map) - // - // @param force_set_values forces spinners to set value even if they are focused - void updateUI(bool force_set_values = false); - - // Convenience func to determine if all faces in selection have - // identical planar texgen settings during edits - // - bool isIdenticalPlanarTexgen(); - - // Callback funcs for individual controls - // - static void onCommitTextureInfo(LLUICtrl* ctrl, void* userdata); - static void onCommitTextureScaleX(LLUICtrl* ctrl, void* userdata); - static void onCommitTextureScaleY(LLUICtrl* ctrl, void* userdata); - static void onCommitTextureRot(LLUICtrl* ctrl, void* userdata); - static void onCommitTextureOffsetX(LLUICtrl* ctrl, void* userdata); - static void onCommitTextureOffsetY(LLUICtrl* ctrl, void* userdata); - - static void onCommitMaterialBumpyScaleX( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialBumpyScaleY( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialBumpyRot( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialBumpyOffsetX( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialBumpyOffsetY( LLUICtrl* ctrl, void* userdata); - - static void syncRepeatX(LLPanelFace* self, F32 scaleU); - static void syncRepeatY(LLPanelFace* self, F32 scaleV); - static void syncOffsetX(LLPanelFace* self, F32 offsetU); - static void syncOffsetY(LLPanelFace* self, F32 offsetV); - static void syncMaterialRot(LLPanelFace* self, F32 rot, int te = -1); - - static void onCommitMaterialShinyScaleX( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialShinyScaleY( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialShinyRot( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialShinyOffsetX( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialShinyOffsetY( LLUICtrl* ctrl, void* userdata); - - static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialID( LLUICtrl* ctrl, void* userdata); - - static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata); - static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata); - static void onCommitPbrType(LLUICtrl* ctrl, void* userdata); - static void onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata); - static void onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata); - static void onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata); - static void onCommitBump( LLUICtrl* ctrl, void* userdata); - static void onCommitTexGen( LLUICtrl* ctrl, void* userdata); - static void onCommitShiny( LLUICtrl* ctrl, void* userdata); - static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); - static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); - static void onCommitGlow( LLUICtrl* ctrl, void *userdata); - static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); - static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); + // Make UI reflect state of currently selected material (refresh) + // and UI mode (e.g. editing normal map v diffuse map) + // + // @param force_set_values forces spinners to set value even if they are focused + void updateUI(bool force_set_values = false); + + // Convenience func to determine if all faces in selection have + // identical planar texgen settings during edits + // + bool isIdenticalPlanarTexgen(); + + // Callback funcs for individual controls + // + static void onCommitTextureInfo(LLUICtrl* ctrl, void* userdata); + static void onCommitTextureScaleX(LLUICtrl* ctrl, void* userdata); + static void onCommitTextureScaleY(LLUICtrl* ctrl, void* userdata); + static void onCommitTextureRot(LLUICtrl* ctrl, void* userdata); + static void onCommitTextureOffsetX(LLUICtrl* ctrl, void* userdata); + static void onCommitTextureOffsetY(LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialBumpyScaleX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyScaleY( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyRot( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyOffsetX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyOffsetY( LLUICtrl* ctrl, void* userdata); + + static void syncRepeatX(LLPanelFace* self, F32 scaleU); + static void syncRepeatY(LLPanelFace* self, F32 scaleV); + static void syncOffsetX(LLPanelFace* self, F32 offsetU); + static void syncOffsetY(LLPanelFace* self, F32 offsetV); + static void syncMaterialRot(LLPanelFace* self, F32 rot, int te = -1); + + static void onCommitMaterialShinyScaleX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyScaleY( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyRot( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyOffsetX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyOffsetY( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialID( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialType( LLUICtrl* ctrl, void* userdata); + static void onCommitPbrType(LLUICtrl* ctrl, void* userdata); + static void onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata); + static void onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata); + static void onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata); + static void onCommitBump( LLUICtrl* ctrl, void* userdata); + static void onCommitTexGen( LLUICtrl* ctrl, void* userdata); + static void onCommitShiny( LLUICtrl* ctrl, void* userdata); + static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); + static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); + static void onCommitGlow( LLUICtrl* ctrl, void *userdata); + static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); + static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); void onCommitGLTFTextureScaleU(LLUICtrl* ctrl); void onCommitGLTFTextureScaleV(LLUICtrl* ctrl); @@ -245,11 +245,11 @@ protected: void onCommitGLTFTextureOffsetU(LLUICtrl* ctrl); void onCommitGLTFTextureOffsetV(LLUICtrl* ctrl); - static void onClickAutoFix(void*); - static void onAlignTexture(void*); - static void onClickBtnLoadInvPBR(void* userdata); - static void onClickBtnEditPBR(void* userdata); - static void onClickBtnSavePBR(void* userdata); + static void onClickAutoFix(void*); + static void onAlignTexture(void*); + static void onClickBtnLoadInvPBR(void* userdata); + static void onClickBtnEditPBR(void* userdata); + static void onClickBtnSavePBR(void* userdata); public: // needs to be accessible to selection manager void onCopyColor(); // records all selected faces @@ -263,200 +263,200 @@ protected: void menuDoToSelected(const LLSD& userdata); bool menuEnableItem(const LLSD& userdata); - static F32 valueGlow(LLViewerObject* object, S32 face); + static F32 valueGlow(LLViewerObject* object, S32 face); + - private: - bool isAlpha() { return mIsAlpha; } - - // Convenience funcs to keep the visual flack to a minimum - // - LLUUID getCurrentNormalMap(); - LLUUID getCurrentSpecularMap(); - U32 getCurrentShininess(); - U32 getCurrentBumpiness(); - U8 getCurrentDiffuseAlphaMode(); - U8 getCurrentAlphaMaskCutoff(); - U8 getCurrentEnvIntensity(); - U8 getCurrentGlossiness(); - F32 getCurrentBumpyRot(); - F32 getCurrentBumpyScaleU(); - F32 getCurrentBumpyScaleV(); - F32 getCurrentBumpyOffsetU(); - F32 getCurrentBumpyOffsetV(); - F32 getCurrentShinyRot(); - F32 getCurrentShinyScaleU(); - F32 getCurrentShinyScaleV(); - F32 getCurrentShinyOffsetU(); - F32 getCurrentShinyOffsetV(); + bool isAlpha() { return mIsAlpha; } + + // Convenience funcs to keep the visual flack to a minimum + // + LLUUID getCurrentNormalMap(); + LLUUID getCurrentSpecularMap(); + U32 getCurrentShininess(); + U32 getCurrentBumpiness(); + U8 getCurrentDiffuseAlphaMode(); + U8 getCurrentAlphaMaskCutoff(); + U8 getCurrentEnvIntensity(); + U8 getCurrentGlossiness(); + F32 getCurrentBumpyRot(); + F32 getCurrentBumpyScaleU(); + F32 getCurrentBumpyScaleV(); + F32 getCurrentBumpyOffsetU(); + F32 getCurrentBumpyOffsetV(); + F32 getCurrentShinyRot(); + F32 getCurrentShinyScaleU(); + F32 getCurrentShinyScaleV(); + F32 getCurrentShinyOffsetU(); + F32 getCurrentShinyOffsetV(); LLComboBox *mComboMatMedia; LLMediaCtrl *mTitleMedia; LLTextBox *mTitleMediaText; - // Update visibility of controls to match current UI mode - // (e.g. materials vs media editing) - // - // Do NOT call updateUI from within this function. - // - void updateVisibility(LLViewerObject* objectp = nullptr); - - // Hey look everyone, a type-safe alternative to copy and paste! :) - // - - // Update material parameters by applying 'edit_func' to selected TEs - // - template< - typename DataType, - typename SetValueType, - void (LLMaterial::*MaterialEditFunc)(SetValueType data) > - static void edit(LLPanelFace* p, DataType data, int te = -1, const LLUUID &only_for_object_id = LLUUID()) - { - LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc > edit(data); - struct LLSelectedTEEditMaterial : public LLSelectedTEMaterialFunctor - { - LLSelectedTEEditMaterial(LLPanelFace* panel, LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* editp, const LLUUID &only_for_object_id) : _panel(panel), _edit(editp), _only_for_object_id(only_for_object_id) {} - virtual ~LLSelectedTEEditMaterial() {}; - virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) - { - if (_edit && (_only_for_object_id.isNull() || _only_for_object_id == object->getID())) - { - LLMaterialPtr new_material = _panel->createDefaultMaterial(current_material); - llassert_always(new_material); - - // Determine correct alpha mode for current diffuse texture - // (i.e. does it have an alpha channel that makes alpha mode useful) - // - // _panel->isAlpha() "lies" when one face has alpha and the rest do not (NORSPEC-329) - // need to get per-face answer to this question for sane alpha mode retention on updates. - // - bool is_alpha_face = object->isImageAlphaBlended(face); - - // need to keep this original answer for valid comparisons in logic below - // - U8 original_default_alpha_mode = is_alpha_face ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - - U8 default_alpha_mode = original_default_alpha_mode; - - if (!current_material.isNull()) - { - default_alpha_mode = current_material->getDiffuseAlphaMode(); - } - - // Insure we don't inherit the default of blend by accident... - // this will be stomped by a legit request to change the alpha mode by the apply() below - // - new_material->setDiffuseAlphaMode(default_alpha_mode); - - // Do "It"! - // - _edit->apply(new_material); - - U32 new_alpha_mode = new_material->getDiffuseAlphaMode(); - LLUUID new_normal_map_id = new_material->getNormalID(); - LLUUID new_spec_map_id = new_material->getSpecularID(); - - if ((new_alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) && !is_alpha_face) - { - new_alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); - } - - bool is_default_blend_mode = (new_alpha_mode == original_default_alpha_mode); - bool is_need_material = !is_default_blend_mode || !new_normal_map_id.isNull() || !new_spec_map_id.isNull(); - - if (!is_need_material) - { - LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; - LLMaterialMgr::getInstance()->remove(object->getID(),face); - new_material = NULL; - } - else - { - LL_DEBUGS("Materials") << "Putting material on object " << object->getID() << " face " << face << ", material: " << new_material->asLLSD() << LL_ENDL; - LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material); - } - - object->setTEMaterialParams(face, new_material); - return new_material; - } - return NULL; - } - LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* _edit; - LLPanelFace *_panel; - const LLUUID & _only_for_object_id; - } editor(p, &edit, only_for_object_id); - LLSelectMgr::getInstance()->selectionSetMaterialParams(&editor, te); - } - - template< - typename DataType, - typename ReturnType, - ReturnType (LLMaterial::* const MaterialGetFunc)() const > - static void getTEMaterialValue(DataType& data_to_return, bool& identical,DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) - { - DataType data_value; - struct GetTEMaterialVal : public LLSelectedTEGetFunctor - { - GetTEMaterialVal(DataType default_value) : _default(default_value) {} - virtual ~GetTEMaterialVal() {} - - DataType get(LLViewerObject* object, S32 face) - { - DataType ret = _default; - LLMaterialPtr material_ptr; - LLTextureEntry* tep = object ? object->getTE(face) : NULL; - if (tep) - { - material_ptr = tep->getMaterialParams(); - if (!material_ptr.isNull()) - { - ret = (material_ptr->*(MaterialGetFunc))(); - } - } - return ret; - } - DataType _default; - } GetFunc(default_value); - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetFunc, data_value, has_tolerance, tolerance); - data_to_return = data_value; - } - - template< - typename DataType, - typename ReturnType, // some kids just have to different... - ReturnType (LLTextureEntry::* const TEGetFunc)() const > - static void getTEValue(DataType& data_to_return, bool& identical, DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) - { - DataType data_value; - struct GetTEVal : public LLSelectedTEGetFunctor - { - GetTEVal(DataType default_value) : _default(default_value) {} - virtual ~GetTEVal() {} - - DataType get(LLViewerObject* object, S32 face) { - LLTextureEntry* tep = object ? object->getTE(face) : NULL; - return tep ? ((tep->*(TEGetFunc))()) : _default; - } - DataType _default; - } GetTEValFunc(default_value); - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetTEValFunc, data_value, has_tolerance, tolerance ); - data_to_return = data_value; - } - - // Update vis and enabling of specific subsets of controls based on material params - // (e.g. hide the spec controls if no spec texture is applied) - // - void updateShinyControls(bool is_setting_texture = false, bool mess_with_combobox = false); - void updateBumpyControls(bool is_setting_texture = false, bool mess_with_combobox = false); - void updateAlphaControls(); - - /* - * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. - * If agent selects texture which is not allowed to be applied for the currently selected object, - * all controls of the floater texture picker which allow to apply the texture will be disabled. - */ + // Update visibility of controls to match current UI mode + // (e.g. materials vs media editing) + // + // Do NOT call updateUI from within this function. + // + void updateVisibility(LLViewerObject* objectp = nullptr); + + // Hey look everyone, a type-safe alternative to copy and paste! :) + // + + // Update material parameters by applying 'edit_func' to selected TEs + // + template< + typename DataType, + typename SetValueType, + void (LLMaterial::*MaterialEditFunc)(SetValueType data) > + static void edit(LLPanelFace* p, DataType data, int te = -1, const LLUUID &only_for_object_id = LLUUID()) + { + LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc > edit(data); + struct LLSelectedTEEditMaterial : public LLSelectedTEMaterialFunctor + { + LLSelectedTEEditMaterial(LLPanelFace* panel, LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* editp, const LLUUID &only_for_object_id) : _panel(panel), _edit(editp), _only_for_object_id(only_for_object_id) {} + virtual ~LLSelectedTEEditMaterial() {}; + virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) + { + if (_edit && (_only_for_object_id.isNull() || _only_for_object_id == object->getID())) + { + LLMaterialPtr new_material = _panel->createDefaultMaterial(current_material); + llassert_always(new_material); + + // Determine correct alpha mode for current diffuse texture + // (i.e. does it have an alpha channel that makes alpha mode useful) + // + // _panel->isAlpha() "lies" when one face has alpha and the rest do not (NORSPEC-329) + // need to get per-face answer to this question for sane alpha mode retention on updates. + // + bool is_alpha_face = object->isImageAlphaBlended(face); + + // need to keep this original answer for valid comparisons in logic below + // + U8 original_default_alpha_mode = is_alpha_face ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + + U8 default_alpha_mode = original_default_alpha_mode; + + if (!current_material.isNull()) + { + default_alpha_mode = current_material->getDiffuseAlphaMode(); + } + + // Insure we don't inherit the default of blend by accident... + // this will be stomped by a legit request to change the alpha mode by the apply() below + // + new_material->setDiffuseAlphaMode(default_alpha_mode); + + // Do "It"! + // + _edit->apply(new_material); + + U32 new_alpha_mode = new_material->getDiffuseAlphaMode(); + LLUUID new_normal_map_id = new_material->getNormalID(); + LLUUID new_spec_map_id = new_material->getSpecularID(); + + if ((new_alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) && !is_alpha_face) + { + new_alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + + bool is_default_blend_mode = (new_alpha_mode == original_default_alpha_mode); + bool is_need_material = !is_default_blend_mode || !new_normal_map_id.isNull() || !new_spec_map_id.isNull(); + + if (!is_need_material) + { + LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; + LLMaterialMgr::getInstance()->remove(object->getID(),face); + new_material = NULL; + } + else + { + LL_DEBUGS("Materials") << "Putting material on object " << object->getID() << " face " << face << ", material: " << new_material->asLLSD() << LL_ENDL; + LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material); + } + + object->setTEMaterialParams(face, new_material); + return new_material; + } + return NULL; + } + LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* _edit; + LLPanelFace *_panel; + const LLUUID & _only_for_object_id; + } editor(p, &edit, only_for_object_id); + LLSelectMgr::getInstance()->selectionSetMaterialParams(&editor, te); + } + + template< + typename DataType, + typename ReturnType, + ReturnType (LLMaterial::* const MaterialGetFunc)() const > + static void getTEMaterialValue(DataType& data_to_return, bool& identical,DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) + { + DataType data_value; + struct GetTEMaterialVal : public LLSelectedTEGetFunctor + { + GetTEMaterialVal(DataType default_value) : _default(default_value) {} + virtual ~GetTEMaterialVal() {} + + DataType get(LLViewerObject* object, S32 face) + { + DataType ret = _default; + LLMaterialPtr material_ptr; + LLTextureEntry* tep = object ? object->getTE(face) : NULL; + if (tep) + { + material_ptr = tep->getMaterialParams(); + if (!material_ptr.isNull()) + { + ret = (material_ptr->*(MaterialGetFunc))(); + } + } + return ret; + } + DataType _default; + } GetFunc(default_value); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetFunc, data_value, has_tolerance, tolerance); + data_to_return = data_value; + } + + template< + typename DataType, + typename ReturnType, // some kids just have to different... + ReturnType (LLTextureEntry::* const TEGetFunc)() const > + static void getTEValue(DataType& data_to_return, bool& identical, DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) + { + DataType data_value; + struct GetTEVal : public LLSelectedTEGetFunctor + { + GetTEVal(DataType default_value) : _default(default_value) {} + virtual ~GetTEVal() {} + + DataType get(LLViewerObject* object, S32 face) { + LLTextureEntry* tep = object ? object->getTE(face) : NULL; + return tep ? ((tep->*(TEGetFunc))()) : _default; + } + DataType _default; + } GetTEValFunc(default_value); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetTEValFunc, data_value, has_tolerance, tolerance ); + data_to_return = data_value; + } + + // Update vis and enabling of specific subsets of controls based on material params + // (e.g. hide the spec controls if no spec texture is applied) + // + void updateShinyControls(bool is_setting_texture = false, bool mess_with_combobox = false); + void updateBumpyControls(bool is_setting_texture = false, bool mess_with_combobox = false); + void updateAlphaControls(); + + /* + * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. + * If agent selects texture which is not allowed to be applied for the currently selected object, + * all controls of the floater texture picker which allow to apply the texture will be disabled. + */ void onTextureSelectionChanged(LLInventoryItem* itemp); void onPbrSelectionChanged(LLInventoryItem* itemp); @@ -471,8 +471,8 @@ private: LLMenuButton* mMenuClipboardColor; LLMenuButton* mMenuClipboardTexture; - bool mIsAlpha; - + bool mIsAlpha; + LLSD mClipboardParams; LLSD mMediaSettings; @@ -515,17 +515,17 @@ private: std::unique_ptr mVOInventoryListener; public: - #if defined(DEF_GET_MAT_STATE) - #undef DEF_GET_MAT_STATE - #endif + #if defined(DEF_GET_MAT_STATE) + #undef DEF_GET_MAT_STATE + #endif - #if defined(DEF_GET_TE_STATE) - #undef DEF_GET_TE_STATE - #endif + #if defined(DEF_GET_TE_STATE) + #undef DEF_GET_TE_STATE + #endif - #if defined(DEF_EDIT_MAT_STATE) - DEF_EDIT_MAT_STATE - #endif + #if defined(DEF_EDIT_MAT_STATE) + DEF_EDIT_MAT_STATE + #endif // Accessors for selected TE material state // @@ -551,74 +551,74 @@ public: getTEValue< DataType, ReturnType, &LLTextureEntry::TexEntryMemberFunc >(data, identical, DefaultValue, has_tolerance, tolerance); \ } - class LLSelectedTEMaterial - { - public: - static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material); - static void getMaxSpecularRepeats(F32& repeats, bool& identical); - static void getMaxNormalRepeats(F32& repeats, bool& identical); - static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha); - - DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getNormalID,LLUUID::null, false, LLUUID::null) - DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getSpecularID,LLUUID::null, false, LLUUID::null) - DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatX,1.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatY,1.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetX,0.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetY,0.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getSpecularRotation,0.0f, true, 0.001f) - - DEF_GET_MAT_STATE(F32,F32,getNormalRepeatX,1.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getNormalRepeatY,1.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getNormalOffsetX,0.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getNormalOffsetY,0.0f, true, 0.001f) - DEF_GET_MAT_STATE(F32,F32,getNormalRotation,0.0f, true, 0.001f) - - DEF_EDIT_MAT_STATE(U8,U8,setDiffuseAlphaMode); - DEF_EDIT_MAT_STATE(U8,U8,setAlphaMaskCutoff); - - DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetX); - DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetY); - DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatX); - DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatY); - DEF_EDIT_MAT_STATE(F32,F32,setNormalRotation); - - DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetX); - DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetY); - DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatX); - DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatY); - DEF_EDIT_MAT_STATE(F32,F32,setSpecularRotation); - - DEF_EDIT_MAT_STATE(U8,U8,setEnvironmentIntensity); - DEF_EDIT_MAT_STATE(U8,U8,setSpecularLightExponent); - - DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID); - DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID); - DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor); - }; - - class LLSelectedTE - { - public: - static void getFace(class LLFace*& face_to_return, bool& identical_face); - static void getImageFormat(LLGLenum& image_format_to_return, bool& identical_face); - static void getTexId(LLUUID& id, bool& identical); + class LLSelectedTEMaterial + { + public: + static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material); + static void getMaxSpecularRepeats(F32& repeats, bool& identical); + static void getMaxNormalRepeats(F32& repeats, bool& identical); + static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha); + + DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getNormalID,LLUUID::null, false, LLUUID::null) + DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getSpecularID,LLUUID::null, false, LLUUID::null) + DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatX,1.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatY,1.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetX,0.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetY,0.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getSpecularRotation,0.0f, true, 0.001f) + + DEF_GET_MAT_STATE(F32,F32,getNormalRepeatX,1.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getNormalRepeatY,1.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getNormalOffsetX,0.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getNormalOffsetY,0.0f, true, 0.001f) + DEF_GET_MAT_STATE(F32,F32,getNormalRotation,0.0f, true, 0.001f) + + DEF_EDIT_MAT_STATE(U8,U8,setDiffuseAlphaMode); + DEF_EDIT_MAT_STATE(U8,U8,setAlphaMaskCutoff); + + DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetX); + DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetY); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatX); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatY); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRotation); + + DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetX); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetY); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatX); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatY); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRotation); + + DEF_EDIT_MAT_STATE(U8,U8,setEnvironmentIntensity); + DEF_EDIT_MAT_STATE(U8,U8,setSpecularLightExponent); + + DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID); + DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID); + DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor); + }; + + class LLSelectedTE + { + public: + static void getFace(class LLFace*& face_to_return, bool& identical_face); + static void getImageFormat(LLGLenum& image_format_to_return, bool& identical_face); + static void getTexId(LLUUID& id, bool& identical); static void getPbrMaterialId(LLUUID& id, bool& identical, bool& has_pbr, bool& has_faces_without_pbr); - static void getObjectScaleS(F32& scale_s, bool& identical); - static void getObjectScaleT(F32& scale_t, bool& identical); - static void getMaxDiffuseRepeats(F32& repeats, bool& identical); - - DEF_GET_TE_STATE(U8,U8,getBumpmap,0, false, 0) - DEF_GET_TE_STATE(U8,U8,getShiny,0, false, 0) - DEF_GET_TE_STATE(U8,U8,getFullbright,0, false, 0) - DEF_GET_TE_STATE(F32,F32,getRotation,0.0f, true, 0.001f) - DEF_GET_TE_STATE(F32,F32,getOffsetS,0.0f, true, 0.001f) - DEF_GET_TE_STATE(F32,F32,getOffsetT,0.0f, true, 0.001f) - DEF_GET_TE_STATE(F32,F32,getScaleS,1.0f, true, 0.001f) - DEF_GET_TE_STATE(F32,F32,getScaleT,1.0f, true, 0.001f) - DEF_GET_TE_STATE(F32,F32,getGlow,0.0f, true, 0.001f) - DEF_GET_TE_STATE(LLTextureEntry::e_texgen,LLTextureEntry::e_texgen,getTexGen,LLTextureEntry::TEX_GEN_DEFAULT, false, LLTextureEntry::TEX_GEN_DEFAULT) - DEF_GET_TE_STATE(LLColor4,const LLColor4&,getColor,LLColor4::white, false, LLColor4::black); - }; + static void getObjectScaleS(F32& scale_s, bool& identical); + static void getObjectScaleT(F32& scale_t, bool& identical); + static void getMaxDiffuseRepeats(F32& repeats, bool& identical); + + DEF_GET_TE_STATE(U8,U8,getBumpmap,0, false, 0) + DEF_GET_TE_STATE(U8,U8,getShiny,0, false, 0) + DEF_GET_TE_STATE(U8,U8,getFullbright,0, false, 0) + DEF_GET_TE_STATE(F32,F32,getRotation,0.0f, true, 0.001f) + DEF_GET_TE_STATE(F32,F32,getOffsetS,0.0f, true, 0.001f) + DEF_GET_TE_STATE(F32,F32,getOffsetT,0.0f, true, 0.001f) + DEF_GET_TE_STATE(F32,F32,getScaleS,1.0f, true, 0.001f) + DEF_GET_TE_STATE(F32,F32,getScaleT,1.0f, true, 0.001f) + DEF_GET_TE_STATE(F32,F32,getGlow,0.0f, true, 0.001f) + DEF_GET_TE_STATE(LLTextureEntry::e_texgen,LLTextureEntry::e_texgen,getTexGen,LLTextureEntry::TEX_GEN_DEFAULT, false, LLTextureEntry::TEX_GEN_DEFAULT) + DEF_GET_TE_STATE(LLColor4,const LLColor4&,getColor,LLColor4::white, false, LLColor4::black); + }; }; #endif diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 2db431d165..5111241e92 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llpanelmaininventory.cpp * @brief Implementation of llpanelmaininventory. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -77,29 +77,29 @@ static LLPanelInjector t_inventory("panel_main_inventory") class LLFloaterInventoryFinder : public LLFloater { public: - LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view); - virtual void draw(); - /*virtual*/ BOOL postBuild(); - void changeFilter(LLInventoryFilter* filter); - void updateElementsFromFilter(); - BOOL getCheckShowEmpty(); - BOOL getCheckSinceLogoff(); - U32 getDateSearchDirection(); - - void onCreatorSelfFilterCommit(); - void onCreatorOtherFilterCommit(); - - static void onTimeAgo(LLUICtrl*, void *); - static void onCloseBtn(void* user_data); - static void selectAllTypes(void* user_data); - static void selectNoTypes(void* user_data); + LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view); + virtual void draw(); + /*virtual*/ BOOL postBuild(); + void changeFilter(LLInventoryFilter* filter); + void updateElementsFromFilter(); + BOOL getCheckShowEmpty(); + BOOL getCheckSinceLogoff(); + U32 getDateSearchDirection(); + + void onCreatorSelfFilterCommit(); + void onCreatorOtherFilterCommit(); + + static void onTimeAgo(LLUICtrl*, void *); + static void onCloseBtn(void* user_data); + static void selectAllTypes(void* user_data); + static void selectNoTypes(void* user_data); private: - LLPanelMainInventory* mPanelMainInventory; - LLSpinCtrl* mSpinSinceDays; - LLSpinCtrl* mSpinSinceHours; - LLCheckBoxCtrl* mCreatorSelf; - LLCheckBoxCtrl* mCreatorOthers; - LLInventoryFilter* mFilter; + LLPanelMainInventory* mPanelMainInventory; + LLSpinCtrl* mSpinSinceDays; + LLSpinCtrl* mSpinSinceHours; + LLCheckBoxCtrl* mCreatorSelf; + LLCheckBoxCtrl* mCreatorOthers; + LLInventoryFilter* mFilter; }; ///---------------------------------------------------------------------------- @@ -107,15 +107,15 @@ private: ///---------------------------------------------------------------------------- LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) - : LLPanel(p), - mActivePanel(NULL), - mWornItemsPanel(NULL), - mSavedFolderState(NULL), - mFilterText(""), - mMenuGearDefault(NULL), - mMenuVisibility(NULL), - mMenuAddHandle(), - mNeedUploadCost(true), + : LLPanel(p), + mActivePanel(NULL), + mWornItemsPanel(NULL), + mSavedFolderState(NULL), + mFilterText(""), + mMenuGearDefault(NULL), + mMenuVisibility(NULL), + mMenuAddHandle(), + mNeedUploadCost(true), mMenuViewDefault(NULL), mSingleFolderMode(false), mForceShowInvLayout(false), @@ -123,128 +123,128 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mListViewRootUpdatedConnection(), mGalleryRootUpdatedConnection() { - // Menu Callbacks (non contex menus) - mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this)); - mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); - mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); - mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2)); - mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); - mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); - mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); + // Menu Callbacks (non contex menus) + mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this)); + mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); + mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); + mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2)); + mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); + mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); + mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); mEnableCallbackRegistrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasSettingsInventory(); }); mEnableCallbackRegistrar.add("Inventory.MaterialsEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasMaterialsInventory(); }); - mSavedFolderState = new LLSaveFolderState(); - mSavedFolderState->setApply(FALSE); + mSavedFolderState = new LLSaveFolderState(); + mSavedFolderState->setApply(FALSE); } BOOL LLPanelMainInventory::postBuild() { - gInventory.addObserver(this); - - mFilterTabs = getChild("inventory filter tabs"); - mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); - + gInventory.addObserver(this); + + mFilterTabs = getChild("inventory filter tabs"); + mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); + mCounterCtrl = getChild("ItemcountText"); - - //panel->getFilter().markDefault(); - - // Set up the default inv. panel/filter settings. - mActivePanel = getChild(ALL_ITEMS); - if (mActivePanel) - { - // "All Items" is the previous only view, so it gets the InventorySortOrder - mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); - mActivePanel->getFilter().markDefault(); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2)); - mResortActivePanel = true; - } - LLInventoryPanel* recent_items_panel = getChild(RECENT_ITEMS); - if (recent_items_panel) - { - // assign default values until we will be sure that we have setting to restore - recent_items_panel->setSinceLogoff(TRUE); - recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); - recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); - recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); - recent_filter.setEmptyLookupMessage("InventoryNoMatchingRecentItems"); - recent_filter.markDefault(); - recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); - } - - mWornItemsPanel = getChild(WORN_ITEMS); - if (mWornItemsPanel) - { - U32 filter_types = 0x0; - filter_types |= 0x1 << LLInventoryType::IT_WEARABLE; - filter_types |= 0x1 << LLInventoryType::IT_ATTACHMENT; - filter_types |= 0x1 << LLInventoryType::IT_OBJECT; - mWornItemsPanel->setFilterTypes(filter_types); - mWornItemsPanel->setFilterWorn(); - mWornItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mWornItemsPanel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); - LLInventoryFilter& worn_filter = mWornItemsPanel->getFilter(); - worn_filter.setFilterCategoryTypes(worn_filter.getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); - worn_filter.markDefault(); - mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2)); - } - mSearchTypeCombo = getChild("search_type"); - if(mSearchTypeCombo) - { - mSearchTypeCombo->setCommitCallback(boost::bind(&LLPanelMainInventory::onSelectSearchType, this)); - } - // Now load the stored settings from disk, if available. - std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); - LL_INFOS("Inventory") << "LLPanelMainInventory::init: reading from " << filterSaveName << LL_ENDL; - llifstream file(filterSaveName.c_str()); - LLSD savedFilterState; - if (file.is_open()) - { - LLSDSerialize::fromXML(savedFilterState, file); - file.close(); - - // Load the persistent "Recent Items" settings. - // Note that the "All Items" settings do not persist. - if(recent_items_panel) - { - if(savedFilterState.has(recent_items_panel->getFilter().getName())) - { - LLSD recent_items = savedFilterState.get( - recent_items_panel->getFilter().getName()); - LLInventoryFilter::Params p; - LLParamSDParser parser; - parser.readSD(recent_items, p); - recent_items_panel->getFilter().fromParams(p); - recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); - } - } - if(mActivePanel) - { - if(savedFilterState.has(mActivePanel->getFilter().getName())) - { - LLSD items = savedFilterState.get(mActivePanel->getFilter().getName()); - LLInventoryFilter::Params p; - LLParamSDParser parser; - parser.readSD(items, p); - mActivePanel->getFilter().setSearchVisibilityTypes(p); - } - } - - } - - mFilterEditor = getChild("inventory search editor"); - if (mFilterEditor) - { - mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2)); - } - - mGearMenuButton = getChild("options_gear_btn"); - mVisibilityMenuButton = getChild("options_visibility_btn"); + + //panel->getFilter().markDefault(); + + // Set up the default inv. panel/filter settings. + mActivePanel = getChild(ALL_ITEMS); + if (mActivePanel) + { + // "All Items" is the previous only view, so it gets the InventorySortOrder + mActivePanel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER)); + mActivePanel->getFilter().markDefault(); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2)); + mResortActivePanel = true; + } + LLInventoryPanel* recent_items_panel = getChild(RECENT_ITEMS); + if (recent_items_panel) + { + // assign default values until we will be sure that we have setting to restore + recent_items_panel->setSinceLogoff(TRUE); + recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); + recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + LLInventoryFilter& recent_filter = recent_items_panel->getFilter(); + recent_filter.setFilterObjectTypes(recent_filter.getFilterObjectTypes() & ~(0x1 << LLInventoryType::IT_CATEGORY)); + recent_filter.setEmptyLookupMessage("InventoryNoMatchingRecentItems"); + recent_filter.markDefault(); + recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2)); + } + + mWornItemsPanel = getChild(WORN_ITEMS); + if (mWornItemsPanel) + { + U32 filter_types = 0x0; + filter_types |= 0x1 << LLInventoryType::IT_WEARABLE; + filter_types |= 0x1 << LLInventoryType::IT_ATTACHMENT; + filter_types |= 0x1 << LLInventoryType::IT_OBJECT; + mWornItemsPanel->setFilterTypes(filter_types); + mWornItemsPanel->setFilterWorn(); + mWornItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mWornItemsPanel->setFilterLinks(LLInventoryFilter::FILTERLINK_EXCLUDE_LINKS); + LLInventoryFilter& worn_filter = mWornItemsPanel->getFilter(); + worn_filter.setFilterCategoryTypes(worn_filter.getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX)); + worn_filter.markDefault(); + mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2)); + } + mSearchTypeCombo = getChild("search_type"); + if(mSearchTypeCombo) + { + mSearchTypeCombo->setCommitCallback(boost::bind(&LLPanelMainInventory::onSelectSearchType, this)); + } + // Now load the stored settings from disk, if available. + std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); + LL_INFOS("Inventory") << "LLPanelMainInventory::init: reading from " << filterSaveName << LL_ENDL; + llifstream file(filterSaveName.c_str()); + LLSD savedFilterState; + if (file.is_open()) + { + LLSDSerialize::fromXML(savedFilterState, file); + file.close(); + + // Load the persistent "Recent Items" settings. + // Note that the "All Items" settings do not persist. + if(recent_items_panel) + { + if(savedFilterState.has(recent_items_panel->getFilter().getName())) + { + LLSD recent_items = savedFilterState.get( + recent_items_panel->getFilter().getName()); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(recent_items, p); + recent_items_panel->getFilter().fromParams(p); + recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); + } + } + if(mActivePanel) + { + if(savedFilterState.has(mActivePanel->getFilter().getName())) + { + LLSD items = savedFilterState.get(mActivePanel->getFilter().getName()); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(items, p); + mActivePanel->getFilter().setSearchVisibilityTypes(p); + } + } + + } + + mFilterEditor = getChild("inventory search editor"); + if (mFilterEditor) + { + mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2)); + } + + mGearMenuButton = getChild("options_gear_btn"); + mVisibilityMenuButton = getChild("options_visibility_btn"); mViewMenuButton = getChild("view_btn"); mBackBtn = getChild("back_btn"); @@ -274,73 +274,73 @@ BOOL LLPanelMainInventory::postBuild() mGalleryRootUpdatedConnection = mCombinationGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, true)); mCombinationGalleryPanel->setSelectionChangeCallback(boost::bind(&LLPanelMainInventory::onCombinationGallerySelectionChanged, this, _1)); - initListCommandsHandlers(); + initListCommandsHandlers(); - const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); - const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); + const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); + const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); - if (menu) - { - menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); - menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); - } + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { + menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); + menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); + } - // Trigger callback for focus received so we can deselect items in inbox/outbox - LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this)); + // Trigger callback for focus received so we can deselect items in inbox/outbox + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMainInventory::onFocusReceived, this)); - return TRUE; + return TRUE; } // Destroys the object LLPanelMainInventory::~LLPanelMainInventory( void ) { - // Save the filters state. - // Some params types cannot be saved this way - // for example, LLParamSDParser doesn't know about U64, - // so some FilterOps params should be revised. - LLSD filterRoot; - LLInventoryPanel* all_items_panel = getChild(ALL_ITEMS); - if (all_items_panel) - { - LLSD filterState; - LLInventoryPanel::InventoryState p; - all_items_panel->getFilter().toParams(p.filter); - all_items_panel->getRootViewModel().getSorter().toParams(p.sort); - if (p.validateBlock(false)) - { - LLParamSDParser().writeSD(filterState, p); - filterRoot[all_items_panel->getName()] = filterState; - } - } - - LLInventoryPanel* panel = findChild(RECENT_ITEMS); - if (panel) - { - LLSD filterState; - LLInventoryPanel::InventoryState p; - panel->getFilter().toParams(p.filter); - panel->getRootViewModel().getSorter().toParams(p.sort); - if (p.validateBlock(false)) - { - LLParamSDParser().writeSD(filterState, p); - filterRoot[panel->getName()] = filterState; - } - } - - std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); - llofstream filtersFile(filterSaveName.c_str()); - if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) - { - LL_WARNS() << "Could not write to filters save file " << filterSaveName << LL_ENDL; - } - else - { - filtersFile.close(); - } - - gInventory.removeObserver(this); - delete mSavedFolderState; + // Save the filters state. + // Some params types cannot be saved this way + // for example, LLParamSDParser doesn't know about U64, + // so some FilterOps params should be revised. + LLSD filterRoot; + LLInventoryPanel* all_items_panel = getChild(ALL_ITEMS); + if (all_items_panel) + { + LLSD filterState; + LLInventoryPanel::InventoryState p; + all_items_panel->getFilter().toParams(p.filter); + all_items_panel->getRootViewModel().getSorter().toParams(p.sort); + if (p.validateBlock(false)) + { + LLParamSDParser().writeSD(filterState, p); + filterRoot[all_items_panel->getName()] = filterState; + } + } + + LLInventoryPanel* panel = findChild(RECENT_ITEMS); + if (panel) + { + LLSD filterState; + LLInventoryPanel::InventoryState p; + panel->getFilter().toParams(p.filter); + panel->getRootViewModel().getSorter().toParams(p.sort); + if (p.validateBlock(false)) + { + LLParamSDParser().writeSD(filterState, p); + filterRoot[panel->getName()] = filterState; + } + } + + std::string filterSaveName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME)); + llofstream filtersFile(filterSaveName.c_str()); + if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) + { + LL_WARNS() << "Could not write to filters save file " << filterSaveName << LL_ENDL; + } + else + { + filtersFile.close(); + } + + gInventory.removeObserver(this); + delete mSavedFolderState; auto menu = mMenuAddHandle.get(); if(menu) @@ -361,57 +361,57 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() { - return getChild(ALL_ITEMS); + return getChild(ALL_ITEMS); } void LLPanelMainInventory::selectAllItemsPanel() { - mFilterTabs->selectFirstTab(); + mFilterTabs->selectFirstTab(); } bool LLPanelMainInventory::isRecentItemsPanelSelected() { - return (RECENT_ITEMS == getActivePanel()->getName()); + return (RECENT_ITEMS == getActivePanel()->getName()); } void LLPanelMainInventory::startSearch() { - // this forces focus to line editor portion of search editor - if (mFilterEditor) - { - mFilterEditor->focusFirstItem(TRUE); - } + // this forces focus to line editor portion of search editor + if (mFilterEditor) + { + mFilterEditor->focusFirstItem(TRUE); + } } BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) { - LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; - if (root_folder) - { - // first check for user accepting current search results - if (mFilterEditor - && mFilterEditor->hasFocus() - && (key == KEY_RETURN - || key == KEY_DOWN) - && mask == MASK_NONE) - { - // move focus to inventory proper - mActivePanel->setFocus(TRUE); - root_folder->scrollToShowSelection(); - return TRUE; - } - - if (mActivePanel->hasFocus() && key == KEY_UP) - { - startSearch(); - } + LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; + if (root_folder) + { + // first check for user accepting current search results + if (mFilterEditor + && mFilterEditor->hasFocus() + && (key == KEY_RETURN + || key == KEY_DOWN) + && mask == MASK_NONE) + { + // move focus to inventory proper + mActivePanel->setFocus(TRUE); + root_folder->scrollToShowSelection(); + return TRUE; + } + + if (mActivePanel->hasFocus() && key == KEY_UP) + { + startSearch(); + } if(mSingleFolderMode && key == KEY_LEFT) { onBackFolderClicked(); } - } + } - return LLPanel::handleKeyHere(key, mask); + return LLPanel::handleKeyHere(key, mask); } @@ -420,12 +420,12 @@ BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) void LLPanelMainInventory::doToSelected(const LLSD& userdata) { - getPanel()->doToSelected(userdata); + getPanel()->doToSelected(userdata); } void LLPanelMainInventory::closeAllFolders() { - getPanel()->getRootFolder()->closeAllFolders(); + getPanel()->getRootFolder()->closeAllFolders(); } S32 get_instance_num() @@ -440,13 +440,13 @@ LLFloaterSidePanelContainer* LLPanelMainInventory::newWindow() { S32 instance_num = get_instance_num(); - if (!gAgentCamera.cameraMouselook()) - { + if (!gAgentCamera.cameraMouselook()) + { LLFloaterSidePanelContainer* floater = LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); LLSidepanelInventory* sidepanel_inventory = floater->findChild("main_panel"); sidepanel_inventory->initInventoryViews(); - return floater; - } + return floater; + } return NULL; } @@ -476,7 +476,7 @@ void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_sele } } } - + S32 instance_num = get_instance_num(); LLFloaterSidePanelContainer* inventory_container = LLFloaterReg::showTypedInstance("inventory", LLSD(instance_num)); @@ -504,7 +504,7 @@ void LLPanelMainInventory::newFolderWindow(LLUUID folder_id, LLUUID item_to_sele void LLPanelMainInventory::doCreate(const LLSD& userdata) { - reset_inventory_filter(); + reset_inventory_filter(); if(mSingleFolderMode) { if(isListViewMode() || isCombinationViewMode()) @@ -565,14 +565,14 @@ void LLPanelMainInventory::doCreate(const LLSD& userdata) void LLPanelMainInventory::resetFilters() { - LLFloaterInventoryFinder *finder = getFinder(); - getCurrentFilter().resetDefault(); - if (finder) - { - finder->updateElementsFromFilter(); - } + LLFloaterInventoryFinder *finder = getFinder(); + getCurrentFilter().resetDefault(); + if (finder) + { + finder->updateElementsFromFilter(); + } - setFilterTextFromFilter(); + setFilterTextFromFilter(); } void LLPanelMainInventory::resetAllItemsFilters() @@ -600,44 +600,44 @@ void LLPanelMainInventory::findLinks(const LLUUID& item_id, const std::string& i void LLPanelMainInventory::setSortBy(const LLSD& userdata) { - U32 sort_order_mask = getActivePanel()->getSortOrder(); - std::string sort_type = userdata.asString(); - if (sort_type == "name") - { - sort_order_mask &= ~LLInventoryFilter::SO_DATE; - } - else if (sort_type == "date") - { - sort_order_mask |= LLInventoryFilter::SO_DATE; - } - else if (sort_type == "foldersalwaysbyname") - { - if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME ) - { - sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - else - { - sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME; - } - } - else if (sort_type == "systemfolderstotop") - { - if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) - { - sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - else - { - sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } - } + U32 sort_order_mask = getActivePanel()->getSortOrder(); + std::string sort_type = userdata.asString(); + if (sort_type == "name") + { + sort_order_mask &= ~LLInventoryFilter::SO_DATE; + } + else if (sort_type == "date") + { + sort_order_mask |= LLInventoryFilter::SO_DATE; + } + else if (sort_type == "foldersalwaysbyname") + { + if ( sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME ) + { + sort_order_mask &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; + } + else + { + sort_order_mask |= LLInventoryFilter::SO_FOLDERS_BY_NAME; + } + } + else if (sort_type == "systemfolderstotop") + { + if ( sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) + { + sort_order_mask &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + } + else + { + sort_order_mask |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + } + } if(mSingleFolderMode && !isListViewMode()) { mCombinationGalleryPanel->setSortOrder(sort_order_mask, true); } - getActivePanel()->setSortOrder(sort_order_mask); + getActivePanel()->setSortOrder(sort_order_mask); if (isRecentItemsPanelSelected()) { gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask); @@ -650,23 +650,23 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata) void LLPanelMainInventory::onSelectSearchType() { - std::string new_type = mSearchTypeCombo->getValue(); - if (new_type == "search_by_name") - { - setSearchType(LLInventoryFilter::SEARCHTYPE_NAME); - } - if (new_type == "search_by_creator") - { - setSearchType(LLInventoryFilter::SEARCHTYPE_CREATOR); - } - if (new_type == "search_by_description") - { - setSearchType(LLInventoryFilter::SEARCHTYPE_DESCRIPTION); - } - if (new_type == "search_by_UUID") - { - setSearchType(LLInventoryFilter::SEARCHTYPE_UUID); - } + std::string new_type = mSearchTypeCombo->getValue(); + if (new_type == "search_by_name") + { + setSearchType(LLInventoryFilter::SEARCHTYPE_NAME); + } + if (new_type == "search_by_creator") + { + setSearchType(LLInventoryFilter::SEARCHTYPE_CREATOR); + } + if (new_type == "search_by_description") + { + setSearchType(LLInventoryFilter::SEARCHTYPE_DESCRIPTION); + } + if (new_type == "search_by_UUID") + { + setSearchType(LLInventoryFilter::SEARCHTYPE_UUID); + } } void LLPanelMainInventory::setSearchType(LLInventoryFilter::ESearchType type) @@ -703,70 +703,70 @@ void LLPanelMainInventory::updateSearchTypeCombo() search_type = getActivePanel()->getSearchType(); } - switch(search_type) - { - case LLInventoryFilter::SEARCHTYPE_CREATOR: - mSearchTypeCombo->setValue("search_by_creator"); - break; - case LLInventoryFilter::SEARCHTYPE_DESCRIPTION: - mSearchTypeCombo->setValue("search_by_description"); - break; - case LLInventoryFilter::SEARCHTYPE_UUID: - mSearchTypeCombo->setValue("search_by_UUID"); - break; - case LLInventoryFilter::SEARCHTYPE_NAME: - default: - mSearchTypeCombo->setValue("search_by_name"); - break; - } + switch(search_type) + { + case LLInventoryFilter::SEARCHTYPE_CREATOR: + mSearchTypeCombo->setValue("search_by_creator"); + break; + case LLInventoryFilter::SEARCHTYPE_DESCRIPTION: + mSearchTypeCombo->setValue("search_by_description"); + break; + case LLInventoryFilter::SEARCHTYPE_UUID: + mSearchTypeCombo->setValue("search_by_UUID"); + break; + case LLInventoryFilter::SEARCHTYPE_NAME: + default: + mSearchTypeCombo->setValue("search_by_name"); + break; + } } // static BOOL LLPanelMainInventory::filtersVisible(void* user_data) { - LLPanelMainInventory* self = (LLPanelMainInventory*)user_data; - if(!self) return FALSE; + LLPanelMainInventory* self = (LLPanelMainInventory*)user_data; + if(!self) return FALSE; - return self->getFinder() != NULL; + return self->getFinder() != NULL; } void LLPanelMainInventory::onClearSearch() { - BOOL initially_active = FALSE; - LLFloater *finder = getFinder(); - if (mActivePanel && (getActivePanel() != mWornItemsPanel)) - { - initially_active = mActivePanel->getFilter().isNotDefault(); - setFilterSubString(LLStringUtil::null); - mActivePanel->setFilterTypes(0xffffffffffffffffULL); - mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS); - } - - if (finder) - { - LLFloaterInventoryFinder::selectAllTypes(finder); - } - - // re-open folders that were initially open in case filter was active - if (mActivePanel && (mFilterSubString.size() || initially_active) && !mSingleFolderMode) - { - mSavedFolderState->setApply(TRUE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - LLOpenFoldersWithSelection opener; - mActivePanel->getRootFolder()->applyFunctorRecursively(opener); - mActivePanel->getRootFolder()->scrollToShowSelection(); - } - mFilterSubString = ""; - - LLSidepanelInventory * sidepanel_inventory = getParentSidepanelInventory(); - if (sidepanel_inventory) - { - LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild("marketplace_inbox"); - if (inbox_panel) - { - inbox_panel->onClearSearch(); - } - } + BOOL initially_active = FALSE; + LLFloater *finder = getFinder(); + if (mActivePanel && (getActivePanel() != mWornItemsPanel)) + { + initially_active = mActivePanel->getFilter().isNotDefault(); + setFilterSubString(LLStringUtil::null); + mActivePanel->setFilterTypes(0xffffffffffffffffULL); + mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS); + } + + if (finder) + { + LLFloaterInventoryFinder::selectAllTypes(finder); + } + + // re-open folders that were initially open in case filter was active + if (mActivePanel && (mFilterSubString.size() || initially_active) && !mSingleFolderMode) + { + mSavedFolderState->setApply(TRUE); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + LLOpenFoldersWithSelection opener; + mActivePanel->getRootFolder()->applyFunctorRecursively(opener); + mActivePanel->getRootFolder()->scrollToShowSelection(); + } + mFilterSubString = ""; + + LLSidepanelInventory * sidepanel_inventory = getParentSidepanelInventory(); + if (sidepanel_inventory) + { + LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild("marketplace_inbox"); + if (inbox_panel) + { + inbox_panel->onClearSearch(); + } + } } void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) @@ -782,15 +782,15 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) mCombinationGalleryPanel->setFilterSubString(search_string); } - if (search_string == "") - { - onClearSearch(); - } + if (search_string == "") + { + onClearSearch(); + } - if (!mActivePanel) - { - return; - } + if (!mActivePanel) + { + return; + } if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { @@ -798,215 +798,215 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) LLInventoryModelBackgroundFetch::instance().start(); } - mFilterSubString = search_string; - if (mActivePanel->getFilterSubString().empty() && mFilterSubString.empty()) - { - // current filter and new filter empty, do nothing - return; - } + mFilterSubString = search_string; + if (mActivePanel->getFilterSubString().empty() && mFilterSubString.empty()) + { + // current filter and new filter empty, do nothing + return; + } - // save current folder open state if no filter currently applied - if (!mActivePanel->getFilter().isNotDefault()) - { - mSavedFolderState->setApply(FALSE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - } + // save current folder open state if no filter currently applied + if (!mActivePanel->getFilter().isNotDefault()) + { + mSavedFolderState->setApply(FALSE); + mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); + } - // set new filter string - setFilterSubString(mFilterSubString); + // set new filter string + setFilterSubString(mFilterSubString); LLSidepanelInventory * sidepanel_inventory = getParentSidepanelInventory(); - if (sidepanel_inventory) - { - LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild("marketplace_inbox"); - if (inbox_panel) - { - inbox_panel->onFilterEdit(search_string); - } - } + if (sidepanel_inventory) + { + LLPanelMarketplaceInbox* inbox_panel = sidepanel_inventory->getChild("marketplace_inbox"); + if (inbox_panel) + { + inbox_panel->onFilterEdit(search_string); + } + } } //static BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward) { - LLPanelMainInventory* active_view = NULL; - - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLPanelMainInventory* iv = dynamic_cast(*iter); - if (iv) - { - if (gFocusMgr.childHasKeyboardFocus(iv)) - { - active_view = iv; - break; - } - } - } - - if (!active_view) - { - return FALSE; - } - - std::string search_string(find_text); - - if (search_string.empty()) - { - return FALSE; - } - - if (active_view->getPanel() && - active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward)) - { - return TRUE; - } - - return FALSE; + LLPanelMainInventory* active_view = NULL; + + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLPanelMainInventory* iv = dynamic_cast(*iter); + if (iv) + { + if (gFocusMgr.childHasKeyboardFocus(iv)) + { + active_view = iv; + break; + } + } + } + + if (!active_view) + { + return FALSE; + } + + std::string search_string(find_text); + + if (search_string.empty()) + { + return FALSE; + } + + if (active_view->getPanel() && + active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward)) + { + return TRUE; + } + + return FALSE; } void LLPanelMainInventory::onFilterSelected() { - // Find my index + // Find my index setActivePanel(); - if (!mActivePanel) - { - return; - } - - if (getActivePanel() == mWornItemsPanel) - { - mActivePanel->openAllFolders(); - } - updateSearchTypeCombo(); - setFilterSubString(mFilterSubString); - LLInventoryFilter& filter = getCurrentFilter(); - LLFloaterInventoryFinder *finder = getFinder(); - if (finder) - { - finder->changeFilter(&filter); + if (!mActivePanel) + { + return; + } + + if (getActivePanel() == mWornItemsPanel) + { + mActivePanel->openAllFolders(); + } + updateSearchTypeCombo(); + setFilterSubString(mFilterSubString); + LLInventoryFilter& filter = getCurrentFilter(); + LLFloaterInventoryFinder *finder = getFinder(); + if (finder) + { + finder->changeFilter(&filter); if (mSingleFolderMode) { finder->setTitle(getLocalizedRootName()); } - } - if (filter.isActive() && !LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) - { + } + if (filter.isActive() && !LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) + { llassert(false); // this should have been done on startup - LLInventoryModelBackgroundFetch::instance().start(); - } - setFilterTextFromFilter(); + LLInventoryModelBackgroundFetch::instance().start(); + } + setFilterTextFromFilter(); } -const std::string LLPanelMainInventory::getFilterSubString() -{ - return mActivePanel->getFilterSubString(); +const std::string LLPanelMainInventory::getFilterSubString() +{ + return mActivePanel->getFilterSubString(); } -void LLPanelMainInventory::setFilterSubString(const std::string& string) -{ - mActivePanel->setFilterSubString(string); +void LLPanelMainInventory::setFilterSubString(const std::string& string) +{ + mActivePanel->setFilterSubString(string); } BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Check to see if we are auto scrolling from the last frame - LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); - BOOL needsToScroll = panel->getScrollableContainer()->canAutoScroll(x, y); - if(mFilterTabs) - { - if(needsToScroll) - { - mFilterTabs->startDragAndDropDelayTimer(); - } - } - - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - return handled; + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Check to see if we are auto scrolling from the last frame + LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); + BOOL needsToScroll = panel->getScrollableContainer()->canAutoScroll(x, y); + if(mFilterTabs) + { + if(needsToScroll) + { + mFilterTabs->startDragAndDropDelayTimer(); + } + } + + BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + return handled; } // virtual void LLPanelMainInventory::changed(U32) { - updateItemcountText(); + updateItemcountText(); } void LLPanelMainInventory::setFocusFilterEditor() { - if(mFilterEditor) - { - mFilterEditor->setFocus(true); - } + if(mFilterEditor) + { + mFilterEditor->setFocus(true); + } } // virtual void LLPanelMainInventory::draw() { - if (mActivePanel && mFilterEditor) - { - mFilterEditor->setText(mFilterSubString); - } - if (mActivePanel && mResortActivePanel) - { - // EXP-756: Force resorting of the list the first time we draw the list: - // In the case of date sorting, we don't have enough information at initialization time - // to correctly sort the folders. Later manual resort doesn't do anything as the order value is - // set correctly. The workaround is to reset the order to alphabetical (or anything) then to the correct order. - U32 order = mActivePanel->getSortOrder(); - mActivePanel->setSortOrder(LLInventoryFilter::SO_NAME); - mActivePanel->setSortOrder(order); - mResortActivePanel = false; - } - LLPanel::draw(); - updateItemcountText(); + if (mActivePanel && mFilterEditor) + { + mFilterEditor->setText(mFilterSubString); + } + if (mActivePanel && mResortActivePanel) + { + // EXP-756: Force resorting of the list the first time we draw the list: + // In the case of date sorting, we don't have enough information at initialization time + // to correctly sort the folders. Later manual resort doesn't do anything as the order value is + // set correctly. The workaround is to reset the order to alphabetical (or anything) then to the correct order. + U32 order = mActivePanel->getSortOrder(); + mActivePanel->setSortOrder(LLInventoryFilter::SO_NAME); + mActivePanel->setSortOrder(order); + mResortActivePanel = false; + } + LLPanel::draw(); + updateItemcountText(); updateCombinationVisibility(); } void LLPanelMainInventory::updateItemcountText() { - if(mItemCount != gInventory.getItemCount()) - { - mItemCount = gInventory.getItemCount(); - mItemCountString = ""; - LLLocale locale(LLLocale::USER_LOCALE); - LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount); - } - - if(mCategoryCount != gInventory.getCategoryCount()) - { - mCategoryCount = gInventory.getCategoryCount(); - mCategoryCountString = ""; - LLLocale locale(LLLocale::USER_LOCALE); - LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount); - } - - LLStringUtil::format_map_t string_args; - string_args["[ITEM_COUNT]"] = mItemCountString; - string_args["[CATEGORY_COUNT]"] = mCategoryCountString; - string_args["[FILTER]"] = getFilterText(); - - std::string text = ""; - - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) - { - text = getString("ItemcountFetching", string_args); - } - else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) - { - text = getString("ItemcountCompleted", string_args); - } - else - { - text = getString("ItemcountUnknown", string_args); - } + if(mItemCount != gInventory.getItemCount()) + { + mItemCount = gInventory.getItemCount(); + mItemCountString = ""; + LLLocale locale(LLLocale::USER_LOCALE); + LLResMgr::getInstance()->getIntegerString(mItemCountString, mItemCount); + } + + if(mCategoryCount != gInventory.getCategoryCount()) + { + mCategoryCount = gInventory.getCategoryCount(); + mCategoryCountString = ""; + LLLocale locale(LLLocale::USER_LOCALE); + LLResMgr::getInstance()->getIntegerString(mCategoryCountString, mCategoryCount); + } + + LLStringUtil::format_map_t string_args; + string_args["[ITEM_COUNT]"] = mItemCountString; + string_args["[CATEGORY_COUNT]"] = mCategoryCountString; + string_args["[FILTER]"] = getFilterText(); + + std::string text = ""; + + if (LLInventoryModelBackgroundFetch::instance().folderFetchActive()) + { + text = getString("ItemcountFetching", string_args); + } + else if (LLInventoryModelBackgroundFetch::instance().isEverythingFetched()) + { + text = getString("ItemcountCompleted", string_args); + } + else + { + text = getString("ItemcountUnknown", string_args); + } if (mSingleFolderMode) { @@ -1022,40 +1022,40 @@ void LLPanelMainInventory::updateItemcountText() text = getString("ItemcountCompleted", string_args); } } - + mCounterCtrl->setValue(text); mCounterCtrl->setToolTip(text); } void LLPanelMainInventory::onFocusReceived() { - LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); - if (!sidepanel_inventory) - { - LL_WARNS() << "Could not find Inventory Panel in My Inventory floater" << LL_ENDL; - return; - } + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel("inventory"); + if (!sidepanel_inventory) + { + LL_WARNS() << "Could not find Inventory Panel in My Inventory floater" << LL_ENDL; + return; + } - sidepanel_inventory->clearSelections(false, true); + sidepanel_inventory->clearSelections(false, true); } -void LLPanelMainInventory::setFilterTextFromFilter() -{ - mFilterText = getCurrentFilter().getFilterText(); +void LLPanelMainInventory::setFilterTextFromFilter() +{ + mFilterText = getCurrentFilter().getFilterText(); } void LLPanelMainInventory::toggleFindOptions() { - LLFloater *floater = getFinder(); - if (!floater) - { - LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); - mFinderHandle = finder->getHandle(); - finder->openFloater(); + LLFloater *floater = getFinder(); + if (!floater) + { + LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); + mFinderHandle = finder->getHandle(); + finder->openFloater(); - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) - parent_floater->addDependentFloater(mFinderHandle); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + if (parent_floater) + parent_floater->addDependentFloater(mFinderHandle); if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { @@ -1067,232 +1067,232 @@ void LLPanelMainInventory::toggleFindOptions() { finder->setTitle(getLocalizedRootName()); } - } - else - { - floater->closeFloater(); - } + } + else + { + floater->closeFloater(); + } } void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { - getChild(ALL_ITEMS)->setSelectCallback(cb); - getChild(RECENT_ITEMS)->setSelectCallback(cb); + getChild(ALL_ITEMS)->setSelectCallback(cb); + getChild(RECENT_ITEMS)->setSelectCallback(cb); } void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque& items, BOOL user_action) { - updateListCommands(); - panel->onSelectionChange(items, user_action); + updateListCommands(); + panel->onSelectionChange(items, user_action); } ///---------------------------------------------------------------------------- /// LLFloaterInventoryFinder ///---------------------------------------------------------------------------- -LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() -{ - return (LLFloaterInventoryFinder*)mFinderHandle.get(); +LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() +{ + return (LLFloaterInventoryFinder*)mFinderHandle.get(); } -LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) : - LLFloater(LLSD()), - mPanelMainInventory(inventory_view), - mFilter(&inventory_view->getPanel()->getFilter()) +LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) : + LLFloater(LLSD()), + mPanelMainInventory(inventory_view), + mFilter(&inventory_view->getPanel()->getFilter()) { - buildFromFile("floater_inventory_view_finder.xml"); - updateElementsFromFilter(); + buildFromFile("floater_inventory_view_finder.xml"); + updateElementsFromFilter(); } BOOL LLFloaterInventoryFinder::postBuild() { - const LLRect& viewrect = mPanelMainInventory->getRect(); - setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); + const LLRect& viewrect = mPanelMainInventory->getRect(); + setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); - childSetAction("All", selectAllTypes, this); - childSetAction("None", selectNoTypes, this); + childSetAction("All", selectAllTypes, this); + childSetAction("None", selectNoTypes, this); - mSpinSinceHours = getChild("spin_hours_ago"); - childSetCommitCallback("spin_hours_ago", onTimeAgo, this); + mSpinSinceHours = getChild("spin_hours_ago"); + childSetCommitCallback("spin_hours_ago", onTimeAgo, this); - mSpinSinceDays = getChild("spin_days_ago"); - childSetCommitCallback("spin_days_ago", onTimeAgo, this); + mSpinSinceDays = getChild("spin_days_ago"); + childSetCommitCallback("spin_days_ago", onTimeAgo, this); - mCreatorSelf = getChild("check_created_by_me"); - mCreatorOthers = getChild("check_created_by_others"); - mCreatorSelf->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorSelfFilterCommit, this)); - mCreatorOthers->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorOtherFilterCommit, this)); + mCreatorSelf = getChild("check_created_by_me"); + mCreatorOthers = getChild("check_created_by_others"); + mCreatorSelf->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorSelfFilterCommit, this)); + mCreatorOthers->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorOtherFilterCommit, this)); - childSetAction("Close", onCloseBtn, this); + childSetAction("Close", onCloseBtn, this); - updateElementsFromFilter(); - return TRUE; + updateElementsFromFilter(); + return TRUE; } void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) { - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) - { - self->getChild("check_since_logoff")->setValue(false); - - U32 days = (U32)self->mSpinSinceDays->get(); - U32 hours = (U32)self->mSpinSinceHours->get(); - if (hours >= 24) - { - // Try to handle both cases of spinner clicking and text input in a sensible fashion as best as possible. - // There is no way to tell if someone has clicked the spinner to get to 24 or input 24 manually, so in - // this case add to days. Any value > 24 means they have input the hours manually, so do not add to the - // current day value. - if (24 == hours) // Got to 24 via spinner clicking or text input of 24 - { - days = days + hours / 24; - } - else // Text input, so do not add to days - { - days = hours / 24; - } - hours = (U32)hours % 24; - self->mSpinSinceHours->setFocus(false); - self->mSpinSinceDays->setFocus(false); - self->mSpinSinceDays->set((F32)days); - self->mSpinSinceHours->set((F32)hours); - self->mSpinSinceHours->setFocus(true); - } - } + LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; + if (!self) return; + + if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) + { + self->getChild("check_since_logoff")->setValue(false); + + U32 days = (U32)self->mSpinSinceDays->get(); + U32 hours = (U32)self->mSpinSinceHours->get(); + if (hours >= 24) + { + // Try to handle both cases of spinner clicking and text input in a sensible fashion as best as possible. + // There is no way to tell if someone has clicked the spinner to get to 24 or input 24 manually, so in + // this case add to days. Any value > 24 means they have input the hours manually, so do not add to the + // current day value. + if (24 == hours) // Got to 24 via spinner clicking or text input of 24 + { + days = days + hours / 24; + } + else // Text input, so do not add to days + { + days = hours / 24; + } + hours = (U32)hours % 24; + self->mSpinSinceHours->setFocus(false); + self->mSpinSinceDays->setFocus(false); + self->mSpinSinceDays->set((F32)days); + self->mSpinSinceHours->set((F32)hours); + self->mSpinSinceHours->setFocus(true); + } + } } void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) { - mFilter = filter; - updateElementsFromFilter(); + mFilter = filter; + updateElementsFromFilter(); } void LLFloaterInventoryFinder::updateElementsFromFilter() { - if (!mFilter) - return; - - // Get data needed for filter display - U32 filter_types = mFilter->getFilterObjectTypes(); - LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); - U32 hours = mFilter->getHoursAgo(); - U32 date_search_direction = mFilter->getDateSearchDirection(); - - LLInventoryFilter::EFilterCreatorType filter_creator = mFilter->getFilterCreatorType(); - bool show_created_by_me = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_SELF)); - bool show_created_by_others = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_OTHERS)); - - // update the ui elements - setTitle(mFilter->getName()); - - getChild("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); - - getChild("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); - getChild("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); - getChild("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); - getChild("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); - getChild("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL)); - getChild("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); - getChild("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); - getChild("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); - getChild("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); - getChild("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); - getChild("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); + if (!mFilter) + return; + + // Get data needed for filter display + U32 filter_types = mFilter->getFilterObjectTypes(); + LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); + U32 hours = mFilter->getHoursAgo(); + U32 date_search_direction = mFilter->getDateSearchDirection(); + + LLInventoryFilter::EFilterCreatorType filter_creator = mFilter->getFilterCreatorType(); + bool show_created_by_me = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_SELF)); + bool show_created_by_others = ((filter_creator == LLInventoryFilter::FILTERCREATOR_ALL) || (filter_creator == LLInventoryFilter::FILTERCREATOR_OTHERS)); + + // update the ui elements + setTitle(mFilter->getName()); + + getChild("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); + + getChild("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); + getChild("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); + getChild("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); + getChild("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); + getChild("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL)); + getChild("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); + getChild("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); + getChild("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); + getChild("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); + getChild("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); + getChild("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); getChild("check_settings")->setValue((S32)(filter_types & 0x1 << LLInventoryType::IT_SETTINGS)); - getChild("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); + getChild("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); - getChild("check_created_by_me")->setValue(show_created_by_me); - getChild("check_created_by_others")->setValue(show_created_by_others); + getChild("check_created_by_me")->setValue(show_created_by_me); + getChild("check_created_by_others")->setValue(show_created_by_others); - getChild("check_since_logoff")->setValue(mFilter->isSinceLogoff()); - mSpinSinceHours->set((F32)(hours % 24)); - mSpinSinceDays->set((F32)(hours / 24)); - getChild("date_search_direction")->setSelectedIndex(date_search_direction); + getChild("check_since_logoff")->setValue(mFilter->isSinceLogoff()); + mSpinSinceHours->set((F32)(hours % 24)); + mSpinSinceDays->set((F32)(hours / 24)); + getChild("date_search_direction")->setSelectedIndex(date_search_direction); } void LLFloaterInventoryFinder::draw() { - U64 filter = 0xffffffffffffffffULL; - BOOL filtered_by_all_types = TRUE; - - if (!getChild("check_animation")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); - filtered_by_all_types = FALSE; - } - - - if (!getChild("check_calling_card")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_clothing")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_gesture")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_GESTURE); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_landmark")->getValue()) - - - { - filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_material")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_MATERIAL); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_notecard")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_object")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_OBJECT); - filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_script")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_LSL); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_sound")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_SOUND); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_texture")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); - filtered_by_all_types = FALSE; - } - - if (!getChild("check_snapshot")->getValue()) - { - filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); - filtered_by_all_types = FALSE; - } + U64 filter = 0xffffffffffffffffULL; + BOOL filtered_by_all_types = TRUE; + + if (!getChild("check_animation")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); + filtered_by_all_types = FALSE; + } + + + if (!getChild("check_calling_card")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_clothing")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_gesture")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_GESTURE); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_landmark")->getValue()) + + + { + filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_material")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_MATERIAL); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_notecard")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_object")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_OBJECT); + filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_script")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_LSL); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_sound")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_SOUND); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_texture")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); + filtered_by_all_types = FALSE; + } + + if (!getChild("check_snapshot")->getValue()) + { + filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); + filtered_by_all_types = FALSE; + } if (!getChild("check_settings")->getValue()) { @@ -1300,11 +1300,11 @@ void LLFloaterInventoryFinder::draw() filtered_by_all_types = FALSE; } - if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE)) - { - // don't include folders in filter, unless I've selected everything or filtering by date - filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); - } + if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE)) + { + // don't include folders in filter, unless I've selected everything or filtering by date + filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); + } bool is_sf_mode = mPanelMainInventory->isSingleFolderMode(); @@ -1328,28 +1328,28 @@ void LLFloaterInventoryFinder::draw() mPanelMainInventory->getPanel()->setFilterTypes(filter); } - if (getCheckSinceLogoff()) - { - mSpinSinceDays->set(0); - mSpinSinceHours->set(0); - } - U32 days = (U32)mSpinSinceDays->get(); - U32 hours = (U32)mSpinSinceHours->get(); - if (hours >= 24) - { - days = hours / 24; - hours = (U32)hours % 24; - // A UI element that has focus will not display a new value set to it - mSpinSinceHours->setFocus(false); - mSpinSinceDays->setFocus(false); - mSpinSinceDays->set((F32)days); - mSpinSinceHours->set((F32)hours); - mSpinSinceHours->setFocus(true); - } - hours += days * 24; - - - mPanelMainInventory->setFilterTextFromFilter(); + if (getCheckSinceLogoff()) + { + mSpinSinceDays->set(0); + mSpinSinceHours->set(0); + } + U32 days = (U32)mSpinSinceDays->get(); + U32 hours = (U32)mSpinSinceHours->get(); + if (hours >= 24) + { + days = hours / 24; + hours = (U32)hours % 24; + // A UI element that has focus will not display a new value set to it + mSpinSinceHours->setFocus(false); + mSpinSinceDays->setFocus(false); + mSpinSinceDays->set((F32)days); + mSpinSinceHours->set((F32)hours); + mSpinSinceHours->setFocus(true); + } + hours += days * 24; + + + mPanelMainInventory->setFilterTextFromFilter(); if(is_sf_mode && mPanelMainInventory->isGalleryViewMode()) { mPanelMainInventory->mCombinationGalleryPanel->getFilter().setHoursAgo(hours); @@ -1369,109 +1369,109 @@ void LLFloaterInventoryFinder::draw() mPanelMainInventory->getPanel()->setDateSearchDirection(getDateSearchDirection()); } - LLPanel::draw(); + LLPanel::draw(); } void LLFloaterInventoryFinder::onCreatorSelfFilterCommit() { - bool show_creator_self = mCreatorSelf->getValue(); - bool show_creator_other = mCreatorOthers->getValue(); + bool show_creator_self = mCreatorSelf->getValue(); + bool show_creator_other = mCreatorOthers->getValue(); - if(show_creator_self && show_creator_other) - { + if(show_creator_self && show_creator_other) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_ALL); - } - else if(show_creator_self) - { + } + else if(show_creator_self) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_SELF); - } - else if(!show_creator_self || !show_creator_other) - { + } + else if(!show_creator_self || !show_creator_other) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_OTHERS); - mCreatorOthers->set(TRUE); - } + mCreatorOthers->set(TRUE); + } } void LLFloaterInventoryFinder::onCreatorOtherFilterCommit() { - bool show_creator_self = mCreatorSelf->getValue(); - bool show_creator_other = mCreatorOthers->getValue(); + bool show_creator_self = mCreatorSelf->getValue(); + bool show_creator_other = mCreatorOthers->getValue(); - if(show_creator_self && show_creator_other) - { + if(show_creator_self && show_creator_other) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_ALL); - } - else if(show_creator_other) - { + } + else if(show_creator_other) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_OTHERS); - } - else if(!show_creator_other || !show_creator_self) - { + } + else if(!show_creator_other || !show_creator_self) + { mPanelMainInventory->getCurrentFilter().setFilterCreator(LLInventoryFilter::FILTERCREATOR_SELF); - mCreatorSelf->set(TRUE); - } + mCreatorSelf->set(TRUE); + } } BOOL LLFloaterInventoryFinder::getCheckShowEmpty() { - return getChild("check_show_empty")->getValue(); + return getChild("check_show_empty")->getValue(); } BOOL LLFloaterInventoryFinder::getCheckSinceLogoff() { - return getChild("check_since_logoff")->getValue(); + return getChild("check_since_logoff")->getValue(); } U32 LLFloaterInventoryFinder::getDateSearchDirection() { - return getChild("date_search_direction")->getSelectedIndex(); + return getChild("date_search_direction")->getSelectedIndex(); } void LLFloaterInventoryFinder::onCloseBtn(void* user_data) { - LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; - finderp->closeFloater(); + LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; + finderp->closeFloater(); } // static void LLFloaterInventoryFinder::selectAllTypes(void* user_data) { - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - self->getChild("check_animation")->setValue(TRUE); - self->getChild("check_calling_card")->setValue(TRUE); - self->getChild("check_clothing")->setValue(TRUE); - self->getChild("check_gesture")->setValue(TRUE); - self->getChild("check_landmark")->setValue(TRUE); - self->getChild("check_material")->setValue(TRUE); - self->getChild("check_notecard")->setValue(TRUE); - self->getChild("check_object")->setValue(TRUE); - self->getChild("check_script")->setValue(TRUE); - self->getChild("check_sound")->setValue(TRUE); - self->getChild("check_texture")->setValue(TRUE); - self->getChild("check_snapshot")->setValue(TRUE); + LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; + if(!self) return; + + self->getChild("check_animation")->setValue(TRUE); + self->getChild("check_calling_card")->setValue(TRUE); + self->getChild("check_clothing")->setValue(TRUE); + self->getChild("check_gesture")->setValue(TRUE); + self->getChild("check_landmark")->setValue(TRUE); + self->getChild("check_material")->setValue(TRUE); + self->getChild("check_notecard")->setValue(TRUE); + self->getChild("check_object")->setValue(TRUE); + self->getChild("check_script")->setValue(TRUE); + self->getChild("check_sound")->setValue(TRUE); + self->getChild("check_texture")->setValue(TRUE); + self->getChild("check_snapshot")->setValue(TRUE); self->getChild("check_settings")->setValue(TRUE); } //static void LLFloaterInventoryFinder::selectNoTypes(void* user_data) { - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - self->getChild("check_animation")->setValue(FALSE); - self->getChild("check_calling_card")->setValue(FALSE); - self->getChild("check_clothing")->setValue(FALSE); - self->getChild("check_gesture")->setValue(FALSE); - self->getChild("check_landmark")->setValue(FALSE); - self->getChild("check_material")->setValue(FALSE); - self->getChild("check_notecard")->setValue(FALSE); - self->getChild("check_object")->setValue(FALSE); - self->getChild("check_script")->setValue(FALSE); - self->getChild("check_sound")->setValue(FALSE); - self->getChild("check_texture")->setValue(FALSE); - self->getChild("check_snapshot")->setValue(FALSE); + LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; + if(!self) return; + + self->getChild("check_animation")->setValue(FALSE); + self->getChild("check_calling_card")->setValue(FALSE); + self->getChild("check_clothing")->setValue(FALSE); + self->getChild("check_gesture")->setValue(FALSE); + self->getChild("check_landmark")->setValue(FALSE); + self->getChild("check_material")->setValue(FALSE); + self->getChild("check_notecard")->setValue(FALSE); + self->getChild("check_object")->setValue(FALSE); + self->getChild("check_script")->setValue(FALSE); + self->getChild("check_sound")->setValue(FALSE); + self->getChild("check_texture")->setValue(FALSE); + self->getChild("check_snapshot")->setValue(FALSE); self->getChild("check_settings")->setValue(FALSE); } @@ -1480,28 +1480,28 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data) void LLPanelMainInventory::initListCommandsHandlers() { - childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this)); + childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this)); childSetAction("view_mode_btn", boost::bind(&LLPanelMainInventory::onViewModeClick, this)); childSetAction("up_btn", boost::bind(&LLPanelMainInventory::onUpFolderClicked, this)); childSetAction("back_btn", boost::bind(&LLPanelMainInventory::onBackFolderClicked, this)); childSetAction("forward_btn", boost::bind(&LLPanelMainInventory::onForwardFolderClicked, this)); - mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); - mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); + mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2)); + mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); + mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Visible", boost::bind(&LLPanelMainInventory::isActionVisible, this, _2)); - mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_BOTTOM_LEFT, true); + mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_BOTTOM_LEFT, true); mMenuViewDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_view_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mViewMenuButton->setMenu(mMenuViewDefault, LLMenuButton::MP_BOTTOM_LEFT, true); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mMenuAddHandle = menu->getHandle(); + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mMenuAddHandle = menu->getHandle(); - mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true); - // Update the trash button when selected item(s) get worn or taken off. - LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); + // Update the trash button when selected item(s) get worn or taken off. + LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); } void LLPanelMainInventory::updateListCommands() @@ -1513,15 +1513,15 @@ void LLPanelMainInventory::onAddButtonClick() // Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed // unless "Always show folders" is checked in the filter options. - LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); - if (menu) - { + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { disableAddIfNeeded(); - setUploadCostIfNeeded(); + setUploadCostIfNeeded(); - showActionMenu(menu,"add_btn"); - } + showActionMenu(menu,"add_btn"); + } } void LLPanelMainInventory::setActivePanel() @@ -1735,22 +1735,22 @@ LLUUID LLPanelMainInventory::getSingleFolderViewRoot() void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name) { - if (menu) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLView* spawning_view = getChild (spawning_view_name); - S32 menu_x, menu_y; - //show menu in co-ordinates of panel - spawning_view->localPointToOtherView(0, 0, &menu_x, &menu_y, this); - LLMenuGL::showPopup(this, menu, menu_x, menu_y); - } + if (menu) + { + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLView* spawning_view = getChild (spawning_view_name); + S32 menu_x, menu_y; + //show menu in co-ordinates of panel + spawning_view->localPointToOtherView(0, 0, &menu_x, &menu_y, this); + LLMenuGL::showPopup(this, menu, menu_x, menu_y); + } } void LLPanelMainInventory::onClipboardAction(const LLSD& userdata) { - std::string command_name = userdata.asString(); - getActivePanel()->doToSelected(command_name); + std::string command_name = userdata.asString(); + getActivePanel()->doToSelected(command_name); } void LLPanelMainInventory::saveTexture(const LLSD& userdata) @@ -1771,89 +1771,89 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata) item_id = static_cast(current_item->getViewModelItem())->getUUID(); } - LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); - if (preview_texture) - { - preview_texture->openToSave(); - } + LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); + if (preview_texture) + { + preview_texture->openToSave(); + } } void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { - if (!isActionEnabled(userdata)) - return; - - const std::string command_name = userdata.asString(); - - if (command_name == "new_window") - { - newWindow(); - } - if (command_name == "sort_by_name") - { - const LLSD arg = "name"; - setSortBy(arg); - } - if (command_name == "sort_by_recent") - { - const LLSD arg = "date"; - setSortBy(arg); - } - if (command_name == "sort_folders_by_name") - { - const LLSD arg = "foldersalwaysbyname"; - setSortBy(arg); - } - if (command_name == "sort_system_folders_to_top") - { - const LLSD arg = "systemfolderstotop"; - setSortBy(arg); - } - if (command_name == "show_filters") - { - toggleFindOptions(); - } - if (command_name == "reset_filters") - { - resetFilters(); - } - if (command_name == "close_folders") - { - closeAllFolders(); - } - if (command_name == "empty_trash") - { - const std::string notification = "ConfirmEmptyTrash"; - gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH); - } - if (command_name == "empty_lostnfound") - { - const std::string notification = "ConfirmEmptyLostAndFound"; - gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND); - } - if (command_name == "save_texture") - { - saveTexture(userdata); - } - // This doesn't currently work, since the viewer can't change an assetID an item. - if (command_name == "regenerate_link") - { - LLInventoryPanel *active_panel = getActivePanel(); - LLFolderViewItem* current_item = active_panel->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - const LLUUID item_id = static_cast(current_item->getViewModelItem())->getUUID(); - LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item) - { - item->regenerateLink(); - } - active_panel->setSelection(item_id, TAKE_FOCUS_NO); - } - if (command_name == "find_original") - { + if (!isActionEnabled(userdata)) + return; + + const std::string command_name = userdata.asString(); + + if (command_name == "new_window") + { + newWindow(); + } + if (command_name == "sort_by_name") + { + const LLSD arg = "name"; + setSortBy(arg); + } + if (command_name == "sort_by_recent") + { + const LLSD arg = "date"; + setSortBy(arg); + } + if (command_name == "sort_folders_by_name") + { + const LLSD arg = "foldersalwaysbyname"; + setSortBy(arg); + } + if (command_name == "sort_system_folders_to_top") + { + const LLSD arg = "systemfolderstotop"; + setSortBy(arg); + } + if (command_name == "show_filters") + { + toggleFindOptions(); + } + if (command_name == "reset_filters") + { + resetFilters(); + } + if (command_name == "close_folders") + { + closeAllFolders(); + } + if (command_name == "empty_trash") + { + const std::string notification = "ConfirmEmptyTrash"; + gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH); + } + if (command_name == "empty_lostnfound") + { + const std::string notification = "ConfirmEmptyLostAndFound"; + gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND); + } + if (command_name == "save_texture") + { + saveTexture(userdata); + } + // This doesn't currently work, since the viewer can't change an assetID an item. + if (command_name == "regenerate_link") + { + LLInventoryPanel *active_panel = getActivePanel(); + LLFolderViewItem* current_item = active_panel->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + const LLUUID item_id = static_cast(current_item->getViewModelItem())->getUUID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item) + { + item->regenerateLink(); + } + active_panel->setSelection(item_id, TAKE_FOCUS_NO); + } + if (command_name == "find_original") + { if(mSingleFolderMode && isGalleryViewMode()) { LLInventoryObject *obj = gInventory.getObject(mCombinationGalleryPanel->getFirstSelectedItemID()); @@ -1864,17 +1864,17 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } else { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - static_cast(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto"); + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) + { + return; + } + static_cast(current_item->getViewModelItem())->performAction(getActivePanel()->getModel(), "goto"); } - } + } - if (command_name == "find_links") - { + if (command_name == "find_links") + { if(mSingleFolderMode && isGalleryViewMode()) { LLFloaterSidePanelContainer* inventory_container = newWindow(); @@ -1906,10 +1906,10 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) const std::string &item_name = current_item->getViewModelItem()->getName(); findLinks(item_id, item_name); } - } + } - if (command_name == "replace_links") - { + if (command_name == "replace_links") + { LLSD params; if(mSingleFolderMode && isGalleryViewMode()) { @@ -1917,23 +1917,23 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } else { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (current_item) - { - LLInvFVBridge* bridge = (LLInvFVBridge*)current_item->getViewModelItem(); + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (current_item) + { + LLInvFVBridge* bridge = (LLInvFVBridge*)current_item->getViewModelItem(); - if (bridge) - { - LLInventoryObject* obj = bridge->getInventoryObject(); - if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER) - { - params = LLSD(obj->getUUID()); - } - } - } + if (bridge) + { + LLInventoryObject* obj = bridge->getInventoryObject(); + if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER) + { + params = LLSD(obj->getUUID()); + } + } } - LLFloaterReg::showInstance("linkreplace", params); - } + } + LLFloaterReg::showInstance("linkreplace", params); + } if (command_name == "close_inv_windows") { @@ -1954,20 +1954,20 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) getCurrentFilter().toggleSearchVisibilityOutfits(); } - if (command_name == "toggle_search_trash") - { + if (command_name == "toggle_search_trash") + { getCurrentFilter().toggleSearchVisibilityTrash(); - } + } - if (command_name == "toggle_search_library") - { + if (command_name == "toggle_search_library") + { getCurrentFilter().toggleSearchVisibilityLibrary(); - } + } - if (command_name == "include_links") - { + if (command_name == "include_links") + { getCurrentFilter().toggleSearchVisibilityLinks(); - } + } if (command_name == "share") { @@ -2001,15 +2001,15 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) { - if(!new_visibility) - { - LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); - if (menu) - { - menu->setVisible(FALSE); - } - getActivePanel()->getRootFolder()->finishRenamingItem(); - } + if(!new_visibility) + { + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if (menu) + { + menu->setVisible(FALSE); + } + getActivePanel()->getRootFolder()->finishRenamingItem(); + } } bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) @@ -2027,124 +2027,124 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) inv_item = dynamic_cast(static_cast(current_item->getViewModelItem())->getInventoryObject()); } } - if(inv_item) - { - bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); + if(inv_item) + { + bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); LLInventoryType::EType curr_type = inv_item->getInventoryType(); - return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); - } + return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); + } - return false; + return false; } BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { - const std::string command_name = userdata.asString(); - if (command_name == "not_empty") - { - BOOL status = FALSE; - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (current_item) - { - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); - LLInventoryModel::cat_array_t* cat_array; - LLInventoryModel::item_array_t* item_array; - gInventory.getDirectDescendentsOf(item_id, cat_array, item_array); - status = (0 == cat_array->size() && 0 == item_array->size()); - } - return status; - } - if (command_name == "delete") - { - return getActivePanel()->isSelectionRemovable(); - } - if (command_name == "save_texture") - { - return isSaveTextureEnabled(userdata); - } - if (command_name == "find_original") - { + const std::string command_name = userdata.asString(); + if (command_name == "not_empty") + { + BOOL status = FALSE; + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (current_item) + { + const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(item_id, cat_array, item_array); + status = (0 == cat_array->size() && 0 == item_array->size()); + } + return status; + } + if (command_name == "delete") + { + return getActivePanel()->isSelectionRemovable(); + } + if (command_name == "save_texture") + { + return isSaveTextureEnabled(userdata); + } + if (command_name == "find_original") + { LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) return FALSE; + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) return FALSE; item_id = static_cast(current_item->getViewModelItem())->getUUID(); } - const LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item && item->getIsLinkType() && !item->getIsBrokenLink()) - { - return TRUE; - } - return FALSE; - } + const LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item && item->getIsLinkType() && !item->getIsBrokenLink()) + { + return TRUE; + } + return FALSE; + } - if (command_name == "find_links") - { + if (command_name == "find_links") + { LLUUID item_id; if(mSingleFolderMode && isGalleryViewMode()) { item_id = mCombinationGalleryPanel->getFirstSelectedItemID(); } else{ - LLFolderView* root = getActivePanel()->getRootFolder(); - std::set selection_set = root->getSelectionList(); - if (selection_set.size() != 1) return FALSE; - LLFolderViewItem* current_item = root->getCurSelectedItem(); - if (!current_item) return FALSE; - item_id = static_cast(current_item->getViewModelItem())->getUUID(); - } - const LLInventoryObject *obj = gInventory.getObject(item_id); - if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) - { - return TRUE; - } - return FALSE; - } - // This doesn't currently work, since the viewer can't change an assetID an item. - if (command_name == "regenerate_link") - { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) return FALSE; - const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); - const LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item && item->getIsBrokenLink()) - { - return TRUE; - } - return FALSE; - } - - if (command_name == "share") - { + LLFolderView* root = getActivePanel()->getRootFolder(); + std::set selection_set = root->getSelectionList(); + if (selection_set.size() != 1) return FALSE; + LLFolderViewItem* current_item = root->getCurSelectedItem(); + if (!current_item) return FALSE; + item_id = static_cast(current_item->getViewModelItem())->getUUID(); + } + const LLInventoryObject *obj = gInventory.getObject(item_id); + if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) + { + return TRUE; + } + return FALSE; + } + // This doesn't currently work, since the viewer can't change an assetID an item. + if (command_name == "regenerate_link") + { + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) return FALSE; + const LLUUID& item_id = static_cast(current_item->getViewModelItem())->getUUID(); + const LLViewerInventoryItem *item = gInventory.getItem(item_id); + if (item && item->getIsBrokenLink()) + { + return TRUE; + } + return FALSE; + } + + if (command_name == "share") + { if(mSingleFolderMode && isGalleryViewMode()) { return can_share_item(mCombinationGalleryPanel->getFirstSelectedItemID()); } else{ - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) return FALSE; - LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel("inventory"); - return parent ? parent->canShare() : FALSE; - } - } - if (command_name == "empty_trash") - { - const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); - return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); - } - if (command_name == "empty_lostnfound") - { - const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); - return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); - } - - return TRUE; + LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + if (!current_item) return FALSE; + LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel("inventory"); + return parent ? parent->canShare() : FALSE; + } + } + if (command_name == "empty_trash") + { + const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); + return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); + } + if (command_name == "empty_lostnfound") + { + const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); + return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); + } + + return TRUE; } bool LLPanelMainInventory::isActionVisible(const LLSD& userdata) @@ -2164,47 +2164,47 @@ bool LLPanelMainInventory::isActionVisible(const LLSD& userdata) BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) { - U32 sort_order_mask = (mSingleFolderMode && isGalleryViewMode()) ? mCombinationGalleryPanel->getSortOrder() : getActivePanel()->getSortOrder(); - const std::string command_name = userdata.asString(); - if (command_name == "sort_by_name") - { - return ~sort_order_mask & LLInventoryFilter::SO_DATE; - } + U32 sort_order_mask = (mSingleFolderMode && isGalleryViewMode()) ? mCombinationGalleryPanel->getSortOrder() : getActivePanel()->getSortOrder(); + const std::string command_name = userdata.asString(); + if (command_name == "sort_by_name") + { + return ~sort_order_mask & LLInventoryFilter::SO_DATE; + } - if (command_name == "sort_by_recent") - { - return sort_order_mask & LLInventoryFilter::SO_DATE; - } + if (command_name == "sort_by_recent") + { + return sort_order_mask & LLInventoryFilter::SO_DATE; + } - if (command_name == "sort_folders_by_name") - { - return sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME; - } + if (command_name == "sort_folders_by_name") + { + return sort_order_mask & LLInventoryFilter::SO_FOLDERS_BY_NAME; + } - if (command_name == "sort_system_folders_to_top") - { - return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - } + if (command_name == "sort_system_folders_to_top") + { + return sort_order_mask & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; + } if (command_name == "toggle_search_outfits") { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_OUTFITS) != 0; } - if (command_name == "toggle_search_trash") - { - return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0; - } + if (command_name == "toggle_search_trash") + { + return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_TRASH) != 0; + } - if (command_name == "toggle_search_library") - { - return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0; - } + if (command_name == "toggle_search_library") + { + return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LIBRARY) != 0; + } - if (command_name == "include_links") - { + if (command_name == "include_links") + { return (getCurrentFilter().getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) != 0; - } + } if (command_name == "list_view") { @@ -2219,20 +2219,20 @@ BOOL LLPanelMainInventory::isActionChecked(const LLSD& userdata) return isCombinationViewMode(); } - return FALSE; + return FALSE; } void LLPanelMainInventory::setUploadCostIfNeeded() { - LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); - if(mNeedUploadCost && menu) - { - const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); - const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); + LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get(); + if(mNeedUploadCost && menu) + { + const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); + const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); - menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); - } + menu->getChild("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str); + menu->getChild("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str); + } } bool is_add_allowed(LLUUID folder_id) @@ -2412,7 +2412,7 @@ void LLPanelMainInventory::updateCombinationVisibility() { mCombinationGalleryPanel->handleModifiedFilter(); } - + getActivePanel()->getRootFolder(); if (mReshapeInvLayout @@ -2536,7 +2536,7 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode) sort_order = mCombinationInventoryPanel->getSortOrder(); break; } - + LLUUID cur_root = getCurrentSFVRoot(); mViewMode = mode; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 91c33b461f..7f111d7619 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llpanelvolume.cpp * @brief Object editing (position, scale, etc.) in the tools floater * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -90,63 +90,63 @@ const F32 DEFAULT_GRAVITY_MULTIPLIER = 1.f; const F32 DEFAULT_DENSITY = 1000.f; // "Features" Tab -BOOL LLPanelVolume::postBuild() +BOOL LLPanelVolume::postBuild() { - // Flexible Objects Parameters - { - childSetCommitCallback("Animated Mesh Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitAnimatedMeshCheckbox, this, _1, _2), NULL); - childSetCommitCallback("Flexible1D Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL); - childSetCommitCallback("FlexNumSections",onCommitFlexible,this); - getChild("FlexNumSections")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexGravity",onCommitFlexible,this); - getChild("FlexGravity")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexFriction",onCommitFlexible,this); - getChild("FlexFriction")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexWind",onCommitFlexible,this); - getChild("FlexWind")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexTension",onCommitFlexible,this); - getChild("FlexTension")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexForceX",onCommitFlexible,this); - getChild("FlexForceX")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexForceY",onCommitFlexible,this); - getChild("FlexForceY")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("FlexForceZ",onCommitFlexible,this); - getChild("FlexForceZ")->setValidateBeforeCommit(precommitValidate); - } - - // LIGHT Parameters - { - childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this); - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch){ - LightColorSwatch->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelColor, this, _2)); - LightColorSwatch->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectColor, this, _2)); - childSetCommitCallback("colorswatch",onCommitLight,this); - } - - LLTextureCtrl* LightTexPicker = getChild("light texture control"); - if (LightTexPicker) - { - LightTexPicker->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelTexture, this, _2)); - LightTexPicker->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectTexture, this, _2)); - childSetCommitCallback("light texture control", onCommitLight, this); - } - - childSetCommitCallback("Light Intensity",onCommitLight,this); - getChild("Light Intensity")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("Light Radius",onCommitLight,this); - getChild("Light Radius")->setValidateBeforeCommit(precommitValidate); - childSetCommitCallback("Light Falloff",onCommitLight,this); - getChild("Light Falloff")->setValidateBeforeCommit(precommitValidate); - - childSetCommitCallback("Light FOV", onCommitLight, this); - getChild("Light FOV")->setValidateBeforeCommit( precommitValidate); - childSetCommitCallback("Light Focus", onCommitLight, this); - getChild("Light Focus")->setValidateBeforeCommit( precommitValidate); - childSetCommitCallback("Light Ambiance", onCommitLight, this); - getChild("Light Ambiance")->setValidateBeforeCommit( precommitValidate); - } - + // Flexible Objects Parameters + { + childSetCommitCallback("Animated Mesh Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitAnimatedMeshCheckbox, this, _1, _2), NULL); + childSetCommitCallback("Flexible1D Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL); + childSetCommitCallback("FlexNumSections",onCommitFlexible,this); + getChild("FlexNumSections")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexGravity",onCommitFlexible,this); + getChild("FlexGravity")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexFriction",onCommitFlexible,this); + getChild("FlexFriction")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexWind",onCommitFlexible,this); + getChild("FlexWind")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexTension",onCommitFlexible,this); + getChild("FlexTension")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexForceX",onCommitFlexible,this); + getChild("FlexForceX")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexForceY",onCommitFlexible,this); + getChild("FlexForceY")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("FlexForceZ",onCommitFlexible,this); + getChild("FlexForceZ")->setValidateBeforeCommit(precommitValidate); + } + + // LIGHT Parameters + { + childSetCommitCallback("Light Checkbox Ctrl",onCommitIsLight,this); + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch){ + LightColorSwatch->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelColor, this, _2)); + LightColorSwatch->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectColor, this, _2)); + childSetCommitCallback("colorswatch",onCommitLight,this); + } + + LLTextureCtrl* LightTexPicker = getChild("light texture control"); + if (LightTexPicker) + { + LightTexPicker->setOnCancelCallback(boost::bind(&LLPanelVolume::onLightCancelTexture, this, _2)); + LightTexPicker->setOnSelectCallback(boost::bind(&LLPanelVolume::onLightSelectTexture, this, _2)); + childSetCommitCallback("light texture control", onCommitLight, this); + } + + childSetCommitCallback("Light Intensity",onCommitLight,this); + getChild("Light Intensity")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("Light Radius",onCommitLight,this); + getChild("Light Radius")->setValidateBeforeCommit(precommitValidate); + childSetCommitCallback("Light Falloff",onCommitLight,this); + getChild("Light Falloff")->setValidateBeforeCommit(precommitValidate); + + childSetCommitCallback("Light FOV", onCommitLight, this); + getChild("Light FOV")->setValidateBeforeCommit( precommitValidate); + childSetCommitCallback("Light Focus", onCommitLight, this); + getChild("Light Focus")->setValidateBeforeCommit( precommitValidate); + childSetCommitCallback("Light Ambiance", onCommitLight, this); + getChild("Light Ambiance")->setValidateBeforeCommit( precommitValidate); + } + // REFLECTION PROBE Parameters { childSetCommitCallback("Reflection Probe", onCommitIsReflectionProbe, this); @@ -156,71 +156,71 @@ BOOL LLPanelVolume::postBuild() childSetCommitCallback("Probe Near Clip", onCommitProbe, this); } - // PHYSICS Parameters - { - // PhysicsShapeType combobox - mComboPhysicsShapeType = getChild("Physics Shape Type Combo Ctrl"); - mComboPhysicsShapeType->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsShapeType, this, _1, mComboPhysicsShapeType)); - - // PhysicsGravity - mSpinPhysicsGravity = getChild("Physics Gravity"); - mSpinPhysicsGravity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsGravity, this, _1, mSpinPhysicsGravity)); + // PHYSICS Parameters + { + // PhysicsShapeType combobox + mComboPhysicsShapeType = getChild("Physics Shape Type Combo Ctrl"); + mComboPhysicsShapeType->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsShapeType, this, _1, mComboPhysicsShapeType)); + + // PhysicsGravity + mSpinPhysicsGravity = getChild("Physics Gravity"); + mSpinPhysicsGravity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsGravity, this, _1, mSpinPhysicsGravity)); - // PhysicsFriction - mSpinPhysicsFriction = getChild("Physics Friction"); - mSpinPhysicsFriction->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsFriction, this, _1, mSpinPhysicsFriction)); + // PhysicsFriction + mSpinPhysicsFriction = getChild("Physics Friction"); + mSpinPhysicsFriction->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsFriction, this, _1, mSpinPhysicsFriction)); - // PhysicsDensity - mSpinPhysicsDensity = getChild("Physics Density"); - mSpinPhysicsDensity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsDensity, this, _1, mSpinPhysicsDensity)); + // PhysicsDensity + mSpinPhysicsDensity = getChild("Physics Density"); + mSpinPhysicsDensity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsDensity, this, _1, mSpinPhysicsDensity)); - // PhysicsRestitution - mSpinPhysicsRestitution = getChild("Physics Restitution"); - mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution)); - } + // PhysicsRestitution + mSpinPhysicsRestitution = getChild("Physics Restitution"); + mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution)); + } mMenuClipboardFeatures = getChild("clipboard_features_params_btn"); mMenuClipboardLight = getChild("clipboard_light_params_btn"); - std::map material_name_map; - material_name_map["Stone"]= LLTrans::getString("Stone"); - material_name_map["Metal"]= LLTrans::getString("Metal"); - material_name_map["Glass"]= LLTrans::getString("Glass"); - material_name_map["Wood"]= LLTrans::getString("Wood"); - material_name_map["Flesh"]= LLTrans::getString("Flesh"); - material_name_map["Plastic"]= LLTrans::getString("Plastic"); - material_name_map["Rubber"]= LLTrans::getString("Rubber"); - material_name_map["Light"]= LLTrans::getString("Light"); - - LLMaterialTable::basic.initTableTransNames(material_name_map); - - // material type popup - mComboMaterial = getChild("material"); - childSetCommitCallback("material",onCommitMaterial,this); - mComboMaterial->removeall(); - - for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin(); - iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter) - { - LLMaterialInfo* minfop = *iter; - if (minfop->mMCode != LL_MCODE_LIGHT) - { - mComboMaterial->add(minfop->mName); - } - } - mComboMaterialItemCount = mComboMaterial->getItemCount(); - - // Start with everyone disabled - clearCtrls(); - - return TRUE; + std::map material_name_map; + material_name_map["Stone"]= LLTrans::getString("Stone"); + material_name_map["Metal"]= LLTrans::getString("Metal"); + material_name_map["Glass"]= LLTrans::getString("Glass"); + material_name_map["Wood"]= LLTrans::getString("Wood"); + material_name_map["Flesh"]= LLTrans::getString("Flesh"); + material_name_map["Plastic"]= LLTrans::getString("Plastic"); + material_name_map["Rubber"]= LLTrans::getString("Rubber"); + material_name_map["Light"]= LLTrans::getString("Light"); + + LLMaterialTable::basic.initTableTransNames(material_name_map); + + // material type popup + mComboMaterial = getChild("material"); + childSetCommitCallback("material",onCommitMaterial,this); + mComboMaterial->removeall(); + + for (LLMaterialTable::info_list_t::iterator iter = LLMaterialTable::basic.mMaterialInfoList.begin(); + iter != LLMaterialTable::basic.mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo* minfop = *iter; + if (minfop->mMCode != LL_MCODE_LIGHT) + { + mComboMaterial->add(minfop->mName); + } + } + mComboMaterialItemCount = mComboMaterial->getItemCount(); + + // Start with everyone disabled + clearCtrls(); + + return TRUE; } LLPanelVolume::LLPanelVolume() - : LLPanel(), - mComboMaterialItemCount(0) + : LLPanel(), + mComboMaterialItemCount(0) { - setMouseOpaque(FALSE); + setMouseOpaque(FALSE); mCommitCallbackRegistrar.add("PanelVolume.menuDoToSelected", boost::bind(&LLPanelVolume::menuDoToSelected, this, _2)); mEnableCallbackRegistrar.add("PanelVolume.menuEnable", boost::bind(&LLPanelVolume::menuEnableItem, this, _2)); @@ -229,142 +229,142 @@ LLPanelVolume::LLPanelVolume() LLPanelVolume::~LLPanelVolume() { - // Children all cleaned up by default view destructor. + // Children all cleaned up by default view destructor. } void LLPanelVolume::getState( ) { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); - LLViewerObject* root_objectp = objectp; - if(!objectp) - { - objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - // *FIX: shouldn't we just keep the child? - if (objectp) - { - LLViewerObject* parentp = objectp->getRootEdit(); - - if (parentp) - { - root_objectp = parentp; - } - else - { - root_objectp = objectp; - } - } - } - - LLVOVolume *volobjp = NULL; - if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) - { - volobjp = (LLVOVolume *)objectp; - } - LLVOVolume *root_volobjp = NULL; + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); + LLViewerObject* root_objectp = objectp; + if(!objectp) + { + objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + // *FIX: shouldn't we just keep the child? + if (objectp) + { + LLViewerObject* parentp = objectp->getRootEdit(); + + if (parentp) + { + root_objectp = parentp; + } + else + { + root_objectp = objectp; + } + } + } + + LLVOVolume *volobjp = NULL; + if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) + { + volobjp = (LLVOVolume *)objectp; + } + LLVOVolume *root_volobjp = NULL; if (root_objectp && (root_objectp->getPCode() == LL_PCODE_VOLUME)) { root_volobjp = (LLVOVolume *)root_objectp; } - - if( !objectp ) - { - //forfeit focus - if (gFocusMgr.childHasKeyboardFocus(this)) - { - gFocusMgr.setKeyboardFocus(NULL); - } - - // Disable all text input fields - clearCtrls(); - - return; - } - - LLUUID owner_id; - std::string owner_name; - LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); - - // BUG? Check for all objects being editable? - BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); - BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) - && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1; - BOOL single_root_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) && + + if( !objectp ) + { + //forfeit focus + if (gFocusMgr.childHasKeyboardFocus(this)) + { + gFocusMgr.setKeyboardFocus(NULL); + } + + // Disable all text input fields + clearCtrls(); + + return; + } + + LLUUID owner_id; + std::string owner_name; + LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); + + // BUG? Check for all objects being editable? + BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); + BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) + && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1; + BOOL single_root_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1; - // Select Single Message - if (single_volume) - { - getChildView("edit_object")->setVisible(true); - getChildView("edit_object")->setEnabled(true); - getChildView("select_single")->setVisible(false); - } - else - { - getChildView("edit_object")->setVisible(false); - getChildView("select_single")->setVisible(true); - getChildView("select_single")->setEnabled(true); - } - - // Light properties - BOOL is_light = volobjp && volobjp->getIsLight(); - getChild("Light Checkbox Ctrl")->setValue(is_light); - getChildView("Light Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); - - if (is_light && editable && single_volume) - { - //mLabelColor ->setEnabled( TRUE ); - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LightColorSwatch->setEnabled( TRUE ); - LightColorSwatch->setValid( TRUE ); - LightColorSwatch->set(volobjp->getLightSRGBBaseColor()); - } - - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - if (LightTextureCtrl) - { - LightTextureCtrl->setEnabled(TRUE); - LightTextureCtrl->setValid(TRUE); - LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID()); - } - - getChildView("Light Intensity")->setEnabled(true); - getChildView("Light Radius")->setEnabled(true); - getChildView("Light Falloff")->setEnabled(true); - - getChildView("Light FOV")->setEnabled(true); - getChildView("Light Focus")->setEnabled(true); - getChildView("Light Ambiance")->setEnabled(true); - - getChild("Light Intensity")->setValue(volobjp->getLightIntensity()); - getChild("Light Radius")->setValue(volobjp->getLightRadius()); - getChild("Light Falloff")->setValue(volobjp->getLightFalloff()); - - LLVector3 params = volobjp->getSpotLightParams(); - getChild("Light FOV")->setValue(params.mV[0]); - getChild("Light Focus")->setValue(params.mV[1]); - getChild("Light Ambiance")->setValue(params.mV[2]); - - mLightSavedColor = volobjp->getLightSRGBBaseColor(); - } - else - { - getChild("Light Intensity", true)->clear(); - getChild("Light Radius", true)->clear(); - getChild("Light Falloff", true)->clear(); - - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LightColorSwatch->setEnabled( FALSE ); - LightColorSwatch->setValid( FALSE ); - } - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - if (LightTextureCtrl) - { - LightTextureCtrl->setEnabled(FALSE); - LightTextureCtrl->setValid(FALSE); + // Select Single Message + if (single_volume) + { + getChildView("edit_object")->setVisible(true); + getChildView("edit_object")->setEnabled(true); + getChildView("select_single")->setVisible(false); + } + else + { + getChildView("edit_object")->setVisible(false); + getChildView("select_single")->setVisible(true); + getChildView("select_single")->setEnabled(true); + } + + // Light properties + BOOL is_light = volobjp && volobjp->getIsLight(); + getChild("Light Checkbox Ctrl")->setValue(is_light); + getChildView("Light Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); + + if (is_light && editable && single_volume) + { + //mLabelColor ->setEnabled( TRUE ); + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch) + { + LightColorSwatch->setEnabled( TRUE ); + LightColorSwatch->setValid( TRUE ); + LightColorSwatch->set(volobjp->getLightSRGBBaseColor()); + } + + LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); + if (LightTextureCtrl) + { + LightTextureCtrl->setEnabled(TRUE); + LightTextureCtrl->setValid(TRUE); + LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID()); + } + + getChildView("Light Intensity")->setEnabled(true); + getChildView("Light Radius")->setEnabled(true); + getChildView("Light Falloff")->setEnabled(true); + + getChildView("Light FOV")->setEnabled(true); + getChildView("Light Focus")->setEnabled(true); + getChildView("Light Ambiance")->setEnabled(true); + + getChild("Light Intensity")->setValue(volobjp->getLightIntensity()); + getChild("Light Radius")->setValue(volobjp->getLightRadius()); + getChild("Light Falloff")->setValue(volobjp->getLightFalloff()); + + LLVector3 params = volobjp->getSpotLightParams(); + getChild("Light FOV")->setValue(params.mV[0]); + getChild("Light Focus")->setValue(params.mV[1]); + getChild("Light Ambiance")->setValue(params.mV[2]); + + mLightSavedColor = volobjp->getLightSRGBBaseColor(); + } + else + { + getChild("Light Intensity", true)->clear(); + getChild("Light Radius", true)->clear(); + getChild("Light Falloff", true)->clear(); + + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch) + { + LightColorSwatch->setEnabled( FALSE ); + LightColorSwatch->setValid( FALSE ); + } + LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); + if (LightTextureCtrl) + { + LightTextureCtrl->setEnabled(FALSE); + LightTextureCtrl->setValid(FALSE); if (objectp->isAttachment()) { @@ -374,16 +374,16 @@ void LLPanelVolume::getState( ) { LightTextureCtrl->setImmediateFilterPermMask(PERM_NONE); } - } + } - getChildView("Light Intensity")->setEnabled(false); - getChildView("Light Radius")->setEnabled(false); - getChildView("Light Falloff")->setEnabled(false); + getChildView("Light Intensity")->setEnabled(false); + getChildView("Light Radius")->setEnabled(false); + getChildView("Light Falloff")->setEnabled(false); - getChildView("Light FOV")->setEnabled(false); - getChildView("Light Focus")->setEnabled(false); - getChildView("Light Ambiance")->setEnabled(false); - } + getChildView("Light FOV")->setEnabled(false); + getChildView("Light Focus")->setEnabled(false); + getChildView("Light Ambiance")->setEnabled(false); + } // Reflection Probe BOOL is_probe = volobjp && volobjp->isReflectionProbe(); @@ -394,7 +394,7 @@ void LLPanelVolume::getState( ) bool mirrors_enabled = LLPipeline::RenderMirrors; - getChildView("Probe Update Type")->setVisible(mirrors_enabled); + getChildView("Probe Update Type")->setVisible(mirrors_enabled); getChildView("Probe Update Label")->setVisible(mirrors_enabled); getChildView("Probe Dynamic")->setVisible(!mirrors_enabled); @@ -425,7 +425,7 @@ void LLPanelVolume::getState( ) } - std::string update_type = "Static"; + std::string update_type = "Static"; if (volobjp->getReflectionProbeIsDynamic() && !volobjp->getReflectionProbeIsMirror()) { @@ -437,9 +437,9 @@ void LLPanelVolume::getState( ) } else if (volobjp->getReflectionProbeIsDynamic() && volobjp->getReflectionProbeIsMirror()) - { - update_type = "Dynamic Mirror"; - } + { + update_type = "Dynamic Mirror"; + } getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror"); @@ -451,12 +451,12 @@ void LLPanelVolume::getState( ) } // Animated Mesh - BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject(); - getChild("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh); + BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject(); + getChild("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh); BOOL enabled_animated_object_box = FALSE; if (root_volobjp && root_volobjp == volobjp) { - enabled_animated_object_box = single_root_volume && root_volobjp && root_volobjp->canBeAnimatedObject() && editable; + enabled_animated_object_box = single_root_volume && root_volobjp && root_volobjp->canBeAnimatedObject() && editable; #if 0 if (!enabled_animated_object_box) { @@ -469,7 +469,7 @@ void LLPanelVolume::getState( ) } } #endif - if (enabled_animated_object_box && !is_animated_mesh && + if (enabled_animated_object_box && !is_animated_mesh && root_volobjp->isAttachment() && !gAgentAvatarp->canAttachMoreAnimatedObjects()) { // Turning this attachment animated would cause us to exceed the limit. @@ -477,182 +477,182 @@ void LLPanelVolume::getState( ) } } getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(enabled_animated_object_box); - - //refresh any bakes - if (root_volobjp) - { - root_volobjp->refreshBakeTexture(); - - LLViewerObject::const_child_list_t& child_list = root_volobjp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* objectp = *iter; - if (objectp) - { - objectp->refreshBakeTexture(); - } - } - - if (gAgentAvatarp) - { - gAgentAvatarp->updateMeshVisibility(); - } - } - - // Flexible properties - BOOL is_flexible = volobjp && volobjp->isFlexible(); - getChild("Flexible1D Checkbox Ctrl")->setValue(is_flexible); - if (is_flexible || (volobjp && volobjp->canBeFlexible())) - { - getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh() && !objectp->isPermanentEnforced()); - } - else - { - getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); - } - if (is_flexible && editable && single_volume) - { - getChildView("FlexNumSections")->setVisible(true); - getChildView("FlexGravity")->setVisible(true); - getChildView("FlexTension")->setVisible(true); - getChildView("FlexFriction")->setVisible(true); - getChildView("FlexWind")->setVisible(true); - getChildView("FlexForceX")->setVisible(true); - getChildView("FlexForceY")->setVisible(true); - getChildView("FlexForceZ")->setVisible(true); - - getChildView("FlexNumSections")->setEnabled(true); - getChildView("FlexGravity")->setEnabled(true); - getChildView("FlexTension")->setEnabled(true); - getChildView("FlexFriction")->setEnabled(true); - getChildView("FlexWind")->setEnabled(true); - getChildView("FlexForceX")->setEnabled(true); - getChildView("FlexForceY")->setEnabled(true); - getChildView("FlexForceZ")->setEnabled(true); - - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - - getChild("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); - getChild("FlexGravity")->setValue(attributes->getGravity()); - getChild("FlexTension")->setValue(attributes->getTension()); - getChild("FlexFriction")->setValue(attributes->getAirFriction()); - getChild("FlexWind")->setValue(attributes->getWindSensitivity()); - getChild("FlexForceX")->setValue(attributes->getUserForce().mV[VX]); - getChild("FlexForceY")->setValue(attributes->getUserForce().mV[VY]); - getChild("FlexForceZ")->setValue(attributes->getUserForce().mV[VZ]); - } - else - { - getChild("FlexNumSections", true)->clear(); - getChild("FlexGravity", true)->clear(); - getChild("FlexTension", true)->clear(); - getChild("FlexFriction", true)->clear(); - getChild("FlexWind", true)->clear(); - getChild("FlexForceX", true)->clear(); - getChild("FlexForceY", true)->clear(); - getChild("FlexForceZ", true)->clear(); - - getChildView("FlexNumSections")->setEnabled(false); - getChildView("FlexGravity")->setEnabled(false); - getChildView("FlexTension")->setEnabled(false); - getChildView("FlexFriction")->setEnabled(false); - getChildView("FlexWind")->setEnabled(false); - getChildView("FlexForceX")->setEnabled(false); - getChildView("FlexForceY")->setEnabled(false); - getChildView("FlexForceZ")->setEnabled(false); - } - - // Material properties - - // Update material part - // slightly inefficient - materials are unique per object, not per TE - U8 material_code = 0; - struct f : public LLSelectedTEGetFunctor - { - U8 get(LLViewerObject* object, S32 te) - { - return object->getMaterial(); - } - } func; - bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code ); - std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright"); - if (editable && single_volume && material_same) - { - mComboMaterial->setEnabled( TRUE ); - if (material_code == LL_MCODE_LIGHT) - { - if (mComboMaterial->getItemCount() == mComboMaterialItemCount) - { - mComboMaterial->add(LEGACY_FULLBRIGHT_DESC); - } - mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC); - } - else - { - if (mComboMaterial->getItemCount() != mComboMaterialItemCount) - { - mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC); - } - - mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code))); - } - } - else - { - mComboMaterial->setEnabled( FALSE ); - } - - // Physics properties - - mSpinPhysicsGravity->set(objectp->getPhysicsGravity()); - mSpinPhysicsGravity->setEnabled(editable); - - mSpinPhysicsFriction->set(objectp->getPhysicsFriction()); - mSpinPhysicsFriction->setEnabled(editable); - - mSpinPhysicsDensity->set(objectp->getPhysicsDensity()); - mSpinPhysicsDensity->setEnabled(editable); - - mSpinPhysicsRestitution->set(objectp->getPhysicsRestitution()); - mSpinPhysicsRestitution->setEnabled(editable); - - // update the physics shape combo to include allowed physics shapes - mComboPhysicsShapeType->removeall(); - mComboPhysicsShapeType->add(getString("None"), LLSD(1)); - - BOOL isMesh = FALSE; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) - { - U8 sculpt_type = sculpt_params->getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH); - } - - if(isMesh && objectp) - { - const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); - LLUUID mesh_id = volume_params.getSculptID(); - if(gMeshRepo.hasPhysicsShape(mesh_id)) - { - // if a mesh contains an uploaded or decomposed physics mesh, - // allow 'Prim' - mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); - } - } - else - { - // simple prims always allow physics shape prim - mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); - } - - mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2)); - mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType())); - mComboPhysicsShapeType->setEnabled(editable && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced())); - - mObject = objectp; - mRootObject = root_objectp; + + //refresh any bakes + if (root_volobjp) + { + root_volobjp->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = root_volobjp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* objectp = *iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } + + if (gAgentAvatarp) + { + gAgentAvatarp->updateMeshVisibility(); + } + } + + // Flexible properties + BOOL is_flexible = volobjp && volobjp->isFlexible(); + getChild("Flexible1D Checkbox Ctrl")->setValue(is_flexible); + if (is_flexible || (volobjp && volobjp->canBeFlexible())) + { + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh() && !objectp->isPermanentEnforced()); + } + else + { + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); + } + if (is_flexible && editable && single_volume) + { + getChildView("FlexNumSections")->setVisible(true); + getChildView("FlexGravity")->setVisible(true); + getChildView("FlexTension")->setVisible(true); + getChildView("FlexFriction")->setVisible(true); + getChildView("FlexWind")->setVisible(true); + getChildView("FlexForceX")->setVisible(true); + getChildView("FlexForceY")->setVisible(true); + getChildView("FlexForceZ")->setVisible(true); + + getChildView("FlexNumSections")->setEnabled(true); + getChildView("FlexGravity")->setEnabled(true); + getChildView("FlexTension")->setEnabled(true); + getChildView("FlexFriction")->setEnabled(true); + getChildView("FlexWind")->setEnabled(true); + getChildView("FlexForceX")->setEnabled(true); + getChildView("FlexForceY")->setEnabled(true); + getChildView("FlexForceZ")->setEnabled(true); + + LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + + getChild("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); + getChild("FlexGravity")->setValue(attributes->getGravity()); + getChild("FlexTension")->setValue(attributes->getTension()); + getChild("FlexFriction")->setValue(attributes->getAirFriction()); + getChild("FlexWind")->setValue(attributes->getWindSensitivity()); + getChild("FlexForceX")->setValue(attributes->getUserForce().mV[VX]); + getChild("FlexForceY")->setValue(attributes->getUserForce().mV[VY]); + getChild("FlexForceZ")->setValue(attributes->getUserForce().mV[VZ]); + } + else + { + getChild("FlexNumSections", true)->clear(); + getChild("FlexGravity", true)->clear(); + getChild("FlexTension", true)->clear(); + getChild("FlexFriction", true)->clear(); + getChild("FlexWind", true)->clear(); + getChild("FlexForceX", true)->clear(); + getChild("FlexForceY", true)->clear(); + getChild("FlexForceZ", true)->clear(); + + getChildView("FlexNumSections")->setEnabled(false); + getChildView("FlexGravity")->setEnabled(false); + getChildView("FlexTension")->setEnabled(false); + getChildView("FlexFriction")->setEnabled(false); + getChildView("FlexWind")->setEnabled(false); + getChildView("FlexForceX")->setEnabled(false); + getChildView("FlexForceY")->setEnabled(false); + getChildView("FlexForceZ")->setEnabled(false); + } + + // Material properties + + // Update material part + // slightly inefficient - materials are unique per object, not per TE + U8 material_code = 0; + struct f : public LLSelectedTEGetFunctor + { + U8 get(LLViewerObject* object, S32 te) + { + return object->getMaterial(); + } + } func; + bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code ); + std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright"); + if (editable && single_volume && material_same) + { + mComboMaterial->setEnabled( TRUE ); + if (material_code == LL_MCODE_LIGHT) + { + if (mComboMaterial->getItemCount() == mComboMaterialItemCount) + { + mComboMaterial->add(LEGACY_FULLBRIGHT_DESC); + } + mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC); + } + else + { + if (mComboMaterial->getItemCount() != mComboMaterialItemCount) + { + mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC); + } + + mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code))); + } + } + else + { + mComboMaterial->setEnabled( FALSE ); + } + + // Physics properties + + mSpinPhysicsGravity->set(objectp->getPhysicsGravity()); + mSpinPhysicsGravity->setEnabled(editable); + + mSpinPhysicsFriction->set(objectp->getPhysicsFriction()); + mSpinPhysicsFriction->setEnabled(editable); + + mSpinPhysicsDensity->set(objectp->getPhysicsDensity()); + mSpinPhysicsDensity->setEnabled(editable); + + mSpinPhysicsRestitution->set(objectp->getPhysicsRestitution()); + mSpinPhysicsRestitution->setEnabled(editable); + + // update the physics shape combo to include allowed physics shapes + mComboPhysicsShapeType->removeall(); + mComboPhysicsShapeType->add(getString("None"), LLSD(1)); + + BOOL isMesh = FALSE; + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if (sculpt_params) + { + U8 sculpt_type = sculpt_params->getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH); + } + + if(isMesh && objectp) + { + const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); + LLUUID mesh_id = volume_params.getSculptID(); + if(gMeshRepo.hasPhysicsShape(mesh_id)) + { + // if a mesh contains an uploaded or decomposed physics mesh, + // allow 'Prim' + mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); + } + } + else + { + // simple prims always allow physics shape prim + mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); + } + + mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2)); + mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType())); + mComboPhysicsShapeType->setEnabled(editable && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced())); + + mObject = objectp; + mRootObject = root_objectp; mMenuClipboardFeatures->setEnabled(editable && single_volume && volobjp); // Note: physics doesn't need to be limited by single volume mMenuClipboardLight->setEnabled(editable && single_volume && volobjp); @@ -661,76 +661,76 @@ void LLPanelVolume::getState( ) // static bool LLPanelVolume::precommitValidate( const LLSD& data ) { - // TODO: Richard will fill this in later. - return TRUE; // FALSE means that validation failed and new value should not be commited. + // TODO: Richard will fill this in later. + return TRUE; // FALSE means that validation failed and new value should not be commited. } void LLPanelVolume::refresh() { - getState(); - if (mObject.notNull() && mObject->isDead()) - { - mObject = NULL; - } - - if (mRootObject.notNull() && mRootObject->isDead()) - { - mRootObject = NULL; - } - - bool enable_mesh = false; - - LLSD sim_features; - LLViewerRegion *region = gAgent.getRegion(); - if(region) - { - LLSD sim_features; - region->getSimulatorFeatures(sim_features); - enable_mesh = sim_features.has("PhysicsShapeTypes"); - } - getChildView("label physicsshapetype")->setVisible(enable_mesh); - getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh); - getChildView("Physics Gravity")->setVisible(enable_mesh); - getChildView("Physics Friction")->setVisible(enable_mesh); - getChildView("Physics Density")->setVisible(enable_mesh); - getChildView("Physics Restitution")->setVisible(enable_mesh); - + getState(); + if (mObject.notNull() && mObject->isDead()) + { + mObject = NULL; + } + + if (mRootObject.notNull() && mRootObject->isDead()) + { + mRootObject = NULL; + } + + bool enable_mesh = false; + + LLSD sim_features; + LLViewerRegion *region = gAgent.getRegion(); + if(region) + { + LLSD sim_features; + region->getSimulatorFeatures(sim_features); + enable_mesh = sim_features.has("PhysicsShapeTypes"); + } + getChildView("label physicsshapetype")->setVisible(enable_mesh); + getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh); + getChildView("Physics Gravity")->setVisible(enable_mesh); + getChildView("Physics Friction")->setVisible(enable_mesh); + getChildView("Physics Density")->setVisible(enable_mesh); + getChildView("Physics Restitution")->setVisible(enable_mesh); + /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */ } void LLPanelVolume::draw() { - LLPanel::draw(); + LLPanel::draw(); } // virtual void LLPanelVolume::clearCtrls() { - LLPanel::clearCtrls(); - - getChildView("select_single")->setEnabled(false); - getChildView("select_single")->setVisible(true); - getChildView("edit_object")->setEnabled(false); - getChildView("edit_object")->setVisible(false); - getChildView("Light Checkbox Ctrl")->setEnabled(false);; - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LightColorSwatch->setEnabled( FALSE ); - LightColorSwatch->setValid( FALSE ); - } - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - if(LightTextureCtrl) - { - LightTextureCtrl->setEnabled( FALSE ); - LightTextureCtrl->setValid( FALSE ); - } - - getChildView("Light Intensity")->setEnabled(false); - getChildView("Light Radius")->setEnabled(false); - getChildView("Light Falloff")->setEnabled(false); + LLPanel::clearCtrls(); + + getChildView("select_single")->setEnabled(false); + getChildView("select_single")->setVisible(true); + getChildView("edit_object")->setEnabled(false); + getChildView("edit_object")->setVisible(false); + getChildView("Light Checkbox Ctrl")->setEnabled(false);; + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch) + { + LightColorSwatch->setEnabled( FALSE ); + LightColorSwatch->setValid( FALSE ); + } + LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); + if(LightTextureCtrl) + { + LightTextureCtrl->setEnabled( FALSE ); + LightTextureCtrl->setValid( FALSE ); + } + + getChildView("Light Intensity")->setEnabled(false); + getChildView("Light Radius")->setEnabled(false); + getChildView("Light Falloff")->setEnabled(false); getChildView("Reflection Probe")->setEnabled(false);; getChildView("Probe Volume Type")->setEnabled(false); @@ -738,22 +738,22 @@ void LLPanelVolume::clearCtrls() 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); - getChildView("FlexGravity")->setEnabled(false); - getChildView("FlexTension")->setEnabled(false); - getChildView("FlexFriction")->setEnabled(false); - getChildView("FlexWind")->setEnabled(false); - getChildView("FlexForceX")->setEnabled(false); - getChildView("FlexForceY")->setEnabled(false); - getChildView("FlexForceZ")->setEnabled(false); - - mSpinPhysicsGravity->setEnabled(FALSE); - mSpinPhysicsFriction->setEnabled(FALSE); - mSpinPhysicsDensity->setEnabled(FALSE); - mSpinPhysicsRestitution->setEnabled(FALSE); - - mComboMaterial->setEnabled( FALSE ); + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); + getChildView("FlexNumSections")->setEnabled(false); + getChildView("FlexGravity")->setEnabled(false); + getChildView("FlexTension")->setEnabled(false); + getChildView("FlexFriction")->setEnabled(false); + getChildView("FlexWind")->setEnabled(false); + getChildView("FlexForceX")->setEnabled(false); + getChildView("FlexForceY")->setEnabled(false); + getChildView("FlexForceZ")->setEnabled(false); + + mSpinPhysicsGravity->setEnabled(FALSE); + mSpinPhysicsFriction->setEnabled(FALSE); + mSpinPhysicsDensity->setEnabled(FALSE); + mSpinPhysicsRestitution->setEnabled(FALSE); + + mComboMaterial->setEnabled( FALSE ); } // @@ -762,16 +762,16 @@ void LLPanelVolume::clearCtrls() void LLPanelVolume::sendIsLight() { - LLViewerObject* objectp = mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - - BOOL value = getChild("Light Checkbox Ctrl")->getValue(); - volobjp->setIsLight(value); - LL_INFOS() << "update light sent" << LL_ENDL; + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + BOOL value = getChild("Light Checkbox Ctrl")->getValue(); + volobjp->setIsLight(value); + LL_INFOS() << "update light sent" << LL_ENDL; } void notify_cant_select_reflection_probe() @@ -857,97 +857,97 @@ void LLPanelVolume::doSendIsReflectionProbe(const LLSD & notification, const LLS void LLPanelVolume::sendIsFlexible() { - LLViewerObject* objectp = mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - - BOOL is_flexible = getChild("Flexible1D Checkbox Ctrl")->getValue(); - //BOOL is_flexible = mCheckFlexible1D->get(); - - if (is_flexible) - { - //LLFirstUse::useFlexible(); - - if (objectp->getClickAction() == CLICK_ACTION_SIT) - { - LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_NONE); - } - - } - - if (volobjp->setIsFlexible(is_flexible)) - { - mObject->sendShapeUpdate(); - LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); - } - - LL_INFOS() << "update flexible sent" << LL_ENDL; + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + BOOL is_flexible = getChild("Flexible1D Checkbox Ctrl")->getValue(); + //BOOL is_flexible = mCheckFlexible1D->get(); + + if (is_flexible) + { + //LLFirstUse::useFlexible(); + + if (objectp->getClickAction() == CLICK_ACTION_SIT) + { + LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_NONE); + } + + } + + if (volobjp->setIsFlexible(is_flexible)) + { + mObject->sendShapeUpdate(); + LLSelectMgr::getInstance()->selectionUpdatePhantom(volobjp->flagPhantom()); + } + + LL_INFOS() << "update flexible sent" << LL_ENDL; } void LLPanelVolume::sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata) { - U8 type = ctrl->getValue().asInteger(); - LLSelectMgr::getInstance()->selectionSetPhysicsType(type); + U8 type = ctrl->getValue().asInteger(); + LLSelectMgr::getInstance()->selectionSetPhysicsType(type); - refreshCost(); + refreshCost(); } void LLPanelVolume::sendPhysicsGravity(LLUICtrl* ctrl, void* userdata) { - F32 val = ctrl->getValue().asReal(); - LLSelectMgr::getInstance()->selectionSetGravity(val); + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetGravity(val); } void LLPanelVolume::sendPhysicsFriction(LLUICtrl* ctrl, void* userdata) { - F32 val = ctrl->getValue().asReal(); - LLSelectMgr::getInstance()->selectionSetFriction(val); + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetFriction(val); } void LLPanelVolume::sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata) { - F32 val = ctrl->getValue().asReal(); - LLSelectMgr::getInstance()->selectionSetRestitution(val); + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetRestitution(val); } void LLPanelVolume::sendPhysicsDensity(LLUICtrl* ctrl, void* userdata) { - F32 val = ctrl->getValue().asReal(); - LLSelectMgr::getInstance()->selectionSetDensity(val); + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetDensity(val); } void LLPanelVolume::refreshCost() { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - - if (obj) - { - obj->getObjectCost(); - } + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + + if (obj) + { + obj->getObjectCost(); + } } void LLPanelVolume::onLightCancelColor(const LLSD& data) { - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LightColorSwatch->setColor(mLightSavedColor); - } - onLightSelectColor(data); + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch) + { + LightColorSwatch->setColor(mLightSavedColor); + } + onLightSelectColor(data); } void LLPanelVolume::onLightCancelTexture(const LLSD& data) { - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - LLVOVolume *volobjp = (LLVOVolume *) mObject.get(); + LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); + LLVOVolume *volobjp = (LLVOVolume *) mObject.get(); - if (volobjp && LightTextureCtrl) - { - // Cancel the light texture as requested - // NORSPEC-292 + if (volobjp && LightTextureCtrl) + { + // Cancel the light texture as requested + // NORSPEC-292 // // Texture picker triggers cancel both in case of actual cancel and in case of // selection of "None" texture. @@ -962,44 +962,44 @@ void LLPanelVolume::onLightCancelTexture(const LLSD& data) getChild("Light Focus")->setValue(spot_params.mV[1]); getChild("Light Ambiance")->setValue(spot_params.mV[2]); } - } + } } void LLPanelVolume::onLightSelectColor(const LLSD& data) { - LLViewerObject* objectp = mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - - - LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); - if(LightColorSwatch) - { - LLColor4 clr = LightColorSwatch->get(); - LLColor3 clr3( clr ); - volobjp->setLightSRGBColor(clr3); - mLightSavedColor = clr; - } + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + + LLColorSwatchCtrl* LightColorSwatch = getChild("colorswatch"); + if(LightColorSwatch) + { + LLColor4 clr = LightColorSwatch->get(); + LLColor3 clr3( clr ); + volobjp->setLightSRGBColor(clr3); + mLightSavedColor = clr; + } } void LLPanelVolume::onLightSelectTexture(const LLSD& data) { - if (mObject.isNull() || (mObject->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - LLVOVolume *volobjp = (LLVOVolume *) mObject.get(); - - - LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); - if(LightTextureCtrl) - { - LLUUID id = LightTextureCtrl->getImageAssetID(); - setLightTextureID(id, LightTextureCtrl->getImageItemID(), volobjp); - } + if (mObject.isNull() || (mObject->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *) mObject.get(); + + + LLTextureCtrl* LightTextureCtrl = getChild("light texture control"); + if(LightTextureCtrl) + { + LLUUID id = LightTextureCtrl->getImageAssetID(); + setLightTextureID(id, LightTextureCtrl->getImageItemID(), volobjp); + } } void LLPanelVolume::onCopyFeatures() @@ -1323,100 +1323,100 @@ bool LLPanelVolume::menuEnableItem(const LLSD& userdata) // static void LLPanelVolume::onCommitMaterial( LLUICtrl* ctrl, void* userdata ) { - LLPanelVolume* self = (LLPanelVolume*)userdata; - LLComboBox* box = (LLComboBox*) ctrl; - - if (box) - { - // apply the currently selected material to the object - const std::string& material_name = box->getSimple(); - std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright"); - if (material_name != LEGACY_FULLBRIGHT_DESC) - { - U8 material_code = LLMaterialTable::basic.getMCode(material_name); - if (self) - { - LLViewerObject* objectp = self->mObject; - if (objectp) - { - objectp->setPhysicsGravity(DEFAULT_GRAVITY_MULTIPLIER); - objectp->setPhysicsFriction(LLMaterialTable::basic.getFriction(material_code)); - //currently density is always set to 1000 serverside regardless of chosen material, - //actual material density should be used here, if this behavior change - objectp->setPhysicsDensity(DEFAULT_DENSITY); - objectp->setPhysicsRestitution(LLMaterialTable::basic.getRestitution(material_code)); - } - } - LLSelectMgr::getInstance()->selectionSetMaterial(material_code); - } - } + LLPanelVolume* self = (LLPanelVolume*)userdata; + LLComboBox* box = (LLComboBox*) ctrl; + + if (box) + { + // apply the currently selected material to the object + const std::string& material_name = box->getSimple(); + std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright"); + if (material_name != LEGACY_FULLBRIGHT_DESC) + { + U8 material_code = LLMaterialTable::basic.getMCode(material_name); + if (self) + { + LLViewerObject* objectp = self->mObject; + if (objectp) + { + objectp->setPhysicsGravity(DEFAULT_GRAVITY_MULTIPLIER); + objectp->setPhysicsFriction(LLMaterialTable::basic.getFriction(material_code)); + //currently density is always set to 1000 serverside regardless of chosen material, + //actual material density should be used here, if this behavior change + objectp->setPhysicsDensity(DEFAULT_DENSITY); + objectp->setPhysicsRestitution(LLMaterialTable::basic.getRestitution(material_code)); + } + } + LLSelectMgr::getInstance()->selectionSetMaterial(material_code); + } + } } // static void LLPanelVolume::onCommitLight( 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->setLightIntensity((F32)self->getChild("Light Intensity")->getValue().asReal()); - volobjp->setLightRadius((F32)self->getChild("Light Radius")->getValue().asReal()); - volobjp->setLightFalloff((F32)self->getChild("Light Falloff")->getValue().asReal()); - - LLColorSwatchCtrl* LightColorSwatch = self->getChild("colorswatch"); - if(LightColorSwatch) - { - LLColor4 clr = LightColorSwatch->get(); - volobjp->setLightSRGBColor(LLColor3(clr)); - } - - LLTextureCtrl* LightTextureCtrl = self->getChild("light texture control"); - if(LightTextureCtrl) - { - LLUUID id = LightTextureCtrl->getImageAssetID(); + LLPanelVolume* self = (LLPanelVolume*) userdata; + LLViewerObject* objectp = self->mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + LLVOVolume *volobjp = (LLVOVolume *)objectp; + + + volobjp->setLightIntensity((F32)self->getChild("Light Intensity")->getValue().asReal()); + volobjp->setLightRadius((F32)self->getChild("Light Radius")->getValue().asReal()); + volobjp->setLightFalloff((F32)self->getChild("Light Falloff")->getValue().asReal()); + + LLColorSwatchCtrl* LightColorSwatch = self->getChild("colorswatch"); + if(LightColorSwatch) + { + LLColor4 clr = LightColorSwatch->get(); + volobjp->setLightSRGBColor(LLColor3(clr)); + } + + LLTextureCtrl* LightTextureCtrl = self->getChild("light texture control"); + if(LightTextureCtrl) + { + LLUUID id = LightTextureCtrl->getImageAssetID(); LLUUID item_id = LightTextureCtrl->getImageItemID(); - if (id.notNull()) - { - if (!volobjp->isLightSpotlight()) - { //this commit is making this a spot light, set UI to default params + if (id.notNull()) + { + if (!volobjp->isLightSpotlight()) + { //this commit is making this a spot light, set UI to default params setLightTextureID(id, item_id, volobjp); - LLVector3 spot_params = volobjp->getSpotLightParams(); - self->getChild("Light FOV")->setValue(spot_params.mV[0]); - self->getChild("Light Focus")->setValue(spot_params.mV[1]); - self->getChild("Light Ambiance")->setValue(spot_params.mV[2]); - } - else - { //modifying existing params, this time volobjp won't change params on its own. + LLVector3 spot_params = volobjp->getSpotLightParams(); + self->getChild("Light FOV")->setValue(spot_params.mV[0]); + self->getChild("Light Focus")->setValue(spot_params.mV[1]); + self->getChild("Light Ambiance")->setValue(spot_params.mV[2]); + } + else + { //modifying existing params, this time volobjp won't change params on its own. if (volobjp->getLightTextureID() != id) { setLightTextureID(id, item_id, volobjp); } - LLVector3 spot_params; - spot_params.mV[0] = (F32) self->getChild("Light FOV")->getValue().asReal(); - spot_params.mV[1] = (F32) self->getChild("Light Focus")->getValue().asReal(); - spot_params.mV[2] = (F32) self->getChild("Light Ambiance")->getValue().asReal(); - volobjp->setSpotLightParams(spot_params); - } - } - else if (volobjp->isLightSpotlight()) - { //no longer a spot light - setLightTextureID(id, item_id, volobjp); - //self->getChildView("Light FOV")->setEnabled(FALSE); - //self->getChildView("Light Focus")->setEnabled(FALSE); - //self->getChildView("Light Ambiance")->setEnabled(FALSE); - } - } - - + LLVector3 spot_params; + spot_params.mV[0] = (F32) self->getChild("Light FOV")->getValue().asReal(); + spot_params.mV[1] = (F32) self->getChild("Light Focus")->getValue().asReal(); + spot_params.mV[2] = (F32) self->getChild("Light Ambiance")->getValue().asReal(); + volobjp->setSpotLightParams(spot_params); + } + } + else if (volobjp->isLightSpotlight()) + { //no longer a spot light + setLightTextureID(id, item_id, volobjp); + //self->getChildView("Light FOV")->setEnabled(FALSE); + //self->getChildView("Light Focus")->setEnabled(FALSE); + //self->getChildView("Light Ambiance")->setEnabled(FALSE); + } + } + + } -//static +//static void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) { LLPanelVolume* self = (LLPanelVolume*)userdata; @@ -1432,9 +1432,9 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) std::string update_type = self->getChild("Probe Update Type")->getValue().asString(); - bool is_mirror = update_type.find("Mirror") != std::string::npos; + bool is_mirror = update_type.find("Mirror") != std::string::npos; - volobjp->setReflectionProbeIsDynamic(update_type.find("Dynamic") != std::string::npos); + volobjp->setReflectionProbeIsDynamic(update_type.find("Dynamic") != std::string::npos); volobjp->setReflectionProbeIsMirror(is_mirror); self->getChildView("Probe Ambiance")->setEnabled(!is_mirror); @@ -1469,7 +1469,7 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) profile = LL_PCODE_PROFILE_SQUARE; path = LL_PCODE_PATH_LINE; } - + LLVolumeParams params; params.getProfileParams().setCurveType(profile); params.getPathParams().setCurveType(path); @@ -1481,8 +1481,8 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) // static void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata ) { - LLPanelVolume* self = (LLPanelVolume*) userdata; - self->sendIsLight(); + LLPanelVolume* self = (LLPanelVolume*) userdata; + self->sendIsLight(); } // static @@ -1507,7 +1507,7 @@ void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) { LLToolDragAndDrop::handleDropMaterialProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); - } + } volobjp->setLightTextureID(asset_id); } } @@ -1525,47 +1525,47 @@ void LLPanelVolume::onCommitIsReflectionProbe(LLUICtrl* ctrl, void* userdata) // static void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) { - LLPanelVolume* self = (LLPanelVolume*) userdata; - LLViewerObject* objectp = self->mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } - - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - if (attributes) - { - LLFlexibleObjectData new_attributes; - new_attributes = *attributes; - - - new_attributes.setSimulateLOD(self->getChild("FlexNumSections")->getValue().asInteger());//(S32)self->mSpinSections->get()); - new_attributes.setGravity((F32)self->getChild("FlexGravity")->getValue().asReal()); - new_attributes.setTension((F32)self->getChild("FlexTension")->getValue().asReal()); - new_attributes.setAirFriction((F32)self->getChild("FlexFriction")->getValue().asReal()); - new_attributes.setWindSensitivity((F32)self->getChild("FlexWind")->getValue().asReal()); - F32 fx = (F32)self->getChild("FlexForceX")->getValue().asReal(); - F32 fy = (F32)self->getChild("FlexForceY")->getValue().asReal(); - F32 fz = (F32)self->getChild("FlexForceZ")->getValue().asReal(); - LLVector3 force(fx,fy,fz); - - new_attributes.setUserForce(force); - objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); - } - - // Values may fail validation - self->refresh(); + LLPanelVolume* self = (LLPanelVolume*) userdata; + LLViewerObject* objectp = self->mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } + + LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + if (attributes) + { + LLFlexibleObjectData new_attributes; + new_attributes = *attributes; + + + new_attributes.setSimulateLOD(self->getChild("FlexNumSections")->getValue().asInteger());//(S32)self->mSpinSections->get()); + new_attributes.setGravity((F32)self->getChild("FlexGravity")->getValue().asReal()); + new_attributes.setTension((F32)self->getChild("FlexTension")->getValue().asReal()); + new_attributes.setAirFriction((F32)self->getChild("FlexFriction")->getValue().asReal()); + new_attributes.setWindSensitivity((F32)self->getChild("FlexWind")->getValue().asReal()); + F32 fx = (F32)self->getChild("FlexForceX")->getValue().asReal(); + F32 fy = (F32)self->getChild("FlexForceY")->getValue().asReal(); + F32 fz = (F32)self->getChild("FlexForceZ")->getValue().asReal(); + LLVector3 force(fx,fy,fz); + + new_attributes.setUserForce(force); + objectp->setParameterEntry(LLNetworkData::PARAMS_FLEXIBLE, new_attributes, true); + } + + // Values may fail validation + self->refresh(); } void LLPanelVolume::onCommitAnimatedMeshCheckbox(LLUICtrl *, void*) { - LLViewerObject* objectp = mObject; - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; + LLViewerObject* objectp = mObject; + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; } - LLVOVolume *volobjp = (LLVOVolume *)objectp; - BOOL animated_mesh = getChild("Animated Mesh Checkbox Ctrl")->getValue(); + LLVOVolume *volobjp = (LLVOVolume *)objectp; + BOOL animated_mesh = getChild("Animated Mesh Checkbox Ctrl")->getValue(); U32 flags = volobjp->getExtendedMeshFlags(); U32 new_flags = flags; if (animated_mesh) @@ -1581,49 +1581,49 @@ void LLPanelVolume::onCommitAnimatedMeshCheckbox(LLUICtrl *, void*) volobjp->setExtendedMeshFlags(new_flags); } - //refresh any bakes - if (volobjp) - { - volobjp->refreshBakeTexture(); - - LLViewerObject::const_child_list_t& child_list = volobjp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* objectp = *iter; - if (objectp) - { - objectp->refreshBakeTexture(); - } - } - - if (gAgentAvatarp) - { - gAgentAvatarp->updateMeshVisibility(); - } - } + //refresh any bakes + if (volobjp) + { + volobjp->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = volobjp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* objectp = *iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } + + if (gAgentAvatarp) + { + gAgentAvatarp->updateMeshVisibility(); + } + } } void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*) { - if (mObject->flagObjectPermanent()) - { - LLNotificationsUtil::add("PathfindingLinksets_ChangeToFlexiblePath", LLSD(), LLSD(), boost::bind(&LLPanelVolume::handleResponseChangeToFlexible, this, _1, _2)); - } - else - { - sendIsFlexible(); - } + if (mObject->flagObjectPermanent()) + { + LLNotificationsUtil::add("PathfindingLinksets_ChangeToFlexiblePath", LLSD(), LLSD(), boost::bind(&LLPanelVolume::handleResponseChangeToFlexible, this, _1, _2)); + } + else + { + sendIsFlexible(); + } } void LLPanelVolume::handleResponseChangeToFlexible(const LLSD &pNotification, const LLSD &pResponse) { - if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) - { - sendIsFlexible(); - } - else - { - getChild("Flexible1D Checkbox Ctrl")->setValue(FALSE); - } + if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) + { + sendIsFlexible(); + } + else + { + getChild("Flexible1D Checkbox Ctrl")->setValue(FALSE); + } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 20b00974e1..f602dee0cb 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llselectmgr.cpp * @brief A manager for selected objects and faces. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -120,13 +120,13 @@ const S32 MAX_CHILDREN_PER_TASK = 255; BOOL LLSelectMgr::sRectSelectInclusive = TRUE; BOOL LLSelectMgr::sRenderHiddenSelections = TRUE; BOOL LLSelectMgr::sRenderLightRadius = FALSE; -F32 LLSelectMgr::sHighlightThickness = 0.f; -F32 LLSelectMgr::sHighlightUScale = 0.f; -F32 LLSelectMgr::sHighlightVScale = 0.f; -F32 LLSelectMgr::sHighlightAlpha = 0.f; -F32 LLSelectMgr::sHighlightAlphaTest = 0.f; -F32 LLSelectMgr::sHighlightUAnim = 0.f; -F32 LLSelectMgr::sHighlightVAnim = 0.f; +F32 LLSelectMgr::sHighlightThickness = 0.f; +F32 LLSelectMgr::sHighlightUScale = 0.f; +F32 LLSelectMgr::sHighlightVScale = 0.f; +F32 LLSelectMgr::sHighlightAlpha = 0.f; +F32 LLSelectMgr::sHighlightAlphaTest = 0.f; +F32 LLSelectMgr::sHighlightUAnim = 0.f; +F32 LLSelectMgr::sHighlightVAnim = 0.f; LLColor4 LLSelectMgr::sSilhouetteParentColor; LLColor4 LLSelectMgr::sSilhouetteChildColor; LLColor4 LLSelectMgr::sHighlightInspectColor; @@ -137,15 +137,15 @@ LLColor4 LLSelectMgr::sContextSilhouetteColor; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // struct LLDeRezInfo // -// Used to keep track of important derez info. +// Used to keep track of important derez info. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct LLDeRezInfo { - EDeRezDestination mDestination; - LLUUID mDestinationID; - LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) : - mDestination(dest), mDestinationID(dest_id) {} + EDeRezDestination mDestination; + LLUUID mDestinationID; + LLDeRezInfo(EDeRezDestination dest, const LLUUID& dest_id) : + mDestination(dest), mDestinationID(dest_id) {} }; // @@ -206,7 +206,7 @@ LLSelectionCallbackData::LLSelectionCallbackData() void LLSelectMgr::cleanupGlobals() { - LLSelectMgr::getInstance()->clearSelections(); + LLSelectMgr::getInstance()->clearSelections(); } //----------------------------------------------------------------------------- @@ -218,38 +218,38 @@ LLSelectMgr::LLSelectMgr() mAllowSelectAvatar( LLCachedControl(gSavedSettings, "AllowSelectAvatar", FALSE)), mDebugSelectMgr(LLCachedControl(gSavedSettings, "DebugSelectMgr", FALSE)) { - mTEMode = FALSE; - mTextureChannel = LLRender::DIFFUSE_MAP; - mLastCameraPos.clearVec(); + mTEMode = FALSE; + mTextureChannel = LLRender::DIFFUSE_MAP; + mLastCameraPos.clearVec(); - sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness"); - sHighlightUScale = gSavedSettings.getF32("SelectionHighlightUScale"); - sHighlightVScale = gSavedSettings.getF32("SelectionHighlightVScale"); - sHighlightAlpha = gSavedSettings.getF32("SelectionHighlightAlpha") * 2; - sHighlightAlphaTest = gSavedSettings.getF32("SelectionHighlightAlphaTest"); - sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim"); - sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim"); + sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness"); + sHighlightUScale = gSavedSettings.getF32("SelectionHighlightUScale"); + sHighlightVScale = gSavedSettings.getF32("SelectionHighlightVScale"); + sHighlightAlpha = gSavedSettings.getF32("SelectionHighlightAlpha") * 2; + sHighlightAlphaTest = gSavedSettings.getF32("SelectionHighlightAlphaTest"); + sHighlightUAnim = gSavedSettings.getF32("SelectionHighlightUAnim"); + sHighlightVAnim = gSavedSettings.getF32("SelectionHighlightVAnim"); - sSilhouetteParentColor =LLUIColorTable::instance().getColor("SilhouetteParentColor"); - sSilhouetteChildColor = LLUIColorTable::instance().getColor("SilhouetteChildColor"); - sHighlightParentColor = LLUIColorTable::instance().getColor("HighlightParentColor"); - sHighlightChildColor = LLUIColorTable::instance().getColor("HighlightChildColor"); - sHighlightInspectColor = LLUIColorTable::instance().getColor("HighlightInspectColor"); - sContextSilhouetteColor = LLUIColorTable::instance().getColor("ContextSilhouetteColor")*0.5f; + sSilhouetteParentColor =LLUIColorTable::instance().getColor("SilhouetteParentColor"); + sSilhouetteChildColor = LLUIColorTable::instance().getColor("SilhouetteChildColor"); + sHighlightParentColor = LLUIColorTable::instance().getColor("HighlightParentColor"); + sHighlightChildColor = LLUIColorTable::instance().getColor("HighlightChildColor"); + sHighlightInspectColor = LLUIColorTable::instance().getColor("HighlightInspectColor"); + sContextSilhouetteColor = LLUIColorTable::instance().getColor("ContextSilhouetteColor")*0.5f; - sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); - - mRenderSilhouettes = TRUE; + sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); - mGridMode = GRID_MODE_WORLD; - gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); + mRenderSilhouettes = TRUE; - mSelectedObjects = new LLObjectSelection(); - mHoverObjects = new LLObjectSelection(); - mHighlightedObjects = new LLObjectSelection(); + mGridMode = GRID_MODE_WORLD; + gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); - mForceSelection = FALSE; - mShowSelection = FALSE; + mSelectedObjects = new LLObjectSelection(); + mHoverObjects = new LLObjectSelection(); + mHighlightedObjects = new LLObjectSelection(); + + mForceSelection = FALSE; + mShowSelection = FALSE; } @@ -258,47 +258,47 @@ LLSelectMgr::LLSelectMgr() //----------------------------------------------------------------------------- LLSelectMgr::~LLSelectMgr() { - clearSelections(); + clearSelections(); } void LLSelectMgr::clearSelections() { - mHoverObjects->deleteAllNodes(); - mSelectedObjects->deleteAllNodes(); - mHighlightedObjects->deleteAllNodes(); - mRectSelectedObjects.clear(); - mGridObjects.deleteAllNodes(); + mHoverObjects->deleteAllNodes(); + mSelectedObjects->deleteAllNodes(); + mHighlightedObjects->deleteAllNodes(); + mRectSelectedObjects.clear(); + mGridObjects.deleteAllNodes(); - LLPipeline::setRenderHighlightTextureChannel(LLRender::DIFFUSE_MAP); + LLPipeline::setRenderHighlightTextureChannel(LLRender::DIFFUSE_MAP); } void LLSelectMgr::update() { - mSelectedObjects->cleanupNodes(); + mSelectedObjects->cleanupNodes(); } void LLSelectMgr::updateEffects() { - //keep reference grid objects active - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - gPipeline.markMoved(drawable); - } - return true; - } - } func; - mGridObjects.applyToObjects(&func); - - if (mEffectsTimer.getElapsedTimeF32() > 1.f) - { - mSelectedObjects->updateEffects(); - mEffectsTimer.reset(); - } + //keep reference grid objects active + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + gPipeline.markMoved(drawable); + } + return true; + } + } func; + mGridObjects.applyToObjects(&func); + + if (mEffectsTimer.getElapsedTimeF32() > 1.f) + { + mSelectedObjects->updateEffects(); + mEffectsTimer.reset(); + } } void LLSelectMgr::resetObjectOverrides() @@ -339,31 +339,31 @@ void LLSelectMgr::resetObjectOverrides(LLObjectSelectionHandle selected_handle) void LLSelectMgr::overrideObjectUpdates() { - //override any position updates from simulator on objects being edited - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* selectNode) - { - LLViewerObject* object = selectNode->getObject(); - if (object && object->permMove() && !object->isPermanentEnforced()) - { - if (!selectNode->mLastPositionLocal.isExactlyZero()) - { - object->setPosition(selectNode->mLastPositionLocal); - } - if (selectNode->mLastRotation != LLQuaternion()) - { - object->setRotation(selectNode->mLastRotation); - } - if (!selectNode->mLastScale.isExactlyZero()) - { - object->setScale(selectNode->mLastScale); - } - } - return true; - } - } func; - getSelection()->applyToNodes(&func); + //override any position updates from simulator on objects being edited + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* selectNode) + { + LLViewerObject* object = selectNode->getObject(); + if (object && object->permMove() && !object->isPermanentEnforced()) + { + if (!selectNode->mLastPositionLocal.isExactlyZero()) + { + object->setPosition(selectNode->mLastPositionLocal); + } + if (selectNode->mLastRotation != LLQuaternion()) + { + object->setRotation(selectNode->mLastRotation); + } + if (!selectNode->mLastScale.isExactlyZero()) + { + object->setScale(selectNode->mLastScale); + } + } + return true; + } + } func; + getSelection()->applyToNodes(&func); } void LLSelectMgr::resetAvatarOverrides() @@ -397,7 +397,7 @@ void LLSelectMgr::overrideAvatarUpdates() } // remove selected avatars from this list, - // but set object overrides to make sure avatar won't snap back + // but set object overrides to make sure avatar won't snap back struct f : public LLSelectedNodeFunctor { f(LLSelectMgr* p) : mManager(p) {} @@ -458,62 +458,62 @@ void LLSelectMgr::overrideAvatarUpdates() //----------------------------------------------------------------------------- LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face, S32 gltf_node, S32 gltf_primitive) { - llassert( object ); - - //remember primary object - mSelectedObjects->mPrimaryObject = object; - - // Don't add an object that is already in the list - if (object->isSelected() ) { - // make sure point at position is updated - updatePointAt(); - gEditMenuHandler = this; - return NULL; - } - - if (!canSelectObject(object)) - { - //make_ui_sound("UISndInvalidOp"); - return NULL; - } - - // LL_INFOS() << "Adding object to selected object list" << LL_ENDL; - - // Place it in the list and tag it. - // This will refresh dialogs. - addAsIndividual(object, face, TRUE, gltf_node, gltf_primitive); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - // *FIX: shouldn't zero out these either - object->setVelocity(LLVector3::zero); - object->setAcceleration(LLVector3::zero); - //object->setAngularVelocity(LLVector3::zero); - object->resetRot(); - - // Always send to simulator, so you get a copy of the - // permissions structure back. - gMessageSystem->newMessageFast(_PREHASH_ObjectSelect); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - LLViewerRegion* regionp = object->getRegion(); - gMessageSystem->sendReliable( regionp->getHost()); - - updatePointAt(); - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; + llassert( object ); + + //remember primary object + mSelectedObjects->mPrimaryObject = object; + + // Don't add an object that is already in the list + if (object->isSelected() ) { + // make sure point at position is updated + updatePointAt(); + gEditMenuHandler = this; + return NULL; + } + + if (!canSelectObject(object)) + { + //make_ui_sound("UISndInvalidOp"); + return NULL; + } + + // LL_INFOS() << "Adding object to selected object list" << LL_ENDL; + + // Place it in the list and tag it. + // This will refresh dialogs. + addAsIndividual(object, face, TRUE, gltf_node, gltf_primitive); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + // *FIX: shouldn't zero out these either + object->setVelocity(LLVector3::zero); + object->setAcceleration(LLVector3::zero); + //object->setAngularVelocity(LLVector3::zero); + object->resetRot(); + + // Always send to simulator, so you get a copy of the + // permissions structure back. + gMessageSystem->newMessageFast(_PREHASH_ObjectSelect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + LLViewerRegion* regionp = object->getRegion(); + gMessageSystem->sendReliable( regionp->getHost()); + + updatePointAt(); + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; } //----------------------------------------------------------------------------- @@ -521,149 +521,149 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S3 //----------------------------------------------------------------------------- LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end, BOOL ignore_select_owned) { - llassert( obj ); - - //remember primary object - mSelectedObjects->mPrimaryObject = obj; - - // This may be incorrect if things weren't family selected before... - djs 07/08/02 - // Don't add an object that is already in the list - if (obj->isSelected() ) - { - // make sure pointat position is updated - updatePointAt(); - gEditMenuHandler = this; - return NULL; - } - - if (!canSelectObject(obj,ignore_select_owned)) - { - //make_ui_sound("UISndInvalidOp"); - return NULL; - } - - // Since we're selecting a family, start at the root, but - // don't include an avatar. - LLViewerObject* root = obj; - - while(!root->isAvatar() && root->getParent()) - { - LLViewerObject* parent = (LLViewerObject*)root->getParent(); - if (parent->isAvatar()) - { - break; - } - root = parent; - } - - // Collect all of the objects - std::vector objects; - - root->addThisAndNonJointChildren(objects); - addAsFamily(objects, add_to_end); - - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); - - dialog_refresh_all(); - - // Always send to simulator, so you get a copy of the permissions - // structure back. - sendSelect(); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - root->setVelocity(LLVector3::zero); - root->setAcceleration(LLVector3::zero); - //root->setAngularVelocity(LLVector3::zero); - root->resetRot(); - - // leave component mode - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - gSavedSettings.setBOOL("EditLinkedParts", FALSE); - promoteSelectionToRoot(); - } - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; + llassert( obj ); + + //remember primary object + mSelectedObjects->mPrimaryObject = obj; + + // This may be incorrect if things weren't family selected before... - djs 07/08/02 + // Don't add an object that is already in the list + if (obj->isSelected() ) + { + // make sure pointat position is updated + updatePointAt(); + gEditMenuHandler = this; + return NULL; + } + + if (!canSelectObject(obj,ignore_select_owned)) + { + //make_ui_sound("UISndInvalidOp"); + return NULL; + } + + // Since we're selecting a family, start at the root, but + // don't include an avatar. + LLViewerObject* root = obj; + + while(!root->isAvatar() && root->getParent()) + { + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) + { + break; + } + root = parent; + } + + // Collect all of the objects + std::vector objects; + + root->addThisAndNonJointChildren(objects); + addAsFamily(objects, add_to_end); + + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); + + dialog_refresh_all(); + + // Always send to simulator, so you get a copy of the permissions + // structure back. + sendSelect(); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + root->setVelocity(LLVector3::zero); + root->setAcceleration(LLVector3::zero); + //root->setAngularVelocity(LLVector3::zero); + root->resetRot(); + + // leave component mode + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + gSavedSettings.setBOOL("EditLinkedParts", FALSE); + promoteSelectionToRoot(); + } + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; } //----------------------------------------------------------------------------- // Select the object, parents and children. //----------------------------------------------------------------------------- LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vector& object_list, - BOOL send_to_sim) -{ - // Collect all of the objects, children included - std::vector objects; - - //clear primary object (no primary object) - mSelectedObjects->mPrimaryObject = NULL; - - if (object_list.size() < 1) - { - return NULL; - } - - // NOTE -- we add the objects in REVERSE ORDER - // to preserve the order in the mSelectedObjects list - for (std::vector::const_reverse_iterator riter = object_list.rbegin(); - riter != object_list.rend(); ++riter) - { - LLViewerObject *object = *riter; - - llassert( object ); - - if (!canSelectObject(object)) continue; - - object->addThisAndNonJointChildren(objects); - addAsFamily(objects); - - // Stop the object from moving (this anticipates changes on the - // simulator in LLTask::userSelect) - object->setVelocity(LLVector3::zero); - object->setAcceleration(LLVector3::zero); - //object->setAngularVelocity(LLVector3::zero); - object->resetRot(); - } - - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); - dialog_refresh_all(); - - // Almost always send to simulator, so you get a copy of the permissions - // structure back. - // JC: The one case where you don't want to do this is if you're selecting - // all the objects on a sim. - if (send_to_sim) - { - sendSelect(); - } - - // leave component mode - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - gSavedSettings.setBOOL("EditLinkedParts", FALSE); - promoteSelectionToRoot(); - } - - // have selection manager handle edit menu immediately after - // user selects an object - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } - - return mSelectedObjects; + BOOL send_to_sim) +{ + // Collect all of the objects, children included + std::vector objects; + + //clear primary object (no primary object) + mSelectedObjects->mPrimaryObject = NULL; + + if (object_list.size() < 1) + { + return NULL; + } + + // NOTE -- we add the objects in REVERSE ORDER + // to preserve the order in the mSelectedObjects list + for (std::vector::const_reverse_iterator riter = object_list.rbegin(); + riter != object_list.rend(); ++riter) + { + LLViewerObject *object = *riter; + + llassert( object ); + + if (!canSelectObject(object)) continue; + + object->addThisAndNonJointChildren(objects); + addAsFamily(objects); + + // Stop the object from moving (this anticipates changes on the + // simulator in LLTask::userSelect) + object->setVelocity(LLVector3::zero); + object->setAcceleration(LLVector3::zero); + //object->setAngularVelocity(LLVector3::zero); + object->resetRot(); + } + + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); + dialog_refresh_all(); + + // Almost always send to simulator, so you get a copy of the permissions + // structure back. + // JC: The one case where you don't want to do this is if you're selecting + // all the objects on a sim. + if (send_to_sim) + { + sendSelect(); + } + + // leave component mode + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + gSavedSettings.setBOOL("EditLinkedParts", FALSE); + promoteSelectionToRoot(); + } + + // have selection manager handle edit menu immediately after + // user selects an object + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } + + return mSelectedObjects; } // Use for when the simulator kills an object. This version also @@ -672,138 +672,138 @@ LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const std::vectorgetCurrentTool(); - - // It's possible that the tool is editing an object that is not selected - LLViewerObject* tool_editing_object = tool->getEditingObject(); - if( tool_editing_object && tool_editing_object->mID == id) - { - tool->stopEditing(); - object_found = TRUE; - } - - // Iterate through selected objects list and kill the object - if( !object_found ) - { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - LLViewerObject* object = (*curiter)->getObject(); - if (object->mID == id) - { - if (tool) - { - tool->stopEditing(); - } - - // lose the selection, don't tell simulator, it knows - deselectObjectAndFamily(object, FALSE); - object_found = TRUE; - break; // must break here, may have removed multiple objects from list - } - else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id) - { - // It's possible the item being removed has an avatar sitting on it - // So remove the avatar that is sitting on the object. - deselectObjectAndFamily(object, FALSE); - break; // must break here, may have removed multiple objects from list - } - } - } - - return object_found; + BOOL object_found = FALSE; + LLTool *tool = NULL; + + tool = LLToolMgr::getInstance()->getCurrentTool(); + + // It's possible that the tool is editing an object that is not selected + LLViewerObject* tool_editing_object = tool->getEditingObject(); + if( tool_editing_object && tool_editing_object->mID == id) + { + tool->stopEditing(); + object_found = TRUE; + } + + // Iterate through selected objects list and kill the object + if( !object_found ) + { + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; + LLViewerObject* object = (*curiter)->getObject(); + if (object->mID == id) + { + if (tool) + { + tool->stopEditing(); + } + + // lose the selection, don't tell simulator, it knows + deselectObjectAndFamily(object, FALSE); + object_found = TRUE; + break; // must break here, may have removed multiple objects from list + } + else if (object->isAvatar() && object->getParent() && ((LLViewerObject*)object->getParent())->mID == id) + { + // It's possible the item being removed has an avatar sitting on it + // So remove the avatar that is sitting on the object. + deselectObjectAndFamily(object, FALSE); + break; // must break here, may have removed multiple objects from list + } + } + } + + return object_found; } bool LLSelectMgr::linkObjects() { - if (!LLSelectMgr::getInstance()->selectGetAllRootsValid()) - { - LLNotificationsUtil::add("UnableToLinkWhileDownloading"); - return true; - } - - S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - if (object_count > MAX_CHILDREN_PER_TASK + 1) - { - LLSD args; - args["COUNT"] = llformat("%d", object_count); - int max = MAX_CHILDREN_PER_TASK+1; - args["MAX"] = llformat("%d", max); - LLNotificationsUtil::add("UnableToLinkObjects", args); - return true; - } - - if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2) - { - LLNotificationsUtil::add("CannotLinkIncompleteSet"); - return true; - } - - if (!LLSelectMgr::getInstance()->selectGetRootsModify()) - { - LLNotificationsUtil::add("CannotLinkModify"); - return true; - } - - if (!LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) - { - LLNotificationsUtil::add("CannotLinkPermanent"); - return true; - } - - LLUUID owner_id; - std::string owner_name; - if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name)) - { - // we don't actually care if you're the owner, but novices are - // the most likely to be stumped by this one, so offer the - // easiest and most likely solution. - LLNotificationsUtil::add("CannotLinkDifferentOwners"); - return true; - } - - if (!LLSelectMgr::getInstance()->selectGetSameRegion()) - { - LLNotificationsUtil::add("CannotLinkAcrossRegions"); - return true; - } - - LLSelectMgr::getInstance()->sendLink(); - - return true; + if (!LLSelectMgr::getInstance()->selectGetAllRootsValid()) + { + LLNotificationsUtil::add("UnableToLinkWhileDownloading"); + return true; + } + + S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (object_count > MAX_CHILDREN_PER_TASK + 1) + { + LLSD args; + args["COUNT"] = llformat("%d", object_count); + int max = MAX_CHILDREN_PER_TASK+1; + args["MAX"] = llformat("%d", max); + LLNotificationsUtil::add("UnableToLinkObjects", args); + return true; + } + + if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2) + { + LLNotificationsUtil::add("CannotLinkIncompleteSet"); + return true; + } + + if (!LLSelectMgr::getInstance()->selectGetRootsModify()) + { + LLNotificationsUtil::add("CannotLinkModify"); + return true; + } + + if (!LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) + { + LLNotificationsUtil::add("CannotLinkPermanent"); + return true; + } + + LLUUID owner_id; + std::string owner_name; + if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name)) + { + // we don't actually care if you're the owner, but novices are + // the most likely to be stumped by this one, so offer the + // easiest and most likely solution. + LLNotificationsUtil::add("CannotLinkDifferentOwners"); + return true; + } + + if (!LLSelectMgr::getInstance()->selectGetSameRegion()) + { + LLNotificationsUtil::add("CannotLinkAcrossRegions"); + return true; + } + + LLSelectMgr::getInstance()->sendLink(); + + return true; } bool LLSelectMgr::unlinkObjects() { - S32 min_objects_for_confirm = gSavedSettings.getS32("MinObjectsForUnlinkConfirm"); - S32 unlink_object_count = mSelectedObjects->getObjectCount(); // clears out nodes with NULL objects - if (unlink_object_count >= min_objects_for_confirm - && unlink_object_count > mSelectedObjects->getRootObjectCount()) - { - // total count > root count means that there are childer inside and that there are linksets that will be unlinked - LLNotificationsUtil::add("ConfirmUnlink", LLSD(), LLSD(), boost::bind(&LLSelectMgr::confirmUnlinkObjects, this, _1, _2)); - return true; - } + S32 min_objects_for_confirm = gSavedSettings.getS32("MinObjectsForUnlinkConfirm"); + S32 unlink_object_count = mSelectedObjects->getObjectCount(); // clears out nodes with NULL objects + if (unlink_object_count >= min_objects_for_confirm + && unlink_object_count > mSelectedObjects->getRootObjectCount()) + { + // total count > root count means that there are childer inside and that there are linksets that will be unlinked + LLNotificationsUtil::add("ConfirmUnlink", LLSD(), LLSD(), boost::bind(&LLSelectMgr::confirmUnlinkObjects, this, _1, _2)); + return true; + } - LLSelectMgr::getInstance()->sendDelink(); - return true; + LLSelectMgr::getInstance()->sendDelink(); + return true; } void LLSelectMgr::confirmUnlinkObjects(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // if Cancel pressed - if (option == 1) - { - return; - } + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } - LLSelectMgr::getInstance()->sendDelink(); - return; + LLSelectMgr::getInstance()->sendDelink(); + return; } // in order to link, all objects must have the same owner, and the @@ -820,158 +820,158 @@ void LLSelectMgr::confirmUnlinkObjects(const LLSD& notification, const LLSD& res // triangle count cannot exceed the designated limit. bool LLSelectMgr::enableLinkObjects() { - bool new_value = false; - // check if there are at least 2 objects selected, and that the - // user can modify at least one of the selected objects. - - // in component mode, can't link - if (!gSavedSettings.getBOOL("EditLinkedParts")) - { - if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit(); - return object->permModify() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()); - } - } func; - const bool firstonly = true; - new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); - } - } + bool new_value = false; + // check if there are at least 2 objects selected, and that the + // user can modify at least one of the selected objects. + + // in component mode, can't link + if (!gSavedSettings.getBOOL("EditLinkedParts")) + { + if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit(); + return object->permModify() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()); + } + } func; + const bool firstonly = true; + new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); + } + } if (!LLSelectMgr::getInstance()->getSelection()->checkAnimatedObjectLinkable()) { new_value = false; } - return new_value; + return new_value; } bool LLSelectMgr::enableUnlinkObjects() { - LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject(); - LLViewerObject *root_object = (first_editable_object == NULL) ? NULL : first_editable_object->getRootEdit(); + LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject(); + LLViewerObject *root_object = (first_editable_object == NULL) ? NULL : first_editable_object->getRootEdit(); - bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() && - first_editable_object && - !first_editable_object->isAttachment() && !first_editable_object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()); + bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() && + first_editable_object && + !first_editable_object->isAttachment() && !first_editable_object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()); - return new_value; + return new_value; } void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object) { - // bail if nothing selected or if object wasn't selected in the first place - if(!object) return; - if(!object->isSelected()) return; - - // Collect all of the objects, and remove them - std::vector objects; - - if (include_entire_object) - { - // Since we're selecting a family, start at the root, but - // don't include an avatar. - LLViewerObject* root = object; - - while(!root->isAvatar() && root->getParent()) - { - LLViewerObject* parent = (LLViewerObject*)root->getParent(); - if (parent->isAvatar()) - { - break; - } - root = parent; - } - - object = root; - } - else - { - object = (LLViewerObject*)object->getRoot(); - } - - object->addThisAndAllChildren(objects); - remove(objects); - - if (!send_to_sim) return; - - //----------------------------------------------------------- - // Inform simulator of deselection - //----------------------------------------------------------- - LLViewerRegion* regionp = object->getRegion(); - - BOOL start_new_message = TRUE; - S32 select_count = 0; - - LLMessageSystem* msg = gMessageSystem; - for (U32 i = 0; i < objects.size(); i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_ObjectDeselect); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - select_count++; - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID()); - select_count++; - - // Zap the angular velocity, as the sim will set it to zero - objects[i]->setAngularVelocity( 0,0,0 ); - objects[i]->setVelocity( 0,0,0 ); - - if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET) - { - msg->sendReliable(regionp->getHost() ); - select_count = 0; - start_new_message = TRUE; - } - } - - if (!start_new_message) - { - msg->sendReliable(regionp->getHost() ); - } - - updatePointAt(); - updateSelectionCenter(); + // bail if nothing selected or if object wasn't selected in the first place + if(!object) return; + if(!object->isSelected()) return; + + // Collect all of the objects, and remove them + std::vector objects; + + if (include_entire_object) + { + // Since we're selecting a family, start at the root, but + // don't include an avatar. + LLViewerObject* root = object; + + while(!root->isAvatar() && root->getParent()) + { + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) + { + break; + } + root = parent; + } + + object = root; + } + else + { + object = (LLViewerObject*)object->getRoot(); + } + + object->addThisAndAllChildren(objects); + remove(objects); + + if (!send_to_sim) return; + + //----------------------------------------------------------- + // Inform simulator of deselection + //----------------------------------------------------------- + LLViewerRegion* regionp = object->getRegion(); + + BOOL start_new_message = TRUE; + S32 select_count = 0; + + LLMessageSystem* msg = gMessageSystem; + for (U32 i = 0; i < objects.size(); i++) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_ObjectDeselect); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + select_count++; + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, (objects[i])->getLocalID()); + select_count++; + + // Zap the angular velocity, as the sim will set it to zero + objects[i]->setAngularVelocity( 0,0,0 ); + objects[i]->setVelocity( 0,0,0 ); + + if(msg->isSendFull(NULL) || select_count >= MAX_OBJECTS_PER_PACKET) + { + msg->sendReliable(regionp->getHost() ); + select_count = 0; + start_new_message = TRUE; + } + } + + if (!start_new_message) + { + msg->sendReliable(regionp->getHost() ); + } + + updatePointAt(); + updateSelectionCenter(); } void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim) { - // bail if nothing selected or if object wasn't selected in the first place - if (!object) return; - if (!object->isSelected() ) return; + // bail if nothing selected or if object wasn't selected in the first place + if (!object) return; + if (!object->isSelected() ) return; - // Zap the angular velocity, as the sim will set it to zero - object->setAngularVelocity( 0,0,0 ); - object->setVelocity( 0,0,0 ); + // Zap the angular velocity, as the sim will set it to zero + object->setAngularVelocity( 0,0,0 ); + object->setVelocity( 0,0,0 ); - if (send_to_sim) - { - LLViewerRegion* region = object->getRegion(); - gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->sendReliable(region->getHost()); - } + if (send_to_sim) + { + LLViewerRegion* region = object->getRegion(); + gMessageSystem->newMessageFast(_PREHASH_ObjectDeselect); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->sendReliable(region->getHost()); + } - // This will refresh dialogs. - remove( object ); + // This will refresh dialogs. + remove( object ); - updatePointAt(); - updateSelectionCenter(); + updatePointAt(); + updateSelectionCenter(); } @@ -981,53 +981,53 @@ void LLSelectMgr::deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim) void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to_end) { - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - - // Can't select yourself - if (objectp->mID == gAgentID - && !mAllowSelectAvatar) - { - continue; - } - - if (!objectp->isSelected()) - { - LLSelectNode *nodep = new LLSelectNode(objectp, TRUE); - if (add_to_end) - { - mSelectedObjects->addNodeAtEnd(nodep); - } - else - { - mSelectedObjects->addNode(nodep); - } - objectp->setSelected(TRUE); - - if (objectp->getNumTEs() > 0) - { - nodep->selectAllTEs(TRUE); - objectp->setAllTESelected(true); - } - else - { - // object has no faces, so don't mess with faces - } - } - else - { - // we want this object to be selected for real - // so clear transient flag - LLSelectNode* select_node = mSelectedObjects->findNode(objectp); - if (select_node) - { - select_node->setTransient(FALSE); - } - } - } - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + + // Can't select yourself + if (objectp->mID == gAgentID + && !mAllowSelectAvatar) + { + continue; + } + + if (!objectp->isSelected()) + { + LLSelectNode *nodep = new LLSelectNode(objectp, TRUE); + if (add_to_end) + { + mSelectedObjects->addNodeAtEnd(nodep); + } + else + { + mSelectedObjects->addNode(nodep); + } + objectp->setSelected(TRUE); + + if (objectp->getNumTEs() > 0) + { + nodep->selectAllTEs(TRUE); + objectp->setAllTESelected(true); + } + else + { + // object has no faces, so don't mess with faces + } + } + else + { + // we want this object to be selected for real + // so clear transient flag + LLSelectNode* select_node = mSelectedObjects->findNode(objectp); + if (select_node) + { + select_node->setTransient(FALSE); + } + } + } + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); } //----------------------------------------------------------------------------- @@ -1035,454 +1035,454 @@ void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to //----------------------------------------------------------------------------- void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable, S32 gltf_node, S32 gltf_primitive) { - // check to see if object is already in list - LLSelectNode *nodep = mSelectedObjects->findNode(objectp); - - // if not in list, add it - if (!nodep) - { - nodep = new LLSelectNode(objectp, TRUE); - mSelectedObjects->addNode(nodep); - llassert_always(nodep->getObject()); - } - else - { - // make this a full-fledged selection - nodep->setTransient(FALSE); - // Move it to the front of the list - mSelectedObjects->moveNodeToFront(nodep); - } - - // Make sure the object is tagged as selected - objectp->setSelected( TRUE ); - - // And make sure we don't consider it as part of a family - nodep->mIndividualSelection = TRUE; - - // Handle face selection - if (objectp->getNumTEs() <= 0) - { - // object has no faces, so don't do anything - } - else if (face == SELECT_ALL_TES) - { - nodep->selectAllTEs(TRUE); - objectp->setAllTESelected(true); - } - else if (0 <= face && face < SELECT_MAX_TES) - { - nodep->selectTE(face, TRUE); - objectp->setTESelected(face, true); - } - else - { - LL_ERRS() << "LLSelectMgr::add face " << face << " out-of-range" << LL_ENDL; - return; - } + // check to see if object is already in list + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); + + // if not in list, add it + if (!nodep) + { + nodep = new LLSelectNode(objectp, TRUE); + mSelectedObjects->addNode(nodep); + llassert_always(nodep->getObject()); + } + else + { + // make this a full-fledged selection + nodep->setTransient(FALSE); + // Move it to the front of the list + mSelectedObjects->moveNodeToFront(nodep); + } + + // Make sure the object is tagged as selected + objectp->setSelected( TRUE ); + + // And make sure we don't consider it as part of a family + nodep->mIndividualSelection = TRUE; + + // Handle face selection + if (objectp->getNumTEs() <= 0) + { + // object has no faces, so don't do anything + } + else if (face == SELECT_ALL_TES) + { + nodep->selectAllTEs(TRUE); + objectp->setAllTESelected(true); + } + else if (0 <= face && face < SELECT_MAX_TES) + { + nodep->selectTE(face, TRUE); + objectp->setTESelected(face, true); + } + else + { + LL_ERRS() << "LLSelectMgr::add face " << face << " out-of-range" << LL_ENDL; + return; + } // Handle glTF node selection if (gltf_node >= 0) { nodep->selectGLTFNode(gltf_node, gltf_primitive, TRUE); - + } - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updateSelectionCenter(); - dialog_refresh_all(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updateSelectionCenter(); + dialog_refresh_all(); } LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 face) { - if (!objectp) - { - mHoverObjects->deleteAllNodes(); - return NULL; - } - - // Can't select yourself - if (objectp->mID == gAgentID) - { - mHoverObjects->deleteAllNodes(); - return NULL; - } - - // Can't select land - if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) - { - mHoverObjects->deleteAllNodes(); - return NULL; - } - - mHoverObjects->mPrimaryObject = objectp; - - objectp = objectp->getRootEdit(); - - // is the requested object the same as the existing hover object root? - // NOTE: there is only ever one linked set in mHoverObjects - if (mHoverObjects->getFirstRootObject() != objectp) - { - - // Collect all of the objects - std::vector objects; - objectp = objectp->getRootEdit(); - objectp->addThisAndNonJointChildren(objects); - - mHoverObjects->deleteAllNodes(); - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* cur_objectp = *iter; - if(!cur_objectp || cur_objectp->isDead()) - { - continue; - } - LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); - nodep->selectTE(face, TRUE); - mHoverObjects->addNodeAtEnd(nodep); - } - - requestObjectPropertiesFamily(objectp); - } - - return mHoverObjects; + if (!objectp) + { + mHoverObjects->deleteAllNodes(); + return NULL; + } + + // Can't select yourself + if (objectp->mID == gAgentID) + { + mHoverObjects->deleteAllNodes(); + return NULL; + } + + // Can't select land + if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) + { + mHoverObjects->deleteAllNodes(); + return NULL; + } + + mHoverObjects->mPrimaryObject = objectp; + + objectp = objectp->getRootEdit(); + + // is the requested object the same as the existing hover object root? + // NOTE: there is only ever one linked set in mHoverObjects + if (mHoverObjects->getFirstRootObject() != objectp) + { + + // Collect all of the objects + std::vector objects; + objectp = objectp->getRootEdit(); + objectp->addThisAndNonJointChildren(objects); + + mHoverObjects->deleteAllNodes(); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* cur_objectp = *iter; + if(!cur_objectp || cur_objectp->isDead()) + { + continue; + } + LLSelectNode* nodep = new LLSelectNode(cur_objectp, FALSE); + nodep->selectTE(face, TRUE); + mHoverObjects->addNodeAtEnd(nodep); + } + + requestObjectPropertiesFamily(objectp); + } + + return mHoverObjects; } LLSelectNode *LLSelectMgr::getHoverNode() { - return mHoverObjects->getFirstRootNode(); + return mHoverObjects->getFirstRootNode(); } LLSelectNode *LLSelectMgr::getPrimaryHoverNode() { - return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject]; + return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject]; } void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) { - if (!objectp) - { - return; - } + if (!objectp) + { + return; + } + + if (objectp->getPCode() != LL_PCODE_VOLUME) + { + return; + } - if (objectp->getPCode() != LL_PCODE_VOLUME) - { - return; - } - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced()))) - { - // only select my own objects - return; - } + { + // only select my own objects + return; + } - mRectSelectedObjects.insert(objectp); + mRectSelectedObjects.insert(objectp); } void LLSelectMgr::highlightObjectAndFamily(LLViewerObject* objectp) { - if (!objectp) - { - return; - } + if (!objectp) + { + return; + } - LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); + LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); - highlightObjectOnly(root_obj); + highlightObjectOnly(root_obj); - LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - highlightObjectOnly(child); - } + LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + highlightObjectOnly(child); + } } // Note that this ignores the "select owned only" flag // It's also more efficient than calling the single-object version over and over. void LLSelectMgr::highlightObjectAndFamily(const std::vector& objects) { - for (std::vector::const_iterator iter1 = objects.begin(); - iter1 != objects.end(); ++iter1) - { - LLViewerObject* object = *iter1; - - if (!object) - { - continue; - } - if (object->getPCode() != LL_PCODE_VOLUME) - { - continue; - } - - LLViewerObject* root = (LLViewerObject*)object->getRoot(); - mRectSelectedObjects.insert(root); - - LLViewerObject::const_child_list_t& child_list = root->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter2 = child_list.begin(); - iter2 != child_list.end(); iter2++) - { - LLViewerObject* child = *iter2; - mRectSelectedObjects.insert(child); - } - } + for (std::vector::const_iterator iter1 = objects.begin(); + iter1 != objects.end(); ++iter1) + { + LLViewerObject* object = *iter1; + + if (!object) + { + continue; + } + if (object->getPCode() != LL_PCODE_VOLUME) + { + continue; + } + + LLViewerObject* root = (LLViewerObject*)object->getRoot(); + mRectSelectedObjects.insert(root); + + LLViewerObject::const_child_list_t& child_list = root->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter2 = child_list.begin(); + iter2 != child_list.end(); iter2++) + { + LLViewerObject* child = *iter2; + mRectSelectedObjects.insert(child); + } + } } void LLSelectMgr::unhighlightObjectOnly(LLViewerObject* objectp) { - if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) - { - return; - } + if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) + { + return; + } - mRectSelectedObjects.erase(objectp); + mRectSelectedObjects.erase(objectp); } void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp) { - if (!objectp) - { - return; - } + if (!objectp) + { + return; + } - LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); + LLViewerObject* root_obj = (LLViewerObject*)objectp->getRoot(); - unhighlightObjectOnly(root_obj); + unhighlightObjectOnly(root_obj); - LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - unhighlightObjectOnly(child); - } + LLViewerObject::const_child_list_t& child_list = root_obj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + unhighlightObjectOnly(child); + } } void LLSelectMgr::unhighlightAll() { - mRectSelectedObjects.clear(); - mHighlightedObjects->deleteAllNodes(); + mRectSelectedObjects.clear(); + mHighlightedObjects->deleteAllNodes(); } LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects() { - if (!mHighlightedObjects->getNumNodes()) - { - return NULL; - } + if (!mHighlightedObjects->getNumNodes()) + { + return NULL; + } + + //clear primary object + mSelectedObjects->mPrimaryObject = NULL; - //clear primary object - mSelectedObjects->mPrimaryObject = NULL; + for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin(); + iter != getHighlightedObjects()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; - for (LLObjectSelection::iterator iter = getHighlightedObjects()->begin(); - iter != getHighlightedObjects()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - - LLSelectNode *nodep = *curiter; - LLViewerObject* objectp = nodep->getObject(); + LLSelectNode *nodep = *curiter; + LLViewerObject* objectp = nodep->getObject(); - if (!canSelectObject(objectp)) - { - continue; - } + if (!canSelectObject(objectp)) + { + continue; + } - // already selected - if (objectp->isSelected()) - { - continue; - } + // already selected + if (objectp->isSelected()) + { + continue; + } - LLSelectNode* new_nodep = new LLSelectNode(*nodep); - mSelectedObjects->addNode(new_nodep); + LLSelectNode* new_nodep = new LLSelectNode(*nodep); + mSelectedObjects->addNode(new_nodep); - // flag this object as selected - objectp->setSelected(TRUE); - objectp->setAllTESelected(true); + // flag this object as selected + objectp->setSelected(TRUE); + objectp->setAllTESelected(true); - mSelectedObjects->mSelectType = getSelectTypeForObject(objectp); + mSelectedObjects->mSelectType = getSelectTypeForObject(objectp); - // request properties on root objects - if (objectp->isRootEdit()) - { - requestObjectPropertiesFamily(objectp); - } - } + // request properties on root objects + if (objectp->isRootEdit()) + { + requestObjectPropertiesFamily(objectp); + } + } - // pack up messages to let sim know these objects are selected - sendSelect(); - unhighlightAll(); - updateSelectionCenter(); - saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - updatePointAt(); + // pack up messages to let sim know these objects are selected + sendSelect(); + unhighlightAll(); + updateSelectionCenter(); + saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + updatePointAt(); - if (mSelectedObjects->getObjectCount()) - { - gEditMenuHandler = this; - } + if (mSelectedObjects->getObjectCount()) + { + gEditMenuHandler = this; + } - return mSelectedObjects; + return mSelectedObjects; } void LLSelectMgr::deselectHighlightedObjects() { - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - for (std::set >::iterator iter = mRectSelectedObjects.begin(); - iter != mRectSelectedObjects.end(); iter++) - { - LLViewerObject *objectp = *iter; - if (!select_linked_set) - { - deselectObjectOnly(objectp); - } - else - { - LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot(); - if (root_object->isSelected()) - { - deselectObjectAndFamily(root_object); - } - } - } - - unhighlightAll(); + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + for (std::set >::iterator iter = mRectSelectedObjects.begin(); + iter != mRectSelectedObjects.end(); iter++) + { + LLViewerObject *objectp = *iter; + if (!select_linked_set) + { + deselectObjectOnly(objectp); + } + else + { + LLViewerObject* root_object = (LLViewerObject*)objectp->getRoot(); + if (root_object->isSelected()) + { + deselectObjectAndFamily(root_object); + } + } + } + + unhighlightAll(); } void LLSelectMgr::addGridObject(LLViewerObject* objectp) { - LLSelectNode* nodep = new LLSelectNode(objectp, FALSE); - mGridObjects.addNodeAtEnd(nodep); + LLSelectNode* nodep = new LLSelectNode(objectp, FALSE); + mGridObjects.addNodeAtEnd(nodep); - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - nodep = new LLSelectNode(child, FALSE); - mGridObjects.addNodeAtEnd(nodep); - } + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + nodep = new LLSelectNode(child, FALSE); + mGridObjects.addNodeAtEnd(nodep); + } } void LLSelectMgr::clearGridObjects() { - mGridObjects.deleteAllNodes(); + mGridObjects.deleteAllNodes(); } void LLSelectMgr::setGridMode(EGridMode mode) { - mGridMode = mode; - gSavedSettings.setS32("GridMode", mode); - updateSelectionCenter(); + mGridMode = mode; + gSavedSettings.setS32("GridMode", mode); + updateSelectionCenter(); } void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &scale, bool for_snap_guides) { - mGridObjects.cleanupNodes(); - - LLViewerObject* first_grid_object = mGridObjects.getFirstObject(); - - if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) - { - //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject()); - mGridOrigin = mSavedSelectionBBox.getCenterAgent(); - mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f; - - // DEV-12570 Just taking the saved selection box rotation prevents - // wild rotations of linked sets while in local grid mode - //if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull()) - { - mGridRotation = mSavedSelectionBBox.getRotation(); - } - /*else //set to the root object - { - mGridRotation = root->getRenderRotation(); - }*/ - } - else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull()) - { - LLSelectNode *node = mSelectedObjects->findNode(first_grid_object); - if (!for_snap_guides && node) - { - mGridRotation = node->mSavedRotation; - } - else - { - mGridRotation = first_grid_object->getRenderRotation(); - } - - LLVector4a min_extents(F32_MAX); - LLVector4a max_extents(-F32_MAX); - BOOL grid_changed = FALSE; - for (LLObjectSelection::iterator iter = mGridObjects.begin(); - iter != mGridObjects.end(); ++iter) - { - LLViewerObject* object = (*iter)->getObject(); - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - const LLVector4a* ext = drawable->getSpatialExtents(); - update_min_max(min_extents, max_extents, ext[0]); - update_min_max(min_extents, max_extents, ext[1]); - grid_changed = TRUE; - } - } - if (grid_changed) - { - LLVector4a center, size; - center.setAdd(min_extents, max_extents); - center.mul(0.5f); - size.setSub(max_extents, min_extents); - size.mul(0.5f); - - mGridOrigin.set(center.getF32ptr()); - LLDrawable* drawable = first_grid_object->mDrawable; - if (drawable && drawable->isActive()) - { - mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); - } - mGridScale.set(size.getF32ptr()); - } - } - else // GRID_MODE_WORLD or just plain default - { - const BOOL non_root_ok = TRUE; - LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok); - - mGridOrigin.clearVec(); - mGridRotation.loadIdentity(); - - mSelectedObjects->mSelectType = getSelectTypeForObject( first_object ); - - switch (mSelectedObjects->mSelectType) - { - case SELECT_TYPE_ATTACHMENT: - if (first_object && first_object->getRootEdit()->mDrawable.notNull()) - { - // this means this object *has* to be an attachment - LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent(); - mGridOrigin = attachment_point_xform->getWorldPosition(); - mGridRotation = attachment_point_xform->getWorldRotation(); - mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); - } - break; - case SELECT_TYPE_HUD: - mGridScale = LLVector3(1.f, 1.f, 1.f) * llmin(gSavedSettings.getF32("GridResolution"), 0.5f); - break; - case SELECT_TYPE_WORLD: - mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); - break; - } - } - llassert(mGridOrigin.isFinite()); - - origin = mGridOrigin; - rotation = mGridRotation; - scale = mGridScale; + mGridObjects.cleanupNodes(); + + LLViewerObject* first_grid_object = mGridObjects.getFirstObject(); + + if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) + { + //LLViewerObject* root = getSelectedParentObject(mSelectedObjects->getFirstObject()); + mGridOrigin = mSavedSelectionBBox.getCenterAgent(); + mGridScale = mSavedSelectionBBox.getExtentLocal() * 0.5f; + + // DEV-12570 Just taking the saved selection box rotation prevents + // wild rotations of linked sets while in local grid mode + //if(mSelectedObjects->getObjectCount() < 2 || !root || root->mDrawable.isNull()) + { + mGridRotation = mSavedSelectionBBox.getRotation(); + } + /*else //set to the root object + { + mGridRotation = root->getRenderRotation(); + }*/ + } + else if (mGridMode == GRID_MODE_REF_OBJECT && first_grid_object && first_grid_object->mDrawable.notNull()) + { + LLSelectNode *node = mSelectedObjects->findNode(first_grid_object); + if (!for_snap_guides && node) + { + mGridRotation = node->mSavedRotation; + } + else + { + mGridRotation = first_grid_object->getRenderRotation(); + } + + LLVector4a min_extents(F32_MAX); + LLVector4a max_extents(-F32_MAX); + BOOL grid_changed = FALSE; + for (LLObjectSelection::iterator iter = mGridObjects.begin(); + iter != mGridObjects.end(); ++iter) + { + LLViewerObject* object = (*iter)->getObject(); + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + const LLVector4a* ext = drawable->getSpatialExtents(); + update_min_max(min_extents, max_extents, ext[0]); + update_min_max(min_extents, max_extents, ext[1]); + grid_changed = TRUE; + } + } + if (grid_changed) + { + LLVector4a center, size; + center.setAdd(min_extents, max_extents); + center.mul(0.5f); + size.setSub(max_extents, min_extents); + size.mul(0.5f); + + mGridOrigin.set(center.getF32ptr()); + LLDrawable* drawable = first_grid_object->mDrawable; + if (drawable && drawable->isActive()) + { + mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); + } + mGridScale.set(size.getF32ptr()); + } + } + else // GRID_MODE_WORLD or just plain default + { + const BOOL non_root_ok = TRUE; + LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(non_root_ok); + + mGridOrigin.clearVec(); + mGridRotation.loadIdentity(); + + mSelectedObjects->mSelectType = getSelectTypeForObject( first_object ); + + switch (mSelectedObjects->mSelectType) + { + case SELECT_TYPE_ATTACHMENT: + if (first_object && first_object->getRootEdit()->mDrawable.notNull()) + { + // this means this object *has* to be an attachment + LLXform* attachment_point_xform = first_object->getRootEdit()->mDrawable->mXform.getParent(); + mGridOrigin = attachment_point_xform->getWorldPosition(); + mGridRotation = attachment_point_xform->getWorldRotation(); + mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); + } + break; + case SELECT_TYPE_HUD: + mGridScale = LLVector3(1.f, 1.f, 1.f) * llmin(gSavedSettings.getF32("GridResolution"), 0.5f); + break; + case SELECT_TYPE_WORLD: + mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution"); + break; + } + } + llassert(mGridOrigin.isFinite()); + + origin = mGridOrigin; + rotation = mGridRotation; + scale = mGridScale; } //----------------------------------------------------------------------------- @@ -1491,20 +1491,20 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & void LLSelectMgr::remove(std::vector& objects) { - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - LLSelectNode* nodep = mSelectedObjects->findNode(objectp); - if (nodep) - { - objectp->setSelected(FALSE); - mSelectedObjects->removeNode(nodep); - nodep = NULL; - } - } - updateSelectionCenter(); - dialog_refresh_all(); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + LLSelectNode* nodep = mSelectedObjects->findNode(objectp); + if (nodep) + { + objectp->setSelected(FALSE); + mSelectedObjects->removeNode(nodep); + nodep = NULL; + } + } + updateSelectionCenter(); + dialog_refresh_all(); } @@ -1513,59 +1513,59 @@ void LLSelectMgr::remove(std::vector& objects) //----------------------------------------------------------------------------- void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) { - // get object node (and verify it is in the selected list) - LLSelectNode *nodep = mSelectedObjects->findNode(objectp); - if (!nodep) - { - return; - } - - // if face = all, remove object from list - if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES)) - { - // Remove all faces (or the object doesn't have faces) so remove the node - mSelectedObjects->removeNode(nodep); - nodep = NULL; - objectp->setSelected( FALSE ); - } - else if (0 <= te && te < SELECT_MAX_TES) - { - // ...valid face, check to see if it was on - if (nodep->isTESelected(te)) - { - nodep->selectTE(te, FALSE); - objectp->setTESelected(te, false); - } - else - { - LL_ERRS() << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << LL_ENDL; - return; - } - - // ...check to see if this operation turned off all faces - BOOL found = FALSE; - for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++) - { - found = found || nodep->isTESelected(i); - } - - // ...all faces now turned off, so remove - if (!found) - { - mSelectedObjects->removeNode(nodep); - nodep = NULL; - objectp->setSelected( FALSE ); - // *FIXME: Doesn't update simulator that object is no longer selected - } - } - else - { - // ...out of range face - LL_ERRS() << "LLSelectMgr::remove - TE " << te << " out of range" << LL_ENDL; - } - - updateSelectionCenter(); - dialog_refresh_all(); + // get object node (and verify it is in the selected list) + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); + if (!nodep) + { + return; + } + + // if face = all, remove object from list + if ((objectp->getNumTEs() <= 0) || (te == SELECT_ALL_TES)) + { + // Remove all faces (or the object doesn't have faces) so remove the node + mSelectedObjects->removeNode(nodep); + nodep = NULL; + objectp->setSelected( FALSE ); + } + else if (0 <= te && te < SELECT_MAX_TES) + { + // ...valid face, check to see if it was on + if (nodep->isTESelected(te)) + { + nodep->selectTE(te, FALSE); + objectp->setTESelected(te, false); + } + else + { + LL_ERRS() << "LLSelectMgr::remove - tried to remove TE " << te << " that wasn't selected" << LL_ENDL; + return; + } + + // ...check to see if this operation turned off all faces + BOOL found = FALSE; + for (S32 i = 0; i < nodep->getObject()->getNumTEs(); i++) + { + found = found || nodep->isTESelected(i); + } + + // ...all faces now turned off, so remove + if (!found) + { + mSelectedObjects->removeNode(nodep); + nodep = NULL; + objectp->setSelected( FALSE ); + // *FIXME: Doesn't update simulator that object is no longer selected + } + } + else + { + // ...out of range face + LL_ERRS() << "LLSelectMgr::remove - TE " << te << " out of range" << LL_ENDL; + } + + updateSelectionCenter(); + dialog_refresh_all(); } @@ -1574,17 +1574,17 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) //----------------------------------------------------------------------------- void LLSelectMgr::removeAll() { - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setSelected( FALSE ); - } + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setSelected( FALSE ); + } - mSelectedObjects->deleteAllNodes(); - - updateSelectionCenter(); - dialog_refresh_all(); + mSelectedObjects->deleteAllNodes(); + + updateSelectionCenter(); + dialog_refresh_all(); } //----------------------------------------------------------------------------- @@ -1592,41 +1592,41 @@ void LLSelectMgr::removeAll() //----------------------------------------------------------------------------- void LLSelectMgr::promoteSelectionToRoot() { - std::set selection_set; + std::set selection_set; + + BOOL selection_changed = FALSE; - BOOL selection_changed = FALSE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ) + { + LLObjectSelection::iterator curiter = iter++; + LLSelectNode* nodep = *curiter; + LLViewerObject* object = nodep->getObject(); - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ) - { - LLObjectSelection::iterator curiter = iter++; - LLSelectNode* nodep = *curiter; - LLViewerObject* object = nodep->getObject(); + if (nodep->mIndividualSelection) + { + selection_changed = TRUE; + } - if (nodep->mIndividualSelection) - { - selection_changed = TRUE; - } + LLViewerObject* parentp = object; + while(parentp->getParent() && !(parentp->isRootEdit())) + { + parentp = (LLViewerObject*)parentp->getParent(); + } - LLViewerObject* parentp = object; - while(parentp->getParent() && !(parentp->isRootEdit())) - { - parentp = (LLViewerObject*)parentp->getParent(); - } - - selection_set.insert(parentp); - } + selection_set.insert(parentp); + } - if (selection_changed) - { - deselectAll(); + if (selection_changed) + { + deselectAll(); - std::set::iterator set_iter; - for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter) - { - selectObjectAndFamily(*set_iter); - } - } + std::set::iterator set_iter; + for (set_iter = selection_set.begin(); set_iter != selection_set.end(); ++set_iter) + { + selectObjectAndFamily(*set_iter); + } + } } //----------------------------------------------------------------------------- @@ -1634,25 +1634,25 @@ void LLSelectMgr::promoteSelectionToRoot() //----------------------------------------------------------------------------- void LLSelectMgr::demoteSelectionToIndividuals() { - std::vector objects; + std::vector objects; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLViewerObject* object = (*iter)->getObject(); - object->addThisAndNonJointChildren(objects); - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLViewerObject* object = (*iter)->getObject(); + object->addThisAndNonJointChildren(objects); + } - if (!objects.empty()) - { - deselectAll(); - for (std::vector::iterator iter = objects.begin(); - iter != objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - selectObjectOnly(objectp); - } - } + if (!objects.empty()) + { + deselectAll(); + for (std::vector::iterator iter = objects.begin(); + iter != objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + selectObjectOnly(objectp); + } + } } //----------------------------------------------------------------------------- @@ -1660,49 +1660,49 @@ void LLSelectMgr::demoteSelectionToIndividuals() //----------------------------------------------------------------------------- void LLSelectMgr::dump() { - LL_INFOS() << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << LL_ENDL; - - LL_INFOS() << "TE mode " << mTEMode << LL_ENDL; - - S32 count = 0; - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLViewerObject* objectp = (*iter)->getObject(); - LL_INFOS() << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << LL_ENDL; - LL_INFOS() << " hasLSL " << objectp->flagScripted() << LL_ENDL; - LL_INFOS() << " hasTouch " << objectp->flagHandleTouch() << LL_ENDL; - LL_INFOS() << " hasMoney " << objectp->flagTakesMoney() << LL_ENDL; - LL_INFOS() << " getposition " << objectp->getPosition() << LL_ENDL; - LL_INFOS() << " getpositionAgent " << objectp->getPositionAgent() << LL_ENDL; - LL_INFOS() << " getpositionRegion " << objectp->getPositionRegion() << LL_ENDL; - LL_INFOS() << " getpositionGlobal " << objectp->getPositionGlobal() << LL_ENDL; - LLDrawable* drawablep = objectp->mDrawable; - LL_INFOS() << " " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << LL_ENDL; - LL_INFOS() << " " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << LL_ENDL; - count++; - } - - // Face iterator - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - for (S32 te = 0; te < objectp->getNumTEs(); ++te ) - { - if (node->isTESelected(te)) - { - LL_INFOS() << "Object " << objectp << " te " << te << LL_ENDL; - } - } - } - - LL_INFOS() << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << LL_ENDL; - - LL_INFOS() << "Center global " << mSelectionCenterGlobal << LL_ENDL; + LL_INFOS() << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << LL_ENDL; + + LL_INFOS() << "TE mode " << mTEMode << LL_ENDL; + + S32 count = 0; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLViewerObject* objectp = (*iter)->getObject(); + LL_INFOS() << "Object " << count << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << LL_ENDL; + LL_INFOS() << " hasLSL " << objectp->flagScripted() << LL_ENDL; + LL_INFOS() << " hasTouch " << objectp->flagHandleTouch() << LL_ENDL; + LL_INFOS() << " hasMoney " << objectp->flagTakesMoney() << LL_ENDL; + LL_INFOS() << " getposition " << objectp->getPosition() << LL_ENDL; + LL_INFOS() << " getpositionAgent " << objectp->getPositionAgent() << LL_ENDL; + LL_INFOS() << " getpositionRegion " << objectp->getPositionRegion() << LL_ENDL; + LL_INFOS() << " getpositionGlobal " << objectp->getPositionGlobal() << LL_ENDL; + LLDrawable* drawablep = objectp->mDrawable; + LL_INFOS() << " " << (drawablep&& drawablep->isVisible() ? "visible" : "invisible") << LL_ENDL; + LL_INFOS() << " " << (drawablep&& drawablep->isState(LLDrawable::FORCE_INVISIBLE) ? "force_invisible" : "") << LL_ENDL; + count++; + } + + // Face iterator + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + for (S32 te = 0; te < objectp->getNumTEs(); ++te ) + { + if (node->isTESelected(te)) + { + LL_INFOS() << "Object " << objectp << " te " << te << LL_ENDL; + } + } + } + + LL_INFOS() << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << LL_ENDL; + + LL_INFOS() << "Center global " << mSelectionCenterGlobal << LL_ENDL; } //----------------------------------------------------------------------------- @@ -1710,7 +1710,7 @@ void LLSelectMgr::dump() //----------------------------------------------------------------------------- void LLSelectMgr::cleanup() { - mSilhouetteImagep = NULL; + mSilhouetteImagep = NULL; } @@ -1720,54 +1720,54 @@ void LLSelectMgr::cleanup() struct LLSelectMgrSendFunctor : public LLSelectedObjectFunctor { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } }; void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) { - if (!item) - { - return; - } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID()); - - for (iterator iter = begin(); iter != end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = (*iter)->getObject(); - if (!object) - { - continue; - } - - S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); - bool texture_copied = false; + if (!item) + { + return; + } + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(item->getAssetUUID()); + + for (iterator iter = begin(); iter != end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = (*iter)->getObject(); + if (!object) + { + continue; + } + + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); + bool texture_copied = false; bool updated = false; - for (S32 te = 0; te < num_tes; ++te) - { - if (node->isTESelected(te)) - { - //(no-copy) textures must be moved to the object's inventory only once - // without making any copies - if (!texture_copied) - { - LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); - texture_copied = true; - } - - // apply texture for the selected faces - add(LLStatViewer::EDIT_TEXTURE, 1); - object->setTEImage(te, image); + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + //(no-copy) textures must be moved to the object's inventory only once + // without making any copies + if (!texture_copied) + { + LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); + texture_copied = true; + } + + // apply texture for the selected faces + add(LLStatViewer::EDIT_TEXTURE, 1); + object->setTEImage(te, image); updated = true; - } - } + } + } if (updated) // not nessesary? sendTEUpdate update supposed to be done by sendfunc { @@ -1776,7 +1776,7 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) // send the update to the simulator object->sendTEUpdate(); } - } + } } bool LLObjectSelection::applyRestrictedPbrMaterialToTEs(LLViewerInventoryItem* item) @@ -1818,7 +1818,7 @@ bool LLObjectSelection::applyRestrictedPbrMaterialToTEs(LLViewerInventoryItem* i if (!material_copied) { // Applying the material is not possible for this object given the current inventory - material_copied_all_faces = false; + material_copied_all_faces = false; break; } @@ -1842,30 +1842,30 @@ bool LLObjectSelection::applyRestrictedPbrMaterialToTEs(LLViewerInventoryItem* i // *TODO: re-arch texture applying out of lltooldraganddrop bool LLSelectMgr::selectionSetImage(const LLUUID& imageid) { - // First for (no copy) textures and multiple object selection - LLViewerInventoryItem* item = gInventory.getItem(imageid); - if(item - && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) - && (mSelectedObjects->getNumNodes() > 1) ) - { + // First for (no copy) textures and multiple object selection + LLViewerInventoryItem* item = gInventory.getItem(imageid); + if(item + && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) + && (mSelectedObjects->getNumNodes() > 1) ) + { LL_DEBUGS() << "Attempted to apply no-copy texture " << imageid << " to multiple objects" << LL_ENDL; LLNotificationsUtil::add("FailedToApplyTextureNoCopyToMultiple"); return false; - } - - struct f : public LLSelectedTEFunctor - { - LLViewerInventoryItem* mItem; - LLUUID mImageID; - f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} - bool apply(LLViewerObject* objectp, S32 te) - { - if(!objectp || !objectp->permModify()) - { - return false; - } + } + + struct f : public LLSelectedTEFunctor + { + LLViewerInventoryItem* mItem; + LLUUID mImageID; + f(LLViewerInventoryItem* item, const LLUUID& id) : mItem(item), mImageID(id) {} + bool apply(LLViewerObject* objectp, S32 te) + { + if(!objectp || !objectp->permModify()) + { + return false; + } // Might be better to run willObjectAcceptInventory if (mItem && objectp->isAttachment()) @@ -1880,58 +1880,58 @@ bool LLSelectMgr::selectionSetImage(const LLUUID& imageid) } } - if (mItem) - { + if (mItem) + { LLToolDragAndDrop::dropTextureOneFace(objectp, te, mItem, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null, false); - } - else // not an inventory item - { - // Texture picker defaults aren't inventory items - // * Don't need to worry about permissions for them - // * Can just apply the texture and be done with it. - objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); - } - - return true; - } - }; - - if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) - { - getSelection()->applyNoCopyTextureToTEs(item); - } - else - { - f setfunc(item, imageid); - getSelection()->applyToTEs(&setfunc); - } - - - struct g : public LLSelectedObjectFunctor - { - LLViewerInventoryItem* mItem; - g(LLViewerInventoryItem* item) : mItem(item) {} - virtual bool apply(LLViewerObject* object) - { - if (!mItem) - { - object->sendTEUpdate(); - // 1 particle effect per object - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgentAvatarp); - effectp->setTargetObject(object); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - } - return true; - } - } sendfunc(item); - getSelection()->applyToObjects(&sendfunc); + } + else // not an inventory item + { + // Texture picker defaults aren't inventory items + // * Don't need to worry about permissions for them + // * Can just apply the texture and be done with it. + objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + } + + return true; + } + }; + + if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) + { + getSelection()->applyNoCopyTextureToTEs(item); + } + else + { + f setfunc(item, imageid); + getSelection()->applyToTEs(&setfunc); + } + + + struct g : public LLSelectedObjectFunctor + { + LLViewerInventoryItem* mItem; + g(LLViewerInventoryItem* item) : mItem(item) {} + virtual bool apply(LLViewerObject* object) + { + if (!mItem) + { + object->sendTEUpdate(); + // 1 particle effect per object + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(object); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + } + return true; + } + } sendfunc(item); + getSelection()->applyToObjects(&sendfunc); return true; } @@ -2035,7 +2035,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) if (!mItem) { - // 1 particle effect per object + // 1 particle effect per object LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); effectp->setSourceObject(gAgentAvatarp); effectp->setTargetObject(object); @@ -2060,23 +2060,23 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) //----------------------------------------------------------------------------- void LLSelectMgr::selectionSetColor(const LLColor4 &color) { - struct f : public LLSelectedTEFunctor - { - LLColor4 mColor; - f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - object->setTEColor(te, mColor); - } - return true; - } - } setfunc(color); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedTEFunctor + { + LLColor4 mColor; + f(const LLColor4& c) : mColor(c) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + object->setTEColor(te, mColor); + } + return true; + } + } setfunc(color); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } //----------------------------------------------------------------------------- @@ -2084,152 +2084,152 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color) //----------------------------------------------------------------------------- void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) { - struct f : public LLSelectedTEFunctor - { - LLColor4 mColor; - f(const LLColor4& c) : mColor(c) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLColor4 prev_color = object->getTE(te)->getColor(); - mColor.mV[VALPHA] = prev_color.mV[VALPHA]; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, mColor); - } - return true; - } - } setfunc(color); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); -} - + struct f : public LLSelectedTEFunctor + { + LLColor4 mColor; + f(const LLColor4& c) : mColor(c) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLColor4 prev_color = object->getTE(te)->getColor(); + mColor.mV[VALPHA] = prev_color.mV[VALPHA]; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, mColor); + } + return true; + } + } setfunc(color); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); +} + //----------------------------------------------------------------------------- // selectionSetAlphaOnly() //----------------------------------------------------------------------------- void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) { - struct f : public LLSelectedTEFunctor - { - F32 mAlpha; - f(const F32& a) : mAlpha(a) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLColor4 prev_color = object->getTE(te)->getColor(); - prev_color.mV[VALPHA] = mAlpha; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, prev_color); - } - return true; - } - } setfunc(alpha); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedTEFunctor + { + F32 mAlpha; + f(const F32& a) : mAlpha(a) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLColor4 prev_color = object->getTE(te)->getColor(); + prev_color.mV[VALPHA] = mAlpha; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, prev_color); + } + return true; + } + } setfunc(alpha); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionRevertColors() { - struct f : public LLSelectedTEFunctor - { - LLObjectSelectionHandle mSelectedObjects; - f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLSelectNode* nodep = mSelectedObjects->findNode(object); - if (nodep && te < (S32)nodep->mSavedColors.size()) - { - LLColor4 color = nodep->mSavedColors[te]; - // update viewer side color in anticipation of update from simulator - object->setTEColor(te, color); - } - } - return true; - } - } setfunc(mSelectedObjects); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedColors.size()) + { + LLColor4 color = nodep->mSavedColors[te]; + // update viewer side color in anticipation of update from simulator + object->setTEColor(te, color); + } + } + return true; + } + } setfunc(mSelectedObjects); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionRevertShinyColors() { - struct f : public LLSelectedTEFunctor - { - LLObjectSelectionHandle mSelectedObjects; - f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLSelectNode* nodep = mSelectedObjects->findNode(object); - if (nodep && te < (S32)nodep->mSavedShinyColors.size()) - { - LLColor4 color = nodep->mSavedShinyColors[te]; - // update viewer side color in anticipation of update from simulator - LLMaterialPtr old_mat = object->getTE(te)->getMaterialParams(); - if (!old_mat.isNull()) - { - LLMaterialPtr new_mat = gFloaterTools->getPanelFace()->createDefaultMaterial(old_mat); - new_mat->setSpecularLightColor(color); - object->getTE(te)->setMaterialParams(new_mat); - LLMaterialMgr::getInstance()->put(object->getID(), te, *new_mat); - } - } - } - return true; - } - } setfunc(mSelectedObjects); - getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedShinyColors.size()) + { + LLColor4 color = nodep->mSavedShinyColors[te]; + // update viewer side color in anticipation of update from simulator + LLMaterialPtr old_mat = object->getTE(te)->getMaterialParams(); + if (!old_mat.isNull()) + { + LLMaterialPtr new_mat = gFloaterTools->getPanelFace()->createDefaultMaterial(old_mat); + new_mat->setSpecularLightColor(color); + object->getTE(te)->setMaterialParams(new_mat); + LLMaterialMgr::getInstance()->put(object->getID(), te, *new_mat); + } + } + } + return true; + } + } setfunc(mSelectedObjects); + getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } BOOL LLSelectMgr::selectionRevertTextures() { - struct f : public LLSelectedTEFunctor - { - LLObjectSelectionHandle mSelectedObjects; - f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - LLSelectNode* nodep = mSelectedObjects->findNode(object); - if (nodep && te < (S32)nodep->mSavedTextures.size()) - { - LLUUID id = nodep->mSavedTextures[te]; - // update textures on viewer side - if (id.isNull()) - { - // this was probably a no-copy texture, leave image as-is - return FALSE; - } - else - { - object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); - - } - } - } - return true; - } - } setfunc(mSelectedObjects); - BOOL revert_successful = getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); - - return revert_successful; + struct f : public LLSelectedTEFunctor + { + LLObjectSelectionHandle mSelectedObjects; + f(LLObjectSelectionHandle sel) : mSelectedObjects(sel) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLSelectNode* nodep = mSelectedObjects->findNode(object); + if (nodep && te < (S32)nodep->mSavedTextures.size()) + { + LLUUID id = nodep->mSavedTextures[te]; + // update textures on viewer side + if (id.isNull()) + { + // this was probably a no-copy texture, leave image as-is + return FALSE; + } + else + { + object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + } + } + } + return true; + } + } setfunc(mSelectedObjects); + BOOL revert_successful = getSelection()->applyToTEs(&setfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); + + return revert_successful; } void LLSelectMgr::selectionRevertGLTFMaterials() @@ -2260,7 +2260,7 @@ void LLSelectMgr::selectionRevertGLTFMaterials() { // Restore overrides and base material LLGLTFMaterialList::queueApply(objectp, te, asset_id, nodep->mSavedGLTFOverrideMaterials[te]); - } + } else { //blank override out @@ -2276,23 +2276,23 @@ void LLSelectMgr::selectionRevertGLTFMaterials() void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id) { - struct f : public LLSelectedTEFunctor - { - U8 mBump; - f(const U8& b) : mBump(b) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEBumpmap(te, mBump); - } - return true; - } - } setfunc(bumpmap); + struct f : public LLSelectedTEFunctor + { + U8 mBump; + f(const U8& b) : mBump(b) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEBumpmap(te, mBump); + } + return true; + } + } setfunc(bumpmap); LLViewerInventoryItem* item = gInventory.getItem(image_id); - if(item + if(item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) && (mSelectedObjects->getNumNodes() > 1) ) { @@ -2318,53 +2318,53 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id) LLToolDragAndDrop::handleDropMaterialProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null); } getSelection()->applyToTEs(&setfunc); - - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetTexGen(U8 texgen) { - struct f : public LLSelectedTEFunctor - { - U8 mTexgen; - f(const U8& t) : mTexgen(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTETexGen(te, mTexgen); - } - return true; - } - } setfunc(texgen); - getSelection()->applyToTEs(&setfunc); + struct f : public LLSelectedTEFunctor + { + U8 mTexgen; + f(const U8& t) : mTexgen(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTETexGen(te, mTexgen); + } + return true; + } + } setfunc(texgen); + getSelection()->applyToTEs(&setfunc); - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id) { - struct f : public LLSelectedTEFunctor - { - U8 mShiny; - f(const U8& t) : mShiny(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEShiny(te, mShiny); - } - return true; - } - } setfunc(shiny); + struct f : public LLSelectedTEFunctor + { + U8 mShiny; + f(const U8& t) : mShiny(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEShiny(te, mShiny); + } + return true; + } + } setfunc(shiny); LLViewerInventoryItem* item = gInventory.getItem(image_id); - if(item + if(item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) && (mSelectedObjects->getNumNodes() > 1) ) { @@ -2391,235 +2391,235 @@ void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id) } getSelection()->applyToTEs(&setfunc); - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetFullbright(U8 fullbright) { - struct f : public LLSelectedTEFunctor - { - U8 mFullbright; - f(const U8& t) : mFullbright(t) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEFullbright(te, mFullbright); - } - return true; - } - } setfunc(fullbright); - getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor - { - U8 mFullbright; - g(const U8& t) : mFullbright(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - if (mFullbright) - { - U8 material = object->getMaterial(); - U8 mcode = material & LL_MCODE_MASK; - if (mcode == LL_MCODE_LIGHT) - { - mcode = LL_MCODE_GLASS; - material = (material & ~LL_MCODE_MASK) | mcode; - object->setMaterial(material); - object->sendMaterialUpdate(); - } - } - } - return true; - } - } sendfunc(fullbright); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedTEFunctor + { + U8 mFullbright; + f(const U8& t) : mFullbright(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEFullbright(te, mFullbright); + } + return true; + } + } setfunc(fullbright); + getSelection()->applyToTEs(&setfunc); + + struct g : public LLSelectedObjectFunctor + { + U8 mFullbright; + g(const U8& t) : mFullbright(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + if (mFullbright) + { + U8 material = object->getMaterial(); + U8 mcode = material & LL_MCODE_MASK; + if (mcode == LL_MCODE_LIGHT) + { + mcode = LL_MCODE_GLASS; + material = (material & ~LL_MCODE_MASK) | mcode; + object->setMaterial(material); + object->sendMaterialUpdate(); + } + } + } + return true; + } + } sendfunc(fullbright); + getSelection()->applyToObjects(&sendfunc); } // This function expects media_data to be a map containing relevant // media data name/value pairs (e.g. home_url, etc.) void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) -{ - struct f : public LLSelectedTEFunctor - { - U8 mMediaFlags; - const LLSD &mMediaData; - f(const U8& t, const LLSD& d) : mMediaFlags(t), mMediaData(d) {} - bool apply(LLViewerObject* object, S32 te) - { - if (object->permModify()) - { - // If we are adding media, then check the current state of the - // media data on this face. - // - If it does not have media, AND we are NOT setting the HOME URL, then do NOT add media to this - // face. - // - If it does not have media, and we ARE setting the HOME URL, add media to this face. - // - If it does already have media, add/update media to/on this face - // If we are removing media, just do it (ignore the passed-in LLSD). - if (mMediaFlags & LLTextureEntry::MF_HAS_MEDIA) - { - llassert(mMediaData.isMap()); - const LLTextureEntry *texture_entry = object->getTE(te); - if (!mMediaData.isMap() || - ((NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY))) - { - // skip adding/updating media - } - else { - // Add/update media - object->setTEMediaFlags(te, mMediaFlags); - LLVOVolume *vo = dynamic_cast(object); - llassert(NULL != vo); - if (NULL != vo) - { - vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/); - } - } - } - else - { - // delete media (or just set the flags) - object->setTEMediaFlags(te, mMediaFlags); - } - } - return true; - } - } setfunc(media_type, media_data); - getSelection()->applyToTEs(&setfunc); - - struct f2 : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - LLVOVolume *vo = dynamic_cast(object); - llassert(NULL != vo); - // It's okay to skip this object if hasMedia() is false... - // the sendTEUpdate() above would remove all media data if it were - // there. +{ + struct f : public LLSelectedTEFunctor + { + U8 mMediaFlags; + const LLSD &mMediaData; + f(const U8& t, const LLSD& d) : mMediaFlags(t), mMediaData(d) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + // If we are adding media, then check the current state of the + // media data on this face. + // - If it does not have media, AND we are NOT setting the HOME URL, then do NOT add media to this + // face. + // - If it does not have media, and we ARE setting the HOME URL, add media to this face. + // - If it does already have media, add/update media to/on this face + // If we are removing media, just do it (ignore the passed-in LLSD). + if (mMediaFlags & LLTextureEntry::MF_HAS_MEDIA) + { + llassert(mMediaData.isMap()); + const LLTextureEntry *texture_entry = object->getTE(te); + if (!mMediaData.isMap() || + ((NULL != texture_entry) && !texture_entry->hasMedia() && !mMediaData.has(LLMediaEntry::HOME_URL_KEY))) + { + // skip adding/updating media + } + else { + // Add/update media + object->setTEMediaFlags(te, mMediaFlags); + LLVOVolume *vo = dynamic_cast(object); + llassert(NULL != vo); + if (NULL != vo) + { + vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/); + } + } + } + else + { + // delete media (or just set the flags) + object->setTEMediaFlags(te, mMediaFlags); + } + } + return true; + } + } setfunc(media_type, media_data); + getSelection()->applyToTEs(&setfunc); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + LLVOVolume *vo = dynamic_cast(object); + llassert(NULL != vo); + // It's okay to skip this object if hasMedia() is false... + // the sendTEUpdate() above would remove all media data if it were + // there. if (NULL != vo && vo->hasMedia()) { // Send updated media data FOR THE ENTIRE OBJECT vo->sendMediaDataUpdate(); } - } - return true; - } - } func2; - mSelectedObjects->applyToObjects( &func2 ); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); } void LLSelectMgr::selectionSetGlow(F32 glow) { - struct f1 : public LLSelectedTEFunctor - { - F32 mGlow; - f1(F32 glow) : mGlow(glow) {}; - bool apply(LLViewerObject* object, S32 face) - { - if (object->permModify()) - { - // update viewer side color in anticipation of update from simulator - object->setTEGlow(face, mGlow); - } - return true; - } - } func1(glow); - mSelectedObjects->applyToTEs( &func1 ); - - struct f2 : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } - } func2; - mSelectedObjects->applyToObjects( &func2 ); + struct f1 : public LLSelectedTEFunctor + { + F32 mGlow; + f1(F32 glow) : mGlow(glow) {}; + bool apply(LLViewerObject* object, S32 face) + { + if (object->permModify()) + { + // update viewer side color in anticipation of update from simulator + object->setTEGlow(face, mGlow); + } + return true; + } + } func1(glow); + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); } void LLSelectMgr::selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int te) { - struct f1 : public LLSelectedTEFunctor - { - LLMaterialPtr mMaterial; - f1(LLSelectedTEMaterialFunctor* material_func, int te) : _material_func(material_func), _specific_te(te) {} + struct f1 : public LLSelectedTEFunctor + { + LLMaterialPtr mMaterial; + f1(LLSelectedTEMaterialFunctor* material_func, int te) : _material_func(material_func), _specific_te(te) {} - bool apply(LLViewerObject* object, S32 te) - { + bool apply(LLViewerObject* object, S32 te) + { if (_specific_te == -1 || (te == _specific_te)) { - if (object && object->permModify() && _material_func) - { - LLTextureEntry* tep = object->getTE(te); - if (tep) - { - LLMaterialPtr current_material = tep->getMaterialParams(); - _material_func->apply(object, te, tep, current_material); - } - } + if (object && object->permModify() && _material_func) + { + LLTextureEntry* tep = object->getTE(te); + if (tep) + { + LLMaterialPtr current_material = tep->getMaterialParams(); + _material_func->apply(object, te, tep, current_material); + } + } } - return true; - } + return true; + } - LLSelectedTEMaterialFunctor* _material_func; + LLSelectedTEMaterialFunctor* _material_func; int _specific_te; - } func1(material_func, te); - mSelectedObjects->applyToTEs( &func1 ); - - struct f2 : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } - } func2; - mSelectedObjects->applyToObjects( &func2 ); + } func1(material_func, te); + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); } void LLSelectMgr::selectionRemoveMaterial() { - struct f1 : public LLSelectedTEFunctor - { - bool apply(LLViewerObject* object, S32 face) - { - if (object->permModify()) - { - LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; - LLMaterialMgr::getInstance()->remove(object->getID(),face); - object->setTEMaterialParams(face, NULL); - } - return true; - } - } func1; - mSelectedObjects->applyToTEs( &func1 ); - - struct f2 : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->sendTEUpdate(); - } - return true; - } - } func2; - mSelectedObjects->applyToObjects( &func2 ); + struct f1 : public LLSelectedTEFunctor + { + bool apply(LLViewerObject* object, S32 face) + { + if (object->permModify()) + { + LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; + LLMaterialMgr::getInstance()->remove(object->getID(),face); + object->setTEMaterialParams(face, NULL); + } + return true; + } + } func1; + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); } @@ -2628,17 +2628,17 @@ void LLSelectMgr::selectionRemoveMaterial() //----------------------------------------------------------------------------- LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object) { - for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); - iter != getSelection()->valid_end(); iter++ ) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object) - { - return nodep->mPermissions; - } - } + for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); + iter != getSelection()->valid_end(); iter++ ) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object) + { + return nodep->mPermissions; + } + } - return NULL; + return NULL; } @@ -2647,115 +2647,115 @@ LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectionGetGlow(F32 *glow) { - BOOL identical; - F32 lglow = 0.f; - struct f1 : public LLSelectedTEGetFunctor - { - F32 get(LLViewerObject* object, S32 face) - { - return object->getTE(face)->getGlow(); - } - } func; - identical = mSelectedObjects->getSelectedTEValue( &func, lglow ); + BOOL identical; + F32 lglow = 0.f; + struct f1 : public LLSelectedTEGetFunctor + { + F32 get(LLViewerObject* object, S32 face) + { + return object->getTE(face)->getGlow(); + } + } func; + identical = mSelectedObjects->getSelectedTEValue( &func, lglow ); - *glow = lglow; - return identical; + *glow = lglow; + return identical; } void LLSelectMgr::selectionSetPhysicsType(U8 type) { - struct f : public LLSelectedObjectFunctor - { - U8 mType; - f(const U8& t) : mType(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->setPhysicsShapeType(mType); - object->updateFlags(TRUE); - } - return true; - } - } sendfunc(type); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + U8 mType; + f(const U8& t) : mType(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsShapeType(mType); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(type); + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetFriction(F32 friction) { - struct f : public LLSelectedObjectFunctor - { - F32 mFriction; - f(const F32& friction) : mFriction(friction) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->setPhysicsFriction(mFriction); - object->updateFlags(TRUE); - } - return true; - } - } sendfunc(friction); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + F32 mFriction; + f(const F32& friction) : mFriction(friction) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsFriction(mFriction); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(friction); + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetGravity(F32 gravity ) { - struct f : public LLSelectedObjectFunctor - { - F32 mGravity; - f(const F32& gravity) : mGravity(gravity) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->setPhysicsGravity(mGravity); - object->updateFlags(TRUE); - } - return true; - } - } sendfunc(gravity); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + F32 mGravity; + f(const F32& gravity) : mGravity(gravity) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsGravity(mGravity); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(gravity); + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetDensity(F32 density ) { - struct f : public LLSelectedObjectFunctor - { - F32 mDensity; - f(const F32& density ) : mDensity(density) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->setPhysicsDensity(mDensity); - object->updateFlags(TRUE); - } - return true; - } - } sendfunc(density); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + F32 mDensity; + f(const F32& density ) : mDensity(density) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsDensity(mDensity); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(density); + getSelection()->applyToObjects(&sendfunc); } void LLSelectMgr::selectionSetRestitution(F32 restitution) { - struct f : public LLSelectedObjectFunctor - { - F32 mRestitution; - f(const F32& restitution ) : mRestitution(restitution) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - object->setPhysicsRestitution(mRestitution); - object->updateFlags(TRUE); - } - return true; - } - } sendfunc(restitution); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + F32 mRestitution; + f(const F32& restitution ) : mRestitution(restitution) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsRestitution(mRestitution); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(restitution); + getSelection()->applyToObjects(&sendfunc); } @@ -2764,136 +2764,136 @@ void LLSelectMgr::selectionSetRestitution(F32 restitution) //----------------------------------------------------------------------------- void LLSelectMgr::selectionSetMaterial(U8 material) { - struct f : public LLSelectedObjectFunctor - { - U8 mMaterial; - f(const U8& t) : mMaterial(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - U8 cur_material = object->getMaterial(); - U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK); - object->setMaterial(material); - object->sendMaterialUpdate(); - } - return true; - } - } sendfunc(material); - getSelection()->applyToObjects(&sendfunc); + struct f : public LLSelectedObjectFunctor + { + U8 mMaterial; + f(const U8& t) : mMaterial(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + U8 cur_material = object->getMaterial(); + U8 material = mMaterial | (cur_material & ~LL_MCODE_MASK); + object->setMaterial(material); + object->sendMaterialUpdate(); + } + return true; + } + } sendfunc(material); + getSelection()->applyToObjects(&sendfunc); } // TRUE if all selected objects have this PCode BOOL LLSelectMgr::selectionAllPCode(LLPCode code) { - struct f : public LLSelectedObjectFunctor - { - LLPCode mCode; - f(const LLPCode& t) : mCode(t) {} - virtual bool apply(LLViewerObject* object) - { - if (object->getPCode() != mCode) - { - return FALSE; - } - return true; - } - } func(code); - BOOL res = getSelection()->applyToObjects(&func); - return res; + struct f : public LLSelectedObjectFunctor + { + LLPCode mCode; + f(const LLPCode& t) : mCode(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->getPCode() != mCode) + { + return FALSE; + } + return true; + } + } func(code); + BOOL res = getSelection()->applyToObjects(&func); + return res; } bool LLSelectMgr::selectionGetIncludeInSearch(bool* include_in_search_out) { - LLViewerObject *object = mSelectedObjects->getFirstRootObject(); - if (!object) return FALSE; + LLViewerObject *object = mSelectedObjects->getFirstRootObject(); + if (!object) return FALSE; - bool include_in_search = object->getIncludeInSearch(); + bool include_in_search = object->getIncludeInSearch(); - bool identical = true; + bool identical = true; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLViewerObject* object = (*iter)->getObject(); + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLViewerObject* object = (*iter)->getObject(); - if ( include_in_search != object->getIncludeInSearch()) - { - identical = false; - break; - } - } + if ( include_in_search != object->getIncludeInSearch()) + { + identical = false; + break; + } + } - *include_in_search_out = include_in_search; - return identical; + *include_in_search_out = include_in_search; + return identical; } void LLSelectMgr::selectionSetIncludeInSearch(bool include_in_search) { - LLViewerObject* object = NULL; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - object = (*iter)->getObject(); - object->setIncludeInSearch(include_in_search); - } - sendListToRegions( - "ObjectIncludeInSearch", - packAgentAndSessionID, - packObjectIncludeInSearch, + LLViewerObject* object = NULL; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + object = (*iter)->getObject(); + object->setIncludeInSearch(include_in_search); + } + sendListToRegions( + "ObjectIncludeInSearch", + packAgentAndSessionID, + packObjectIncludeInSearch, logNoOp, - &include_in_search, - SEND_ONLY_ROOTS); + &include_in_search, + SEND_ONLY_ROOTS); } BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) { - LLViewerObject *object = mSelectedObjects->getFirstObject(); - if (!object) - { - return FALSE; - } - - U8 action = object->getClickAction(); - *out_action = action; - - struct f : public LLSelectedObjectFunctor - { - U8 mAction; - f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) - { - if ( mAction != object->getClickAction()) - { - return false; - } - return true; - } - } func(action); - BOOL res = getSelection()->applyToObjects(&func); - return res; -} - -void LLSelectMgr::selectionSetClickAction(U8 action) + LLViewerObject *object = mSelectedObjects->getFirstObject(); + if (!object) + { + return FALSE; + } + + U8 action = object->getClickAction(); + *out_action = action; + + struct f : public LLSelectedObjectFunctor + { + U8 mAction; + f(const U8& t) : mAction(t) {} + virtual bool apply(LLViewerObject* object) + { + if ( mAction != object->getClickAction()) + { + return false; + } + return true; + } + } func(action); + BOOL res = getSelection()->applyToObjects(&func); + return res; +} + +void LLSelectMgr::selectionSetClickAction(U8 action) { - struct f : public LLSelectedObjectFunctor - { - U8 mAction; - f(const U8& t) : mAction(t) {} - virtual bool apply(LLViewerObject* object) - { - object->setClickAction(mAction); - return true; - } - } func(action); - getSelection()->applyToObjects(&func); - - sendListToRegions("ObjectClickAction", - packAgentAndSessionID, - packObjectClickAction, + struct f : public LLSelectedObjectFunctor + { + U8 mAction; + f(const U8& t) : mAction(t) {} + virtual bool apply(LLViewerObject* object) + { + object->setClickAction(mAction); + return true; + } + } func(action); + getSelection()->applyToObjects(&func); + + sendListToRegions("ObjectClickAction", + packAgentAndSessionID, + packObjectClickAction, logNoOp, - &action, - SEND_INDIVIDUALS); + &action, + SEND_INDIVIDUALS); } @@ -2905,54 +2905,54 @@ typedef std::pair godlike_request_t; void LLSelectMgr::sendGodlikeRequest(const std::string& request, const std::string& param) { - // If the agent is neither godlike nor an estate owner, the server - // will reject the request. - std::string message_type; - if (gAgent.isGodlike()) - { - message_type = "GodlikeMessage"; - } - else - { - message_type = "EstateOwnerMessage"; - } - - godlike_request_t data(request, param); - if(!mSelectedObjects->getRootObjectCount()) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage(message_type.c_str()); - LLSelectMgr::packGodlikeHead(&data); - gAgent.sendReliableMessage(); - } - else - { - sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, logNoOp, &data, SEND_ONLY_ROOTS); - } + // If the agent is neither godlike nor an estate owner, the server + // will reject the request. + std::string message_type; + if (gAgent.isGodlike()) + { + message_type = "GodlikeMessage"; + } + else + { + message_type = "EstateOwnerMessage"; + } + + godlike_request_t data(request, param); + if(!mSelectedObjects->getRootObjectCount()) + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage(message_type.c_str()); + LLSelectMgr::packGodlikeHead(&data); + gAgent.sendReliableMessage(); + } + else + { + sendListToRegions(message_type, packGodlikeHead, packObjectIDAsParam, logNoOp, &data, SEND_ONLY_ROOTS); + } } void LLSelectMgr::packGodlikeHead(void* user_data) { - LLMessageSystem* msg = gMessageSystem; - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUID("TransactionID", LLUUID::null); - godlike_request_t* data = (godlike_request_t*)user_data; - msg->nextBlock("MethodData"); - msg->addString("Method", data->first); - msg->addUUID("Invoice", LLUUID::null); - - // The parameters used to be restricted to either string or - // integer. This mimics that behavior under the new 'string-only' - // parameter list by not packing a string if there wasn't one - // specified. The object ids will be packed in the - // packObjectIDAsParam() method. - if(data->second.size() > 0) - { - msg->nextBlock("ParamList"); - msg->addString("Parameter", data->second); - } + LLMessageSystem* msg = gMessageSystem; + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUID("TransactionID", LLUUID::null); + godlike_request_t* data = (godlike_request_t*)user_data; + msg->nextBlock("MethodData"); + msg->addString("Method", data->first); + msg->addUUID("Invoice", LLUUID::null); + + // The parameters used to be restricted to either string or + // integer. This mimics that behavior under the new 'string-only' + // parameter list by not packing a string if there wasn't one + // specified. The object ids will be packed in the + // packObjectIDAsParam() method. + if(data->second.size() > 0) + { + msg->nextBlock("ParamList"); + msg->addString("Parameter", data->second); + } } // static @@ -2975,9 +2975,9 @@ void LLSelectMgr::logDetachRequest(LLSelectNode* node, void *) // static void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) { - std::string buf = llformat("%u", node->getObject()->getLocalID()); - gMessageSystem->nextBlock("ParamList"); - gMessageSystem->addString("Parameter", buf); + std::string buf = llformat("%u", node->getObject()->getLocalID()); + gMessageSystem->nextBlock("ParamList"); + gMessageSystem->addString("Parameter", buf); } //----------------------------------------------------------------------------- @@ -2985,34 +2985,34 @@ void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) //----------------------------------------------------------------------------- void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) { - struct f : public LLSelectedTEFunctor - { - F32 mRepeatsPerMeter; - f(const F32& t) : mRepeatsPerMeter(t) {} - bool apply(LLViewerObject* object, S32 te) - { - - if (object->permModify()) - { - // Compute S,T to axis mapping - U32 s_axis, t_axis; - if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) - { - return TRUE; - } + struct f : public LLSelectedTEFunctor + { + F32 mRepeatsPerMeter; + f(const F32& t) : mRepeatsPerMeter(t) {} + bool apply(LLViewerObject* object, S32 te) + { + + if (object->permModify()) + { + // Compute S,T to axis mapping + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return TRUE; + } - F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter; - F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter; + F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter; + F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter; - object->setTEScale(te, new_s, new_t); - } - return true; - } - } setfunc(repeats_per_meter); - getSelection()->applyToTEs(&setfunc); + object->setTEScale(te, new_s, new_t); + } + return true; + } + } setfunc(repeats_per_meter); + getSelection()->applyToTEs(&setfunc); - LLSelectMgrSendFunctor sendfunc; - getSelection()->applyToObjects(&sendfunc); + LLSelectMgrSendFunctor sendfunc; + getSelection()->applyToObjects(&sendfunc); } @@ -3025,113 +3025,113 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) //----------------------------------------------------------------------------- void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++) - { - LLSelectNode* selectNode = *iter; - LLViewerObject* object = selectNode->getObject(); - - if (!object) - { - continue; - } - - if (!object->permModify()) - { - continue; - } - - if (object->getNumTEs() == 0) - { - continue; - } - - BOOL send = FALSE; - - for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++) - { - const LLTextureEntry* tep = object->getTE(te_num); - - BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR; - if (planar == stretch) - { - // Figure out how S,T changed with scale operation - U32 s_axis, t_axis; - if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis)) - { - continue; - } - - LLVector3 object_scale = object->getScale(); - LLVector3 diffuse_scale_ratio = selectNode->mTextureScaleRatios[te_num]; - - // We like these to track together. NORSPEC-96 - // - LLVector3 normal_scale_ratio = diffuse_scale_ratio; - LLVector3 specular_scale_ratio = diffuse_scale_ratio; - - // Apply new scale to face - if (planar) - { - F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; - F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; - - F32 normal_scale_s = normal_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; - F32 normal_scale_t = normal_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; - - F32 specular_scale_s = specular_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; - F32 specular_scale_t = specular_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; - - object->setTEScale(te_num, diffuse_scale_s, diffuse_scale_t); - - LLTextureEntry* tep = object->getTE(te_num); - - if (tep && !tep->getMaterialParams().isNull()) - { - LLMaterialPtr orig = tep->getMaterialParams(); - LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); - p->setNormalRepeat(normal_scale_s, normal_scale_t); - p->setSpecularRepeat(specular_scale_s, specular_scale_t); - - LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); - } - } - else - { - - F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; - F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; - - F32 normal_scale_s = normal_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; - F32 normal_scale_t = normal_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; - - F32 specular_scale_s = specular_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; - F32 specular_scale_t = specular_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; - - object->setTEScale(te_num, diffuse_scale_s,diffuse_scale_t); - - LLTextureEntry* tep = object->getTE(te_num); - - if (tep && !tep->getMaterialParams().isNull()) - { - LLMaterialPtr orig = tep->getMaterialParams(); - LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); - - p->setNormalRepeat(normal_scale_s, normal_scale_t); - p->setSpecularRepeat(specular_scale_s, specular_scale_t); - - LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); - } - } - send = send_to_sim; - } - } - - if (send) - { - object->sendTEUpdate(); - } - } + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++) + { + LLSelectNode* selectNode = *iter; + LLViewerObject* object = selectNode->getObject(); + + if (!object) + { + continue; + } + + if (!object->permModify()) + { + continue; + } + + if (object->getNumTEs() == 0) + { + continue; + } + + BOOL send = FALSE; + + for (U8 te_num = 0; te_num < object->getNumTEs(); te_num++) + { + const LLTextureEntry* tep = object->getTE(te_num); + + BOOL planar = tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR; + if (planar == stretch) + { + // Figure out how S,T changed with scale operation + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te_num, &s_axis, &t_axis)) + { + continue; + } + + LLVector3 object_scale = object->getScale(); + LLVector3 diffuse_scale_ratio = selectNode->mTextureScaleRatios[te_num]; + + // We like these to track together. NORSPEC-96 + // + LLVector3 normal_scale_ratio = diffuse_scale_ratio; + LLVector3 specular_scale_ratio = diffuse_scale_ratio; + + // Apply new scale to face + if (planar) + { + F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + F32 normal_scale_s = normal_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 normal_scale_t = normal_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + F32 specular_scale_s = specular_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 specular_scale_t = specular_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + object->setTEScale(te_num, diffuse_scale_s, diffuse_scale_t); + + LLTextureEntry* tep = object->getTE(te_num); + + if (tep && !tep->getMaterialParams().isNull()) + { + LLMaterialPtr orig = tep->getMaterialParams(); + LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); + p->setNormalRepeat(normal_scale_s, normal_scale_t); + p->setSpecularRepeat(specular_scale_s, specular_scale_t); + + LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); + } + } + else + { + + F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + F32 normal_scale_s = normal_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 normal_scale_t = normal_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + F32 specular_scale_s = specular_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 specular_scale_t = specular_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + object->setTEScale(te_num, diffuse_scale_s,diffuse_scale_t); + + LLTextureEntry* tep = object->getTE(te_num); + + if (tep && !tep->getMaterialParams().isNull()) + { + LLMaterialPtr orig = tep->getMaterialParams(); + LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); + + p->setNormalRepeat(normal_scale_s, normal_scale_t); + p->setSpecularRepeat(specular_scale_s, specular_scale_t); + + LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); + } + } + send = send_to_sim; + } + } + + if (send) + { + object->sendTEUpdate(); + } + } } //----------------------------------------------------------------------------- @@ -3140,16 +3140,16 @@ void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetAllRootsValid() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); ++iter ) - { - LLSelectNode* node = *iter; - if( !node->mValid ) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); ++iter ) + { + LLSelectNode* node = *iter; + if( !node->mValid ) + { + return FALSE; + } + } + return TRUE; } @@ -3159,16 +3159,16 @@ BOOL LLSelectMgr::selectGetAllRootsValid() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetAllValid() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); ++iter ) - { - LLSelectNode* node = *iter; - if( !node->mValid ) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); ++iter ) + { + LLSelectNode* node = *iter; + if( !node->mValid ) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3179,17 +3179,17 @@ BOOL LLSelectMgr::selectGetAllValid() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetAllValidAndObjectsFound() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3198,21 +3198,21 @@ BOOL LLSelectMgr::selectGetAllValidAndObjectsFound() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetModify() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( !object->permModify() ) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->permModify() ) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3221,22 +3221,22 @@ BOOL LLSelectMgr::selectGetModify() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsModify() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( !object->permModify() ) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->permModify() ) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3275,21 +3275,21 @@ BOOL LLSelectMgr::selectGetSameRegion() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetNonPermanentEnforced() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( object->isPermanentEnforced()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->isPermanentEnforced()) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3298,22 +3298,22 @@ BOOL LLSelectMgr::selectGetNonPermanentEnforced() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsNonPermanentEnforced() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( object->isPermanentEnforced()) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->isPermanentEnforced()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3321,21 +3321,21 @@ BOOL LLSelectMgr::selectGetRootsNonPermanentEnforced() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetPermanent() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( !object->flagObjectPermanent()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagObjectPermanent()) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3344,22 +3344,22 @@ BOOL LLSelectMgr::selectGetPermanent() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsPermanent() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( !object->flagObjectPermanent()) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->flagObjectPermanent()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3367,21 +3367,21 @@ BOOL LLSelectMgr::selectGetRootsPermanent() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetCharacter() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( !object->flagCharacter()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3390,22 +3390,22 @@ BOOL LLSelectMgr::selectGetCharacter() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsCharacter() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( !object->flagCharacter()) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3413,21 +3413,21 @@ BOOL LLSelectMgr::selectGetRootsCharacter() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetNonPathfinding() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( object->flagObjectPermanent() || object->flagCharacter()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent() || object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3436,22 +3436,22 @@ BOOL LLSelectMgr::selectGetNonPathfinding() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsNonPathfinding() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( object->flagObjectPermanent() || object->flagCharacter()) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent() || object->flagCharacter()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3459,45 +3459,45 @@ BOOL LLSelectMgr::selectGetRootsNonPathfinding() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetNonPermanent() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( object->flagObjectPermanent()) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// selectGetRootsNonPermanent() - return TRUE if all root objects are not -// permanent -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetRootsNonPermanent() -{ - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( object->flagObjectPermanent()) - { - return FALSE; - } - } + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonPermanent() - return TRUE if all root objects are not +// permanent +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsNonPermanent() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -3505,45 +3505,45 @@ BOOL LLSelectMgr::selectGetRootsNonPermanent() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetNonCharacter() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( object->flagCharacter()) - { - return FALSE; - } - } - return TRUE; -} - -//----------------------------------------------------------------------------- -// selectGetRootsNonCharacter() - return TRUE if all root objects are not + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonCharacter() - return TRUE if all root objects are not // character //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsNonCharacter() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if( object->flagCharacter()) - { - return FALSE; - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagCharacter()) + { + return FALSE; + } + } - return TRUE; + return TRUE; } @@ -3553,30 +3553,30 @@ BOOL LLSelectMgr::selectGetRootsNonCharacter() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetEditableLinksets() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if (object->flagUsePhysics() || - object->flagTemporaryOnRez() || - object->flagCharacter() || - object->flagVolumeDetect() || - object->flagAnimSource() || - (object->getRegion() != gAgent.getRegion()) || - (!gAgent.isGodlike() && - !gAgent.canManageEstate() && - !object->permYouOwner() && - !object->permMove())) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if (object->flagUsePhysics() || + object->flagTemporaryOnRez() || + object->flagCharacter() || + object->flagVolumeDetect() || + object->flagAnimSource() || + (object->getRegion() != gAgent.getRegion()) || + (!gAgent.isGodlike() && + !gAgent.canManageEstate() && + !object->permYouOwner() && + !object->permMove())) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3585,22 +3585,22 @@ BOOL LLSelectMgr::selectGetEditableLinksets() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetViewableCharacters() { - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !object || !node->mValid ) - { - return FALSE; - } - if( !object->flagCharacter() || - (object->getRegion() != gAgent.getRegion())) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter() || + (object->getRegion() != gAgent.getRegion())) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3609,21 +3609,21 @@ BOOL LLSelectMgr::selectGetViewableCharacters() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsTransfer() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if(!object->permTransfer()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if(!object->permTransfer()) + { + return FALSE; + } + } + return TRUE; } //----------------------------------------------------------------------------- @@ -3632,88 +3632,88 @@ BOOL LLSelectMgr::selectGetRootsTransfer() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsCopy() { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if( !node->mValid ) - { - return FALSE; - } - if(!object->permCopy()) - { - return FALSE; - } - } - return TRUE; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if(!object->permCopy()) + { + return FALSE; + } + } + return TRUE; } struct LLSelectGetFirstTest { - LLSelectGetFirstTest() : mIdentical(true), mFirst(true) { } - virtual ~LLSelectGetFirstTest() { } - - // returns false to break out of the iteration. - bool checkMatchingNode(LLSelectNode* node) - { - if (!node || !node->mValid) - { - return false; - } - - if (mFirst) - { - mFirstValue = getValueFromNode(node); - mFirst = false; - } - else - { - if ( mFirstValue != getValueFromNode(node) ) - { - mIdentical = false; - // stop testing once we know not all selected are identical. - return false; - } - } - // continue testing. - return true; - } - - bool mIdentical; - LLUUID mFirstValue; + LLSelectGetFirstTest() : mIdentical(true), mFirst(true) { } + virtual ~LLSelectGetFirstTest() { } + + // returns false to break out of the iteration. + bool checkMatchingNode(LLSelectNode* node) + { + if (!node || !node->mValid) + { + return false; + } + + if (mFirst) + { + mFirstValue = getValueFromNode(node); + mFirst = false; + } + else + { + if ( mFirstValue != getValueFromNode(node) ) + { + mIdentical = false; + // stop testing once we know not all selected are identical. + return false; + } + } + // continue testing. + return true; + } + + bool mIdentical; + LLUUID mFirstValue; protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) = 0; + virtual const LLUUID& getValueFromNode(LLSelectNode* node) = 0; private: - bool mFirst; + bool mFirst; }; void LLSelectMgr::getFirst(LLSelectGetFirstTest* test) { - if (gSavedSettings.getBOOL("EditLinkedParts")) - { - for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); - iter != getSelection()->valid_end(); ++iter ) - { - if (!test->checkMatchingNode(*iter)) - { - break; - } - } - } - else - { - for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); - iter != getSelection()->root_object_end(); ++iter ) - { - if (!test->checkMatchingNode(*iter)) - { - break; - } - } - } + if (gSavedSettings.getBOOL("EditLinkedParts")) + { + for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); + iter != getSelection()->valid_end(); ++iter ) + { + if (!test->checkMatchingNode(*iter)) + { + break; + } + } + } + else + { + for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); + iter != getSelection()->root_object_end(); ++iter ) + { + if (!test->checkMatchingNode(*iter)) + { + break; + } + } + } } //----------------------------------------------------------------------------- @@ -3723,35 +3723,35 @@ void LLSelectMgr::getFirst(LLSelectGetFirstTest* test) struct LLSelectGetFirstCreator : public LLSelectGetFirstTest { protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { - return node->mPermissions->getCreator(); - } + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + return node->mPermissions->getCreator(); + } }; BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) { - LLSelectGetFirstCreator test; - getFirst(&test); + LLSelectGetFirstCreator test; + getFirst(&test); + + if (test.mFirstValue.isNull()) + { + name = LLTrans::getString("AvatarNameNobody"); + return FALSE; + } + + result_id = test.mFirstValue; - if (test.mFirstValue.isNull()) - { - name = LLTrans::getString("AvatarNameNobody"); - return FALSE; - } - - result_id = test.mFirstValue; - - if (test.mIdentical) - { - name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); - } - else - { - name = LLTrans::getString("AvatarNameMultiple"); - } + if (test.mIdentical) + { + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); + } + else + { + name = LLTrans::getString("AvatarNameMultiple"); + } - return test.mIdentical; + return test.mIdentical; } //----------------------------------------------------------------------------- @@ -3761,44 +3761,44 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) struct LLSelectGetFirstOwner : public LLSelectGetFirstTest { protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { - // Don't use 'getOwnership' since we return a reference, not a copy. - // Will return LLUUID::null if unowned (which is not allowed and should never happen.) - return node->mPermissions->isGroupOwned() ? node->mPermissions->getGroup() : node->mPermissions->getOwner(); - } + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + // Don't use 'getOwnership' since we return a reference, not a copy. + // Will return LLUUID::null if unowned (which is not allowed and should never happen.) + return node->mPermissions->isGroupOwned() ? node->mPermissions->getGroup() : node->mPermissions->getOwner(); + } }; BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) { - LLSelectGetFirstOwner test; - getFirst(&test); - - if (test.mFirstValue.isNull()) - { - return FALSE; - } - - result_id = test.mFirstValue; - - if (test.mIdentical) - { - bool group_owned = selectIsGroupOwned(); - if (group_owned) - { - name = LLSLURL("group", test.mFirstValue, "inspect").getSLURLString(); - } - else - { - name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); - } - } - else - { - name = LLTrans::getString("AvatarNameMultiple"); - } - - return test.mIdentical; + LLSelectGetFirstOwner test; + getFirst(&test); + + if (test.mFirstValue.isNull()) + { + return FALSE; + } + + result_id = test.mFirstValue; + + if (test.mIdentical) + { + bool group_owned = selectIsGroupOwned(); + if (group_owned) + { + name = LLSLURL("group", test.mFirstValue, "inspect").getSLURLString(); + } + else + { + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); + } + } + else + { + name = LLTrans::getString("AvatarNameMultiple"); + } + + return test.mIdentical; } //----------------------------------------------------------------------------- @@ -3808,34 +3808,34 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) struct LLSelectGetFirstLastOwner : public LLSelectGetFirstTest { protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { - return node->mPermissions->getLastOwner(); - } + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + return node->mPermissions->getLastOwner(); + } }; BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) { - LLSelectGetFirstLastOwner test; - getFirst(&test); + LLSelectGetFirstLastOwner test; + getFirst(&test); - if (test.mFirstValue.isNull()) - { - return FALSE; - } + if (test.mFirstValue.isNull()) + { + return FALSE; + } + + result_id = test.mFirstValue; - result_id = test.mFirstValue; - - if (test.mIdentical) - { - name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); - } - else - { - name.assign( "" ); - } + if (test.mIdentical) + { + name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); + } + else + { + name.assign( "" ); + } - return test.mIdentical; + return test.mIdentical; } //----------------------------------------------------------------------------- @@ -3845,45 +3845,45 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) struct LLSelectGetFirstGroup : public LLSelectGetFirstTest { protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { - return node->mPermissions->getGroup(); - } + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + return node->mPermissions->getGroup(); + } }; BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) { - LLSelectGetFirstGroup test; - getFirst(&test); + LLSelectGetFirstGroup test; + getFirst(&test); - result_id = test.mFirstValue; - return test.mIdentical; + result_id = test.mFirstValue; + return test.mIdentical; } //----------------------------------------------------------------------------- // selectIsGroupOwned() -// Only operates on root nodes unless editing linked parts. +// Only operates on root nodes unless editing linked parts. // Returns TRUE if the first selected is group owned. //----------------------------------------------------------------------------- struct LLSelectGetFirstGroupOwner : public LLSelectGetFirstTest { protected: - virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { - if (node->mPermissions->isGroupOwned()) - { - return node->mPermissions->getGroup(); - } - return LLUUID::null; - } + virtual const LLUUID& getValueFromNode(LLSelectNode* node) + { + if (node->mPermissions->isGroupOwned()) + { + return node->mPermissions->getGroup(); + } + return LLUUID::null; + } }; BOOL LLSelectMgr::selectIsGroupOwned() { - LLSelectGetFirstGroupOwner test; - getFirst(&test); + LLSelectGetFirstGroupOwner test; + getFirst(&test); - return test.mFirstValue.notNull() ? TRUE : FALSE; + return test.mFirstValue.notNull() ? TRUE : FALSE; } //----------------------------------------------------------------------------- @@ -3897,439 +3897,439 @@ BOOL LLSelectMgr::selectIsGroupOwned() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) { - U32 mask; - U32 mask_and = 0xffffffff; - U32 mask_or = 0x00000000; - BOOL all_valid = FALSE; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - - if (!node->mValid) - { - all_valid = FALSE; - break; - } - - all_valid = TRUE; - - switch( which_perm ) - { - case PERM_BASE: - mask = node->mPermissions->getMaskBase(); - break; - case PERM_OWNER: - mask = node->mPermissions->getMaskOwner(); - break; - case PERM_GROUP: - mask = node->mPermissions->getMaskGroup(); - break; - case PERM_EVERYONE: - mask = node->mPermissions->getMaskEveryone(); - break; - case PERM_NEXT_OWNER: - mask = node->mPermissions->getMaskNextOwner(); - break; - default: - mask = 0x0; - break; - } - mask_and &= mask; - mask_or |= mask; - } - - if (all_valid) - { - // ...TRUE through all ANDs means all TRUE - *mask_on = mask_and; - - // ...FALSE through all ORs means all FALSE - *mask_off = ~mask_or; - return TRUE; - } - else - { - *mask_on = 0; - *mask_off = 0; - return FALSE; - } -} - - - -BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm) -{ - BOOL first = TRUE; - LLPermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } + U32 mask; + U32 mask_and = 0xffffffff; + U32 mask_or = 0x00000000; + BOOL all_valid = FALSE; - if (first) - { - perm = *(node->mPermissions); - first = FALSE; - } - else - { - perm.accumulate(*(node->mPermissions)); - } - } + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; - result_perm = perm; + if (!node->mValid) + { + all_valid = FALSE; + break; + } - return TRUE; -} + all_valid = TRUE; + switch( which_perm ) + { + case PERM_BASE: + mask = node->mPermissions->getMaskBase(); + break; + case PERM_OWNER: + mask = node->mPermissions->getMaskOwner(); + break; + case PERM_GROUP: + mask = node->mPermissions->getMaskGroup(); + break; + case PERM_EVERYONE: + mask = node->mPermissions->getMaskEveryone(); + break; + case PERM_NEXT_OWNER: + mask = node->mPermissions->getMaskNextOwner(); + break; + default: + mask = 0x0; + break; + } + mask_and &= mask; + mask_or |= mask; + } -void LLSelectMgr::selectDelete() -{ - S32 deleteable_count = 0; - - BOOL locked_but_deleteable_object = FALSE; - BOOL no_copy_but_deleteable_object = FALSE; - BOOL all_owned_by_you = TRUE; - - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++) - { - LLViewerObject* obj = (*iter)->getObject(); - - if( obj->isAttachment() ) - { - continue; - } - - deleteable_count++; - - // Check to see if you can delete objects which are locked. - if(!obj->permMove()) - { - locked_but_deleteable_object = TRUE; - } - if(!obj->permCopy()) - { - no_copy_but_deleteable_object = TRUE; - } - if(!obj->permYouOwner()) - { - all_owned_by_you = FALSE; - } - } - - if( 0 == deleteable_count ) - { - make_ui_sound("UISndInvalidOp"); - return; - } - - LLNotification::Params params("ConfirmObjectDeleteLock"); - params.functor.function(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection())); - - if(locked_but_deleteable_object || - no_copy_but_deleteable_object || - !all_owned_by_you) - { - // convert any transient pie-menu selections to full selection so this operation - // has some context - // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode - // but this is ok, if not ideal - convertTransient(); - - //This is messy, but needed to get all english our of the UI. - if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you) - { - //Locked only - params.name("ConfirmObjectDeleteLock"); - } - else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) - { - //No Copy only - params.name("ConfirmObjectDeleteNoCopy"); - } - else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) - { - //not owned only - params.name("ConfirmObjectDeleteNoOwn"); - } - else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) - { - //locked and no copy - params.name("ConfirmObjectDeleteLockNoCopy"); - } - else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) - { - //locked and not owned - params.name("ConfirmObjectDeleteLockNoOwn"); - } - else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you) - { - //no copy and not owned - params.name("ConfirmObjectDeleteNoCopyNoOwn"); - } - else - { - //locked, no copy and not owned - params.name("ConfirmObjectDeleteLockNoCopyNoOwn"); - } - - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } -} + if (all_valid) + { + // ...TRUE through all ANDs means all TRUE + *mask_on = mask_and; -// static -bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - if (!handle->getObjectCount()) - { - LL_WARNS() << "Nothing to delete!" << LL_ENDL; - return false; - } - - switch(option) - { - case 0: - { - // TODO: Make sure you have delete permissions on all of them. - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - // attempt to derez into the trash. - LLDeRezInfo info(DRD_TRASH, trash_id); - LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", - packDeRezHeader, - packObjectLocalID, - logNoOp, - (void*) &info, - SEND_ONLY_ROOTS); - // VEFFECT: Delete Object - one effect for all deletes - if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) - { - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - F32 duration = 0.5f; - duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; - effectp->setDuration(duration); - } - - gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); - - // Keep track of how many objects have been deleted. - add(LLStatViewer::DELETE_OBJECT, LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount()); - } - break; - case 1: - default: - break; - } - return false; + // ...FALSE through all ORs means all FALSE + *mask_off = ~mask_or; + return TRUE; + } + else + { + *mask_on = 0; + *mask_off = 0; + return FALSE; + } } -void LLSelectMgr::selectForceDelete() -{ - sendListToRegions( - "ObjectDelete", - packDeleteHeader, - packObjectLocalID, - logNoOp, - (void*)TRUE, - SEND_ONLY_ROOTS); -} -BOOL LLSelectMgr::selectGetEditMoveLinksetPermissions(bool &move, bool &modify) +BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm) { - move = true; - modify = true; - bool selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - - for (LLObjectSelection::iterator iter = getSelection()->begin(); - iter != getSelection()->end(); iter++) + BOOL first = TRUE; + LLPermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) { - LLSelectNode* nodep = *iter; - LLViewerObject* object = nodep->getObject(); - if (!object || !nodep->mValid) + LLSelectNode* node = *iter; + if (!node->mValid) { - move = false; - modify = false; return FALSE; } - LLViewerObject *root_object = object->getRootEdit(); - bool this_object_movable = false; - if (object->permMove() && !object->isPermanentEnforced() && - ((root_object == NULL) || !root_object->isPermanentEnforced()) && - (object->permModify() || selecting_linked_set)) + if (first) { - this_object_movable = true; + perm = *(node->mPermissions); + first = FALSE; + } + else + { + perm.accumulate(*(node->mPermissions)); } - move = move && this_object_movable; - modify = modify && object->permModify(); } + result_perm = perm; + return TRUE; } -void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale, - BOOL &is_for_sale_mixed, - BOOL &is_sale_price_mixed, - S32 &total_sale_price, - S32 &individual_sale_price) -{ - num_for_sale = 0; - is_for_sale_mixed = FALSE; - is_sale_price_mixed = FALSE; - total_sale_price = 0; - individual_sale_price = 0; - - - // Empty set. - if (getSelection()->root_begin() == getSelection()->root_end()) - return; - - LLSelectNode *node = *(getSelection()->root_begin()); - const BOOL first_node_for_sale = node->mSaleInfo.isForSale(); - const S32 first_node_sale_price = node->mSaleInfo.getSalePrice(); - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - const BOOL node_for_sale = node->mSaleInfo.isForSale(); - const S32 node_sale_price = node->mSaleInfo.getSalePrice(); - - // Set mixed if the fields don't match the first node's fields. - if (node_for_sale != first_node_for_sale) - is_for_sale_mixed = TRUE; - if (node_sale_price != first_node_sale_price) - is_sale_price_mixed = TRUE; - - if (node_for_sale) - { - total_sale_price += node_sale_price; - num_for_sale ++; - } - } - - individual_sale_price = first_node_sale_price; - if (is_for_sale_mixed) - { - is_sale_price_mixed = TRUE; - individual_sale_price = 0; - } -} -// returns TRUE if all nodes are valid. method also stores an -// accumulated sale info. -BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info) +void LLSelectMgr::selectDelete() { - BOOL first = TRUE; - LLSaleInfo sale_info; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - sale_info = node->mSaleInfo; - first = FALSE; - } - else - { - sale_info.accumulate(node->mSaleInfo); - } - } - - result_sale_info = sale_info; - - return TRUE; -} + S32 deleteable_count = 0; -BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm) -{ - BOOL first = TRUE; - LLAggregatePermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - if (first) - { - perm = node->mAggregatePerm; - first = FALSE; - } - else - { - perm.aggregate(node->mAggregatePerm); - } - } - - result_perm = perm; - - return TRUE; + BOOL locked_but_deleteable_object = FALSE; + BOOL no_copy_but_deleteable_object = FALSE; + BOOL all_owned_by_you = TRUE; + + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++) + { + LLViewerObject* obj = (*iter)->getObject(); + + if( obj->isAttachment() ) + { + continue; + } + + deleteable_count++; + + // Check to see if you can delete objects which are locked. + if(!obj->permMove()) + { + locked_but_deleteable_object = TRUE; + } + if(!obj->permCopy()) + { + no_copy_but_deleteable_object = TRUE; + } + if(!obj->permYouOwner()) + { + all_owned_by_you = FALSE; + } + } + + if( 0 == deleteable_count ) + { + make_ui_sound("UISndInvalidOp"); + return; + } + + LLNotification::Params params("ConfirmObjectDeleteLock"); + params.functor.function(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection())); + + if(locked_but_deleteable_object || + no_copy_but_deleteable_object || + !all_owned_by_you) + { + // convert any transient pie-menu selections to full selection so this operation + // has some context + // NOTE: if user cancels delete operation, this will potentially leave objects selected outside of build mode + // but this is ok, if not ideal + convertTransient(); + + //This is messy, but needed to get all english our of the UI. + if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you) + { + //Locked only + params.name("ConfirmObjectDeleteLock"); + } + else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) + { + //No Copy only + params.name("ConfirmObjectDeleteNoCopy"); + } + else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) + { + //not owned only + params.name("ConfirmObjectDeleteNoOwn"); + } + else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) + { + //locked and no copy + params.name("ConfirmObjectDeleteLockNoCopy"); + } + else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) + { + //locked and not owned + params.name("ConfirmObjectDeleteLockNoOwn"); + } + else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you) + { + //no copy and not owned + params.name("ConfirmObjectDeleteNoCopyNoOwn"); + } + else + { + //locked, no copy and not owned + params.name("ConfirmObjectDeleteLockNoCopyNoOwn"); + } + + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } +} + +// static +bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (!handle->getObjectCount()) + { + LL_WARNS() << "Nothing to delete!" << LL_ENDL; + return false; + } + + switch(option) + { + case 0: + { + // TODO: Make sure you have delete permissions on all of them. + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + // attempt to derez into the trash. + LLDeRezInfo info(DRD_TRASH, trash_id); + LLSelectMgr::getInstance()->sendListToRegions("DeRezObject", + packDeRezHeader, + packObjectLocalID, + logNoOp, + (void*) &info, + SEND_ONLY_ROOTS); + // VEFFECT: Delete Object - one effect for all deletes + if (LLSelectMgr::getInstance()->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) + { + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal() ); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + F32 duration = 0.5f; + duration += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount() / 64.f; + effectp->setDuration(duration); + } + + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); + + // Keep track of how many objects have been deleted. + add(LLStatViewer::DELETE_OBJECT, LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount()); + } + break; + case 1: + default: + break; + } + return false; +} + + +void LLSelectMgr::selectForceDelete() +{ + sendListToRegions( + "ObjectDelete", + packDeleteHeader, + packObjectLocalID, + logNoOp, + (void*)TRUE, + SEND_ONLY_ROOTS); +} + +BOOL LLSelectMgr::selectGetEditMoveLinksetPermissions(bool &move, bool &modify) +{ + move = true; + modify = true; + bool selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++) + { + LLSelectNode* nodep = *iter; + LLViewerObject* object = nodep->getObject(); + if (!object || !nodep->mValid) + { + move = false; + modify = false; + return FALSE; + } + + LLViewerObject *root_object = object->getRootEdit(); + bool this_object_movable = false; + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->permModify() || selecting_linked_set)) + { + this_object_movable = true; + } + move = move && this_object_movable; + modify = modify && object->permModify(); + } + + return TRUE; +} + +void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale, + BOOL &is_for_sale_mixed, + BOOL &is_sale_price_mixed, + S32 &total_sale_price, + S32 &individual_sale_price) +{ + num_for_sale = 0; + is_for_sale_mixed = FALSE; + is_sale_price_mixed = FALSE; + total_sale_price = 0; + individual_sale_price = 0; + + + // Empty set. + if (getSelection()->root_begin() == getSelection()->root_end()) + return; + + LLSelectNode *node = *(getSelection()->root_begin()); + const BOOL first_node_for_sale = node->mSaleInfo.isForSale(); + const S32 first_node_sale_price = node->mSaleInfo.getSalePrice(); + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + const BOOL node_for_sale = node->mSaleInfo.isForSale(); + const S32 node_sale_price = node->mSaleInfo.getSalePrice(); + + // Set mixed if the fields don't match the first node's fields. + if (node_for_sale != first_node_for_sale) + is_for_sale_mixed = TRUE; + if (node_sale_price != first_node_sale_price) + is_sale_price_mixed = TRUE; + + if (node_for_sale) + { + total_sale_price += node_sale_price; + num_for_sale ++; + } + } + + individual_sale_price = first_node_sale_price; + if (is_for_sale_mixed) + { + is_sale_price_mixed = TRUE; + individual_sale_price = 0; + } +} + +// returns TRUE if all nodes are valid. method also stores an +// accumulated sale info. +BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& result_sale_info) +{ + BOOL first = TRUE; + LLSaleInfo sale_info; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + sale_info = node->mSaleInfo; + first = FALSE; + } + else + { + sale_info.accumulate(node->mSaleInfo); + } + } + + result_sale_info = sale_info; + + return TRUE; +} + +BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& result_perm) +{ + BOOL first = TRUE; + LLAggregatePermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + if (first) + { + perm = node->mAggregatePerm; + first = FALSE; + } + else + { + perm.aggregate(node->mAggregatePerm); + } + } + + result_perm = perm; + + return TRUE; } BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& result_perm) { - BOOL first = TRUE; - LLAggregatePermissions perm; - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mValid) - { - return FALSE; - } - - LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm; - if (first) - { - perm = t_perm; - first = FALSE; - } - else - { - perm.aggregate(t_perm); - } - } - - result_perm = perm; - - return TRUE; + BOOL first = TRUE; + LLAggregatePermissions perm; + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mValid) + { + return FALSE; + } + + LLAggregatePermissions t_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm; + if (first) + { + perm = t_perm; + first = FALSE; + } + else + { + perm.aggregate(t_perm); + } + } + + result_perm = perm; + + return TRUE; } BOOL LLSelectMgr::isMovableAvatarSelected() { - if (mAllowSelectAvatar && getSelection()->getObjectCount() == 1) - { + if (mAllowSelectAvatar && getSelection()->getObjectCount() == 1) + { // nothing but avatar should be selected, so check that // there is only one selected object and it is a root LLViewerObject* obj = getSelection()->getFirstRootObject(); - return obj && obj->isAvatar() && getSelection()->getFirstMoveableNode(TRUE); - } - return FALSE; + return obj && obj->isAvatar() && getSelection()->getFirstMoveableNode(TRUE); + } + return FALSE; } //-------------------------------------------------------------------- @@ -4341,119 +4341,119 @@ BOOL LLSelectMgr::isMovableAvatarSelected() // messages. struct LLDuplicateData { - LLVector3 offset; - U32 flags; + LLVector3 offset; + U32 flags; }; void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) { - if (mSelectedObjects->isAttachment()) - { - //RN: do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - if (!canDuplicate()) - { - LLSelectNode* node = getSelection()->getFirstRootNode(NULL, true); - if (node) - { - LLSD args; - args["OBJ_NAME"] = node->mName; - LLNotificationsUtil::add("NoCopyPermsNoObject", args); - return; - } - } - LLDuplicateData data; - - data.offset = offset; - data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); - - if (select_copy) - { - // the new copy will be coming in selected - deselectAll(); - } - else - { - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - node->mDuplicated = TRUE; - node->mDuplicatePos = node->getObject()->getPositionGlobal(); - node->mDuplicateRot = node->getObject()->getRotation(); - } - } + if (mSelectedObjects->isAttachment()) + { + //RN: do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + if (!canDuplicate()) + { + LLSelectNode* node = getSelection()->getFirstRootNode(NULL, true); + if (node) + { + LLSD args; + args["OBJ_NAME"] = node->mName; + LLNotificationsUtil::add("NoCopyPermsNoObject", args); + return; + } + } + LLDuplicateData data; + + data.offset = offset; + data.flags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); + + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); + + if (select_copy) + { + // the new copy will be coming in selected + deselectAll(); + } + else + { + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + node->mDuplicated = TRUE; + node->mDuplicatePos = node->getObject()->getPositionGlobal(); + node->mDuplicateRot = node->getObject()->getRotation(); + } + } } void LLSelectMgr::repeatDuplicate() { - if (mSelectedObjects->isAttachment()) - { - //RN: do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - - std::vector non_duplicated_objects; - - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (!node->mDuplicated) - { - non_duplicated_objects.push_back(node->getObject()); - } - } - - // make sure only previously duplicated objects are selected - for (std::vector::iterator iter = non_duplicated_objects.begin(); - iter != non_duplicated_objects.end(); ++iter) - { - LLViewerObject* objectp = *iter; - deselectObjectAndFamily(objectp); - } - - // duplicate objects in place - LLDuplicateData data; - - data.offset = LLVector3::zero; - data.flags = 0x0; - - sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); - - // move current selection based on delta from duplication position and update duplication position - for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); - iter != getSelection()->root_end(); iter++ ) - { - LLSelectNode* node = *iter; - if (node->mDuplicated) - { - LLQuaternion cur_rot = node->getObject()->getRotation(); - LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot); - LLQuaternion new_rot = cur_rot * rot_delta; - LLVector3d cur_pos = node->getObject()->getPositionGlobal(); - LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta); - - node->mDuplicatePos = node->getObject()->getPositionGlobal(); - node->mDuplicateRot = node->getObject()->getRotation(); - node->getObject()->setPositionGlobal(new_pos); - node->getObject()->setRotation(new_rot); - } - } - - sendMultipleUpdate(UPD_ROTATION | UPD_POSITION); -} - -// static + if (mSelectedObjects->isAttachment()) + { + //RN: do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + + std::vector non_duplicated_objects; + + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (!node->mDuplicated) + { + non_duplicated_objects.push_back(node->getObject()); + } + } + + // make sure only previously duplicated objects are selected + for (std::vector::iterator iter = non_duplicated_objects.begin(); + iter != non_duplicated_objects.end(); ++iter) + { + LLViewerObject* objectp = *iter; + deselectObjectAndFamily(objectp); + } + + // duplicate objects in place + LLDuplicateData data; + + data.offset = LLVector3::zero; + data.flags = 0x0; + + sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, logNoOp, &data, SEND_ONLY_ROOTS); + + // move current selection based on delta from duplication position and update duplication position + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + if (node->mDuplicated) + { + LLQuaternion cur_rot = node->getObject()->getRotation(); + LLQuaternion rot_delta = (~node->mDuplicateRot * cur_rot); + LLQuaternion new_rot = cur_rot * rot_delta; + LLVector3d cur_pos = node->getObject()->getPositionGlobal(); + LLVector3d new_pos = cur_pos + ((cur_pos - node->mDuplicatePos) * rot_delta); + + node->mDuplicatePos = node->getObject()->getPositionGlobal(); + node->mDuplicateRot = node->getObject()->getRotation(); + node->getObject()->setPositionGlobal(new_pos); + node->getObject()->setRotation(new_rot); + } + } + + sendMultipleUpdate(UPD_ROTATION | UPD_POSITION); +} + +// static void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data ) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); } @@ -4465,71 +4465,71 @@ void LLSelectMgr::packDuplicate( LLSelectNode* node, void *duplicate_data ) // ray. struct LLDuplicateOnRayData { - LLVector3 mRayStartRegion; - LLVector3 mRayEndRegion; - BOOL mBypassRaycast; - BOOL mRayEndIsIntersection; - LLUUID mRayTargetID; - BOOL mCopyCenters; - BOOL mCopyRotates; - U32 mFlags; + LLVector3 mRayStartRegion; + LLVector3 mRayEndRegion; + BOOL mBypassRaycast; + BOOL mRayEndIsIntersection; + LLUUID mRayTargetID; + BOOL mCopyCenters; + BOOL mCopyRotates; + U32 mFlags; }; void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, - const LLVector3 &ray_end_region, - BOOL bypass_raycast, - BOOL ray_end_is_intersection, - const LLUUID &ray_target_id, - BOOL copy_centers, - BOOL copy_rotates, - BOOL select_copy) -{ - if (mSelectedObjects->isAttachment()) - { - // do not duplicate attachments - make_ui_sound("UISndInvalidOp"); - return; - } - - LLDuplicateOnRayData data; - - data.mRayStartRegion = ray_start_region; - data.mRayEndRegion = ray_end_region; - data.mBypassRaycast = bypass_raycast; - data.mRayEndIsIntersection = ray_end_is_intersection; - data.mRayTargetID = ray_target_id; - data.mCopyCenters = copy_centers; - data.mCopyRotates = copy_rotates; - data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); - - sendListToRegions("ObjectDuplicateOnRay", + const LLVector3 &ray_end_region, + BOOL bypass_raycast, + BOOL ray_end_is_intersection, + const LLUUID &ray_target_id, + BOOL copy_centers, + BOOL copy_rotates, + BOOL select_copy) +{ + if (mSelectedObjects->isAttachment()) + { + // do not duplicate attachments + make_ui_sound("UISndInvalidOp"); + return; + } + + LLDuplicateOnRayData data; + + data.mRayStartRegion = ray_start_region; + data.mRayEndRegion = ray_end_region; + data.mBypassRaycast = bypass_raycast; + data.mRayEndIsIntersection = ray_end_is_intersection; + data.mRayTargetID = ray_target_id; + data.mCopyCenters = copy_centers; + data.mCopyRotates = copy_rotates; + data.mFlags = (select_copy ? FLAGS_CREATE_SELECTED : 0x0); + + sendListToRegions("ObjectDuplicateOnRay", packDuplicateOnRayHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); - if (select_copy) - { - // the new copy will be coming in selected - deselectAll(); - } + if (select_copy) + { + // the new copy will be coming in selected + deselectAll(); + } } // static void LLSelectMgr::packDuplicateOnRayHead(void *user_data) { - LLMessageSystem *msg = gMessageSystem; - LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data; + LLMessageSystem *msg = gMessageSystem; + LLDuplicateOnRayData *data = (LLDuplicateOnRayData *)user_data; - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); - msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion ); - msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion ); - msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast ); - msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection ); - msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters ); - msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates ); - msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID ); - msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags ); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); + msg->addVector3Fast(_PREHASH_RayStart, data->mRayStartRegion ); + msg->addVector3Fast(_PREHASH_RayEnd, data->mRayEndRegion ); + msg->addBOOLFast(_PREHASH_BypassRaycast, data->mBypassRaycast ); + msg->addBOOLFast(_PREHASH_RayEndIsIntersection, data->mRayEndIsIntersection ); + msg->addBOOLFast(_PREHASH_CopyCenters, data->mCopyCenters ); + msg->addBOOLFast(_PREHASH_CopyRotates, data->mCopyRotates ); + msg->addUUIDFast(_PREHASH_RayTargetID, data->mRayTargetID ); + msg->addU32Fast(_PREHASH_DuplicateFlags, data->mFlags ); } @@ -4540,61 +4540,61 @@ void LLSelectMgr::packDuplicateOnRayHead(void *user_data) void LLSelectMgr::sendMultipleUpdate(U32 type) { - if (type == UPD_NONE) return; - // send individual updates when selecting textures or individual objects - ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST; - if (send_type == SEND_ONLY_ROOTS) - { - // tell simulator to apply to whole linked sets - type |= UPD_LINKED_SETS; - } - - sendListToRegions( - "MultipleObjectUpdate", - packAgentAndSessionID, - packMultipleUpdate, + if (type == UPD_NONE) return; + // send individual updates when selecting textures or individual objects + ESendType send_type = (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) ? SEND_ONLY_ROOTS : SEND_ROOTS_FIRST; + if (send_type == SEND_ONLY_ROOTS) + { + // tell simulator to apply to whole linked sets + type |= UPD_LINKED_SETS; + } + + sendListToRegions( + "MultipleObjectUpdate", + packAgentAndSessionID, + packMultipleUpdate, logNoOp, - &type, - send_type); + &type, + send_type); } // static void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data) { - LLViewerObject* object = node->getObject(); - U32 *type32 = (U32 *)user_data; - U8 type = (U8)*type32; - U8 data[256]; - - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->addU8Fast(_PREHASH_Type, type ); - - S32 offset = 0; - - // JC: You MUST pack the data in this order. The receiving - // routine process_multiple_update_message on simulator will - // extract them in this order. - - if (type & UPD_POSITION) - { - htolememcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); - offset += 12; - } - if (type & UPD_ROTATION) - { - LLQuaternion quat = object->getRotation(); - LLVector3 vec = quat.packToVector3(); - htolememcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); - offset += 12; - } - if (type & UPD_SCALE) - { - //LL_INFOS() << "Sending object scale " << object->getScale() << LL_ENDL; - htolememcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); - offset += 12; - } - gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); + LLViewerObject* object = node->getObject(); + U32 *type32 = (U32 *)user_data; + U8 type = (U8)*type32; + U8 data[256]; + + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->addU8Fast(_PREHASH_Type, type ); + + S32 offset = 0; + + // JC: You MUST pack the data in this order. The receiving + // routine process_multiple_update_message on simulator will + // extract them in this order. + + if (type & UPD_POSITION) + { + htolememcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12); + offset += 12; + } + if (type & UPD_ROTATION) + { + LLQuaternion quat = object->getRotation(); + LLVector3 vec = quat.packToVector3(); + htolememcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12); + offset += 12; + } + if (type & UPD_SCALE) + { + //LL_INFOS() << "Sending object scale " << object->getScale() << LL_ENDL; + htolememcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12); + offset += 12; + } + gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset); } //------------------------------------------------------------------------ @@ -4602,36 +4602,36 @@ void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data) //------------------------------------------------------------------------ struct LLOwnerData { - LLUUID owner_id; - LLUUID group_id; - BOOL override; + LLUUID owner_id; + LLUUID group_id; + BOOL override; }; void LLSelectMgr::sendOwner(const LLUUID& owner_id, - const LLUUID& group_id, - BOOL override) + const LLUUID& group_id, + BOOL override) { - LLOwnerData data; + LLOwnerData data; - data.owner_id = owner_id; - data.group_id = group_id; - data.override = override; + data.owner_id = owner_id; + data.group_id = group_id; + data.override = override; - sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectOwner", packOwnerHead, packObjectLocalID, logNoOp, &data, SEND_ONLY_ROOTS); } // static void LLSelectMgr::packOwnerHead(void *user_data) { - LLOwnerData *data = (LLOwnerData *)user_data; + LLOwnerData *data = (LLOwnerData *)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - gMessageSystem->nextBlockFast(_PREHASH_HeaderData); - gMessageSystem->addBOOLFast(_PREHASH_Override, data->override); - gMessageSystem->addUUIDFast(_PREHASH_OwnerID, data->owner_id); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gMessageSystem->nextBlockFast(_PREHASH_HeaderData); + gMessageSystem->addBOOLFast(_PREHASH_Override, data->override); + gMessageSystem->addUUIDFast(_PREHASH_OwnerID, data->owner_id); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id); } //------------------------------------------------------------------------ @@ -4640,8 +4640,8 @@ void LLSelectMgr::packOwnerHead(void *user_data) void LLSelectMgr::sendGroup(const LLUUID& group_id) { - LLUUID local_group_id(group_id); - sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, logNoOp, &local_group_id, SEND_ONLY_ROOTS); + LLUUID local_group_id(group_id); + sendListToRegions("ObjectGroup", packAgentAndSessionAndGroupID, packObjectLocalID, logNoOp, &local_group_id, SEND_ONLY_ROOTS); } @@ -4651,9 +4651,9 @@ void LLSelectMgr::sendGroup(const LLUUID& group_id) struct LLBuyData { - std::vector mObjectsSent; - LLUUID mCategoryID; - LLSaleInfo mSaleInfo; + std::vector mObjectsSent; + LLUUID mCategoryID; + LLSaleInfo mSaleInfo; }; // *NOTE: does not work for multiple object buy, which UI does not @@ -4662,26 +4662,26 @@ struct LLBuyData // info -as displayed in the UI- for every item. void LLSelectMgr::sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info) { - LLBuyData buy; - buy.mCategoryID = category_id; - buy.mSaleInfo = sale_info; - sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, logNoOp, &buy, SEND_ONLY_ROOTS); + LLBuyData buy; + buy.mCategoryID = category_id; + buy.mSaleInfo = sale_info; + sendListToRegions("ObjectBuy", packAgentGroupAndCatID, packBuyObjectIDs, logNoOp, &buy, SEND_ONLY_ROOTS); } // static void LLSelectMgr::packBuyObjectIDs(LLSelectNode* node, void* data) { - LLBuyData* buy = (LLBuyData*)data; + LLBuyData* buy = (LLBuyData*)data; - LLViewerObject* object = node->getObject(); - if (std::find(buy->mObjectsSent.begin(), buy->mObjectsSent.end(), object) == buy->mObjectsSent.end()) - { - buy->mObjectsSent.push_back(object); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); - gMessageSystem->addU8Fast(_PREHASH_SaleType, buy->mSaleInfo.getSaleType()); - gMessageSystem->addS32Fast(_PREHASH_SalePrice, buy->mSaleInfo.getSalePrice()); - } + LLViewerObject* object = node->getObject(); + if (std::find(buy->mObjectsSent.begin(), buy->mObjectsSent.end(), object) == buy->mObjectsSent.end()) + { + buy->mObjectsSent.push_back(object); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID() ); + gMessageSystem->addU8Fast(_PREHASH_SaleType, buy->mSaleInfo.getSaleType()); + gMessageSystem->addS32Fast(_PREHASH_SalePrice, buy->mSaleInfo.getSalePrice()); + } } //------------------------------------------------------------------------ @@ -4690,37 +4690,37 @@ void LLSelectMgr::packBuyObjectIDs(LLSelectNode* node, void* data) struct LLPermData { - U8 mField; - BOOL mSet; - U32 mMask; - BOOL mOverride; + U8 mField; + BOOL mSet; + U32 mMask; + BOOL mOverride; }; // TODO: Make this able to fail elegantly. void LLSelectMgr::selectionSetObjectPermissions(U8 field, - BOOL set, - U32 mask, - BOOL override) + BOOL set, + U32 mask, + BOOL override) { - LLPermData data; + LLPermData data; - data.mField = field; - data.mSet = set; - data.mMask = mask; - data.mOverride = override; + data.mField = field; + data.mSet = set; + data.mMask = mask; + data.mOverride = override; - sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, logNoOp, &data, SEND_ONLY_ROOTS); + sendListToRegions("ObjectPermissions", packPermissionsHead, packPermissions, logNoOp, &data, SEND_ONLY_ROOTS); } void LLSelectMgr::packPermissionsHead(void* user_data) { - LLPermData* data = (LLPermData*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_HeaderData); - gMessageSystem->addBOOLFast(_PREHASH_Override, data->mOverride); -} + LLPermData* data = (LLPermData*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_HeaderData); + gMessageSystem->addBOOLFast(_PREHASH_Override, data->mOverride); +} // Now that you've added a bunch of objects, send a select message @@ -4728,204 +4728,204 @@ void LLSelectMgr::packPermissionsHead(void* user_data) /* void LLSelectMgr::sendSelect() { - LL_ERRS() << "Not implemented" << LL_ENDL; + LL_ERRS() << "Not implemented" << LL_ENDL; } */ void LLSelectMgr::deselectAll() { - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - // Zap the angular velocity, as the sim will set it to zero - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setAngularVelocity( 0,0,0 ); - objectp->setVelocity( 0,0,0 ); - } - - sendListToRegions( - "ObjectDeselect", - packAgentAndSessionID, - packObjectLocalID, - logNoOp, - NULL, - SEND_INDIVIDUALS); + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + // Zap the angular velocity, as the sim will set it to zero + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setAngularVelocity( 0,0,0 ); + objectp->setVelocity( 0,0,0 ); + } + + sendListToRegions( + "ObjectDeselect", + packAgentAndSessionID, + packObjectLocalID, + logNoOp, + NULL, + SEND_INDIVIDUALS); + + removeAll(); - removeAll(); - - mLastSentSelectionCenterGlobal.clearVec(); + mLastSentSelectionCenterGlobal.clearVec(); - updatePointAt(); + updatePointAt(); } void LLSelectMgr::deselectAllForStandingUp() { - /* - This function is similar deselectAll() except for the first if statement - which was removed. This is needed as a workaround for DEV-2854 - */ - - // Zap the angular velocity, as the sim will set it to zero - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++ ) - { - LLViewerObject *objectp = (*iter)->getObject(); - objectp->setAngularVelocity( 0,0,0 ); - objectp->setVelocity( 0,0,0 ); - } - - sendListToRegions( - "ObjectDeselect", - packAgentAndSessionID, - packObjectLocalID, + /* + This function is similar deselectAll() except for the first if statement + which was removed. This is needed as a workaround for DEV-2854 + */ + + // Zap the angular velocity, as the sim will set it to zero + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++ ) + { + LLViewerObject *objectp = (*iter)->getObject(); + objectp->setAngularVelocity( 0,0,0 ); + objectp->setVelocity( 0,0,0 ); + } + + sendListToRegions( + "ObjectDeselect", + packAgentAndSessionID, + packObjectLocalID, logNoOp, - NULL, - SEND_INDIVIDUALS); + NULL, + SEND_INDIVIDUALS); + + removeAll(); - removeAll(); - - mLastSentSelectionCenterGlobal.clearVec(); + mLastSentSelectionCenterGlobal.clearVec(); - updatePointAt(); + updatePointAt(); } void LLSelectMgr::deselectUnused() { - // no more outstanding references to this selection - if (mSelectedObjects->getNumRefs() == 1) - { - deselectAll(); - } + // no more outstanding references to this selection + if (mSelectedObjects->getNumRefs() == 1) + { + deselectAll(); + } } void LLSelectMgr::convertTransient() { - LLObjectSelection::iterator node_it; - for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it) - { - LLSelectNode *nodep = *node_it; - nodep->setTransient(FALSE); - } + LLObjectSelection::iterator node_it; + for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it) + { + LLSelectNode *nodep = *node_it; + nodep->setTransient(FALSE); + } } void LLSelectMgr::deselectAllIfTooFar() { - if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD) - { - return; - } - - // HACK: Don't deselect when we're navigating to rate an object's - // owner or creator. JC - if (gMenuObject->getVisible()) - { - return; - } - - LLVector3d selectionCenter = getSelectionCenterGlobal(); - if (gSavedSettings.getBOOL("LimitSelectDistance") - && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) - && (mSelectedObjects->getPrimaryObject() != LLViewerMediaFocus::getInstance()->getFocusedObject()) - && !mSelectedObjects->isAttachment() - && !selectionCenter.isExactlyZero()) - { - F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); - F32 deselect_dist_sq = deselect_dist * deselect_dist; - - LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; - F32 select_dist_sq = (F32) select_delta.magVecSquared(); - - if (select_dist_sq > deselect_dist_sq) - { - if (mDebugSelectMgr) - { - LL_INFOS() << "Selection manager: auto-deselecting, select_dist = " << (F32) sqrt(select_dist_sq) << LL_ENDL; - LL_INFOS() << "agent pos global = " << gAgent.getPositionGlobal() << LL_ENDL; - LL_INFOS() << "selection pos global = " << selectionCenter << LL_ENDL; - } - - deselectAll(); - } - } + if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD) + { + return; + } + + // HACK: Don't deselect when we're navigating to rate an object's + // owner or creator. JC + if (gMenuObject->getVisible()) + { + return; + } + + LLVector3d selectionCenter = getSelectionCenterGlobal(); + if (gSavedSettings.getBOOL("LimitSelectDistance") + && (!mSelectedObjects->getPrimaryObject() || !mSelectedObjects->getPrimaryObject()->isAvatar()) + && (mSelectedObjects->getPrimaryObject() != LLViewerMediaFocus::getInstance()->getFocusedObject()) + && !mSelectedObjects->isAttachment() + && !selectionCenter.isExactlyZero()) + { + F32 deselect_dist = gSavedSettings.getF32("MaxSelectDistance"); + F32 deselect_dist_sq = deselect_dist * deselect_dist; + + LLVector3d select_delta = gAgent.getPositionGlobal() - selectionCenter; + F32 select_dist_sq = (F32) select_delta.magVecSquared(); + + if (select_dist_sq > deselect_dist_sq) + { + if (mDebugSelectMgr) + { + LL_INFOS() << "Selection manager: auto-deselecting, select_dist = " << (F32) sqrt(select_dist_sq) << LL_ENDL; + LL_INFOS() << "agent pos global = " << gAgent.getPositionGlobal() << LL_ENDL; + LL_INFOS() << "selection pos global = " << selectionCenter << LL_ENDL; + } + + deselectAll(); + } + } } void LLSelectMgr::selectionSetObjectName(const std::string& name) { - std::string name_copy(name); + std::string name_copy(name); - // we only work correctly if 1 object is selected. - if(mSelectedObjects->getRootObjectCount() == 1) - { - sendListToRegions("ObjectName", - packAgentAndSessionID, - packObjectName, + // we only work correctly if 1 object is selected. + if(mSelectedObjects->getRootObjectCount() == 1) + { + sendListToRegions("ObjectName", + packAgentAndSessionID, + packObjectName, logNoOp, - (void*)(&name_copy), - SEND_ONLY_ROOTS); - } - else if(mSelectedObjects->getObjectCount() == 1) - { - sendListToRegions("ObjectName", - packAgentAndSessionID, - packObjectName, + (void*)(&name_copy), + SEND_ONLY_ROOTS); + } + else if(mSelectedObjects->getObjectCount() == 1) + { + sendListToRegions("ObjectName", + packAgentAndSessionID, + packObjectName, logNoOp, - (void*)(&name_copy), - SEND_INDIVIDUALS); - } + (void*)(&name_copy), + SEND_INDIVIDUALS); + } } void LLSelectMgr::selectionSetObjectDescription(const std::string& desc) { - std::string desc_copy(desc); + std::string desc_copy(desc); - // we only work correctly if 1 object is selected. - if(mSelectedObjects->getRootObjectCount() == 1) - { - sendListToRegions("ObjectDescription", - packAgentAndSessionID, - packObjectDescription, + // we only work correctly if 1 object is selected. + if(mSelectedObjects->getRootObjectCount() == 1) + { + sendListToRegions("ObjectDescription", + packAgentAndSessionID, + packObjectDescription, logNoOp, - (void*)(&desc_copy), - SEND_ONLY_ROOTS); - } - else if(mSelectedObjects->getObjectCount() == 1) - { - sendListToRegions("ObjectDescription", - packAgentAndSessionID, - packObjectDescription, + (void*)(&desc_copy), + SEND_ONLY_ROOTS); + } + else if(mSelectedObjects->getObjectCount() == 1) + { + sendListToRegions("ObjectDescription", + packAgentAndSessionID, + packObjectDescription, logNoOp, - (void*)(&desc_copy), - SEND_INDIVIDUALS); - } + (void*)(&desc_copy), + SEND_INDIVIDUALS); + } } void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) { - // for now, we only want to be able to set one root category at - // a time. - if(mSelectedObjects->getRootObjectCount() != 1) return; - sendListToRegions("ObjectCategory", - packAgentAndSessionID, - packObjectCategory, + // for now, we only want to be able to set one root category at + // a time. + if(mSelectedObjects->getRootObjectCount() != 1) return; + sendListToRegions("ObjectCategory", + packAgentAndSessionID, + packObjectCategory, logNoOp, - (void*)(&category), - SEND_ONLY_ROOTS); + (void*)(&category), + SEND_ONLY_ROOTS); } void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) { - sendListToRegions("ObjectSaleInfo", - packAgentAndSessionID, - packObjectSaleInfo, + sendListToRegions("ObjectSaleInfo", + packAgentAndSessionID, + packObjectSaleInfo, logNoOp, - (void*)(&sale_info), - SEND_ONLY_ROOTS); + (void*)(&sale_info), + SEND_ONLY_ROOTS); } //---------------------------------------------------------------------- @@ -4939,80 +4939,80 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace) void LLSelectMgr::sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace) { - if (selection_handle.isNull()) - { - return; - } - - LLViewerObject* attach_object = selection_handle->getFirstRootObject(); - - if (!attach_object || !isAgentAvatarValid() || selection_handle->mSelectType != SELECT_TYPE_WORLD) - { - return; - } - - BOOL build_mode = LLToolMgr::getInstance()->inEdit(); - // Special case: Attach to default location for this object. - if (0 == attachment_point || - get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) - { - if (!replace || attachment_point != 0) - { - // If we know the attachment point then we got here by clicking an - // "Attach to..." context menu item, so we should add, not replace. - attachment_point |= ATTACHMENT_ADD; - } - - sendListToRegions( - selection_handle, - "ObjectAttach", - packAgentIDAndSessionAndAttachment, - packObjectIDAndRotation, + if (selection_handle.isNull()) + { + return; + } + + LLViewerObject* attach_object = selection_handle->getFirstRootObject(); + + if (!attach_object || !isAgentAvatarValid() || selection_handle->mSelectType != SELECT_TYPE_WORLD) + { + return; + } + + BOOL build_mode = LLToolMgr::getInstance()->inEdit(); + // Special case: Attach to default location for this object. + if (0 == attachment_point || + get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) + { + if (!replace || attachment_point != 0) + { + // If we know the attachment point then we got here by clicking an + // "Attach to..." context menu item, so we should add, not replace. + attachment_point |= ATTACHMENT_ADD; + } + + sendListToRegions( + selection_handle, + "ObjectAttach", + packAgentIDAndSessionAndAttachment, + packObjectIDAndRotation, logAttachmentRequest, - &attachment_point, - SEND_ONLY_ROOTS ); - if (!build_mode) - { - // After "ObjectAttach" server will unsubscribe us from properties updates - // so either deselect objects or resend selection after attach packet reaches server - // In case of build_mode LLPanelObjectInventory::refresh() will deal with selection - // Still unsubscribe even in case selection_handle is not current selection - deselectAll(); - } - } + &attachment_point, + SEND_ONLY_ROOTS ); + if (!build_mode) + { + // After "ObjectAttach" server will unsubscribe us from properties updates + // so either deselect objects or resend selection after attach packet reaches server + // In case of build_mode LLPanelObjectInventory::refresh() will deal with selection + // Still unsubscribe even in case selection_handle is not current selection + deselectAll(); + } + } } void LLSelectMgr::sendDetach() { - if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) - { - return; - } + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) + { + return; + } - sendListToRegions( - "ObjectDetach", - packAgentAndSessionID, - packObjectLocalID, + sendListToRegions( + "ObjectDetach", + packAgentAndSessionID, + packObjectLocalID, logDetachRequest, - NULL, - SEND_ONLY_ROOTS ); + NULL, + SEND_ONLY_ROOTS ); } void LLSelectMgr::sendDropAttachment() { - if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) - { - return; - } + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) + { + return; + } - sendListToRegions( - "ObjectDrop", - packAgentAndSessionID, - packObjectLocalID, + sendListToRegions( + "ObjectDrop", + packAgentAndSessionID, + packObjectLocalID, logDetachRequest, - NULL, - SEND_ONLY_ROOTS); + NULL, + SEND_ONLY_ROOTS); } //---------------------------------------------------------------------- @@ -5021,56 +5021,56 @@ void LLSelectMgr::sendDropAttachment() void LLSelectMgr::sendLink() { - if (!mSelectedObjects->getNumNodes()) - { - return; - } + if (!mSelectedObjects->getNumNodes()) + { + return; + } - sendListToRegions( - "ObjectLink", - packAgentAndSessionID, - packObjectLocalID, + sendListToRegions( + "ObjectLink", + packAgentAndSessionID, + packObjectLocalID, logNoOp, - NULL, - SEND_ONLY_ROOTS); + NULL, + SEND_ONLY_ROOTS); } void LLSelectMgr::sendDelink() { - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - struct f : public LLSelectedObjectFunctor - { //on delink, any modifyable object should - f() {} - - virtual bool apply(LLViewerObject* object) - { - if (object->permModify()) - { - if (object->getPhysicsShapeType() == LLViewerObject::PHYSICS_SHAPE_NONE) - { - object->setPhysicsShapeType(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); - object->updateFlags(); - } - } - return true; - } - } sendfunc; - getSelection()->applyToObjects(&sendfunc); - - - // Delink needs to send individuals so you can unlink a single object from - // a linked set. - sendListToRegions( - "ObjectDelink", - packAgentAndSessionID, - packObjectLocalID, + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + struct f : public LLSelectedObjectFunctor + { //on delink, any modifyable object should + f() {} + + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + if (object->getPhysicsShapeType() == LLViewerObject::PHYSICS_SHAPE_NONE) + { + object->setPhysicsShapeType(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + object->updateFlags(); + } + } + return true; + } + } sendfunc; + getSelection()->applyToObjects(&sendfunc); + + + // Delink needs to send individuals so you can unlink a single object from + // a linked set. + sendListToRegions( + "ObjectDelink", + packAgentAndSessionID, + packObjectLocalID, logNoOp, - NULL, - SEND_INDIVIDUALS); + NULL, + SEND_INDIVIDUALS); } @@ -5081,118 +5081,118 @@ void LLSelectMgr::sendDelink() /* void LLSelectMgr::sendHinge(U8 type) { - if (!mSelectedObjects->getNumNodes()) - { - return; - } + if (!mSelectedObjects->getNumNodes()) + { + return; + } - sendListToRegions( - "ObjectHinge", - packHingeHead, - packObjectLocalID, - &type, - SEND_ONLY_ROOTS); + sendListToRegions( + "ObjectHinge", + packHingeHead, + packObjectLocalID, + &type, + SEND_ONLY_ROOTS); } void LLSelectMgr::sendDehinge() { - if (!mSelectedObjects->getNumNodes()) - { - return; - } - - sendListToRegions( - "ObjectDehinge", - packAgentAndSessionID, - packObjectLocalID, - NULL, - SEND_ONLY_ROOTS); + if (!mSelectedObjects->getNumNodes()) + { + return; + } + + sendListToRegions( + "ObjectDehinge", + packAgentAndSessionID, + packObjectLocalID, + NULL, + SEND_ONLY_ROOTS); }*/ void LLSelectMgr::sendSelect() { - if (!mSelectedObjects->getNumNodes()) - { - return; - } + if (!mSelectedObjects->getNumNodes()) + { + return; + } - sendListToRegions( - "ObjectSelect", - packAgentAndSessionID, - packObjectLocalID, + sendListToRegions( + "ObjectSelect", + packAgentAndSessionID, + packObjectLocalID, logNoOp, - NULL, - SEND_INDIVIDUALS); + NULL, + SEND_INDIVIDUALS); } // static void LLSelectMgr::packHingeHead(void *user_data) { - U8 *type = (U8 *)user_data; + U8 *type = (U8 *)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - gMessageSystem->nextBlockFast(_PREHASH_JointType); - gMessageSystem->addU8Fast(_PREHASH_Type, *type ); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gMessageSystem->nextBlockFast(_PREHASH_JointType); + gMessageSystem->addU8Fast(_PREHASH_Type, *type ); } void LLSelectMgr::selectionDump() { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - object->dump(); - return true; - } - } func; - getSelection()->applyToObjects(&func); + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + object->dump(); + return true; + } + } func; + getSelection()->applyToObjects(&func); } void LLSelectMgr::saveSelectedObjectColors() { - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->saveColors(); - return true; - } - } func; - getSelection()->applyToNodes(&func); + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->saveColors(); + return true; + } + } func; + getSelection()->applyToNodes(&func); } void LLSelectMgr::saveSelectedShinyColors() { - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->saveShinyColors(); - return true; - } - } func; - getSelection()->applyToNodes(&func); + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->saveShinyColors(); + return true; + } + } func; + getSelection()->applyToNodes(&func); } void LLSelectMgr::saveSelectedObjectTextures() { - // invalidate current selection so we update saved textures - struct f : public LLSelectedNodeFunctor - { - virtual bool apply(LLSelectNode* node) - { - node->mValid = FALSE; - return true; - } - } func; - getSelection()->applyToNodes(&func); + // invalidate current selection so we update saved textures + struct f : public LLSelectedNodeFunctor + { + virtual bool apply(LLSelectNode* node) + { + node->mValid = FALSE; + return true; + } + } func; + getSelection()->applyToNodes(&func); - // request object properties message to get updated permissions data - sendSelect(); + // request object properties message to get updated permissions data + sendSelect(); } @@ -5200,24 +5200,24 @@ void LLSelectMgr::saveSelectedObjectTextures() // also need to know to which simulator to send update message void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) { - if (mSelectedObjects->isEmpty()) - { - // nothing selected, so nothing to save - return; - } - - struct f : public LLSelectedNodeFunctor - { - EActionType mActionType; - LLSelectMgr* mManager; - f(EActionType a, LLSelectMgr* p) : mActionType(a), mManager(p) {} - virtual bool apply(LLSelectNode* selectNode) - { - LLViewerObject* object = selectNode->getObject(); - if (!object) - { - return true; // skip - } + if (mSelectedObjects->isEmpty()) + { + // nothing selected, so nothing to save + return; + } + + struct f : public LLSelectedNodeFunctor + { + EActionType mActionType; + LLSelectMgr* mManager; + f(EActionType a, LLSelectMgr* p) : mActionType(a), mManager(p) {} + virtual bool apply(LLSelectNode* selectNode) + { + LLViewerObject* object = selectNode->getObject(); + if (!object) + { + return true; // skip + } if (selectNode->mSelectedGLTFNode != -1) { @@ -5269,235 +5269,235 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) selectNode->mSavedScale = object->getScale(); selectNode->saveTextureScaleRatios(mManager->mTextureChannel); } - return true; - } - } func(action_type, this); - getSelection()->applyToNodes(&func); - - mSavedSelectionBBox = getBBoxOfSelection(); + return true; + } + } func(action_type, this); + getSelection()->applyToNodes(&func); + + mSavedSelectionBBox = getBBoxOfSelection(); } struct LLSelectMgrApplyFlags : public LLSelectedObjectFunctor { - LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {} - U32 mFlags; - BOOL mState; - virtual bool apply(LLViewerObject* object) - { - if ( object->permModify()) - { - if (object->isRoot()) // don't send for child objects - { - object->setFlags( mFlags, mState); - } - else if (FLAGS_WORLD & mFlags && ((LLViewerObject*)object->getRoot())->isSelected()) - { - // FLAGS_WORLD are shared by all items in linkset - object->setFlagsWithoutUpdate(FLAGS_WORLD & mFlags, mState); - } - }; - return true; - } + LLSelectMgrApplyFlags(U32 flags, BOOL state) : mFlags(flags), mState(state) {} + U32 mFlags; + BOOL mState; + virtual bool apply(LLViewerObject* object) + { + if ( object->permModify()) + { + if (object->isRoot()) // don't send for child objects + { + object->setFlags( mFlags, mState); + } + else if (FLAGS_WORLD & mFlags && ((LLViewerObject*)object->getRoot())->isSelected()) + { + // FLAGS_WORLD are shared by all items in linkset + object->setFlagsWithoutUpdate(FLAGS_WORLD & mFlags, mState); + } + }; + return true; + } }; void LLSelectMgr::selectionUpdatePhysics(BOOL physics) { - LLSelectMgrApplyFlags func( FLAGS_USE_PHYSICS, physics); - getSelection()->applyToObjects(&func); + LLSelectMgrApplyFlags func( FLAGS_USE_PHYSICS, physics); + getSelection()->applyToObjects(&func); } void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary) { - LLSelectMgrApplyFlags func( FLAGS_TEMPORARY_ON_REZ, is_temporary); - getSelection()->applyToObjects(&func); + LLSelectMgrApplyFlags func( FLAGS_TEMPORARY_ON_REZ, is_temporary); + getSelection()->applyToObjects(&func); } void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom) { - LLSelectMgrApplyFlags func( FLAGS_PHANTOM, is_phantom); - getSelection()->applyToObjects(&func); + LLSelectMgrApplyFlags func( FLAGS_PHANTOM, is_phantom); + getSelection()->applyToObjects(&func); } //---------------------------------------------------------------------- // Helpful packing functions for sendObjectMessage() //---------------------------------------------------------------------- -// static +// static void LLSelectMgr::packAgentIDAndSessionAndAttachment( void *user_data) { - U8 *attachment_point = (U8*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addU8Fast(_PREHASH_AttachmentPoint, *attachment_point); + U8 *attachment_point = (U8*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addU8Fast(_PREHASH_AttachmentPoint, *attachment_point); } // static -void LLSelectMgr::packAgentID( void *user_data) +void LLSelectMgr::packAgentID( void *user_data) { - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); } // static void LLSelectMgr::packAgentAndSessionID(void* user_data) { - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); } // static void LLSelectMgr::packAgentAndGroupID(void* user_data) { - LLOwnerData *data = (LLOwnerData *)user_data; + LLOwnerData *data = (LLOwnerData *)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, data->owner_id ); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id ); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, data->owner_id ); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, data->group_id ); } // static void LLSelectMgr::packAgentAndSessionAndGroupID(void* user_data) { - LLUUID* group_idp = (LLUUID*) user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, *group_idp); + LLUUID* group_idp = (LLUUID*) user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, *group_idp); } // static void LLSelectMgr::packDuplicateHeader(void* data) { - LLUUID group_id(gAgent.getGroupID()); - packAgentAndSessionAndGroupID(&group_id); + LLUUID group_id(gAgent.getGroupID()); + packAgentAndSessionAndGroupID(&group_id); - LLDuplicateData* dup_data = (LLDuplicateData*) data; + LLDuplicateData* dup_data = (LLDuplicateData*) data; - gMessageSystem->nextBlockFast(_PREHASH_SharedData); - gMessageSystem->addVector3Fast(_PREHASH_Offset, dup_data->offset); - gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, dup_data->flags); + gMessageSystem->nextBlockFast(_PREHASH_SharedData); + gMessageSystem->addVector3Fast(_PREHASH_Offset, dup_data->offset); + gMessageSystem->addU32Fast(_PREHASH_DuplicateFlags, dup_data->flags); } // static void LLSelectMgr::packDeleteHeader(void* userdata) { - BOOL force = (BOOL)(intptr_t)userdata; + BOOL force = (BOOL)(intptr_t)userdata; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addBOOLFast(_PREHASH_Force, force); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addBOOLFast(_PREHASH_Force, force); } // static void LLSelectMgr::packAgentGroupAndCatID(void* user_data) { - LLBuyData* buy = (LLBuyData*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - gMessageSystem->addUUIDFast(_PREHASH_CategoryID, buy->mCategoryID); + LLBuyData* buy = (LLBuyData*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->addUUIDFast(_PREHASH_CategoryID, buy->mCategoryID); } //static void LLSelectMgr::packDeRezHeader(void* user_data) { - LLDeRezInfo* info = (LLDeRezInfo*)user_data; - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); - gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - gMessageSystem->addU8Fast(_PREHASH_Destination, (U8)info->mDestination); - gMessageSystem->addUUIDFast(_PREHASH_DestinationID, info->mDestinationID); - LLUUID tid; - tid.generate(); - gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); - const U8 PACKET = 1; - gMessageSystem->addU8Fast(_PREHASH_PacketCount, PACKET); - gMessageSystem->addU8Fast(_PREHASH_PacketNumber, PACKET); -} - -// static + LLDeRezInfo* info = (LLDeRezInfo*)user_data; + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_AgentBlock); + gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + gMessageSystem->addU8Fast(_PREHASH_Destination, (U8)info->mDestination); + gMessageSystem->addUUIDFast(_PREHASH_DestinationID, info->mDestinationID); + LLUUID tid; + tid.generate(); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, tid); + const U8 PACKET = 1; + gMessageSystem->addU8Fast(_PREHASH_PacketCount, PACKET); + gMessageSystem->addU8Fast(_PREHASH_PacketNumber, PACKET); +} + +// static void LLSelectMgr::packObjectID(LLSelectNode* node, void *user_data) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_ObjectID, node->getObject()->mID ); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_ObjectID, node->getObject()->mID ); } void LLSelectMgr::packObjectIDAndRotation(LLSelectNode* node, void *user_data) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addQuatFast(_PREHASH_Rotation, node->getObject()->getRotation()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addQuatFast(_PREHASH_Rotation, node->getObject()->getRotation()); } void LLSelectMgr::packObjectClickAction(LLSelectNode* node, void *user_data) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addU8("ClickAction", node->getObject()->getClickAction()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addU8("ClickAction", node->getObject()->getClickAction()); } void LLSelectMgr::packObjectIncludeInSearch(LLSelectNode* node, void *user_data) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); - gMessageSystem->addBOOL("IncludeInSearch", node->getObject()->getIncludeInSearch()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID() ); + gMessageSystem->addBOOL("IncludeInSearch", node->getObject()->getIncludeInSearch()); } // static void LLSelectMgr::packObjectLocalID(LLSelectNode* node, void *) { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); } // static void LLSelectMgr::packObjectName(LLSelectNode* node, void* user_data) { - const std::string* name = (const std::string*)user_data; - if(!name->empty()) - { - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - gMessageSystem->addStringFast(_PREHASH_Name, *name); - } + const std::string* name = (const std::string*)user_data; + if(!name->empty()) + { + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Name, *name); + } } // static void LLSelectMgr::packObjectDescription(LLSelectNode* node, void* user_data) { - const std::string* desc = (const std::string*)user_data; - if(desc) - { // Empty (non-null, but zero length) descriptions are OK - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - gMessageSystem->addStringFast(_PREHASH_Description, *desc); - } + const std::string* desc = (const std::string*)user_data; + if(desc) + { // Empty (non-null, but zero length) descriptions are OK + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + gMessageSystem->addStringFast(_PREHASH_Description, *desc); + } } // static void LLSelectMgr::packObjectCategory(LLSelectNode* node, void* user_data) { - LLCategory* category = (LLCategory*)user_data; - if(!category) return; - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - category->packMessage(gMessageSystem); + LLCategory* category = (LLCategory*)user_data; + if(!category) return; + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + category->packMessage(gMessageSystem); } // static void LLSelectMgr::packObjectSaleInfo(LLSelectNode* node, void* user_data) { - LLSaleInfo* sale_info = (LLSaleInfo*)user_data; - if(!sale_info) return; - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); - sale_info->packMessage(gMessageSystem); + LLSaleInfo* sale_info = (LLSaleInfo*)user_data; + if(!sale_info) return; + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_LocalID, node->getObject()->getLocalID()); + sale_info->packMessage(gMessageSystem); } // static @@ -5510,46 +5510,46 @@ void LLSelectMgr::packShape(LLSelectNode* node, void *user_data) { } -// static +// static void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data) { - LLPermData *data = (LLPermData *)user_data; + LLPermData *data = (LLPermData *)user_data; - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, node->getObject()->getLocalID()); - gMessageSystem->addU8Fast(_PREHASH_Field, data->mField); - gMessageSystem->addBOOLFast(_PREHASH_Set, data->mSet); - gMessageSystem->addU32Fast(_PREHASH_Mask, data->mMask); + gMessageSystem->addU8Fast(_PREHASH_Field, data->mField); + gMessageSystem->addBOOLFast(_PREHASH_Set, data->mSet); + gMessageSystem->addU32Fast(_PREHASH_Mask, data->mMask); } // Utility function to send some information to every region containing // an object on the selection list. We want to do this to reduce the total // number of packets sent by the viewer. void LLSelectMgr::sendListToRegions(const std::string& message_name, - void (*pack_header)(void *user_data), - void (*pack_body)(LLSelectNode* node, void *user_data), - void (*log_func)(LLSelectNode* node, void *user_data), - void *user_data, - ESendType send_type) + void (*pack_header)(void *user_data), + void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), + void *user_data, + ESendType send_type) { sendListToRegions(mSelectedObjects, message_name, pack_header, pack_body, log_func, user_data, send_type); } void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle, - const std::string& message_name, - void (*pack_header)(void *user_data), - void (*pack_body)(LLSelectNode* node, void *user_data), - void (*log_func)(LLSelectNode* node, void *user_data), - void *user_data, - ESendType send_type) + const std::string& message_name, + void (*pack_header)(void *user_data), + void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), + void *user_data, + ESendType send_type) { - LLSelectNode* node; - LLSelectNode* linkset_root = NULL; - LLViewerRegion* last_region; - LLViewerRegion* current_region; - S32 objects_in_this_packet = 0; + LLSelectNode* node; + LLSelectNode* linkset_root = NULL; + LLViewerRegion* last_region; + LLViewerRegion* current_region; + S32 objects_in_this_packet = 0; - bool link_operation = message_name == "ObjectLink"; + bool link_operation = message_name == "ObjectLink"; if (mAllowSelectAvatar) { @@ -5573,164 +5573,164 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle, resetObjectOverrides(selected_handle); } - std::queue nodes_to_send; - - struct push_all : public LLSelectedNodeFunctor - { - std::queue& nodes_to_send; - push_all(std::queue& n) : nodes_to_send(n) {} - virtual bool apply(LLSelectNode* node) - { - if (node->getObject()) - { - nodes_to_send.push(node); - } - return true; - } - }; - struct push_some : public LLSelectedNodeFunctor - { - std::queue& nodes_to_send; - bool mRoots; - push_some(std::queue& n, bool roots) : nodes_to_send(n), mRoots(roots) {} - virtual bool apply(LLSelectNode* node) - { - if (node->getObject()) - { - BOOL is_root = node->getObject()->isRootEdit(); - if ((mRoots && is_root) || (!mRoots && !is_root)) - { - nodes_to_send.push(node); - } - } - return true; - } - }; - struct push_all pushall(nodes_to_send); - struct push_some pushroots(nodes_to_send, TRUE); - struct push_some pushnonroots(nodes_to_send, FALSE); - - switch(send_type) - { - case SEND_ONLY_ROOTS: - if(message_name == "ObjectBuy") - selected_handle->applyToRootNodes(&pushroots); - else - selected_handle->applyToRootNodes(&pushall); - - break; - case SEND_INDIVIDUALS: - selected_handle->applyToNodes(&pushall); - break; - case SEND_ROOTS_FIRST: - // first roots... - selected_handle->applyToNodes(&pushroots); - // then children... - selected_handle->applyToNodes(&pushnonroots); - break; - case SEND_CHILDREN_FIRST: - // first children... - selected_handle->applyToNodes(&pushnonroots); - // then roots... - selected_handle->applyToNodes(&pushroots); - break; - - default: - LL_ERRS() << "Bad send type " << send_type << " passed to SendListToRegions()" << LL_ENDL; - } - - // bail if nothing selected - if (nodes_to_send.empty()) - { - return; - } - - node = nodes_to_send.front(); - nodes_to_send.pop(); - - // cache last region information - current_region = node->getObject()->getRegion(); - - // Start duplicate message - // CRO: this isn't - gMessageSystem->newMessage(message_name.c_str()); - (*pack_header)(user_data); - - // For each object - while (node != NULL) - { - // remember the last region, look up the current one - last_region = current_region; - current_region = node->getObject()->getRegion(); - - // if to same simulator and message not too big - if ((current_region == last_region) - && (! gMessageSystem->isSendFull(NULL)) - && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) - { - if (link_operation && linkset_root == NULL) - { - // linksets over 254 will be split into multiple messages, - // but we need to provide same root for all messages or we will get separate linksets - linkset_root = node; - } - // add another instance of the body of the data - (*pack_body)(node, user_data); + std::queue nodes_to_send; + + struct push_all : public LLSelectedNodeFunctor + { + std::queue& nodes_to_send; + push_all(std::queue& n) : nodes_to_send(n) {} + virtual bool apply(LLSelectNode* node) + { + if (node->getObject()) + { + nodes_to_send.push(node); + } + return true; + } + }; + struct push_some : public LLSelectedNodeFunctor + { + std::queue& nodes_to_send; + bool mRoots; + push_some(std::queue& n, bool roots) : nodes_to_send(n), mRoots(roots) {} + virtual bool apply(LLSelectNode* node) + { + if (node->getObject()) + { + BOOL is_root = node->getObject()->isRootEdit(); + if ((mRoots && is_root) || (!mRoots && !is_root)) + { + nodes_to_send.push(node); + } + } + return true; + } + }; + struct push_all pushall(nodes_to_send); + struct push_some pushroots(nodes_to_send, TRUE); + struct push_some pushnonroots(nodes_to_send, FALSE); + + switch(send_type) + { + case SEND_ONLY_ROOTS: + if(message_name == "ObjectBuy") + selected_handle->applyToRootNodes(&pushroots); + else + selected_handle->applyToRootNodes(&pushall); + + break; + case SEND_INDIVIDUALS: + selected_handle->applyToNodes(&pushall); + break; + case SEND_ROOTS_FIRST: + // first roots... + selected_handle->applyToNodes(&pushroots); + // then children... + selected_handle->applyToNodes(&pushnonroots); + break; + case SEND_CHILDREN_FIRST: + // first children... + selected_handle->applyToNodes(&pushnonroots); + // then roots... + selected_handle->applyToNodes(&pushroots); + break; + + default: + LL_ERRS() << "Bad send type " << send_type << " passed to SendListToRegions()" << LL_ENDL; + } + + // bail if nothing selected + if (nodes_to_send.empty()) + { + return; + } + + node = nodes_to_send.front(); + nodes_to_send.pop(); + + // cache last region information + current_region = node->getObject()->getRegion(); + + // Start duplicate message + // CRO: this isn't + gMessageSystem->newMessage(message_name.c_str()); + (*pack_header)(user_data); + + // For each object + while (node != NULL) + { + // remember the last region, look up the current one + last_region = current_region; + current_region = node->getObject()->getRegion(); + + // if to same simulator and message not too big + if ((current_region == last_region) + && (! gMessageSystem->isSendFull(NULL)) + && (objects_in_this_packet < MAX_OBJECTS_PER_PACKET)) + { + if (link_operation && linkset_root == NULL) + { + // linksets over 254 will be split into multiple messages, + // but we need to provide same root for all messages or we will get separate linksets + linkset_root = node; + } + // add another instance of the body of the data + (*pack_body)(node, user_data); // do any related logging (*log_func)(node, user_data); - ++objects_in_this_packet; - - // and on to the next object - if(nodes_to_send.empty()) - { - node = NULL; - } - else - { - node = nodes_to_send.front(); - nodes_to_send.pop(); - } - } - else - { - // otherwise send current message and start new one - gMessageSystem->sendReliable( last_region->getHost()); - objects_in_this_packet = 0; - - gMessageSystem->newMessage(message_name.c_str()); - (*pack_header)(user_data); - - if (linkset_root != NULL) - { - if (current_region != last_region) - { - // root should be in one region with the child, reset it - linkset_root = NULL; - } - else - { - // add root instance into new message - (*pack_body)(linkset_root, user_data); - ++objects_in_this_packet; - } - } - - // don't move to the next object, we still need to add the - // body data. - } - } - - // flush messages - if (gMessageSystem->getCurrentSendTotal() > 0) - { - gMessageSystem->sendReliable( current_region->getHost()); - } - else - { - gMessageSystem->clearMessage(); - } - - // LL_INFOS() << "sendListToRegions " << message_name << " obj " << objects_sent << " pkt " << packets_sent << LL_ENDL; + ++objects_in_this_packet; + + // and on to the next object + if(nodes_to_send.empty()) + { + node = NULL; + } + else + { + node = nodes_to_send.front(); + nodes_to_send.pop(); + } + } + else + { + // otherwise send current message and start new one + gMessageSystem->sendReliable( last_region->getHost()); + objects_in_this_packet = 0; + + gMessageSystem->newMessage(message_name.c_str()); + (*pack_header)(user_data); + + if (linkset_root != NULL) + { + if (current_region != last_region) + { + // root should be in one region with the child, reset it + linkset_root = NULL; + } + else + { + // add root instance into new message + (*pack_body)(linkset_root, user_data); + ++objects_in_this_packet; + } + } + + // don't move to the next object, we still need to add the + // body data. + } + } + + // flush messages + if (gMessageSystem->getCurrentSendTotal() > 0) + { + gMessageSystem->sendReliable( current_region->getHost()); + } + else + { + gMessageSystem->clearMessage(); + } + + // LL_INFOS() << "sendListToRegions " << message_name << " obj " << objects_sent << " pkt " << packets_sent << LL_ENDL; } @@ -5740,166 +5740,166 @@ void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle, void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object) { - LLMessageSystem* msg = gMessageSystem; + LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_RequestFlags, 0x0 ); - msg->addUUIDFast(_PREHASH_ObjectID, object->mID ); + msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_RequestFlags, 0x0 ); + msg->addUUIDFast(_PREHASH_ObjectID, object->mID ); - LLViewerRegion* regionp = object->getRegion(); - msg->sendReliable( regionp->getHost() ); + LLViewerRegion* regionp = object->getRegion(); + msg->sendReliable( regionp->getHost() ); } // static void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data) { - S32 i; - S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData); - for (i = 0; i < count; i++) - { - LLUUID id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i); - - LLUUID creator_id; - LLUUID owner_id; - LLUUID group_id; - LLUUID last_owner_id; - U64 creation_date; - LLUUID extra_id; - U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; - LLSaleInfo sale_info; - LLCategory category; - LLAggregatePermissions ag_perms; - LLAggregatePermissions ag_texture_perms; - LLAggregatePermissions ag_texture_perms_owner; - - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_CreatorID, creator_id, i); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, i); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id, i); - msg->getU64Fast(_PREHASH_ObjectData, _PREHASH_CreationDate, creation_date, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_GroupMask, group_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask, i); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask, i); - sale_info.unpackMultiMessage(msg, _PREHASH_ObjectData, i); - - ag_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePerms, i); - ag_texture_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTextures, i); - ag_texture_perms_owner.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTexturesOwner, i); - category.unpackMultiMessage(msg, _PREHASH_ObjectData, i); - - S16 inv_serial = 0; - msg->getS16Fast(_PREHASH_ObjectData, _PREHASH_InventorySerial, inv_serial, i); - - LLUUID item_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ItemID, item_id, i); - LLUUID folder_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FolderID, folder_id, i); - LLUUID from_task_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FromTaskID, from_task_id, i); - - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i); - - std::string name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name, i); - std::string desc; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc, i); - - std::string touch_name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, touch_name, i); - std::string sit_name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i); - - //unpack TE IDs - uuid_vec_t texture_ids; - S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID); - if (size > 0) - { - S8 packed_buffer[SELECT_MAX_TES * UUID_BYTES]; - msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureID, packed_buffer, 0, i, SELECT_MAX_TES * UUID_BYTES); - - for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES) - { - LLUUID tid; - memcpy(tid.mData, packed_buffer + buf_offset, UUID_BYTES); /* Flawfinder: ignore */ - texture_ids.push_back(tid); - } - } - - - // Iterate through nodes at end, since it can be on both the regular AND hover list - struct f : public LLSelectedNodeFunctor - { - LLUUID mID; - f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mID == mID); - } - } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); - - if (!node) - { - LL_WARNS() << "Couldn't find object " << id << " selected." << LL_ENDL; - } - else - { + S32 i; + S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData); + for (i = 0; i < count; i++) + { + LLUUID id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i); + + LLUUID creator_id; + LLUUID owner_id; + LLUUID group_id; + LLUUID last_owner_id; + U64 creation_date; + LLUUID extra_id; + U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; + LLSaleInfo sale_info; + LLCategory category; + LLAggregatePermissions ag_perms; + LLAggregatePermissions ag_texture_perms; + LLAggregatePermissions ag_texture_perms_owner; + + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_CreatorID, creator_id, i); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, i); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id, i); + msg->getU64Fast(_PREHASH_ObjectData, _PREHASH_CreationDate, creation_date, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_GroupMask, group_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask, i); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask, i); + sale_info.unpackMultiMessage(msg, _PREHASH_ObjectData, i); + + ag_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePerms, i); + ag_texture_perms.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTextures, i); + ag_texture_perms_owner.unpackMessage(msg, _PREHASH_ObjectData, _PREHASH_AggregatePermTexturesOwner, i); + category.unpackMultiMessage(msg, _PREHASH_ObjectData, i); + + S16 inv_serial = 0; + msg->getS16Fast(_PREHASH_ObjectData, _PREHASH_InventorySerial, inv_serial, i); + + LLUUID item_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ItemID, item_id, i); + LLUUID folder_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FolderID, folder_id, i); + LLUUID from_task_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FromTaskID, from_task_id, i); + + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i); + + std::string name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name, i); + std::string desc; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc, i); + + std::string touch_name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, touch_name, i); + std::string sit_name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i); + + //unpack TE IDs + uuid_vec_t texture_ids; + S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID); + if (size > 0) + { + S8 packed_buffer[SELECT_MAX_TES * UUID_BYTES]; + msg->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureID, packed_buffer, 0, i, SELECT_MAX_TES * UUID_BYTES); + + for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES) + { + LLUUID tid; + memcpy(tid.mData, packed_buffer + buf_offset, UUID_BYTES); /* Flawfinder: ignore */ + texture_ids.push_back(tid); + } + } + + + // Iterate through nodes at end, since it can be on both the regular AND hover list + struct f : public LLSelectedNodeFunctor + { + LLUUID mID; + f(const LLUUID& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mID == mID); + } + } func(id); + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); + + if (!node) + { + LL_WARNS() << "Couldn't find object " << id << " selected." << LL_ENDL; + } + else + { // save texture data as soon as we get texture perms first time bool save_textures = !node->mValid; - if (node->mInventorySerial != inv_serial && node->getObject()) - { - node->getObject()->dirtyInventory(); + if (node->mInventorySerial != inv_serial && node->getObject()) + { + node->getObject()->dirtyInventory(); // Even if this isn't object's first udpate, inventory changed // and some of the applied textures might have been in inventory // so update texture list. save_textures = true; - } - - if (save_textures) - { - BOOL can_copy = FALSE; - BOOL can_transfer = FALSE; - - LLAggregatePermissions::EValue value = LLAggregatePermissions::AP_NONE; - if(node->getObject()->permYouOwner()) - { - value = ag_texture_perms_owner.getValue(PERM_COPY); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_copy = TRUE; - } - value = ag_texture_perms_owner.getValue(PERM_TRANSFER); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_transfer = TRUE; - } - } - else - { - value = ag_texture_perms.getValue(PERM_COPY); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_copy = TRUE; - } - value = ag_texture_perms.getValue(PERM_TRANSFER); - if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) - { - can_transfer = TRUE; - } - } - - if (can_copy && can_transfer) - { - node->saveTextures(texture_ids); - } + } + + if (save_textures) + { + BOOL can_copy = FALSE; + BOOL can_transfer = FALSE; + + LLAggregatePermissions::EValue value = LLAggregatePermissions::AP_NONE; + if(node->getObject()->permYouOwner()) + { + value = ag_texture_perms_owner.getValue(PERM_COPY); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_copy = TRUE; + } + value = ag_texture_perms_owner.getValue(PERM_TRANSFER); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_transfer = TRUE; + } + } + else + { + value = ag_texture_perms.getValue(PERM_COPY); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_copy = TRUE; + } + value = ag_texture_perms.getValue(PERM_TRANSFER); + if (value == LLAggregatePermissions::AP_EMPTY || value == LLAggregatePermissions::AP_ALL) + { + can_transfer = TRUE; + } + } + + if (can_copy && can_transfer) + { + node->saveTextures(texture_ids); + } if (can_copy && can_transfer && node->getObject()->getVolume()) { @@ -5930,572 +5930,572 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data // might need to be moved to LLGLTFMaterialOverrideDispatchHandler node->saveGLTFMaterials(material_ids, override_materials); } - } - - node->mValid = TRUE; - node->mPermissions->init(creator_id, owner_id, - last_owner_id, group_id); - node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); - node->mCreationDate = creation_date; - node->mItemID = item_id; - node->mFolderID = folder_id; - node->mFromTaskID = from_task_id; - node->mName.assign(name); - node->mDescription.assign(desc); - node->mSaleInfo = sale_info; - node->mAggregatePerm = ag_perms; - node->mAggregateTexturePerm = ag_texture_perms; - node->mAggregateTexturePermOwner = ag_texture_perms_owner; - node->mCategory = category; - node->mInventorySerial = inv_serial; - node->mSitName.assign(sit_name); - node->mTouchName.assign(touch_name); - } - } - - dialog_refresh_all(); - - // hack for left-click buy object - LLToolPie::selectionPropertiesReceived(); -} + } + + node->mValid = TRUE; + node->mPermissions->init(creator_id, owner_id, + last_owner_id, group_id); + node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); + node->mCreationDate = creation_date; + node->mItemID = item_id; + node->mFolderID = folder_id; + node->mFromTaskID = from_task_id; + node->mName.assign(name); + node->mDescription.assign(desc); + node->mSaleInfo = sale_info; + node->mAggregatePerm = ag_perms; + node->mAggregateTexturePerm = ag_texture_perms; + node->mAggregateTexturePermOwner = ag_texture_perms_owner; + node->mCategory = category; + node->mInventorySerial = inv_serial; + node->mSitName.assign(sit_name); + node->mTouchName.assign(touch_name); + } + } + + dialog_refresh_all(); + + // hack for left-click buy object + LLToolPie::selectionPropertiesReceived(); +} // static void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data) { - LLUUID id; - - U32 request_flags; - LLUUID creator_id; - LLUUID owner_id; - LLUUID group_id; - LLUUID extra_id; - U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; - LLSaleInfo sale_info; - LLCategory category; - - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags, request_flags ); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id ); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id ); - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask ); - msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask, group_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask ); - msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask); - sale_info.unpackMessage(msg, _PREHASH_ObjectData); - category.unpackMessage(msg, _PREHASH_ObjectData); - - LLUUID last_owner_id; - msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id ); - - // unpack name & desc - std::string name; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); - - std::string desc; - msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc); - - // the reporter widget askes the server for info about picked objects - if (request_flags & COMPLAINT_REPORT_REQUEST ) - { - LLFloaterReporter *reporterp = LLFloaterReg::findTypedInstance("reporter"); - if (reporterp) - { - LLAvatarName av_name; - LLAvatarNameCache::get(owner_id, &av_name); - reporterp->setPickedObjectProperties(name, av_name.getUserName(), owner_id); - } - } - else if (request_flags & OBJECT_PAY_REQUEST) - { - // check if the owner of the paid object is muted - LLMuteList::getInstance()->autoRemove(owner_id, LLMuteList::AR_MONEY); - } - - // Now look through all of the hovered nodes - struct f : public LLSelectedNodeFunctor - { - LLUUID mID; - f(const LLUUID& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mID == mID); - } - } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func); - - if (node) - { - node->mValid = TRUE; - node->mPermissions->init(LLUUID::null, owner_id, - last_owner_id, group_id); - node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); - node->mSaleInfo = sale_info; - node->mCategory = category; - node->mName.assign(name); - node->mDescription.assign(desc); - } - - dialog_refresh_all(); + LLUUID id; + + U32 request_flags; + LLUUID creator_id; + LLUUID owner_id; + LLUUID group_id; + LLUUID extra_id; + U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask; + LLSaleInfo sale_info; + LLCategory category; + + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags, request_flags ); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id ); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id ); + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, group_id ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask, base_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask, owner_mask ); + msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask, group_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask, everyone_mask ); + msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask); + sale_info.unpackMessage(msg, _PREHASH_ObjectData); + category.unpackMessage(msg, _PREHASH_ObjectData); + + LLUUID last_owner_id; + msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id ); + + // unpack name & desc + std::string name; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name); + + std::string desc; + msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc); + + // the reporter widget askes the server for info about picked objects + if (request_flags & COMPLAINT_REPORT_REQUEST ) + { + LLFloaterReporter *reporterp = LLFloaterReg::findTypedInstance("reporter"); + if (reporterp) + { + LLAvatarName av_name; + LLAvatarNameCache::get(owner_id, &av_name); + reporterp->setPickedObjectProperties(name, av_name.getUserName(), owner_id); + } + } + else if (request_flags & OBJECT_PAY_REQUEST) + { + // check if the owner of the paid object is muted + LLMuteList::getInstance()->autoRemove(owner_id, LLMuteList::AR_MONEY); + } + + // Now look through all of the hovered nodes + struct f : public LLSelectedNodeFunctor + { + LLUUID mID; + f(const LLUUID& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mID == mID); + } + } func(id); + LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func); + + if (node) + { + node->mValid = TRUE; + node->mPermissions->init(LLUUID::null, owner_id, + last_owner_id, group_id); + node->mPermissions->initMasks(base_mask, owner_mask, everyone_mask, group_mask, next_owner_mask); + node->mSaleInfo = sale_info; + node->mCategory = category; + node->mName.assign(name); + node->mDescription.assign(desc); + } + + dialog_refresh_all(); } // static void LLSelectMgr::processForceObjectSelect(LLMessageSystem* msg, void**) { - BOOL reset_list; - msg->getBOOL("Header", "ResetList", reset_list); + BOOL reset_list; + msg->getBOOL("Header", "ResetList", reset_list); - if (reset_list) - { - LLSelectMgr::getInstance()->deselectAll(); - } - - LLUUID full_id; - S32 local_id; - LLViewerObject* object; - std::vector objects; - S32 i; - S32 block_count = msg->getNumberOfBlocks("Data"); + if (reset_list) + { + LLSelectMgr::getInstance()->deselectAll(); + } - for (i = 0; i < block_count; i++) - { - msg->getS32("Data", "LocalID", local_id, i); + LLUUID full_id; + S32 local_id; + LLViewerObject* object; + std::vector objects; + S32 i; + S32 block_count = msg->getNumberOfBlocks("Data"); - gObjectList.getUUIDFromLocal(full_id, - local_id, - msg->getSenderIP(), - msg->getSenderPort()); - object = gObjectList.findObject(full_id); - if (object) - { - objects.push_back(object); - } - } + for (i = 0; i < block_count; i++) + { + msg->getS32("Data", "LocalID", local_id, i); + + gObjectList.getUUIDFromLocal(full_id, + local_id, + msg->getSenderIP(), + msg->getSenderPort()); + object = gObjectList.findObject(full_id); + if (object) + { + objects.push_back(object); + } + } - // Don't select, just highlight - LLSelectMgr::getInstance()->highlightObjectAndFamily(objects); + // Don't select, just highlight + LLSelectMgr::getInstance()->highlightObjectAndFamily(objects); } -extern F32 gGLModelView[16]; +extern F32 gGLModelView[16]; void LLSelectMgr::updateSilhouettes() { - S32 num_sils_genned = 0; - - LLVector3d cameraPos = gAgentCamera.getCameraPositionGlobal(); - F32 currentCameraZoom = gAgentCamera.getCurrentCameraBuildOffset(); - - if (!mSilhouetteImagep) - { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI); - } - - mHighlightedObjects->cleanupNodes(); - - if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - object->setChanged(LLXform::SILHOUETTE); - return true; - } - } func; - getSelection()->applyToObjects(&func); - - mLastCameraPos = gAgentCamera.getCameraPositionGlobal(); - } - - std::vector changed_objects; - - updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects); - if (mRectSelectedObjects.size() > 0) - { - //gGLSPipelineSelection.set(); - - //mSilhouetteImagep->bindTexture(); - //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); - - std::set roots; - - // sync mHighlightedObjects with mRectSelectedObjects since the latter is rebuilt every frame and former - // persists from frame to frame to avoid regenerating object silhouettes - // mHighlightedObjects includes all siblings of rect selected objects - - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - - // generate list of roots from current object selection - for (std::set >::iterator iter = mRectSelectedObjects.begin(); - iter != mRectSelectedObjects.end(); iter++) - { - LLViewerObject *objectp = *iter; - if (select_linked_set) - { - LLViewerObject *rootp = (LLViewerObject*)objectp->getRoot(); - roots.insert(rootp); - } - else - { - roots.insert(objectp); - } - } - - // remove highlight nodes not in roots list - std::vector remove_these_nodes; - std::vector remove_these_roots; - - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - if (objectp->isRoot() || !select_linked_set) - { - if (roots.count(objectp) == 0) - { - remove_these_nodes.push_back(node); - } - else - { - remove_these_roots.push_back(objectp); - } - } - else - { - LLViewerObject* rootp = (LLViewerObject*)objectp->getRoot(); - - if (roots.count(rootp) == 0) - { - remove_these_nodes.push_back(node); - } - } - } - - // remove all highlight nodes no longer in rectangle selection - for (std::vector::iterator iter = remove_these_nodes.begin(); - iter != remove_these_nodes.end(); ++iter) - { - LLSelectNode* nodep = *iter; - mHighlightedObjects->removeNode(nodep); - } - - // remove all root objects already being highlighted - for (std::vector::iterator iter = remove_these_roots.begin(); - iter != remove_these_roots.end(); ++iter) - { - LLViewerObject* objectp = *iter; - roots.erase(objectp); - } - - // add all new objects in rectangle selection - for (std::set::iterator iter = roots.begin(); - iter != roots.end(); iter++) - { - LLViewerObject* objectp = *iter; - if (!canSelectObject(objectp)) - { - continue; - } - - LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE); - rect_select_root_node->selectAllTEs(TRUE); - - if (!select_linked_set) - { - rect_select_root_node->mIndividualSelection = TRUE; - } - else - { - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child_objectp = *iter; - - if (!canSelectObject(child_objectp)) - { - continue; - } - - LLSelectNode* rect_select_node = new LLSelectNode(child_objectp, TRUE); - rect_select_node->selectAllTEs(TRUE); - mHighlightedObjects->addNodeAtEnd(rect_select_node); - } - } - - // Add the root last, to preserve order for link operations. - mHighlightedObjects->addNodeAtEnd(rect_select_root_node); - } - - num_sils_genned = 0; - - // render silhouettes for highlighted objects - //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - - // do roots first, then children so that root flags are cleared ASAP - BOOL roots_only = (pass == 0); - BOOL is_root = objectp->isRootEdit(); - if (roots_only != is_root) - { - continue; - } - - if (!node->mSilhouetteExists - || objectp->isChanged(LLXform::SILHOUETTE) - || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) - { - if (num_sils_genned++ < MAX_SILS_PER_FRAME) - { - generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); - changed_objects.push_back(objectp); - } - else if (objectp->isAttachment() && objectp->getRootEdit()->mDrawable.notNull()) - { - //RN: hack for orthogonal projection of HUD attachments - LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); - if (attachment_pt && attachment_pt->getIsHUDAttachment()) - { - LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); - generateSilhouette(node, camera_pos); - } - } - } - //LLColor4 highlight_color; - // - //if (subtracting_from_selection) - //{ - // node->renderOneSilhouette(LLColor4::red); - //} - //else if (!objectp->isSelected()) - //{ - // highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; - // node->renderOneSilhouette(highlight_color); - //} - } - } - //mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D); - } - else - { - mHighlightedObjects->deleteAllNodes(); - } - - for (std::vector::iterator iter = changed_objects.begin(); - iter != changed_objects.end(); ++iter) - { - // clear flags after traversing node list (as child objects need to refer to parent flags, etc) - LLViewerObject* objectp = *iter; - objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE); - } + S32 num_sils_genned = 0; + + LLVector3d cameraPos = gAgentCamera.getCameraPositionGlobal(); + F32 currentCameraZoom = gAgentCamera.getCurrentCameraBuildOffset(); + + if (!mSilhouetteImagep) + { + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI); + } + + mHighlightedObjects->cleanupNodes(); + + if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + object->setChanged(LLXform::SILHOUETTE); + return true; + } + } func; + getSelection()->applyToObjects(&func); + + mLastCameraPos = gAgentCamera.getCameraPositionGlobal(); + } + + std::vector changed_objects; + + updateSelectionSilhouette(mSelectedObjects, num_sils_genned, changed_objects); + if (mRectSelectedObjects.size() > 0) + { + //gGLSPipelineSelection.set(); + + //mSilhouetteImagep->bindTexture(); + //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); + + std::set roots; + + // sync mHighlightedObjects with mRectSelectedObjects since the latter is rebuilt every frame and former + // persists from frame to frame to avoid regenerating object silhouettes + // mHighlightedObjects includes all siblings of rect selected objects + + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + + // generate list of roots from current object selection + for (std::set >::iterator iter = mRectSelectedObjects.begin(); + iter != mRectSelectedObjects.end(); iter++) + { + LLViewerObject *objectp = *iter; + if (select_linked_set) + { + LLViewerObject *rootp = (LLViewerObject*)objectp->getRoot(); + roots.insert(rootp); + } + else + { + roots.insert(objectp); + } + } + + // remove highlight nodes not in roots list + std::vector remove_these_nodes; + std::vector remove_these_roots; + + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + if (objectp->isRoot() || !select_linked_set) + { + if (roots.count(objectp) == 0) + { + remove_these_nodes.push_back(node); + } + else + { + remove_these_roots.push_back(objectp); + } + } + else + { + LLViewerObject* rootp = (LLViewerObject*)objectp->getRoot(); + + if (roots.count(rootp) == 0) + { + remove_these_nodes.push_back(node); + } + } + } + + // remove all highlight nodes no longer in rectangle selection + for (std::vector::iterator iter = remove_these_nodes.begin(); + iter != remove_these_nodes.end(); ++iter) + { + LLSelectNode* nodep = *iter; + mHighlightedObjects->removeNode(nodep); + } + + // remove all root objects already being highlighted + for (std::vector::iterator iter = remove_these_roots.begin(); + iter != remove_these_roots.end(); ++iter) + { + LLViewerObject* objectp = *iter; + roots.erase(objectp); + } + + // add all new objects in rectangle selection + for (std::set::iterator iter = roots.begin(); + iter != roots.end(); iter++) + { + LLViewerObject* objectp = *iter; + if (!canSelectObject(objectp)) + { + continue; + } + + LLSelectNode* rect_select_root_node = new LLSelectNode(objectp, TRUE); + rect_select_root_node->selectAllTEs(TRUE); + + if (!select_linked_set) + { + rect_select_root_node->mIndividualSelection = TRUE; + } + else + { + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child_objectp = *iter; + + if (!canSelectObject(child_objectp)) + { + continue; + } + + LLSelectNode* rect_select_node = new LLSelectNode(child_objectp, TRUE); + rect_select_node->selectAllTEs(TRUE); + mHighlightedObjects->addNodeAtEnd(rect_select_node); + } + } + + // Add the root last, to preserve order for link operations. + mHighlightedObjects->addNodeAtEnd(rect_select_root_node); + } + + num_sils_genned = 0; + + // render silhouettes for highlighted objects + //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + + // do roots first, then children so that root flags are cleared ASAP + BOOL roots_only = (pass == 0); + BOOL is_root = objectp->isRootEdit(); + if (roots_only != is_root) + { + continue; + } + + if (!node->mSilhouetteExists + || objectp->isChanged(LLXform::SILHOUETTE) + || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) + { + if (num_sils_genned++ < MAX_SILS_PER_FRAME) + { + generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); + changed_objects.push_back(objectp); + } + else if (objectp->isAttachment() && objectp->getRootEdit()->mDrawable.notNull()) + { + //RN: hack for orthogonal projection of HUD attachments + LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); + if (attachment_pt && attachment_pt->getIsHUDAttachment()) + { + LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); + generateSilhouette(node, camera_pos); + } + } + } + //LLColor4 highlight_color; + // + //if (subtracting_from_selection) + //{ + // node->renderOneSilhouette(LLColor4::red); + //} + //else if (!objectp->isSelected()) + //{ + // highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; + // node->renderOneSilhouette(highlight_color); + //} + } + } + //mSilhouetteImagep->unbindTexture(0, GL_TEXTURE_2D); + } + else + { + mHighlightedObjects->deleteAllNodes(); + } + + for (std::vector::iterator iter = changed_objects.begin(); + iter != changed_objects.end(); ++iter) + { + // clear flags after traversing node list (as child objects need to refer to parent flags, etc) + LLViewerObject* objectp = *iter; + objectp->clearChanged(LLXform::MOVED | LLXform::SILHOUETTE); + } } void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector& changed_objects) { - if (object_handle->getNumNodes()) - { - //gGLSPipelineSelection.set(); - - //mSilhouetteImagep->bindTexture(); - //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); - - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = object_handle->begin(); - iter != object_handle->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - // do roots first, then children so that root flags are cleared ASAP - BOOL roots_only = (pass == 0); - BOOL is_root = (objectp->isRootEdit()); - if (roots_only != is_root || objectp->mDrawable.isNull()) - { - continue; - } - - if (!node->mSilhouetteExists - || objectp->isChanged(LLXform::SILHOUETTE) - || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) - { - if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible()) - { - generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); - changed_objects.push_back(objectp); - } - else if (objectp->isAttachment()) - { - //RN: hack for orthogonal projection of HUD attachments - LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); - if (attachment_pt && attachment_pt->getIsHUDAttachment()) - { - LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); - generateSilhouette(node, camera_pos); - } - } - } - } - } - } + if (object_handle->getNumNodes()) + { + //gGLSPipelineSelection.set(); + + //mSilhouetteImagep->bindTexture(); + //glAlphaFunc(GL_GREATER, sHighlightAlphaTest); + + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = object_handle->begin(); + iter != object_handle->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + // do roots first, then children so that root flags are cleared ASAP + BOOL roots_only = (pass == 0); + BOOL is_root = (objectp->isRootEdit()); + if (roots_only != is_root || objectp->mDrawable.isNull()) + { + continue; + } + + if (!node->mSilhouetteExists + || objectp->isChanged(LLXform::SILHOUETTE) + || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) + { + if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible()) + { + generateSilhouette(node, LLViewerCamera::getInstance()->getOrigin()); + changed_objects.push_back(objectp); + } + else if (objectp->isAttachment()) + { + //RN: hack for orthogonal projection of HUD attachments + LLViewerJointAttachment* attachment_pt = (LLViewerJointAttachment*)objectp->getRootEdit()->mDrawable->getParent(); + if (attachment_pt && attachment_pt->getIsHUDAttachment()) + { + LLVector3 camera_pos = LLVector3(-10000.f, 0.f, 0.f); + generateSilhouette(node, camera_pos); + } + } + } + } + } + } } void LLSelectMgr::renderSilhouettes(BOOL for_hud) { - if (!mRenderSilhouettes || !mRenderHighlightSelections) - { - return; - } - - gGL.getTexUnit(0)->bind(mSilhouetteImagep); - LLGLSPipelineSelection gls_select; - LLGLEnable blend(GL_BLEND); - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - if (isAgentAvatarValid() && for_hud) - { - LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); - - F32 cur_zoom = gAgentCamera.mHUDCurZoom; - - // set up transform to encompass bounding box of HUD - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.pushUIMatrix(); - gGL.loadUIIdentity(); - gGL.loadIdentity(); - gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame - gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); - gGL.scalef(cur_zoom, cur_zoom, cur_zoom); - } - - bool wireframe_selection = (gFloaterTools && gFloaterTools->getVisible()) || LLSelectMgr::sRenderHiddenSelections; - F32 fogCfx = (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0); - - static LLColor4 sParentColor = LLColor4(sSilhouetteParentColor[VRED], sSilhouetteParentColor[VGREEN], sSilhouetteParentColor[VBLUE], LLSelectMgr::sHighlightAlpha); - static LLColor4 sChildColor = LLColor4(sSilhouetteChildColor[VRED], sSilhouetteChildColor[VGREEN], sSilhouetteChildColor[VBLUE], LLSelectMgr::sHighlightAlpha); - - auto renderMeshSelection_f = [fogCfx, wireframe_selection](LLSelectNode* node, LLViewerObject* objectp, LLColor4 hlColor) - { - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) - { - gDebugProgram.bind(); - } - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - - BOOL is_hud_object = objectp->isHUDAttachment(); - - if (!is_hud_object) - { - gGL.loadIdentity(); - gGL.multMatrix(gGLModelView); - } - - if (objectp->mDrawable->isActive()) - { - gGL.multMatrix((F32*)objectp->getRenderMatrix().mMatrix); - } - else if (!is_hud_object) - { - LLVector3 trans = objectp->getRegion()->getOriginAgent(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - } - - bool bRenderHidenSelection = node->isTransient() ? false : LLSelectMgr::sRenderHiddenSelections; - - - LLVOVolume* vobj = objectp->mDrawable->getVOVolume(); - if (vobj) - { - LLVertexBuffer::unbind(); - gGL.pushMatrix(); - gGL.multMatrix((F32*)vobj->getRelativeXform().mMatrix); - - if (objectp->mDrawable->isState(LLDrawable::RIGGED)) - { - vobj->updateRiggedVolume(true); - } - } - - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces - for (S32 te = 0; te < num_tes; ++te) - { - if (node->isTESelected(te)) - { - objectp->mDrawable->getFace(te)->renderOneWireframe(hlColor, fogCfx, wireframe_selection, bRenderHidenSelection, nullptr != shader); - } - } - - gGL.popMatrix(); - gGL.popMatrix(); - - glLineWidth(1.f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - if (shader) - { - shader->bind(); - } - }; - - if (mSelectedObjects->getNumNodes()) - { - LLUUID inspect_item_id= LLUUID::null; - LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance("inspect"); - if(inspect_instance && inspect_instance->getVisible()) - { - inspect_item_id = inspect_instance->getSelectedUUID(); - } - else - { - LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); - if (panel_task_info) - { - inspect_item_id = panel_task_info->getSelectedUUID(); - } - } - - LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID(); - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - + if (!mRenderSilhouettes || !mRenderHighlightSelections) + { + return; + } + + gGL.getTexUnit(0)->bind(mSilhouetteImagep); + LLGLSPipelineSelection gls_select; + LLGLEnable blend(GL_BLEND); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + + if (isAgentAvatarValid() && for_hud) + { + LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); + + F32 cur_zoom = gAgentCamera.mHUDCurZoom; + + // set up transform to encompass bounding box of HUD + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.pushUIMatrix(); + gGL.loadUIIdentity(); + gGL.loadIdentity(); + gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame + gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); + gGL.scalef(cur_zoom, cur_zoom, cur_zoom); + } + + bool wireframe_selection = (gFloaterTools && gFloaterTools->getVisible()) || LLSelectMgr::sRenderHiddenSelections; + F32 fogCfx = (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0); + + static LLColor4 sParentColor = LLColor4(sSilhouetteParentColor[VRED], sSilhouetteParentColor[VGREEN], sSilhouetteParentColor[VBLUE], LLSelectMgr::sHighlightAlpha); + static LLColor4 sChildColor = LLColor4(sSilhouetteChildColor[VRED], sSilhouetteChildColor[VGREEN], sSilhouetteChildColor[VBLUE], LLSelectMgr::sHighlightAlpha); + + auto renderMeshSelection_f = [fogCfx, wireframe_selection](LLSelectNode* node, LLViewerObject* objectp, LLColor4 hlColor) + { + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + + if (shader) + { + gDebugProgram.bind(); + } + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + + BOOL is_hud_object = objectp->isHUDAttachment(); + + if (!is_hud_object) + { + gGL.loadIdentity(); + gGL.multMatrix(gGLModelView); + } + + if (objectp->mDrawable->isActive()) + { + gGL.multMatrix((F32*)objectp->getRenderMatrix().mMatrix); + } + else if (!is_hud_object) + { + LLVector3 trans = objectp->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + } + + bool bRenderHidenSelection = node->isTransient() ? false : LLSelectMgr::sRenderHiddenSelections; + + + LLVOVolume* vobj = objectp->mDrawable->getVOVolume(); + if (vobj) + { + LLVertexBuffer::unbind(); + gGL.pushMatrix(); + gGL.multMatrix((F32*)vobj->getRelativeXform().mMatrix); + + if (objectp->mDrawable->isState(LLDrawable::RIGGED)) + { + vobj->updateRiggedVolume(true); + } + } + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + objectp->mDrawable->getFace(te)->renderOneWireframe(hlColor, fogCfx, wireframe_selection, bRenderHidenSelection, nullptr != shader); + } + } + + gGL.popMatrix(); + gGL.popMatrix(); + + glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + if (shader) + { + shader->bind(); + } + }; + + if (mSelectedObjects->getNumNodes()) + { + LLUUID inspect_item_id= LLUUID::null; + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance("inspect"); + if(inspect_instance && inspect_instance->getVisible()) + { + inspect_item_id = inspect_instance->getSelectedUUID(); + } + else + { + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + inspect_item_id = panel_task_info->getSelectedUUID(); + } + } + + LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID(); + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + if (getTEMode() && !node->hasSelectedTE()) continue; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; - if (objectp->mDrawable - && objectp->mDrawable->getVOVolume() + if (objectp->mDrawable + && objectp->mDrawable->getVOVolume() && objectp->mDrawable->getVOVolume()->isMesh()) { LLColor4 hlColor = objectp->isRootEdit() ? sParentColor : sChildColor; @@ -6539,145 +6539,145 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) node->renderOneSilhouette(sSilhouetteChildColor); } } - } //for all selected node's - } //for pass - } - - if (mHighlightedObjects->getNumNodes()) - { - // render silhouettes for highlighted objects - BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); - for (S32 pass = 0; pass < 2; pass++) - { - for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); - iter != mHighlightedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* objectp = node->getObject(); - if (!objectp) - continue; - if (objectp->isHUDAttachment() != for_hud) - { - continue; - } - - LLColor4 highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; - if (objectp->mDrawable - && objectp->mDrawable->getVOVolume() - && objectp->mDrawable->getVOVolume()->isMesh()) - { - renderMeshSelection_f(node, objectp, subtracting_from_selection ? LLColor4::red : highlight_color); - } - else if (subtracting_from_selection) - { - node->renderOneSilhouette(LLColor4::red); - } - else if (!objectp->isSelected()) - { - node->renderOneSilhouette(highlight_color); - } - } - } - } - - if (isAgentAvatarValid() && for_hud) - { - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - gGL.popUIMatrix(); - stop_glerror(); - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } //for all selected node's + } //for pass + } + + if (mHighlightedObjects->getNumNodes()) + { + // render silhouettes for highlighted objects + BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); + for (S32 pass = 0; pass < 2; pass++) + { + for (LLObjectSelection::iterator iter = mHighlightedObjects->begin(); + iter != mHighlightedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* objectp = node->getObject(); + if (!objectp) + continue; + if (objectp->isHUDAttachment() != for_hud) + { + continue; + } + + LLColor4 highlight_color = objectp->isRoot() ? sHighlightParentColor : sHighlightChildColor; + if (objectp->mDrawable + && objectp->mDrawable->getVOVolume() + && objectp->mDrawable->getVOVolume()->isMesh()) + { + renderMeshSelection_f(node, objectp, subtracting_from_selection ? LLColor4::red : highlight_color); + } + else if (subtracting_from_selection) + { + node->renderOneSilhouette(LLColor4::red); + } + else if (!objectp->isSelected()) + { + node->renderOneSilhouette(highlight_color); + } + } + } + } + + if (isAgentAvatarValid() && for_hud) + { + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + gGL.popUIMatrix(); + stop_glerror(); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) { - LLViewerObject* objectp = nodep->getObject(); + LLViewerObject* objectp = nodep->getObject(); - if (objectp && objectp->getPCode() == LL_PCODE_VOLUME) - { - ((LLVOVolume*)objectp)->generateSilhouette(nodep, view_point); - } + if (objectp && objectp->getPCode() == LL_PCODE_VOLUME) + { + ((LLVOVolume*)objectp)->generateSilhouette(nodep, view_point); + } } // // Utility classes // LLSelectNode::LLSelectNode(LLViewerObject* object, BOOL glow) -: mObject(object), - mIndividualSelection(FALSE), - mTransient(FALSE), - mValid(FALSE), - mPermissions(new LLPermissions()), - mInventorySerial(0), - mSilhouetteExists(FALSE), - mDuplicated(FALSE), - mTESelectMask(0), - mLastTESelected(0), - mName(LLStringUtil::null), - mDescription(LLStringUtil::null), - mTouchName(LLStringUtil::null), - mSitName(LLStringUtil::null), - mCreationDate(0) -{ - saveColors(); - saveShinyColors(); +: mObject(object), + mIndividualSelection(FALSE), + mTransient(FALSE), + mValid(FALSE), + mPermissions(new LLPermissions()), + mInventorySerial(0), + mSilhouetteExists(FALSE), + mDuplicated(FALSE), + mTESelectMask(0), + mLastTESelected(0), + mName(LLStringUtil::null), + mDescription(LLStringUtil::null), + mTouchName(LLStringUtil::null), + mSitName(LLStringUtil::null), + mCreationDate(0) +{ + saveColors(); + saveShinyColors(); } LLSelectNode::LLSelectNode(const LLSelectNode& nodep) { - mTESelectMask = nodep.mTESelectMask; - mLastTESelected = nodep.mLastTESelected; - - mIndividualSelection = nodep.mIndividualSelection; - - mValid = nodep.mValid; - mTransient = nodep.mTransient; - mPermissions = new LLPermissions(*nodep.mPermissions); - mSaleInfo = nodep.mSaleInfo;; - mAggregatePerm = nodep.mAggregatePerm; - mAggregateTexturePerm = nodep.mAggregateTexturePerm; - mAggregateTexturePermOwner = nodep.mAggregateTexturePermOwner; - mName = nodep.mName; - mDescription = nodep.mDescription; - mCategory = nodep.mCategory; - mInventorySerial = 0; - mSavedPositionLocal = nodep.mSavedPositionLocal; - mSavedPositionGlobal = nodep.mSavedPositionGlobal; - mSavedScale = nodep.mSavedScale; - mSavedRotation = nodep.mSavedRotation; - mDuplicated = nodep.mDuplicated; - mDuplicatePos = nodep.mDuplicatePos; - mDuplicateRot = nodep.mDuplicateRot; - mItemID = nodep.mItemID; - mFolderID = nodep.mFolderID; - mFromTaskID = nodep.mFromTaskID; - mTouchName = nodep.mTouchName; - mSitName = nodep.mSitName; - mCreationDate = nodep.mCreationDate; - - mSilhouetteVertices = nodep.mSilhouetteVertices; - mSilhouetteNormals = nodep.mSilhouetteNormals; - mSilhouetteExists = nodep.mSilhouetteExists; - mObject = nodep.mObject; - - std::vector::const_iterator color_iter; - mSavedColors.clear(); - for (color_iter = nodep.mSavedColors.begin(); color_iter != nodep.mSavedColors.end(); ++color_iter) - { - mSavedColors.push_back(*color_iter); - } - mSavedShinyColors.clear(); - for (color_iter = nodep.mSavedShinyColors.begin(); color_iter != nodep.mSavedShinyColors.end(); ++color_iter) - { - mSavedShinyColors.push_back(*color_iter); - } - - saveTextures(nodep.mSavedTextures); + mTESelectMask = nodep.mTESelectMask; + mLastTESelected = nodep.mLastTESelected; + + mIndividualSelection = nodep.mIndividualSelection; + + mValid = nodep.mValid; + mTransient = nodep.mTransient; + mPermissions = new LLPermissions(*nodep.mPermissions); + mSaleInfo = nodep.mSaleInfo;; + mAggregatePerm = nodep.mAggregatePerm; + mAggregateTexturePerm = nodep.mAggregateTexturePerm; + mAggregateTexturePermOwner = nodep.mAggregateTexturePermOwner; + mName = nodep.mName; + mDescription = nodep.mDescription; + mCategory = nodep.mCategory; + mInventorySerial = 0; + mSavedPositionLocal = nodep.mSavedPositionLocal; + mSavedPositionGlobal = nodep.mSavedPositionGlobal; + mSavedScale = nodep.mSavedScale; + mSavedRotation = nodep.mSavedRotation; + mDuplicated = nodep.mDuplicated; + mDuplicatePos = nodep.mDuplicatePos; + mDuplicateRot = nodep.mDuplicateRot; + mItemID = nodep.mItemID; + mFolderID = nodep.mFolderID; + mFromTaskID = nodep.mFromTaskID; + mTouchName = nodep.mTouchName; + mSitName = nodep.mSitName; + mCreationDate = nodep.mCreationDate; + + mSilhouetteVertices = nodep.mSilhouetteVertices; + mSilhouetteNormals = nodep.mSilhouetteNormals; + mSilhouetteExists = nodep.mSilhouetteExists; + mObject = nodep.mObject; + + std::vector::const_iterator color_iter; + mSavedColors.clear(); + for (color_iter = nodep.mSavedColors.begin(); color_iter != nodep.mSavedColors.end(); ++color_iter) + { + mSavedColors.push_back(*color_iter); + } + mSavedShinyColors.clear(); + for (color_iter = nodep.mSavedShinyColors.begin(); color_iter != nodep.mSavedShinyColors.end(); ++color_iter) + { + mSavedShinyColors.push_back(*color_iter); + } + + saveTextures(nodep.mSavedTextures); saveGLTFMaterials(nodep.mSavedGLTFMaterialIds, nodep.mSavedGLTFOverrideMaterials); } @@ -6701,31 +6701,31 @@ LLSelectNode::~LLSelectNode() } delete mPermissions; - mPermissions = NULL; + mPermissions = NULL; } void LLSelectNode::selectAllTEs(BOOL b) { - mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0; - mLastTESelected = 0; + mTESelectMask = b ? TE_SELECT_MASK_ALL : 0x0; + mLastTESelected = 0; } void LLSelectNode::selectTE(S32 te_index, BOOL selected) { - if (te_index < 0 || te_index >= SELECT_MAX_TES) - { - return; - } - S32 mask = 0x1 << te_index; - if(selected) - { - mTESelectMask |= mask; - } - else - { - mTESelectMask &= ~mask; - } - mLastTESelected = te_index; + if (te_index < 0 || te_index >= SELECT_MAX_TES) + { + return; + } + S32 mask = 0x1 << te_index; + if(selected) + { + mTESelectMask |= mask; + } + else + { + mTESelectMask &= ~mask; + } + mLastTESelected = te_index; } void LLSelectNode::selectGLTFNode(S32 node_index, S32 primitive_index, bool selected) @@ -6735,414 +6735,414 @@ void LLSelectNode::selectGLTFNode(S32 node_index, S32 primitive_index, bool sele return; } - mSelectedGLTFNode = node_index; - mSelectedGLTFPrimitive = primitive_index; -} + mSelectedGLTFNode = node_index; + mSelectedGLTFPrimitive = primitive_index; +} + +BOOL LLSelectNode::isTESelected(S32 te_index) const +{ + if (te_index < 0 || te_index >= mObject->getNumTEs()) + { + return FALSE; + } + return (mTESelectMask & (0x1 << te_index)) != 0; +} + +S32 LLSelectNode::getLastSelectedTE() const +{ + if (!isTESelected(mLastTESelected)) + { + return -1; + } + return mLastTESelected; +} + +LLViewerObject* LLSelectNode::getObject() +{ + if (!mObject) + { + return NULL; + } + else if (mObject->isDead()) + { + mObject = NULL; + } + return mObject; +} + +void LLSelectNode::setObject(LLViewerObject* object) +{ + mObject = object; +} + +void LLSelectNode::saveColors() +{ + if (mObject.notNull()) + { + mSavedColors.clear(); + for (S32 i = 0; i < mObject->getNumTEs(); i++) + { + const LLTextureEntry* tep = mObject->getTE(i); + mSavedColors.push_back(tep->getColor()); + } + } +} + +void LLSelectNode::saveShinyColors() +{ + if (mObject.notNull()) + { + mSavedShinyColors.clear(); + for (S32 i = 0; i < mObject->getNumTEs(); i++) + { + const LLMaterialPtr mat = mObject->getTE(i)->getMaterialParams(); + if (!mat.isNull()) + { + mSavedShinyColors.push_back(mat->getSpecularLightColor()); + } + else + { + mSavedShinyColors.push_back(LLColor4::white); + } + } + } +} + +void LLSelectNode::saveTextures(const uuid_vec_t& textures) +{ + if (mObject.notNull()) + { + mSavedTextures.clear(); + + for (uuid_vec_t::const_iterator texture_it = textures.begin(); + texture_it != textures.end(); ++texture_it) + { + mSavedTextures.push_back(*texture_it); + } + } +} + +void LLSelectNode::saveGLTFMaterials(const uuid_vec_t& materials, const gltf_materials_vec_t& override_materials) +{ + if (mObject.notNull()) + { + mSavedGLTFMaterialIds.clear(); + mSavedGLTFOverrideMaterials.clear(); + + for (uuid_vec_t::const_iterator materials_it = materials.begin(); + materials_it != materials.end(); ++materials_it) + { + mSavedGLTFMaterialIds.push_back(*materials_it); + } + + for (gltf_materials_vec_t::const_iterator mat_it = override_materials.begin(); + mat_it != override_materials.end(); ++mat_it) + { + mSavedGLTFOverrideMaterials.push_back(*mat_it); + } + } +} + +void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) +{ + mTextureScaleRatios.clear(); + + if (mObject.notNull()) + { + + LLVector3 scale = mObject->getScale(); + + for (U8 i = 0; i < mObject->getNumTEs(); i++) + { + F32 diffuse_s = 1.0f; + F32 diffuse_t = 1.0f; + + LLVector3 v; + const LLTextureEntry* tep = mObject->getTE(i); + if (!tep) + continue; + + U32 s_axis = VX; + U32 t_axis = VY; + LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); + + tep->getScale(&diffuse_s,&diffuse_t); + + if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) + { + v.mV[s_axis] = diffuse_s*scale.mV[s_axis]; + v.mV[t_axis] = diffuse_t*scale.mV[t_axis]; + mTextureScaleRatios.push_back(v); + } + else + { + v.mV[s_axis] = diffuse_s/scale.mV[s_axis]; + v.mV[t_axis] = diffuse_t/scale.mV[t_axis]; + mTextureScaleRatios.push_back(v); + } + } + } +} + + +// This implementation should be similar to LLTask::allowOperationOnTask +BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const +{ + // Extract ownership. + BOOL object_is_group_owned = FALSE; + LLUUID object_owner_id; + mPermissions->getOwnership(object_owner_id, object_is_group_owned); + + // Operations on invalid or public objects is not allowed. + if (!mObject || (mObject->isDead()) || !mPermissions->isOwned()) + { + return FALSE; + } + + // The transfer permissions can never be given through proxy. + if (PERM_TRANSFER == op) + { + // The owner of an agent-owned object can transfer to themselves. + if ( !object_is_group_owned + && (gAgent.getID() == object_owner_id) ) + { + return TRUE; + } + else + { + // Otherwise check aggregate permissions. + return mObject->permTransfer(); + } + } + + if (PERM_MOVE == op + || PERM_MODIFY == op) + { + // only owners can move or modify their attachments + // no proxy allowed. + if (mObject->isAttachment() && object_owner_id != gAgent.getID()) + { + return FALSE; + } + } + + // Calculate proxy_agent_id and group_id to use for permissions checks. + // proxy_agent_id may be set to the object owner through group powers. + // group_id can only be set to the object's group, if the agent is in that group. + LLUUID group_id = LLUUID::null; + LLUUID proxy_agent_id = gAgent.getID(); + + // Gods can always operate. + if (gAgent.isGodlike()) + { + return TRUE; + } + + // Check if the agent is in the same group as the object. + LLUUID object_group_id = mPermissions->getGroup(); + if (object_group_id.notNull() && + gAgent.isInGroup(object_group_id)) + { + // Assume the object's group during this operation. + group_id = object_group_id; + } + + // Only allow proxy powers for PERM_COPY if the actual agent can + // receive the item (ie has PERM_TRANSFER permissions). + // NOTE: op == PERM_TRANSFER has already been handled, but if + // that ever changes we need to BLOCK proxy powers for PERM_TRANSFER. DK 03/28/06 + if (PERM_COPY != op || mPermissions->allowTransferTo(gAgent.getID())) + { + // Check if the agent can assume ownership through group proxy or agent-granted proxy. + if ( ( object_is_group_owned + && gAgent.hasPowerInGroup(object_owner_id, group_proxy_power)) + // Only allow proxy for move, modify, and copy. + || ( (PERM_MOVE == op || PERM_MODIFY == op || PERM_COPY == op) + && (!object_is_group_owned + && gAgent.isGrantedProxy(*mPermissions)))) + { + // This agent is able to assume the ownership role for this operation. + proxy_agent_id = object_owner_id; + } + } + + // We now have max ownership information. + if (PERM_OWNER == op) + { + // This this was just a check for ownership, we can now return the answer. + return (proxy_agent_id == object_owner_id ? TRUE : FALSE); + } + + // check permissions to see if the agent can operate + return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); +} + +//----------------------------------------------------------------------------- +// renderOneSilhouette() +//----------------------------------------------------------------------------- +void LLSelectNode::renderOneSilhouette(const LLColor4 &color) +{ + LLViewerObject* objectp = getObject(); + if (!objectp) + { + return; + } + + LLDrawable* drawable = objectp->mDrawable; + if(!drawable) + { + return; + } + + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj && vobj->isMesh()) + { + //This check (if(...)) with assert here just for ensure that this situation will not happens, and can be removed later. For example on the next release. + llassert(!"renderOneWireframe() was removed SL-10194"); + return; + } + + if (!mSilhouetteExists) + { + return; + } -BOOL LLSelectNode::isTESelected(S32 te_index) const -{ - if (te_index < 0 || te_index >= mObject->getNumTEs()) - { - return FALSE; - } - return (mTESelectMask & (0x1 << te_index)) != 0; -} + BOOL is_hud_object = objectp->isHUDAttachment(); -S32 LLSelectNode::getLastSelectedTE() const -{ - if (!isTESelected(mLastTESelected)) - { - return -1; - } - return mLastTESelected; -} + if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) + { + return; + } -LLViewerObject* LLSelectNode::getObject() -{ - if (!mObject) - { - return NULL; - } - else if (mObject->isDead()) - { - mObject = NULL; - } - return mObject; -} -void LLSelectNode::setObject(LLViewerObject* object) -{ - mObject = object; -} + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; -void LLSelectNode::saveColors() -{ - if (mObject.notNull()) - { - mSavedColors.clear(); - for (S32 i = 0; i < mObject->getNumTEs(); i++) - { - const LLTextureEntry* tep = mObject->getTE(i); - mSavedColors.push_back(tep->getColor()); - } - } -} + if (shader) + { //use UI program for selection highlights (texture color modulated by vertex color) + gUIProgram.bind(); + } -void LLSelectNode::saveShinyColors() -{ - if (mObject.notNull()) - { - mSavedShinyColors.clear(); - for (S32 i = 0; i < mObject->getNumTEs(); i++) - { - const LLMaterialPtr mat = mObject->getTE(i)->getMaterialParams(); - if (!mat.isNull()) - { - mSavedShinyColors.push_back(mat->getSpecularLightColor()); - } - else - { - mSavedShinyColors.push_back(LLColor4::white); - } - } - } -} + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.pushUIMatrix(); + gGL.loadUIIdentity(); -void LLSelectNode::saveTextures(const uuid_vec_t& textures) -{ - if (mObject.notNull()) - { - mSavedTextures.clear(); + if (!is_hud_object) + { + gGL.loadIdentity(); + gGL.multMatrix(gGLModelView); + } - for (uuid_vec_t::const_iterator texture_it = textures.begin(); - texture_it != textures.end(); ++texture_it) - { - mSavedTextures.push_back(*texture_it); - } - } -} -void LLSelectNode::saveGLTFMaterials(const uuid_vec_t& materials, const gltf_materials_vec_t& override_materials) -{ - if (mObject.notNull()) + if (drawable->isActive()) { - mSavedGLTFMaterialIds.clear(); - mSavedGLTFOverrideMaterials.clear(); + gGL.multMatrix((F32*) objectp->getRenderMatrix().mMatrix); + } - for (uuid_vec_t::const_iterator materials_it = materials.begin(); - materials_it != materials.end(); ++materials_it) + LLVolume *volume = objectp->getVolume(); + if (volume) + { + F32 silhouette_thickness; + if (isAgentAvatarValid() && is_hud_object) { - mSavedGLTFMaterialIds.push_back(*materials_it); + silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgentCamera.mHUDCurZoom; } - - for (gltf_materials_vec_t::const_iterator mat_it = override_materials.begin(); - mat_it != override_materials.end(); ++mat_it) + else { - mSavedGLTFOverrideMaterials.push_back(*mat_it); + LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition(); + silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()); } - } -} - -void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) -{ - mTextureScaleRatios.clear(); - - if (mObject.notNull()) - { - - LLVector3 scale = mObject->getScale(); - - for (U8 i = 0; i < mObject->getNumTEs(); i++) - { - F32 diffuse_s = 1.0f; - F32 diffuse_t = 1.0f; - - LLVector3 v; - const LLTextureEntry* tep = mObject->getTE(i); - if (!tep) - continue; - - U32 s_axis = VX; - U32 t_axis = VY; - LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); - - tep->getScale(&diffuse_s,&diffuse_t); - - if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) - { - v.mV[s_axis] = diffuse_s*scale.mV[s_axis]; - v.mV[t_axis] = diffuse_t*scale.mV[t_axis]; - mTextureScaleRatios.push_back(v); - } - else - { - v.mV[s_axis] = diffuse_s/scale.mV[s_axis]; - v.mV[t_axis] = diffuse_t/scale.mV[t_axis]; - mTextureScaleRatios.push_back(v); - } - } - } -} + F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); + F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); + F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f); + F32 u_divisor = 1.f / ((F32)(mSilhouetteVertices.size() - 1)); -// This implementation should be similar to LLTask::allowOperationOnTask -BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const -{ - // Extract ownership. - BOOL object_is_group_owned = FALSE; - LLUUID object_owner_id; - mPermissions->getOwnership(object_owner_id, object_is_group_owned); - - // Operations on invalid or public objects is not allowed. - if (!mObject || (mObject->isDead()) || !mPermissions->isOwned()) - { - return FALSE; - } - - // The transfer permissions can never be given through proxy. - if (PERM_TRANSFER == op) - { - // The owner of an agent-owned object can transfer to themselves. - if ( !object_is_group_owned - && (gAgent.getID() == object_owner_id) ) - { - return TRUE; - } - else - { - // Otherwise check aggregate permissions. - return mObject->permTransfer(); - } - } - - if (PERM_MOVE == op - || PERM_MODIFY == op) - { - // only owners can move or modify their attachments - // no proxy allowed. - if (mObject->isAttachment() && object_owner_id != gAgent.getID()) - { - return FALSE; - } - } - - // Calculate proxy_agent_id and group_id to use for permissions checks. - // proxy_agent_id may be set to the object owner through group powers. - // group_id can only be set to the object's group, if the agent is in that group. - LLUUID group_id = LLUUID::null; - LLUUID proxy_agent_id = gAgent.getID(); - - // Gods can always operate. - if (gAgent.isGodlike()) - { - return TRUE; - } - - // Check if the agent is in the same group as the object. - LLUUID object_group_id = mPermissions->getGroup(); - if (object_group_id.notNull() && - gAgent.isInGroup(object_group_id)) - { - // Assume the object's group during this operation. - group_id = object_group_id; - } - - // Only allow proxy powers for PERM_COPY if the actual agent can - // receive the item (ie has PERM_TRANSFER permissions). - // NOTE: op == PERM_TRANSFER has already been handled, but if - // that ever changes we need to BLOCK proxy powers for PERM_TRANSFER. DK 03/28/06 - if (PERM_COPY != op || mPermissions->allowTransferTo(gAgent.getID())) - { - // Check if the agent can assume ownership through group proxy or agent-granted proxy. - if ( ( object_is_group_owned - && gAgent.hasPowerInGroup(object_owner_id, group_proxy_power)) - // Only allow proxy for move, modify, and copy. - || ( (PERM_MOVE == op || PERM_MODIFY == op || PERM_COPY == op) - && (!object_is_group_owned - && gAgent.isGrantedProxy(*mPermissions)))) - { - // This agent is able to assume the ownership role for this operation. - proxy_agent_id = object_owner_id; - } - } - - // We now have max ownership information. - if (PERM_OWNER == op) - { - // This this was just a check for ownership, we can now return the answer. - return (proxy_agent_id == object_owner_id ? TRUE : FALSE); - } - - // check permissions to see if the agent can operate - return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); -} + if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) + { + gGL.flush(); + gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); -//----------------------------------------------------------------------------- -// renderOneSilhouette() -//----------------------------------------------------------------------------- -void LLSelectNode::renderOneSilhouette(const LLColor4 &color) -{ - LLViewerObject* objectp = getObject(); - if (!objectp) - { - return; - } - - LLDrawable* drawable = objectp->mDrawable; - if(!drawable) - { - return; - } - - LLVOVolume* vobj = drawable->getVOVolume(); - if (vobj && vobj->isMesh()) - { - //This check (if(...)) with assert here just for ensure that this situation will not happens, and can be removed later. For example on the next release. - llassert(!"renderOneWireframe() was removed SL-10194"); - return; - } - - if (!mSilhouetteExists) - { - return; - } - - BOOL is_hud_object = objectp->isHUDAttachment(); - - if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) - { - return; - } - - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - - if (shader) - { //use UI program for selection highlights (texture color modulated by vertex color) - gUIProgram.bind(); - } - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.pushUIMatrix(); - gGL.loadUIIdentity(); - - if (!is_hud_object) - { - gGL.loadIdentity(); - gGL.multMatrix(gGLModelView); - } - - - if (drawable->isActive()) - { - gGL.multMatrix((F32*) objectp->getRenderMatrix().mMatrix); - } - - LLVolume *volume = objectp->getVolume(); - if (volume) - { - F32 silhouette_thickness; - if (isAgentAvatarValid() && is_hud_object) - { - silhouette_thickness = LLSelectMgr::sHighlightThickness / gAgentCamera.mHUDCurZoom; - } - else - { - LLVector3 view_vector = LLViewerCamera::getInstance()->getOrigin() - objectp->getRenderPosition(); - silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()); - } - F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); - - F32 u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); - F32 v_coord = 1.f - fmod(animationTime * LLSelectMgr::sHighlightVAnim, 1.f); - F32 u_divisor = 1.f / ((F32)(mSilhouetteVertices.size() - 1)); - - if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) - { - gGL.flush(); - gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); gGL.flush(); - gGL.begin(LLRender::LINES); - { - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); - - for(S32 i = 0; i < mSilhouetteVertices.size(); i += 2) - { - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV); - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv(mSilhouetteVertices[i+1].mV); - } - } + gGL.begin(LLRender::LINES); + { + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + + for(S32 i = 0; i < mSilhouetteVertices.size(); i += 2) + { + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv( mSilhouetteVertices[i].mV); + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv(mSilhouetteVertices[i+1].mV); + } + } gGL.end(); - u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); - } - - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.begin(LLRender::TRIANGLES); - { - for(S32 i = 0; i < mSilhouetteVertices.size(); i+=2) - { - if (!mSilhouetteNormals[i].isFinite() || - !mSilhouetteNormals[i+1].isFinite()) - { //skip skewed segments - continue; - } - - LLVector3 v[4]; - LLVector2 tc[4]; - v[0] = mSilhouetteVertices[i] + (mSilhouetteNormals[i] * silhouette_thickness); - tc[0].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); - - v[1] = mSilhouetteVertices[i]; - tc[1].set(u_coord, v_coord); - - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - - v[2] = mSilhouetteVertices[i+1] + (mSilhouetteNormals[i+1] * silhouette_thickness); - tc[2].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); - - v[3] = mSilhouetteVertices[i+1]; - tc[3].set(u_coord,v_coord); - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2fv(tc[0].mV); - gGL.vertex3fv( v[0].mV ); - - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha); - gGL.texCoord2fv( tc[1].mV ); - gGL.vertex3fv( v[1].mV ); - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2fv( tc[2].mV ); - gGL.vertex3fv( v[2].mV ); - - gGL.vertex3fv( v[2].mV ); - - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha); - gGL.texCoord2fv( tc[1].mV ); - gGL.vertex3fv( v[1].mV ); - - gGL.texCoord2fv( tc[3].mV ); - gGL.vertex3fv( v[3].mV ); - } - } - gGL.end(); - gGL.flush(); - } - gGL.popMatrix(); - gGL.popUIMatrix(); - - if (shader) - { - shader->bind(); - } + u_coord = fmod(animationTime * LLSelectMgr::sHighlightUAnim, 1.f); + } + + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.begin(LLRender::TRIANGLES); + { + for(S32 i = 0; i < mSilhouetteVertices.size(); i+=2) + { + if (!mSilhouetteNormals[i].isFinite() || + !mSilhouetteNormals[i+1].isFinite()) + { //skip skewed segments + continue; + } + + LLVector3 v[4]; + LLVector2 tc[4]; + v[0] = mSilhouetteVertices[i] + (mSilhouetteNormals[i] * silhouette_thickness); + tc[0].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); + + v[1] = mSilhouetteVertices[i]; + tc[1].set(u_coord, v_coord); + + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + + v[2] = mSilhouetteVertices[i+1] + (mSilhouetteNormals[i+1] * silhouette_thickness); + tc[2].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); + + v[3] = mSilhouetteVertices[i+1]; + tc[3].set(u_coord,v_coord); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv(tc[0].mV); + gGL.vertex3fv( v[0].mV ); + + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv( tc[1].mV ); + gGL.vertex3fv( v[1].mV ); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv( tc[2].mV ); + gGL.vertex3fv( v[2].mV ); + + gGL.vertex3fv( v[2].mV ); + + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv( tc[1].mV ); + gGL.vertex3fv( v[1].mV ); + + gGL.texCoord2fv( tc[3].mV ); + gGL.vertex3fv( v[3].mV ); + } + } + gGL.end(); + gGL.flush(); + } + gGL.popMatrix(); + gGL.popUIMatrix(); + + if (shader) + { + shader->bind(); + } } // @@ -7152,71 +7152,71 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) // *DEPRECATED: See header comment. void dialog_refresh_all() { - // This is the easiest place to fire the update signal, as it will - // make cleaning up the functions below easier. Also, sometimes entities - // outside the selection manager change properties of selected objects - // and call into this function. Yuck. - LLSelectMgr::getInstance()->mUpdateSignal(); + // This is the easiest place to fire the update signal, as it will + // make cleaning up the functions below easier. Also, sometimes entities + // outside the selection manager change properties of selected objects + // and call into this function. Yuck. + LLSelectMgr::getInstance()->mUpdateSignal(); - // *TODO: Eliminate all calls into outside classes below, make those - // objects register with the update signal. + // *TODO: Eliminate all calls into outside classes below, make those + // objects register with the update signal. - gFloaterTools->dirty(); + gFloaterTools->dirty(); - gMenuObject->needsArrange(); + gMenuObject->needsArrange(); - if( gMenuAttachmentSelf->getVisible() ) - { - gMenuAttachmentSelf->arrange(); - } - if( gMenuAttachmentOther->getVisible() ) - { - gMenuAttachmentOther->arrange(); - } + if( gMenuAttachmentSelf->getVisible() ) + { + gMenuAttachmentSelf->arrange(); + } + if( gMenuAttachmentOther->getVisible() ) + { + gMenuAttachmentOther->arrange(); + } - LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance("inspect"); - if(inspect_instance) - { - inspect_instance->dirty(); - } + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance("inspect"); + if(inspect_instance) + { + inspect_instance->dirty(); + } - LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); - if (panel_task_info) - { - panel_task_info->dirty(); - } + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + panel_task_info->dirty(); + } } S32 get_family_count(LLViewerObject *parent) { - if (!parent) - { - LL_WARNS() << "Trying to get_family_count on null parent!" << LL_ENDL; - } - S32 count = 1; // for this object - LLViewerObject::const_child_list_t& child_list = parent->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - - if (!child) - { - LL_WARNS() << "Family object has NULL child! Show Doug." << LL_ENDL; - } - else if (child->isDead()) - { - LL_WARNS() << "Family object has dead child object. Show Doug." << LL_ENDL; - } - else - { - if (LLSelectMgr::getInstance()->canSelectObject(child)) - { - count += get_family_count( child ); - } - } - } - return count; + if (!parent) + { + LL_WARNS() << "Trying to get_family_count on null parent!" << LL_ENDL; + } + S32 count = 1; // for this object + LLViewerObject::const_child_list_t& child_list = parent->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + + if (!child) + { + LL_WARNS() << "Family object has NULL child! Show Doug." << LL_ENDL; + } + else if (child->isDead()) + { + LL_WARNS() << "Family object has dead child object. Show Doug." << LL_ENDL; + } + else + { + if (LLSelectMgr::getInstance()->canSelectObject(child)) + { + count += get_family_count( child ); + } + } + } + return count; } //----------------------------------------------------------------------------- @@ -7227,106 +7227,106 @@ S32 get_family_count(LLViewerObject *parent) // ----------------------------------------------------------------------------- void LLSelectMgr::updateSelectionCenter() { - const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection - // center (tractor beam) + const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection + // center (tractor beam) // override any avatar updates received // Works only if avatar was repositioned // and edit floater is visible overrideAvatarUpdates(); - //override any object updates received - //for selected objects - overrideObjectUpdates(); - - LLViewerObject* object = mSelectedObjects->getFirstObject(); - if (!object) - { - // nothing selected, probably grabbing - // Ignore by setting to avatar origin. - mSelectionCenterGlobal.clearVec(); - mShowSelection = FALSE; - mSelectionBBox = LLBBox(); - resetAgentHUDZoom(); - } - else - { - mSelectedObjects->mSelectType = getSelectTypeForObject(object); - - if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid()) - { - // reset hud ZOOM - resetAgentHUDZoom(); - } - - mShowSelection = FALSE; - LLBBox bbox; - - // have stuff selected - LLVector3d select_center; - // keep a list of jointed objects for showing the joint HUDEffects - - // Initialize the bounding box to the root prim, so the BBox orientation - // matches the root prim's (affecting the orientation of the manipulators). - bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() ); - - for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); - iter != mSelectedObjects->end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if (!object) - continue; - - LLViewerObject *root = object->getRootEdit(); - if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment - !root->isChild(gAgentAvatarp) && // not the object you're sitting on - !object->isAvatar()) // not another avatar - { - mShowSelection = TRUE; - } - - bbox.addBBoxAgent( object->getBoundingBoxAgent() ); - } - - LLVector3 bbox_center_agent = bbox.getCenterAgent(); - mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); - mSelectionBBox = bbox; - - } - - if ( !(gAgentID == LLUUID::null)) - { - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (mShowSelection) - { - LLVector3d select_center_global; - - if( tool->isEditing() ) - { - select_center_global = tool->getEditingPointGlobal(); - } - else - { - select_center_global = mSelectionCenterGlobal; - } - - // Send selection center if moved beyond threshold (used to animate tractor beam) - LLVector3d diff; - diff = select_center_global - mLastSentSelectionCenterGlobal; - - if ( diff.magVecSquared() > MOVE_SELECTION_THRESHOLD*MOVE_SELECTION_THRESHOLD ) - { - // Transmit updated selection center - mLastSentSelectionCenterGlobal = select_center_global; - } - } - } - - // give up edit menu if no objects selected - if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0) - { - gEditMenuHandler = NULL; - } + //override any object updates received + //for selected objects + overrideObjectUpdates(); + + LLViewerObject* object = mSelectedObjects->getFirstObject(); + if (!object) + { + // nothing selected, probably grabbing + // Ignore by setting to avatar origin. + mSelectionCenterGlobal.clearVec(); + mShowSelection = FALSE; + mSelectionBBox = LLBBox(); + resetAgentHUDZoom(); + } + else + { + mSelectedObjects->mSelectType = getSelectTypeForObject(object); + + if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid()) + { + // reset hud ZOOM + resetAgentHUDZoom(); + } + + mShowSelection = FALSE; + LLBBox bbox; + + // have stuff selected + LLVector3d select_center; + // keep a list of jointed objects for showing the joint HUDEffects + + // Initialize the bounding box to the root prim, so the BBox orientation + // matches the root prim's (affecting the orientation of the manipulators). + bbox.addBBoxAgent( (mSelectedObjects->getFirstRootObject(TRUE))->getBoundingBoxAgent() ); + + for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); + iter != mSelectedObjects->end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (!object) + continue; + + LLViewerObject *root = object->getRootEdit(); + if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment + !root->isChild(gAgentAvatarp) && // not the object you're sitting on + !object->isAvatar()) // not another avatar + { + mShowSelection = TRUE; + } + + bbox.addBBoxAgent( object->getBoundingBoxAgent() ); + } + + LLVector3 bbox_center_agent = bbox.getCenterAgent(); + mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); + mSelectionBBox = bbox; + + } + + if ( !(gAgentID == LLUUID::null)) + { + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + if (mShowSelection) + { + LLVector3d select_center_global; + + if( tool->isEditing() ) + { + select_center_global = tool->getEditingPointGlobal(); + } + else + { + select_center_global = mSelectionCenterGlobal; + } + + // Send selection center if moved beyond threshold (used to animate tractor beam) + LLVector3d diff; + diff = select_center_global - mLastSentSelectionCenterGlobal; + + if ( diff.magVecSquared() > MOVE_SELECTION_THRESHOLD*MOVE_SELECTION_THRESHOLD ) + { + // Transmit updated selection center + mLastSentSelectionCenterGlobal = select_center_global; + } + } + } + + // give up edit menu if no objects selected + if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0) + { + gEditMenuHandler = NULL; + } pauseAssociatedAvatars(); } @@ -7349,7 +7349,7 @@ void LLSelectMgr::pauseAssociatedAvatars() LLViewerObject* object = node->getObject(); if (!object) continue; - + mSelectedObjects->mSelectType = getSelectTypeForObject(object); LLVOAvatar* parent_av = NULL; @@ -7377,40 +7377,40 @@ void LLSelectMgr::pauseAssociatedAvatars() void LLSelectMgr::updatePointAt() { - if (mShowSelection) - { - if (mSelectedObjects->getObjectCount()) - { - LLVector3 select_offset; - const LLPickInfo& pick = gViewerWindow->getLastPick(); - LLViewerObject *click_object = pick.getObject(); - if (click_object && click_object->isSelected()) - { - // clicked on another object in our selection group, use that as target - select_offset.setVec(pick.mObjectOffset); - select_offset.rotVec(~click_object->getRenderRotation()); - - gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset); - gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset); - } - else - { - // didn't click on an object this time, revert to pointing at center of first object - gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); - gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); - } - } - else - { - gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR); - gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); - } - } - else - { - gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR); - gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); - } + if (mShowSelection) + { + if (mSelectedObjects->getObjectCount()) + { + LLVector3 select_offset; + const LLPickInfo& pick = gViewerWindow->getLastPick(); + LLViewerObject *click_object = pick.getObject(); + if (click_object && click_object->isSelected()) + { + // clicked on another object in our selection group, use that as target + select_offset.setVec(pick.mObjectOffset); + select_offset.rotVec(~click_object->getRenderRotation()); + + gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, click_object, select_offset); + gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, click_object, select_offset); + } + else + { + // didn't click on an object this time, revert to pointing at center of first object + gAgentCamera.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); + gAgentCamera.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); + } + } + else + { + gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR); + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); + } + } + else + { + gAgentCamera.setPointAt(POINTAT_TARGET_CLEAR); + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); + } } //----------------------------------------------------------------------------- @@ -7418,7 +7418,7 @@ void LLSelectMgr::updatePointAt() //----------------------------------------------------------------------------- LLBBox LLSelectMgr::getBBoxOfSelection() const { - return mSelectionBBox; + return mSelectionBBox; } @@ -7427,8 +7427,8 @@ LLBBox LLSelectMgr::getBBoxOfSelection() const //----------------------------------------------------------------------------- BOOL LLSelectMgr::canUndo() const { - // Can edit or can move - return const_cast(this)->mSelectedObjects->getFirstUndoEnabledObject() != NULL; // HACK: casting away constness - MG; + // Can edit or can move + return const_cast(this)->mSelectedObjects->getFirstUndoEnabledObject() != NULL; // HACK: casting away constness - MG; } //----------------------------------------------------------------------------- @@ -7436,9 +7436,9 @@ BOOL LLSelectMgr::canUndo() const //----------------------------------------------------------------------------- void LLSelectMgr::undo() { - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + LLUUID group_id(gAgent.getGroupID()); + sendListToRegions("Undo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- @@ -7446,7 +7446,7 @@ void LLSelectMgr::undo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canRedo() const { - return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG + return const_cast(this)->mSelectedObjects->getFirstEditableObject() != NULL; // HACK: casting away constness - MG } //----------------------------------------------------------------------------- @@ -7454,9 +7454,9 @@ BOOL LLSelectMgr::canRedo() const //----------------------------------------------------------------------------- void LLSelectMgr::redo() { - BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); - LLUUID group_id(gAgent.getGroupID()); - sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); + BOOL select_linked_set = !gSavedSettings.getBOOL("EditLinkedParts"); + LLUUID group_id(gAgent.getGroupID()); + sendListToRegions("Redo", packAgentAndSessionAndGroupID, packObjectID, logNoOp, &group_id, select_linked_set ? SEND_ONLY_ROOTS : SEND_CHILDREN_FIRST); } //----------------------------------------------------------------------------- @@ -7464,22 +7464,22 @@ void LLSelectMgr::redo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDoDelete() const { - bool can_delete = false; - // This function is "logically const" - it does not change state in - // a way visible outside the selection manager. - LLSelectMgr* self = const_cast(this); - LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject(); - // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) - if (obj!= NULL) - { - // all the faces needs to be selected - if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES )) - { - can_delete = true; - } - } - - return can_delete; + bool can_delete = false; + // This function is "logically const" - it does not change state in + // a way visible outside the selection manager. + LLSelectMgr* self = const_cast(this); + LLViewerObject* obj = self->mSelectedObjects->getFirstDeleteableObject(); + // Note: Can only delete root objects (see getFirstDeleteableObject() for more info) + if (obj!= NULL) + { + // all the faces needs to be selected + if(self->mSelectedObjects->contains(obj,SELECT_ALL_TES )) + { + can_delete = true; + } + } + + return can_delete; } //----------------------------------------------------------------------------- @@ -7487,7 +7487,7 @@ BOOL LLSelectMgr::canDoDelete() const //----------------------------------------------------------------------------- void LLSelectMgr::doDelete() { - selectDelete(); + selectDelete(); } //----------------------------------------------------------------------------- @@ -7495,7 +7495,7 @@ void LLSelectMgr::doDelete() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDeselect() const { - return !mSelectedObjects->isEmpty(); + return !mSelectedObjects->isEmpty(); } //----------------------------------------------------------------------------- @@ -7503,123 +7503,123 @@ BOOL LLSelectMgr::canDeselect() const //----------------------------------------------------------------------------- void LLSelectMgr::deselect() { - deselectAll(); + deselectAll(); } //----------------------------------------------------------------------------- // canDuplicate() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDuplicate() const { - return const_cast(this)->mSelectedObjects->getFirstCopyableObject() != NULL; // HACK: casting away constness - MG + return const_cast(this)->mSelectedObjects->getFirstCopyableObject() != NULL; // HACK: casting away constness - MG } //----------------------------------------------------------------------------- // duplicate() //----------------------------------------------------------------------------- void LLSelectMgr::duplicate() { - LLVector3 offset(0.5f, 0.5f, 0.f); - selectDuplicate(offset, TRUE); + LLVector3 offset(0.5f, 0.5f, 0.f); + selectDuplicate(offset, TRUE); } ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object) { - if (!object) - { - return SELECT_TYPE_WORLD; - } - if (object->isHUDAttachment()) - { - return SELECT_TYPE_HUD; - } - else if (object->isAttachment()) - { - return SELECT_TYPE_ATTACHMENT; - } - else - { - return SELECT_TYPE_WORLD; - } + if (!object) + { + return SELECT_TYPE_WORLD; + } + if (object->isHUDAttachment()) + { + return SELECT_TYPE_HUD; + } + else if (object->isAttachment()) + { + return SELECT_TYPE_ATTACHMENT; + } + else + { + return SELECT_TYPE_WORLD; + } } void LLSelectMgr::validateSelection() { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - if (!LLSelectMgr::getInstance()->canSelectObject(object)) - { - LLSelectMgr::getInstance()->deselectObjectOnly(object); - } - return true; - } - } func; - getSelection()->applyToObjects(&func); + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (!LLSelectMgr::getInstance()->canSelectObject(object)) + { + LLSelectMgr::getInstance()->deselectObjectOnly(object); + } + return true; + } + } func; + getSelection()->applyToObjects(&func); } BOOL LLSelectMgr::canSelectObject(LLViewerObject* object, BOOL ignore_select_owned) { - // Never select dead objects - if (!object || object->isDead()) - { - return FALSE; - } + // Never select dead objects + if (!object || object->isDead()) + { + return FALSE; + } - if (mForceSelection) - { - return TRUE; - } + if (mForceSelection) + { + return TRUE; + } - if(!ignore_select_owned) - { - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) - { - // only select my own objects - return FALSE; - } - } + if(!ignore_select_owned) + { + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || + (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) + { + // only select my own objects + return FALSE; + } + } - // Can't select orphans - if (object->isOrphaned()) return FALSE; + // Can't select orphans + if (object->isOrphaned()) return FALSE; - // Can't select avatars - if (object->isAvatar()) return FALSE; + // Can't select avatars + if (object->isAvatar()) return FALSE; - // Can't select land - if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE; + // Can't select land + if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE; - ESelectType selection_type = getSelectTypeForObject(object); - if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE; + ESelectType selection_type = getSelectTypeForObject(object); + if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE; - return TRUE; + return TRUE; } -BOOL LLSelectMgr::setForceSelection(BOOL force) -{ - std::swap(mForceSelection,force); - return force; +BOOL LLSelectMgr::setForceSelection(BOOL force) +{ + std::swap(mForceSelection,force); + return force; } void LLSelectMgr::resetAgentHUDZoom() { - if (gAgentCamera.mHUDTargetZoom != 1) - { - gAgentCamera.mHUDTargetZoom = 1.f; - gAgentCamera.mHUDCurZoom = 1.f; - } + if (gAgentCamera.mHUDTargetZoom != 1) + { + gAgentCamera.mHUDTargetZoom = 1.f; + gAgentCamera.mHUDCurZoom = 1.f; + } } void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const { - target_zoom = gAgentCamera.mHUDTargetZoom; - current_zoom = gAgentCamera.mHUDCurZoom; + target_zoom = gAgentCamera.mHUDTargetZoom; + current_zoom = gAgentCamera.mHUDCurZoom; } void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) { - gAgentCamera.mHUDTargetZoom = target_zoom; - gAgentCamera.mHUDCurZoom = current_zoom; + gAgentCamera.mHUDTargetZoom = target_zoom; + gAgentCamera.mHUDCurZoom = current_zoom; } ///////////////////////////////////////////////////////////////////////////// @@ -7627,45 +7627,45 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) ///////////////////////////////////////////////////////////////////////////// bool LLObjectSelection::is_root::operator()(LLSelectNode *node) { - LLViewerObject* object = node->getObject(); - return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit()); + LLViewerObject* object = node->getObject(); + return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit()); } bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node) { - LLViewerObject* object = node->getObject(); - return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit()); + LLViewerObject* object = node->getObject(); + return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit()); } bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node) { - LLViewerObject* object = node->getObject(); - return (object != NULL) && (object->isRootEdit()); + LLViewerObject* object = node->getObject(); + return (object != NULL) && (object->isRootEdit()); } -LLObjectSelection::LLObjectSelection() : - LLRefCount(), - mSelectType(SELECT_TYPE_WORLD) +LLObjectSelection::LLObjectSelection() : + LLRefCount(), + mSelectType(SELECT_TYPE_WORLD) { } LLObjectSelection::~LLObjectSelection() { - deleteAllNodes(); + deleteAllNodes(); } void LLObjectSelection::cleanupNodes() { - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ) - { - list_t::iterator curiter = iter++; - LLSelectNode* node = *curiter; - if (node->getObject() == NULL || node->getObject()->isDead()) - { - mList.erase(curiter); - delete node; - } - } + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ) + { + list_t::iterator curiter = iter++; + LLSelectNode* node = *curiter; + if (node->getObject() == NULL || node->getObject()->isDead()) + { + mList.erase(curiter); + delete node; + } + } } void LLObjectSelection::updateEffects() @@ -7674,56 +7674,56 @@ void LLObjectSelection::updateEffects() S32 LLObjectSelection::getNumNodes() { - return mList.size(); + return mList.size(); } void LLObjectSelection::addNode(LLSelectNode *nodep) { - llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); - mList.push_front(nodep); - mSelectNodeMap[nodep->getObject()] = nodep; + llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); + mList.push_front(nodep); + mSelectNodeMap[nodep->getObject()] = nodep; } void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep) { - llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); - mList.push_back(nodep); - mSelectNodeMap[nodep->getObject()] = nodep; + llassert_always(nodep->getObject() && !nodep->getObject()->isDead()); + mList.push_back(nodep); + mSelectNodeMap[nodep->getObject()] = nodep; } void LLObjectSelection::moveNodeToFront(LLSelectNode *nodep) { - mList.remove(nodep); - mList.push_front(nodep); + mList.remove(nodep); + mList.push_front(nodep); } void LLObjectSelection::removeNode(LLSelectNode *nodep) { - mSelectNodeMap.erase(nodep->getObject()); - if (nodep->getObject() == mPrimaryObject) - { - mPrimaryObject = NULL; - } - nodep->setObject(NULL); // Will get erased in cleanupNodes() - mList.remove(nodep); + mSelectNodeMap.erase(nodep->getObject()); + if (nodep->getObject() == mPrimaryObject) + { + mPrimaryObject = NULL; + } + nodep->setObject(NULL); // Will get erased in cleanupNodes() + mList.remove(nodep); } void LLObjectSelection::deleteAllNodes() { - std::for_each(mList.begin(), mList.end(), DeletePointer()); - mList.clear(); - mSelectNodeMap.clear(); - mPrimaryObject = NULL; + std::for_each(mList.begin(), mList.end(), DeletePointer()); + mList.clear(); + mSelectNodeMap.clear(); + mPrimaryObject = NULL; } LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp) { - std::map, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp); - if (found_it != mSelectNodeMap.end()) - { - return found_it->second; - } - return NULL; + std::map, LLSelectNode*>::iterator found_it = mSelectNodeMap.find(objectp); + if (found_it != mSelectNodeMap.end()) + { + return found_it->second; + } + return NULL; } //----------------------------------------------------------------------------- @@ -7731,7 +7731,7 @@ LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp) //----------------------------------------------------------------------------- BOOL LLObjectSelection::isEmpty() const { - return (mList.size() == 0); + return (mList.size() == 0); } @@ -7740,119 +7740,119 @@ BOOL LLObjectSelection::isEmpty() const //----------------------------------------------------------------------------- S32 LLObjectSelection::getObjectCount() { - cleanupNodes(); - S32 count = mList.size(); + cleanupNodes(); + S32 count = mList.size(); - return count; + return count; } F32 LLObjectSelection::getSelectedObjectCost() { - cleanupNodes(); - F32 cost = 0.f; + cleanupNodes(); + F32 cost = 0.f; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object) - { - cost += object->getObjectCost(); - } - } + if (object) + { + cost += object->getObjectCost(); + } + } - return cost; + return cost; } F32 LLObjectSelection::getSelectedLinksetCost() { - cleanupNodes(); - F32 cost = 0.f; - - std::set me_roots; - - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object && !object->isAttachment()) - { - LLViewerObject* root = static_cast(object->getRoot()); - if (root) - { - if (me_roots.find(root) == me_roots.end()) - { - me_roots.insert(root); - cost += root->getLinksetCost(); - } - } - } - } - - return cost; + cleanupNodes(); + F32 cost = 0.f; + + std::set me_roots; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object && !object->isAttachment()) + { + LLViewerObject* root = static_cast(object->getRoot()); + if (root) + { + if (me_roots.find(root) == me_roots.end()) + { + me_roots.insert(root); + cost += root->getLinksetCost(); + } + } + } + } + + return cost; } F32 LLObjectSelection::getSelectedPhysicsCost() { - cleanupNodes(); - F32 cost = 0.f; + cleanupNodes(); + F32 cost = 0.f; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object) - { - cost += object->getPhysicsCost(); - } - } + if (object) + { + cost += object->getPhysicsCost(); + } + } - return cost; + return cost; } -F32 LLObjectSelection::getSelectedLinksetPhysicsCost() -{ - cleanupNodes(); - F32 cost = 0.f; - - std::set me_roots; - - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object) - { - LLViewerObject* root = static_cast(object->getRoot()); - if (root) - { - if (me_roots.find(root) == me_roots.end()) - { - me_roots.insert(root); - cost += root->getLinksetPhysicsCost(); - } - } - } - } - - return cost; +F32 LLObjectSelection::getSelectedLinksetPhysicsCost() +{ + cleanupNodes(); + F32 cost = 0.f; + + std::set me_roots; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + LLViewerObject* root = static_cast(object->getRoot()); + if (root) + { + if (me_roots.find(root) == me_roots.end()) + { + me_roots.insert(root); + cost += root->getLinksetPhysicsCost(); + } + } + } + } + + return cost; } F32 LLObjectSelection::getSelectedObjectStreamingCost(S32* total_bytes, S32* visible_bytes) { - F32 cost = 0.f; - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object) - { - cost += object->getStreamingCost(); + F32 cost = 0.f; + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + cost += object->getStreamingCost(); S32 bytes = 0; S32 visible = 0; @@ -7862,38 +7862,38 @@ F32 LLObjectSelection::getSelectedObjectStreamingCost(S32* total_bytes, S32* vis bytes = costs.getSizeTotal(); visible = costs.getSizeByLOD(object->getLOD()); } - if (total_bytes) - { - *total_bytes += bytes; - } + if (total_bytes) + { + *total_bytes += bytes; + } - if (visible_bytes) - { - *visible_bytes += visible; - } - } - } + if (visible_bytes) + { + *visible_bytes += visible; + } + } + } - return cost; + return cost; } U32 LLObjectSelection::getSelectedObjectTriangleCount(S32* vcount) { - U32 count = 0; - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - - if (object) - { - S32 vt = 0; - count += object->getTriangleCount(&vt); - *vcount += vt; - } - } + U32 count = 0; + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + S32 vt = 0; + count += object->getTriangleCount(&vt); + *vcount += vt; + } + } - return count; + return count; } S32 LLObjectSelection::getSelectedObjectRenderCost() @@ -7903,65 +7903,65 @@ S32 LLObjectSelection::getSelectedObjectRenderCost() typedef std::set uuid_list_t; uuid_list_t computed_objects; - typedef std::list > child_list_t; - typedef const child_list_t const_child_list_t; + typedef std::list > child_list_t; + typedef const child_list_t const_child_list_t; - // add render cost of complete linksets first, to get accurate texture counts + // add render cost of complete linksets first, to get accurate texture counts for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) { LLSelectNode* node = *iter; - + LLVOVolume* object = (LLVOVolume*)node->getObject(); if (object && object->isRootEdit()) { - cost += object->getRenderCost(textures); - computed_objects.insert(object->getID()); - - const_child_list_t children = object->getChildren(); - for (const_child_list_t::const_iterator child_iter = children.begin(); - child_iter != children.end(); - ++child_iter) - { - LLViewerObject* child_obj = *child_iter; - LLVOVolume *child = dynamic_cast( child_obj ); - if (child) - { - cost += child->getRenderCost(textures); - computed_objects.insert(child->getID()); - } - } - - for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) - { - // add the cost of each individual texture in the linkset - cost += LLVOVolume::getTextureCost(*iter); - } - - textures.clear(); + cost += object->getRenderCost(textures); + computed_objects.insert(object->getID()); + + const_child_list_t children = object->getChildren(); + for (const_child_list_t::const_iterator child_iter = children.begin(); + child_iter != children.end(); + ++child_iter) + { + LLViewerObject* child_obj = *child_iter; + LLVOVolume *child = dynamic_cast( child_obj ); + if (child) + { + cost += child->getRenderCost(textures); + computed_objects.insert(child->getID()); + } + } + + for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) + { + // add the cost of each individual texture in the linkset + cost += LLVOVolume::getTextureCost(*iter); + } + + textures.clear(); } } - - // add any partial linkset objects, texture cost may be slightly misleading - for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) - { - LLSelectNode* node = *iter; - LLVOVolume* object = (LLVOVolume*)node->getObject(); - - if (object && computed_objects.find(object->getID()) == computed_objects.end() ) - { - cost += object->getRenderCost(textures); - computed_objects.insert(object->getID()); - } - - for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) - { - // add the cost of each individual texture in the linkset - cost += LLVOVolume::getTextureCost(*iter); - } - - textures.clear(); - } + + // add any partial linkset objects, texture cost may be slightly misleading + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLVOVolume* object = (LLVOVolume*)node->getObject(); + + if (object && computed_objects.find(object->getID()) == computed_objects.end() ) + { + cost += object->getRenderCost(textures); + computed_objects.insert(object->getID()); + } + + for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) + { + // add the cost of each individual texture in the linkset + cost += LLVOVolume::getTextureCost(*iter); + } + + textures.clear(); + } return cost; } @@ -7971,23 +7971,23 @@ S32 LLObjectSelection::getSelectedObjectRenderCost() //----------------------------------------------------------------------------- S32 LLObjectSelection::getTECount() { - S32 count = 0; - for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if (!object) - continue; - S32 num_tes = object->getNumTEs(); - for (S32 te = 0; te < num_tes; te++) - { - if (node->isTESelected(te)) - { - ++count; - } - } - } - return count; + S32 count = 0; + for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (!object) + continue; + S32 num_tes = object->getNumTEs(); + for (S32 te = 0; te < num_tes; te++) + { + if (node->isTESelected(te)) + { + ++count; + } + } + } + return count; } //----------------------------------------------------------------------------- @@ -7995,27 +7995,27 @@ S32 LLObjectSelection::getTECount() //----------------------------------------------------------------------------- S32 LLObjectSelection::getRootObjectCount() { - S32 count = 0; - for (LLObjectSelection::root_iterator iter = root_begin(); iter != root_end(); iter++) - { - ++count; - } - return count; + S32 count = 0; + for (LLObjectSelection::root_iterator iter = root_begin(); iter != root_end(); iter++) + { + ++count; + } + return count; } bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func) { - bool result = true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - bool r = func->apply(object); - result = result && r; - } - return result; + bool result = true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + bool r = func->apply(object); + result = result && r; + } + return result; } bool LLObjectSelection::checkAnimatedObjectEstTris() @@ -8023,19 +8023,19 @@ bool LLObjectSelection::checkAnimatedObjectEstTris() F32 est_tris = 0; F32 max_tris = 0; S32 anim_count = 0; - for (root_iterator iter = root_begin(); iter != root_end(); ++iter) - { - LLViewerObject* object = (*iter)->getObject(); - if (!object) - continue; + for (root_iterator iter = root_begin(); iter != root_end(); ++iter) + { + LLViewerObject* object = (*iter)->getObject(); + if (!object) + continue; if (object->isAnimatedObject()) { anim_count++; } est_tris += object->recursiveGetEstTrianglesMax(); max_tris = llmax((F32)max_tris,(F32)object->getAnimatedObjectMaxTris()); - } - return anim_count==0 || est_tris <= max_tris; + } + return anim_count==0 || est_tris <= max_tris; } bool LLObjectSelection::checkAnimatedObjectLinkable() @@ -8045,101 +8045,101 @@ bool LLObjectSelection::checkAnimatedObjectLinkable() bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly) { - bool result = firstonly ? false : true; - for (root_iterator iter = root_begin(); iter != root_end(); ) - { - root_iterator nextiter = iter++; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - bool r = func->apply(object); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; + bool result = firstonly ? false : true; + for (root_iterator iter = root_begin(); iter != root_end(); ) + { + root_iterator nextiter = iter++; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + bool r = func->apply(object); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; } bool LLObjectSelection::applyToTEs(LLSelectedTEFunctor* func, bool firstonly) { - bool result = firstonly ? false : true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - LLViewerObject* object = (*nextiter)->getObject(); - if (!object) - continue; - S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces - for (S32 te = 0; te < num_tes; ++te) - { - if (node->isTESelected(te)) - { - bool r = func->apply(object, te); - if (firstonly && r) - return true; - else - result = result && r; - } - } - } - return result; + bool result = firstonly ? false : true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + LLViewerObject* object = (*nextiter)->getObject(); + if (!object) + continue; + S32 num_tes = llmin((S32)object->getNumTEs(), (S32)object->getNumFaces()); // avatars have TEs but no faces + for (S32 te = 0; te < num_tes; ++te) + { + if (node->isTESelected(te)) + { + bool r = func->apply(object, te); + if (firstonly && r) + return true; + else + result = result && r; + } + } + } + return result; } bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func, bool firstonly) { - bool result = firstonly ? false : true; - for (iterator iter = begin(); iter != end(); ) - { - iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - bool r = func->apply(node); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; + bool result = firstonly ? false : true; + for (iterator iter = begin(); iter != end(); ) + { + iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + bool r = func->apply(node); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; } bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool firstonly) { - bool result = firstonly ? false : true; - for (root_iterator iter = root_begin(); iter != root_end(); ) - { - root_iterator nextiter = iter++; - LLSelectNode* node = *nextiter; - bool r = func->apply(node); - if (firstonly && r) - return true; - else - result = result && r; - } - return result; + bool result = firstonly ? false : true; + for (root_iterator iter = root_begin(); iter != root_end(); ) + { + root_iterator nextiter = iter++; + LLSelectNode* node = *nextiter; + bool r = func->apply(node); + if (firstonly && r) + return true; + else + result = result && r; + } + return result; } BOOL LLObjectSelection::isMultipleTESelected() { - BOOL te_selected = FALSE; - // ...all faces - for (LLObjectSelection::iterator iter = begin(); - iter != end(); iter++) - { - LLSelectNode* nodep = *iter; - for (S32 i = 0; i < SELECT_MAX_TES; i++) - { - if(nodep->isTESelected(i)) - { - if(te_selected) - { - return TRUE; - } - te_selected = TRUE; - } - } - } - return FALSE; + BOOL te_selected = FALSE; + // ...all faces + for (LLObjectSelection::iterator iter = begin(); + iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + for (S32 i = 0; i < SELECT_MAX_TES; i++) + { + if(nodep->isTESelected(i)) + { + if(te_selected) + { + return TRUE; + } + te_selected = TRUE; + } + } + } + return FALSE; } //----------------------------------------------------------------------------- @@ -8147,7 +8147,7 @@ BOOL LLObjectSelection::isMultipleTESelected() //----------------------------------------------------------------------------- BOOL LLObjectSelection::contains(LLViewerObject* object) { - return findNode(object) != NULL; + return findNode(object) != NULL; } @@ -8156,50 +8156,50 @@ BOOL LLObjectSelection::contains(LLViewerObject* object) //----------------------------------------------------------------------------- BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te) { - if (te == SELECT_ALL_TES) - { - // ...all faces - for (LLObjectSelection::iterator iter = begin(); - iter != end(); iter++) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object) - { - // Optimization - if (nodep->getTESelectMask() == TE_SELECT_MASK_ALL) - { - return TRUE; - } - - BOOL all_selected = TRUE; - for (S32 i = 0; i < object->getNumTEs(); i++) - { - all_selected = all_selected && nodep->isTESelected(i); - } - return all_selected; - } - } - return FALSE; - } - else - { - // ...one face - for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* nodep = *iter; - if (nodep->getObject() == object && nodep->isTESelected(te)) - { - return TRUE; - } - } - return FALSE; - } + if (te == SELECT_ALL_TES) + { + // ...all faces + for (LLObjectSelection::iterator iter = begin(); + iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object) + { + // Optimization + if (nodep->getTESelectMask() == TE_SELECT_MASK_ALL) + { + return TRUE; + } + + BOOL all_selected = TRUE; + for (S32 i = 0; i < object->getNumTEs(); i++) + { + all_selected = all_selected && nodep->isTESelected(i); + } + return all_selected; + } + } + return FALSE; + } + else + { + // ...one face + for (LLObjectSelection::iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + if (nodep->getObject() == object && nodep->isTESelected(te)) + { + return TRUE; + } + } + return FALSE; + } } // returns TRUE is any node is currenly worn as an attachment BOOL LLObjectSelection::isAttachment() { - return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); + return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); } //----------------------------------------------------------------------------- @@ -8207,19 +8207,19 @@ BOOL LLObjectSelection::isAttachment() //----------------------------------------------------------------------------- LLViewerObject* getSelectedParentObject(LLViewerObject *object) { - LLViewerObject *parent; - while (object && (parent = (LLViewerObject*)object->getParent())) - { - if (parent->isSelected()) - { - object = parent; - } - else - { - break; - } - } - return object; + LLViewerObject *parent; + while (object && (parent = (LLViewerObject*)object->getParent())) + { + if (parent->isSelected()) + { + object = parent; + } + else + { + break; + } + } + return object; } //----------------------------------------------------------------------------- @@ -8227,33 +8227,33 @@ LLViewerObject* getSelectedParentObject(LLViewerObject *object) //----------------------------------------------------------------------------- LLSelectNode* LLObjectSelection::getFirstNode(LLSelectedNodeFunctor* func) { - for (iterator iter = begin(); iter != end(); ++iter) - { - LLSelectNode* node = *iter; - if (func == NULL || func->apply(node)) - { - return node; - } - } - return NULL; + for (iterator iter = begin(); iter != end(); ++iter) + { + LLSelectNode* node = *iter; + if (func == NULL || func->apply(node)) + { + return node; + } + } + return NULL; } LLSelectNode* LLObjectSelection::getFirstRootNode(LLSelectedNodeFunctor* func, BOOL non_root_ok) { - for (root_iterator iter = root_begin(); iter != root_end(); ++iter) - { - LLSelectNode* node = *iter; - if (func == NULL || func->apply(node)) - { - return node; - } - } - if (non_root_ok) - { - // Get non root - return getFirstNode(func); - } - return NULL; + for (root_iterator iter = root_begin(); iter != root_end(); ++iter) + { + LLSelectNode* node = *iter; + if (func == NULL || func->apply(node)) + { + return node; + } + } + if (non_root_ok) + { + // Get non root + return getFirstNode(func); + } + return NULL; } @@ -8262,16 +8262,16 @@ LLSelectNode* LLObjectSelection::getFirstRootNode(LLSelectedNodeFunctor* func, B //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent) { - LLSelectNode* res = getFirstNode(func); - if (res && get_parent) - { - return getSelectedParentObject(res->getObject()); - } - else if (res) - { - return res->getObject(); - } - return NULL; + LLSelectNode* res = getFirstNode(func); + if (res && get_parent) + { + return getSelectedParentObject(res->getObject()); + } + else if (res) + { + return res->getObject(); + } + return NULL; } //----------------------------------------------------------------------------- @@ -8279,8 +8279,8 @@ LLViewerObject* LLObjectSelection::getFirstSelectedObject(LLSelectedNodeFunctor* //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstObject() { - LLSelectNode* res = getFirstNode(NULL); - return res ? res->getObject() : NULL; + LLSelectNode* res = getFirstNode(NULL); + return res ? res->getObject() : NULL; } //----------------------------------------------------------------------------- @@ -8288,8 +8288,8 @@ LLViewerObject* LLObjectSelection::getFirstObject() //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstRootObject(BOOL non_root_ok) { - LLSelectNode* res = getFirstRootNode(NULL, non_root_ok); - return res ? res->getObject() : NULL; + LLSelectNode* res = getFirstRootNode(NULL, non_root_ok); + return res ? res->getObject() : NULL; } //----------------------------------------------------------------------------- @@ -8297,16 +8297,16 @@ LLViewerObject* LLObjectSelection::getFirstRootObject(BOOL non_root_ok) //----------------------------------------------------------------------------- LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) { - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permMove() && !obj->isPermanentEnforced(); - } - } func; - LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func); - return res; + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permMove() && !obj->isPermanentEnforced(); + } + } func; + LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func); + return res; } //----------------------------------------------------------------------------- @@ -8314,15 +8314,15 @@ LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent) { - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permCopy() && !obj->isAttachment(); - } - } func; - return getFirstSelectedObject(&func, get_parent); + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permCopy() && !obj->isAttachment(); + } + } func; + return getFirstSelectedObject(&func, get_parent); } //----------------------------------------------------------------------------- @@ -8330,31 +8330,31 @@ LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_parent) //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstDeleteableObject() { - //RN: don't currently support deletion of child objects, as that requires separating them first - // then derezzing to trash - - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - // you can delete an object if you are the owner - // or you have permission to modify it. - if( obj && !obj->isPermanentEnforced() && - ( (obj->permModify()) || - (obj->permYouOwner()) || - (!obj->permAnyOwner()) )) // public - { - if( !obj->isAttachment() ) - { - return true; - } - } - return false; - } - } func; - LLSelectNode* node = getFirstNode(&func); - return node ? node->getObject() : NULL; + //RN: don't currently support deletion of child objects, as that requires separating them first + // then derezzing to trash + + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + // you can delete an object if you are the owner + // or you have permission to modify it. + if( obj && !obj->isPermanentEnforced() && + ( (obj->permModify()) || + (obj->permYouOwner()) || + (!obj->permAnyOwner()) )) // public + { + if( !obj->isAttachment() ) + { + return true; + } + } + return false; + } + } func; + LLSelectNode* node = getFirstNode(&func); + return node ? node->getObject() : NULL; } //----------------------------------------------------------------------------- @@ -8362,15 +8362,15 @@ LLViewerObject* LLObjectSelection::getFirstDeleteableObject() //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent) { - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permModify(); - } - } func; - return getFirstSelectedObject(&func, get_parent); + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permModify(); + } + } func; + return getFirstSelectedObject(&func, get_parent); } //----------------------------------------------------------------------------- @@ -8378,15 +8378,15 @@ LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_parent) //----------------------------------------------------------------------------- LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent) { - struct f : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - return obj && obj->permMove() && !obj->isPermanentEnforced(); - } - } func; - return getFirstSelectedObject(&func, get_parent); + struct f : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + return obj && obj->permMove() && !obj->isPermanentEnforced(); + } + } func; + return getFirstSelectedObject(&func, get_parent); } //----------------------------------------------------------------------------- @@ -8411,196 +8411,196 @@ LLViewerObject* LLObjectSelection::getFirstUndoEnabledObject(BOOL get_parent) bool LLSelectMgr::selectionMove(const LLVector3& displ, F32 roll, F32 pitch, F32 yaw, U32 update_type) { - if (update_type == UPD_NONE) - { - return false; - } - - LLVector3 displ_global; - bool update_success = true; - bool update_position = update_type & UPD_POSITION; - bool update_rotation = update_type & UPD_ROTATION; - const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts"); - - if (update_position) - { - // calculate the distance of the object closest to the camera origin - F32 min_dist_squared = F32_MAX; // value will be overridden in the loop - - LLVector3 obj_pos; - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it) - { - obj_pos = (*it)->getObject()->getPositionEdit(); - - F32 obj_dist_squared = dist_vec_squared(obj_pos, LLViewerCamera::getInstance()->getOrigin()); - if (obj_dist_squared < min_dist_squared) - { - min_dist_squared = obj_dist_squared; - } - } - - // factor the distance into the displacement vector. This will get us - // equally visible movements for both close and far away selections. - F32 min_dist = sqrt((F32) sqrtf(min_dist_squared)) / 2; - displ_global.setVec(displ.mV[0] * min_dist, - displ.mV[1] * min_dist, - displ.mV[2] * min_dist); - - // equates to: Displ_global = Displ * M_cam_axes_in_global_frame - displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); - } - - LLQuaternion new_rot; - if (update_rotation) - { - // let's calculate the rotation around each camera axes - LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis()); - LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis()); - LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis()); - new_rot.setQuat(qx * qy * qz); - } - - LLViewerObject *obj; - S32 obj_count = getSelection()->getObjectCount(); - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it ) - { - obj = (*it)->getObject(); - bool enable_pos = false, enable_rot = false; - bool perm_move = obj->permMove() && !obj->isPermanentEnforced(); - bool perm_mod = obj->permModify(); - - LLVector3d sel_center(getSelectionCenterGlobal()); - - if (update_rotation) - { - enable_rot = perm_move - && ((perm_mod && !obj->isAttachment()) || noedit_linked_parts); - - if (enable_rot) - { - int children_count = obj->getChildren().size(); - if (obj_count > 1 && children_count > 0) - { - // for linked sets, rotate around the group center - const LLVector3 t(obj->getPositionGlobal() - sel_center); - - // Ra = T x R x T^-1 - LLMatrix4 mt; mt.setTranslation(t); - const LLMatrix4 mnew_rot(new_rot); - LLMatrix4 mt_1; mt_1.setTranslation(-t); - mt *= mnew_rot; - mt *= mt_1; - - // Rfin = Rcur * Ra - obj->setRotation(obj->getRotationEdit() * mt.quaternion()); - displ_global += mt.getTranslation(); - } - else - { - obj->setRotation(obj->getRotationEdit() * new_rot); - } - } - else - { - update_success = false; - } - } - - if (update_position) - { - // establish if object can be moved or not - enable_pos = perm_move && !obj->isAttachment() - && (perm_mod || noedit_linked_parts); - - if (enable_pos) - { - obj->setPosition(obj->getPositionEdit() + displ_global); - } - else - { - update_success = false; - } - } - - if (enable_pos && enable_rot && obj->mDrawable.notNull()) - { - gPipeline.markMoved(obj->mDrawable, TRUE); - } - } - - if (update_position && update_success && obj_count > 1) - { - updateSelectionCenter(); - } - - return update_success; + if (update_type == UPD_NONE) + { + return false; + } + + LLVector3 displ_global; + bool update_success = true; + bool update_position = update_type & UPD_POSITION; + bool update_rotation = update_type & UPD_ROTATION; + const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts"); + + if (update_position) + { + // calculate the distance of the object closest to the camera origin + F32 min_dist_squared = F32_MAX; // value will be overridden in the loop + + LLVector3 obj_pos; + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it) + { + obj_pos = (*it)->getObject()->getPositionEdit(); + + F32 obj_dist_squared = dist_vec_squared(obj_pos, LLViewerCamera::getInstance()->getOrigin()); + if (obj_dist_squared < min_dist_squared) + { + min_dist_squared = obj_dist_squared; + } + } + + // factor the distance into the displacement vector. This will get us + // equally visible movements for both close and far away selections. + F32 min_dist = sqrt((F32) sqrtf(min_dist_squared)) / 2; + displ_global.setVec(displ.mV[0] * min_dist, + displ.mV[1] * min_dist, + displ.mV[2] * min_dist); + + // equates to: Displ_global = Displ * M_cam_axes_in_global_frame + displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); + } + + LLQuaternion new_rot; + if (update_rotation) + { + // let's calculate the rotation around each camera axes + LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis()); + LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis()); + LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis()); + new_rot.setQuat(qx * qy * qz); + } + + LLViewerObject *obj; + S32 obj_count = getSelection()->getObjectCount(); + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it ) + { + obj = (*it)->getObject(); + bool enable_pos = false, enable_rot = false; + bool perm_move = obj->permMove() && !obj->isPermanentEnforced(); + bool perm_mod = obj->permModify(); + + LLVector3d sel_center(getSelectionCenterGlobal()); + + if (update_rotation) + { + enable_rot = perm_move + && ((perm_mod && !obj->isAttachment()) || noedit_linked_parts); + + if (enable_rot) + { + int children_count = obj->getChildren().size(); + if (obj_count > 1 && children_count > 0) + { + // for linked sets, rotate around the group center + const LLVector3 t(obj->getPositionGlobal() - sel_center); + + // Ra = T x R x T^-1 + LLMatrix4 mt; mt.setTranslation(t); + const LLMatrix4 mnew_rot(new_rot); + LLMatrix4 mt_1; mt_1.setTranslation(-t); + mt *= mnew_rot; + mt *= mt_1; + + // Rfin = Rcur * Ra + obj->setRotation(obj->getRotationEdit() * mt.quaternion()); + displ_global += mt.getTranslation(); + } + else + { + obj->setRotation(obj->getRotationEdit() * new_rot); + } + } + else + { + update_success = false; + } + } + + if (update_position) + { + // establish if object can be moved or not + enable_pos = perm_move && !obj->isAttachment() + && (perm_mod || noedit_linked_parts); + + if (enable_pos) + { + obj->setPosition(obj->getPositionEdit() + displ_global); + } + else + { + update_success = false; + } + } + + if (enable_pos && enable_rot && obj->mDrawable.notNull()) + { + gPipeline.markMoved(obj->mDrawable, TRUE); + } + } + + if (update_position && update_success && obj_count > 1) + { + updateSelectionCenter(); + } + + return update_success; } void LLSelectMgr::sendSelectionMove() { - LLSelectNode *node = mSelectedObjects->getFirstRootNode(); - if (node == NULL) - { - return; - } - - //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); - - U32 update_type = UPD_POSITION | UPD_ROTATION; - LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion(); - S32 objects_in_this_packet = 0; - - // apply to linked objects if unable to select their individual parts - if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) - { - // tell simulator to apply to whole linked sets - update_type |= UPD_LINKED_SETS; - } - - // prepare first bulk message - gMessageSystem->newMessage("MultipleObjectUpdate"); - packAgentAndSessionID(&update_type); - - LLViewerObject *obj = NULL; - for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); - it != getSelection()->root_end(); ++it) - { - obj = (*it)->getObject(); - - // note: following code adapted from sendListToRegions() (@3924) - last_region = curr_region; - curr_region = obj->getRegion(); - - // if not simulator or message too big - if (curr_region != last_region - || gMessageSystem->isSendFull(NULL) - || objects_in_this_packet >= MAX_OBJECTS_PER_PACKET) - { - // send sim the current message and start new one - gMessageSystem->sendReliable(last_region->getHost()); - objects_in_this_packet = 0; - gMessageSystem->newMessage("MultipleObjectUpdate"); - packAgentAndSessionID(&update_type); - } - - // add another instance of the body of data - packMultipleUpdate(*it, &update_type); - ++objects_in_this_packet; - } - - // flush remaining messages - if (gMessageSystem->getCurrentSendTotal() > 0) - { - gMessageSystem->sendReliable(curr_region->getHost()); - } - else - { - gMessageSystem->clearMessage(); - } - - //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + LLSelectNode *node = mSelectedObjects->getFirstRootNode(); + if (node == NULL) + { + return; + } + + //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); + + U32 update_type = UPD_POSITION | UPD_ROTATION; + LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion(); + S32 objects_in_this_packet = 0; + + // apply to linked objects if unable to select their individual parts + if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) + { + // tell simulator to apply to whole linked sets + update_type |= UPD_LINKED_SETS; + } + + // prepare first bulk message + gMessageSystem->newMessage("MultipleObjectUpdate"); + packAgentAndSessionID(&update_type); + + LLViewerObject *obj = NULL; + for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); + it != getSelection()->root_end(); ++it) + { + obj = (*it)->getObject(); + + // note: following code adapted from sendListToRegions() (@3924) + last_region = curr_region; + curr_region = obj->getRegion(); + + // if not simulator or message too big + if (curr_region != last_region + || gMessageSystem->isSendFull(NULL) + || objects_in_this_packet >= MAX_OBJECTS_PER_PACKET) + { + // send sim the current message and start new one + gMessageSystem->sendReliable(last_region->getHost()); + objects_in_this_packet = 0; + gMessageSystem->newMessage("MultipleObjectUpdate"); + packAgentAndSessionID(&update_type); + } + + // add another instance of the body of data + packMultipleUpdate(*it, &update_type); + ++objects_in_this_packet; + } + + // flush remaining messages + if (gMessageSystem->getCurrentSendTotal() > 0) + { + gMessageSystem->sendReliable(curr_region->getHost()); + } + else + { + gMessageSystem->clearMessage(); + } + + //saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); } template<> diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 66c794af4c..02c74d0ab0 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -1,25 +1,25 @@ -/** +/** * @file llselectmgr.h * @brief A manager for selected objects and TEs. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -42,13 +42,13 @@ #include "llbbox.h" #include "llpermissions.h" #include "llcontrol.h" -#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template +#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template #include "llmaterial.h" #include #include #include -#include // boost::make_shared +#include // boost::make_shared class LLMessageSystem; class LLViewerTexture; @@ -56,30 +56,30 @@ class LLColor4; class LLVector3; class LLSelectNode; -const U8 UPD_NONE = 0x00; -const U8 UPD_POSITION = 0x01; -const U8 UPD_ROTATION = 0x02; -const U8 UPD_SCALE = 0x04; -const U8 UPD_LINKED_SETS = 0x08; -const U8 UPD_UNIFORM = 0x10; // used with UPD_SCALE +const U8 UPD_NONE = 0x00; +const U8 UPD_POSITION = 0x01; +const U8 UPD_ROTATION = 0x02; +const U8 UPD_SCALE = 0x04; +const U8 UPD_LINKED_SETS = 0x08; +const U8 UPD_UNIFORM = 0x10; // used with UPD_SCALE // This is used by the DeRezObject message to determine where to put // derezed tasks. enum EDeRezDestination { - DRD_SAVE_INTO_AGENT_INVENTORY = 0, - DRD_ACQUIRE_TO_AGENT_INVENTORY = 1, // try to leave copy in world - DRD_SAVE_INTO_TASK_INVENTORY = 2, - DRD_ATTACHMENT = 3, - DRD_TAKE_INTO_AGENT_INVENTORY = 4, // delete from world - DRD_FORCE_TO_GOD_INVENTORY = 5, // force take copy - DRD_TRASH = 6, - DRD_ATTACHMENT_TO_INV = 7, - DRD_ATTACHMENT_EXISTS = 8, - DRD_RETURN_TO_OWNER = 9, // back to owner's inventory - DRD_RETURN_TO_LAST_OWNER = 10, // deeded object back to last owner's inventory - - DRD_COUNT = 11 + DRD_SAVE_INTO_AGENT_INVENTORY = 0, + DRD_ACQUIRE_TO_AGENT_INVENTORY = 1, // try to leave copy in world + DRD_SAVE_INTO_TASK_INVENTORY = 2, + DRD_ATTACHMENT = 3, + DRD_TAKE_INTO_AGENT_INVENTORY = 4, // delete from world + DRD_FORCE_TO_GOD_INVENTORY = 5, // force take copy + DRD_TRASH = 6, + DRD_ATTACHMENT_TO_INV = 7, + DRD_ATTACHMENT_EXISTS = 8, + DRD_RETURN_TO_OWNER = 9, // back to owner's inventory + DRD_RETURN_TO_LAST_OWNER = 10, // deeded object back to last owner's inventory + + DRD_COUNT = 11 }; @@ -92,8 +92,8 @@ const S32 SELECT_MAX_TES = 32; // the operation was successful. struct LLSelectedObjectFunctor { - virtual ~LLSelectedObjectFunctor() {}; - virtual bool apply(LLViewerObject* object) = 0; + virtual ~LLSelectedObjectFunctor() {}; + virtual bool apply(LLViewerObject* object) = 0; }; // Do something to all select nodes in the selection manager. @@ -102,63 +102,63 @@ struct LLSelectedObjectFunctor // the operation was successful. struct LLSelectedNodeFunctor { - virtual ~LLSelectedNodeFunctor() {}; - virtual bool apply(LLSelectNode* node) = 0; + virtual ~LLSelectedNodeFunctor() {}; + virtual bool apply(LLSelectNode* node) = 0; }; struct LLSelectedTEFunctor { - virtual ~LLSelectedTEFunctor() {}; - virtual bool apply(LLViewerObject* object, S32 face) = 0; + virtual ~LLSelectedTEFunctor() {}; + virtual bool apply(LLViewerObject* object, S32 face) = 0; }; struct LLSelectedTEMaterialFunctor { - virtual ~LLSelectedTEMaterialFunctor() {}; - virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) = 0; + virtual ~LLSelectedTEMaterialFunctor() {}; + virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) = 0; }; template struct LLSelectedTEGetFunctor { - virtual ~LLSelectedTEGetFunctor() {}; - virtual T get(LLViewerObject* object, S32 te) = 0; + virtual ~LLSelectedTEGetFunctor() {}; + virtual T get(LLViewerObject* object, S32 te) = 0; }; template struct LLCheckIdenticalFunctor { - static bool same(const T& a, const T& b, const T& tolerance); + static bool same(const T& a, const T& b, const T& tolerance); }; typedef enum e_send_type { - SEND_ONLY_ROOTS, - SEND_INDIVIDUALS, - SEND_ROOTS_FIRST, // useful for serial undos on linked sets - SEND_CHILDREN_FIRST // useful for serial transforms of linked sets + SEND_ONLY_ROOTS, + SEND_INDIVIDUALS, + SEND_ROOTS_FIRST, // useful for serial undos on linked sets + SEND_CHILDREN_FIRST // useful for serial transforms of linked sets } ESendType; typedef enum e_grid_mode { - GRID_MODE_WORLD, - GRID_MODE_LOCAL, - GRID_MODE_REF_OBJECT + GRID_MODE_WORLD, + GRID_MODE_LOCAL, + GRID_MODE_REF_OBJECT } EGridMode; typedef enum e_action_type { - SELECT_ACTION_TYPE_BEGIN, - SELECT_ACTION_TYPE_PICK, - SELECT_ACTION_TYPE_MOVE, - SELECT_ACTION_TYPE_ROTATE, - SELECT_ACTION_TYPE_SCALE, - NUM_ACTION_TYPES + SELECT_ACTION_TYPE_BEGIN, + SELECT_ACTION_TYPE_PICK, + SELECT_ACTION_TYPE_MOVE, + SELECT_ACTION_TYPE_ROTATE, + SELECT_ACTION_TYPE_SCALE, + NUM_ACTION_TYPES }EActionType; typedef enum e_selection_type { - SELECT_TYPE_WORLD, - SELECT_TYPE_ATTACHMENT, - SELECT_TYPE_HUD + SELECT_TYPE_WORLD, + SELECT_TYPE_ATTACHMENT, + SELECT_TYPE_HUD }ESelectType; typedef std::vector > gltf_materials_vec_t; @@ -169,29 +169,29 @@ const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF; class LLSelectNode { public: - LLSelectNode(LLViewerObject* object, BOOL do_glow); - LLSelectNode(const LLSelectNode& nodep); - ~LLSelectNode(); + LLSelectNode(LLViewerObject* object, BOOL do_glow); + LLSelectNode(const LLSelectNode& nodep); + ~LLSelectNode(); - void selectAllTEs(BOOL b); - void selectTE(S32 te_index, BOOL selected); + void selectAllTEs(BOOL b); + void selectTE(S32 te_index, BOOL selected); void selectGLTFNode(S32 node_index, S32 primitive_index, bool selected); - BOOL isTESelected(S32 te_index) const; - bool hasSelectedTE() const { return TE_SELECT_MASK_ALL & mTESelectMask; } - S32 getLastSelectedTE() const; - S32 getLastOperatedTE() const { return mLastTESelected; } - S32 getTESelectMask() { return mTESelectMask; } - void renderOneSilhouette(const LLColor4 &color); - void setTransient(BOOL transient) { mTransient = transient; } - BOOL isTransient() const { return mTransient; } - LLViewerObject* getObject(); - void setObject(LLViewerObject* object); - // *NOTE: invalidate stored textures and colors when # faces change + BOOL isTESelected(S32 te_index) const; + bool hasSelectedTE() const { return TE_SELECT_MASK_ALL & mTESelectMask; } + S32 getLastSelectedTE() const; + S32 getLastOperatedTE() const { return mLastTESelected; } + S32 getTESelectMask() { return mTESelectMask; } + void renderOneSilhouette(const LLColor4 &color); + void setTransient(BOOL transient) { mTransient = transient; } + BOOL isTransient() const { return mTransient; } + LLViewerObject* getObject(); + void setObject(LLViewerObject* object); + // *NOTE: invalidate stored textures and colors when # faces change // Used by tools floater's color/texture pickers to restore changes - void saveColors(); - void saveShinyColors(); - void saveTextures(const uuid_vec_t& textures); - void saveTextureScaleRatios(LLRender::eTexIndex index_to_query); + void saveColors(); + void saveShinyColors(); + void saveTextures(const uuid_vec_t& textures); + void saveTextureScaleRatios(LLRender::eTexIndex index_to_query); // GLTF materials are applied to objects by ids, // overrides get applied on top of materials resulting in @@ -200,189 +200,189 @@ public: // overrides get applied in live material editor void saveGLTFMaterials(const uuid_vec_t& materials, const gltf_materials_vec_t& override_materials); - BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const; + BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const; public: - BOOL mIndividualSelection; // For root objects and objects individually selected - - BOOL mTransient; - BOOL mValid; // is extra information valid? - LLPermissions* mPermissions; - LLSaleInfo mSaleInfo; - LLAggregatePermissions mAggregatePerm; - LLAggregatePermissions mAggregateTexturePerm; - LLAggregatePermissions mAggregateTexturePermOwner; - std::string mName; - std::string mDescription; - LLCategory mCategory; - S16 mInventorySerial; - LLVector3 mSavedPositionLocal; // for interactively modifying object position - LLVector3 mLastPositionLocal; - LLVector3 mLastMoveLocal; - LLVector3d mSavedPositionGlobal; // for interactively modifying object position - LLVector3 mSavedScale; // for interactively modifying object scale - LLVector3 mLastScale; - LLQuaternion mSavedRotation; // for interactively modifying object rotation - LLQuaternion mLastRotation; - BOOL mDuplicated; - LLVector3d mDuplicatePos; - LLQuaternion mDuplicateRot; - LLUUID mItemID; - LLUUID mFolderID; - LLUUID mFromTaskID; - std::string mTouchName; - std::string mSitName; - U64 mCreationDate; - std::vector mSavedColors; - std::vector mSavedShinyColors; - uuid_vec_t mSavedTextures; - uuid_vec_t mSavedGLTFMaterialIds; + BOOL mIndividualSelection; // For root objects and objects individually selected + + BOOL mTransient; + BOOL mValid; // is extra information valid? + LLPermissions* mPermissions; + LLSaleInfo mSaleInfo; + LLAggregatePermissions mAggregatePerm; + LLAggregatePermissions mAggregateTexturePerm; + LLAggregatePermissions mAggregateTexturePermOwner; + std::string mName; + std::string mDescription; + LLCategory mCategory; + S16 mInventorySerial; + LLVector3 mSavedPositionLocal; // for interactively modifying object position + LLVector3 mLastPositionLocal; + LLVector3 mLastMoveLocal; + LLVector3d mSavedPositionGlobal; // for interactively modifying object position + LLVector3 mSavedScale; // for interactively modifying object scale + LLVector3 mLastScale; + LLQuaternion mSavedRotation; // for interactively modifying object rotation + LLQuaternion mLastRotation; + BOOL mDuplicated; + LLVector3d mDuplicatePos; + LLQuaternion mDuplicateRot; + LLUUID mItemID; + LLUUID mFolderID; + LLUUID mFromTaskID; + std::string mTouchName; + std::string mSitName; + U64 mCreationDate; + std::vector mSavedColors; + std::vector mSavedShinyColors; + uuid_vec_t mSavedTextures; + uuid_vec_t mSavedGLTFMaterialIds; gltf_materials_vec_t mSavedGLTFOverrideMaterials; - std::vector mTextureScaleRatios; - std::vector mSilhouetteVertices; // array of vertices to render silhouette of object - std::vector mSilhouetteNormals; // array of normals to render silhouette of object - BOOL mSilhouetteExists; // need to generate silhouette? + std::vector mTextureScaleRatios; + std::vector mSilhouetteVertices; // array of vertices to render silhouette of object + std::vector mSilhouetteNormals; // array of normals to render silhouette of object + BOOL mSilhouetteExists; // need to generate silhouette? S32 mSelectedGLTFNode = -1; S32 mSelectedGLTFPrimitive = -1; protected: - LLPointer mObject; - S32 mTESelectMask; - S32 mLastTESelected; - + LLPointer mObject; + S32 mTESelectMask; + S32 mLastTESelected; + }; class LLObjectSelection : public LLRefCount { - friend class LLSelectMgr; - friend class LLSafeHandle; - friend class LLSelectionCallbackData; + friend class LLSelectMgr; + friend class LLSafeHandle; + friend class LLSelectionCallbackData; protected: - ~LLObjectSelection(); + ~LLObjectSelection(); public: - typedef std::list list_t; - - // Iterators - struct is_non_null - { - bool operator()(LLSelectNode* node) - { - return (node->getObject() != NULL); - } - }; - typedef boost::filter_iterator iterator; - iterator begin() { return iterator(mList.begin(), mList.end()); } - iterator end() { return iterator(mList.end(), mList.end()); } - - struct is_valid - { - bool operator()(LLSelectNode* node) - { - return (node->getObject() != NULL) && node->mValid; - } - }; - typedef boost::filter_iterator valid_iterator; - valid_iterator valid_begin() { return valid_iterator(mList.begin(), mList.end()); } - valid_iterator valid_end() { return valid_iterator(mList.end(), mList.end()); } - - struct is_root - { - bool operator()(LLSelectNode* node); - }; - typedef boost::filter_iterator root_iterator; - root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); } - root_iterator root_end() { return root_iterator(mList.end(), mList.end()); } - - struct is_valid_root - { - bool operator()(LLSelectNode* node); - }; - typedef boost::filter_iterator valid_root_iterator; - valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); } - valid_root_iterator valid_root_end() { return valid_root_iterator(mList.end(), mList.end()); } - - struct is_root_object - { - bool operator()(LLSelectNode* node); - }; - typedef boost::filter_iterator root_object_iterator; - root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); } - root_object_iterator root_object_end() { return root_object_iterator(mList.end(), mList.end()); } - + typedef std::list list_t; + + // Iterators + struct is_non_null + { + bool operator()(LLSelectNode* node) + { + return (node->getObject() != NULL); + } + }; + typedef boost::filter_iterator iterator; + iterator begin() { return iterator(mList.begin(), mList.end()); } + iterator end() { return iterator(mList.end(), mList.end()); } + + struct is_valid + { + bool operator()(LLSelectNode* node) + { + return (node->getObject() != NULL) && node->mValid; + } + }; + typedef boost::filter_iterator valid_iterator; + valid_iterator valid_begin() { return valid_iterator(mList.begin(), mList.end()); } + valid_iterator valid_end() { return valid_iterator(mList.end(), mList.end()); } + + struct is_root + { + bool operator()(LLSelectNode* node); + }; + typedef boost::filter_iterator root_iterator; + root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); } + root_iterator root_end() { return root_iterator(mList.end(), mList.end()); } + + struct is_valid_root + { + bool operator()(LLSelectNode* node); + }; + typedef boost::filter_iterator valid_root_iterator; + valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); } + valid_root_iterator valid_root_end() { return valid_root_iterator(mList.end(), mList.end()); } + + struct is_root_object + { + bool operator()(LLSelectNode* node); + }; + typedef boost::filter_iterator root_object_iterator; + root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); } + root_object_iterator root_object_end() { return root_object_iterator(mList.end(), mList.end()); } + public: - LLObjectSelection(); - - void updateEffects(); - - BOOL isEmpty() const; - - LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = NULL); - LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = NULL, BOOL non_root_ok = FALSE); - LLViewerObject* getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent = FALSE); - LLViewerObject* getFirstObject(); - LLViewerObject* getFirstRootObject(BOOL non_root_ok = FALSE); - - LLSelectNode* getFirstMoveableNode(BOOL get_root_first = FALSE); - - LLViewerObject* getFirstEditableObject(BOOL get_parent = FALSE); - LLViewerObject* getFirstCopyableObject(BOOL get_parent = FALSE); - LLViewerObject* getFirstDeleteableObject(); - LLViewerObject* getFirstMoveableObject(BOOL get_parent = FALSE); - LLViewerObject* getFirstUndoEnabledObject(BOOL get_parent = FALSE); - - /// Return the object that lead to this selection, possible a child - LLViewerObject* getPrimaryObject() { return mPrimaryObject; } - - // iterate through texture entries - template bool getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res, bool has_tolerance = false, T tolerance = T()); - template bool isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value); - - S32 getNumNodes(); - LLSelectNode* findNode(LLViewerObject* objectp); - - // count members - S32 getObjectCount(); - F32 getSelectedObjectCost(); - F32 getSelectedLinksetCost(); - F32 getSelectedPhysicsCost(); - F32 getSelectedLinksetPhysicsCost(); - S32 getSelectedObjectRenderCost(); - - F32 getSelectedObjectStreamingCost(S32* total_bytes = NULL, S32* visible_bytes = NULL); - U32 getSelectedObjectTriangleCount(S32* vcount = NULL); - - S32 getTECount(); - S32 getRootObjectCount(); - - BOOL isMultipleTESelected(); - BOOL contains(LLViewerObject* object); - BOOL contains(LLViewerObject* object, S32 te); - - // returns TRUE is any node is currenly worn as an attachment - BOOL isAttachment(); + LLObjectSelection(); + + void updateEffects(); + + BOOL isEmpty() const; + + LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = NULL); + LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = NULL, BOOL non_root_ok = FALSE); + LLViewerObject* getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent = FALSE); + LLViewerObject* getFirstObject(); + LLViewerObject* getFirstRootObject(BOOL non_root_ok = FALSE); + + LLSelectNode* getFirstMoveableNode(BOOL get_root_first = FALSE); + + LLViewerObject* getFirstEditableObject(BOOL get_parent = FALSE); + LLViewerObject* getFirstCopyableObject(BOOL get_parent = FALSE); + LLViewerObject* getFirstDeleteableObject(); + LLViewerObject* getFirstMoveableObject(BOOL get_parent = FALSE); + LLViewerObject* getFirstUndoEnabledObject(BOOL get_parent = FALSE); + + /// Return the object that lead to this selection, possible a child + LLViewerObject* getPrimaryObject() { return mPrimaryObject; } + + // iterate through texture entries + template bool getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res, bool has_tolerance = false, T tolerance = T()); + template bool isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value); + + S32 getNumNodes(); + LLSelectNode* findNode(LLViewerObject* objectp); + + // count members + S32 getObjectCount(); + F32 getSelectedObjectCost(); + F32 getSelectedLinksetCost(); + F32 getSelectedPhysicsCost(); + F32 getSelectedLinksetPhysicsCost(); + S32 getSelectedObjectRenderCost(); + + F32 getSelectedObjectStreamingCost(S32* total_bytes = NULL, S32* visible_bytes = NULL); + U32 getSelectedObjectTriangleCount(S32* vcount = NULL); + + S32 getTECount(); + S32 getRootObjectCount(); + + BOOL isMultipleTESelected(); + BOOL contains(LLViewerObject* object); + BOOL contains(LLViewerObject* object, S32 te); + + // returns TRUE is any node is currenly worn as an attachment + BOOL isAttachment(); bool checkAnimatedObjectEstTris(); bool checkAnimatedObjectLinkable(); - - // Apply functors to various subsets of the selected objects - // If firstonly is FALSE, returns the AND of all apply() calls. - // Else returns TRUE immediately if any apply() call succeeds (i.e. OR with early exit) - bool applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly = false); - bool applyToObjects(LLSelectedObjectFunctor* func); - bool applyToTEs(LLSelectedTEFunctor* func, bool firstonly = false); - bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false); - bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); - - /* - * Used to apply (no-copy) textures to the selected object or - * selected face/faces of the object. - * This method moves (no-copy) texture to the object's inventory - * and doesn't make copy of the texture for each face. - * Then this only texture is used for all selected faces. - */ - void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); + + // Apply functors to various subsets of the selected objects + // If firstonly is FALSE, returns the AND of all apply() calls. + // Else returns TRUE immediately if any apply() call succeeds (i.e. OR with early exit) + bool applyToRootObjects(LLSelectedObjectFunctor* func, bool firstonly = false); + bool applyToObjects(LLSelectedObjectFunctor* func); + bool applyToTEs(LLSelectedTEFunctor* func, bool firstonly = false); + bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false); + bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); + + /* + * Used to apply (no-copy) textures to the selected object or + * selected face/faces of the object. + * This method moves (no-copy) texture to the object's inventory + * and doesn't make copy of the texture for each face. + * Then this only texture is used for all selected faces. + */ + void applyNoCopyTextureToTEs(LLViewerInventoryItem* item); /* * Multi-purpose function for applying PBR materials to the * selected object or faces, any combination of copy/mod/transfer @@ -395,24 +395,24 @@ public: */ bool applyRestrictedPbrMaterialToTEs(LLViewerInventoryItem* item); - ESelectType getSelectType() const { return mSelectType; } + ESelectType getSelectType() const { return mSelectType; } private: - void addNode(LLSelectNode *nodep); - void addNodeAtEnd(LLSelectNode *nodep); - void moveNodeToFront(LLSelectNode *nodep); - void removeNode(LLSelectNode *nodep); - void deleteAllNodes(); - void cleanupNodes(); + void addNode(LLSelectNode *nodep); + void addNodeAtEnd(LLSelectNode *nodep); + void moveNodeToFront(LLSelectNode *nodep); + void removeNode(LLSelectNode *nodep); + void deleteAllNodes(); + void cleanupNodes(); private: - list_t mList; - const LLObjectSelection &operator=(const LLObjectSelection &); + list_t mList; + const LLObjectSelection &operator=(const LLObjectSelection &); - LLPointer mPrimaryObject; - std::map, LLSelectNode*> mSelectNodeMap; - ESelectType mSelectType; + LLPointer mPrimaryObject; + std::map, LLSelectNode*> mSelectNodeMap; + ESelectType mSelectType; }; typedef LLSafeHandle LLObjectSelectionHandle; @@ -430,70 +430,70 @@ class LLSelectionCallbackData { public: LLSelectionCallbackData(); - LLObjectSelectionHandle getSelection() { return mSelectedObjects; } + LLObjectSelectionHandle getSelection() { return mSelectedObjects; } private: - LLObjectSelectionHandle mSelectedObjects; + LLObjectSelectionHandle mSelectedObjects; }; class LLSelectMgr : public LLEditMenuHandler, public LLSimpleton { public: - static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? - static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? - static BOOL sRenderLightRadius; // do we show the radius of selected lights? - - static F32 sHighlightThickness; - static F32 sHighlightUScale; - static F32 sHighlightVScale; - static F32 sHighlightAlpha; - static F32 sHighlightAlphaTest; - static F32 sHighlightUAnim; - static F32 sHighlightVAnim; - static LLColor4 sSilhouetteParentColor; - static LLColor4 sSilhouetteChildColor; - static LLColor4 sHighlightParentColor; - static LLColor4 sHighlightChildColor; - static LLColor4 sHighlightInspectColor; - static LLColor4 sContextSilhouetteColor; - - LLCachedControl mHideSelectedObjects; - LLCachedControl mRenderHighlightSelections; - LLCachedControl mAllowSelectAvatar; - LLCachedControl mDebugSelectMgr; + static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? + static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? + static BOOL sRenderLightRadius; // do we show the radius of selected lights? + + static F32 sHighlightThickness; + static F32 sHighlightUScale; + static F32 sHighlightVScale; + static F32 sHighlightAlpha; + static F32 sHighlightAlphaTest; + static F32 sHighlightUAnim; + static F32 sHighlightVAnim; + static LLColor4 sSilhouetteParentColor; + static LLColor4 sSilhouetteChildColor; + static LLColor4 sHighlightParentColor; + static LLColor4 sHighlightChildColor; + static LLColor4 sHighlightInspectColor; + static LLColor4 sContextSilhouetteColor; + + LLCachedControl mHideSelectedObjects; + LLCachedControl mRenderHighlightSelections; + LLCachedControl mAllowSelectAvatar; + LLCachedControl mDebugSelectMgr; public: LLSelectMgr(); ~LLSelectMgr(); - static void cleanupGlobals(); + static void cleanupGlobals(); - // LLEditMenuHandler interface - virtual BOOL canUndo() const; - virtual void undo(); + // LLEditMenuHandler interface + virtual BOOL canUndo() const; + virtual void undo(); - virtual BOOL canRedo() const; - virtual void redo(); + virtual BOOL canRedo() const; + virtual void redo(); - virtual BOOL canDoDelete() const; - virtual void doDelete(); + virtual BOOL canDoDelete() const; + virtual void doDelete(); - virtual void deselect(); - virtual BOOL canDeselect() const; + virtual void deselect(); + virtual BOOL canDeselect() const; - virtual void duplicate(); - virtual BOOL canDuplicate() const; + virtual void duplicate(); + virtual BOOL canDuplicate() const; - void clearSelections(); - void update(); - void updateEffects(); // Update HUD effects + void clearSelections(); + void update(); + void updateEffects(); // Update HUD effects - // When we edit object's position/rotation/scale we set local - // overrides and ignore any updates (override received valeus). - // When we send data to server, we send local values and reset - // overrides - void resetObjectOverrides(); - void resetObjectOverrides(LLObjectSelectionHandle selected_handle); - void overrideObjectUpdates(); + // When we edit object's position/rotation/scale we set local + // overrides and ignore any updates (override received valeus). + // When we send data to server, we send local values and reset + // overrides + void resetObjectOverrides(); + void resetObjectOverrides(LLObjectSelectionHandle selected_handle); + void overrideObjectUpdates(); void resetAvatarOverrides(); void overrideAvatarUpdates(); @@ -519,430 +519,430 @@ public: public: - // Returns the previous value of mForceSelection - BOOL setForceSelection(BOOL force); + // Returns the previous value of mForceSelection + BOOL setForceSelection(BOOL force); - //////////////////////////////////////////////////////////////// - // Selection methods - //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + // Selection methods + //////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////// - // Add - //////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// + // Add + //////////////////////////////////////////////////////////////// - // This method is meant to select an object, and then select all - // of the ancestors and descendants. This should be the normal behavior. - // - // *NOTE: You must hold on to the object selection handle, otherwise - // the objects will be automatically deselected in 1 frame. - LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE, BOOL ignore_select_owned = FALSE); + // This method is meant to select an object, and then select all + // of the ancestors and descendants. This should be the normal behavior. + // + // *NOTE: You must hold on to the object selection handle, otherwise + // the objects will be automatically deselected in 1 frame. + LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE, BOOL ignore_select_owned = FALSE); - // For when you want just a child object. + // For when you want just a child object. LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES, S32 gltf_node = -1, S32 gltf_primitive = -1); - // Same as above, but takes a list of objects. Used by rectangle select. - LLObjectSelectionHandle selectObjectAndFamily(const std::vector& object_list, BOOL send_to_sim = TRUE); + // Same as above, but takes a list of objects. Used by rectangle select. + LLObjectSelectionHandle selectObjectAndFamily(const std::vector& object_list, BOOL send_to_sim = TRUE); + + // converts all objects currently highlighted to a selection, and returns it + LLObjectSelectionHandle selectHighlightedObjects(); + + LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1); + LLSelectNode *getHoverNode(); + LLSelectNode *getPrimaryHoverNode(); - // converts all objects currently highlighted to a selection, and returns it - LLObjectSelectionHandle selectHighlightedObjects(); + void highlightObjectOnly(LLViewerObject *objectp); + void highlightObjectAndFamily(LLViewerObject *objectp); + void highlightObjectAndFamily(const std::vector& list); - LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1); - LLSelectNode *getHoverNode(); - LLSelectNode *getPrimaryHoverNode(); + //////////////////////////////////////////////////////////////// + // Remove + //////////////////////////////////////////////////////////////// - void highlightObjectOnly(LLViewerObject *objectp); - void highlightObjectAndFamily(LLViewerObject *objectp); - void highlightObjectAndFamily(const std::vector& list); + void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE); + void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE, BOOL include_entire_object = FALSE); - //////////////////////////////////////////////////////////////// - // Remove - //////////////////////////////////////////////////////////////// + // Send deselect messages to simulator, then clear the list + void deselectAll(); + void deselectAllForStandingUp(); - void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE); - void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE, BOOL include_entire_object = FALSE); + // deselect only if nothing else currently referencing the selection + void deselectUnused(); - // Send deselect messages to simulator, then clear the list - void deselectAll(); - void deselectAllForStandingUp(); + // Deselect if the selection center is too far away from the agent. + void deselectAllIfTooFar(); - // deselect only if nothing else currently referencing the selection - void deselectUnused(); + // Removes all highlighted objects from current selection + void deselectHighlightedObjects(); - // Deselect if the selection center is too far away from the agent. - void deselectAllIfTooFar(); + void unhighlightObjectOnly(LLViewerObject *objectp); + void unhighlightObjectAndFamily(LLViewerObject *objectp); + void unhighlightAll(); - // Removes all highlighted objects from current selection - void deselectHighlightedObjects(); + BOOL removeObjectFromSelections(const LLUUID &id); - void unhighlightObjectOnly(LLViewerObject *objectp); - void unhighlightObjectAndFamily(LLViewerObject *objectp); - void unhighlightAll(); + //////////////////////////////////////////////////////////////// + // Selection editing + //////////////////////////////////////////////////////////////// + bool linkObjects(); - BOOL removeObjectFromSelections(const LLUUID &id); + bool unlinkObjects(); - //////////////////////////////////////////////////////////////// - // Selection editing - //////////////////////////////////////////////////////////////// - bool linkObjects(); + void confirmUnlinkObjects(const LLSD& notification, const LLSD& response); - bool unlinkObjects(); + bool enableLinkObjects(); - void confirmUnlinkObjects(const LLSD& notification, const LLSD& response); + bool enableUnlinkObjects(); - bool enableLinkObjects(); + //////////////////////////////////////////////////////////////// + // Selection accessors + //////////////////////////////////////////////////////////////// + LLObjectSelectionHandle getSelection() { return mSelectedObjects; } + // right now this just renders the selection with root/child colors instead of a single color + LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } + LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } - bool enableUnlinkObjects(); + //////////////////////////////////////////////////////////////// + // Grid manipulation + //////////////////////////////////////////////////////////////// + void addGridObject(LLViewerObject* objectp); + void clearGridObjects(); + void setGridMode(EGridMode mode); + EGridMode getGridMode() { return mGridMode; } + void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale, bool for_snap_guides = false); - //////////////////////////////////////////////////////////////// - // Selection accessors - //////////////////////////////////////////////////////////////// - LLObjectSelectionHandle getSelection() { return mSelectedObjects; } - // right now this just renders the selection with root/child colors instead of a single color - LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } - LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } + BOOL getTEMode() const { return mTEMode; } + void setTEMode(BOOL b) { mTEMode = b; } - //////////////////////////////////////////////////////////////// - // Grid manipulation - //////////////////////////////////////////////////////////////// - void addGridObject(LLViewerObject* objectp); - void clearGridObjects(); - void setGridMode(EGridMode mode); - EGridMode getGridMode() { return mGridMode; } - void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale, bool for_snap_guides = false); + BOOL shouldShowSelection() const { return mShowSelection; } - BOOL getTEMode() const { return mTEMode; } - void setTEMode(BOOL b) { mTEMode = b; } + LLBBox getBBoxOfSelection() const; + LLBBox getSavedBBoxOfSelection() const { return mSavedSelectionBBox; } - BOOL shouldShowSelection() const { return mShowSelection; } + void dump(); + void cleanup(); - LLBBox getBBoxOfSelection() const; - LLBBox getSavedBBoxOfSelection() const { return mSavedSelectionBBox; } + void updateSilhouettes(); + void renderSilhouettes(BOOL for_hud); + void enableSilhouette(BOOL enable) { mRenderSilhouettes = enable; } - void dump(); - void cleanup(); + //////////////////////////////////////////////////////////////// + // Utility functions that operate on the current selection + //////////////////////////////////////////////////////////////// + void saveSelectedObjectTransform(EActionType action_type); + void saveSelectedObjectColors(); + void saveSelectedShinyColors(); + void saveSelectedObjectTextures(); - void updateSilhouettes(); - void renderSilhouettes(BOOL for_hud); - void enableSilhouette(BOOL enable) { mRenderSilhouettes = enable; } - - //////////////////////////////////////////////////////////////// - // Utility functions that operate on the current selection - //////////////////////////////////////////////////////////////// - void saveSelectedObjectTransform(EActionType action_type); - void saveSelectedObjectColors(); - void saveSelectedShinyColors(); - void saveSelectedObjectTextures(); + void selectionUpdatePhysics(BOOL use_physics); + void selectionUpdateTemporary(BOOL is_temporary); + void selectionUpdatePhantom(BOOL is_ghost); + void selectionDump(); - void selectionUpdatePhysics(BOOL use_physics); - void selectionUpdateTemporary(BOOL is_temporary); - void selectionUpdatePhantom(BOOL is_ghost); - void selectionDump(); + BOOL selectionAllPCode(LLPCode code); // all objects have this PCode + BOOL selectionGetClickAction(U8 *out_action); + bool selectionGetIncludeInSearch(bool* include_in_search_out); // true if all selected objects have same + BOOL selectionGetGlow(F32 *glow); - BOOL selectionAllPCode(LLPCode code); // all objects have this PCode - BOOL selectionGetClickAction(U8 *out_action); - bool selectionGetIncludeInSearch(bool* include_in_search_out); // true if all selected objects have same - BOOL selectionGetGlow(F32 *glow); - - void selectionSetPhysicsType(U8 type); - void selectionSetGravity(F32 gravity); - void selectionSetFriction(F32 friction); - void selectionSetDensity(F32 density); - void selectionSetRestitution(F32 restitution); - void selectionSetMaterial(U8 material); - bool selectionSetImage(const LLUUID& imageid); // could be item or asset id + void selectionSetPhysicsType(U8 type); + void selectionSetGravity(F32 gravity); + void selectionSetFriction(F32 friction); + void selectionSetDensity(F32 density); + void selectionSetRestitution(F32 restitution); + void selectionSetMaterial(U8 material); + bool selectionSetImage(const LLUUID& imageid); // could be item or asset id bool selectionSetGLTFMaterial(const LLUUID& mat_id); // material id only - void selectionSetColor(const LLColor4 &color); - void selectionSetColorOnly(const LLColor4 &color); // Set only the RGB channels - void selectionSetAlphaOnly(const F32 alpha); // Set only the alpha channel - void selectionRevertColors(); - void selectionRevertShinyColors(); - BOOL selectionRevertTextures(); + void selectionSetColor(const LLColor4 &color); + void selectionSetColorOnly(const LLColor4 &color); // Set only the RGB channels + void selectionSetAlphaOnly(const F32 alpha); // Set only the alpha channel + void selectionRevertColors(); + void selectionRevertShinyColors(); + BOOL selectionRevertTextures(); void selectionRevertGLTFMaterials(); - void selectionSetBumpmap( U8 bumpmap, const LLUUID &image_id ); - void selectionSetTexGen( U8 texgen ); - void selectionSetShiny( U8 shiny, const LLUUID &image_id ); - void selectionSetFullbright( U8 fullbright ); - void selectionSetMedia( U8 media_type, const LLSD &media_data ); - void selectionSetClickAction(U8 action); - void selectionSetIncludeInSearch(bool include_in_search); - void selectionSetGlow(const F32 glow); - void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); - void selectionRemoveMaterial(); - - void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); - void selectionSetObjectName(const std::string& name); - void selectionSetObjectDescription(const std::string& desc); - void selectionSetObjectCategory(const LLCategory& category); - void selectionSetObjectSaleInfo(const LLSaleInfo& sale_info); - - void selectionTexScaleAutofit(F32 repeats_per_meter); - void adjustTexturesByScale(BOOL send_to_sim, BOOL stretch); - - bool selectionMove(const LLVector3& displ, F32 rx, F32 ry, F32 rz, - U32 update_type); - void sendSelectionMove(); - - void sendGodlikeRequest(const std::string& request, const std::string& parameter); - - - // will make sure all selected object meet current criteria, or deselect them otherwise - void validateSelection(); - - // returns TRUE if it is possible to select this object - BOOL canSelectObject(LLViewerObject* object, BOOL ignore_select_owned = FALSE); - - // Returns TRUE if the viewer has information on all selected objects - BOOL selectGetAllRootsValid(); - BOOL selectGetAllValid(); - BOOL selectGetAllValidAndObjectsFound(); - - // returns TRUE if you can modify all selected objects. - BOOL selectGetRootsModify(); - BOOL selectGetModify(); - - // returns TRUE if all objects are in same region - BOOL selectGetSameRegion(); - - // returns TRUE if is all objects are non-permanent-enforced - BOOL selectGetRootsNonPermanentEnforced(); - BOOL selectGetNonPermanentEnforced(); - - // returns TRUE if is all objects are permanent - BOOL selectGetRootsPermanent(); - BOOL selectGetPermanent(); - - // returns TRUE if is all objects are character - BOOL selectGetRootsCharacter(); - BOOL selectGetCharacter(); - - // returns TRUE if is all objects are not permanent - BOOL selectGetRootsNonPathfinding(); - BOOL selectGetNonPathfinding(); - - // returns TRUE if is all objects are not permanent - BOOL selectGetRootsNonPermanent(); - BOOL selectGetNonPermanent(); - - // returns TRUE if is all objects are not character - BOOL selectGetRootsNonCharacter(); - BOOL selectGetNonCharacter(); - - BOOL selectGetEditableLinksets(); - BOOL selectGetViewableCharacters(); - - // returns TRUE if selected objects can be transferred. - BOOL selectGetRootsTransfer(); - - // returns TRUE if selected objects can be copied. - BOOL selectGetRootsCopy(); - - BOOL selectGetCreator(LLUUID& id, std::string& name); // TRUE if all have same creator, returns id - BOOL selectGetOwner(LLUUID& id, std::string& name); // TRUE if all objects have same owner, returns id - BOOL selectGetLastOwner(LLUUID& id, std::string& name); // TRUE if all objects have same owner, returns id - - // returns TRUE if all are the same. id is stuffed with - // the value found if available. - BOOL selectGetGroup(LLUUID& id); - BOOL selectGetPerm( U8 which_perm, U32* mask_on, U32* mask_off); // TRUE if all have data, returns two masks, each indicating which bits are all on and all off - - BOOL selectIsGroupOwned(); // TRUE if all root objects have valid data and are group owned. - - // returns TRUE if all the nodes are valid. Accumulates - // permissions in the parameter. - BOOL selectGetPermissions(LLPermissions& perm); - - // returns TRUE if all the nodes are valid. Depends onto "edit linked" state - // Children in linksets are a bit special - they require not only move permission - // but also modify if "edit linked" is set, since you move them relative to parent - BOOL selectGetEditMoveLinksetPermissions(bool &move, bool &modify); - - // Get a bunch of useful sale information for the object(s) selected. - // "_mixed" is true if not all objects have the same setting. - void selectGetAggregateSaleInfo(U32 &num_for_sale, - BOOL &is_for_sale_mixed, - BOOL &is_sale_price_mixed, - S32 &total_sale_price, - S32 &individual_sale_price); - - // returns TRUE if all nodes are valid. - BOOL selectGetCategory(LLCategory& category); - - // returns TRUE if all nodes are valid. method also stores an - // accumulated sale info. - BOOL selectGetSaleInfo(LLSaleInfo& sale_info); - - // returns TRUE if all nodes are valid. fills passed in object - // with the aggregate permissions of the selection. - BOOL selectGetAggregatePermissions(LLAggregatePermissions& ag_perm); - - // returns TRUE if all nodes are valid. fills passed in object - // with the aggregate permissions for texture inventory items of the selection. - BOOL selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm); - - LLPermissions* findObjectPermissions(const LLViewerObject* object); - - BOOL isMovableAvatarSelected(); - - void selectDelete(); // Delete on simulator - void selectForceDelete(); // just delete, no into trash - void selectDuplicate(const LLVector3& offset, BOOL select_copy); // Duplicate on simulator - void repeatDuplicate(); - void selectDuplicateOnRay(const LLVector3 &ray_start_region, - const LLVector3 &ray_end_region, - BOOL bypass_raycast, - BOOL ray_end_is_intersection, - const LLUUID &ray_target_id, - BOOL copy_centers, - BOOL copy_rotates, - BOOL select_copy); - - void sendMultipleUpdate(U32 type); // Position, rotation, scale all in one - void sendOwner(const LLUUID& owner_id, const LLUUID& group_id, BOOL override = FALSE); - void sendGroup(const LLUUID& group_id); - - // Category ID is the UUID of the folder you want to contain the purchase. - // *NOTE: sale_info check doesn't work for multiple object buy, - // which UI does not currently support sale info is used for - // verification only, if it doesn't match region info then sale is - // canceled - void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info); - void sendAttach(U8 attachment_point, bool replace); - void sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace); - void sendDetach(); - void sendDropAttachment(); - void sendLink(); - void sendDelink(); - //void sendHinge(U8 type); - //void sendDehinge(); - void sendSelect(); - - void requestObjectPropertiesFamily(LLViewerObject* object); // asks sim for creator, permissions, resources, etc. - static void processObjectProperties(LLMessageSystem *mesgsys, void **user_data); - static void processObjectPropertiesFamily(LLMessageSystem *mesgsys, void **user_data); - static void processForceObjectSelect(LLMessageSystem* msg, void**); - - void requestGodInfo(); - - LLVector3d getSelectionCenterGlobal() const { return mSelectionCenterGlobal; } - void updateSelectionCenter(); + void selectionSetBumpmap( U8 bumpmap, const LLUUID &image_id ); + void selectionSetTexGen( U8 texgen ); + void selectionSetShiny( U8 shiny, const LLUUID &image_id ); + void selectionSetFullbright( U8 fullbright ); + void selectionSetMedia( U8 media_type, const LLSD &media_data ); + void selectionSetClickAction(U8 action); + void selectionSetIncludeInSearch(bool include_in_search); + void selectionSetGlow(const F32 glow); + void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func, int specific_te = -1); + void selectionRemoveMaterial(); + + void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); + void selectionSetObjectName(const std::string& name); + void selectionSetObjectDescription(const std::string& desc); + void selectionSetObjectCategory(const LLCategory& category); + void selectionSetObjectSaleInfo(const LLSaleInfo& sale_info); + + void selectionTexScaleAutofit(F32 repeats_per_meter); + void adjustTexturesByScale(BOOL send_to_sim, BOOL stretch); + + bool selectionMove(const LLVector3& displ, F32 rx, F32 ry, F32 rz, + U32 update_type); + void sendSelectionMove(); + + void sendGodlikeRequest(const std::string& request, const std::string& parameter); + + + // will make sure all selected object meet current criteria, or deselect them otherwise + void validateSelection(); + + // returns TRUE if it is possible to select this object + BOOL canSelectObject(LLViewerObject* object, BOOL ignore_select_owned = FALSE); + + // Returns TRUE if the viewer has information on all selected objects + BOOL selectGetAllRootsValid(); + BOOL selectGetAllValid(); + BOOL selectGetAllValidAndObjectsFound(); + + // returns TRUE if you can modify all selected objects. + BOOL selectGetRootsModify(); + BOOL selectGetModify(); + + // returns TRUE if all objects are in same region + BOOL selectGetSameRegion(); + + // returns TRUE if is all objects are non-permanent-enforced + BOOL selectGetRootsNonPermanentEnforced(); + BOOL selectGetNonPermanentEnforced(); + + // returns TRUE if is all objects are permanent + BOOL selectGetRootsPermanent(); + BOOL selectGetPermanent(); + + // returns TRUE if is all objects are character + BOOL selectGetRootsCharacter(); + BOOL selectGetCharacter(); + + // returns TRUE if is all objects are not permanent + BOOL selectGetRootsNonPathfinding(); + BOOL selectGetNonPathfinding(); + + // returns TRUE if is all objects are not permanent + BOOL selectGetRootsNonPermanent(); + BOOL selectGetNonPermanent(); + + // returns TRUE if is all objects are not character + BOOL selectGetRootsNonCharacter(); + BOOL selectGetNonCharacter(); + + BOOL selectGetEditableLinksets(); + BOOL selectGetViewableCharacters(); + + // returns TRUE if selected objects can be transferred. + BOOL selectGetRootsTransfer(); + + // returns TRUE if selected objects can be copied. + BOOL selectGetRootsCopy(); + + BOOL selectGetCreator(LLUUID& id, std::string& name); // TRUE if all have same creator, returns id + BOOL selectGetOwner(LLUUID& id, std::string& name); // TRUE if all objects have same owner, returns id + BOOL selectGetLastOwner(LLUUID& id, std::string& name); // TRUE if all objects have same owner, returns id + + // returns TRUE if all are the same. id is stuffed with + // the value found if available. + BOOL selectGetGroup(LLUUID& id); + BOOL selectGetPerm( U8 which_perm, U32* mask_on, U32* mask_off); // TRUE if all have data, returns two masks, each indicating which bits are all on and all off + + BOOL selectIsGroupOwned(); // TRUE if all root objects have valid data and are group owned. + + // returns TRUE if all the nodes are valid. Accumulates + // permissions in the parameter. + BOOL selectGetPermissions(LLPermissions& perm); + + // returns TRUE if all the nodes are valid. Depends onto "edit linked" state + // Children in linksets are a bit special - they require not only move permission + // but also modify if "edit linked" is set, since you move them relative to parent + BOOL selectGetEditMoveLinksetPermissions(bool &move, bool &modify); + + // Get a bunch of useful sale information for the object(s) selected. + // "_mixed" is true if not all objects have the same setting. + void selectGetAggregateSaleInfo(U32 &num_for_sale, + BOOL &is_for_sale_mixed, + BOOL &is_sale_price_mixed, + S32 &total_sale_price, + S32 &individual_sale_price); + + // returns TRUE if all nodes are valid. + BOOL selectGetCategory(LLCategory& category); + + // returns TRUE if all nodes are valid. method also stores an + // accumulated sale info. + BOOL selectGetSaleInfo(LLSaleInfo& sale_info); + + // returns TRUE if all nodes are valid. fills passed in object + // with the aggregate permissions of the selection. + BOOL selectGetAggregatePermissions(LLAggregatePermissions& ag_perm); + + // returns TRUE if all nodes are valid. fills passed in object + // with the aggregate permissions for texture inventory items of the selection. + BOOL selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm); + + LLPermissions* findObjectPermissions(const LLViewerObject* object); + + BOOL isMovableAvatarSelected(); + + void selectDelete(); // Delete on simulator + void selectForceDelete(); // just delete, no into trash + void selectDuplicate(const LLVector3& offset, BOOL select_copy); // Duplicate on simulator + void repeatDuplicate(); + void selectDuplicateOnRay(const LLVector3 &ray_start_region, + const LLVector3 &ray_end_region, + BOOL bypass_raycast, + BOOL ray_end_is_intersection, + const LLUUID &ray_target_id, + BOOL copy_centers, + BOOL copy_rotates, + BOOL select_copy); + + void sendMultipleUpdate(U32 type); // Position, rotation, scale all in one + void sendOwner(const LLUUID& owner_id, const LLUUID& group_id, BOOL override = FALSE); + void sendGroup(const LLUUID& group_id); + + // Category ID is the UUID of the folder you want to contain the purchase. + // *NOTE: sale_info check doesn't work for multiple object buy, + // which UI does not currently support sale info is used for + // verification only, if it doesn't match region info then sale is + // canceled + void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info); + void sendAttach(U8 attachment_point, bool replace); + void sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace); + void sendDetach(); + void sendDropAttachment(); + void sendLink(); + void sendDelink(); + //void sendHinge(U8 type); + //void sendDehinge(); + void sendSelect(); + + void requestObjectPropertiesFamily(LLViewerObject* object); // asks sim for creator, permissions, resources, etc. + static void processObjectProperties(LLMessageSystem *mesgsys, void **user_data); + static void processObjectPropertiesFamily(LLMessageSystem *mesgsys, void **user_data); + static void processForceObjectSelect(LLMessageSystem* msg, void**); + + void requestGodInfo(); + + LLVector3d getSelectionCenterGlobal() const { return mSelectionCenterGlobal; } + void updateSelectionCenter(); void pauseAssociatedAvatars(); - void resetAgentHUDZoom(); - void setAgentHUDZoom(F32 target_zoom, F32 current_zoom); - void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; + void resetAgentHUDZoom(); + void setAgentHUDZoom(F32 target_zoom, F32 current_zoom); + void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; - void updatePointAt(); + void updatePointAt(); - // Internal list maintenance functions. TODO: Make these private! - void remove(std::vector& objects); - void remove(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE); - void removeAll(); - void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE, S32 gltf_node = -1, S32 gltf_primitive = -1); - void promoteSelectionToRoot(); - void demoteSelectionToIndividuals(); + // Internal list maintenance functions. TODO: Make these private! + void remove(std::vector& objects); + void remove(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE); + void removeAll(); + void addAsIndividual(LLViewerObject* object, S32 te = SELECT_ALL_TES, BOOL undoable = TRUE, S32 gltf_node = -1, S32 gltf_primitive = -1); + void promoteSelectionToRoot(); + void demoteSelectionToIndividuals(); private: - void convertTransient(); // converts temporarily selected objects to full-fledged selections - ESelectType getSelectTypeForObject(LLViewerObject* object); - void addAsFamily(std::vector& objects, BOOL add_to_end = FALSE); - void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point); - void updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector& changed_objects); - // Send one message to each region containing an object on selection list. - void sendListToRegions( const std::string& message_name, - void (*pack_header)(void *user_data), - void (*pack_body)(LLSelectNode* node, void *user_data), - void (*log_func)(LLSelectNode* node, void *user_data), - void *user_data, - ESendType send_type); - void sendListToRegions( LLObjectSelectionHandle selected_handle, - const std::string& message_name, - void (*pack_header)(void *user_data), - void (*pack_body)(LLSelectNode* node, void *user_data), - void (*log_func)(LLSelectNode* node, void *user_data), - void *user_data, - ESendType send_type); - - - static void packAgentID( void *); - static void packAgentAndSessionID(void* user_data); - static void packAgentAndGroupID(void* user_data); - static void packAgentAndSessionAndGroupID(void* user_data); - static void packAgentIDAndSessionAndAttachment(void*); - static void packAgentGroupAndCatID(void*); - static void packDeleteHeader(void* userdata); - static void packDeRezHeader(void* user_data); - static void packObjectID( LLSelectNode* node, void *); - static void packObjectIDAsParam(LLSelectNode* node, void *); - static void packObjectIDAndRotation(LLSelectNode* node, void *); - static void packObjectLocalID(LLSelectNode* node, void *); - static void packObjectClickAction(LLSelectNode* node, void* data); - static void packObjectIncludeInSearch(LLSelectNode* node, void* data); - static void packObjectName(LLSelectNode* node, void* user_data); - static void packObjectDescription(LLSelectNode* node, void* user_data); - static void packObjectCategory(LLSelectNode* node, void* user_data); - static void packObjectSaleInfo(LLSelectNode* node, void* user_data); - static void packBuyObjectIDs(LLSelectNode* node, void* user_data); - static void packDuplicate( LLSelectNode* node, void *duplicate_data); - static void packDuplicateHeader(void*); - static void packDuplicateOnRayHead(void *user_data); - static void packPermissions(LLSelectNode* node, void *user_data); - static void packDeselect( LLSelectNode* node, void *user_data); - static void packMultipleUpdate(LLSelectNode* node, void *user_data); - static void packPhysics(LLSelectNode* node, void *user_data); - static void packShape(LLSelectNode* node, void *user_data); - static void packOwnerHead(void *user_data); - static void packHingeHead(void *user_data); - static void packPermissionsHead(void* user_data); - static void packGodlikeHead(void* user_data); + void convertTransient(); // converts temporarily selected objects to full-fledged selections + ESelectType getSelectTypeForObject(LLViewerObject* object); + void addAsFamily(std::vector& objects, BOOL add_to_end = FALSE); + void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point); + void updateSelectionSilhouette(LLObjectSelectionHandle object_handle, S32& num_sils_genned, std::vector& changed_objects); + // Send one message to each region containing an object on selection list. + void sendListToRegions( const std::string& message_name, + void (*pack_header)(void *user_data), + void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), + void *user_data, + ESendType send_type); + void sendListToRegions( LLObjectSelectionHandle selected_handle, + const std::string& message_name, + void (*pack_header)(void *user_data), + void (*pack_body)(LLSelectNode* node, void *user_data), + void (*log_func)(LLSelectNode* node, void *user_data), + void *user_data, + ESendType send_type); + + + static void packAgentID( void *); + static void packAgentAndSessionID(void* user_data); + static void packAgentAndGroupID(void* user_data); + static void packAgentAndSessionAndGroupID(void* user_data); + static void packAgentIDAndSessionAndAttachment(void*); + static void packAgentGroupAndCatID(void*); + static void packDeleteHeader(void* userdata); + static void packDeRezHeader(void* user_data); + static void packObjectID( LLSelectNode* node, void *); + static void packObjectIDAsParam(LLSelectNode* node, void *); + static void packObjectIDAndRotation(LLSelectNode* node, void *); + static void packObjectLocalID(LLSelectNode* node, void *); + static void packObjectClickAction(LLSelectNode* node, void* data); + static void packObjectIncludeInSearch(LLSelectNode* node, void* data); + static void packObjectName(LLSelectNode* node, void* user_data); + static void packObjectDescription(LLSelectNode* node, void* user_data); + static void packObjectCategory(LLSelectNode* node, void* user_data); + static void packObjectSaleInfo(LLSelectNode* node, void* user_data); + static void packBuyObjectIDs(LLSelectNode* node, void* user_data); + static void packDuplicate( LLSelectNode* node, void *duplicate_data); + static void packDuplicateHeader(void*); + static void packDuplicateOnRayHead(void *user_data); + static void packPermissions(LLSelectNode* node, void *user_data); + static void packDeselect( LLSelectNode* node, void *user_data); + static void packMultipleUpdate(LLSelectNode* node, void *user_data); + static void packPhysics(LLSelectNode* node, void *user_data); + static void packShape(LLSelectNode* node, void *user_data); + static void packOwnerHead(void *user_data); + static void packHingeHead(void *user_data); + static void packPermissionsHead(void* user_data); + static void packGodlikeHead(void* user_data); static void logNoOp(LLSelectNode* node, void *user_data); static void logAttachmentRequest(LLSelectNode* node, void *user_data); static void logDetachRequest(LLSelectNode* node, void *user_data); - static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); + static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); - // Get the first ID that matches test and whether or not all ids are identical in selected objects. - void getFirst(LLSelectGetFirstTest* test); + // Get the first ID that matches test and whether or not all ids are identical in selected objects. + void getFirst(LLSelectGetFirstTest* test); public: - // Observer/callback support for when object selection changes or - // properties are received/updated - typedef boost::signals2::signal< void ()> update_signal_t; - update_signal_t mUpdateSignal; + // Observer/callback support for when object selection changes or + // properties are received/updated + typedef boost::signals2::signal< void ()> update_signal_t; + update_signal_t mUpdateSignal; private: - LLPointer mSilhouetteImagep; - LLObjectSelectionHandle mSelectedObjects; - LLObjectSelectionHandle mHoverObjects; - LLObjectSelectionHandle mHighlightedObjects; - std::set > mRectSelectedObjects; - - LLObjectSelection mGridObjects; - LLQuaternion mGridRotation; - LLVector3 mGridOrigin; - LLVector3 mGridScale; - EGridMode mGridMode; - - BOOL mTEMode; // render te - LLRender::eTexIndex mTextureChannel; // diff, norm, or spec, depending on UI editing mode - LLVector3d mSelectionCenterGlobal; - LLBBox mSelectionBBox; - - LLVector3d mLastSentSelectionCenterGlobal; - BOOL mShowSelection; // do we send the selection center name value and do we animate this selection? - LLVector3d mLastCameraPos; // camera position from last generation of selection silhouette - BOOL mRenderSilhouettes; // do we render the silhouette - LLBBox mSavedSelectionBBox; - - LLFrameTimer mEffectsTimer; - BOOL mForceSelection; - - std::vector mPauseRequests; + LLPointer mSilhouetteImagep; + LLObjectSelectionHandle mSelectedObjects; + LLObjectSelectionHandle mHoverObjects; + LLObjectSelectionHandle mHighlightedObjects; + std::set > mRectSelectedObjects; + + LLObjectSelection mGridObjects; + LLQuaternion mGridRotation; + LLVector3 mGridOrigin; + LLVector3 mGridScale; + EGridMode mGridMode; + + BOOL mTEMode; // render te + LLRender::eTexIndex mTextureChannel; // diff, norm, or spec, depending on UI editing mode + LLVector3d mSelectionCenterGlobal; + LLBBox mSelectionBBox; + + LLVector3d mLastSentSelectionCenterGlobal; + BOOL mShowSelection; // do we send the selection center name value and do we animate this selection? + LLVector3d mLastCameraPos; // camera position from last generation of selection silhouette + BOOL mRenderSilhouettes; // do we render the silhouette + LLBBox mSavedSelectionBBox; + + LLFrameTimer mEffectsTimer; + BOOL mForceSelection; + + std::vector mPauseRequests; }; // *DEPRECATED: For callbacks or observers, use // LLSelectMgr::getInstance()->mUpdateSignal.connect( callback ) // Update subscribers to the selection list -void dialog_refresh_all(); +void dialog_refresh_all(); // Templates //----------------------------------------------------------------------------- @@ -950,113 +950,113 @@ void dialog_refresh_all(); //----------------------------------------------------------------------------- template bool LLObjectSelection::getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res, bool has_tolerance, T tolerance) { - bool have_first = false; - bool have_selected = false; - T selected_value = T(); - - // Now iterate through all TEs to test for sameness - bool identical = TRUE; - for (iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - S32 selected_te = -1; - if (object == getPrimaryObject()) - { - selected_te = node->getLastSelectedTE(); - } - for (S32 te = 0; te < object->getNumTEs(); ++te) - { - if (!node->isTESelected(te)) - { - continue; - } - T value = func->get(object, te); - if (!have_first) - { - have_first = true; - if (!have_selected) - { - selected_value = value; - } - } - else - { - if ( value != selected_value ) - { + bool have_first = false; + bool have_selected = false; + T selected_value = T(); + + // Now iterate through all TEs to test for sameness + bool identical = TRUE; + for (iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + S32 selected_te = -1; + if (object == getPrimaryObject()) + { + selected_te = node->getLastSelectedTE(); + } + for (S32 te = 0; te < object->getNumTEs(); ++te) + { + if (!node->isTESelected(te)) + { + continue; + } + T value = func->get(object, te); + if (!have_first) + { + have_first = true; + if (!have_selected) + { + selected_value = value; + } + } + else + { + if ( value != selected_value ) + { if (!has_tolerance) { - identical = false; + identical = false; } else if (!LLCheckIdenticalFunctor::same(value, selected_value, tolerance)) { identical = false; } - } - if (te == selected_te) - { - selected_value = value; - have_selected = true; - } - } - } - if (!identical && have_selected) - { - break; - } - } - if (have_first || have_selected) - { - res = selected_value; - } - return identical; + } + if (te == selected_te) + { + selected_value = value; + have_selected = true; + } + } + } + if (!identical && have_selected) + { + break; + } + } + if (have_first || have_selected) + { + res = selected_value; + } + return identical; } // Templates //----------------------------------------------------------------------------- -// isMultipleTEValue iterate through all TEs and test for uniqueness -// with certain return value ignored when performing the test. +// isMultipleTEValue iterate through all TEs and test for uniqueness +// with certain return value ignored when performing the test. // e.g. when testing if the selection has a unique non-empty homeurl : -// you can set ignore_value = "" and it will only compare among the non-empty +// you can set ignore_value = "" and it will only compare among the non-empty // homeUrls and ignore the empty ones. //----------------------------------------------------------------------------- template bool LLObjectSelection::isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value) { - bool have_first = false; - T selected_value = T(); - - // Now iterate through all TEs to test for sameness - bool unique = TRUE; - for (iterator iter = begin(); iter != end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - for (S32 te = 0; te < object->getNumTEs(); ++te) - { - if (!node->isTESelected(te)) - { - continue; - } - T value = func->get(object, te); - if(value == ignore_value) - { - continue; - } - if (!have_first) - { - have_first = true; - } - else - { - if (value !=selected_value ) - { - unique = false; - return !unique; - } - } - } - } - return !unique; + bool have_first = false; + T selected_value = T(); + + // Now iterate through all TEs to test for sameness + bool unique = TRUE; + for (iterator iter = begin(); iter != end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + for (S32 te = 0; te < object->getNumTEs(); ++te) + { + if (!node->isTESelected(te)) + { + continue; + } + T value = func->get(object, te); + if(value == ignore_value) + { + continue; + } + if (!have_first) + { + have_first = true; + } + else + { + if (value !=selected_value ) + { + unique = false; + return !unique; + } + } + } + } + return !unique; } diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index ff9332aeee..76632a83ae 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -72,7 +72,7 @@ extern BOOL gCubeSnapshot; //========================================================================= -namespace +namespace { LLSD ensure_array_4(LLSD in, F32 fill); LLSD read_legacy_preset_data(const std::string &name, const std::string& path, LLSD &messages); @@ -185,7 +185,7 @@ void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSetti } } if (!settings) - { // The item was created as new with no settings passed in. Simulator should have given it the default for the type... check ID, + { // The item was created as new with no settings passed in. Simulator should have given it the default for the type... check ID, // no need to upload asset. LLUUID asset_id; if (pitem) @@ -246,11 +246,11 @@ void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings } } - std::stringstream buffer; + std::stringstream buffer; LLSD settingdata(settings->getSettings()); LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION); - LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), + LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) { LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback); @@ -313,7 +313,7 @@ void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, L void LLSettingsVOBase::getSettingsAsset(const LLUUID &assetId, LLSettingsVOBase::asset_download_fn callback) { gAssetStorage->getAssetData(assetId, LLAssetType::AT_SETTINGS, - [callback](const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) + [callback](const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) { onAssetDownloadComplete(asset_id, status, ext_status, callback); }, nullptr, true); @@ -503,7 +503,7 @@ LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &n if (!llsd_equals(oldsettings, oldsettings)) { - LL_WARNS("SKY") << "Conversion to/from legacy does not match!\n" + LL_WARNS("SKY") << "Conversion to/from legacy does not match!\n" << "Old: " << oldsettings << "new: " << oldsettings << LL_ENDL; } @@ -601,7 +601,7 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA { LLSD legacy(LLSD::emptyMap()); LLSD settings = psky->getSettings(); - + convertAtmosphericsToLegacy(legacy, settings); legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0); @@ -610,15 +610,15 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA legacy[SETTING_CLOUD_SCALE] = llsd::array(settings[SETTING_CLOUD_SCALE], LLSD::Real(0.0), LLSD::Real(0.0), LLSD::Real(1.0)); legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE]; legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = llsd::array(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())), - LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal()))); - legacy[SETTING_CLOUD_SHADOW] = llsd::array(settings[SETTING_CLOUD_SHADOW].asReal(), 0.0f, 0.0f, 1.0f); + LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal()))); + legacy[SETTING_CLOUD_SHADOW] = llsd::array(settings[SETTING_CLOUD_SHADOW].asReal(), 0.0f, 0.0f, 1.0f); legacy[SETTING_GAMMA] = llsd::array(settings[SETTING_GAMMA], 0.0f, 0.0f, 1.0f); legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0); legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f); legacy[SETTING_MAX_Y] = llsd::array(settings[SETTING_MAX_Y], 0.0f, 0.0f, 1.0f); legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS].asReal() / 250.0f; // convert from 0-500 -> 0-2 ala pre-FS-compat changes legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f); - + LLVector3 dir = psky->getLightDirection(); F32 phi = asin(dir.mV[2]); @@ -633,17 +633,17 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA { theta += F_PI * 2; } - + if (theta > 4 * F_PI) { theta = fmod(theta, 2 * F_PI); } - + while (phi < -F_PI) { phi += 2 * F_PI; } - + if (phi > 3 * F_PI) { phi = F_PI + fmod(phi - F_PI, 2 * F_PI); @@ -651,8 +651,8 @@ LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isA legacy[SETTING_LEGACY_EAST_ANGLE] = theta; legacy[SETTING_LEGACY_SUN_ANGLE] = phi; - - return legacy; + + return legacy; } //------------------------------------------------------------------------- @@ -669,10 +669,10 @@ void LLSettingsVOSky::updateSettings() // Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio // between sunlight and point lights in windlight to normalize point lights. // - // After some A/B comparison of relesae vs EEP, tweak to allow strength to fall below 2 + // After some A/B comparison of relesae vs EEP, tweak to allow strength to fall below 2 // at night, for better match. (mSceneLightStrength is a divisor, so lower value means brighter // local lights) - F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f); + F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f); mSceneLightStrength = 2.0f * (0.75f + sun_dynamic_range * dp); gSky.setSunAndMoonDirectionsCFR(sun_direction, moon_direction); @@ -693,11 +693,11 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) bool irradiance_pass = gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass(); LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_DEFAULT]; - { + { shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction); shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, LLViewerCamera::getInstance()->getOrigin()); - } - + } + shader = &((LLShaderUniforms*)ptarget)[LLGLSLShader::SG_SKY]; shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, light_direction); @@ -759,13 +759,13 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, sqrtf(g)*2.0); // use a modifier here so 1.0 maps to the "most desirable" default and the maximum value doesn't go off the rails } else if (psky->canAutoAdjust() && should_auto_adjust) - { // auto-adjust legacy sky to take advantage of probe ambiance + { // auto-adjust legacy sky to take advantage of probe ambiance shader->uniform3fv(LLShaderMgr::AMBIENT, (ambient * auto_adjust_ambient_scale).mV); shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, auto_adjust_hdr_scale); LLColor3 blue_horizon = getBlueHorizon() * auto_adjust_blue_horizon_scale; LLColor3 blue_density = getBlueDensity() * auto_adjust_blue_density_scale; sun_light_color = sun_light_color * auto_adjust_sun_color_scale; - + shader->uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, sun_light_color.mV); shader->uniform3fv(LLShaderMgr::BLUE_DENSITY, blue_density.mV); shader->uniform3fv(LLShaderMgr::BLUE_HORIZON, blue_horizon.mV); @@ -785,7 +785,7 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor()); shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier()); shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier()); - + shader->uniform1f(LLShaderMgr::GAMMA, g); } @@ -809,7 +809,7 @@ LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const // Following values are always present, so we can just zero these ones, but used values from defaults() LLSD sky_defaults = LLSettingsSky::defaults(); - + param_map[SETTING_CLOUD_POS_DENSITY2] = DefaultParam(LLShaderMgr::CLOUD_POS_DENSITY2, sky_defaults[SETTING_CLOUD_POS_DENSITY2]); param_map[SETTING_CLOUD_SCALE] = DefaultParam(LLShaderMgr::CLOUD_SCALE, sky_defaults[SETTING_CLOUD_SCALE]); param_map[SETTING_CLOUD_SHADOW] = DefaultParam(LLShaderMgr::CLOUD_SHADOW, sky_defaults[SETTING_CLOUD_SHADOW]); @@ -872,7 +872,7 @@ LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPreset(const std::strin return LLSettingsWater::ptr_t(); } - newsettings[SETTING_NAME] = name; + newsettings[SETTING_NAME] = name; LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList(); LLSD results = LLSettingsWater::settingValidation(newsettings, validations); if (!results["success"].asBoolean()) @@ -970,7 +970,7 @@ LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater) legacy[SETTING_LEGACY_SCALE_BELOW] = settings[SETTING_SCALE_BELOW]; legacy[SETTING_LEGACY_WAVE1_DIR] = settings[SETTING_WAVE1_DIR]; legacy[SETTING_LEGACY_WAVE2_DIR] = settings[SETTING_WAVE2_DIR]; - + return legacy; } //------------------------------------------------------------------------- @@ -983,8 +983,8 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) auto group = LLGLSLShader::SG_ANY; LLShaderUniforms* shader = &((LLShaderUniforms*)ptarget)[group]; - - { + + { F32 water_height = env.getWaterHeight(); if (LLViewerCamera::instance().cameraUnderWater()) @@ -1119,7 +1119,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n std::set notfound; // expected and correct folder sctructure is to have - // three folders in widnlight's root: days, water, skies + // three folders in widnlight's root: days, water, skies std::string base_path(gDirUtilp->getDirName(path)); std::string water_path(base_path); std::string sky_path(base_path); @@ -1210,7 +1210,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &n if (!llsd_equals(oldsettings, testsettings)) { - LL_WARNS("DAYCYCLE") << "Conversion to/from legacy does not match!\n" + LL_WARNS("DAYCYCLE") << "Conversion to/from legacy does not match!\n" << "Old: " << oldsettings << "new: " << testsettings << LL_ENDL; } @@ -1245,7 +1245,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID ®io { std::string newname = "sky:" + (*itm).first; LLSD newsettings = LLSettingsSky::translateLegacySettings((*itm).second); - + newsettings[SETTING_NAME] = newname; frames[newname] = newsettings; @@ -1284,7 +1284,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID ®io } LLSettingsDay::ptr_t dayp = std::make_shared(newsettings); - + if (dayp) { // true for validation - either validate here, or when cloning for floater. @@ -1434,34 +1434,34 @@ LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday) if (!pwater) pwater = LLSettingsVOWater::buildDefaultWater(); - + LLSD llsdwater = LLSettingsVOWater::convertToLegacy(pwater); - + CycleTrack_t &tracksky = pday->getCycleTrack(1); // first sky track std::map skys; - + LLSD llsdcycle(LLSD::emptyArray()); - + for(CycleTrack_t::iterator it = tracksky.begin(); it != tracksky.end(); ++it) { size_t hash = (*it).second->getHash(); std::stringstream name; - + name << hash; - + skys[name.str()] = std::static_pointer_cast((*it).second); - + F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first; llsdcycle.append( llsd::array(LLSD::Real(frame), name.str()) ); } LLSD llsdskylist(LLSD::emptyMap()); - + for (std::map::iterator its = skys.begin(); its != skys.end(); ++its) { LLSD llsdsky = LLSettingsVOSky::convertToLegacy((*its).second, false); llsdsky[SETTING_NAME] = (*its).first; - + llsdskylist[(*its).first] = llsdsky; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f3b5bb0565..9e05a02b7a 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llspatialpartition.cpp * @brief LLSpatialGroup class implementation and supporting functions * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -73,131 +73,131 @@ static F32 sCurMaxTexPriority = 1.f; void sg_assert(BOOL expr) { #if LL_OCTREE_PARANOIA_CHECK - if (!expr) - { - LL_ERRS() << "Octree invalid!" << LL_ENDL; - } + if (!expr) + { + LL_ERRS() << "Octree invalid!" << LL_ENDL; + } #endif } //returns: -// 0 if sphere and AABB are not intersecting -// 1 if they are -// 2 if AABB is entirely inside sphere +// 0 if sphere and AABB are not intersecting +// 1 if they are +// 2 if AABB is entirely inside sphere S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad) { - S32 ret = 2; - - LLVector3 min = center - size; - LLVector3 max = center + size; - for (U32 i = 0; i < 3; i++) - { - if (min.mV[i] > pos.mV[i] + rad || - max.mV[i] < pos.mV[i] - rad) - { //totally outside - return 0; - } - - if (min.mV[i] < pos.mV[i] - rad || - max.mV[i] > pos.mV[i] + rad) - { //intersecting - ret = 1; - } - } - - return ret; + S32 ret = 2; + + LLVector3 min = center - size; + LLVector3 max = center + size; + for (U32 i = 0; i < 3; i++) + { + if (min.mV[i] > pos.mV[i] + rad || + max.mV[i] < pos.mV[i] - rad) + { //totally outside + return 0; + } + + if (min.mV[i] < pos.mV[i] - rad || + max.mV[i] > pos.mV[i] + rad) + { //intersecting + ret = 1; + } + } + + return ret; } LLSpatialGroup::~LLSpatialGroup() { - /*if (sNoDelete) - { - LL_ERRS() << "Illegal deletion of LLSpatialGroup!" << LL_ENDL; - }*/ + /*if (sNoDelete) + { + LL_ERRS() << "Illegal deletion of LLSpatialGroup!" << LL_ENDL; + }*/ + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } - if (gDebugGL) - { - gPipeline.checkReferences(this); - } + if (hasState(DEAD)) + { + sZombieGroups--; + } - if (hasState(DEAD)) - { - sZombieGroups--; - } - - sNodeCount--; + sNodeCount--; - clearDrawMap(); + clearDrawMap(); } void LLSpatialGroup::clearDrawMap() { - mDrawMap.clear(); + mDrawMap.clear(); } -BOOL LLSpatialGroup::isHUDGroup() +BOOL LLSpatialGroup::isHUDGroup() { - return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; + return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; } void LLSpatialGroup::validate() { - ll_assert_aligned(this,64); + ll_assert_aligned(this,64); #if LL_OCTREE_PARANOIA_CHECK - sg_assert(!isState(DIRTY)); - sg_assert(!isDead()); - - LLVector4a myMin; - myMin.setSub(mBounds[0], mBounds[1]); - LLVector4a myMax; - myMax.setAdd(mBounds[0], mBounds[1]); - - validateDrawMap(); - - for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) - { - LLDrawable* drawable = *i; - sg_assert(drawable->getSpatialGroup() == this); - if (drawable->getSpatialBridge()) - { - sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); - } - - /*if (drawable->isSpatialBridge()) - { - LLSpatialPartition* part = drawable->asPartition(); - if (!part) - { - LL_ERRS() << "Drawable reports it is a spatial bridge but not a partition." << LL_ENDL; - } - LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - group->validate(); - }*/ - } - - for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) - { - LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); - - group->validate(); - - //ensure all children are enclosed in this node - LLVector4a center = group->mBounds[0]; - LLVector4a size = group->mBounds[1]; - - LLVector4a min; - min.setSub(center, size); - LLVector4a max; - max.setAdd(center, size); - - for (U32 j = 0; j < 3; j++) - { - sg_assert(min[j] >= myMin[j]-0.02f); - sg_assert(max[j] <= myMax[j]+0.02f); - } - } + sg_assert(!isState(DIRTY)); + sg_assert(!isDead()); + + LLVector4a myMin; + myMin.setSub(mBounds[0], mBounds[1]); + LLVector4a myMax; + myMax.setAdd(mBounds[0], mBounds[1]); + + validateDrawMap(); + + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) + { + LLDrawable* drawable = *i; + sg_assert(drawable->getSpatialGroup() == this); + if (drawable->getSpatialBridge()) + { + sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); + } + + /*if (drawable->isSpatialBridge()) + { + LLSpatialPartition* part = drawable->asPartition(); + if (!part) + { + LL_ERRS() << "Drawable reports it is a spatial bridge but not a partition." << LL_ENDL; + } + LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); + group->validate(); + }*/ + } + + for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) + { + LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); + + group->validate(); + + //ensure all children are enclosed in this node + LLVector4a center = group->mBounds[0]; + LLVector4a size = group->mBounds[1]; + + LLVector4a min; + min.setSub(center, size); + LLVector4a max; + max.setAdd(center, size); + + for (U32 j = 0; j < 3; j++) + { + sg_assert(min[j] >= myMin[j]-0.02f); + sg_assert(max[j] <= myMax[j]+0.02f); + } + } #endif } @@ -205,195 +205,195 @@ void LLSpatialGroup::validate() void LLSpatialGroup::validateDrawMap() { #if LL_OCTREE_PARANOIA_CHECK - for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; - for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) - { - LLDrawInfo& params = **j; - - params.validate(); - } - } + for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo& params = **j; + + params.validate(); + } + } #endif } BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) { LL_PROFILE_ZONE_SCOPED; - drawablep->updateSpatialExtents(); - - OctreeNode* parent = mOctreeNode->getOctParent(); - - if (mOctreeNode->isInside(drawablep->getPositionGroup()) && - (mOctreeNode->contains(drawablep->getEntry()) || - (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && - parent && parent->getElementCount() >= gOctreeMaxCapacity))) - { - unbound(); - setState(OBJECT_DIRTY); - //setState(GEOM_DIRTY); - return TRUE; - } - - return FALSE; + drawablep->updateSpatialExtents(); + + OctreeNode* parent = mOctreeNode->getOctParent(); + + if (mOctreeNode->isInside(drawablep->getPositionGroup()) && + (mOctreeNode->contains(drawablep->getEntry()) || + (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && + parent && parent->getElementCount() >= gOctreeMaxCapacity))) + { + unbound(); + setState(OBJECT_DIRTY); + //setState(GEOM_DIRTY); + return TRUE; + } + + return FALSE; } void LLSpatialGroup::expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform) { - // Get coordinates of the adding extents - const LLVector4a& min = addingExtents[0]; - const LLVector4a& max = addingExtents[1]; - - // Get coordinates of all corners of the bounding box - LLVector3 corners[] = - { - LLVector3(min[0], min[1], min[2]), - LLVector3(min[0], min[1], max[2]), - LLVector3(min[0], max[1], min[2]), - LLVector3(min[0], max[1], max[2]), - LLVector3(max[0], min[1], min[2]), - LLVector3(max[0], min[1], max[2]), - LLVector3(max[0], max[1], min[2]), - LLVector3(max[0], max[1], max[2]) - }; - - // New extents (to be expanded) - LLVector3 extents[] = - { - LLVector3(mExtents[0].getF32ptr()), - LLVector3(mExtents[1].getF32ptr()) - }; - - LLQuaternion backwardRotation = ~currentTransform.getWorldRotation(); - for (LLVector3& corner : corners) - { - // Make coordinates relative to the current position - corner -= currentTransform.getWorldPosition(); - // Rotate coordinates backward to the current rotation - corner.rotVec(backwardRotation); - // Expand root extents on the current corner - for (int j = 0; j < 3; ++j) - { - if (corner[j] < extents[0][j]) - extents[0][j] = corner[j]; - if (corner[j] > extents[1][j]) - extents[1][j] = corner[j]; - } - } - - // Set new expanded extents - mExtents[0].load3(extents[0].mV); - mExtents[1].load3(extents[1].mV); - - // Calculate new center and size - mBounds[0].setAdd(mExtents[0], mExtents[1]); - mBounds[0].mul(0.5f); - mBounds[1].setSub(mExtents[0], mExtents[1]); - mBounds[1].mul(0.5f); + // Get coordinates of the adding extents + const LLVector4a& min = addingExtents[0]; + const LLVector4a& max = addingExtents[1]; + + // Get coordinates of all corners of the bounding box + LLVector3 corners[] = + { + LLVector3(min[0], min[1], min[2]), + LLVector3(min[0], min[1], max[2]), + LLVector3(min[0], max[1], min[2]), + LLVector3(min[0], max[1], max[2]), + LLVector3(max[0], min[1], min[2]), + LLVector3(max[0], min[1], max[2]), + LLVector3(max[0], max[1], min[2]), + LLVector3(max[0], max[1], max[2]) + }; + + // New extents (to be expanded) + LLVector3 extents[] = + { + LLVector3(mExtents[0].getF32ptr()), + LLVector3(mExtents[1].getF32ptr()) + }; + + LLQuaternion backwardRotation = ~currentTransform.getWorldRotation(); + for (LLVector3& corner : corners) + { + // Make coordinates relative to the current position + corner -= currentTransform.getWorldPosition(); + // Rotate coordinates backward to the current rotation + corner.rotVec(backwardRotation); + // Expand root extents on the current corner + for (int j = 0; j < 3; ++j) + { + if (corner[j] < extents[0][j]) + extents[0][j] = corner[j]; + if (corner[j] > extents[1][j]) + extents[1][j] = corner[j]; + } + } + + // Set new expanded extents + mExtents[0].load3(extents[0].mV); + mExtents[1].load3(extents[1].mV); + + // Calculate new center and size + mBounds[0].setAdd(mExtents[0], mExtents[1]); + mBounds[0].mul(0.5f); + mBounds[1].setSub(mExtents[0], mExtents[1]); + mBounds[1].mul(0.5f); } BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) { - if(!drawablep) - { - return FALSE; - } - { - drawablep->setGroup(this); - setState(OBJECT_DIRTY | GEOM_DIRTY); - setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); - gPipeline.markRebuild(this); - if (drawablep->isSpatialBridge()) - { - mBridgeList.push_back((LLSpatialBridge*) drawablep); - } - if (drawablep->getRadius() > 1.f) - { - setState(IMAGE_DIRTY); - } - } - - return TRUE; + if(!drawablep) + { + return FALSE; + } + { + drawablep->setGroup(this); + setState(OBJECT_DIRTY | GEOM_DIRTY); + setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); + gPipeline.markRebuild(this); + if (drawablep->isSpatialBridge()) + { + mBridgeList.push_back((LLSpatialBridge*) drawablep); + } + if (drawablep->getRadius() > 1.f) + { + setState(IMAGE_DIRTY); + } + } + + return TRUE; } void LLSpatialGroup::rebuildGeom() { - if (!isDead()) - { - getSpatialPartition()->rebuildGeom(this); + if (!isDead()) + { + getSpatialPartition()->rebuildGeom(this); - if (hasState(LLSpatialGroup::MESH_DIRTY)) - { - gPipeline.markMeshDirty(this); - } - } + if (hasState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } + } } void LLSpatialGroup::rebuildMesh() { - if (!isDead()) - { - getSpatialPartition()->rebuildMesh(this); - } + if (!isDead()) + { + getSpatialPartition()->rebuildMesh(this); + } } void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { - return; - } - - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - group->mLastUpdateViewAngle = group->mViewAngle; - } - + if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL; - group->clearDrawMap(); - - //get geometry count - U32 index_count = 0; - U32 vertex_count = 0; + group->clearDrawMap(); + + //get geometry count + U32 index_count = 0; + U32 vertex_count = 0; addGeometryCount(group, vertex_count, index_count); - - if (vertex_count > 0 && index_count > 0) - { //create vertex buffer containing volume geometry for this node - { - group->mBuilt = 1.f; - if (group->mVertexBuffer.isNull() || + + if (vertex_count > 0 && index_count > 0) + { //create vertex buffer containing volume geometry for this node + { + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || group->mVertexBuffer->getNumVerts() != vertex_count || group->mVertexBuffer->getNumVerts() != index_count) - { - group->mVertexBuffer = new LLVertexBuffer(mVertexDataMask); - if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer on rebuild to " - << vertex_count << " vertices and " - << index_count << " indices" << LL_ENDL; - group->mVertexBuffer = NULL; - group->mBufferMap.clear(); - } - } - } - - if (group->mVertexBuffer) - { - getGeometry(group); - } - } - else - { - group->mVertexBuffer = NULL; - group->mBufferMap.clear(); - } - - group->mLastUpdateTime = gFrameTimeSeconds; - group->clearState(LLSpatialGroup::GEOM_DIRTY); + { + group->mVertexBuffer = new LLVertexBuffer(mVertexDataMask); + if (!group->mVertexBuffer->allocateBuffer(vertex_count, index_count)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer on rebuild to " + << vertex_count << " vertices and " + << index_count << " indices" << LL_ENDL; + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + } + } + + if (group->mVertexBuffer) + { + getGeometry(group); + } + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY); } @@ -404,198 +404,198 @@ void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) LLSpatialGroup* LLSpatialGroup::getParent() { - return (LLSpatialGroup*)LLViewerOctreeGroup::getParent(); - } + return (LLSpatialGroup*)LLViewerOctreeGroup::getParent(); + } BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - - if(!drawablep) - { - return FALSE; - } - - unbound(); - if (mOctreeNode && !from_octree) - { - drawablep->setGroup(NULL); - } - else - { - drawablep->setGroup(NULL); - setState(GEOM_DIRTY); - gPipeline.markRebuild(this); - - if (drawablep->isSpatialBridge()) - { - for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) - { - if (*i == drawablep) - { - mBridgeList.erase(i); - break; - } - } - } - - if (getElementCount() == 0) - { //delete draw map on last element removal since a rebuild might never happen - clearDrawMap(); - } - } - return TRUE; + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + + if(!drawablep) + { + return FALSE; + } + + unbound(); + if (mOctreeNode && !from_octree) + { + drawablep->setGroup(NULL); + } + else + { + drawablep->setGroup(NULL); + setState(GEOM_DIRTY); + gPipeline.markRebuild(this); + + if (drawablep->isSpatialBridge()) + { + for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) + { + if (*i == drawablep) + { + mBridgeList.erase(i); + break; + } + } + } + + if (getElementCount() == 0) + { //delete draw map on last element removal since a rebuild might never happen + clearDrawMap(); + } + } + return TRUE; } void LLSpatialGroup::shift(const LLVector4a &offset) { - LLVector4a t = mOctreeNode->getCenter(); - t.add(offset); - mOctreeNode->setCenter(t); - mOctreeNode->updateMinMax(); - mBounds[0].add(offset); - mExtents[0].add(offset); - mExtents[1].add(offset); - mObjectBounds[0].add(offset); - mObjectExtents[0].add(offset); - mObjectExtents[1].add(offset); - - if (!getSpatialPartition()->mRenderByGroup && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_AVATAR && - getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_CONTROL_AV) - { - setState(GEOM_DIRTY); - gPipeline.markRebuild(this); - } + LLVector4a t = mOctreeNode->getCenter(); + t.add(offset); + mOctreeNode->setCenter(t); + mOctreeNode->updateMinMax(); + mBounds[0].add(offset); + mExtents[0].add(offset); + mExtents[1].add(offset); + mObjectBounds[0].add(offset); + mObjectExtents[0].add(offset); + mObjectExtents[1].add(offset); + + if (!getSpatialPartition()->mRenderByGroup && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_AVATAR && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_CONTROL_AV) + { + setState(GEOM_DIRTY); + gPipeline.markRebuild(this); + } } class LLSpatialSetState : public OctreeTraveler { public: - U32 mState; - LLSpatialSetState(U32 state) : mState(state) { } - virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } + U32 mState; + LLSpatialSetState(U32 state) : mState(state) { } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } }; class LLSpatialSetStateDiff : public LLSpatialSetState { public: - LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } - - virtual void traverse(const OctreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (!group->hasState(mState)) - { - OctreeTraveler::traverse(n); - } - } + LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } + + virtual void traverse(const OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (!group->hasState(mState)) + { + OctreeTraveler::traverse(n); + } + } }; -void LLSpatialGroup::setState(U32 state, S32 mode) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - - llassert(state <= LLSpatialGroup::STATE_MASK); - - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialSetStateDiff setter(state); - setter.traverse(mOctreeNode); - } - else - { - LLSpatialSetState setter(state); - setter.traverse(mOctreeNode); - } - } - else - { - mState |= state; - } +void LLSpatialGroup::setState(U32 state, S32 mode) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + + llassert(state <= LLSpatialGroup::STATE_MASK); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialSetStateDiff setter(state); + setter.traverse(mOctreeNode); + } + else + { + LLSpatialSetState setter(state); + setter.traverse(mOctreeNode); + } + } + else + { + mState |= state; + } } class LLSpatialClearState : public OctreeTraveler { public: - U32 mState; - LLSpatialClearState(U32 state) : mState(state) { } - virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } + U32 mState; + LLSpatialClearState(U32 state) : mState(state) { } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } }; class LLSpatialClearStateDiff : public LLSpatialClearState { public: - LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } - - virtual void traverse(const OctreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (group->hasState(mState)) - { - OctreeTraveler::traverse(n); - } - } + LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } + + virtual void traverse(const OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (group->hasState(mState)) + { + OctreeTraveler::traverse(n); + } + } }; void LLSpatialGroup::clearState(U32 state, S32 mode) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - - llassert(state <= LLSpatialGroup::STATE_MASK); - - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialClearStateDiff clearer(state); - clearer.traverse(mOctreeNode); - } - else - { - LLSpatialClearState clearer(state); - clearer.traverse(mOctreeNode); - } - } - else - { - mState &= ~state; - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + + llassert(state <= LLSpatialGroup::STATE_MASK); + + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialClearStateDiff clearer(state); + clearer.traverse(mOctreeNode); + } + else + { + LLSpatialClearState clearer(state); + clearer.traverse(mOctreeNode); + } + } + else + { + mState &= ~state; + } } //====================================== -// Octree Listener Implementation +// Octree Listener Implementation //====================================== LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part), - mObjectBoxSize(1.f), - mGeometryBytes(0), - mSurfaceArea(0.f), - mBuilt(0.f), - mVertexBuffer(NULL), - mDistance(0.f), - mDepth(0.f), - mLastUpdateDistance(-1.f), - mLastUpdateTime(gFrameTimeSeconds) -{ - ll_assert_aligned(this,16); - - sNodeCount++; - - mViewAngle.splat(0.f); - mLastUpdateViewAngle.splat(-1.f); - - sg_assert(mOctreeNode->getListenerCount() == 0); - setState(SG_INITIAL_STATE_MASK); - gPipeline.markRebuild(this); - + mObjectBoxSize(1.f), + mGeometryBytes(0), + mSurfaceArea(0.f), + mBuilt(0.f), + mVertexBuffer(NULL), + mDistance(0.f), + mDepth(0.f), + mLastUpdateDistance(-1.f), + mLastUpdateTime(gFrameTimeSeconds) +{ + ll_assert_aligned(this,16); + + sNodeCount++; + + mViewAngle.splat(0.f); + mLastUpdateViewAngle.splat(-1.f); + + sg_assert(mOctreeNode->getListenerCount() == 0); + setState(SG_INITIAL_STATE_MASK); + gPipeline.markRebuild(this); + // let the reflection map manager know about this spatial group mReflectionProbe = gPipeline.mReflectionMapManager.registerSpatialGroup(this); @@ -605,141 +605,141 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO void LLSpatialGroup::updateDistance(LLCamera &camera) { - if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) - { - LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL; + if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL; llassert(false); - return; - } + return; + } - if (gShiftFrame) - { - return; - } + if (gShiftFrame) + { + return; + } #if !LL_RELEASE_FOR_DOWNLOAD - if (hasState(LLSpatialGroup::OBJECT_DIRTY)) - { - LL_ERRS() << "Spatial group dirty on distance update." << LL_ENDL; - } + if (hasState(LLSpatialGroup::OBJECT_DIRTY)) + { + LL_ERRS() << "Spatial group dirty on distance update." << LL_ENDL; + } #endif - if (!isEmpty()) - { - mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : - (F32) mOctreeNode->getSize().getLength3().getF32(); - mDistance = getSpatialPartition()->calcDistance(this, camera); - mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); - } + if (!isEmpty()) + { + mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + (F32) mOctreeNode->getSize().getLength3().getF32(); + mDistance = getSpatialPartition()->calcDistance(this, camera); + mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); + } } F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - - LLVector4a eye; - LLVector4a origin; - origin.load3(camera.getOrigin().mV); - - eye.setSub(group->mObjectBounds[0], origin); - - F32 dist = 0.f; - - if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) - { - LLVector4a v = eye; - - dist = eye.getLength3().getF32(); - eye.normalize3fast(); - - if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) - { - if (!group->getSpatialPartition()->isBridge()) - { - LLVector4a view_angle = eye; - - LLVector4a diff; - diff.setSub(view_angle, group->mLastUpdateViewAngle); - - if (diff.getLength3().getF32() > 0.64f) - { - group->mViewAngle = view_angle; - group->mLastUpdateViewAngle = view_angle; - //for occasional alpha sorting within the group - //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, - //not setting this node to dirty would be a very good thing - group->setState(LLSpatialGroup::ALPHA_DIRTY); - gPipeline.markRebuild(group); - } - } - } - - //calculate depth of node for alpha sorting - - LLVector3 at = camera.getAtAxis(); - - LLVector4a ata; - ata.load3(at.mV); - - LLVector4a t = ata; - //front of bounding box - t.mul(0.25f); - t.mul(group->mObjectBounds[1]); - v.sub(t); - - group->mDepth = v.dot3(ata).getF32(); - } - else - { - dist = eye.getLength3().getF32(); - } + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + + LLVector4a eye; + LLVector4a origin; + origin.load3(camera.getOrigin().mV); + + eye.setSub(group->mObjectBounds[0], origin); + + F32 dist = 0.f; + + if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) + { + LLVector4a v = eye; + + dist = eye.getLength3().getF32(); + eye.normalize3fast(); + + if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) + { + if (!group->getSpatialPartition()->isBridge()) + { + LLVector4a view_angle = eye; + + LLVector4a diff; + diff.setSub(view_angle, group->mLastUpdateViewAngle); + + if (diff.getLength3().getF32() > 0.64f) + { + group->mViewAngle = view_angle; + group->mLastUpdateViewAngle = view_angle; + //for occasional alpha sorting within the group + //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, + //not setting this node to dirty would be a very good thing + group->setState(LLSpatialGroup::ALPHA_DIRTY); + gPipeline.markRebuild(group); + } + } + } + + //calculate depth of node for alpha sorting + + LLVector3 at = camera.getAtAxis(); + + LLVector4a ata; + ata.load3(at.mV); + + LLVector4a t = ata; + //front of bounding box + t.mul(0.25f); + t.mul(group->mObjectBounds[1]); + v.sub(t); + + group->mDepth = v.dot3(ata).getF32(); + } + else + { + dist = eye.getLength3().getF32(); + } #if !LL_RELEASE - LL_DEBUGS("RiggedBox") << "calcDistance, group " << group << " camera " << origin << " obj bounds " - << group->mObjectBounds[0] << ", " << group->mObjectBounds[1] + LL_DEBUGS("RiggedBox") << "calcDistance, group " << group << " camera " << origin << " obj bounds " + << group->mObjectBounds[0] << ", " << group->mObjectBounds[1] << " dist " << dist << " radius " << group->mRadius << LL_ENDL; #endif - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } - return dist; + return dist; } F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) { - return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); + return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } F32 LLSpatialGroup::getUpdateUrgency() const { - if (!isVisible()) - { - return 0.f; - } - else - { - F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; - return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance; - } + if (!isVisible()) + { + return 0.f; + } + else + { + F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; + return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance; + } } BOOL LLSpatialGroup::changeLOD() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) - { - //a rebuild is going to happen, update distance and LoD - return TRUE; - } + if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) + { + //a rebuild is going to happen, update distance and LoD + return TRUE; + } - if (getSpatialPartition()->mSlopRatio > 0.f) - { - F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); + if (getSpatialPartition()->mSlopRatio > 0.f) + { + F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); // MAINT-8264 - this check is not robust if it needs to work // for bounding boxes much larger than the actual enclosed @@ -753,85 +753,85 @@ BOOL LLSpatialGroup::changeLOD() // was large only due to another error, so this logic did not // need to be changed. - if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) - { + if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) + { LL_DEBUGS("RiggedBox") << "changeLOD true because of ratio compare " << fabsf(ratio) << " " << getSpatialPartition()->mSlopRatio << LL_ENDL; LL_DEBUGS("RiggedBox") << "sg " << this << "\nmDistance " << mDistance << " mLastUpdateDistance " << mLastUpdateDistance << " mRadius " << mRadius - << " fab ratio " << fabsf(ratio) + << " fab ratio " << fabsf(ratio) << " slop " << getSpatialPartition()->mSlopRatio << LL_ENDL; - - return TRUE; - } - } - - if (needsUpdate()) - { - return TRUE; - } - - return FALSE; + + return TRUE; + } + } + + if (needsUpdate()) + { + return TRUE; + } + + return FALSE; } void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) { - addObject((LLDrawable*)entry->getDrawable()); - unbound(); - setState(OBJECT_DIRTY); + addObject((LLDrawable*)entry->getDrawable()); + unbound(); + setState(OBJECT_DIRTY); } void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) { - removeObject((LLDrawable*)entry->getDrawable(), TRUE); - LLViewerOctreeGroup::handleRemoval(node, entry); + removeObject((LLDrawable*)entry->getDrawable(), TRUE); + LLViewerOctreeGroup::handleRemoval(node, entry); } void LLSpatialGroup::handleDestruction(const TreeNode* node) { - if(isDead()) - { - return; - } - setState(DEAD); - - for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) - { - LLViewerOctreeEntry* entry = *i; - - if (entry->getGroup() == this) - { - if(entry->hasDrawable()) - { - ((LLDrawable*)entry->getDrawable())->setGroup(NULL); - } - } - } - - clearDrawMap(); - mVertexBuffer = NULL; - mBufferMap.clear(); - sZombieGroups++; - mOctreeNode = NULL; + if(isDead()) + { + return; + } + setState(DEAD); + + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) + { + LLViewerOctreeEntry* entry = *i; + + if (entry->getGroup() == this) + { + if(entry->hasDrawable()) + { + ((LLDrawable*)entry->getDrawable())->setGroup(NULL); + } + } + } + + clearDrawMap(); + mVertexBuffer = NULL; + mBufferMap.clear(); + sZombieGroups++; + mOctreeNode = NULL; } -void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) +void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL + LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL - if (child->getListenerCount() == 0) - { - new LLSpatialGroup(child, getSpatialPartition()); - } - else - { - OCT_ERRS << "LLSpatialGroup redundancy detected." << LL_ENDL; - } + if (child->getListenerCount() == 0) + { + new LLSpatialGroup(child, getSpatialPartition()); + } + else + { + OCT_ERRS << "LLSpatialGroup redundancy detected." << LL_ENDL; + } - unbound(); + unbound(); - assert_states_valid(this); + assert_states_valid(this); } //virtual @@ -872,41 +872,41 @@ void LLSpatialGroup::rebound() void LLSpatialGroup::destroyGLState(bool keep_occlusion) { - setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - - if (!keep_occlusion) - { //going to need a rebuild - gPipeline.markRebuild(this); - } - - mLastUpdateTime = gFrameTimeSeconds; - mVertexBuffer = NULL; - mBufferMap.clear(); - - clearDrawMap(); - - if (!keep_occlusion) - { - releaseOcclusionQueryObjectNames(); - } - - - for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - for (S32 j = 0; j < drawable->getNumFaces(); j++) - { - LLFace* facep = drawable->getFace(j); - if (facep) - { - facep->clearVertexBuffer(); - } - } - } + setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); + + if (!keep_occlusion) + { //going to need a rebuild + gPipeline.markRebuild(this); + } + + mLastUpdateTime = gFrameTimeSeconds; + mVertexBuffer = NULL; + mBufferMap.clear(); + + clearDrawMap(); + + if (!keep_occlusion) + { + releaseOcclusionQueryObjectNames(); + } + + + for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + for (S32 j = 0; j < drawable->getNumFaces(); j++) + { + LLFace* facep = drawable->getFace(j); + if (facep) + { + facep->clearVertexBuffer(); + } + } + } } //============================================== @@ -914,14 +914,14 @@ void LLSpatialGroup::destroyGLState(bool keep_occlusion) LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, LLViewerRegion* regionp) : mRenderByGroup(render_by_group), mBridge(NULL) { - mRegionp = regionp; - mPartitionType = LLViewerRegion::PARTITION_NONE; - mVertexDataMask = data_mask; - mDepthMask = FALSE; - mSlopRatio = 0.25f; - mInfiniteFarClip = FALSE; + mRegionp = regionp; + mPartitionType = LLViewerRegion::PARTITION_NONE; + mVertexDataMask = data_mask; + mDepthMask = FALSE; + mSlopRatio = 0.25f; + mInfiniteFarClip = FALSE; - new LLSpatialGroup(mOctree, this); + new LLSpatialGroup(mOctree, this); } @@ -933,391 +933,391 @@ LLSpatialPartition::~LLSpatialPartition() LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) { LL_PROFILE_ZONE_SCOPED; - drawablep->updateSpatialExtents(); - - //keep drawable from being garbage collected - LLPointer ptr = drawablep; - - if(!drawablep->getGroup()) - { - assert_octree_valid(mOctree); - mOctree->insert(drawablep->getEntry()); - assert_octree_valid(mOctree); - } - - LLSpatialGroup* group = drawablep->getSpatialGroup(); - //llassert(group != NULL); - - if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) - { - group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); - } - - return group; + drawablep->updateSpatialExtents(); + + //keep drawable from being garbage collected + LLPointer ptr = drawablep; + + if(!drawablep->getGroup()) + { + assert_octree_valid(mOctree); + mOctree->insert(drawablep->getEntry()); + assert_octree_valid(mOctree); + } + + LLSpatialGroup* group = drawablep->getSpatialGroup(); + //llassert(group != NULL); + + if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) + { + group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); + } + + return group; } BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { LL_PROFILE_ZONE_SCOPED; - if (!curp->removeObject(drawablep)) - { - OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; - } - else - { - drawablep->setGroup(NULL); - } - - assert_octree_valid(mOctree); - - return TRUE; -} + if (!curp->removeObject(drawablep)) + { + OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; + } + else + { + drawablep->setGroup(NULL); + } + + assert_octree_valid(mOctree); + + return TRUE; +} void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) { LL_PROFILE_ZONE_SCOPED; - // sanity check submitted by open source user bushing Spatula - // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) - if (!drawablep) - { - OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << LL_ENDL; - return; - } - - BOOL was_visible = curp ? curp->isVisible() : FALSE; - - if (curp && curp->getSpatialPartition() != this) - { - //keep drawable from being garbage collected - LLPointer ptr = drawablep; - if (curp->getSpatialPartition()->remove(drawablep, curp)) - { - put(drawablep, was_visible); - return; - } - else - { - OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << LL_ENDL; - } - } - - if (curp && curp->updateInGroup(drawablep, immediate)) - { - // Already updated, don't need to do anything - assert_octree_valid(mOctree); - return; - } - - //keep drawable from being garbage collected - LLPointer ptr = drawablep; - if (curp && !remove(drawablep, curp)) - { - OCT_ERRS << "Move couldn't find existing spatial group!" << LL_ENDL; - } - - put(drawablep, was_visible); + // sanity check submitted by open source user bushing Spatula + // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) + if (!drawablep) + { + OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << LL_ENDL; + return; + } + + BOOL was_visible = curp ? curp->isVisible() : FALSE; + + if (curp && curp->getSpatialPartition() != this) + { + //keep drawable from being garbage collected + LLPointer ptr = drawablep; + if (curp->getSpatialPartition()->remove(drawablep, curp)) + { + put(drawablep, was_visible); + return; + } + else + { + OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << LL_ENDL; + } + } + + if (curp && curp->updateInGroup(drawablep, immediate)) + { + // Already updated, don't need to do anything + assert_octree_valid(mOctree); + return; + } + + //keep drawable from being garbage collected + LLPointer ptr = drawablep; + if (curp && !remove(drawablep, curp)) + { + OCT_ERRS << "Move couldn't find existing spatial group!" << LL_ENDL; + } + + put(drawablep, was_visible); } class LLSpatialShift : public OctreeTraveler { public: - const LLVector4a& mOffset; + const LLVector4a& mOffset; - LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } - virtual void visit(const OctreeNode* branch) - { - ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); - } + LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } + virtual void visit(const OctreeNode* branch) + { + ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); + } }; void LLSpatialPartition::shift(const LLVector4a &offset) { //shift octree node bounding boxes by offset - LLSpatialShift shifter(offset); - shifter.traverse(mOctree); + LLSpatialShift shifter(offset); + shifter.traverse(mOctree); } class LLOctreeCull : public LLViewerOctreeCull { public: - LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} + LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} - virtual bool earlyFail(LLViewerOctreeGroup* base_group) - { + virtual bool earlyFail(LLViewerOctreeGroup* base_group) + { if (LLPipeline::sReflectionRender) { return false; } - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - group->checkOcclusion(); - - if (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - gPipeline.markOccluder(group); - return true; - } - - return false; - } - - virtual S32 frustumCheck(const LLViewerOctreeGroup* group) - { - S32 res = AABBInFrustumNoFarClipGroupBounds(group); - if (res != 0) - { - res = llmin(res, AABBSphereIntersectGroupExtents(group)); - } - return res; - } - - virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) - { - S32 res = AABBInFrustumNoFarClipObjectBounds(group); - if (res != 0) - { - res = llmin(res, AABBSphereIntersectObjectExtents(group)); - } - return res; - } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - /*if (group->needsUpdate() || - group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) - { - group->doOcclusion(mCamera); - }*/ - gPipeline.markNotCulled(group, *mCamera); - } + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + group->checkOcclusion(); + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + gPipeline.markOccluder(group); + return true; + } + + return false; + } + + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) + { + S32 res = AABBInFrustumNoFarClipGroupBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectGroupExtents(group)); + } + return res; + } + + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) + { + S32 res = AABBInFrustumNoFarClipObjectBounds(group); + if (res != 0) + { + res = llmin(res, AABBSphereIntersectObjectExtents(group)); + } + return res; + } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + /*if (group->needsUpdate() || + group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) + { + group->doOcclusion(mCamera); + }*/ + gPipeline.markNotCulled(group, *mCamera); + } }; class LLOctreeCullNoFarClip : public LLOctreeCull { -public: - LLOctreeCullNoFarClip(LLCamera* camera) - : LLOctreeCull(camera) { } +public: + LLOctreeCullNoFarClip(LLCamera* camera) + : LLOctreeCull(camera) { } - virtual S32 frustumCheck(const LLViewerOctreeGroup* group) - { - return AABBInFrustumNoFarClipGroupBounds(group); - } + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) + { + return AABBInFrustumNoFarClipGroupBounds(group); + } - virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) - { - S32 res = AABBInFrustumNoFarClipObjectBounds(group); - return res; - } + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) + { + S32 res = AABBInFrustumNoFarClipObjectBounds(group); + return res; + } }; class LLOctreeCullShadow : public LLOctreeCull { public: - LLOctreeCullShadow(LLCamera* camera) - : LLOctreeCull(camera) { } - - virtual S32 frustumCheck(const LLViewerOctreeGroup* group) - { - return AABBInFrustumGroupBounds(group); - } - - virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) - { - return AABBInFrustumObjectBounds(group); - } + LLOctreeCullShadow(LLCamera* camera) + : LLOctreeCull(camera) { } + + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) + { + return AABBInFrustumGroupBounds(group); + } + + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) + { + return AABBInFrustumObjectBounds(group); + } }; class LLOctreeCullVisExtents: public LLOctreeCullShadow { public: - LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) - : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } - - virtual bool earlyFail(LLViewerOctreeGroup* base_group) - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - if (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - return true; - } - - return false; - } - - virtual void traverse(const OctreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (earlyFail(group)) - { - return; - } - - if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || - mRes == 2) - { //don't need to do frustum check - OctreeTraveler::traverse(n); - } - else - { - mRes = frustumCheck(group); - - if (mRes) - { //at least partially in, run on down - OctreeTraveler::traverse(n); - } - - mRes = 0; - } - } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()); - - if (mRes < 2) - { - if (AABBInFrustumObjectBounds(group) > 0) - { - mEmpty = FALSE; - const LLVector4a* exts = group->getObjectExtents(); - update_min_max(mMin, mMax, exts[0]); - update_min_max(mMin, mMax, exts[1]); - } - } - else - { - mEmpty = FALSE; - const LLVector4a* exts = group->getExtents(); - update_min_max(mMin, mMax, exts[0]); - update_min_max(mMin, mMax, exts[1]); - } - } - - BOOL mEmpty; - LLVector4a& mMin; - LLVector4a& mMax; + LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) + : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } + + virtual bool earlyFail(LLViewerOctreeGroup* base_group) + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + + return false; + } + + virtual void traverse(const OctreeNode* n) + { + LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); + + if (earlyFail(group)) + { + return; + } + + if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + mRes == 2) + { //don't need to do frustum check + OctreeTraveler::traverse(n); + } + else + { + mRes = frustumCheck(group); + + if (mRes) + { //at least partially in, run on down + OctreeTraveler::traverse(n); + } + + mRes = 0; + } + } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()); + + if (mRes < 2) + { + if (AABBInFrustumObjectBounds(group) > 0) + { + mEmpty = FALSE; + const LLVector4a* exts = group->getObjectExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); + } + } + else + { + mEmpty = FALSE; + const LLVector4a* exts = group->getExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); + } + } + + BOOL mEmpty; + LLVector4a& mMin; + LLVector4a& mMax; }; class LLOctreeCullDetectVisible: public LLOctreeCullShadow { public: - LLOctreeCullDetectVisible(LLCamera* camera) - : LLOctreeCullShadow(camera), mResult(FALSE) { } - - virtual bool earlyFail(LLViewerOctreeGroup* base_group) - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - - if (mResult || //already found a node, don't check any more - (group->getOctreeNode()->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isOcclusionState(LLSpatialGroup::OCCLUDED))) - { - return true; - } - - return false; - } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - if (base_group->isVisible()) - { - mResult = TRUE; - } - } - - BOOL mResult; + LLOctreeCullDetectVisible(LLCamera* camera) + : LLOctreeCullShadow(camera), mResult(FALSE) { } + + virtual bool earlyFail(LLViewerOctreeGroup* base_group) + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (mResult || //already found a node, don't check any more + (group->getOctreeNode()->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //ignore occlusion if disabled + group->isOcclusionState(LLSpatialGroup::OCCLUDED))) + { + return true; + } + + return false; + } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + if (base_group->isVisible()) + { + mResult = TRUE; + } + } + + BOOL mResult; }; class LLOctreeSelect : public LLOctreeCull { public: - LLOctreeSelect(LLCamera* camera, std::vector* results) - : LLOctreeCull(camera), mResults(results) { } - - virtual bool earlyFail(LLViewerOctreeGroup* group) { return false; } - virtual void preprocess(LLViewerOctreeGroup* group) { } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - LLSpatialGroup* group = (LLSpatialGroup*)base_group; - OctreeNode* branch = group->getOctreeNode(); - - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - if (!drawable->isDead()) - { - if (drawable->isSpatialBridge()) - { - drawable->setVisible(*mCamera, mResults, TRUE); - } - else - { - mResults->push_back(drawable); - } - } - } - } - - std::vector* mResults; + LLOctreeSelect(LLCamera* camera, std::vector* results) + : LLOctreeCull(camera), mResults(results) { } + + virtual bool earlyFail(LLViewerOctreeGroup* group) { return false; } + virtual void preprocess(LLViewerOctreeGroup* group) { } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + OctreeNode* branch = group->getOctreeNode(); + + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!drawable->isDead()) + { + if (drawable->isSpatialBridge()) + { + drawable->setVisible(*mCamera, mResults, TRUE); + } + else + { + mResults->push_back(drawable); + } + } + } + } + + std::vector* mResults; }; void drawBox(const LLVector3& c, const LLVector3& r) { - LLVertexBuffer::unbind(); - - gGL.begin(LLRender::TRIANGLE_STRIP); - //left front - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - //right front - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); - //right back - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); - //left back - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); - //left front - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - gGL.end(); - - //bottom - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - gGL.end(); - - //top - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); - gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); - gGL.end(); + LLVertexBuffer::unbind(); + + gGL.begin(LLRender::TRIANGLE_STRIP); + //left front + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + //right front + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + //right back + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + //left back + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + //left front + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.end(); + + //bottom + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.end(); + + //top + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + gGL.end(); } void drawBox(const LLVector4a& c, const LLVector4a& r) { - drawBox(reinterpret_cast(c), reinterpret_cast(r)); + drawBox(reinterpret_cast(c), reinterpret_cast(r)); } void drawBoxOutline(const LLVector3& pos, const LLVector3& size) @@ -1325,53 +1325,53 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size) if (!pos.isFinite() || !size.isFinite()) return; - LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); - LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); - LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); - LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); - - gGL.begin(LLRender::LINES); - - //top - gGL.vertex3fv((pos+v1).mV); - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos+v1).mV); - - //bottom - gGL.vertex3fv((pos-v1).mV); - gGL.vertex3fv((pos-v2).mV); - gGL.vertex3fv((pos-v2).mV); - gGL.vertex3fv((pos-v3).mV); - gGL.vertex3fv((pos-v3).mV); - gGL.vertex3fv((pos-v4).mV); - gGL.vertex3fv((pos-v4).mV); - gGL.vertex3fv((pos-v1).mV); - - //right - gGL.vertex3fv((pos+v1).mV); - gGL.vertex3fv((pos-v3).mV); - - gGL.vertex3fv((pos+v4).mV); - gGL.vertex3fv((pos-v2).mV); - - //left - gGL.vertex3fv((pos+v2).mV); - gGL.vertex3fv((pos-v4).mV); - - gGL.vertex3fv((pos+v3).mV); - gGL.vertex3fv((pos-v1).mV); - - gGL.end(); + LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); + LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); + LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); + LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); + + gGL.begin(LLRender::LINES); + + //top + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v1).mV); + + //bottom + gGL.vertex3fv((pos-v1).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v1).mV); + + //right + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos-v3).mV); + + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos-v2).mV); + + //left + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos-v4).mV); + + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos-v1).mV); + + gGL.end(); } void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) { - drawBoxOutline(reinterpret_cast(pos), reinterpret_cast(size)); + drawBoxOutline(reinterpret_cast(pos), reinterpret_cast(size)); } @@ -1382,49 +1382,49 @@ void LLSpatialPartition::restoreGL() BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL; - LLVector4a visMina, visMaxa; - visMina.load3(visMin.mV); - visMaxa.load3(visMax.mV); + LLVector4a visMina, visMaxa; + visMina.load3(visMin.mV); + visMaxa.load3(visMax.mV); - { - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } + { + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } - LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); - vis.traverse(mOctree); + LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); + vis.traverse(mOctree); - visMin.set(visMina.getF32ptr()); - visMax.set(visMaxa.getF32ptr()); - return vis.mEmpty; + visMin.set(visMina.getF32ptr()); + visMax.set(visMaxa.getF32ptr()); + return vis.mEmpty; } BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) { - LLOctreeCullDetectVisible vis(&camera); - vis.traverse(mOctree); - return vis.mResult; + LLOctreeCullDetectVisible vis(&camera); + vis.traverse(mOctree); + return vis.mResult; } S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* results, BOOL for_select) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL; #if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif - { - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - } + { + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } #if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->validate(); + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif - LLOctreeSelect selecter(&camera, results); - selecter.traverse(mOctree); - - return 0; + LLOctreeSelect selecter(&camera, results); + selecter.traverse(mOctree); + + return 0; } extern BOOL gCubeSnapshot; @@ -1433,13 +1433,13 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) { LL_PROFILE_ZONE_SCOPED_CATEGORY_SPATIAL; #if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); #endif - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); #if LL_OCTREE_PARANOIA_CHECK - ((LLSpatialGroup*)mOctree->getListener(0))->validate(); + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif if (LLPipeline::sShadowRender) @@ -1457,132 +1457,132 @@ S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) LLOctreeCull culler(&camera); culler.traverse(mOctree); } - - return 0; + + return 0; } void pushVerts(LLDrawInfo* params) { - LLRenderPass::applyModelMatrix(*params); - params->mVertexBuffer->setBuffer(); - params->mVertexBuffer->drawRange(LLRender::TRIANGLES, - params->mStart, params->mEnd, params->mCount, params->mOffset); + LLRenderPass::applyModelMatrix(*params); + params->mVertexBuffer->setBuffer(); + params->mVertexBuffer->drawRange(LLRender::TRIANGLES, + params->mStart, params->mEnd, params->mCount, params->mOffset); } void pushVerts(LLSpatialGroup* group) { - LLDrawInfo* params = NULL; + LLDrawInfo* params = NULL; - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - params = *j; - pushVerts(params); - } - } + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + params = *j; + pushVerts(params); + } + } } void pushVerts(LLFace* face) { - if (face) - { - llassert(face->verify()); + if (face) + { + llassert(face->verify()); face->renderIndexed(); - } + } } void pushVerts(LLDrawable* drawable) { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - pushVerts(drawable->getFace(i)); - } + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + pushVerts(drawable->getFace(i)); + } } void pushVerts(LLVolume* volume) { - LLVertexBuffer::unbind(); - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); - } + LLVertexBuffer::unbind(); + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); + } } void pushBufferVerts(LLVertexBuffer* buffer) { - if (buffer) - { - buffer->setBuffer(); - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); - } + if (buffer) + { + buffer->setBuffer(); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); + } } void pushBufferVerts(LLSpatialGroup* group, bool push_alpha = true) { - if (group->getSpatialPartition()->mRenderByGroup) - { - if (!group->mDrawMap.empty()) - { - LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); - LLRenderPass::applyModelMatrix(*params); - - if (push_alpha) - { - pushBufferVerts(group->mVertexBuffer); - } - - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) - { - for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k) - { - pushBufferVerts(*k); - } - } - } - } - } - /*else - { - //const LLVector4a* bounds = group->getBounds(); - //drawBox(bounds[0], bounds[1]); - }*/ + if (group->getSpatialPartition()->mRenderByGroup) + { + if (!group->mDrawMap.empty()) + { + LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); + LLRenderPass::applyModelMatrix(*params); + + if (push_alpha) + { + pushBufferVerts(group->mVertexBuffer); + } + + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + { + for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k) + { + pushBufferVerts(*k); + } + } + } + } + } + /*else + { + //const LLVector4a* bounds = group->getBounds(); + //drawBox(bounds[0], bounds[1]); + }*/ } void pushVertsColorCoded(LLSpatialGroup* group) { - LLDrawInfo* params = NULL; - - static const LLColor4 colors[] = { - LLColor4::green, - LLColor4::green1, - LLColor4::green2, - LLColor4::green3, - LLColor4::green4, - LLColor4::green5, - LLColor4::green6 - }; - - static const U32 col_count = LL_ARRAY_SIZE(colors); - - U32 col = 0; - - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - params = *j; - LLRenderPass::applyModelMatrix(*params); - gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); - params->mVertexBuffer->setBuffer(); - params->mVertexBuffer->drawRange(LLRender::TRIANGLES, - params->mStart, params->mEnd, params->mCount, params->mOffset); - col = (col+1)%col_count; - } - } + LLDrawInfo* params = NULL; + + static const LLColor4 colors[] = { + LLColor4::green, + LLColor4::green1, + LLColor4::green2, + LLColor4::green3, + LLColor4::green4, + LLColor4::green5, + LLColor4::green6 + }; + + static const U32 col_count = LL_ARRAY_SIZE(colors); + + U32 col = 0; + + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + params = *j; + LLRenderPass::applyModelMatrix(*params); + gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); + params->mVertexBuffer->setBuffer(); + params->mVertexBuffer->drawRange(LLRender::TRIANGLES, + params->mStart, params->mEnd, params->mCount, params->mOffset); + col = (col+1)%col_count; + } + } } // return false if drawable is rigged and: @@ -1630,7 +1630,7 @@ bool check_rigged_group(LLDrawable* drawable) last_draw_index = face->getDrawOrderIndex(); } } - + if (child->mDrawable->getSpatialGroup() != group) { llassert(false); @@ -1644,49 +1644,49 @@ bool check_rigged_group(LLDrawable* drawable) void renderOctree(LLSpatialGroup* group) { - //render solid object bounding box, color - //coded by buffer usage and activity - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - LLVector4 col; - if (group->mBuilt > 0.f) - { - group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); - col.setVec(0.1f,0.1f,1,0.1f); - - { - LLGLDepthTest gl_depth(FALSE, FALSE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - gGL.diffuseColor4f(1,0,0,group->mBuilt); - gGL.flush(); - glLineWidth(5.f); - - const LLVector4a* bounds = group->getObjectBounds(); - drawBoxOutline(bounds[0], bounds[1]); - gGL.flush(); - glLineWidth(1.f); - gGL.flush(); + //render solid object bounding box, color + //coded by buffer usage and activity + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + LLVector4 col; + if (group->mBuilt > 0.f) + { + group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); + col.setVec(0.1f,0.1f,1,0.1f); + + { + LLGLDepthTest gl_depth(FALSE, FALSE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4f(1,0,0,group->mBuilt); + gGL.flush(); + glLineWidth(5.f); + + const LLVector4a* bounds = group->getObjectBounds(); + drawBoxOutline(bounds[0], bounds[1]); + gGL.flush(); + glLineWidth(1.f); + gGL.flush(); LLVOAvatar* lastAvatar = nullptr; U64 lastMeshId = 0; - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable || drawable->getNumFaces() == 0) - { - continue; - } + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable || drawable->getNumFaces() == 0) + { + continue; + } llassert(check_rigged_group(drawable)); - if (!group->getSpatialPartition()->isBridge()) - { - gGL.pushMatrix(); - LLVector3 trans = drawable->getRegion()->getOriginAgent(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - } - + if (!group->getSpatialPartition()->isBridge()) + { + gGL.pushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + } + LLFace* face = drawable->getFace(0); bool rigged = face->isState(LLFace::RIGGED); gDebugProgram.bind(rigged); @@ -1708,11 +1708,11 @@ void renderOctree(LLSpatialGroup* group) lastMeshId = face->mSkinInfo->mHash; } } - for (S32 j = 0; j < drawable->getNumFaces(); j++) - { - LLFace* face = drawable->getFace(j); - if (face && face->getVertexBuffer()) - { + for (S32 j = 0; j < drawable->getNumFaces(); j++) + { + LLFace* face = drawable->getFace(j); + if (face && face->getVertexBuffer()) + { LLVOVolume* vol = drawable->getVOVolume(); if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) @@ -1742,40 +1742,40 @@ void renderOctree(LLSpatialGroup* group) continue; } - face->getVertexBuffer()->setBuffer(); - face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); - } - } + face->getVertexBuffer()->setBuffer(); + face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); + } + } if (rigged) { gGL.popMatrix(); } - if (!group->getSpatialPartition()->isBridge()) - { - gGL.popMatrix(); - } - } - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + if (!group->getSpatialPartition()->isBridge()) + { + gGL.popMatrix(); + } + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); gDebugProgram.bind(); // make sure non-rigged variant is bound - gGL.diffuseColor4f(1,1,1,1); - } - } + gGL.diffuseColor4f(1,1,1,1); + } + } - gGL.diffuseColor4fv(col.mV); - LLVector4a fudge; - fudge.splat(0.001f); + gGL.diffuseColor4fv(col.mV); + LLVector4a fudge; + fudge.splat(0.001f); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); - { - //draw opaque outline - gGL.diffuseColor4f(0,1,1,1); + { + //draw opaque outline + gGL.diffuseColor4f(0,1,1,1); - const LLVector4a* bounds = group->getBounds(); - drawBoxOutline(bounds[0], bounds[1]); - } + const LLVector4a* bounds = group->getBounds(); + drawBoxOutline(bounds[0], bounds[1]); + } } std::set visible_selected_groups; @@ -1784,263 +1784,263 @@ std::set visible_selected_groups; void renderXRay(LLSpatialGroup* group, LLCamera* camera) { - BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->isEmpty(); - - if (render_objects) - { - pushBufferVerts(group, false); - - bool selected = false; - - for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) - { - LLDrawable* drawable = (LLDrawable*)(*iter)->getDrawable(); - if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) - { - selected = true; - break; - } - } - - if (selected) - { //store for rendering occlusion volume as overlay - - if (!group->getSpatialPartition()->isBridge()) - { - visible_selected_groups.insert(group); - } - else - { - visible_selected_groups.insert(group->getSpatialPartition()->asBridge()->getSpatialGroup()); - } - } - } + BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->isEmpty(); + + if (render_objects) + { + pushBufferVerts(group, false); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = (LLDrawable*)(*iter)->getDrawable(); + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + + if (!group->getSpatialPartition()->isBridge()) + { + visible_selected_groups.insert(group); + } + else + { + visible_selected_groups.insert(group->getSpatialPartition()->asBridge()->getSpatialGroup()); + } + } + } } void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color) { - gGL.color4fv(color.mV); - gGL.begin(LLRender::LINES); - { - gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); - gGL.vertex3fv((position + LLVector3(size, 0.f, 0.f)).mV); - gGL.vertex3fv((position - LLVector3(0.f, size, 0.f)).mV); - gGL.vertex3fv((position + LLVector3(0.f, size, 0.f)).mV); - gGL.vertex3fv((position - LLVector3(0.f, 0.f, size)).mV); - gGL.vertex3fv((position + LLVector3(0.f, 0.f, size)).mV); - } - gGL.end(); + gGL.color4fv(color.mV); + gGL.begin(LLRender::LINES); + { + gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); + gGL.vertex3fv((position + LLVector3(size, 0.f, 0.f)).mV); + gGL.vertex3fv((position - LLVector3(0.f, size, 0.f)).mV); + gGL.vertex3fv((position + LLVector3(0.f, size, 0.f)).mV); + gGL.vertex3fv((position - LLVector3(0.f, 0.f, size)).mV); + gGL.vertex3fv((position + LLVector3(0.f, 0.f, size)).mV); + } + gGL.end(); } void renderUpdateType(LLDrawable* drawablep) { - LLViewerObject* vobj = drawablep->getVObj(); - if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) - { - return; - } - LLGLEnable blend(GL_BLEND); - switch (vobj->getLastUpdateType()) - { - case OUT_FULL: - gGL.diffuseColor4f(0,1,0,0.5f); - break; - case OUT_TERSE_IMPROVED: - gGL.diffuseColor4f(0,1,1,0.5f); - break; - case OUT_FULL_COMPRESSED: - if (vobj->getLastUpdateCached()) - { - gGL.diffuseColor4f(1,0,0,0.5f); - } - else - { - gGL.diffuseColor4f(1,1,0,0.5f); - } - break; - case OUT_FULL_CACHED: - gGL.diffuseColor4f(0,0,1,0.5f); - break; - default: - LL_WARNS() << "Unknown update_type " << vobj->getLastUpdateType() << LL_ENDL; - break; - }; - S32 num_faces = drawablep->getNumFaces(); - if (num_faces) - { - for (S32 i = 0; i < num_faces; ++i) - { - pushVerts(drawablep->getFace(i)); - } - } -} - -void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) -{ - if (set_color) - { - if (drawable->isSpatialBridge()) - { - gGL.diffuseColor4f(1,0.5f,0,1); // orange - } - else if (drawable->getVOVolume()) - { - if (drawable->isRoot()) - { - gGL.diffuseColor4f(1,1,0,1); // yellow - } - else - { - gGL.diffuseColor4f(0,1,0,1); // green - } - } - else if (drawable->getVObj()) - { - switch (drawable->getVObj()->getPCode()) - { - case LLViewerObject::LL_VO_SURFACE_PATCH: - gGL.diffuseColor4f(0,1,1,1); // cyan - break; - case LLViewerObject::LL_VO_CLOUDS: - // no longer used - break; - case LLViewerObject::LL_VO_PART_GROUP: - case LLViewerObject::LL_VO_HUD_PART_GROUP: - gGL.diffuseColor4f(0,0,1,1); // blue - break; - case LLViewerObject::LL_VO_VOID_WATER: - case LLViewerObject::LL_VO_WATER: - gGL.diffuseColor4f(0,0.5f,1,1); // medium blue - break; - case LL_PCODE_LEGACY_TREE: - gGL.diffuseColor4f(0,0.5f,0,1); // dark green - break; - default: - LLControlAvatar *cav = dynamic_cast(drawable->getVObj()->asAvatar()); - if (cav) - { - bool has_pos_constraint = (cav->mPositionConstraintFixup != LLVector3()); - bool has_scale_constraint = (cav->mScaleConstraintFixup != 1.0f); - if (has_pos_constraint || has_scale_constraint) - { - gGL.diffuseColor4f(1,0,0,1); - } - else - { - gGL.diffuseColor4f(0,1,0.5,1); - } - } - else - { - gGL.diffuseColor4f(1,0,1,1); // magenta - } - break; - } - } - else - { - gGL.diffuseColor4f(1,0,0,1); - } - } - - const LLVector4a* ext; - LLVector4a pos, size; - - if (drawable->getVOVolume()) - { - //render face bounding boxes - for (S32 i = 0; i < drawable->getNumFaces(); i++) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - ext = facep->mExtents; - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - drawBoxOutline(pos,size); - } - } - } - - //render drawable bounding box - ext = drawable->getSpatialExtents(); - - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - LLViewerObject* vobj = drawable->getVObj(); - if (vobj && vobj->onActiveList()) - { - gGL.flush(); - glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); - //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); - stop_glerror(); - drawBoxOutline(pos,size); - gGL.flush(); - glLineWidth(1.f); - } - else - { - drawBoxOutline(pos,size); - } -} -// *TODO: LLDrawables which are not part of LLVOVolumes fall into a different -// code path which uses a shader - it was tested to be faster than mapping a -// vertex buffer in the terrain case. Consider using it for LLVOVolumes as well -// to simplify and speed up this debug code. Alternatively, a compute shader is -// likely faster. -Cosmic,2023-09-28 -void renderNormals(LLDrawable *drawablep) -{ - if (!drawablep->isVisible()) + LLViewerObject* vobj = drawablep->getVObj(); + if (!vobj || OUT_UNKNOWN == vobj->getLastUpdateType()) + { return; - - LLVertexBuffer::unbind(); - - LLViewerObject* obj = drawablep->getVObj(); - LLVOVolume *vol = drawablep->getVOVolume(); - - if (obj) + } + LLGLEnable blend(GL_BLEND); + switch (vobj->getLastUpdateType()) { - LLGLEnable blend(GL_BLEND); - LLGLDepthTest gl_depth(GL_TRUE, GL_FALSE); - - // Drawable's normals & tangents are stored in model space, i.e. before any scaling is applied. - // - // SL-13490, using pos + normal to compute the 2nd vertex of a normal line segment doesn't - // work when there's a non-uniform scale in the mix. Normals require MVP-inverse-transpose - // transform. We get that effect here by pre-applying the inverse scale (twice, because - // one forward scale will be re-applied via the MVP in the vertex shader) - - LLVector4a inv_scale; - float scale_len; - if (vol) + case OUT_FULL: + gGL.diffuseColor4f(0,1,0,0.5f); + break; + case OUT_TERSE_IMPROVED: + gGL.diffuseColor4f(0,1,1,0.5f); + break; + case OUT_FULL_COMPRESSED: + if (vobj->getLastUpdateCached()) { - LLVector3 scale_v3 = vol->getScale(); - LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]); - obj_scale.normalize3(); - - // Create inverse-scale vector for normals - inv_scale.set(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ], 0.0); - inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice - - inv_scale.normalize3fast(); - scale_len = scale_v3.length(); + gGL.diffuseColor4f(1,0,0,0.5f); } else { - inv_scale.set(1.0, 1.0, 1.0, 0.0); - scale_len = 1.0; + gGL.diffuseColor4f(1,1,0,0.5f); } - - gGL.pushMatrix(); - if (vol) + break; + case OUT_FULL_CACHED: + gGL.diffuseColor4f(0,0,1,0.5f); + break; + default: + LL_WARNS() << "Unknown update_type " << vobj->getLastUpdateType() << LL_ENDL; + break; + }; + S32 num_faces = drawablep->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(drawablep->getFace(i)); + } + } +} + +void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) +{ + if (set_color) + { + if (drawable->isSpatialBridge()) + { + gGL.diffuseColor4f(1,0.5f,0,1); // orange + } + else if (drawable->getVOVolume()) + { + if (drawable->isRoot()) + { + gGL.diffuseColor4f(1,1,0,1); // yellow + } + else + { + gGL.diffuseColor4f(0,1,0,1); // green + } + } + else if (drawable->getVObj()) + { + switch (drawable->getVObj()->getPCode()) + { + case LLViewerObject::LL_VO_SURFACE_PATCH: + gGL.diffuseColor4f(0,1,1,1); // cyan + break; + case LLViewerObject::LL_VO_CLOUDS: + // no longer used + break; + case LLViewerObject::LL_VO_PART_GROUP: + case LLViewerObject::LL_VO_HUD_PART_GROUP: + gGL.diffuseColor4f(0,0,1,1); // blue + break; + case LLViewerObject::LL_VO_VOID_WATER: + case LLViewerObject::LL_VO_WATER: + gGL.diffuseColor4f(0,0.5f,1,1); // medium blue + break; + case LL_PCODE_LEGACY_TREE: + gGL.diffuseColor4f(0,0.5f,0,1); // dark green + break; + default: + LLControlAvatar *cav = dynamic_cast(drawable->getVObj()->asAvatar()); + if (cav) + { + bool has_pos_constraint = (cav->mPositionConstraintFixup != LLVector3()); + bool has_scale_constraint = (cav->mScaleConstraintFixup != 1.0f); + if (has_pos_constraint || has_scale_constraint) + { + gGL.diffuseColor4f(1,0,0,1); + } + else + { + gGL.diffuseColor4f(0,1,0.5,1); + } + } + else + { + gGL.diffuseColor4f(1,0,1,1); // magenta + } + break; + } + } + else + { + gGL.diffuseColor4f(1,0,0,1); + } + } + + const LLVector4a* ext; + LLVector4a pos, size; + + if (drawable->getVOVolume()) + { + //render face bounding boxes + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; + + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + drawBoxOutline(pos,size); + } + } + } + + //render drawable bounding box + ext = drawable->getSpatialExtents(); + + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + LLViewerObject* vobj = drawable->getVObj(); + if (vobj && vobj->onActiveList()) + { + gGL.flush(); + glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f)); + //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f)); + stop_glerror(); + drawBoxOutline(pos,size); + gGL.flush(); + glLineWidth(1.f); + } + else + { + drawBoxOutline(pos,size); + } +} +// *TODO: LLDrawables which are not part of LLVOVolumes fall into a different +// code path which uses a shader - it was tested to be faster than mapping a +// vertex buffer in the terrain case. Consider using it for LLVOVolumes as well +// to simplify and speed up this debug code. Alternatively, a compute shader is +// likely faster. -Cosmic,2023-09-28 +void renderNormals(LLDrawable *drawablep) +{ + if (!drawablep->isVisible()) + return; + + LLVertexBuffer::unbind(); + + LLViewerObject* obj = drawablep->getVObj(); + LLVOVolume *vol = drawablep->getVOVolume(); + + if (obj) + { + LLGLEnable blend(GL_BLEND); + LLGLDepthTest gl_depth(GL_TRUE, GL_FALSE); + + // Drawable's normals & tangents are stored in model space, i.e. before any scaling is applied. + // + // SL-13490, using pos + normal to compute the 2nd vertex of a normal line segment doesn't + // work when there's a non-uniform scale in the mix. Normals require MVP-inverse-transpose + // transform. We get that effect here by pre-applying the inverse scale (twice, because + // one forward scale will be re-applied via the MVP in the vertex shader) + + LLVector4a inv_scale; + float scale_len; + if (vol) + { + LLVector3 scale_v3 = vol->getScale(); + LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]); + obj_scale.normalize3(); + + // Create inverse-scale vector for normals + inv_scale.set(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ], 0.0); + inv_scale.mul(inv_scale); // Squared, to apply inverse scale twice + + inv_scale.normalize3fast(); + scale_len = scale_v3.length(); + } + else + { + inv_scale.set(1.0, 1.0, 1.0, 0.0); + scale_len = 1.0; + } + + gGL.pushMatrix(); + if (vol) { gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix); } @@ -2052,7 +2052,7 @@ void renderNormals(LLDrawable *drawablep) float draw_length = gSavedSettings.getF32("RenderDebugNormalScale") / scale_len; std::vector* faces = nullptr; - std::vector* drawable_faces = nullptr; + std::vector* drawable_faces = nullptr; if (vol) { LLVolume* volume = vol->getVolume(); @@ -2060,67 +2060,67 @@ void renderNormals(LLDrawable *drawablep) } else { - drawable_faces = &drawablep->getFaces(); + drawable_faces = &drawablep->getFaces(); } - if (faces) - { - for (auto it = faces->begin(); it != faces->end(); ++it) - { - const LLVolumeFace& face = *it; - - gGL.flush(); - gGL.diffuseColor4f(1, 1, 0, 1); - gGL.begin(LLRender::LINES); - for (S32 j = 0; j < face.mNumVertices; ++j) - { - LLVector4a n, p; - - n.setMul(face.mNormals[j], 1.0); - n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP - n.normalize3fast(); - n.mul(draw_length); - p.setAdd(face.mPositions[j], n); - - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - } - gGL.end(); - - // Tangents are simple vectors and do not require reorientation via pre-scaling - if (face.mTangents) - { - gGL.flush(); - gGL.diffuseColor4f(0, 1, 1, 1); - gGL.begin(LLRender::LINES); - for (S32 j = 0; j < face.mNumVertices; ++j) - { - LLVector4a t, p; - - t.setMul(face.mTangents[j], 1.0f); - t.normalize3fast(); - t.mul(draw_length); - p.setAdd(face.mPositions[j], t); - - gGL.vertex3fv(face.mPositions[j].getF32ptr()); - gGL.vertex3fv(p.getF32ptr()); - } - gGL.end(); - } - } - } - else if (drawable_faces) - { - // *HACK: Prepare to restore previous shader as other debug code depends on a simpler shader being present - llassert(LLGLSLShader::sCurBoundShaderPtr == &gDebugProgram); - LLGLSLShader* prev_shader = LLGLSLShader::sCurBoundShaderPtr; + if (faces) + { + for (auto it = faces->begin(); it != faces->end(); ++it) + { + const LLVolumeFace& face = *it; + + gGL.flush(); + gGL.diffuseColor4f(1, 1, 0, 1); + gGL.begin(LLRender::LINES); + for (S32 j = 0; j < face.mNumVertices; ++j) + { + LLVector4a n, p; + + n.setMul(face.mNormals[j], 1.0); + n.mul(inv_scale); // Pre-scale normal, so it's left with an inverse-transpose xform after MVP + n.normalize3fast(); + n.mul(draw_length); + p.setAdd(face.mPositions[j], n); + + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + + // Tangents are simple vectors and do not require reorientation via pre-scaling + if (face.mTangents) + { + gGL.flush(); + gGL.diffuseColor4f(0, 1, 1, 1); + gGL.begin(LLRender::LINES); + for (S32 j = 0; j < face.mNumVertices; ++j) + { + LLVector4a t, p; + + t.setMul(face.mTangents[j], 1.0f); + t.normalize3fast(); + t.mul(draw_length); + p.setAdd(face.mPositions[j], t); + + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + } + } + } + else if (drawable_faces) + { + // *HACK: Prepare to restore previous shader as other debug code depends on a simpler shader being present + llassert(LLGLSLShader::sCurBoundShaderPtr == &gDebugProgram); + LLGLSLShader* prev_shader = LLGLSLShader::sCurBoundShaderPtr; for (auto it = drawable_faces->begin(); it != drawable_faces->end(); ++it) { LLFace* facep = *it; LLFace& face = **it; LLVertexBuffer* buf = face.getVertexBuffer(); if (!buf) { continue; } - U32 mask_vn = LLVertexBuffer::TYPE_VERTEX | LLVertexBuffer::TYPE_NORMAL; + U32 mask_vn = LLVertexBuffer::TYPE_VERTEX | LLVertexBuffer::TYPE_NORMAL; if ((buf->getTypeMask() & mask_vn) != mask_vn) { continue; } LLGLSLShader* shader; @@ -2143,11 +2143,11 @@ void renderNormals(LLDrawable *drawablep) // *NOTE: For terrain normal debug, this seems to also include vertices for water, which is technically not part of the terrain. Should fix that at some point. buf->drawRange(LLRender::TRIANGLES, face.getGeomIndex(), face.getGeomIndex() + face.getGeomCount()-1, face.getIndicesCount(), face.getIndicesStart()); } - if (prev_shader) - { - prev_shader->bind(); - } - } + if (prev_shader) + { + prev_shader->bind(); + } + } gGL.popMatrix(); } @@ -2155,278 +2155,278 @@ void renderNormals(LLDrawable *drawablep) S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale) { - const S32 DEFAULT_DETAIL = 1; - const F32 LARGE_THRESHOLD = 5.f; - const F32 MEGA_THRESHOLD = 25.f; + const S32 DEFAULT_DETAIL = 1; + const F32 LARGE_THRESHOLD = 5.f; + const F32 MEGA_THRESHOLD = 25.f; - S32 detail = DEFAULT_DETAIL; - F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f; + S32 detail = DEFAULT_DETAIL; + F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f; - if (avg_scale > LARGE_THRESHOLD) - { - detail += 1; - if (avg_scale > MEGA_THRESHOLD) - { - detail += 1; - } - } + if (avg_scale > LARGE_THRESHOLD) + { + detail += 1; + if (avg_scale > MEGA_THRESHOLD) + { + detail += 1; + } + } - return detail; + return detail; } void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color) { - LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); - LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); - const LLVector3 center(0,0,0); - const LLVector3 size(0.25f,0.25f,0.25f); + const LLVector3 center(0,0,0); + const LLVector3 size(0.25f,0.25f,0.25f); - if (decomp) - { - if (!decomp->mBaseHullMesh.empty()) - { + if (decomp) + { + if (!decomp->mBaseHullMesh.empty()) + { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); - } - else - { - gMeshRepo.buildPhysicsMesh(*decomp); - gGL.diffuseColor4f(0,1,1,1); - drawBoxOutline(center, size); - } - - } - else - { - gGL.diffuseColor3f(1,0,1); - drawBoxOutline(center, size); - } + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions); + } + else + { + gMeshRepo.buildPhysicsMesh(*decomp); + gGL.diffuseColor4f(0,1,1,1); + drawBoxOutline(center, size); + } + + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + } } void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color) { gGL.diffuseColor4fv(color.mV); - LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions); } void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe) { - U8 physics_type = volume->getPhysicsShapeType(); + U8 physics_type = volume->getPhysicsShapeType(); - if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) - { - return; - } + if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) + { + return; + } - //not allowed to return at this point without rendering *something* + //not allowed to return at this point without rendering *something* - F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold"); - F32 cost = volume->getObjectCost(); + F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold"); + F32 cost = volume->getObjectCost(); - LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor"); - LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor"); - LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor"); + LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor"); + LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor"); + LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor"); - F32 normalizedCost = 1.f - exp( -(cost / threshold) ); + F32 normalizedCost = 1.f - exp( -(cost / threshold) ); - LLColor4 color; - if ( normalizedCost <= 0.5f ) - { - color = lerp( low, mid, 2.f * normalizedCost ); - } - else - { - color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) ); - } + LLColor4 color; + if ( normalizedCost <= 0.5f ) + { + color = lerp( low, mid, 2.f * normalizedCost ); + } + else + { + color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) ); + } if (wireframe) { color = color * 0.5f; } - U32 data_mask = LLVertexBuffer::MAP_VERTEX; + U32 data_mask = LLVertexBuffer::MAP_VERTEX; + + LLVolumeParams volume_params = volume->getVolume()->getParams(); - LLVolumeParams volume_params = volume->getVolume()->getParams(); + LLPhysicsVolumeParams physics_params(volume_params, + physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); - LLPhysicsVolumeParams physics_params(volume_params, - physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec; + LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec); - LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec; - LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec); + U32 type = physics_spec.getType(); - U32 type = physics_spec.getType(); + LLVector3 center(0,0,0); + LLVector3 size(0.25f,0.25f,0.25f); - LLVector3 center(0,0,0); - LLVector3 size(0.25f,0.25f,0.25f); + gGL.pushMatrix(); + gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); - gGL.pushMatrix(); - gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); - - if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) - { - LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); - LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); - - if (decomp) - { //render a physics based mesh - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) + { + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + if (decomp) + { //render a physics based mesh - if (!decomp->mHull.empty()) - { //decomposition exists, use that + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (decomp->mMesh.empty()) - { - gMeshRepo.buildPhysicsMesh(*decomp); - } + if (!decomp->mHull.empty()) + { //decomposition exists, use that + + if (decomp->mMesh.empty()) + { + gMeshRepo.buildPhysicsMesh(*decomp); + } - for (U32 i = 0; i < decomp->mMesh.size(); ++i) - { - render_hull(decomp->mMesh[i], color); - } - } - else if (!decomp->mPhysicsShapeMesh.empty()) - { - //decomp has physics mesh, render that mesh + for (U32 i = 0; i < decomp->mMesh.size(); ++i) + { + render_hull(decomp->mMesh[i], color); + } + } + else if (!decomp->mPhysicsShapeMesh.empty()) + { + //decomp has physics mesh, render that mesh gGL.diffuseColor4fv(color.mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions); - } - else - { //no mesh or decomposition, render base hull - renderMeshBaseHull(volume, data_mask, color); - - if (decomp->mPhysicsShapeMesh.empty()) - { - //attempt to fetch physics shape mesh if available - gMeshRepo.fetchPhysicsShape(mesh_id); - } - } - } - else - { - gGL.diffuseColor3f(1,1,0); - drawBoxOutline(center, size); - } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || - type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) - { - if (volume->isMesh()) - { - renderMeshBaseHull(volume, data_mask, color); - } - else - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); - - if (!phys_volume->mHullPoints) - { //build convex hull - std::vector pos; - std::vector index; - - S32 index_offset = 0; - - for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = phys_volume->getVolumeFace(i); - if (index_offset + face.mNumVertices > 65535) - { - continue; - } - - for (S32 j = 0; j < face.mNumVertices; ++j) - { - pos.push_back(LLVector3(face.mPositions[j].getF32ptr())); - } - - for (S32 j = 0; j < face.mNumIndices; ++j) - { - index.push_back(face.mIndices[j]+index_offset); - } - - index_offset += face.mNumVertices; - } - - if (!pos.empty() && !index.empty()) - { - LLCDMeshData mesh; - mesh.mIndexBase = &index[0]; - mesh.mVertexBase = pos[0].mV; - mesh.mNumVertices = pos.size(); - mesh.mVertexStrideBytes = 12; - mesh.mIndexStrideBytes = 6; - mesh.mIndexType = LLCDMeshData::INT_16; - - mesh.mNumTriangles = index.size()/3; - - LLCDMeshData res; - - LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res ); - - //copy res into phys_volume - phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices); - phys_volume->mNumHullPoints = res.mNumVertices; - - S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF; - phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size); - phys_volume->mNumHullIndices = res.mNumTriangles*3; - - const F32* v = res.mVertexBase; - - for (S32 i = 0; i < res.mNumVertices; ++i) - { - F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes); - phys_volume->mHullPoints[i].load3(p); - } - - if (res.mIndexType == LLCDMeshData::INT_16) - { - for (S32 i = 0; i < res.mNumTriangles; ++i) - { - U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); - - phys_volume->mHullIndices[i*3+0] = idx[0]; - phys_volume->mHullIndices[i*3+1] = idx[1]; - phys_volume->mHullIndices[i*3+2] = idx[2]; - } - } - else - { - for (S32 i = 0; i < res.mNumTriangles; ++i) - { - U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); - - phys_volume->mHullIndices[i*3+0] = (U16) idx[0]; - phys_volume->mHullIndices[i*3+1] = (U16) idx[1]; - phys_volume->mHullIndices[i*3+2] = (U16) idx[2]; - } - } - } - } - - if (phys_volume->mHullPoints) - { - //render hull + } + else + { //no mesh or decomposition, render base hull + renderMeshBaseHull(volume, data_mask, color); + + if (decomp->mPhysicsShapeMesh.empty()) + { + //attempt to fetch physics shape mesh if available + gMeshRepo.fetchPhysicsShape(mesh_id); + } + } + } + else + { + gGL.diffuseColor3f(1,1,0); + drawBoxOutline(center, size); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || + type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + if (volume->isMesh()) + { + renderMeshBaseHull(volume, data_mask, color); + } + else + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + + if (!phys_volume->mHullPoints) + { //build convex hull + std::vector pos; + std::vector index; + + S32 index_offset = 0; + + for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = phys_volume->getVolumeFace(i); + if (index_offset + face.mNumVertices > 65535) + { + continue; + } + + for (S32 j = 0; j < face.mNumVertices; ++j) + { + pos.push_back(LLVector3(face.mPositions[j].getF32ptr())); + } + + for (S32 j = 0; j < face.mNumIndices; ++j) + { + index.push_back(face.mIndices[j]+index_offset); + } + + index_offset += face.mNumVertices; + } + + if (!pos.empty() && !index.empty()) + { + LLCDMeshData mesh; + mesh.mIndexBase = &index[0]; + mesh.mVertexBase = pos[0].mV; + mesh.mNumVertices = pos.size(); + mesh.mVertexStrideBytes = 12; + mesh.mIndexStrideBytes = 6; + mesh.mIndexType = LLCDMeshData::INT_16; + + mesh.mNumTriangles = index.size()/3; + + LLCDMeshData res; + + LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res ); + + //copy res into phys_volume + phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices); + phys_volume->mNumHullPoints = res.mNumVertices; + + S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF; + phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size); + phys_volume->mNumHullIndices = res.mNumTriangles*3; + + const F32* v = res.mVertexBase; + + for (S32 i = 0; i < res.mNumVertices; ++i) + { + F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes); + phys_volume->mHullPoints[i].load3(p); + } + + if (res.mIndexType == LLCDMeshData::INT_16) + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = idx[0]; + phys_volume->mHullIndices[i*3+1] = idx[1]; + phys_volume->mHullIndices[i*3+2] = idx[2]; + } + } + else + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = (U16) idx[0]; + phys_volume->mHullIndices[i*3+1] = (U16) idx[1]; + phys_volume->mHullIndices[i*3+2] = (U16) idx[2]; + } + } + } + } + + if (phys_volume->mHullPoints) + { + //render hull gGL.diffuseColor4fv(color.mV); LLVertexBuffer::unbind(); - LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); - } - else - { - gGL.diffuseColor4f(1,0,1,1); - drawBoxOutline(center, size); - } - - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX) - { + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + } + else + { + gGL.diffuseColor4f(1,0,1,1); + drawBoxOutline(center, size); + } + + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX) + { if (!wireframe) { LLVector3 center = physics_spec.getCenter(); @@ -2437,9 +2437,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe gGL.diffuseColor4fv(color.mV); drawBox(center, scale); } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE) - { + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE) + { if (!wireframe) { LLVolumeParams volume_params; @@ -2454,9 +2454,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe pushVerts(sphere); LLPrimitive::sVolumeManager->unrefVolume(sphere); } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) - { + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) + { if (!wireframe) { LLVolumeParams volume_params; @@ -2471,244 +2471,244 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe pushVerts(cylinder); LLPrimitive::sVolumeManager->unrefVolume(cylinder); } - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); gGL.diffuseColor4fv(color.mV); - pushVerts(phys_volume); + pushVerts(phys_volume); + + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) - { - LLVolumeParams volume_params = volume->getVolume()->getParams(); - S32 detail = get_physics_detail(volume_params, volume->getScale()); + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); - LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + if (phys_volume->mHullPoints && phys_volume->mHullIndices) + { - if (phys_volume->mHullPoints && phys_volume->mHullIndices) - { - - llassert(LLGLSLShader::sCurBoundShader != 0); - LLVertexBuffer::unbind(); - glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); + llassert(LLGLSLShader::sCurBoundShader != 0); + LLVertexBuffer::unbind(); + glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); gGL.diffuseColor4fv(color.mV); gGL.syncMatrices(); - glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); - } - else - { - gGL.diffuseColor3f(1,0,1); - drawBoxOutline(center, size); - gMeshRepo.buildHull(volume_params, detail); - } - LLPrimitive::sVolumeManager->unrefVolume(phys_volume); - } - else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) - { - //TODO: implement sculpted prim physics display - } - else - { - LL_ERRS() << "Unhandled type" << LL_ENDL; - } - - gGL.popMatrix(); + glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + gMeshRepo.buildHull(volume_params, detail); + } + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) + { + //TODO: implement sculpted prim physics display + } + else + { + LL_ERRS() << "Unhandled type" << LL_ENDL; + } + + gGL.popMatrix(); } void renderPhysicsShapes(LLSpatialGroup* group, bool wireframe) { - for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - - if (drawable->isSpatialBridge()) - { - LLSpatialBridge* bridge = drawable->asPartition()->asBridge(); - - if (bridge) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderPhysicsShapes(wireframe); - gGL.popMatrix(); - } - } - else - { - LLVOVolume* volume = drawable->getVOVolume(); - if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) - { - if (!group->getSpatialPartition()->isBridge()) - { - gGL.pushMatrix(); - LLVector3 trans = drawable->getRegion()->getOriginAgent(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - renderPhysicsShape(drawable, volume, wireframe); - gGL.popMatrix(); - } - else - { - renderPhysicsShape(drawable, volume, wireframe); - } - } - else - { -#if 0 - LLViewerObject* object = drawable->getVObj(); - if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); - //push face vertices for terrain - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) - { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - buff->setBuffer(); - gGL.diffuseColor4f(0.2f, 0.5f, 0.3f, 0.5f); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - - gGL.diffuseColor4f(0.2f, 1.f, 0.3f, 0.75f); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); - } - } - } - gGL.popMatrix(); - } + for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + + if (drawable->isSpatialBridge()) + { + LLSpatialBridge* bridge = drawable->asPartition()->asBridge(); + + if (bridge) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderPhysicsShapes(wireframe); + gGL.popMatrix(); + } + } + else + { + LLVOVolume* volume = drawable->getVOVolume(); + if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) + { + if (!group->getSpatialPartition()->isBridge()) + { + gGL.pushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + renderPhysicsShape(drawable, volume, wireframe); + gGL.popMatrix(); + } + else + { + renderPhysicsShape(drawable, volume, wireframe); + } + } + else + { +#if 0 + LLViewerObject* object = drawable->getVObj(); + if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); + //push face vertices for terrain + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + buff->setBuffer(); + gGL.diffuseColor4f(0.2f, 0.5f, 0.3f, 0.5f); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + + gGL.diffuseColor4f(0.2f, 1.f, 0.3f, 0.75f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + } + } + } + gGL.popMatrix(); + } #endif - } - } - } + } + } + } } void renderTexturePriority(LLDrawable* drawable) { - for (int face=0; facegetNumFaces(); ++face) - { - LLFace *facep = drawable->getFace(face); - - LLVector4 cold(0,0,0.25f); - LLVector4 hot(1,0.25f,0.25f); - - LLVector4 boost_cold(0,0,0,0); - LLVector4 boost_hot(0,1,0,1); - - LLGLDisable blend(GL_BLEND); - - //LLViewerTexture* imagep = facep->getTexture(); - //if (imagep) - if (facep) - { - - //F32 vsize = imagep->mMaxVirtualSize; - F32 vsize = facep->getPixelArea(); - - if (vsize > sCurMaxTexPriority) - { - sCurMaxTexPriority = vsize; - } - - F32 t = vsize/sLastMaxTexPriority; - - LLVector4 col = lerp(cold, hot, t); - gGL.diffuseColor4fv(col.mV); - } - //else - //{ - // gGL.diffuseColor4f(1,0,1,1); - //} - - LLVector4a center; - center.setAdd(facep->mExtents[1],facep->mExtents[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(facep->mExtents[1],facep->mExtents[0]); - size.mul(0.5f); - size.add(LLVector4a(0.01f)); - drawBox(center, size); - - /*S32 boost = imagep->getBoostLevel(); - if (boost>LLGLTexture::BOOST_NONE) - { - F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); - LLVector4 col = lerp(boost_cold, boost_hot, t); - LLGLEnable blend_on(GL_BLEND); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); - gGL.diffuseColor4fv(col.mV); - drawBox(center, size); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - }*/ - } + for (int face=0; facegetNumFaces(); ++face) + { + LLFace *facep = drawable->getFace(face); + + LLVector4 cold(0,0,0.25f); + LLVector4 hot(1,0.25f,0.25f); + + LLVector4 boost_cold(0,0,0,0); + LLVector4 boost_hot(0,1,0,1); + + LLGLDisable blend(GL_BLEND); + + //LLViewerTexture* imagep = facep->getTexture(); + //if (imagep) + if (facep) + { + + //F32 vsize = imagep->mMaxVirtualSize; + F32 vsize = facep->getPixelArea(); + + if (vsize > sCurMaxTexPriority) + { + sCurMaxTexPriority = vsize; + } + + F32 t = vsize/sLastMaxTexPriority; + + LLVector4 col = lerp(cold, hot, t); + gGL.diffuseColor4fv(col.mV); + } + //else + //{ + // gGL.diffuseColor4f(1,0,1,1); + //} + + LLVector4a center; + center.setAdd(facep->mExtents[1],facep->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(facep->mExtents[1],facep->mExtents[0]); + size.mul(0.5f); + size.add(LLVector4a(0.01f)); + drawBox(center, size); + + /*S32 boost = imagep->getBoostLevel(); + if (boost>LLGLTexture::BOOST_NONE) + { + F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); + LLVector4 col = lerp(boost_cold, boost_hot, t); + LLGLEnable blend_on(GL_BLEND); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); + gGL.diffuseColor4fv(col.mV); + drawBox(center, size); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + }*/ + } } void renderPoints(LLDrawable* drawablep) { - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - if (drawablep->getNumFaces()) - { - gGL.begin(LLRender::POINTS); - gGL.diffuseColor3f(1,1,1); - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace * face = drawablep->getFace(i); - if (face) - { - gGL.vertex3fv(face->mCenterLocal.mV); - } - } - gGL.end(); - } + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + if (drawablep->getNumFaces()) + { + gGL.begin(LLRender::POINTS); + gGL.diffuseColor3f(1,1,1); + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace * face = drawablep->getFace(i); + if (face) + { + gGL.vertex3fv(face->mCenterLocal.mV); + } + } + gGL.end(); + } } void renderTextureAnim(LLDrawInfo* params) { - if (!params->mTextureMatrix) - { - return; - } - - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(1,1,0,0.5f); - pushVerts(params); + if (!params->mTextureMatrix) + { + return; + } + + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(1,1,0,0.5f); + pushVerts(params); } void renderBatchSize(LLDrawInfo* params) { - LLGLEnable offset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.f, 1.f); + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, 1.f); LLGLSLShader* old_shader = LLGLSLShader::sCurBoundShaderPtr; bool bind = false; if (params->mAvatar) - { + { gGL.pushMatrix(); gGL.loadMatrix(gGLModelView); bind = true; old_shader->mRiggedVariant->bind(); LLRenderPass::uploadMatrixPalette(*params); } - - + + gGL.diffuseColor4ubv(params->getDebugColor().mV); - pushVerts(params); + pushVerts(params); if (bind) { @@ -2719,220 +2719,220 @@ void renderBatchSize(LLDrawInfo* params) void renderTexelDensity(LLDrawable* drawable) { - if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF - || LLViewerTexture::sCheckerBoardImagep.isNull()) - { - return; - } - - LLGLEnable _(GL_BLEND); - - LLMatrix4 checkerboard_matrix; - S32 discard_level = -1; - - for (S32 f = 0; f < drawable->getNumFaces(); f++) - { - LLFace* facep = drawable->getFace(f); - LLVertexBuffer* buffer = facep->getVertexBuffer(); - LLViewerTexture* texturep = facep->getTexture(); - - if (texturep == NULL) continue; - - switch(LLViewerTexture::sDebugTexelsMode) - { - case LLViewerTexture::DEBUG_TEXELS_CURRENT: - discard_level = -1; - break; - case LLViewerTexture::DEBUG_TEXELS_DESIRED: - { - LLViewerFetchedTexture* fetched_texturep = dynamic_cast(texturep); - discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; - break; - } - default: - case LLViewerTexture::DEBUG_TEXELS_FULL: - discard_level = 0; - break; - } - - checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); - - gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); - gGL.matrixMode(LLRender::MM_TEXTURE); - gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); - - if (buffer && (facep->getGeomCount() >= 3)) - { - buffer->setBuffer(); - U16 start = facep->getGeomStart(); - U16 end = start + facep->getGeomCount()-1; - U32 count = facep->getIndicesCount(); - U16 offset = facep->getIndicesStart(); - buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); - } - - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - - //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); - - //for (S32 i = 0; i < num_textures; i++) - //{ - // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); - // if (texturep == NULL) continue; - - // LLMatrix4 checkboard_matrix; - // S32 discard_level = -1; - // switch(LLViewerTexture::sDebugTexelsMode) - // { - // case LLViewerTexture::DEBUG_TEXELS_CURRENT: - // discard_level = -1; - // break; - // case LLViewerTexture::DEBUG_TEXELS_DESIRED: - // { - // LLViewerFetchedTexture* fetched_texturep = dynamic_cast(texturep); - // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; - // break; - // } - // default: - // case LLViewerTexture::DEBUG_TEXELS_FULL: - // discard_level = 0; - // break; - // } - - // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); - // gGL.getTexUnit(i)->activate(); - - // glMatrixMode(GL_TEXTURE); - // glPushMatrix(); - // glLoadIdentity(); - // //gGL.matrixMode(LLRender::MM_TEXTURE); - // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); - - // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); - - // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); - - // glPopMatrix(); - // glMatrixMode(GL_MODELVIEW); - // //gGL.matrixMode(LLRender::MM_MODELVIEW); - //} + if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF + || LLViewerTexture::sCheckerBoardImagep.isNull()) + { + return; + } + + LLGLEnable _(GL_BLEND); + + LLMatrix4 checkerboard_matrix; + S32 discard_level = -1; + + for (S32 f = 0; f < drawable->getNumFaces(); f++) + { + LLFace* facep = drawable->getFace(f); + LLVertexBuffer* buffer = facep->getVertexBuffer(); + LLViewerTexture* texturep = facep->getTexture(); + + if (texturep == NULL) continue; + + switch(LLViewerTexture::sDebugTexelsMode) + { + case LLViewerTexture::DEBUG_TEXELS_CURRENT: + discard_level = -1; + break; + case LLViewerTexture::DEBUG_TEXELS_DESIRED: + { + LLViewerFetchedTexture* fetched_texturep = dynamic_cast(texturep); + discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + break; + } + default: + case LLViewerTexture::DEBUG_TEXELS_FULL: + discard_level = 0; + break; + } + + checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + + gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); + + if (buffer && (facep->getGeomCount() >= 3)) + { + buffer->setBuffer(); + U16 start = facep->getGeomStart(); + U16 end = start + facep->getGeomCount()-1; + U32 count = facep->getIndicesCount(); + U16 offset = facep->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + + //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); + + //for (S32 i = 0; i < num_textures; i++) + //{ + // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); + // if (texturep == NULL) continue; + + // LLMatrix4 checkboard_matrix; + // S32 discard_level = -1; + // switch(LLViewerTexture::sDebugTexelsMode) + // { + // case LLViewerTexture::DEBUG_TEXELS_CURRENT: + // discard_level = -1; + // break; + // case LLViewerTexture::DEBUG_TEXELS_DESIRED: + // { + // LLViewerFetchedTexture* fetched_texturep = dynamic_cast(texturep); + // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + // break; + // } + // default: + // case LLViewerTexture::DEBUG_TEXELS_FULL: + // discard_level = 0; + // break; + // } + + // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + // gGL.getTexUnit(i)->activate(); + + // glMatrixMode(GL_TEXTURE); + // glPushMatrix(); + // glLoadIdentity(); + // //gGL.matrixMode(LLRender::MM_TEXTURE); + // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); + + // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + + // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); + + // glPopMatrix(); + // glMatrixMode(GL_MODELVIEW); + // //gGL.matrixMode(LLRender::MM_MODELVIEW); + //} } void renderLights(LLDrawable* drawablep) { - if (!drawablep->isLight()) - { - return; - } - - if (drawablep->getNumFaces()) - { - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(0,1,1,0.5f); - - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace * face = drawablep->getFace(i); - if (face) - { - pushVerts(face); - } - } - - const LLVector4a* ext = drawablep->getSpatialExtents(); - - LLVector4a pos; - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - { - LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.diffuseColor4f(1,1,1,1); - drawBoxOutline(pos, size); - } - - gGL.diffuseColor4f(1,1,0,1); - F32 rad = drawablep->getVOVolume()->getLightRadius(); - drawBoxOutline(pos, LLVector4a(rad)); - } + if (!drawablep->isLight()) + { + return; + } + + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(0,1,1,0.5f); + + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace * face = drawablep->getFace(i); + if (face) + { + pushVerts(face); + } + } + + const LLVector4a* ext = drawablep->getSpatialExtents(); + + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + { + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.diffuseColor4f(1,1,1,1); + drawBoxOutline(pos, size); + } + + gGL.diffuseColor4f(1,1,0,1); + F32 rad = drawablep->getVOVolume()->getLightRadius(); + drawBoxOutline(pos, LLVector4a(rad)); + } } class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect { public: - LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) - : LLOctreeTriangleRayIntersect(start, dir, nullptr, closest_t, NULL, NULL, NULL, NULL) - { + LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) + : LLOctreeTriangleRayIntersect(start, dir, nullptr, closest_t, NULL, NULL, NULL, NULL) + { - } + } void visit(const LLOctreeNode* branch) - { - LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); - - LLVector3 center, size; - - if (branch->isEmpty()) - { - gGL.diffuseColor3f(1.f,0.2f,0.f); - center.set(branch->getCenter().getF32ptr()); - size.set(branch->getSize().getF32ptr()); - } - else - { - gGL.diffuseColor3f(0.75f, 1.f, 0.f); - center.set(vl->mBounds[0].getF32ptr()); - size.set(vl->mBounds[1].getF32ptr()); - } - - drawBoxOutline(center, size); - - for (U32 i = 0; i < 2; i++) - { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); - - if (i == 1) - { - gGL.diffuseColor4f(0,1,1,0.5f); - } - else - { - gGL.diffuseColor4f(0,0.5f,0.5f, 0.25f); - drawBoxOutline(center, size); - } - - if (i == 1) - { - gGL.flush(); - glLineWidth(3.f); - } - - gGL.begin(LLRender::TRIANGLES); + { + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); + + LLVector3 center, size; + + if (branch->isEmpty()) + { + gGL.diffuseColor3f(1.f,0.2f,0.f); + center.set(branch->getCenter().getF32ptr()); + size.set(branch->getSize().getF32ptr()); + } + else + { + gGL.diffuseColor3f(0.75f, 1.f, 0.f); + center.set(vl->mBounds[0].getF32ptr()); + size.set(vl->mBounds[1].getF32ptr()); + } + + drawBoxOutline(center, size); + + for (U32 i = 0; i < 2; i++) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); + + if (i == 1) + { + gGL.diffuseColor4f(0,1,1,0.5f); + } + else + { + gGL.diffuseColor4f(0,0.5f,0.5f, 0.25f); + drawBoxOutline(center, size); + } + + if (i == 1) + { + gGL.flush(); + glLineWidth(3.f); + } + + gGL.begin(LLRender::TRIANGLES); for (LLOctreeNode::const_element_iter iter = branch->getDataBegin(); - iter != branch->getDataEnd(); - ++iter) - { - const LLVolumeTriangle* tri = *iter; - - gGL.vertex3fv(tri->mV[0]->getF32ptr()); - gGL.vertex3fv(tri->mV[1]->getF32ptr()); - gGL.vertex3fv(tri->mV[2]->getF32ptr()); - } - gGL.end(); - - if (i == 1) - { - gGL.flush(); - glLineWidth(1.f); - } - } - } + iter != branch->getDataEnd(); + ++iter) + { + const LLVolumeTriangle* tri = *iter; + + gGL.vertex3fv(tri->mV[0]->getF32ptr()); + gGL.vertex3fv(tri->mV[1]->getF32ptr()); + gGL.vertex3fv(tri->mV[2]->getF32ptr()); + } + gGL.end(); + + if (i == 1) + { + gGL.flush(); + glLineWidth(1.f); + } + } + } }; void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const LLVolumeOctree* octree) @@ -2944,161 +2944,161 @@ void renderOctreeRaycast(const LLVector4a& start, const LLVector4a& end, const L void renderRaycast(LLDrawable* drawablep) { - if (drawablep->getNumFaces()) - { - LLGLEnable blend(GL_BLEND); - gGL.diffuseColor4f(0,1,1,0.5f); - - LLVOVolume* vobj = drawablep->getVOVolume(); - if (vobj && !vobj->isDead()) - { - //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - LLVolume* volume = vobj->getVolume(); - - bool transform = true; - if (drawablep->isState(LLDrawable::RIGGED)) - { - volume = vobj->getRiggedVolume(); - transform = false; - } - - if (volume) - { - LLVector3 trans = drawablep->getRegion()->getOriginAgent(); - - for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - - gGL.pushMatrix(); - gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); - gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); - - LLVector4a start, end; - if (transform) - { - LLVector3 v_start(gDebugRaycastStart.getF32ptr()); - LLVector3 v_end(gDebugRaycastEnd.getF32ptr()); - - v_start = vobj->agentPositionToVolume(v_start); - v_end = vobj->agentPositionToVolume(v_end); - - start.load3(v_start.mV); - end.load3(v_end.mV); - } - else - { - start = gDebugRaycastStart; - end = gDebugRaycastEnd; - } - - LLVector4a dir; - dir.setSub(end, start); - - gGL.flush(); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - { - //render face positions - //gGL.diffuseColor4f(0,1,1,0.5f); + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + gGL.diffuseColor4f(0,1,1,0.5f); + + LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj && !vobj->isDead()) + { + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + LLVolume* volume = vobj->getVolume(); + + bool transform = true; + if (drawablep->isState(LLDrawable::RIGGED)) + { + volume = vobj->getRiggedVolume(); + transform = false; + } + + if (volume) + { + LLVector3 trans = drawablep->getRegion()->getOriginAgent(); + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + gGL.pushMatrix(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + + LLVector4a start, end; + if (transform) + { + LLVector3 v_start(gDebugRaycastStart.getF32ptr()); + LLVector3 v_end(gDebugRaycastEnd.getF32ptr()); + + v_start = vobj->agentPositionToVolume(v_start); + v_end = vobj->agentPositionToVolume(v_end); + + start.load3(v_start.mV); + end.load3(v_end.mV); + } + else + { + start = gDebugRaycastStart; + end = gDebugRaycastEnd; + } + + LLVector4a dir; + dir.setSub(end, start); + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + { + //render face positions + //gGL.diffuseColor4f(0,1,1,0.5f); //LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, nullptr, face.mNumIndices, face.mIndices); - } - - if (!volume->isUnique()) - { + } + + if (!volume->isUnique()) + { if (!face.getOctree()) - { - ((LLVolumeFace*) &face)->createOctree(); - } + { + ((LLVolumeFace*) &face)->createOctree(); + } renderOctreeRaycast(start, end, face.getOctree()); - } - - gGL.popMatrix(); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - } - } - else if (drawablep->isAvatar()) - { - if (drawablep->getVObj() == gDebugRaycastObject) - { - LLGLDepthTest depth(GL_FALSE); - LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get(); - av->renderCollisionVolumes(); - } - } - - if (drawablep->getVObj() == gDebugRaycastObject) - { - // draw intersection point - gGL.pushMatrix(); - gGL.loadMatrix(gGLModelView); - LLVector3 translate(gDebugRaycastIntersection.getF32ptr()); - gGL.translatef(translate.mV[0], translate.mV[1], translate.mV[2]); - LLCoordFrame orient; - LLVector4a debug_binormal; - - debug_binormal.setCross3(gDebugRaycastNormal, gDebugRaycastTangent); - debug_binormal.mul(gDebugRaycastTangent.getF32ptr()[3]); - - LLVector3 normal(gDebugRaycastNormal.getF32ptr()); - LLVector3 binormal(debug_binormal.getF32ptr()); - - orient.lookDir(normal, binormal); - LLMatrix4 rotation; - orient.getRotMatrixToParent(rotation); - gGL.multMatrix((float*)rotation.mMatrix); - - gGL.diffuseColor4f(1,0,0,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); - gGL.diffuseColor4f(0,1,0,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); - gGL.diffuseColor4f(0,0,1,0.5f); - drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); - gGL.popMatrix(); - - // draw bounding box of prim - const LLVector4a* ext = drawablep->getSpatialExtents(); - - LLVector4a pos; - pos.setAdd(ext[0], ext[1]); - pos.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.diffuseColor4f(0,0.5f,0.5f,1); - drawBoxOutline(pos, size); - } - } + } + + gGL.popMatrix(); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + } + else if (drawablep->isAvatar()) + { + if (drawablep->getVObj() == gDebugRaycastObject) + { + LLGLDepthTest depth(GL_FALSE); + LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get(); + av->renderCollisionVolumes(); + } + } + + if (drawablep->getVObj() == gDebugRaycastObject) + { + // draw intersection point + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + LLVector3 translate(gDebugRaycastIntersection.getF32ptr()); + gGL.translatef(translate.mV[0], translate.mV[1], translate.mV[2]); + LLCoordFrame orient; + LLVector4a debug_binormal; + + debug_binormal.setCross3(gDebugRaycastNormal, gDebugRaycastTangent); + debug_binormal.mul(gDebugRaycastTangent.getF32ptr()[3]); + + LLVector3 normal(gDebugRaycastNormal.getF32ptr()); + LLVector3 binormal(debug_binormal.getF32ptr()); + + orient.lookDir(normal, binormal); + LLMatrix4 rotation; + orient.getRotMatrixToParent(rotation); + gGL.multMatrix((float*)rotation.mMatrix); + + gGL.diffuseColor4f(1,0,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); + gGL.diffuseColor4f(0,1,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); + gGL.diffuseColor4f(0,0,1,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); + gGL.popMatrix(); + + // draw bounding box of prim + const LLVector4a* ext = drawablep->getSpatialExtents(); + + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.diffuseColor4f(0,0.5f,0.5f,1); + drawBoxOutline(pos, size); + } + } } void renderAvatarCollisionVolumes(LLVOAvatar* avatar) { - avatar->renderCollisionVolumes(); + avatar->renderCollisionVolumes(); } void renderAvatarBones(LLVOAvatar* avatar) { - avatar->renderBones(); + avatar->renderBones(); } void renderAgentTarget(LLVOAvatar* avatar) { - // render these for self only (why, i don't know) - if (avatar->isSelf()) - { - renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); - renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); - renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); - renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); - } + // render these for self only (why, i don't know) + if (avatar->isSelf()) + { + renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); + renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f)); + renderCrossHairs(avatar->mRoot->getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f)); + renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f)); + } } static void setTextureAreaDebugText(LLDrawable* drawablep) @@ -3140,686 +3140,686 @@ static void setTextureAreaDebugText(LLDrawable* drawablep) { str << llformat("\nS - %.2f", sqrtf(imagep->getMaxVirtualSize())); } - - str << "\n\n"; + + str << "\n\n"; + } + + vobjp->setDebugText(str.str()); + } + } + } + else + { + vobjp->setDebugText("."); + } + } +} + +class LLOctreeRenderNonOccluded : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + //draw tight fit bounding boxes for spatial group + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + renderOctree(group); + stop_glerror(); + } + } + } + + virtual void visit(const OctreeNode* branch) + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) + { + return; + } + + group->rebuildGeom(); + group->rebuildMesh(); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + if (!group->isEmpty()) + { + gGL.diffuseColor3f(0,0,1); + const LLVector4a* obj_bounds = group->getObjectBounds(); + drawBoxOutline(obj_bounds[0], obj_bounds[1]); + } + } + + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable || drawable->isDead()) + { + continue; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) + { + renderBoundingBox(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS)) + { + renderNormals(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setTextureAreaDebugText(drawable); + } + + /*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + renderTexturePriority(drawable); + }*/ + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) + { + renderPoints(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS)) + { + renderLights(drawable); + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + renderRaycast(drawable); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) + { + renderUpdateType(drawable); + } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + renderTexelDensity(drawable); + } + + LLVOAvatar* avatar = dynamic_cast(drawable->getVObj().get()); + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) + { + renderAvatarCollisionVolumes(avatar); + } + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) + { + renderAvatarBones(avatar); + } + + if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) + { + renderAgentTarget(avatar); + } + +#if 0 + if (gDebugGL) + { + for (U32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) + { + if (index < FACE_DO_NOT_BATCH_TEXTURES) + { + if (facep->mDrawInfo->mTextureList.size() <= index) + { + LL_ERRS() << "Face texture index out of bounds." << LL_ENDL; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + LL_ERRS() << "Face texture index incorrect." << LL_ENDL; + } + } + } } - - vobjp->setDebugText(str.str()); } } +#endif } - else + + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { - vobjp->setDebugText("."); + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* draw_info = *j; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) + { + renderTextureAnim(draw_info); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE)) + { + renderBatchSize(draw_info); + } + } } } -} +}; -class LLOctreeRenderNonOccluded : public OctreeTraveler +class LLOctreeRenderXRay : public OctreeTraveler { public: - LLCamera* mCamera; - LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} - - virtual void traverse(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - //draw tight fit bounding boxes for spatial group - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) - { - group->rebuildGeom(); - group->rebuildMesh(); - - renderOctree(group); - stop_glerror(); - } - } - } - - virtual void visit(const OctreeNode* branch) - { - LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - const LLVector4a* bounds = group->getBounds(); - if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) - { - return; - } - - group->rebuildGeom(); - group->rebuildMesh(); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) - { - if (!group->isEmpty()) - { - gGL.diffuseColor3f(0,0,1); - const LLVector4a* obj_bounds = group->getObjectBounds(); - drawBoxOutline(obj_bounds[0], obj_bounds[1]); - } - } - - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable || drawable->isDead()) - { - continue; - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) - { - renderBoundingBox(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS)) - { - renderNormals(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + LLCamera* mCamera; + LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) { - setTextureAreaDebugText(drawable); + traverse(node->getChild(i)); + stop_glerror(); } - /*if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - renderTexturePriority(drawable); - }*/ - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) - { - renderPoints(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS)) - { - renderLights(drawable); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - renderRaycast(drawable); - } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_UPDATE_TYPE)) - { - renderUpdateType(drawable); - } - if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) - { - renderTexelDensity(drawable); - } - - LLVOAvatar* avatar = dynamic_cast(drawable->getVObj().get()); - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME)) - { - renderAvatarCollisionVolumes(avatar); - } - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_JOINTS)) - { - renderAvatarBones(avatar); - } - - if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET)) - { - renderAgentTarget(avatar); - } - -#if 0 - if (gDebugGL) - { - for (U32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - U8 index = facep->getTextureIndex(); - if (facep->mDrawInfo) - { - if (index < FACE_DO_NOT_BATCH_TEXTURES) - { - if (facep->mDrawInfo->mTextureList.size() <= index) - { - LL_ERRS() << "Face texture index out of bounds." << LL_ENDL; - } - else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) - { - LL_ERRS() << "Face texture index incorrect." << LL_ENDL; - } - } - } - } - } - } -#endif - } - - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; - for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) - { - LLDrawInfo* draw_info = *j; - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) - { - renderTextureAnim(draw_info); - } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE)) - { - renderBatchSize(draw_info); - } - } - } - } -}; + //render visibility wireframe + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + gGL.flush(); + gGL.pushMatrix(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + renderXRay(group, mCamera); + stop_glerror(); + gGLLastMatrix = NULL; + gGL.popMatrix(); + } + } + } -class LLOctreeRenderXRay : public OctreeTraveler -{ -public: - LLCamera* mCamera; - LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {} - - virtual void traverse(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - //render visibility wireframe - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - group->rebuildGeom(); - group->rebuildMesh(); - - gGL.flush(); - gGL.pushMatrix(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - renderXRay(group, mCamera); - stop_glerror(); - gGLLastMatrix = NULL; - gGL.popMatrix(); - } - } - } - - virtual void visit(const OctreeNode* node) {} + virtual void visit(const OctreeNode* node) {} }; class LLOctreeRenderPhysicsShapes : public OctreeTraveler { public: - LLCamera* mCamera; + LLCamera* mCamera; bool mWireframe; - LLOctreeRenderPhysicsShapes(LLCamera* camera, bool wireframe): mCamera(camera), mWireframe(wireframe) {} - - virtual void traverse(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) - { - node->accept(this); - stop_glerror(); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - stop_glerror(); - } - - group->rebuildGeom(); - group->rebuildMesh(); - - renderPhysicsShapes(group, mWireframe); - } - } - - virtual void visit(const OctreeNode* branch) - { - - } + LLOctreeRenderPhysicsShapes(LLCamera* camera, bool wireframe): mCamera(camera), mWireframe(wireframe) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + group->rebuildGeom(); + group->rebuildMesh(); + + renderPhysicsShapes(group, mWireframe); + } + } + + virtual void visit(const OctreeNode* branch) + { + + } }; class LLOctreePushBBoxVerts : public OctreeTraveler { public: - LLCamera* mCamera; - LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} - - virtual void traverse(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) - { - node->accept(this); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - } - } - - virtual void visit(const OctreeNode* branch) - { - LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - - const LLVector4a* bounds = group->getBounds(); - if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) - { - return; - } - - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(!drawable) - { - continue; - } - renderBoundingBox(drawable, FALSE); - } - } + LLCamera* mCamera; + LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + } + } + + virtual void visit(const OctreeNode* branch) + { + LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) + { + return; + } + + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + renderBoundingBox(drawable, FALSE); + } + } }; void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) { - LLOctreePushBBoxVerts pusher(camera); - pusher.traverse(mOctree); + LLOctreePushBBoxVerts pusher(camera); + pusher.traverse(mOctree); } class LLOctreeStateCheck : public OctreeTraveler { public: - U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; - - LLOctreeStateCheck() - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mInheritedMask[i] = 0; - } - } - - virtual void traverse(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - node->accept(this); - - - U32 temp[LLViewerCamera::NUM_CAMERAS]; - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - temp[i] = mInheritedMask[i]; - mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED; - } - - for (U32 i = 0; i < node->getChildCount(); i++) - { - traverse(node->getChild(i)); - } - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mInheritedMask[i] = temp[i]; - } - } - - - virtual void visit(const OctreeNode* state) - { - LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) - { - LL_ERRS() << "Spatial group failed inherited mask test." << LL_ENDL; - } - } - - if (group->hasState(LLSpatialGroup::DIRTY)) - { - assert_parent_state(group, LLSpatialGroup::DIRTY); - } - } - - void assert_parent_state(LLSpatialGroup* group, U32 state) - { - LLSpatialGroup* parent = group->getParent(); - while (parent) - { - if (!parent->hasState(state)) - { - LL_ERRS() << "Spatial group failed parent state check." << LL_ENDL; - } - parent = parent->getParent(); - } - } + U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; + + LLOctreeStateCheck() + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mInheritedMask[i] = 0; + } + } + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + node->accept(this); + + + U32 temp[LLViewerCamera::NUM_CAMERAS]; + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + temp[i] = mInheritedMask[i]; + mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED; + } + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mInheritedMask[i] = temp[i]; + } + } + + + virtual void visit(const OctreeNode* state) + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) + { + LL_ERRS() << "Spatial group failed inherited mask test." << LL_ENDL; + } + } + + if (group->hasState(LLSpatialGroup::DIRTY)) + { + assert_parent_state(group, LLSpatialGroup::DIRTY); + } + } + + void assert_parent_state(LLSpatialGroup* group, U32 state) + { + LLSpatialGroup* parent = group->getParent(); + while (parent) + { + if (!parent->hasState(state)) + { + LL_ERRS() << "Spatial group failed parent state check." << LL_ENDL; + } + parent = parent->getParent(); + } + } }; void LLSpatialPartition::renderPhysicsShapes(bool wireframe) { - LLSpatialBridge* bridge = asBridge(); - LLCamera* camera = LLViewerCamera::getInstance(); - - if (bridge) - { - camera = NULL; - } - - gGL.flush(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLOctreeRenderPhysicsShapes render_physics(camera, wireframe); - render_physics.traverse(mOctree); - gGL.flush(); + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = LLViewerCamera::getInstance(); + + if (bridge) + { + camera = NULL; + } + + gGL.flush(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLOctreeRenderPhysicsShapes render_physics(camera, wireframe); + render_physics.traverse(mOctree); + gGL.flush(); } void LLSpatialPartition::renderDebug() { - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | - LLPipeline::RENDER_DEBUG_OCCLUSION | - LLPipeline::RENDER_DEBUG_LIGHTS | - LLPipeline::RENDER_DEBUG_BATCH_SIZE | - LLPipeline::RENDER_DEBUG_UPDATE_TYPE | - LLPipeline::RENDER_DEBUG_BBOXES | - LLPipeline::RENDER_DEBUG_NORMALS | - LLPipeline::RENDER_DEBUG_POINTS | + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | + LLPipeline::RENDER_DEBUG_OCCLUSION | + LLPipeline::RENDER_DEBUG_LIGHTS | + LLPipeline::RENDER_DEBUG_BATCH_SIZE | + LLPipeline::RENDER_DEBUG_UPDATE_TYPE | + LLPipeline::RENDER_DEBUG_BBOXES | + LLPipeline::RENDER_DEBUG_NORMALS | + LLPipeline::RENDER_DEBUG_POINTS | LLPipeline::RENDER_DEBUG_TEXTURE_AREA | - LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | - LLPipeline::RENDER_DEBUG_RAYCAST | - LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | - LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | - LLPipeline::RENDER_DEBUG_AGENT_TARGET | - LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | - LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) - { - return; - } - - gDebugProgram.bind(); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); - sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); - sCurMaxTexPriority = 0.f; - } - - LLGLDisable cullface(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gPipeline.disableLights(); - - LLSpatialBridge* bridge = asBridge(); - LLCamera* camera = LLViewerCamera::getInstance(); - - if (bridge) - { - camera = NULL; - } - - LLOctreeStateCheck checker; - checker.traverse(mOctree); - - LLOctreeRenderNonOccluded render_debug(camera); - render_debug.traverse(mOctree); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - { - LLGLEnable cull(GL_CULL_FACE); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); - - LLGLEnable offset(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(-1.f, -1.f); - - LLOctreeRenderXRay xray(camera); - xray.traverse(mOctree); - - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - } - gDebugProgram.unbind(); + LLPipeline::RENDER_DEBUG_TEXTURE_ANIM | + LLPipeline::RENDER_DEBUG_RAYCAST | + LLPipeline::RENDER_DEBUG_AVATAR_VOLUME | + LLPipeline::RENDER_DEBUG_AVATAR_JOINTS | + LLPipeline::RENDER_DEBUG_AGENT_TARGET | + LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + return; + } + + gDebugProgram.bind(); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); + sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea(); + sCurMaxTexPriority = 0.f; + } + + LLGLDisable cullface(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gPipeline.disableLights(); + + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = LLViewerCamera::getInstance(); + + if (bridge) + { + camera = NULL; + } + + LLOctreeStateCheck checker; + checker.traverse(mOctree); + + LLOctreeRenderNonOccluded render_debug(camera); + render_debug.traverse(mOctree); + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + { + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); + + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(-1.f, -1.f); + + LLOctreeRenderXRay xray(camera); + xray.traverse(mOctree); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + gDebugProgram.unbind(); } void LLSpatialGroup::drawObjectBox(LLColor4 col) { - gGL.diffuseColor4fv(col.mV); - LLVector4a size; - size = mObjectBounds[1]; - size.mul(1.01f); - size.add(LLVector4a(0.001f)); - drawBox(mObjectBounds[0], size); + gGL.diffuseColor4fv(col.mV); + LLVector4a size; + size = mObjectBounds[1]; + size.mul(1.01f); + size.add(LLVector4a(0.001f)); + drawBox(mObjectBounds[0], size); } -bool LLSpatialPartition::isHUDPartition() -{ - return mPartitionType == LLViewerRegion::PARTITION_HUD ; -} +bool LLSpatialPartition::isHUDPartition() +{ + return mPartitionType == LLViewerRegion::PARTITION_HUD ; +} BOOL LLSpatialPartition::isVisible(const LLVector3& v) { - if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f)) - { - return FALSE; - } + if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f)) + { + return FALSE; + } - return TRUE; + return TRUE; } LL_ALIGN_PREFIX(16) class LLOctreeIntersect : public LLOctreeTraveler> { public: - LL_ALIGN_16(LLVector4a mStart); - LL_ALIGN_16(LLVector4a mEnd); - - S32 *mFaceHit; - LLVector4a *mIntersection; - LLVector2 *mTexCoord; - LLVector4a *mNormal; - LLVector4a *mTangent; - LLDrawable* mHit; - BOOL mPickTransparent; - BOOL mPickRigged; + LL_ALIGN_16(LLVector4a mStart); + LL_ALIGN_16(LLVector4a mEnd); + + S32 *mFaceHit; + LLVector4a *mIntersection; + LLVector2 *mTexCoord; + LLVector4a *mNormal; + LLVector4a *mTangent; + LLDrawable* mHit; + BOOL mPickTransparent; + BOOL mPickRigged; BOOL mPickUnselectable; BOOL mPickReflectionProbe; - LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, BOOL pick_reflection_probe, - S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) - : mStart(start), - mEnd(end), - mFaceHit(face_hit), - mIntersection(intersection), - mTexCoord(tex_coord), - mNormal(normal), - mTangent(tangent), - mHit(NULL), - mPickTransparent(pick_transparent), - mPickRigged(pick_rigged), + LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_unselectable, BOOL pick_reflection_probe, + S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + : mStart(start), + mEnd(end), + mFaceHit(face_hit), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mTangent(tangent), + mHit(NULL), + mPickTransparent(pick_transparent), + mPickRigged(pick_rigged), mPickUnselectable(pick_unselectable), mPickReflectionProbe(pick_reflection_probe) - { - } - - virtual void visit(const OctreeNode* branch) - { - for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) - { - check(*i); - } - } - - virtual LLDrawable* check(const OctreeNode* node) - { - node->accept(this); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - const OctreeNode* child = node->getChild(i); - LLVector3 res; - - LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); - - LLVector4a size; - LLVector4a center; - - const LLVector4a* bounds = group->getBounds(); - size = bounds[1]; - center = bounds[0]; - - LLVector4a local_start = mStart; - LLVector4a local_end = mEnd; - - if (group->getSpatialPartition()->isBridge()) - { - LLMatrix4 local_matrix = group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix(); - local_matrix.invert(); - - LLMatrix4a local_matrix4a; - local_matrix4a.loadu(local_matrix); - - local_matrix4a.affineTransform(mStart, local_start); - local_matrix4a.affineTransform(mEnd, local_end); - } - - if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) - { - check(child); - } - } - - return mHit; - } - - virtual bool check(LLViewerOctreeEntry* entry) - { - LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); - - if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) - { - return false; - } - - if (drawable->isSpatialBridge()) - { - LLSpatialPartition *part = drawable->asPartition(); - LLSpatialBridge* bridge = part->asBridge(); - if (bridge && gPipeline.hasRenderType(bridge->mDrawableType)) - { - check(part->mOctree); - } - } - else - { - LLViewerObject* vobj = drawable->getVObj(); + { + } + + virtual void visit(const OctreeNode* branch) + { + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + check(*i); + } + } + + virtual LLDrawable* check(const OctreeNode* node) + { + node->accept(this); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + const OctreeNode* child = node->getChild(i); + LLVector3 res; + + LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); + + LLVector4a size; + LLVector4a center; + + const LLVector4a* bounds = group->getBounds(); + size = bounds[1]; + center = bounds[0]; + + LLVector4a local_start = mStart; + LLVector4a local_end = mEnd; + + if (group->getSpatialPartition()->isBridge()) + { + LLMatrix4 local_matrix = group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix(); + local_matrix.invert(); + + LLMatrix4a local_matrix4a; + local_matrix4a.loadu(local_matrix); + + local_matrix4a.affineTransform(mStart, local_start); + local_matrix4a.affineTransform(mEnd, local_end); + } + + if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) + { + check(child); + } + } + + return mHit; + } + + virtual bool check(LLViewerOctreeEntry* entry) + { + LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); + + if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) + { + return false; + } + + if (drawable->isSpatialBridge()) + { + LLSpatialPartition *part = drawable->asPartition(); + LLSpatialBridge* bridge = part->asBridge(); + if (bridge && gPipeline.hasRenderType(bridge->mDrawableType)) + { + check(part->mOctree); + } + } + else + { + LLViewerObject* vobj = drawable->getVObj(); if (vobj && (!vobj->isReflectionProbe() || mPickReflectionProbe)) - { - if (vobj->getClickAction() == CLICK_ACTION_IGNORE && !LLFloater::isVisible(gFloaterTools)) - { - return false; - } - - LLVector4a intersection; - bool skip_check = false; - if (vobj->isAvatar()) - { - LLVOAvatar* avatar = (LLVOAvatar*) vobj; - if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) - { - LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); - if (hit) - { - mEnd = intersection; - if (mIntersection) - { - *mIntersection = intersection; - } - - mHit = hit->mDrawable; - skip_check = true; - } - - } - } - - if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, + { + if (vobj->getClickAction() == CLICK_ACTION_IGNORE && !LLFloater::isVisible(gFloaterTools)) + { + return false; + } + + LLVector4a intersection; + bool skip_check = false; + if (vobj->isAvatar()) + { + LLVOAvatar* avatar = (LLVOAvatar*) vobj; + if ((mPickRigged) || ((avatar->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) + { + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); + if (hit) + { + mEnd = intersection; + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = hit->mDrawable; + skip_check = true; + } + + } + } + + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, (mPickReflectionProbe && vobj->isReflectionProbe()) ? TRUE : mPickTransparent, // always pick transparent when picking selection probe mPickRigged, mPickUnselectable, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) - { - mEnd = intersection; // shorten ray so we only find CLOSER hits - if (mIntersection) - { - *mIntersection = intersection; - } - - mHit = vobj->mDrawable; - } - } - } - - return false; - } + { + mEnd = intersection; // shorten ray so we only find CLOSER hits + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = vobj->mDrawable; + } + } + } + + return false; + } } LL_ALIGN_POSTFIX(16); LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - BOOL pick_transparent, - BOOL pick_rigged, + BOOL pick_transparent, + BOOL pick_rigged, BOOL pick_unselectable, BOOL pick_reflection_probe, - S32* face_hit, // return the face hit - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) + S32* face_hit, // return the face hit + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) { - LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, intersection, tex_coord, normal, tangent); - LLDrawable* drawable = intersect.check(mOctree); + LLOctreeIntersect intersect(start, end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, intersection, tex_coord, normal, tangent); + LLDrawable* drawable = intersect.check(mOctree); - return drawable; + return drawable; } LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, @@ -3831,7 +3831,7 @@ LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const LLVector4a* intersection, // return the intersection point LLVector2* tex_coord, // return the texture coordinates of the intersection point LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point ) { @@ -3841,32 +3841,32 @@ LLDrawable* LLSpatialGroup::lineSegmentIntersect(const LLVector4a& start, const return drawable; } -LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, - LLViewerTexture* texture, LLVertexBuffer* buffer, - bool fullbright, U8 bump) -: mVertexBuffer(buffer), - mTexture(texture), - mStart(start), - mEnd(end), - mCount(count), - mOffset(offset), - mFullbright(fullbright), - mBump(bump), - mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), - mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), - mHasGlow(false), - mEnvIntensity(0.0f), - mAlphaMaskCutoff(0.5f) -{ - mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); +LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, + LLViewerTexture* texture, LLVertexBuffer* buffer, + bool fullbright, U8 bump) +: mVertexBuffer(buffer), + mTexture(texture), + mStart(start), + mEnd(end), + mCount(count), + mOffset(offset), + mFullbright(fullbright), + mBump(bump), + mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), + mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), + mHasGlow(false), + mEnvIntensity(0.0f), + mAlphaMaskCutoff(0.5f) +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); } -LLDrawInfo::~LLDrawInfo() +LLDrawInfo::~LLDrawInfo() { - if (gDebugGL) - { - gPipeline.checkReferences(this); - } + if (gDebugGL) + { + gPipeline.checkReferences(this); + } } LLColor4U LLDrawInfo::getDebugColor() const @@ -3879,13 +3879,13 @@ LLColor4U LLDrawInfo::getDebugColor() const *((U32*) color.mV) = hash.getCRC(); color.mV[3] = 200; - + return color; } void LLDrawInfo::validate() { - mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); } U64 LLDrawInfo::getSkinHash() @@ -3893,110 +3893,110 @@ U64 LLDrawInfo::getSkinHash() return mSkinInfo ? mSkinInfo->mHash : 0; } -LLCullResult::LLCullResult() +LLCullResult::LLCullResult() { - mVisibleGroupsAllocated = 0; - mAlphaGroupsAllocated = 0; + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; mRiggedAlphaGroupsAllocated = 0; - mOcclusionGroupsAllocated = 0; - mDrawableGroupsAllocated = 0; - mVisibleListAllocated = 0; - mVisibleBridgeAllocated = 0; - - mVisibleGroups.clear(); - mVisibleGroups.push_back(NULL); - mVisibleGroupsEnd = &mVisibleGroups[0]; - mAlphaGroups.clear(); - mAlphaGroups.push_back(NULL); - mAlphaGroupsEnd = &mAlphaGroups[0]; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups.clear(); + mVisibleGroups.push_back(NULL); + mVisibleGroupsEnd = &mVisibleGroups[0]; + mAlphaGroups.clear(); + mAlphaGroups.push_back(NULL); + mAlphaGroupsEnd = &mAlphaGroups[0]; mRiggedAlphaGroups.clear(); mRiggedAlphaGroups.push_back(NULL); mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; - mOcclusionGroups.clear(); - mOcclusionGroups.push_back(NULL); - mOcclusionGroupsEnd = &mOcclusionGroups[0]; - mDrawableGroups.clear(); - mDrawableGroups.push_back(NULL); - mDrawableGroupsEnd = &mDrawableGroups[0]; - mVisibleList.clear(); - mVisibleList.push_back(NULL); - mVisibleListEnd = &mVisibleList[0]; - mVisibleBridge.clear(); - mVisibleBridge.push_back(NULL); - mVisibleBridgeEnd = &mVisibleBridge[0]; - - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - mRenderMap[i].clear(); - mRenderMap[i].push_back(NULL); - mRenderMapEnd[i] = &mRenderMap[i][0]; - mRenderMapAllocated[i] = 0; - } - - clear(); + mOcclusionGroups.clear(); + mOcclusionGroups.push_back(NULL); + mOcclusionGroupsEnd = &mOcclusionGroups[0]; + mDrawableGroups.clear(); + mDrawableGroups.push_back(NULL); + mDrawableGroupsEnd = &mDrawableGroups[0]; + mVisibleList.clear(); + mVisibleList.push_back(NULL); + mVisibleListEnd = &mVisibleList[0]; + mVisibleBridge.clear(); + mVisibleBridge.push_back(NULL); + mVisibleBridgeEnd = &mVisibleBridge[0]; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i].clear(); + mRenderMap[i].push_back(NULL); + mRenderMapEnd[i] = &mRenderMap[i][0]; + mRenderMapAllocated[i] = 0; + } + + clear(); } -template +template void LLCullResult::pushBack(T& head, U32& count, V* val) { - head[count] = val; - head.push_back(NULL); - count++; + head[count] = val; + head.push_back(NULL); + count++; } void LLCullResult::clear() { - mVisibleGroupsSize = 0; - mVisibleGroupsEnd = &mVisibleGroups[0]; + mVisibleGroupsSize = 0; + mVisibleGroupsEnd = &mVisibleGroups[0]; - mAlphaGroupsSize = 0; - mAlphaGroupsEnd = &mAlphaGroups[0]; + mAlphaGroupsSize = 0; + mAlphaGroupsEnd = &mAlphaGroups[0]; mRiggedAlphaGroupsSize = 0; mRiggedAlphaGroupsEnd = &mRiggedAlphaGroups[0]; - mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = &mOcclusionGroups[0]; + mOcclusionGroupsSize = 0; + mOcclusionGroupsEnd = &mOcclusionGroups[0]; - mDrawableGroupsSize = 0; - mDrawableGroupsEnd = &mDrawableGroups[0]; + mDrawableGroupsSize = 0; + mDrawableGroupsEnd = &mDrawableGroups[0]; - mVisibleListSize = 0; - mVisibleListEnd = &mVisibleList[0]; + mVisibleListSize = 0; + mVisibleListEnd = &mVisibleList[0]; - mVisibleBridgeSize = 0; - mVisibleBridgeEnd = &mVisibleBridge[0]; + mVisibleBridgeSize = 0; + mVisibleBridgeEnd = &mVisibleBridge[0]; - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - for (U32 j = 0; j < mRenderMapSize[i]; j++) - { - mRenderMap[i][j] = 0; - } - mRenderMapSize[i] = 0; - mRenderMapEnd[i] = &(mRenderMap[i][0]); - } + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + for (U32 j = 0; j < mRenderMapSize[i]; j++) + { + mRenderMap[i][j] = 0; + } + mRenderMapSize[i] = 0; + mRenderMapEnd[i] = &(mRenderMap[i][0]); + } } LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return &mVisibleGroups[0]; + return &mVisibleGroups[0]; } LLCullResult::sg_iterator LLCullResult::endVisibleGroups() { - return mVisibleGroupsEnd; + return mVisibleGroupsEnd; } LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return &mAlphaGroups[0]; + return &mAlphaGroups[0]; } LLCullResult::sg_iterator LLCullResult::endAlphaGroups() { - return mAlphaGroupsEnd; + return mAlphaGroupsEnd; } LLCullResult::sg_iterator LLCullResult::beginRiggedAlphaGroups() @@ -4011,80 +4011,80 @@ LLCullResult::sg_iterator LLCullResult::endRiggedAlphaGroups() LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return &mOcclusionGroups[0]; + return &mOcclusionGroups[0]; } LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() { - return mOcclusionGroupsEnd; + return mOcclusionGroupsEnd; } LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return &mDrawableGroups[0]; + return &mDrawableGroups[0]; } LLCullResult::sg_iterator LLCullResult::endDrawableGroups() { - return mDrawableGroupsEnd; + return mDrawableGroupsEnd; } LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return &mVisibleList[0]; + return &mVisibleList[0]; } LLCullResult::drawable_iterator LLCullResult::endVisibleList() { - return mVisibleListEnd; + return mVisibleListEnd; } LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return &mVisibleBridge[0]; + return &mVisibleBridge[0]; } LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() { - return mVisibleBridgeEnd; + return mVisibleBridgeEnd; } LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return &mRenderMap[type][0]; + return &mRenderMap[type][0]; } LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) { - return mRenderMapEnd[type]; + return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) { - if (mVisibleGroupsSize < mVisibleGroupsAllocated) - { - mVisibleGroups[mVisibleGroupsSize] = group; - } - else - { - pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); - } - ++mVisibleGroupsSize; - mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; + if (mVisibleGroupsSize < mVisibleGroupsAllocated) + { + mVisibleGroups[mVisibleGroupsSize] = group; + } + else + { + pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); + } + ++mVisibleGroupsSize; + mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) { - if (mAlphaGroupsSize < mAlphaGroupsAllocated) - { - mAlphaGroups[mAlphaGroupsSize] = group; - } - else - { - pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); - } - ++mAlphaGroupsSize; - mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; + if (mAlphaGroupsSize < mAlphaGroupsAllocated) + { + mAlphaGroups[mAlphaGroupsSize] = group; + } + else + { + pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); + } + ++mAlphaGroupsSize; + mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; } void LLCullResult::pushRiggedAlphaGroup(LLSpatialGroup* group) @@ -4103,16 +4103,16 @@ void LLCullResult::pushRiggedAlphaGroup(LLSpatialGroup* group) void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { - if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) - { - mOcclusionGroups[mOcclusionGroupsSize] = group; - } - else - { - pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); - } - ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) + { + mOcclusionGroups[mOcclusionGroupsSize] = group; + } + else + { + pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); + } + ++mOcclusionGroupsSize; + mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) @@ -4121,16 +4121,16 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) // group must NOT be in the drawble groups list already llassert(std::find(&mDrawableGroups[0], mDrawableGroupsEnd, group) == mDrawableGroupsEnd); #endif - if (mDrawableGroupsSize < mDrawableGroupsAllocated) - { - mDrawableGroups[mDrawableGroupsSize] = group; - } - else - { - pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); - } - ++mDrawableGroupsSize; - mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; + if (mDrawableGroupsSize < mDrawableGroupsAllocated) + { + mDrawableGroups[mDrawableGroupsSize] = group; + } + else + { + pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); + } + ++mDrawableGroupsSize; + mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; } void LLCullResult::pushDrawable(LLDrawable* drawable) @@ -4139,56 +4139,56 @@ void LLCullResult::pushDrawable(LLDrawable* drawable) // drawable must NOT be in the visible list already llassert(std::find(&mVisibleList[0], mVisibleListEnd, drawable) == mVisibleListEnd); #endif - if (mVisibleListSize < mVisibleListAllocated) - { - mVisibleList[mVisibleListSize] = drawable; - } - else - { - pushBack(mVisibleList, mVisibleListAllocated, drawable); - } - ++mVisibleListSize; - mVisibleListEnd = &mVisibleList[mVisibleListSize]; + if (mVisibleListSize < mVisibleListAllocated) + { + mVisibleList[mVisibleListSize] = drawable; + } + else + { + pushBack(mVisibleList, mVisibleListAllocated, drawable); + } + ++mVisibleListSize; + mVisibleListEnd = &mVisibleList[mVisibleListSize]; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) { - if (mVisibleBridgeSize < mVisibleBridgeAllocated) - { - mVisibleBridge[mVisibleBridgeSize] = bridge; - } - else - { - pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); - } - ++mVisibleBridgeSize; - mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; + if (mVisibleBridgeSize < mVisibleBridgeAllocated) + { + mVisibleBridge[mVisibleBridgeSize] = bridge; + } + else + { + pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); + } + ++mVisibleBridgeSize; + mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) { - if (mRenderMapSize[type] < mRenderMapAllocated[type]) - { - mRenderMap[type][mRenderMapSize[type]] = draw_info; - } - else - { - pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); - } - ++mRenderMapSize[type]; - mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); + if (mRenderMapSize[type] < mRenderMapAllocated[type]) + { + mRenderMap[type][mRenderMapSize[type]] = draw_info; + } + else + { + pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); + } + ++mRenderMapSize[type]; + mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); } void LLCullResult::assertDrawMapsEmpty() { - for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) - { - if (mRenderMapSize[i] != 0) - { - LL_ERRS() << "Stale LLDrawInfo's in LLCullResult!" - << " (mRenderMapSize[" << i << "] = " << mRenderMapSize[i] << ")" << LL_ENDL; - } - } + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + if (mRenderMapSize[i] != 0) + { + LL_ERRS() << "Stale LLDrawInfo's in LLCullResult!" + << " (mRenderMapSize[" << i << "] = " << mRenderMapSize[i] << ")" << LL_ENDL; + } + } } diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 804afe6266..55ecc7ccc5 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llsurface.cpp * @brief Implementation of LLSurface class * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -66,82 +66,82 @@ S32 LLSurface::sTextureSize = 256; // ---------------- LLSurface:: Public Members --------------- LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) : - mGridsPerEdge(0), - mOOGridsPerEdge(0.f), - mPatchesPerEdge(0), - mNumberOfPatches(0), - mType(type), - mDetailTextureScale(0.f), - mOriginGlobal(0.0, 0.0, 0.0), - mSTexturep(NULL), - mWaterTexturep(NULL), - mGridsPerPatchEdge(0), - mMetersPerGrid(1.0f), - mMetersPerEdge(1.0f), - mRegionp(regionp) + mGridsPerEdge(0), + mOOGridsPerEdge(0.f), + mPatchesPerEdge(0), + mNumberOfPatches(0), + mType(type), + mDetailTextureScale(0.f), + mOriginGlobal(0.0, 0.0, 0.0), + mSTexturep(NULL), + mWaterTexturep(NULL), + mGridsPerPatchEdge(0), + mMetersPerGrid(1.0f), + mMetersPerEdge(1.0f), + mRegionp(regionp) { - // Surface data - mSurfaceZ = NULL; - mNorm = NULL; + // Surface data + mSurfaceZ = NULL; + mNorm = NULL; - // Patch data - mPatchList = NULL; + // Patch data + mPatchList = NULL; - // One of each for each camera - mVisiblePatchCount = 0; + // One of each for each camera + mVisiblePatchCount = 0; - mHasZData = FALSE; - // "uninitialized" min/max z - mMinZ = 10000.f; - mMaxZ = -10000.f; + mHasZData = FALSE; + // "uninitialized" min/max z + mMinZ = 10000.f; + mMaxZ = -10000.f; - mWaterObjp = NULL; + mWaterObjp = NULL; - // In here temporarily. - mSurfacePatchUpdateCount = 0; + // In here temporarily. + mSurfacePatchUpdateCount = 0; - for (S32 i = 0; i < 8; i++) - { - mNeighbors[i] = NULL; - } + for (S32 i = 0; i < 8; i++) + { + mNeighbors[i] = NULL; + } } LLSurface::~LLSurface() { - delete [] mSurfaceZ; - mSurfaceZ = NULL; - - delete [] mNorm; - - mGridsPerEdge = 0; - mGridsPerPatchEdge = 0; - mPatchesPerEdge = 0; - mNumberOfPatches = 0; - destroyPatchData(); - - LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); - if (!poolp) - { - LL_WARNS() << "No pool for terrain on destruction!" << LL_ENDL; - } - else if (poolp->mReferences.empty()) - { - gPipeline.removePool(poolp); - // Don't enable this until we blitz the draw pool for it as well. -- djs - if (mSTexturep) - { - mSTexturep = NULL; - } - if (mWaterTexturep) - { - mWaterTexturep = NULL; - } - } - else - { - LL_ERRS() << "Terrain pool not empty!" << LL_ENDL; - } + delete [] mSurfaceZ; + mSurfaceZ = NULL; + + delete [] mNorm; + + mGridsPerEdge = 0; + mGridsPerPatchEdge = 0; + mPatchesPerEdge = 0; + mNumberOfPatches = 0; + destroyPatchData(); + + LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); + if (!poolp) + { + LL_WARNS() << "No pool for terrain on destruction!" << LL_ENDL; + } + else if (poolp->mReferences.empty()) + { + gPipeline.removePool(poolp); + // Don't enable this until we blitz the draw pool for it as well. -- djs + if (mSTexturep) + { + mSTexturep = NULL; + } + if (mWaterTexturep) + { + mWaterTexturep = NULL; + } + } + else + { + LL_ERRS() << "Terrain pool not empty!" << LL_ENDL; + } } void LLSurface::initClasses() @@ -150,538 +150,538 @@ void LLSurface::initClasses() void LLSurface::setRegion(LLViewerRegion *regionp) { - mRegionp = regionp; - mWaterObjp = NULL; // depends on regionp, needs recreating + mRegionp = regionp; + mWaterObjp = NULL; // depends on regionp, needs recreating } // Assumes that arguments are powers of 2, and that -// grids_per_edge / grids_per_patch_edge = power of 2 +// grids_per_edge / grids_per_patch_edge = power of 2 void LLSurface::create(const S32 grids_per_edge, - const S32 grids_per_patch_edge, - const LLVector3d &origin_global, - const F32 width) + const S32 grids_per_patch_edge, + const LLVector3d &origin_global, + const F32 width) { - // Initialize various constants for the surface - mGridsPerEdge = grids_per_edge + 1; // Add 1 for the east and north buffer - mOOGridsPerEdge = 1.f / mGridsPerEdge; - mGridsPerPatchEdge = grids_per_patch_edge; - mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge; - mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge; - mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1)); - mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1); - - mOriginGlobal.setVec(origin_global); - - mPVArray.create(mGridsPerEdge, mGridsPerPatchEdge, LLWorld::getInstance()->getRegionScale()); - - S32 number_of_grids = mGridsPerEdge * mGridsPerEdge; - - ///////////////////////////////////// - // - // Initialize data arrays for surface - /// - mSurfaceZ = new F32[number_of_grids]; - mNorm = new LLVector3[number_of_grids]; - - // Reset the surface to be a flat square grid - for(S32 i=0; i < number_of_grids; i++) - { - // Surface is flat and zero - // Normals all point up - mSurfaceZ[i] = 0.0f; - mNorm[i].setVec(0.f, 0.f, 1.f); - } + // Initialize various constants for the surface + mGridsPerEdge = grids_per_edge + 1; // Add 1 for the east and north buffer + mOOGridsPerEdge = 1.f / mGridsPerEdge; + mGridsPerPatchEdge = grids_per_patch_edge; + mPatchesPerEdge = (mGridsPerEdge - 1) / mGridsPerPatchEdge; + mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge; + mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1)); + mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1); + + mOriginGlobal.setVec(origin_global); + + mPVArray.create(mGridsPerEdge, mGridsPerPatchEdge, LLWorld::getInstance()->getRegionScale()); + + S32 number_of_grids = mGridsPerEdge * mGridsPerEdge; + + ///////////////////////////////////// + // + // Initialize data arrays for surface + /// + mSurfaceZ = new F32[number_of_grids]; + mNorm = new LLVector3[number_of_grids]; + + // Reset the surface to be a flat square grid + for(S32 i=0; i < number_of_grids; i++) + { + // Surface is flat and zero + // Normals all point up + mSurfaceZ[i] = 0.0f; + mNorm[i].setVec(0.f, 0.f, 1.f); + } - mVisiblePatchCount = 0; + mVisiblePatchCount = 0; - /////////////////////// - // - // Initialize textures - // + /////////////////////// + // + // Initialize textures + // - initTextures(); + initTextures(); - // Has to be done after texture initialization - createPatchData(); + // Has to be done after texture initialization + createPatchData(); } LLViewerTexture* LLSurface::getSTexture() { - if (mSTexturep.notNull() && !mSTexturep->hasGLTexture()) - { - createSTexture(); - } - return mSTexturep; + if (mSTexturep.notNull() && !mSTexturep->hasGLTexture()) + { + createSTexture(); + } + return mSTexturep; } LLViewerTexture* LLSurface::getWaterTexture() { - if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture()) - { - createWaterTexture(); - } - return mWaterTexturep; + if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture()) + { + createWaterTexture(); + } + return mWaterTexturep; } void LLSurface::createSTexture() { - if (!mSTexturep) - { - // Fill with dummy gray data. - // GL NOT ACTIVE HERE - LLPointer raw = new LLImageRaw(sTextureSize, sTextureSize, 3); - U8 *default_texture = raw->getData(); - for (S32 i = 0; i < sTextureSize; i++) - { - for (S32 j = 0; j < sTextureSize; j++) - { - *(default_texture + (i*sTextureSize + j)*3) = 128; - *(default_texture + (i*sTextureSize + j)*3 + 1) = 128; - *(default_texture + (i*sTextureSize + j)*3 + 2) = 128; - } - } - - mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); - mSTexturep->dontDiscard(); - gGL.getTexUnit(0)->bind(mSTexturep); - mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - } + if (!mSTexturep) + { + // Fill with dummy gray data. + // GL NOT ACTIVE HERE + LLPointer raw = new LLImageRaw(sTextureSize, sTextureSize, 3); + U8 *default_texture = raw->getData(); + for (S32 i = 0; i < sTextureSize; i++) + { + for (S32 j = 0; j < sTextureSize; j++) + { + *(default_texture + (i*sTextureSize + j)*3) = 128; + *(default_texture + (i*sTextureSize + j)*3 + 1) = 128; + *(default_texture + (i*sTextureSize + j)*3 + 2) = 128; + } + } + + mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + mSTexturep->dontDiscard(); + gGL.getTexUnit(0)->bind(mSTexturep); + mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + } } void LLSurface::createWaterTexture() { - if (!mWaterTexturep) - { - // Create the water texture - LLPointer raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4); - U8 *default_texture = raw->getData(); - for (S32 i = 0; i < sTextureSize/2; i++) - { - for (S32 j = 0; j < sTextureSize/2; j++) - { - *(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0]; - *(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1]; - *(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2]; - *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3]; - } - } - - mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); - mWaterTexturep->dontDiscard(); - gGL.getTexUnit(0)->bind(mWaterTexturep); - mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - } + if (!mWaterTexturep) + { + // Create the water texture + LLPointer raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4); + U8 *default_texture = raw->getData(); + for (S32 i = 0; i < sTextureSize/2; i++) + { + for (S32 j = 0; j < sTextureSize/2; j++) + { + *(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0]; + *(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1]; + *(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2]; + *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3]; + } + } + + mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); + mWaterTexturep->dontDiscard(); + gGL.getTexUnit(0)->bind(mWaterTexturep); + mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + } } void LLSurface::initTextures() { - /////////////////////// - // - // Main surface texture - // - createSTexture(); - - /////////////////////// - // - // Water texture - // - if (gSavedSettings.getBOOL("RenderWater") ) - { - createWaterTexture(); - mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); - gPipeline.createObject(mWaterObjp); - LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); - water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); // region doesn't have a valid water height yet - mWaterObjp->setPositionGlobal(water_pos_global); - } + /////////////////////// + // + // Main surface texture + // + createSTexture(); + + /////////////////////// + // + // Water texture + // + if (gSavedSettings.getBOOL("RenderWater") ) + { + createWaterTexture(); + mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); + gPipeline.createObject(mWaterObjp); + LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); + water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); // region doesn't have a valid water height yet + mWaterObjp->setPositionGlobal(water_pos_global); + } } -void LLSurface::setOriginGlobal(const LLVector3d &origin_global) +void LLSurface::setOriginGlobal(const LLVector3d &origin_global) { - LLVector3d new_origin_global; - mOriginGlobal = origin_global; - LLSurfacePatch *patchp; - S32 i, j; - // Need to update the southwest corners of the patches - for (j=0; jgetOriginGlobal(); - - new_origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge; - new_origin_global.mdV[1] = mOriginGlobal.mdV[1] + j * mMetersPerGrid * mGridsPerPatchEdge; - patchp->setOriginGlobal(new_origin_global); - } - } - - // Hack! - if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull()) - { - const F64 x = origin_global.mdV[VX] + 128.0; - const F64 y = origin_global.mdV[VY] + 128.0; - const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ]; - - LLVector3d water_origin_global(x, y, z); - - mWaterObjp->setPositionGlobal(water_origin_global); - } + LLVector3d new_origin_global; + mOriginGlobal = origin_global; + LLSurfacePatch *patchp; + S32 i, j; + // Need to update the southwest corners of the patches + for (j=0; jgetOriginGlobal(); + + new_origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge; + new_origin_global.mdV[1] = mOriginGlobal.mdV[1] + j * mMetersPerGrid * mGridsPerPatchEdge; + patchp->setOriginGlobal(new_origin_global); + } + } + + // Hack! + if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull()) + { + const F64 x = origin_global.mdV[VX] + 128.0; + const F64 y = origin_global.mdV[VY] + 128.0; + const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ]; + + LLVector3d water_origin_global(x, y, z); + + mWaterObjp->setPositionGlobal(water_origin_global); + } } void LLSurface::getNeighboringRegions( std::vector& uniqueRegions ) { - S32 i; - for (i = 0; i < 8; i++) - { - if ( mNeighbors[i] != NULL ) - { - uniqueRegions.push_back( mNeighbors[i]->getRegion() ); - } - } + S32 i; + for (i = 0; i < 8; i++) + { + if ( mNeighbors[i] != NULL ) + { + uniqueRegions.push_back( mNeighbors[i]->getRegion() ); + } + } } void LLSurface::getNeighboringRegionsStatus( std::vector& regions ) { - S32 i; - for (i = 0; i < 8; i++) - { - if ( mNeighbors[i] != NULL ) - { - regions.push_back( i ); - } - } + S32 i; + for (i = 0; i < 8; i++) + { + if ( mNeighbors[i] != NULL ) + { + regions.push_back( i ); + } + } } void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction) { - S32 i; - LLSurfacePatch *patchp, *neighbor_patchp; - - mNeighbors[direction] = neighborp; - neighborp->mNeighbors[gDirOpposite[direction]] = this; - - // Connect patches - if (NORTHEAST == direction) - { - patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(0, 0); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); // Only update one of north or east. - patchp->dirtyZ(); - } - else if (NORTHWEST == direction) - { - patchp = getPatch(0, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (SOUTHWEST == direction) - { - patchp = getPatch(0, 0); - neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateNorthEdge(); // Only update one of north or east. - neighbor_patchp->dirtyZ(); - } - else if (SOUTHEAST == direction) - { - patchp = getPatch(mPatchesPerEdge - 1, 0); - neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - } - else if (EAST == direction) - { - // Do east/west connections, first - for (i = 0; i < (S32)mPatchesPerEdge; i++) - { - patchp = getPatch(mPatchesPerEdge - 1, i); - neighbor_patchp = neighborp->getPatch(0, i); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateEastEdge(); - patchp->dirtyZ(); - } - - // Now do northeast/southwest connections - for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - { - patchp = getPatch(mPatchesPerEdge - 1, i); - neighbor_patchp = neighborp->getPatch(0, i+1); - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Now do southeast/northwest connections - for (i = 1; i < (S32)mPatchesPerEdge; i++) - { - patchp = getPatch(mPatchesPerEdge - 1, i); - neighbor_patchp = neighborp->getPatch(0, i-1); - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); - } - } - else if (NORTH == direction) - { - // Do north/south connections, first - for (i = 0; i < (S32)mPatchesPerEdge; i++) - { - patchp = getPatch(i, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i, 0); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - patchp->updateNorthEdge(); - patchp->dirtyZ(); - } - - // Do northeast/southwest connections - for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) - { - patchp = getPatch(i, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i+1, 0); - - patchp->connectNeighbor(neighbor_patchp, NORTHEAST); - neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); - } - // Do southeast/northwest connections - for (i = 1; i < (S32)mPatchesPerEdge; i++) - { - patchp = getPatch(i, mPatchesPerEdge - 1); - neighbor_patchp = neighborp->getPatch(i-1, 0); - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); - } - } - else if (WEST == direction) - { - // Do east/west connections, first - for (i = 0; i < mPatchesPerEdge; i++) - { - patchp = getPatch(0, i); - neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateEastEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections - for (i = 1; i < mPatchesPerEdge; i++) - { - patchp = getPatch(0, i); - neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1); - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - - // Now do northwest/southeast connections - for (i = 0; i < mPatchesPerEdge - 1; i++) - { - patchp = getPatch(0, i); - neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1); - - patchp->connectNeighbor(neighbor_patchp, NORTHWEST); - neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); - } - } - else if (SOUTH == direction) - { - // Do north/south connections, first - for (i = 0; i < mPatchesPerEdge; i++) - { - patchp = getPatch(i, 0); - neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1); - - patchp->connectNeighbor(neighbor_patchp, direction); - neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); - - neighbor_patchp->updateNorthEdge(); - neighbor_patchp->dirtyZ(); - } - - // Now do northeast/southwest connections - for (i = 1; i < mPatchesPerEdge; i++) - { - patchp = getPatch(i, 0); - neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1); - - patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); - neighbor_patchp->connectNeighbor(patchp, NORTHEAST); - } - // Now do northeast/southwest connections - for (i = 0; i < mPatchesPerEdge - 1; i++) - { - patchp = getPatch(i, 0); - neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1); - - patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); - neighbor_patchp->connectNeighbor(patchp, NORTHWEST); - } - } + S32 i; + LLSurfacePatch *patchp, *neighbor_patchp; + + mNeighbors[direction] = neighborp; + neighborp->mNeighbors[gDirOpposite[direction]] = this; + + // Connect patches + if (NORTHEAST == direction) + { + patchp = getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); + neighbor_patchp = neighborp->getPatch(0, 0); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + patchp->updateNorthEdge(); // Only update one of north or east. + patchp->dirtyZ(); + } + else if (NORTHWEST == direction) + { + patchp = getPatch(0, mPatchesPerEdge - 1); + neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, 0); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + } + else if (SOUTHWEST == direction) + { + patchp = getPatch(0, 0); + neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, mPatchesPerEdge - 1); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + neighbor_patchp->updateNorthEdge(); // Only update one of north or east. + neighbor_patchp->dirtyZ(); + } + else if (SOUTHEAST == direction) + { + patchp = getPatch(mPatchesPerEdge - 1, 0); + neighbor_patchp = neighborp->getPatch(0, mPatchesPerEdge - 1); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + } + else if (EAST == direction) + { + // Do east/west connections, first + for (i = 0; i < (S32)mPatchesPerEdge; i++) + { + patchp = getPatch(mPatchesPerEdge - 1, i); + neighbor_patchp = neighborp->getPatch(0, i); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + patchp->updateEastEdge(); + patchp->dirtyZ(); + } + + // Now do northeast/southwest connections + for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) + { + patchp = getPatch(mPatchesPerEdge - 1, i); + neighbor_patchp = neighborp->getPatch(0, i+1); + + patchp->connectNeighbor(neighbor_patchp, NORTHEAST); + neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); + } + // Now do southeast/northwest connections + for (i = 1; i < (S32)mPatchesPerEdge; i++) + { + patchp = getPatch(mPatchesPerEdge - 1, i); + neighbor_patchp = neighborp->getPatch(0, i-1); + + patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); + neighbor_patchp->connectNeighbor(patchp, NORTHWEST); + } + } + else if (NORTH == direction) + { + // Do north/south connections, first + for (i = 0; i < (S32)mPatchesPerEdge; i++) + { + patchp = getPatch(i, mPatchesPerEdge - 1); + neighbor_patchp = neighborp->getPatch(i, 0); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + patchp->updateNorthEdge(); + patchp->dirtyZ(); + } + + // Do northeast/southwest connections + for (i = 0; i < (S32)mPatchesPerEdge - 1; i++) + { + patchp = getPatch(i, mPatchesPerEdge - 1); + neighbor_patchp = neighborp->getPatch(i+1, 0); + + patchp->connectNeighbor(neighbor_patchp, NORTHEAST); + neighbor_patchp->connectNeighbor(patchp, SOUTHWEST); + } + // Do southeast/northwest connections + for (i = 1; i < (S32)mPatchesPerEdge; i++) + { + patchp = getPatch(i, mPatchesPerEdge - 1); + neighbor_patchp = neighborp->getPatch(i-1, 0); + + patchp->connectNeighbor(neighbor_patchp, NORTHWEST); + neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); + } + } + else if (WEST == direction) + { + // Do east/west connections, first + for (i = 0; i < mPatchesPerEdge; i++) + { + patchp = getPatch(0, i); + neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + neighbor_patchp->updateEastEdge(); + neighbor_patchp->dirtyZ(); + } + + // Now do northeast/southwest connections + for (i = 1; i < mPatchesPerEdge; i++) + { + patchp = getPatch(0, i); + neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i - 1); + + patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); + neighbor_patchp->connectNeighbor(patchp, NORTHEAST); + } + + // Now do northwest/southeast connections + for (i = 0; i < mPatchesPerEdge - 1; i++) + { + patchp = getPatch(0, i); + neighbor_patchp = neighborp->getPatch(mPatchesPerEdge - 1, i + 1); + + patchp->connectNeighbor(neighbor_patchp, NORTHWEST); + neighbor_patchp->connectNeighbor(patchp, SOUTHEAST); + } + } + else if (SOUTH == direction) + { + // Do north/south connections, first + for (i = 0; i < mPatchesPerEdge; i++) + { + patchp = getPatch(i, 0); + neighbor_patchp = neighborp->getPatch(i, mPatchesPerEdge - 1); + + patchp->connectNeighbor(neighbor_patchp, direction); + neighbor_patchp->connectNeighbor(patchp, gDirOpposite[direction]); + + neighbor_patchp->updateNorthEdge(); + neighbor_patchp->dirtyZ(); + } + + // Now do northeast/southwest connections + for (i = 1; i < mPatchesPerEdge; i++) + { + patchp = getPatch(i, 0); + neighbor_patchp = neighborp->getPatch(i - 1, mPatchesPerEdge - 1); + + patchp->connectNeighbor(neighbor_patchp, SOUTHWEST); + neighbor_patchp->connectNeighbor(patchp, NORTHEAST); + } + // Now do northeast/southwest connections + for (i = 0; i < mPatchesPerEdge - 1; i++) + { + patchp = getPatch(i, 0); + neighbor_patchp = neighborp->getPatch(i + 1, mPatchesPerEdge - 1); + + patchp->connectNeighbor(neighbor_patchp, SOUTHEAST); + neighbor_patchp->connectNeighbor(patchp, NORTHWEST); + } + } } void LLSurface::disconnectNeighbor(LLSurface *surfacep) { - S32 i; - for (i = 0; i < 8; i++) - { - if (surfacep == mNeighbors[i]) - { - mNeighbors[i] = NULL; - } - } - - // Iterate through surface patches, removing any connectivity to removed surface. - for (i = 0; i < mNumberOfPatches; i++) - { - (mPatchList + i)->disconnectNeighbor(surfacep); - } + S32 i; + for (i = 0; i < 8; i++) + { + if (surfacep == mNeighbors[i]) + { + mNeighbors[i] = NULL; + } + } + + // Iterate through surface patches, removing any connectivity to removed surface. + for (i = 0; i < mNumberOfPatches; i++) + { + (mPatchList + i)->disconnectNeighbor(surfacep); + } } void LLSurface::disconnectAllNeighbors() { - S32 i; - for (i = 0; i < 8; i++) - { - if (mNeighbors[i]) - { - mNeighbors[i]->disconnectNeighbor(this); - mNeighbors[i] = NULL; - } - } + S32 i; + for (i = 0; i < 8; i++) + { + if (mNeighbors[i]) + { + mNeighbors[i]->disconnectNeighbor(this); + mNeighbors[i] = NULL; + } + } } const LLVector3d &LLSurface::getOriginGlobal() const { - return mOriginGlobal; + return mOriginGlobal; } LLVector3 LLSurface::getOriginAgent() const { - return gAgent.getPosAgentFromGlobal(mOriginGlobal); + return gAgent.getPosAgentFromGlobal(mOriginGlobal); } F32 LLSurface::getMetersPerGrid() const { - return mMetersPerGrid; + return mMetersPerGrid; } S32 LLSurface::getGridsPerEdge() const { - return mGridsPerEdge; + return mGridsPerEdge; } S32 LLSurface::getPatchesPerEdge() const { - return mPatchesPerEdge; + return mPatchesPerEdge; } S32 LLSurface::getGridsPerPatchEdge() const { - return mGridsPerPatchEdge; + return mGridsPerPatchEdge; } void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta) { - llassert(x >= 0); - llassert(y >= 0); - llassert(x < mGridsPerEdge); - llassert(y < mGridsPerEdge); - mSurfaceZ[x + y*mGridsPerEdge] += delta; + llassert(x >= 0); + llassert(y >= 0); + llassert(x < mGridsPerEdge); + llassert(y < mGridsPerEdge); + mSurfaceZ[x + y*mGridsPerEdge] += delta; } -void LLSurface::updatePatchVisibilities(LLAgent &agent) +void LLSurface::updatePatchVisibilities(LLAgent &agent) { - if (gShiftFrame) - { - return; - } - - LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); - - LLSurfacePatch *patchp; - - mVisiblePatchCount = 0; - for (S32 i=0; iupdateVisibility(); - if (patchp->getVisible()) - { - mVisiblePatchCount++; - patchp->updateCameraDistanceRegion(pos_region); - } - } + if (gShiftFrame) + { + return; + } + + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); + + LLSurfacePatch *patchp; + + mVisiblePatchCount = 0; + for (S32 i=0; iupdateVisibility(); + if (patchp->getVisible()) + { + mVisiblePatchCount++; + patchp->updateCameraDistanceRegion(pos_region); + } + } } template bool LLSurface::idleUpdate(F32 max_update_time) { - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) - { - return false; - } - - // Perform idle time update of non-critical stuff. - // In this case, texture and normal updates. - LLTimer update_timer; - bool did_update = false; - - // If the Z height data has changed, we need to rebuild our - // property line vertex arrays. - if (mDirtyPatchList.size() > 0) - { - getRegion()->dirtyHeights(); - } - - // Always call updateNormals() / updateVerticalStats() - // every frame to avoid artifacts - for(std::set::iterator iter = mDirtyPatchList.begin(); - iter != mDirtyPatchList.end(); ) - { - std::set::iterator curiter = iter++; - LLSurfacePatch *patchp = *curiter; - patchp->updateNormals(); - patchp->updateVerticalStats(); - if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) - { - if (patchp->updateTexture()) - { - did_update = true; - patchp->clearDirty(); - mDirtyPatchList.erase(curiter); - } - } - } + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) + { + return false; + } + + // Perform idle time update of non-critical stuff. + // In this case, texture and normal updates. + LLTimer update_timer; + bool did_update = false; + + // If the Z height data has changed, we need to rebuild our + // property line vertex arrays. + if (mDirtyPatchList.size() > 0) + { + getRegion()->dirtyHeights(); + } + + // Always call updateNormals() / updateVerticalStats() + // every frame to avoid artifacts + for(std::set::iterator iter = mDirtyPatchList.begin(); + iter != mDirtyPatchList.end(); ) + { + std::set::iterator curiter = iter++; + LLSurfacePatch *patchp = *curiter; + patchp->updateNormals(); + patchp->updateVerticalStats(); + if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) + { + if (patchp->updateTexture()) + { + did_update = true; + patchp->clearDirty(); + mDirtyPatchList.erase(curiter); + } + } + } if (did_update) { @@ -689,76 +689,76 @@ bool LLSurface::idleUpdate(F32 max_update_time) mRegionp->updateReflectionProbes(); } - return did_update; + return did_update; } template bool LLSurface::idleUpdate(F32 max_update_time); template bool LLSurface::idleUpdate(F32 max_update_time); -void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch) +void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch) { - LLPatchHeader ph; - S32 j, i; - S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE]; - LLSurfacePatch *patchp; - - init_patch_decompressor(gopp->patch_size); - gopp->stride = mGridsPerEdge; - set_group_of_patch_header(gopp); - - while (1) - { - decode_patch_header(bitpack, &ph); - if (ph.quant_wbits == END_OF_PATCHES) - { - break; - } - - i = ph.patchids >> 5; - j = ph.patchids & 0x1F; - - if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge)) - { - LL_WARNS() << "Received invalid terrain packet - patch header patch ID incorrect!" - << " patches per edge " << mPatchesPerEdge - << " i " << i - << " j " << j - << " dc_offset " << ph.dc_offset - << " range " << (S32)ph.range - << " quant_wbits " << (S32)ph.quant_wbits - << " patchids " << (S32)ph.patchids - << LL_ENDL; - return; - } - - patchp = &mPatchList[j*mPatchesPerEdge + i]; - - - decode_patch(bitpack, patch); - decompress_patch(patchp->getDataZ(), patch, &ph); - - // Update edges for neighbors. Need to guarantee that this gets done before we generate vertical stats. - patchp->updateNorthEdge(); - patchp->updateEastEdge(); - if (patchp->getNeighborPatch(WEST)) - { - patchp->getNeighborPatch(WEST)->updateEastEdge(); - } - if (patchp->getNeighborPatch(SOUTHWEST)) - { - patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge(); - patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge(); - } - if (patchp->getNeighborPatch(SOUTH)) - { - patchp->getNeighborPatch(SOUTH)->updateNorthEdge(); - } - - // Dirty patch statistics, and flag that the patch has data. - patchp->dirtyZ(); - patchp->setHasReceivedData(); - } + LLPatchHeader ph; + S32 j, i; + S32 patch[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE]; + LLSurfacePatch *patchp; + + init_patch_decompressor(gopp->patch_size); + gopp->stride = mGridsPerEdge; + set_group_of_patch_header(gopp); + + while (1) + { + decode_patch_header(bitpack, &ph); + if (ph.quant_wbits == END_OF_PATCHES) + { + break; + } + + i = ph.patchids >> 5; + j = ph.patchids & 0x1F; + + if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge)) + { + LL_WARNS() << "Received invalid terrain packet - patch header patch ID incorrect!" + << " patches per edge " << mPatchesPerEdge + << " i " << i + << " j " << j + << " dc_offset " << ph.dc_offset + << " range " << (S32)ph.range + << " quant_wbits " << (S32)ph.quant_wbits + << " patchids " << (S32)ph.patchids + << LL_ENDL; + return; + } + + patchp = &mPatchList[j*mPatchesPerEdge + i]; + + + decode_patch(bitpack, patch); + decompress_patch(patchp->getDataZ(), patch, &ph); + + // Update edges for neighbors. Need to guarantee that this gets done before we generate vertical stats. + patchp->updateNorthEdge(); + patchp->updateEastEdge(); + if (patchp->getNeighborPatch(WEST)) + { + patchp->getNeighborPatch(WEST)->updateEastEdge(); + } + if (patchp->getNeighborPatch(SOUTHWEST)) + { + patchp->getNeighborPatch(SOUTHWEST)->updateEastEdge(); + patchp->getNeighborPatch(SOUTHWEST)->updateNorthEdge(); + } + if (patchp->getNeighborPatch(SOUTH)) + { + patchp->getNeighborPatch(SOUTH)->updateNorthEdge(); + } + + // Dirty patch statistics, and flag that the patch has data. + patchp->dirtyZ(); + patchp->setHasReceivedData(); + } } @@ -766,157 +766,157 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL // "position" is region-local BOOL LLSurface::containsPosition(const LLVector3 &position) { - if (position.mV[VX] < 0.0f || position.mV[VX] > mMetersPerEdge || - position.mV[VY] < 0.0f || position.mV[VY] > mMetersPerEdge) - { - return FALSE; - } - return TRUE; + if (position.mV[VX] < 0.0f || position.mV[VX] > mMetersPerEdge || + position.mV[VY] < 0.0f || position.mV[VY] > mMetersPerEdge) + { + return FALSE; + } + return TRUE; } F32 LLSurface::resolveHeightRegion(const F32 x, const F32 y) const { - F32 height = 0.0f; - F32 oometerspergrid = 1.f/mMetersPerGrid; - - // Check to see if v is actually above surface - // We use (mGridsPerEdge-1) below rather than (mGridsPerEdge) - // becuase of the east and north buffers - - if (x >= 0.f && - x <= mMetersPerEdge && - y >= 0.f && - y <= mMetersPerEdge) - { - const S32 left = llfloor(x * oometerspergrid); - const S32 bottom = llfloor(y * oometerspergrid); - - // Don't walk off the edge of the array! - const S32 right = ( left+1 < (S32)mGridsPerEdge-1 ? left+1 : left ); - const S32 top = ( bottom+1 < (S32)mGridsPerEdge-1 ? bottom+1 : bottom ); - - // Figure out if v is in first or second triangle of the square - // and calculate the slopes accordingly - // | | - // -(i,j+1)---(i+1,j+1)-- - // | 1 / | ^ - // | / 2 | | - // | / | j - // --(i,j)----(i+1,j)-- - // | | - // - // i -> - // where N = mGridsPerEdge - - const F32 left_bottom = getZ( left, bottom ); - const F32 right_bottom = getZ( right, bottom ); - const F32 left_top = getZ( left, top ); - const F32 right_top = getZ( right, top ); - - // dx and dy are incremental steps from (mSurface + k) - F32 dx = x - left * mMetersPerGrid; - F32 dy = y - bottom * mMetersPerGrid; - - if (dy > dx) - { - // triangle 1 - dy *= left_top - left_bottom; - dx *= right_top - left_top; - } - else - { - // triangle 2 - dx *= right_bottom - left_bottom; - dy *= right_top - right_bottom; - } - height = left_bottom + (dx + dy) * oometerspergrid; - } - return height; + F32 height = 0.0f; + F32 oometerspergrid = 1.f/mMetersPerGrid; + + // Check to see if v is actually above surface + // We use (mGridsPerEdge-1) below rather than (mGridsPerEdge) + // becuase of the east and north buffers + + if (x >= 0.f && + x <= mMetersPerEdge && + y >= 0.f && + y <= mMetersPerEdge) + { + const S32 left = llfloor(x * oometerspergrid); + const S32 bottom = llfloor(y * oometerspergrid); + + // Don't walk off the edge of the array! + const S32 right = ( left+1 < (S32)mGridsPerEdge-1 ? left+1 : left ); + const S32 top = ( bottom+1 < (S32)mGridsPerEdge-1 ? bottom+1 : bottom ); + + // Figure out if v is in first or second triangle of the square + // and calculate the slopes accordingly + // | | + // -(i,j+1)---(i+1,j+1)-- + // | 1 / | ^ + // | / 2 | | + // | / | j + // --(i,j)----(i+1,j)-- + // | | + // + // i -> + // where N = mGridsPerEdge + + const F32 left_bottom = getZ( left, bottom ); + const F32 right_bottom = getZ( right, bottom ); + const F32 left_top = getZ( left, top ); + const F32 right_top = getZ( right, top ); + + // dx and dy are incremental steps from (mSurface + k) + F32 dx = x - left * mMetersPerGrid; + F32 dy = y - bottom * mMetersPerGrid; + + if (dy > dx) + { + // triangle 1 + dy *= left_top - left_bottom; + dx *= right_top - left_top; + } + else + { + // triangle 2 + dx *= right_bottom - left_bottom; + dy *= right_top - right_bottom; + } + height = left_bottom + (dx + dy) * oometerspergrid; + } + return height; } F32 LLSurface::resolveHeightGlobal(const LLVector3d& v) const { - if (!mRegionp) - { - return 0.f; - } - - LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(v); - - return resolveHeightRegion(pos_region); + if (!mRegionp) + { + return 0.f; + } + + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(v); + + return resolveHeightRegion(pos_region); } LLVector3 LLSurface::resolveNormalGlobal(const LLVector3d& pos_global) const { - if (!mSurfaceZ) - { - // Hmm. Uninitialized surface! - return LLVector3::z_axis; - } - // - // Returns the vector normal to a surface at location specified by vector v - // - F32 oometerspergrid = 1.f/mMetersPerGrid; - LLVector3 normal; - F32 dzx, dzy; - - if (pos_global.mdV[VX] >= mOriginGlobal.mdV[VX] && - pos_global.mdV[VX] < mOriginGlobal.mdV[VX] + mMetersPerEdge && - pos_global.mdV[VY] >= mOriginGlobal.mdV[VY] && - pos_global.mdV[VY] < mOriginGlobal.mdV[VY] + mMetersPerEdge) - { - U32 i, j, k; - F32 dx, dy; - i = (U32) ((pos_global.mdV[VX] - mOriginGlobal.mdV[VX]) * oometerspergrid); - j = (U32) ((pos_global.mdV[VY] - mOriginGlobal.mdV[VY]) * oometerspergrid ); - k = i + j*mGridsPerEdge; - - // Figure out if v is in first or second triangle of the square - // and calculate the slopes accordingly - // | | - // -(k+N)---(k+1+N)-- - // | 1 / | ^ - // | / 2 | | - // | / | j - // --(k)----(k+1)-- - // | | - // - // i -> - // where N = mGridsPerEdge - - // dx and dy are incremental steps from (mSurface + k) - dx = (F32)(pos_global.mdV[VX] - i*mMetersPerGrid - mOriginGlobal.mdV[VX]); - dy = (F32)(pos_global.mdV[VY] - j*mMetersPerGrid - mOriginGlobal.mdV[VY]); - if (dy > dx) - { // triangle 1 - dzx = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + mGridsPerEdge); - dzy = *(mSurfaceZ + k) - *(mSurfaceZ + k + mGridsPerEdge); - normal.setVec(-dzx,dzy,1); - } - else - { // triangle 2 - dzx = *(mSurfaceZ + k) - *(mSurfaceZ + k + 1); - dzy = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + 1); - normal.setVec(dzx,-dzy,1); - } - } - normal.normVec(); - return normal; + if (!mSurfaceZ) + { + // Hmm. Uninitialized surface! + return LLVector3::z_axis; + } + // + // Returns the vector normal to a surface at location specified by vector v + // + F32 oometerspergrid = 1.f/mMetersPerGrid; + LLVector3 normal; + F32 dzx, dzy; + + if (pos_global.mdV[VX] >= mOriginGlobal.mdV[VX] && + pos_global.mdV[VX] < mOriginGlobal.mdV[VX] + mMetersPerEdge && + pos_global.mdV[VY] >= mOriginGlobal.mdV[VY] && + pos_global.mdV[VY] < mOriginGlobal.mdV[VY] + mMetersPerEdge) + { + U32 i, j, k; + F32 dx, dy; + i = (U32) ((pos_global.mdV[VX] - mOriginGlobal.mdV[VX]) * oometerspergrid); + j = (U32) ((pos_global.mdV[VY] - mOriginGlobal.mdV[VY]) * oometerspergrid ); + k = i + j*mGridsPerEdge; + + // Figure out if v is in first or second triangle of the square + // and calculate the slopes accordingly + // | | + // -(k+N)---(k+1+N)-- + // | 1 / | ^ + // | / 2 | | + // | / | j + // --(k)----(k+1)-- + // | | + // + // i -> + // where N = mGridsPerEdge + + // dx and dy are incremental steps from (mSurface + k) + dx = (F32)(pos_global.mdV[VX] - i*mMetersPerGrid - mOriginGlobal.mdV[VX]); + dy = (F32)(pos_global.mdV[VY] - j*mMetersPerGrid - mOriginGlobal.mdV[VY]); + if (dy > dx) + { // triangle 1 + dzx = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + mGridsPerEdge); + dzy = *(mSurfaceZ + k) - *(mSurfaceZ + k + mGridsPerEdge); + normal.setVec(-dzx,dzy,1); + } + else + { // triangle 2 + dzx = *(mSurfaceZ + k) - *(mSurfaceZ + k + 1); + dzy = *(mSurfaceZ + k + 1 + mGridsPerEdge) - *(mSurfaceZ + k + 1); + normal.setVec(dzx,-dzy,1); + } + } + normal.normVec(); + return normal; } LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const { -// x and y should be region-local coordinates. +// x and y should be region-local coordinates. // If x and y are outside of the surface, then the returned // index will be for the nearest boundary patch. // // 12 | 13| 14| 15 -// | | | +// | | | // +---+---+---+---+ // | 12| 13| 14| 15| // ----+---+---+---+---+----- @@ -926,393 +926,393 @@ LLSurfacePatch *LLSurface::resolvePatchRegion(const F32 x, const F32 y) const // ----+---+---+---+---+----- // | 0 | 1 | 2 | 3 | // +---+---+---+---+ -// | | | +// | | | // 0 | 1 | 2 | 3 // // When x and y are not region-local do the following first - S32 i, j; - if (x < 0.0f) - { - i = 0; - } - else if (x >= mMetersPerEdge) - { - i = mPatchesPerEdge - 1; - } - else - { - i = (U32) (x / (mMetersPerGrid * mGridsPerPatchEdge)); - } - - if (y < 0.0f) - { - j = 0; - } - else if (y >= mMetersPerEdge) - { - j = mPatchesPerEdge - 1; - } - else - { - j = (U32) (y / (mMetersPerGrid * mGridsPerPatchEdge)); - } - - // *NOTE: Super paranoia code follows. - S32 index = i + j * mPatchesPerEdge; - if((index < 0) || (index >= mNumberOfPatches)) - { - if(0 == mNumberOfPatches) - { - LL_WARNS() << "No patches for current region!" << LL_ENDL; - return NULL; - } - S32 old_index = index; - index = llclamp(old_index, 0, (mNumberOfPatches - 1)); - LL_WARNS() << "Clamping out of range patch index " << old_index - << " to " << index << LL_ENDL; - } - return &(mPatchList[index]); + S32 i, j; + if (x < 0.0f) + { + i = 0; + } + else if (x >= mMetersPerEdge) + { + i = mPatchesPerEdge - 1; + } + else + { + i = (U32) (x / (mMetersPerGrid * mGridsPerPatchEdge)); + } + + if (y < 0.0f) + { + j = 0; + } + else if (y >= mMetersPerEdge) + { + j = mPatchesPerEdge - 1; + } + else + { + j = (U32) (y / (mMetersPerGrid * mGridsPerPatchEdge)); + } + + // *NOTE: Super paranoia code follows. + S32 index = i + j * mPatchesPerEdge; + if((index < 0) || (index >= mNumberOfPatches)) + { + if(0 == mNumberOfPatches) + { + LL_WARNS() << "No patches for current region!" << LL_ENDL; + return NULL; + } + S32 old_index = index; + index = llclamp(old_index, 0, (mNumberOfPatches - 1)); + LL_WARNS() << "Clamping out of range patch index " << old_index + << " to " << index << LL_ENDL; + } + return &(mPatchList[index]); } LLSurfacePatch *LLSurface::resolvePatchRegion(const LLVector3 &pos_region) const { - return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]); + return resolvePatchRegion(pos_region.mV[VX], pos_region.mV[VY]); } LLSurfacePatch *LLSurface::resolvePatchGlobal(const LLVector3d &pos_global) const { - llassert(mRegionp); - LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global); - return resolvePatchRegion(pos_region); + llassert(mRegionp); + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(pos_global); + return resolvePatchRegion(pos_region); } -std::ostream& operator<<(std::ostream &s, const LLSurface &S) +std::ostream& operator<<(std::ostream &s, const LLSurface &S) { - s << "{ \n"; - s << " mGridsPerEdge = " << S.mGridsPerEdge - 1 << " + 1\n"; - s << " mGridsPerPatchEdge = " << S.mGridsPerPatchEdge << "\n"; - s << " mPatchesPerEdge = " << S.mPatchesPerEdge << "\n"; - s << " mOriginGlobal = " << S.mOriginGlobal << "\n"; - s << " mMetersPerGrid = " << S.mMetersPerGrid << "\n"; - s << " mVisiblePatchCount = " << S.mVisiblePatchCount << "\n"; - s << "}"; - return s; + s << "{ \n"; + s << " mGridsPerEdge = " << S.mGridsPerEdge - 1 << " + 1\n"; + s << " mGridsPerPatchEdge = " << S.mGridsPerPatchEdge << "\n"; + s << " mPatchesPerEdge = " << S.mPatchesPerEdge << "\n"; + s << " mOriginGlobal = " << S.mOriginGlobal << "\n"; + s << " mMetersPerGrid = " << S.mMetersPerGrid << "\n"; + s << " mVisiblePatchCount = " << S.mVisiblePatchCount << "\n"; + s << "}"; + return s; } // ---------------- LLSurface:: Protected ---------------- -void LLSurface::createPatchData() +void LLSurface::createPatchData() { - // Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set - // TODO -- check for create() called when surface is not empty - S32 i, j; - LLSurfacePatch *patchp; - - // Allocate memory - mPatchList = new LLSurfacePatch[mNumberOfPatches]; - - // One of each for each camera - mVisiblePatchCount = mNumberOfPatches; - - for (j=0; jsetSurface(this); - } - } - - for (j=0; jmHasReceivedData = FALSE; - patchp->mSTexUpdate = TRUE; - - S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge; - - patchp->setDataZ(mSurfaceZ + data_offset); - patchp->setDataNorm(mNorm + data_offset); - - - // We make each patch point to its neighbors so we can do resolution checking - // when butting up different resolutions. Patches that don't have neighbors - // somewhere will point to NULL on that side. - if (i < mPatchesPerEdge-1) - { - patchp->setNeighborPatch(EAST,getPatch(i+1, j)); - } - else - { - patchp->setNeighborPatch(EAST, NULL); - } - - if (j < mPatchesPerEdge-1) - { - patchp->setNeighborPatch(NORTH, getPatch(i, j+1)); - } - else - { - patchp->setNeighborPatch(NORTH, NULL); - } - - if (i > 0) - { - patchp->setNeighborPatch(WEST, getPatch(i - 1, j)); - } - else - { - patchp->setNeighborPatch(WEST, NULL); - } - - if (j > 0) - { - patchp->setNeighborPatch(SOUTH, getPatch(i, j-1)); - } - else - { - patchp->setNeighborPatch(SOUTH, NULL); - } - - if (i < (mPatchesPerEdge-1) && j < (mPatchesPerEdge-1)) - { - patchp->setNeighborPatch(NORTHEAST, getPatch(i + 1, j + 1)); - } - else - { - patchp->setNeighborPatch(NORTHEAST, NULL); - } - - if (i > 0 && j < (mPatchesPerEdge-1)) - { - patchp->setNeighborPatch(NORTHWEST, getPatch(i - 1, j + 1)); - } - else - { - patchp->setNeighborPatch(NORTHWEST, NULL); - } - - if (i > 0 && j > 0) - { - patchp->setNeighborPatch(SOUTHWEST, getPatch(i - 1, j - 1)); - } - else - { - patchp->setNeighborPatch(SOUTHWEST, NULL); - } - - if (i < (mPatchesPerEdge-1) && j > 0) - { - patchp->setNeighborPatch(SOUTHEAST, getPatch(i + 1, j - 1)); - } - else - { - patchp->setNeighborPatch(SOUTHEAST, NULL); - } - - LLVector3d origin_global; - origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge; - origin_global.mdV[1] = mOriginGlobal.mdV[0] + j * mMetersPerGrid * mGridsPerPatchEdge; - origin_global.mdV[2] = 0.f; - patchp->setOriginGlobal(origin_global); - } - } + // Assumes mGridsPerEdge, mGridsPerPatchEdge, and mPatchesPerEdge have been properly set + // TODO -- check for create() called when surface is not empty + S32 i, j; + LLSurfacePatch *patchp; + + // Allocate memory + mPatchList = new LLSurfacePatch[mNumberOfPatches]; + + // One of each for each camera + mVisiblePatchCount = mNumberOfPatches; + + for (j=0; jsetSurface(this); + } + } + + for (j=0; jmHasReceivedData = FALSE; + patchp->mSTexUpdate = TRUE; + + S32 data_offset = i * mGridsPerPatchEdge + j * mGridsPerPatchEdge * mGridsPerEdge; + + patchp->setDataZ(mSurfaceZ + data_offset); + patchp->setDataNorm(mNorm + data_offset); + + + // We make each patch point to its neighbors so we can do resolution checking + // when butting up different resolutions. Patches that don't have neighbors + // somewhere will point to NULL on that side. + if (i < mPatchesPerEdge-1) + { + patchp->setNeighborPatch(EAST,getPatch(i+1, j)); + } + else + { + patchp->setNeighborPatch(EAST, NULL); + } + + if (j < mPatchesPerEdge-1) + { + patchp->setNeighborPatch(NORTH, getPatch(i, j+1)); + } + else + { + patchp->setNeighborPatch(NORTH, NULL); + } + + if (i > 0) + { + patchp->setNeighborPatch(WEST, getPatch(i - 1, j)); + } + else + { + patchp->setNeighborPatch(WEST, NULL); + } + + if (j > 0) + { + patchp->setNeighborPatch(SOUTH, getPatch(i, j-1)); + } + else + { + patchp->setNeighborPatch(SOUTH, NULL); + } + + if (i < (mPatchesPerEdge-1) && j < (mPatchesPerEdge-1)) + { + patchp->setNeighborPatch(NORTHEAST, getPatch(i + 1, j + 1)); + } + else + { + patchp->setNeighborPatch(NORTHEAST, NULL); + } + + if (i > 0 && j < (mPatchesPerEdge-1)) + { + patchp->setNeighborPatch(NORTHWEST, getPatch(i - 1, j + 1)); + } + else + { + patchp->setNeighborPatch(NORTHWEST, NULL); + } + + if (i > 0 && j > 0) + { + patchp->setNeighborPatch(SOUTHWEST, getPatch(i - 1, j - 1)); + } + else + { + patchp->setNeighborPatch(SOUTHWEST, NULL); + } + + if (i < (mPatchesPerEdge-1) && j > 0) + { + patchp->setNeighborPatch(SOUTHEAST, getPatch(i + 1, j - 1)); + } + else + { + patchp->setNeighborPatch(SOUTHEAST, NULL); + } + + LLVector3d origin_global; + origin_global.mdV[0] = mOriginGlobal.mdV[0] + i * mMetersPerGrid * mGridsPerPatchEdge; + origin_global.mdV[1] = mOriginGlobal.mdV[0] + j * mMetersPerGrid * mGridsPerPatchEdge; + origin_global.mdV[2] = 0.f; + patchp->setOriginGlobal(origin_global); + } + } } void LLSurface::destroyPatchData() { - // Delete all of the cached patch data for these patches. + // Delete all of the cached patch data for these patches. - delete [] mPatchList; - mPatchList = NULL; - mVisiblePatchCount = 0; + delete [] mPatchList; + mPatchList = NULL; + mVisiblePatchCount = 0; } void LLSurface::setTextureSize(const S32 texture_size) { - sTextureSize = texture_size; + sTextureSize = texture_size; } U32 LLSurface::getRenderLevel(const U32 render_stride) const { - return mPVArray.mRenderLevelp[render_stride]; + return mPVArray.mRenderLevelp[render_stride]; } U32 LLSurface::getRenderStride(const U32 render_level) const { - return mPVArray.mRenderStridep[render_level]; + return mPVArray.mRenderStridep[render_level]; } LLSurfacePatch *LLSurface::getPatch(const S32 x, const S32 y) const { - if ((x < 0) || (x >= mPatchesPerEdge)) - { - LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; - } - if ((y < 0) || (y >= mPatchesPerEdge)) - { - LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL; - return NULL; - } - - return mPatchList + x + y*mPatchesPerEdge; + if ((x < 0) || (x >= mPatchesPerEdge)) + { + LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL; + return NULL; + } + if ((y < 0) || (y >= mPatchesPerEdge)) + { + LL_ERRS() << "Asking for patch out of bounds" << LL_ENDL; + return NULL; + } + + return mPatchList + x + y*mPatchesPerEdge; } void LLSurface::dirtyAllPatches() { - S32 i; - for (i = 0; i < mNumberOfPatches; i++) - { - mPatchList[i].dirtyZ(); - } + S32 i; + for (i = 0; i < mNumberOfPatches; i++) + { + mPatchList[i].dirtyZ(); + } } void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp) { - // Put surface patch on dirty surface patch list - mDirtyPatchList.insert(patchp); + // Put surface patch on dirty surface patch list + mDirtyPatchList.insert(patchp); } void LLSurface::setWaterHeight(F32 height) { - if (!mWaterObjp.isNull()) - { - LLVector3 water_pos_region = mWaterObjp->getPositionRegion(); - bool changed = water_pos_region.mV[VZ] != height; - water_pos_region.mV[VZ] = height; - mWaterObjp->setPositionRegion(water_pos_region); - if (changed) - { - LLWorld::getInstance()->updateWaterObjects(); - } - } - else - { - LL_WARNS() << "LLSurface::setWaterHeight with no water object!" << LL_ENDL; - } + if (!mWaterObjp.isNull()) + { + LLVector3 water_pos_region = mWaterObjp->getPositionRegion(); + bool changed = water_pos_region.mV[VZ] != height; + water_pos_region.mV[VZ] = height; + mWaterObjp->setPositionRegion(water_pos_region); + if (changed) + { + LLWorld::getInstance()->updateWaterObjects(); + } + } + else + { + LL_WARNS() << "LLSurface::setWaterHeight with no water object!" << LL_ENDL; + } } F32 LLSurface::getWaterHeight() const { - if (!mWaterObjp.isNull()) - { - // we have a water object, the usual case - return mWaterObjp->getPositionRegion().mV[VZ]; - } - else - { - return DEFAULT_WATER_HEIGHT; - } + if (!mWaterObjp.isNull()) + { + // we have a water object, the usual case + return mWaterObjp->getPositionRegion().mV[VZ]; + } + else + { + return DEFAULT_WATER_HEIGHT; + } } BOOL LLSurface::generateWaterTexture(const F32 x, const F32 y, - const F32 width, const F32 height) + const F32 width, const F32 height) { - LL_PROFILE_ZONE_SCOPED - if (!getWaterTexture()) - { - return FALSE; - } - - S32 tex_width = mWaterTexturep->getWidth(); - S32 tex_height = mWaterTexturep->getHeight(); - S32 tex_comps = mWaterTexturep->getComponents(); - S32 tex_stride = tex_width * tex_comps; - LLPointer raw = new LLImageRaw(tex_width, tex_height, tex_comps); - U8 *rawp = raw->getData(); - - F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width; - F32 scale_inv = 1.f / scale; - - S32 x_begin, y_begin, x_end, y_end; - - x_begin = ll_round(x * scale_inv); - y_begin = ll_round(y * scale_inv); - x_end = ll_round((x + width) * scale_inv); - y_end = ll_round((y + width) * scale_inv); - - if (x_end > tex_width) - { - x_end = tex_width; - } - if (y_end > tex_width) - { - y_end = tex_width; - } - - // OK, for now, just have the composition value equal the height at the point. - LLVector3 location; - LLColor4U coloru; - - const F32 WATER_HEIGHT = getWaterHeight(); - - S32 i, j, offset; - for (j = y_begin; j < y_end; j++) - { - for (i = x_begin; i < x_end; i++) - { - //F32 nv[2]; - //nv[0] = i/256.f; - //nv[1] = j/256.f; - // const S32 modulation = noise2(nv)*40; - offset = j*tex_stride + i*tex_comps; - location.mV[VX] = i*scale; - location.mV[VY] = j*scale; - - // Sample multiple points - const F32 height = resolveHeightRegion(location); - - if (height > WATER_HEIGHT) - { - // Above water... - coloru = MAX_WATER_COLOR; - coloru.mV[3] = ABOVE_WATERLINE_ALPHA; - *(rawp + offset++) = coloru.mV[0]; - *(rawp + offset++) = coloru.mV[1]; - *(rawp + offset++) = coloru.mV[2]; - *(rawp + offset++) = coloru.mV[3]; - } - else - { - // Want non-linear curve for transparency gradient - coloru = MAX_WATER_COLOR; - const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT)); - S32 alpha = 64 + ll_round((255-64)*frac); - - alpha = llmin(ll_round((F32)MAX_WATER_COLOR.mV[3]), alpha); - alpha = llmax(64, alpha); - - coloru.mV[3] = alpha; - *(rawp + offset++) = coloru.mV[0]; - *(rawp + offset++) = coloru.mV[1]; - *(rawp + offset++) = coloru.mV[2]; - *(rawp + offset++) = coloru.mV[3]; - } - } - } - - if (!mWaterTexturep->hasGLTexture()) - { - mWaterTexturep->createGLTexture(0, raw); - } - - mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin); - return TRUE; + LL_PROFILE_ZONE_SCOPED + if (!getWaterTexture()) + { + return FALSE; + } + + S32 tex_width = mWaterTexturep->getWidth(); + S32 tex_height = mWaterTexturep->getHeight(); + S32 tex_comps = mWaterTexturep->getComponents(); + S32 tex_stride = tex_width * tex_comps; + LLPointer raw = new LLImageRaw(tex_width, tex_height, tex_comps); + U8 *rawp = raw->getData(); + + F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width; + F32 scale_inv = 1.f / scale; + + S32 x_begin, y_begin, x_end, y_end; + + x_begin = ll_round(x * scale_inv); + y_begin = ll_round(y * scale_inv); + x_end = ll_round((x + width) * scale_inv); + y_end = ll_round((y + width) * scale_inv); + + if (x_end > tex_width) + { + x_end = tex_width; + } + if (y_end > tex_width) + { + y_end = tex_width; + } + + // OK, for now, just have the composition value equal the height at the point. + LLVector3 location; + LLColor4U coloru; + + const F32 WATER_HEIGHT = getWaterHeight(); + + S32 i, j, offset; + for (j = y_begin; j < y_end; j++) + { + for (i = x_begin; i < x_end; i++) + { + //F32 nv[2]; + //nv[0] = i/256.f; + //nv[1] = j/256.f; + // const S32 modulation = noise2(nv)*40; + offset = j*tex_stride + i*tex_comps; + location.mV[VX] = i*scale; + location.mV[VY] = j*scale; + + // Sample multiple points + const F32 height = resolveHeightRegion(location); + + if (height > WATER_HEIGHT) + { + // Above water... + coloru = MAX_WATER_COLOR; + coloru.mV[3] = ABOVE_WATERLINE_ALPHA; + *(rawp + offset++) = coloru.mV[0]; + *(rawp + offset++) = coloru.mV[1]; + *(rawp + offset++) = coloru.mV[2]; + *(rawp + offset++) = coloru.mV[3]; + } + else + { + // Want non-linear curve for transparency gradient + coloru = MAX_WATER_COLOR; + const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT)); + S32 alpha = 64 + ll_round((255-64)*frac); + + alpha = llmin(ll_round((F32)MAX_WATER_COLOR.mV[3]), alpha); + alpha = llmax(64, alpha); + + coloru.mV[3] = alpha; + *(rawp + offset++) = coloru.mV[0]; + *(rawp + offset++) = coloru.mV[1]; + *(rawp + offset++) = coloru.mV[2]; + *(rawp + offset++) = coloru.mV[3]; + } + } + } + + if (!mWaterTexturep->hasGLTexture()) + { + mWaterTexturep->createGLTexture(0, raw); + } + + mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin); + return TRUE; } diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index b7b47d2a1c..093b141271 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -1,25 +1,25 @@ -/** +/** * @file llsurface.h * @brief Description of LLSurface class * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -52,9 +52,9 @@ static const U8 NORTH_EDGE = 0x02; static const U8 WEST_EDGE = 0x04; static const U8 SOUTH_EDGE = 0x08; -static const S32 ONE_MORE_THAN_NEIGHBOR = 1; -static const S32 EQUAL_TO_NEIGHBOR = 0; -static const S32 ONE_LESS_THAN_NEIGHBOR = -1; +static const S32 ONE_MORE_THAN_NEIGHBOR = 1; +static const S32 EQUAL_TO_NEIGHBOR = 0; +static const S32 ONE_LESS_THAN_NEIGHBOR = -1; const S32 ABOVE_WATERLINE_ALPHA = 32; // The alpha of water when the land elevation is above the waterline. @@ -63,166 +63,166 @@ class LLSurfacePatch; class LLBitPack; class LLGroupHeader; -class LLSurface +class LLSurface { public: - LLSurface(U32 type, LLViewerRegion *regionp = NULL); - virtual ~LLSurface(); + LLSurface(U32 type, LLViewerRegion *regionp = NULL); + virtual ~LLSurface(); - static void initClasses(); // Do class initialization for LLSurface and its child classes. + static void initClasses(); // Do class initialization for LLSurface and its child classes. - void create(const S32 surface_grid_width, - const S32 surface_patch_width, - const LLVector3d &origin_global, - const F32 width); // Allocates and initializes surface + void create(const S32 surface_grid_width, + const S32 surface_patch_width, + const LLVector3d &origin_global, + const F32 width); // Allocates and initializes surface - void setRegion(LLViewerRegion *regionp); + void setRegion(LLViewerRegion *regionp); - void setOriginGlobal(const LLVector3d &origin_global); + void setOriginGlobal(const LLVector3d &origin_global); - void connectNeighbor(LLSurface *neighborp, U32 direction); - void disconnectNeighbor(LLSurface *neighborp); - void disconnectAllNeighbors(); + void connectNeighbor(LLSurface *neighborp, U32 direction); + void disconnectNeighbor(LLSurface *neighborp); + void disconnectAllNeighbors(); - virtual void decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch); - virtual void updatePatchVisibilities(LLAgent &agent); + virtual void decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL b_large_patch); + virtual void updatePatchVisibilities(LLAgent &agent); - inline F32 getZ(const U32 k) const { return mSurfaceZ[k]; } - inline F32 getZ(const S32 i, const S32 j) const { return mSurfaceZ[i + j*mGridsPerEdge]; } + inline F32 getZ(const U32 k) const { return mSurfaceZ[k]; } + inline F32 getZ(const S32 i, const S32 j) const { return mSurfaceZ[i + j*mGridsPerEdge]; } - LLVector3 getOriginAgent() const; - const LLVector3d &getOriginGlobal() const; - F32 getMetersPerGrid() const; - S32 getGridsPerEdge() const; - S32 getPatchesPerEdge() const; - S32 getGridsPerPatchEdge() const; - U32 getRenderStride(const U32 render_level) const; - U32 getRenderLevel(const U32 render_stride) const; + LLVector3 getOriginAgent() const; + const LLVector3d &getOriginGlobal() const; + F32 getMetersPerGrid() const; + S32 getGridsPerEdge() const; + S32 getPatchesPerEdge() const; + S32 getGridsPerPatchEdge() const; + U32 getRenderStride(const U32 render_level) const; + U32 getRenderLevel(const U32 render_stride) const; - // Returns the height of the surface immediately above (or below) location, - // or if location is not above surface returns zero. - F32 resolveHeightRegion(const F32 x, const F32 y) const; - F32 resolveHeightRegion(const LLVector3 &location) const - { return resolveHeightRegion( location.mV[VX], location.mV[VY] ); } - F32 resolveHeightGlobal(const LLVector3d &position_global) const; - LLVector3 resolveNormalGlobal(const LLVector3d& v) const; // Returns normal to surface + // Returns the height of the surface immediately above (or below) location, + // or if location is not above surface returns zero. + F32 resolveHeightRegion(const F32 x, const F32 y) const; + F32 resolveHeightRegion(const LLVector3 &location) const + { return resolveHeightRegion( location.mV[VX], location.mV[VY] ); } + F32 resolveHeightGlobal(const LLVector3d &position_global) const; + LLVector3 resolveNormalGlobal(const LLVector3d& v) const; // Returns normal to surface - LLSurfacePatch *resolvePatchRegion(const F32 x, const F32 y) const; - LLSurfacePatch *resolvePatchRegion(const LLVector3 &position_region) const; - LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; + LLSurfacePatch *resolvePatchRegion(const F32 x, const F32 y) const; + LLSurfacePatch *resolvePatchRegion(const LLVector3 &position_region) const; + LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; - // Update methods (called during idle, normally) + // Update methods (called during idle, normally) template - bool idleUpdate(F32 max_update_time); + bool idleUpdate(F32 max_update_time); + + BOOL containsPosition(const LLVector3 &position); - BOOL containsPosition(const LLVector3 &position); + void moveZ(const S32 x, const S32 y, const F32 delta); - void moveZ(const S32 x, const S32 y, const F32 delta); + LLViewerRegion *getRegion() const { return mRegionp; } - LLViewerRegion *getRegion() const { return mRegionp; } + F32 getMinZ() const { return mMinZ; } + F32 getMaxZ() const { return mMaxZ; } - F32 getMinZ() const { return mMinZ; } - F32 getMaxZ() const { return mMaxZ; } + void setWaterHeight(F32 height); + F32 getWaterHeight() const; - void setWaterHeight(F32 height); - F32 getWaterHeight() const; + LLViewerTexture *getSTexture(); + LLViewerTexture *getWaterTexture(); + BOOL hasZData() const { return mHasZData; } - LLViewerTexture *getSTexture(); - LLViewerTexture *getWaterTexture(); - BOOL hasZData() const { return mHasZData; } + void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters - void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters + void dirtySurfacePatch(LLSurfacePatch *patchp); + LLVOWater *getWaterObj() { return mWaterObjp; } - void dirtySurfacePatch(LLSurfacePatch *patchp); - LLVOWater *getWaterObj() { return mWaterObjp; } + static void setTextureSize(const S32 texture_size); - static void setTextureSize(const S32 texture_size); + friend class LLSurfacePatch; + friend std::ostream& operator<<(std::ostream &s, const LLSurface &S); + + void getNeighboringRegions( std::vector& uniqueRegions ); + void getNeighboringRegionsStatus( std::vector& regions ); - friend class LLSurfacePatch; - friend std::ostream& operator<<(std::ostream &s, const LLSurface &S); - - void getNeighboringRegions( std::vector& uniqueRegions ); - void getNeighboringRegionsStatus( std::vector& regions ); - public: - // Number of grid points on one side of a region, including +1 buffer for - // north and east edge. - S32 mGridsPerEdge; + // Number of grid points on one side of a region, including +1 buffer for + // north and east edge. + S32 mGridsPerEdge; + + F32 mOOGridsPerEdge; // Inverse of grids per edge - F32 mOOGridsPerEdge; // Inverse of grids per edge + S32 mPatchesPerEdge; // Number of patches on one side of a region + S32 mNumberOfPatches; // Total number of patches - S32 mPatchesPerEdge; // Number of patches on one side of a region - S32 mNumberOfPatches; // Total number of patches + // Each surface points at 8 neighbors (or NULL) + // +---+---+---+ + // |NW | N | NE| + // +---+---+---+ + // | W | 0 | E | + // +---+---+---+ + // |SW | S | SE| + // +---+---+---+ + LLSurface *mNeighbors[8]; // Adjacent patches - // Each surface points at 8 neighbors (or NULL) - // +---+---+---+ - // |NW | N | NE| - // +---+---+---+ - // | W | 0 | E | - // +---+---+---+ - // |SW | S | SE| - // +---+---+---+ - LLSurface *mNeighbors[8]; // Adjacent patches + U32 mType; // Useful for identifying derived classes - U32 mType; // Useful for identifying derived classes - - F32 mDetailTextureScale; // Number of times to repeat detail texture across this surface + F32 mDetailTextureScale; // Number of times to repeat detail texture across this surface protected: - void createSTexture(); - void createWaterTexture(); - void initTextures(); - void initWater(); + void createSTexture(); + void createWaterTexture(); + void initTextures(); + void initWater(); - void createPatchData(); // Allocates memory for patches. - void destroyPatchData(); // Deallocates memory for patches. + void createPatchData(); // Allocates memory for patches. + void destroyPatchData(); // Deallocates memory for patches. - BOOL generateWaterTexture(const F32 x, const F32 y, - const F32 width, const F32 height); // Generate texture from composition values. + BOOL generateWaterTexture(const F32 x, const F32 y, + const F32 width, const F32 height); // Generate texture from composition values. - //F32 updateTexture(LLSurfacePatch *ppatch); - - LLSurfacePatch *getPatch(const S32 x, const S32 y) const; + //F32 updateTexture(LLSurfacePatch *ppatch); + + LLSurfacePatch *getPatch(const S32 x, const S32 y) const; protected: - LLVector3d mOriginGlobal; // In absolute frame - LLSurfacePatch *mPatchList; // Array of all patches + LLVector3d mOriginGlobal; // In absolute frame + LLSurfacePatch *mPatchList; // Array of all patches - // Array of grid data, mGridsPerEdge * mGridsPerEdge - F32 *mSurfaceZ; + // Array of grid data, mGridsPerEdge * mGridsPerEdge + F32 *mSurfaceZ; - // Array of grid normals, mGridsPerEdge * mGridsPerEdge - LLVector3 *mNorm; + // Array of grid normals, mGridsPerEdge * mGridsPerEdge + LLVector3 *mNorm; - std::set mDirtyPatchList; + std::set mDirtyPatchList; - // The textures should never be directly initialized - use the setter methods! - LLPointer mSTexturep; // Texture for surface - LLPointer mWaterTexturep; // Water texture + // The textures should never be directly initialized - use the setter methods! + LLPointer mSTexturep; // Texture for surface + LLPointer mWaterTexturep; // Water texture - LLPointer mWaterObjp; + LLPointer mWaterObjp; - // When we want multiple cameras we'll need one of each these for each camera - S32 mVisiblePatchCount; + // When we want multiple cameras we'll need one of each these for each camera + S32 mVisiblePatchCount; - U32 mGridsPerPatchEdge; // Number of grid points on a side of a patch - F32 mMetersPerGrid; // Converts (i,j) indecies to distance - F32 mMetersPerEdge; // = mMetersPerGrid * (mGridsPerEdge-1) + U32 mGridsPerPatchEdge; // Number of grid points on a side of a patch + F32 mMetersPerGrid; // Converts (i,j) indecies to distance + F32 mMetersPerEdge; // = mMetersPerGrid * (mGridsPerEdge-1) - LLPatchVertexArray mPVArray; + LLPatchVertexArray mPVArray; - BOOL mHasZData; // We've received any patch data for this surface. - F32 mMinZ; // min z for this region (during the session) - F32 mMaxZ; // max z for this region (during the session) + BOOL mHasZData; // We've received any patch data for this surface. + F32 mMinZ; // min z for this region (during the session) + F32 mMaxZ; // max z for this region (during the session) - S32 mSurfacePatchUpdateCount; // Number of frames since last update. + S32 mSurfacePatchUpdateCount; // Number of frames since last update. private: - LLViewerRegion *mRegionp; // Patch whose coordinate system this surface is using. - static S32 sTextureSize; // Size of the surface texture + LLViewerRegion *mRegionp; // Patch whose coordinate system this surface is using. + static S32 sTextureSize; // Size of the surface texture }; extern template bool LLSurface::idleUpdate(F32 max_update_time); @@ -232,33 +232,33 @@ extern template bool LLSurface::idleUpdate(F32 max_update_time); // . __. // Z /|\ /| Y North -// | / +// | / // | / |<----------------- mGridsPerSurfaceEdge --------------->| // | / __________________________________________________________ // |/______\ X /_______________________________________________________ / -// / / / / / / / /M*M-2 /M*M-1 / / -// /______/______/______/______/______/______/______/______/ / -// / / / / / / / / / / -// /______/______/______/______/______/______/______/______/ / -// / / / / / / / / / / -// /______/______/______/______/______/______/______/______/ / -// West / / / / / / / / / / +// / / / / / / / /M*M-2 /M*M-1 / / +// /______/______/______/______/______/______/______/______/ / +// / / / / / / / / / / +// /______/______/______/______/______/______/______/______/ / +// / / / / / / / / / / +// /______/______/______/______/______/______/______/______/ / +// West / / / / / / / / / / // /______/______/______/______/______/______/______/______/ / East -// /... / / / / / / / / / -// /______/______/______/______/______/______/______/______/ / -// _. / 2M / / / / / / / / / -// /| /______/______/______/______/______/______/______/______/ / -// / / M / M+1 / M+2 / ... / / / / 2M-1 / / -// j /______/______/______/______/______/______/______/______/ / -// / 0 / 1 / 2 / ... / / / / M-1 / / -// /______/______/______/______/______/______/______/______/_/ +// /... / / / / / / / / / +// /______/______/______/______/______/______/______/______/ / +// _. / 2M / / / / / / / / / +// /| /______/______/______/______/______/______/______/______/ / +// / / M / M+1 / M+2 / ... / / / / 2M-1 / / +// j /______/______/______/______/______/______/______/______/ / +// / 0 / 1 / 2 / ... / / / / M-1 / / +// /______/______/______/______/______/______/______/______/_/ // South |<-L->| // i --> // // where M = mSurfPatchWidth // and L = mPatchGridWidth -// +// // Notice that mGridsPerSurfaceEdge = a power of two + 1 -// This provides a buffer on the east and north edges that will allow us to +// This provides a buffer on the east and north edges that will allow us to // fill the cracks between adjacent surfaces when rendering. #endif diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 92b1273041..b26d48b07f 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llsurfacepatch.cpp * @brief LLSurfacePatch class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -46,198 +46,198 @@ extern bool gShiftFrame; extern U64MicrosecondsImplicit gFrameTime; extern LLPipeline gPipeline; -LLSurfacePatch::LLSurfacePatch() -: mHasReceivedData(FALSE), - mSTexUpdate(FALSE), - mDirty(FALSE), - mDirtyZStats(TRUE), - mHeightsGenerated(FALSE), - mDataOffset(0), - mDataZ(NULL), - mDataNorm(NULL), - mVObjp(NULL), - mOriginRegion(0.f, 0.f, 0.f), - mCenterRegion(0.f, 0.f, 0.f), - mMinZ(0.f), - mMaxZ(0.f), - mMeanZ(0.f), - mRadius(0.f), - mMinComposition(0.f), - mMaxComposition(0.f), - mMeanComposition(0.f), - // This flag is used to communicate between adjacent surfaces and is - // set to non-zero values by higher classes. - mConnectedEdge(NO_EDGE), - mLastUpdateTime(0), - mSurfacep(NULL) -{ - S32 i; - for (i = 0; i < 8; i++) - { - setNeighborPatch(i, NULL); - } - for (i = 0; i < 9; i++) - { - mNormalsInvalid[i] = TRUE; - } +LLSurfacePatch::LLSurfacePatch() +: mHasReceivedData(FALSE), + mSTexUpdate(FALSE), + mDirty(FALSE), + mDirtyZStats(TRUE), + mHeightsGenerated(FALSE), + mDataOffset(0), + mDataZ(NULL), + mDataNorm(NULL), + mVObjp(NULL), + mOriginRegion(0.f, 0.f, 0.f), + mCenterRegion(0.f, 0.f, 0.f), + mMinZ(0.f), + mMaxZ(0.f), + mMeanZ(0.f), + mRadius(0.f), + mMinComposition(0.f), + mMaxComposition(0.f), + mMeanComposition(0.f), + // This flag is used to communicate between adjacent surfaces and is + // set to non-zero values by higher classes. + mConnectedEdge(NO_EDGE), + mLastUpdateTime(0), + mSurfacep(NULL) +{ + S32 i; + for (i = 0; i < 8; i++) + { + setNeighborPatch(i, NULL); + } + for (i = 0; i < 9; i++) + { + mNormalsInvalid[i] = TRUE; + } } LLSurfacePatch::~LLSurfacePatch() { - mVObjp = NULL; + mVObjp = NULL; } void LLSurfacePatch::dirty() { - // These are outside of the loop in case we're still waiting for a dirty from the - // texture being updated... - if (mVObjp) - { - mVObjp->dirtyGeom(); - } - else - { - LL_WARNS("Terrain") << "No viewer object for this surface patch!" << LL_ENDL; - } - - mDirtyZStats = TRUE; - mHeightsGenerated = FALSE; - - if (!mDirty) - { - mDirty = TRUE; - mSurfacep->dirtySurfacePatch(this); - } + // These are outside of the loop in case we're still waiting for a dirty from the + // texture being updated... + if (mVObjp) + { + mVObjp->dirtyGeom(); + } + else + { + LL_WARNS("Terrain") << "No viewer object for this surface patch!" << LL_ENDL; + } + + mDirtyZStats = TRUE; + mHeightsGenerated = FALSE; + + if (!mDirty) + { + mDirty = TRUE; + mSurfacep->dirtySurfacePatch(this); + } } void LLSurfacePatch::setSurface(LLSurface *surfacep) { - mSurfacep = surfacep; - if (mVObjp == (LLVOSurfacePatch *)NULL) - { - llassert(mSurfacep->mType == 'l'); - - mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion()); - mVObjp->setPatch(this); - mVObjp->setPositionRegion(mCenterRegion); - gPipeline.createObject(mVObjp); - } -} + mSurfacep = surfacep; + if (mVObjp == (LLVOSurfacePatch *)NULL) + { + llassert(mSurfacep->mType == 'l'); + + mVObjp = (LLVOSurfacePatch *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SURFACE_PATCH, mSurfacep->getRegion()); + mVObjp->setPatch(this); + mVObjp->setPositionRegion(mCenterRegion); + gPipeline.createObject(mVObjp); + } +} void LLSurfacePatch::disconnectNeighbor(LLSurface *surfacep) { - U32 i; - for (i = 0; i < 8; i++) - { - if (getNeighborPatch(i)) - { - if (getNeighborPatch(i)->mSurfacep == surfacep) - { - setNeighborPatch(i, NULL); - mNormalsInvalid[i] = TRUE; - } - } - } - - // Clean up connected edges - if (getNeighborPatch(EAST)) - { - if (getNeighborPatch(EAST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~EAST_EDGE; - } - } - if (getNeighborPatch(NORTH)) - { - if (getNeighborPatch(NORTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~NORTH_EDGE; - } - } - if (getNeighborPatch(WEST)) - { - if (getNeighborPatch(WEST)->mSurfacep == surfacep) - { - mConnectedEdge &= ~WEST_EDGE; - } - } - if (getNeighborPatch(SOUTH)) - { - if (getNeighborPatch(SOUTH)->mSurfacep == surfacep) - { - mConnectedEdge &= ~SOUTH_EDGE; - } - } + U32 i; + for (i = 0; i < 8; i++) + { + if (getNeighborPatch(i)) + { + if (getNeighborPatch(i)->mSurfacep == surfacep) + { + setNeighborPatch(i, NULL); + mNormalsInvalid[i] = TRUE; + } + } + } + + // Clean up connected edges + if (getNeighborPatch(EAST)) + { + if (getNeighborPatch(EAST)->mSurfacep == surfacep) + { + mConnectedEdge &= ~EAST_EDGE; + } + } + if (getNeighborPatch(NORTH)) + { + if (getNeighborPatch(NORTH)->mSurfacep == surfacep) + { + mConnectedEdge &= ~NORTH_EDGE; + } + } + if (getNeighborPatch(WEST)) + { + if (getNeighborPatch(WEST)->mSurfacep == surfacep) + { + mConnectedEdge &= ~WEST_EDGE; + } + } + if (getNeighborPatch(SOUTH)) + { + if (getNeighborPatch(SOUTH)->mSurfacep == surfacep) + { + mConnectedEdge &= ~SOUTH_EDGE; + } + } } LLVector3 LLSurfacePatch::getPointAgent(const U32 x, const U32 y) const { - U32 surface_stride = mSurfacep->getGridsPerEdge(); - U32 point_offset = x + y*surface_stride; - LLVector3 pos; - pos = getOriginAgent(); - pos.mV[VX] += x * mSurfacep->getMetersPerGrid(); - pos.mV[VY] += y * mSurfacep->getMetersPerGrid(); - pos.mV[VZ] = *(mDataZ + point_offset); - return pos; + U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 point_offset = x + y*surface_stride; + LLVector3 pos; + pos = getOriginAgent(); + pos.mV[VX] += x * mSurfacep->getMetersPerGrid(); + pos.mV[VY] += y * mSurfacep->getMetersPerGrid(); + pos.mV[VZ] = *(mDataZ + point_offset); + return pos; } LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const { - U32 surface_stride = mSurfacep->getGridsPerEdge(); - U32 point_offset = x + y*surface_stride; - LLVector3 pos, rel_pos; - pos = getOriginAgent(); - pos.mV[VX] += x * mSurfacep->getMetersPerGrid(); - pos.mV[VY] += y * mSurfacep->getMetersPerGrid(); - pos.mV[VZ] = *(mDataZ + point_offset); - rel_pos = pos - mSurfacep->getOriginAgent(); - rel_pos *= 1.f/surface_stride; - return LLVector2(rel_pos.mV[VX], rel_pos.mV[VY]); + U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 point_offset = x + y*surface_stride; + LLVector3 pos, rel_pos; + pos = getOriginAgent(); + pos.mV[VX] += x * mSurfacep->getMetersPerGrid(); + pos.mV[VY] += y * mSurfacep->getMetersPerGrid(); + pos.mV[VZ] = *(mDataZ + point_offset); + rel_pos = pos - mSurfacep->getOriginAgent(); + rel_pos *= 1.f/surface_stride; + return LLVector2(rel_pos.mV[VX], rel_pos.mV[VY]); } void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal, - LLVector2 *tex0, LLVector2 *tex1) + LLVector2 *tex0, LLVector2 *tex1) { - if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp) - { - return; // failsafe - } - llassert_always(vertex && normal && tex0 && tex1); - - U32 surface_stride = mSurfacep->getGridsPerEdge(); - U32 point_offset = x + y*surface_stride; - - *normal = getNormal(x, y); - - LLVector3 pos_agent = getOriginAgent(); - pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); - pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); - pos_agent.mV[VZ] = *(mDataZ + point_offset); - *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); - - LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); - // *NOTE: Only PBR terrain uses the UVs right now. Texture terrain just ignores it. + if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp) + { + return; // failsafe + } + llassert_always(vertex && normal && tex0 && tex1); + + U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 point_offset = x + y*surface_stride; + + *normal = getNormal(x, y); + + LLVector3 pos_agent = getOriginAgent(); + pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); + pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); + pos_agent.mV[VZ] = *(mDataZ + point_offset); + *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); + + LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); + // *NOTE: Only PBR terrain uses the UVs right now. Texture terrain just ignores it. // *NOTE: In the future, UVs and horizontal position will no longer have a 1:1 relationship for PBR terrain - LLVector3 tex_pos = rel_pos; - tex0->mV[0] = tex_pos.mV[0]; - tex0->mV[1] = tex_pos.mV[1]; - tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y); + LLVector3 tex_pos = rel_pos; + tex0->mV[0] = tex_pos.mV[0]; + tex0->mV[1] = tex_pos.mV[1]; + tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y); - const F32 xyScale = 4.9215f*7.f; //0.93284f; - const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f); + const F32 xyScale = 4.9215f*7.f; //0.93284f; + const F32 xyScaleInv = (1.f / xyScale)*(0.2222222222f); - F32 vec[3] = { + F32 vec[3] = { (F32)fmod((F32)(mOriginGlobal.mdV[0] + x)*xyScaleInv, 256.f), (F32)fmod((F32)(mOriginGlobal.mdV[1] + y)*xyScaleInv, 256.f), - 0.f - }; - F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f); - tex1->mV[1] = rand_val; + 0.f + }; + F32 rand_val = llclamp(noise2(vec)* 0.75f + 0.5f, 0.f, 1.f); + tex1->mV[1] = rand_val; } @@ -246,126 +246,126 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 template<> void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) { - U32 patch_width = mSurfacep->mPVArray.mPatchWidth; - U32 surface_stride = mSurfacep->getGridsPerEdge(); - - const F32 mpg = mSurfacep->getMetersPerGrid() * stride; - - S32 poffsets[2][2][2]; - poffsets[0][0][0] = x - stride; - poffsets[0][0][1] = y - stride; - - poffsets[0][1][0] = x - stride; - poffsets[0][1][1] = y + stride; - - poffsets[1][0][0] = x + stride; - poffsets[1][0][1] = y - stride; - - poffsets[1][1][0] = x + stride; - poffsets[1][1][1] = y + stride; - - const LLSurfacePatch *ppatches[2][2]; - - // LLVector3 p1, p2, p3, p4; - - ppatches[0][0] = this; - ppatches[0][1] = this; - ppatches[1][0] = this; - ppatches[1][1] = this; - - U32 i, j; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - if (poffsets[i][j][0] < 0) - { - if (!ppatches[i][j]->getNeighborPatch(WEST)) - { - poffsets[i][j][0] = 0; - } - else - { - poffsets[i][j][0] += patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); - } - } - if (poffsets[i][j][1] < 0) - { - if (!ppatches[i][j]->getNeighborPatch(SOUTH)) - { - poffsets[i][j][1] = 0; - } - else - { - poffsets[i][j][1] += patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); - } - } - if (poffsets[i][j][0] >= (S32)patch_width) - { - if (!ppatches[i][j]->getNeighborPatch(EAST)) - { - poffsets[i][j][0] = patch_width - 1; - } - else - { - poffsets[i][j][0] -= patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); - } - } - if (poffsets[i][j][1] >= (S32)patch_width) - { - if (!ppatches[i][j]->getNeighborPatch(NORTH)) - { - poffsets[i][j][1] = patch_width - 1; - } - else - { - poffsets[i][j][1] -= patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); - } - } - } - } - - LLVector3 p00(-mpg,-mpg, - *(ppatches[0][0]->mDataZ - + poffsets[0][0][0] - + poffsets[0][0][1]*surface_stride)); - LLVector3 p01(-mpg,+mpg, - *(ppatches[0][1]->mDataZ - + poffsets[0][1][0] - + poffsets[0][1][1]*surface_stride)); - LLVector3 p10(+mpg,-mpg, - *(ppatches[1][0]->mDataZ - + poffsets[1][0][0] - + poffsets[1][0][1]*surface_stride)); - LLVector3 p11(+mpg,+mpg, - *(ppatches[1][1]->mDataZ - + poffsets[1][1][0] - + poffsets[1][1][1]*surface_stride)); - - LLVector3 c1 = p11 - p00; - LLVector3 c2 = p01 - p10; - - LLVector3 normal = c1; - normal %= c2; - normal.normVec(); - - llassert(mDataNorm); - *(mDataNorm + surface_stride * y + x) = normal; + U32 patch_width = mSurfacep->mPVArray.mPatchWidth; + U32 surface_stride = mSurfacep->getGridsPerEdge(); + + const F32 mpg = mSurfacep->getMetersPerGrid() * stride; + + S32 poffsets[2][2][2]; + poffsets[0][0][0] = x - stride; + poffsets[0][0][1] = y - stride; + + poffsets[0][1][0] = x - stride; + poffsets[0][1][1] = y + stride; + + poffsets[1][0][0] = x + stride; + poffsets[1][0][1] = y - stride; + + poffsets[1][1][0] = x + stride; + poffsets[1][1][1] = y + stride; + + const LLSurfacePatch *ppatches[2][2]; + + // LLVector3 p1, p2, p3, p4; + + ppatches[0][0] = this; + ppatches[0][1] = this; + ppatches[1][0] = this; + ppatches[1][1] = this; + + U32 i, j; + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + { + if (poffsets[i][j][0] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(WEST)) + { + poffsets[i][j][0] = 0; + } + else + { + poffsets[i][j][0] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); + } + } + if (poffsets[i][j][1] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(SOUTH)) + { + poffsets[i][j][1] = 0; + } + else + { + poffsets[i][j][1] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); + } + } + if (poffsets[i][j][0] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(EAST)) + { + poffsets[i][j][0] = patch_width - 1; + } + else + { + poffsets[i][j][0] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); + } + } + if (poffsets[i][j][1] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(NORTH)) + { + poffsets[i][j][1] = patch_width - 1; + } + else + { + poffsets[i][j][1] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); + } + } + } + } + + LLVector3 p00(-mpg,-mpg, + *(ppatches[0][0]->mDataZ + + poffsets[0][0][0] + + poffsets[0][0][1]*surface_stride)); + LLVector3 p01(-mpg,+mpg, + *(ppatches[0][1]->mDataZ + + poffsets[0][1][0] + + poffsets[0][1][1]*surface_stride)); + LLVector3 p10(+mpg,-mpg, + *(ppatches[1][0]->mDataZ + + poffsets[1][0][0] + + poffsets[1][0][1]*surface_stride)); + LLVector3 p11(+mpg,+mpg, + *(ppatches[1][1]->mDataZ + + poffsets[1][1][0] + + poffsets[1][1][1]*surface_stride)); + + LLVector3 c1 = p11 - p00; + LLVector3 c2 = p01 - p10; + + LLVector3 normal = c1; + normal %= c2; + normal.normVec(); + + llassert(mDataNorm); + *(mDataNorm + surface_stride * y + x) = normal; } template<> void LLSurfacePatch::calcNormal(const U32 x, const U32 y, const U32 stride) { - llassert(mDataNorm); + llassert(mDataNorm); constexpr U32 index = 0; - const U32 surface_stride = mSurfacep->getGridsPerEdge(); - LLVector3& normal_out = *(mDataNorm + surface_stride * y + x); - calcNormalFlat(normal_out, x, y, index); + const U32 surface_stride = mSurfacep->getGridsPerEdge(); + LLVector3& normal_out = *(mDataNorm + surface_stride * y + x); + calcNormalFlat(normal_out, x, y, index); } // Calculate the flat normal of a triangle whose least coordinate is specified by the given x,y values. @@ -374,120 +374,120 @@ void LLSurfacePatch::calcNormalFlat(LLVector3& normal_out, const U32 x, const U3 { llassert(index == 0 || index == 1); - U32 patch_width = mSurfacep->mPVArray.mPatchWidth; - U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 patch_width = mSurfacep->mPVArray.mPatchWidth; + U32 surface_stride = mSurfacep->getGridsPerEdge(); // Vertex stride is always 1 because we want the flat surface of the current triangle face constexpr U32 stride = 1; - const F32 mpg = mSurfacep->getMetersPerGrid() * stride; - - S32 poffsets[2][2][2]; - poffsets[0][0][0] = x; - poffsets[0][0][1] = y; - - poffsets[0][1][0] = x; - poffsets[0][1][1] = y + stride; - - poffsets[1][0][0] = x + stride; - poffsets[1][0][1] = y; - - poffsets[1][1][0] = x + stride; - poffsets[1][1][1] = y + stride; - - const LLSurfacePatch *ppatches[2][2]; - - // LLVector3 p1, p2, p3, p4; - - ppatches[0][0] = this; - ppatches[0][1] = this; - ppatches[1][0] = this; - ppatches[1][1] = this; - - U32 i, j; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - if (poffsets[i][j][0] < 0) - { - if (!ppatches[i][j]->getNeighborPatch(WEST)) - { - poffsets[i][j][0] = 0; - } - else - { - poffsets[i][j][0] += patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); - } - } - if (poffsets[i][j][1] < 0) - { - if (!ppatches[i][j]->getNeighborPatch(SOUTH)) - { - poffsets[i][j][1] = 0; - } - else - { - poffsets[i][j][1] += patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); - } - } - if (poffsets[i][j][0] >= (S32)patch_width) - { - if (!ppatches[i][j]->getNeighborPatch(EAST)) - { - poffsets[i][j][0] = patch_width - 1; - } - else - { - poffsets[i][j][0] -= patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); - } - } - if (poffsets[i][j][1] >= (S32)patch_width) - { - if (!ppatches[i][j]->getNeighborPatch(NORTH)) - { - poffsets[i][j][1] = patch_width - 1; - } - else - { - poffsets[i][j][1] -= patch_width; - ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); - } - } - } - } - - LLVector3 p00(-mpg,-mpg, - *(ppatches[0][0]->mDataZ - + poffsets[0][0][0] - + poffsets[0][0][1]*surface_stride)); - LLVector3 p01(-mpg,+mpg, - *(ppatches[0][1]->mDataZ - + poffsets[0][1][0] - + poffsets[0][1][1]*surface_stride)); - LLVector3 p10(+mpg,-mpg, - *(ppatches[1][0]->mDataZ - + poffsets[1][0][0] - + poffsets[1][0][1]*surface_stride)); - LLVector3 p11(+mpg,+mpg, - *(ppatches[1][1]->mDataZ - + poffsets[1][1][0] - + poffsets[1][1][1]*surface_stride)); - + const F32 mpg = mSurfacep->getMetersPerGrid() * stride; + + S32 poffsets[2][2][2]; + poffsets[0][0][0] = x; + poffsets[0][0][1] = y; + + poffsets[0][1][0] = x; + poffsets[0][1][1] = y + stride; + + poffsets[1][0][0] = x + stride; + poffsets[1][0][1] = y; + + poffsets[1][1][0] = x + stride; + poffsets[1][1][1] = y + stride; + + const LLSurfacePatch *ppatches[2][2]; + + // LLVector3 p1, p2, p3, p4; + + ppatches[0][0] = this; + ppatches[0][1] = this; + ppatches[1][0] = this; + ppatches[1][1] = this; + + U32 i, j; + for (i = 0; i < 2; i++) + { + for (j = 0; j < 2; j++) + { + if (poffsets[i][j][0] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(WEST)) + { + poffsets[i][j][0] = 0; + } + else + { + poffsets[i][j][0] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(WEST); + } + } + if (poffsets[i][j][1] < 0) + { + if (!ppatches[i][j]->getNeighborPatch(SOUTH)) + { + poffsets[i][j][1] = 0; + } + else + { + poffsets[i][j][1] += patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(SOUTH); + } + } + if (poffsets[i][j][0] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(EAST)) + { + poffsets[i][j][0] = patch_width - 1; + } + else + { + poffsets[i][j][0] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(EAST); + } + } + if (poffsets[i][j][1] >= (S32)patch_width) + { + if (!ppatches[i][j]->getNeighborPatch(NORTH)) + { + poffsets[i][j][1] = patch_width - 1; + } + else + { + poffsets[i][j][1] -= patch_width; + ppatches[i][j] = ppatches[i][j]->getNeighborPatch(NORTH); + } + } + } + } + + LLVector3 p00(-mpg,-mpg, + *(ppatches[0][0]->mDataZ + + poffsets[0][0][0] + + poffsets[0][0][1]*surface_stride)); + LLVector3 p01(-mpg,+mpg, + *(ppatches[0][1]->mDataZ + + poffsets[0][1][0] + + poffsets[0][1][1]*surface_stride)); + LLVector3 p10(+mpg,-mpg, + *(ppatches[1][0]->mDataZ + + poffsets[1][0][0] + + poffsets[1][0][1]*surface_stride)); + LLVector3 p11(+mpg,+mpg, + *(ppatches[1][1]->mDataZ + + poffsets[1][1][0] + + poffsets[1][1][1]*surface_stride)); + // Triangle index / coordinate convention // for a single surface patch // // p01 p11 // - // ^ ._____. - // | |\ | - // | | \ 1 | - // | | \ | - // | 0 \ | - // y |____\| + // ^ ._____. + // | |\ | + // | | \ 1 | + // | | \ | + // | 0 \ | + // y |____\| // // p00 x ---> p10 // @@ -513,268 +513,268 @@ void LLSurfacePatch::calcNormalFlat(LLVector3& normal_out, const U32 x, const U3 normal.normVec(); } - llassert(&normal_out); - normal_out = normal; + llassert(&normal_out); + normal_out = normal; } const LLVector3 &LLSurfacePatch::getNormal(const U32 x, const U32 y) const { - U32 surface_stride = mSurfacep->getGridsPerEdge(); - llassert(mDataNorm); - return *(mDataNorm + surface_stride * y + x); + U32 surface_stride = mSurfacep->getGridsPerEdge(); + llassert(mDataNorm); + return *(mDataNorm + surface_stride * y + x); } void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { - if (LLPipeline::sDynamicLOD) - { - if (!gShiftFrame) - { - LLVector3 dv = pos_region; - dv -= mCenterRegion; - mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ - llmax(LLVOSurfacePatch::sLODFactor, 0.1f); - } - } - else - { - mVisInfo.mDistance = 0.f; - } + if (LLPipeline::sDynamicLOD) + { + if (!gShiftFrame) + { + LLVector3 dv = pos_region; + dv -= mCenterRegion; + mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ + llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + } + } + else + { + mVisInfo.mDistance = 0.f; + } } F32 LLSurfacePatch::getDistance() const { - return mVisInfo.mDistance; + return mVisInfo.mDistance; } // Called when a patch has changed its height field // data. -void LLSurfacePatch::updateVerticalStats() +void LLSurfacePatch::updateVerticalStats() { - if (!mDirtyZStats) - { - return; - } - - U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - U32 grids_per_edge = mSurfacep->getGridsPerEdge(); - F32 meters_per_grid = mSurfacep->getMetersPerGrid(); - - U32 i, j, k; - F32 z, total; - - llassert(mDataZ); - z = *(mDataZ); - - mMinZ = z; - mMaxZ = z; - - k = 0; - total = 0.0f; - - // Iterate to +1 because we need to do the edges correctly. - for (j=0; j<(grids_per_patch_edge+1); j++) - { - for (i=0; i<(grids_per_patch_edge+1); i++) - { - z = *(mDataZ + i + j*grids_per_edge); - - if (z < mMinZ) - { - mMinZ = z; - } - if (z > mMaxZ) - { - mMaxZ = z; - } - total += z; - k++; - } - } - mMeanZ = total / (F32) k; - mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ); - - LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge, - meters_per_grid*grids_per_patch_edge, - mMaxZ - mMinZ); - mRadius = diam_vec.magVec() * 0.5f; - - mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ); - mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ); - mSurfacep->mHasZData = TRUE; - mSurfacep->getRegion()->calculateCenterGlobal(); - - if (mVObjp) - { - mVObjp->dirtyPatch(); - } - mDirtyZStats = FALSE; + if (!mDirtyZStats) + { + return; + } + + U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); + U32 grids_per_edge = mSurfacep->getGridsPerEdge(); + F32 meters_per_grid = mSurfacep->getMetersPerGrid(); + + U32 i, j, k; + F32 z, total; + + llassert(mDataZ); + z = *(mDataZ); + + mMinZ = z; + mMaxZ = z; + + k = 0; + total = 0.0f; + + // Iterate to +1 because we need to do the edges correctly. + for (j=0; j<(grids_per_patch_edge+1); j++) + { + for (i=0; i<(grids_per_patch_edge+1); i++) + { + z = *(mDataZ + i + j*grids_per_edge); + + if (z < mMinZ) + { + mMinZ = z; + } + if (z > mMaxZ) + { + mMaxZ = z; + } + total += z; + k++; + } + } + mMeanZ = total / (F32) k; + mCenterRegion.mV[VZ] = 0.5f * (mMinZ + mMaxZ); + + LLVector3 diam_vec(meters_per_grid*grids_per_patch_edge, + meters_per_grid*grids_per_patch_edge, + mMaxZ - mMinZ); + mRadius = diam_vec.magVec() * 0.5f; + + mSurfacep->mMaxZ = llmax(mMaxZ, mSurfacep->mMaxZ); + mSurfacep->mMinZ = llmin(mMinZ, mSurfacep->mMinZ); + mSurfacep->mHasZData = TRUE; + mSurfacep->getRegion()->calculateCenterGlobal(); + + if (mVObjp) + { + mVObjp->dirtyPatch(); + } + mDirtyZStats = FALSE; } template -void LLSurfacePatch::updateNormals() +void LLSurfacePatch::updateNormals() { - if (mSurfacep->mType == 'w') - { - return; - } - U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - U32 grids_per_edge = mSurfacep->getGridsPerEdge(); - - BOOL dirty_patch = FALSE; - - U32 i, j; - // update the east edge - if (mNormalsInvalid[EAST] || mNormalsInvalid[NORTHEAST] || mNormalsInvalid[SOUTHEAST]) - { - for (j = 0; j <= grids_per_patch_edge; j++) - { - calcNormal(grids_per_patch_edge, j, 2); - calcNormal(grids_per_patch_edge - 1, j, 2); - calcNormal(grids_per_patch_edge - 2, j, 2); - } - - dirty_patch = TRUE; - } - - // update the north edge - if (mNormalsInvalid[NORTHEAST] || mNormalsInvalid[NORTH] || mNormalsInvalid[NORTHWEST]) - { - for (i = 0; i <= grids_per_patch_edge; i++) - { - calcNormal(i, grids_per_patch_edge, 2); - calcNormal(i, grids_per_patch_edge - 1, 2); - calcNormal(i, grids_per_patch_edge - 2, 2); - } - - dirty_patch = TRUE; - } - - // update the west edge - if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST]) - { - for (j = 0; j < grids_per_patch_edge; j++) - { - calcNormal(0, j, 2); - calcNormal(1, j, 2); - } - dirty_patch = TRUE; - } - - // update the south edge - if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST]) - { - for (i = 0; i < grids_per_patch_edge; i++) - { - calcNormal(i, 0, 2); - calcNormal(i, 1, 2); - } - dirty_patch = TRUE; - } - - // Invalidating the northeast corner is different, because depending on what the adjacent neighbors are, - // we'll want to do different things. - if (mNormalsInvalid[NORTHEAST]) - { - if (!getNeighborPatch(NORTHEAST)) - { - if (!getNeighborPatch(NORTH)) - { - if (!getNeighborPatch(EAST)) - { - // No north or east neighbors. Pull from the diagonal in your own patch. - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); - } - else - { - if (getNeighborPatch(EAST)->getHasReceivedData()) - { - // East, but not north. Pull from your east neighbor's northwest point. - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge); - } - else - { - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); - } - } - } - else - { - // We have a north. - if (getNeighborPatch(EAST)) - { - // North and east neighbors, but not northeast. - // Pull from diagonal in your own patch. - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); - } - else - { - if (getNeighborPatch(NORTH)->getHasReceivedData()) - { - // North, but not east. Pull from your north neighbor's southeast corner. - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1)); - } - else - { - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); - } - } - } - } - else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep) - { - if ( - (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep)) - && - (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep))) - { - *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = - *(getNeighborPatch(NORTHEAST)->mDataZ); - } - } - else - { - // We've got a northeast patch in the same surface. - // The z and normals will be handled by that patch. - } - calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2); - calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2); - calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2); - calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2); - dirty_patch = TRUE; - } - - // update the middle normals - if (mNormalsInvalid[MIDDLE]) - { - for (j=2; j < grids_per_patch_edge - 2; j++) - { - for (i=2; i < grids_per_patch_edge - 2; i++) - { - calcNormal(i, j, 2); - } - } - dirty_patch = TRUE; - } - - if (dirty_patch) - { - mSurfacep->dirtySurfacePatch(this); - } - - for (i = 0; i < 9; i++) - { - mNormalsInvalid[i] = FALSE; - } + if (mSurfacep->mType == 'w') + { + return; + } + U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); + U32 grids_per_edge = mSurfacep->getGridsPerEdge(); + + BOOL dirty_patch = FALSE; + + U32 i, j; + // update the east edge + if (mNormalsInvalid[EAST] || mNormalsInvalid[NORTHEAST] || mNormalsInvalid[SOUTHEAST]) + { + for (j = 0; j <= grids_per_patch_edge; j++) + { + calcNormal(grids_per_patch_edge, j, 2); + calcNormal(grids_per_patch_edge - 1, j, 2); + calcNormal(grids_per_patch_edge - 2, j, 2); + } + + dirty_patch = TRUE; + } + + // update the north edge + if (mNormalsInvalid[NORTHEAST] || mNormalsInvalid[NORTH] || mNormalsInvalid[NORTHWEST]) + { + for (i = 0; i <= grids_per_patch_edge; i++) + { + calcNormal(i, grids_per_patch_edge, 2); + calcNormal(i, grids_per_patch_edge - 1, 2); + calcNormal(i, grids_per_patch_edge - 2, 2); + } + + dirty_patch = TRUE; + } + + // update the west edge + if (mNormalsInvalid[NORTHWEST] || mNormalsInvalid[WEST] || mNormalsInvalid[SOUTHWEST]) + { + for (j = 0; j < grids_per_patch_edge; j++) + { + calcNormal(0, j, 2); + calcNormal(1, j, 2); + } + dirty_patch = TRUE; + } + + // update the south edge + if (mNormalsInvalid[SOUTHWEST] || mNormalsInvalid[SOUTH] || mNormalsInvalid[SOUTHEAST]) + { + for (i = 0; i < grids_per_patch_edge; i++) + { + calcNormal(i, 0, 2); + calcNormal(i, 1, 2); + } + dirty_patch = TRUE; + } + + // Invalidating the northeast corner is different, because depending on what the adjacent neighbors are, + // we'll want to do different things. + if (mNormalsInvalid[NORTHEAST]) + { + if (!getNeighborPatch(NORTHEAST)) + { + if (!getNeighborPatch(NORTH)) + { + if (!getNeighborPatch(EAST)) + { + // No north or east neighbors. Pull from the diagonal in your own patch. + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); + } + else + { + if (getNeighborPatch(EAST)->getHasReceivedData()) + { + // East, but not north. Pull from your east neighbor's northwest point. + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(getNeighborPatch(EAST)->mDataZ + (grids_per_patch_edge - 1)*grids_per_edge); + } + else + { + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); + } + } + } + else + { + // We have a north. + if (getNeighborPatch(EAST)) + { + // North and east neighbors, but not northeast. + // Pull from diagonal in your own patch. + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); + } + else + { + if (getNeighborPatch(NORTH)->getHasReceivedData()) + { + // North, but not east. Pull from your north neighbor's southeast corner. + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(getNeighborPatch(NORTH)->mDataZ + (grids_per_patch_edge - 1)); + } + else + { + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(mDataZ + grids_per_patch_edge - 1 + (grids_per_patch_edge - 1)*grids_per_edge); + } + } + } + } + else if (getNeighborPatch(NORTHEAST)->mSurfacep != mSurfacep) + { + if ( + (!getNeighborPatch(NORTH) || (getNeighborPatch(NORTH)->mSurfacep != mSurfacep)) + && + (!getNeighborPatch(EAST) || (getNeighborPatch(EAST)->mSurfacep != mSurfacep))) + { + *(mDataZ + grids_per_patch_edge + grids_per_patch_edge*grids_per_edge) = + *(getNeighborPatch(NORTHEAST)->mDataZ); + } + } + else + { + // We've got a northeast patch in the same surface. + // The z and normals will be handled by that patch. + } + calcNormal(grids_per_patch_edge, grids_per_patch_edge, 2); + calcNormal(grids_per_patch_edge, grids_per_patch_edge - 1, 2); + calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge, 2); + calcNormal(grids_per_patch_edge - 1, grids_per_patch_edge - 1, 2); + dirty_patch = TRUE; + } + + // update the middle normals + if (mNormalsInvalid[MIDDLE]) + { + for (j=2; j < grids_per_patch_edge - 2; j++) + { + for (i=2; i < grids_per_patch_edge - 2; i++) + { + calcNormal(i, j, 2); + } + } + dirty_patch = TRUE; + } + + if (dirty_patch) + { + mSurfacep->dirtySurfacePatch(this); + } + + for (i = 0; i < 9; i++) + { + mNormalsInvalid[i] = FALSE; + } } template void LLSurfacePatch::updateNormals(); @@ -782,418 +782,418 @@ template void LLSurfacePatch::updateNormals(); void LLSurfacePatch::updateEastEdge() { - U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - U32 grids_per_edge = mSurfacep->getGridsPerEdge(); - - U32 j, k; - F32 *west_surface, *east_surface; - - if (!getNeighborPatch(EAST)) - { - west_surface = mDataZ + grids_per_patch_edge; - east_surface = mDataZ + grids_per_patch_edge - 1; - } - else if (mConnectedEdge & EAST_EDGE) - { - west_surface = mDataZ + grids_per_patch_edge; - east_surface = getNeighborPatch(EAST)->mDataZ; - } - else - { - return; - } - - // If patchp is on the east edge of its surface, then we update the east - // side buffer - for (j=0; j < grids_per_patch_edge; j++) - { - k = j * grids_per_edge; - *(west_surface + k) = *(east_surface + k); // update buffer Z - } + U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); + U32 grids_per_edge = mSurfacep->getGridsPerEdge(); + + U32 j, k; + F32 *west_surface, *east_surface; + + if (!getNeighborPatch(EAST)) + { + west_surface = mDataZ + grids_per_patch_edge; + east_surface = mDataZ + grids_per_patch_edge - 1; + } + else if (mConnectedEdge & EAST_EDGE) + { + west_surface = mDataZ + grids_per_patch_edge; + east_surface = getNeighborPatch(EAST)->mDataZ; + } + else + { + return; + } + + // If patchp is on the east edge of its surface, then we update the east + // side buffer + for (j=0; j < grids_per_patch_edge; j++) + { + k = j * grids_per_edge; + *(west_surface + k) = *(east_surface + k); // update buffer Z + } } void LLSurfacePatch::updateNorthEdge() { - U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - U32 grids_per_edge = mSurfacep->getGridsPerEdge(); - - U32 i; - F32 *south_surface, *north_surface; - - if (!getNeighborPatch(NORTH)) - { - south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; - north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge; - } - else if (mConnectedEdge & NORTH_EDGE) - { - south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; - north_surface = getNeighborPatch(NORTH)->mDataZ; - } - else - { - return; - } - - // Update patchp's north edge ... - for (i=0; igetGridsPerPatchEdge(); + U32 grids_per_edge = mSurfacep->getGridsPerEdge(); + + U32 i; + F32 *south_surface, *north_surface; + + if (!getNeighborPatch(NORTH)) + { + south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; + north_surface = mDataZ + (grids_per_patch_edge - 1) * grids_per_edge; + } + else if (mConnectedEdge & NORTH_EDGE) + { + south_surface = mDataZ + grids_per_patch_edge*grids_per_edge; + north_surface = getNeighborPatch(NORTH)->mDataZ; + } + else + { + return; + } + + // Update patchp's north edge ... + for (i=0; igetMetersPerGrid(); - F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); - - if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData()) - && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData()) - && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData()) - && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData())) - { - LLViewerRegion *regionp = getSurface()->getRegion(); - LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); - - // Have to figure out a better way to deal with these edge conditions... - LLVLComposition* comp = regionp->getComposition(); - if (!mHeightsGenerated) - { - F32 patch_size = meters_per_grid*(grids_per_patch_edge+1); - if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY], - patch_size, patch_size)) - { - mHeightsGenerated = TRUE; - } - else - { - return FALSE; - } - } - - if (comp->generateComposition()) - { - if (mVObjp) - { - mVObjp->dirtyGeom(); - gPipeline.markGLRebuild(mVObjp); - return !mSTexUpdate; - } - } - } - return FALSE; - } - else - { - return TRUE; - } + if (mSTexUpdate) // Update texture as needed + { + F32 meters_per_grid = getSurface()->getMetersPerGrid(); + F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); + + if ((!getNeighborPatch(EAST) || getNeighborPatch(EAST)->getHasReceivedData()) + && (!getNeighborPatch(WEST) || getNeighborPatch(WEST)->getHasReceivedData()) + && (!getNeighborPatch(SOUTH) || getNeighborPatch(SOUTH)->getHasReceivedData()) + && (!getNeighborPatch(NORTH) || getNeighborPatch(NORTH)->getHasReceivedData())) + { + LLViewerRegion *regionp = getSurface()->getRegion(); + LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); + + // Have to figure out a better way to deal with these edge conditions... + LLVLComposition* comp = regionp->getComposition(); + if (!mHeightsGenerated) + { + F32 patch_size = meters_per_grid*(grids_per_patch_edge+1); + if (comp->generateHeights((F32)origin_region[VX], (F32)origin_region[VY], + patch_size, patch_size)) + { + mHeightsGenerated = TRUE; + } + else + { + return FALSE; + } + } + + if (comp->generateComposition()) + { + if (mVObjp) + { + mVObjp->dirtyGeom(); + gPipeline.markGLRebuild(mVObjp); + return !mSTexUpdate; + } + } + } + return FALSE; + } + else + { + return TRUE; + } } void LLSurfacePatch::updateGL() { - LL_PROFILE_ZONE_SCOPED - F32 meters_per_grid = getSurface()->getMetersPerGrid(); - F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); - - LLViewerRegion *regionp = getSurface()->getRegion(); - LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); - - LLVLComposition* comp = regionp->getComposition(); - - updateCompositionStats(); - F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; - if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY], - tex_patch_size, tex_patch_size)) - { - mSTexUpdate = FALSE; - - // Also generate the water texture - mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], - tex_patch_size, tex_patch_size); - } + LL_PROFILE_ZONE_SCOPED + F32 meters_per_grid = getSurface()->getMetersPerGrid(); + F32 grids_per_patch_edge = (F32)getSurface()->getGridsPerPatchEdge(); + + LLViewerRegion *regionp = getSurface()->getRegion(); + LLVector3d origin_region = getOriginGlobal() - getSurface()->getOriginGlobal(); + + LLVLComposition* comp = regionp->getComposition(); + + updateCompositionStats(); + F32 tex_patch_size = meters_per_grid*grids_per_patch_edge; + if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY], + tex_patch_size, tex_patch_size)) + { + mSTexUpdate = FALSE; + + // Also generate the water texture + mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY], + tex_patch_size, tex_patch_size); + } } void LLSurfacePatch::dirtyZ() { - mSTexUpdate = TRUE; - - // Invalidate all normals in this patch - U32 i; - for (i = 0; i < 9; i++) - { - mNormalsInvalid[i] = TRUE; - } - - // Invalidate normals in this and neighboring patches - for (i = 0; i < 8; i++) - { - if (getNeighborPatch(i)) - { - getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE; - getNeighborPatch(i)->dirty(); - if (i < 4) - { - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; - getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; - } - } - } - - dirty(); - mLastUpdateTime = gFrameTime; + mSTexUpdate = TRUE; + + // Invalidate all normals in this patch + U32 i; + for (i = 0; i < 9; i++) + { + mNormalsInvalid[i] = TRUE; + } + + // Invalidate normals in this and neighboring patches + for (i = 0; i < 8; i++) + { + if (getNeighborPatch(i)) + { + getNeighborPatch(i)->mNormalsInvalid[gDirOpposite[i]] = TRUE; + getNeighborPatch(i)->dirty(); + if (i < 4) + { + getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][0]] = TRUE; + getNeighborPatch(i)->mNormalsInvalid[gDirAdjacent[gDirOpposite[i]][1]] = TRUE; + } + } + } + + dirty(); + mLastUpdateTime = gFrameTime; } const U64 &LLSurfacePatch::getLastUpdateTime() const { - return mLastUpdateTime; + return mLastUpdateTime; } F32 LLSurfacePatch::getMaxZ() const { - return mMaxZ; + return mMaxZ; } F32 LLSurfacePatch::getMinZ() const { - return mMinZ; + return mMinZ; } void LLSurfacePatch::setOriginGlobal(const LLVector3d &origin_global) { - mOriginGlobal = origin_global; + mOriginGlobal = origin_global; + + LLVector3 origin_region; + origin_region.setVec(mOriginGlobal - mSurfacep->getOriginGlobal()); - LLVector3 origin_region; - origin_region.setVec(mOriginGlobal - mSurfacep->getOriginGlobal()); + mOriginRegion = origin_region; + mCenterRegion.mV[VX] = origin_region.mV[VX] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid(); + mCenterRegion.mV[VY] = origin_region.mV[VY] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid(); - mOriginRegion = origin_region; - mCenterRegion.mV[VX] = origin_region.mV[VX] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid(); - mCenterRegion.mV[VY] = origin_region.mV[VY] + 0.5f*mSurfacep->getGridsPerPatchEdge()*mSurfacep->getMetersPerGrid(); + mVisInfo.mbIsVisible = FALSE; + mVisInfo.mDistance = 512.0f; + mVisInfo.mRenderLevel = 0; + mVisInfo.mRenderStride = mSurfacep->getGridsPerPatchEdge(); - mVisInfo.mbIsVisible = FALSE; - mVisInfo.mDistance = 512.0f; - mVisInfo.mRenderLevel = 0; - mVisInfo.mRenderStride = mSurfacep->getGridsPerPatchEdge(); - } void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 direction) { - llassert(neighbor_patchp); - mNormalsInvalid[direction] = TRUE; - neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE; - - setNeighborPatch(direction, neighbor_patchp); - neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this); - - if (EAST == direction) - { - mConnectedEdge |= EAST_EDGE; - neighbor_patchp->mConnectedEdge |= WEST_EDGE; - } - else if (NORTH == direction) - { - mConnectedEdge |= NORTH_EDGE; - neighbor_patchp->mConnectedEdge |= SOUTH_EDGE; - } - else if (WEST == direction) - { - mConnectedEdge |= WEST_EDGE; - neighbor_patchp->mConnectedEdge |= EAST_EDGE; - } - else if (SOUTH == direction) - { - mConnectedEdge |= SOUTH_EDGE; - neighbor_patchp->mConnectedEdge |= NORTH_EDGE; - } + llassert(neighbor_patchp); + mNormalsInvalid[direction] = TRUE; + neighbor_patchp->mNormalsInvalid[gDirOpposite[direction]] = TRUE; + + setNeighborPatch(direction, neighbor_patchp); + neighbor_patchp->setNeighborPatch(gDirOpposite[direction], this); + + if (EAST == direction) + { + mConnectedEdge |= EAST_EDGE; + neighbor_patchp->mConnectedEdge |= WEST_EDGE; + } + else if (NORTH == direction) + { + mConnectedEdge |= NORTH_EDGE; + neighbor_patchp->mConnectedEdge |= SOUTH_EDGE; + } + else if (WEST == direction) + { + mConnectedEdge |= WEST_EDGE; + neighbor_patchp->mConnectedEdge |= EAST_EDGE; + } + else if (SOUTH == direction) + { + mConnectedEdge |= SOUTH_EDGE; + neighbor_patchp->mConnectedEdge |= NORTH_EDGE; + } } void LLSurfacePatch::updateVisibility() { - if (mVObjp.isNull()) - { - return; - } - - const F32 DEFAULT_DELTA_ANGLE = (0.15f); - U32 old_render_stride, max_render_stride; - U32 new_render_level; - F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid(); - U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - - LLVector4a center; - center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV); - LLVector4a radius; - radius.splat(mRadius); - - // sphere in frustum on global coordinates - if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius)) - { - // We now need to calculate the render stride based on patchp's distance - // from LLCamera render_stride is governed by a relation something like this... - // - // delta_angle * patch.distance - // render_stride <= ---------------------------------------- - // mMetersPerGrid - // - // where 'delta_angle' is the desired solid angle of the average polgon on a patch. - // - // Any render_stride smaller than the RHS would be 'satisfactory'. Smaller - // strides give more resolution, but efficiency suggests that we use the largest - // of the render_strides that obey the relation. Flexibility is achieved by - // modulating 'delta_angle' until we have an acceptable number of triangles. - - old_render_stride = mVisInfo.mRenderStride; - - // Calculate the render_stride using information in agent - max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance); - max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge); - - // We only use render_strides that are powers of two, so we use look-up tables to figure out - // the render_level and corresponding render_stride - new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride); - mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level); - - if ((mVisInfo.mRenderStride != old_render_stride)) - // The reason we check !mbIsVisible is because non-visible patches normals - // are not updated when their data is changed. When this changes we can get - // rid of mbIsVisible altogether. - { - if (mVObjp) - { - mVObjp->dirtyGeom(); - if (getNeighborPatch(WEST)) - { - getNeighborPatch(WEST)->mVObjp->dirtyGeom(); - } - if (getNeighborPatch(SOUTH)) - { - getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); - } - } - } - mVisInfo.mbIsVisible = TRUE; - } - else - { - mVisInfo.mbIsVisible = FALSE; - } + if (mVObjp.isNull()) + { + return; + } + + const F32 DEFAULT_DELTA_ANGLE = (0.15f); + U32 old_render_stride, max_render_stride; + U32 new_render_level; + F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid(); + U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); + + LLVector4a center; + center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV); + LLVector4a radius; + radius.splat(mRadius); + + // sphere in frustum on global coordinates + if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius)) + { + // We now need to calculate the render stride based on patchp's distance + // from LLCamera render_stride is governed by a relation something like this... + // + // delta_angle * patch.distance + // render_stride <= ---------------------------------------- + // mMetersPerGrid + // + // where 'delta_angle' is the desired solid angle of the average polgon on a patch. + // + // Any render_stride smaller than the RHS would be 'satisfactory'. Smaller + // strides give more resolution, but efficiency suggests that we use the largest + // of the render_strides that obey the relation. Flexibility is achieved by + // modulating 'delta_angle' until we have an acceptable number of triangles. + + old_render_stride = mVisInfo.mRenderStride; + + // Calculate the render_stride using information in agent + max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance); + max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge); + + // We only use render_strides that are powers of two, so we use look-up tables to figure out + // the render_level and corresponding render_stride + new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride); + mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level); + + if ((mVisInfo.mRenderStride != old_render_stride)) + // The reason we check !mbIsVisible is because non-visible patches normals + // are not updated when their data is changed. When this changes we can get + // rid of mbIsVisible altogether. + { + if (mVObjp) + { + mVObjp->dirtyGeom(); + if (getNeighborPatch(WEST)) + { + getNeighborPatch(WEST)->mVObjp->dirtyGeom(); + } + if (getNeighborPatch(SOUTH)) + { + getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); + } + } + } + mVisInfo.mbIsVisible = TRUE; + } + else + { + mVisInfo.mbIsVisible = FALSE; + } } const LLVector3d &LLSurfacePatch::getOriginGlobal() const { - return mOriginGlobal; + return mOriginGlobal; } LLVector3 LLSurfacePatch::getOriginAgent() const { - return gAgent.getPosAgentFromGlobal(mOriginGlobal); + return gAgent.getPosAgentFromGlobal(mOriginGlobal); } BOOL LLSurfacePatch::getVisible() const { - return mVisInfo.mbIsVisible; + return mVisInfo.mbIsVisible; } U32 LLSurfacePatch::getRenderStride() const { - return mVisInfo.mRenderStride; + return mVisInfo.mRenderStride; } S32 LLSurfacePatch::getRenderLevel() const { - return mVisInfo.mRenderLevel; + return mVisInfo.mRenderLevel; } void LLSurfacePatch::setHasReceivedData() { - mHasReceivedData = TRUE; + mHasReceivedData = TRUE; } BOOL LLSurfacePatch::getHasReceivedData() const { - return mHasReceivedData; + return mHasReceivedData; } const LLVector3 &LLSurfacePatch::getCenterRegion() const { - return mCenterRegion; + return mCenterRegion; } void LLSurfacePatch::updateCompositionStats() { - LLViewerLayer *vlp = mSurfacep->getRegion()->getComposition(); - - F32 x, y, width, height, mpg, min, mean, max; - - LLVector3 origin = getOriginAgent() - mSurfacep->getOriginAgent(); - mpg = mSurfacep->getMetersPerGrid(); - x = origin.mV[VX]; - y = origin.mV[VY]; - width = mpg*(mSurfacep->getGridsPerPatchEdge()+1); - height = mpg*(mSurfacep->getGridsPerPatchEdge()+1); - - mean = 0.f; - min = vlp->getValueScaled(x, y); - max= min; - U32 count = 0; - F32 i, j; - for (j = 0; j < height; j += mpg) - { - for (i = 0; i < width; i += mpg) - { - F32 comp = vlp->getValueScaled(x + i, y + j); - mean += comp; - min = llmin(min, comp); - max = llmax(max, comp); - count++; - } - } - mean /= count; - - mMinComposition = min; - mMeanComposition = mean; - mMaxComposition = max; + LLViewerLayer *vlp = mSurfacep->getRegion()->getComposition(); + + F32 x, y, width, height, mpg, min, mean, max; + + LLVector3 origin = getOriginAgent() - mSurfacep->getOriginAgent(); + mpg = mSurfacep->getMetersPerGrid(); + x = origin.mV[VX]; + y = origin.mV[VY]; + width = mpg*(mSurfacep->getGridsPerPatchEdge()+1); + height = mpg*(mSurfacep->getGridsPerPatchEdge()+1); + + mean = 0.f; + min = vlp->getValueScaled(x, y); + max= min; + U32 count = 0; + F32 i, j; + for (j = 0; j < height; j += mpg) + { + for (i = 0; i < width; i += mpg) + { + F32 comp = vlp->getValueScaled(x + i, y + j); + mean += comp; + min = llmin(min, comp); + max = llmax(max, comp); + count++; + } + } + mean /= count; + + mMinComposition = min; + mMeanComposition = mean; + mMaxComposition = max; } F32 LLSurfacePatch::getMeanComposition() const { - return mMeanComposition; + return mMeanComposition; } F32 LLSurfacePatch::getMinComposition() const { - return mMinComposition; + return mMinComposition; } F32 LLSurfacePatch::getMaxComposition() const { - return mMaxComposition; + return mMaxComposition; } void LLSurfacePatch::setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp) { - mNeighborPatches[direction] = neighborp; - mNormalsInvalid[direction] = TRUE; - if (direction < 4) - { - mNormalsInvalid[gDirAdjacent[direction][0]] = TRUE; - mNormalsInvalid[gDirAdjacent[direction][1]] = TRUE; - } + mNeighborPatches[direction] = neighborp; + mNormalsInvalid[direction] = TRUE; + if (direction < 4) + { + mNormalsInvalid[gDirAdjacent[direction][0]] = TRUE; + mNormalsInvalid[gDirAdjacent[direction][1]] = TRUE; + } } LLSurfacePatch *LLSurfacePatch::getNeighborPatch(const U32 direction) const { - return mNeighborPatches[direction]; + return mNeighborPatches[direction]; } void LLSurfacePatch::clearVObj() { - mVObjp = NULL; + mVObjp = NULL; } diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index ec3864ce44..94d471b43d 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -1,25 +1,25 @@ -/** +/** * @file llsurfacepatch.h * @brief LLSurfacePatch class definition * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -37,71 +37,71 @@ class LLVector2; class LLColor4U; class LLAgent; -// A patch shouldn't know about its visibility since that really depends on the +// A patch shouldn't know about its visibility since that really depends on the // camera that is looking (or not looking) at it. So, anything about a patch // that is specific to a camera should be in the class below. class LLPatchVisibilityInfo { public: - LLPatchVisibilityInfo() : - mbIsVisible(FALSE), - mDistance(0.f), - mRenderLevel(0), - mRenderStride(0) { }; - ~LLPatchVisibilityInfo() { }; - - BOOL mbIsVisible; - F32 mDistance; // Distance from camera - S32 mRenderLevel; - U32 mRenderStride; + LLPatchVisibilityInfo() : + mbIsVisible(FALSE), + mDistance(0.f), + mRenderLevel(0), + mRenderStride(0) { }; + ~LLPatchVisibilityInfo() { }; + + BOOL mbIsVisible; + F32 mDistance; // Distance from camera + S32 mRenderLevel; + U32 mRenderStride; }; -class LLSurfacePatch +class LLSurfacePatch { public: - LLSurfacePatch(); - ~LLSurfacePatch(); + LLSurfacePatch(); + ~LLSurfacePatch(); - void reset(const U32 id); - void connectNeighbor(LLSurfacePatch *neighborp, const U32 direction); - void disconnectNeighbor(LLSurface *surfacep); + void reset(const U32 id); + void connectNeighbor(LLSurfacePatch *neighborp, const U32 direction); + void disconnectNeighbor(LLSurface *surfacep); - void setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp); - LLSurfacePatch *getNeighborPatch(const U32 direction) const; + void setNeighborPatch(const U32 direction, LLSurfacePatch *neighborp); + LLSurfacePatch *getNeighborPatch(const U32 direction) const; - void colorPatch(const U8 r, const U8 g, const U8 b); + void colorPatch(const U8 r, const U8 g, const U8 b); - BOOL updateTexture(); + BOOL updateTexture(); - void updateVerticalStats(); - void updateCompositionStats(); + void updateVerticalStats(); + void updateCompositionStats(); template - void updateNormals(); - - void updateEastEdge(); - void updateNorthEdge(); - - void updateCameraDistanceRegion( const LLVector3 &pos_region); - void updateVisibility(); - void updateGL(); - - void dirtyZ(); // Dirty the z values of this patch - void setHasReceivedData(); - BOOL getHasReceivedData() const; - - F32 getDistance() const; - F32 getMaxZ() const; - F32 getMinZ() const; - F32 getMeanComposition() const; - F32 getMinComposition() const; - F32 getMaxComposition() const; - const LLVector3 &getCenterRegion() const; - const U64 &getLastUpdateTime() const; - LLSurface *getSurface() const { return mSurfacep; } - LLVector3 getPointAgent(const U32 x, const U32 y) const; // get the point at the offset. - LLVector2 getTexCoords(const U32 x, const U32 y) const; + void updateNormals(); + + void updateEastEdge(); + void updateNorthEdge(); + + void updateCameraDistanceRegion( const LLVector3 &pos_region); + void updateVisibility(); + void updateGL(); + + void dirtyZ(); // Dirty the z values of this patch + void setHasReceivedData(); + BOOL getHasReceivedData() const; + + F32 getDistance() const; + F32 getMaxZ() const; + F32 getMinZ() const; + F32 getMeanComposition() const; + F32 getMinComposition() const; + F32 getMaxComposition() const; + const LLVector3 &getCenterRegion() const; + const U64 &getLastUpdateTime() const; + LLSurface *getSurface() const { return mSurfacep; } + LLVector3 getPointAgent(const U32 x, const U32 y) const; // get the point at the offset. + LLVector2 getTexCoords(const U32 x, const U32 y) const; // Per-vertex normals // *TODO: PBR=true is a test implementation solely for proof-of-concept. @@ -109,86 +109,86 @@ public: // this function. If we decide to keep calcNormalFlat, remove index as it // is a debug parameter for testing. template - void calcNormal(const U32 x, const U32 y, const U32 stride); - const LLVector3 &getNormal(const U32 x, const U32 y) const; + void calcNormal(const U32 x, const U32 y, const U32 stride); + const LLVector3 &getNormal(const U32 x, const U32 y) const; // Per-triangle normals for flat edges - void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */); + void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */); + + void eval(const U32 x, const U32 y, const U32 stride, + LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1); + + - void eval(const U32 x, const U32 y, const U32 stride, - LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex0, LLVector2 *tex1); - - + LLVector3 getOriginAgent() const; + const LLVector3d &getOriginGlobal() const; + void setOriginGlobal(const LLVector3d &origin_global); - LLVector3 getOriginAgent() const; - const LLVector3d &getOriginGlobal() const; - void setOriginGlobal(const LLVector3d &origin_global); - - // connectivity -- each LLPatch points at 5 neighbors (or NULL) - // +---+---+---+ - // | | 2 | 5 | - // +---+---+---+ - // | 3 | 0 | 1 | - // +---+---+---+ - // | 6 | 4 | | - // +---+---+---+ + // connectivity -- each LLPatch points at 5 neighbors (or NULL) + // +---+---+---+ + // | | 2 | 5 | + // +---+---+---+ + // | 3 | 0 | 1 | + // +---+---+---+ + // | 6 | 4 | | + // +---+---+---+ - BOOL getVisible() const; - U32 getRenderStride() const; - S32 getRenderLevel() const; + BOOL getVisible() const; + U32 getRenderStride() const; + S32 getRenderLevel() const; - void setSurface(LLSurface *surfacep); - void setDataZ(F32 *data_z) { mDataZ = data_z; } - void setDataNorm(LLVector3 *data_norm) { mDataNorm = data_norm; } - F32 *getDataZ() const { return mDataZ; } + void setSurface(LLSurface *surfacep); + void setDataZ(F32 *data_z) { mDataZ = data_z; } + void setDataNorm(LLVector3 *data_norm) { mDataNorm = data_norm; } + F32 *getDataZ() const { return mDataZ; } - void dirty(); // Mark this surface patch as dirty... - void clearDirty() { mDirty = FALSE; } + void dirty(); // Mark this surface patch as dirty... + void clearDirty() { mDirty = FALSE; } - void clearVObj(); + void clearVObj(); public: - BOOL mHasReceivedData; // has the patch EVER received height data? - BOOL mSTexUpdate; // Does the surface texture need to be updated? + BOOL mHasReceivedData; // has the patch EVER received height data? + BOOL mSTexUpdate; // Does the surface texture need to be updated? protected: - LLSurfacePatch *mNeighborPatches[8]; // Adjacent patches - BOOL mNormalsInvalid[9]; // Which normals are invalid + LLSurfacePatch *mNeighborPatches[8]; // Adjacent patches + BOOL mNormalsInvalid[9]; // Which normals are invalid - BOOL mDirty; - BOOL mDirtyZStats; - BOOL mHeightsGenerated; + BOOL mDirty; + BOOL mDirtyZStats; + BOOL mHeightsGenerated; - U32 mDataOffset; - F32 *mDataZ; - LLVector3 *mDataNorm; + U32 mDataOffset; + F32 *mDataZ; + LLVector3 *mDataNorm; - // Pointer to the LLVOSurfacePatch object which is used in the new renderer. - LLPointer mVObjp; + // Pointer to the LLVOSurfacePatch object which is used in the new renderer. + LLPointer mVObjp; - // All of the camera-dependent stuff should be in its own class... - LLPatchVisibilityInfo mVisInfo; + // All of the camera-dependent stuff should be in its own class... + LLPatchVisibilityInfo mVisInfo; - // pointers to beginnings of patch data fields - LLVector3d mOriginGlobal; - LLVector3 mOriginRegion; + // pointers to beginnings of patch data fields + LLVector3d mOriginGlobal; + LLVector3 mOriginRegion; - // height field stats - LLVector3 mCenterRegion; // Center in region-local coords - F32 mMinZ, mMaxZ, mMeanZ; - F32 mRadius; + // height field stats + LLVector3 mCenterRegion; // Center in region-local coords + F32 mMinZ, mMaxZ, mMeanZ; + F32 mRadius; - F32 mMinComposition; - F32 mMaxComposition; - F32 mMeanComposition; + F32 mMinComposition; + F32 mMaxComposition; + F32 mMeanComposition; - U8 mConnectedEdge; // This flag is non-zero iff patch is on at least one edge - // of LLSurface that is "connected" to another LLSurface - U64 mLastUpdateTime; // Time patch was last updated + U8 mConnectedEdge; // This flag is non-zero iff patch is on at least one edge + // of LLSurface that is "connected" to another LLSurface + U64 mLastUpdateTime; // Time patch was last updated - LLSurface *mSurfacep; // Pointer to "parent" surface + LLSurface *mSurfacep; // Pointer to "parent" surface }; extern template void LLSurfacePatch::updateNormals(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 91c2755ea5..4744edd5a3 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1,4 +1,4 @@ -/** +/** * @file lltexturectrl.cpp * @author Richard Nelson, James Cook * @brief LLTextureCtrl class implementation including related functions @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -49,7 +49,7 @@ #include "llmaterialeditor.h" #include "llui.h" #include "llviewerinventory.h" -#include "llviewermenufile.h" // LLFilePickerReplyThread +#include "llviewermenufile.h" // LLFilePickerReplyThread #include "llpermissions.h" #include "llpreviewtexture.h" #include "llsaleinfo.h" @@ -105,7 +105,7 @@ LLUUID get_copy_free_item_by_asset_id(LLUUID asset_id, bool no_trans_perm) items, LLInventoryModel::INCLUDE_TRASH, asset_id_matches); - + LLUUID res; if (items.size()) { @@ -143,53 +143,53 @@ bool get_can_copy_texture(LLUUID asset_id) S32 LLFloaterTexturePicker::sLastPickerMode = 0; -LLFloaterTexturePicker::LLFloaterTexturePicker( - LLView* owner, - LLUUID image_asset_id, - LLUUID default_image_asset_id, - LLUUID blank_image_asset_id, - BOOL tentative, - BOOL allow_no_texture, - const std::string& label, - PermissionMask immediate_filter_perm_mask, - PermissionMask dnd_filter_perm_mask, - BOOL can_apply_immediately, - LLUIImagePtr fallback_image, +LLFloaterTexturePicker::LLFloaterTexturePicker( + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, + const std::string& label, + PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, + BOOL can_apply_immediately, + LLUIImagePtr fallback_image, EPickInventoryType pick_type) -: LLFloater(LLSD()), - mOwner( owner ), - mImageAssetID( image_asset_id ), - mOriginalImageAssetID(image_asset_id), - mFallbackImage(fallback_image), - mDefaultImageAssetID(default_image_asset_id), - mBlankImageAssetID(blank_image_asset_id), - mTentative(tentative), - mAllowNoTexture(allow_no_texture), - mLabel(label), - mTentativeLabel(NULL), - mResolutionLabel(NULL), - mActive( TRUE ), - mFilterEdit(NULL), - mImmediateFilterPermMask(immediate_filter_perm_mask), - mDnDFilterPermMask(dnd_filter_perm_mask), - mContextConeOpacity(0.f), - mSelectedItemPinned( FALSE ), - mCanApply(true), - mCanPreview(true), +: LLFloater(LLSD()), + mOwner( owner ), + mImageAssetID( image_asset_id ), + mOriginalImageAssetID(image_asset_id), + mFallbackImage(fallback_image), + mDefaultImageAssetID(default_image_asset_id), + mBlankImageAssetID(blank_image_asset_id), + mTentative(tentative), + mAllowNoTexture(allow_no_texture), + mLabel(label), + mTentativeLabel(NULL), + mResolutionLabel(NULL), + mActive( TRUE ), + mFilterEdit(NULL), + mImmediateFilterPermMask(immediate_filter_perm_mask), + mDnDFilterPermMask(dnd_filter_perm_mask), + mContextConeOpacity(0.f), + mSelectedItemPinned( FALSE ), + mCanApply(true), + mCanPreview(true), mLimitsSet(false), mMaxDim(S32_MAX), mMinDim(0), - mPreviewSettingChanged(false), - mOnFloaterCommitCallback(NULL), - mOnFloaterCloseCallback(NULL), - mSetImageAssetIDCallback(NULL), - mOnUpdateImageStatsCallback(NULL), - mBakeTextureEnabled(FALSE), + mPreviewSettingChanged(false), + mOnFloaterCommitCallback(NULL), + mOnFloaterCloseCallback(NULL), + mSetImageAssetIDCallback(NULL), + mOnUpdateImageStatsCallback(NULL), + mBakeTextureEnabled(FALSE), mInventoryPickType(pick_type) { - mCanApplyImmediately = can_apply_immediately; - buildFromFile("floater_texture_ctrl.xml"); - setCanMinimize(FALSE); + mCanApplyImmediately = can_apply_immediately; + buildFromFile("floater_texture_ctrl.xml"); + setCanMinimize(FALSE); } LLFloaterTexturePicker::~LLFloaterTexturePicker() @@ -198,27 +198,27 @@ LLFloaterTexturePicker::~LLFloaterTexturePicker() void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selection /*=true*/) { - if( ((mImageAssetID != image_id) || mTentative) && mActive) - { - mNoCopyTextureSelected = FALSE; - mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - mImageAssetID = image_id; - - if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) - { - if ( mBakeTextureEnabled && mModeSelector->getValue().asInteger() != 2) - { - mModeSelector->selectByValue(2); - onModeSelect(0,this); - } - } - else - { - if (mModeSelector->getValue().asInteger() == 2) - { - mModeSelector->selectByValue(0); - onModeSelect(0,this); - } + if( ((mImageAssetID != image_id) || mTentative) && mActive) + { + mNoCopyTextureSelected = FALSE; + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + mImageAssetID = image_id; + + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + if ( mBakeTextureEnabled && mModeSelector->getValue().asInteger() != 2) + { + mModeSelector->selectByValue(2); + onModeSelect(0,this); + } + } + else + { + if (mModeSelector->getValue().asInteger() == 2) + { + mModeSelector->selectByValue(0); + onModeSelect(0,this); + } LLUUID item_id; LLFolderView* root_folder = mInventoryPanel->getRootFolder(); @@ -244,27 +244,27 @@ void LLFloaterTexturePicker::setImageID(const LLUUID& image_id, bool set_selecti { item_id = findItemID(mImageAssetID, FALSE); } - if (item_id.isNull()) - { - mInventoryPanel->getRootFolder()->clearSelection(); - } - else - { - LLInventoryItem* itemp = gInventory.getItem(item_id); - if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - // no copy texture - getChild("apply_immediate_check")->setValue(FALSE); - mNoCopyTextureSelected = TRUE; - } - } - - if (set_selection) - { - mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); - } - } - } + if (item_id.isNull()) + { + mInventoryPanel->getRootFolder()->clearSelection(); + } + else + { + LLInventoryItem* itemp = gInventory.getItem(item_id); + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + // no copy texture + getChild("apply_immediate_check")->setValue(FALSE); + mNoCopyTextureSelected = TRUE; + } + } + + if (set_selection) + { + mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO); + } + } + } } void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bool set_selection) @@ -278,18 +278,18 @@ void LLFloaterTexturePicker::setImageIDFromItem(const LLInventoryItem* itemp, bo setImageID(asset_id, set_selection); } -void LLFloaterTexturePicker::setActive( BOOL active ) +void LLFloaterTexturePicker::setActive( BOOL active ) { - if (!active && getChild("Pipette")->getValue().asBoolean()) - { - stopUsingPipette(); - } - mActive = active; + if (!active && getChild("Pipette")->getValue().asBoolean()) + { + stopUsingPipette(); + } + mActive = active; } void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) { - mCanApplyImmediately = b; + mCanApplyImmediately = b; LLUICtrl *apply_checkbox = getChild("apply_immediate_check"); apply_checkbox->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")); @@ -298,10 +298,10 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) void LLFloaterTexturePicker::stopUsingPipette() { - if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()) - { - LLToolMgr::getInstance()->clearTransientTool(); - } + if (LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()) + { + LLToolMgr::getInstance()->clearTransientTool(); + } } bool LLFloaterTexturePicker::updateImageStats() @@ -359,13 +359,13 @@ bool LLFloaterTexturePicker::updateImageStats() mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("")); } } - else if (mTexturep.notNull()) - { - //RN: have we received header data for this image? + else if (mTexturep.notNull()) + { + //RN: have we received header data for this image? S32 width = mTexturep->getFullWidth(); S32 height = mTexturep->getFullHeight(); - if (width > 0 && height > 0) - { + if (width > 0 && height > 0) + { if ((mLimitsSet && (width != height)) || width < mMinDim || width > mMaxDim @@ -387,16 +387,16 @@ bool LLFloaterTexturePicker::updateImageStats() { mOnUpdateImageStatsCallback(mTexturep); } - } - else - { - mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]")); - } - } - else - { - mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("")); - } + } + else + { + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("[? x ?]")); + } + } + else + { + mResolutionLabel->setTextArg("[DIMENSIONS]", std::string("")); + } mResolutionLabel->setVisible(result); mResolutionWarning->setVisible(!result); @@ -415,16 +415,16 @@ bool LLFloaterTexturePicker::updateImageStats() } // virtual -BOOL LLFloaterTexturePicker::handleDragAndDrop( - S32 x, S32 y, MASK mask, - BOOL drop, - EDragAndDropType cargo_type, void *cargo_data, - EAcceptance *accept, - std::string& tooltip_msg) +BOOL LLFloaterTexturePicker::handleDragAndDrop( + S32 x, S32 y, MASK mask, + BOOL drop, + EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) { - BOOL handled = FALSE; + BOOL handled = FALSE; - bool is_mesh = cargo_type == DAD_MESH; + bool is_mesh = cargo_type == DAD_MESH; bool is_texture = cargo_type == DAD_TEXTURE; bool is_material = cargo_type == DAD_MATERIAL; @@ -442,83 +442,83 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( allow_dnd = is_texture || is_mesh || is_material; } - if (allow_dnd) - { - LLInventoryItem *item = (LLInventoryItem *)cargo_data; - - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - - PermissionMask item_perm_mask = 0; - if (copy) item_perm_mask |= PERM_COPY; - if (mod) item_perm_mask |= PERM_MODIFY; - if (xfer) item_perm_mask |= PERM_TRANSFER; - - PermissionMask filter_perm_mask = mDnDFilterPermMask; - if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) - { - if (drop) - { + if (allow_dnd) + { + LLInventoryItem *item = (LLInventoryItem *)cargo_data; + + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + PermissionMask item_perm_mask = 0; + if (copy) item_perm_mask |= PERM_COPY; + if (mod) item_perm_mask |= PERM_MODIFY; + if (xfer) item_perm_mask |= PERM_TRANSFER; + + PermissionMask filter_perm_mask = mDnDFilterPermMask; + if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) + { + if (drop) + { setImageIDFromItem(item); - commitIfImmediateSet(); - } + commitIfImmediateSet(); + } - *accept = ACCEPT_YES_SINGLE; - } - else - { - *accept = ACCEPT_NO; - } - } - else - { - *accept = ACCEPT_NO; - } + *accept = ACCEPT_YES_SINGLE; + } + else + { + *accept = ACCEPT_NO; + } + } + else + { + *accept = ACCEPT_NO; + } - handled = TRUE; - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << LL_ENDL; + handled = TRUE; + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << LL_ENDL; - return handled; + return handled; } BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { - LLFolderView* root_folder = mInventoryPanel->getRootFolder(); - - if (root_folder && mFilterEdit) - { - if (mFilterEdit->hasFocus() - && (key == KEY_RETURN || key == KEY_DOWN) - && mask == MASK_NONE) - { - if (!root_folder->getCurSelectedItem()) - { - LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID()); - if (itemp) - { - root_folder->setSelection(itemp, FALSE, FALSE); - } - } - root_folder->scrollToShowSelection(); - - // move focus to inventory proper - mInventoryPanel->setFocus(TRUE); - - // treat this as a user selection of the first filtered result - commitIfImmediateSet(); - - return TRUE; - } - - if (mInventoryPanel->hasFocus() && key == KEY_UP) - { - mFilterEdit->focusFirstItem(TRUE); - } - } - - return LLFloater::handleKeyHere(key, mask); + LLFolderView* root_folder = mInventoryPanel->getRootFolder(); + + if (root_folder && mFilterEdit) + { + if (mFilterEdit->hasFocus() + && (key == KEY_RETURN || key == KEY_DOWN) + && mask == MASK_NONE) + { + if (!root_folder->getCurSelectedItem()) + { + LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID()); + if (itemp) + { + root_folder->setSelection(itemp, FALSE, FALSE); + } + } + root_folder->scrollToShowSelection(); + + // move focus to inventory proper + mInventoryPanel->setFocus(TRUE); + + // treat this as a user selection of the first filtered result + commitIfImmediateSet(); + + return TRUE; + } + + if (mInventoryPanel->hasFocus() && key == KEY_UP) + { + mFilterEdit->focusFirstItem(TRUE); + } + } + + return LLFloater::handleKeyHere(key, mask); } void LLFloaterTexturePicker::onOpen(const LLSD& key) @@ -532,11 +532,11 @@ void LLFloaterTexturePicker::onOpen(const LLSD& key) void LLFloaterTexturePicker::onClose(bool app_quitting) { - if (mOwner && mOnFloaterCloseCallback) - { - mOnFloaterCloseCallback(); - } - stopUsingPipette(); + if (mOwner && mOnFloaterCloseCallback) + { + mOnFloaterCloseCallback(); + } + stopUsingPipette(); sLastPickerMode = mModeSelector->getValue().asInteger(); // *NOTE: Vertex buffer for sphere preview is still cached mGLTFPreview = nullptr; @@ -545,17 +545,17 @@ void LLFloaterTexturePicker::onClose(bool app_quitting) // virtual BOOL LLFloaterTexturePicker::postBuild() { - LLFloater::postBuild(); + LLFloater::postBuild(); - if (!mLabel.empty()) - { - std::string pick = getString("pick title"); - - setTitle(pick + mLabel); - } - mTentativeLabel = getChild("Multiple"); + if (!mLabel.empty()) + { + std::string pick = getString("pick title"); - mResolutionLabel = getChild("size_lbl"); + setTitle(pick + mLabel); + } + mTentativeLabel = getChild("Multiple"); + + mResolutionLabel = getChild("size_lbl"); mResolutionWarning = getChild("over_limit_lbl"); @@ -576,70 +576,70 @@ BOOL LLFloaterTexturePicker::postBuild() mFilterEdit = getChild("inventory search editor"); mFilterEdit->setCommitCallback(boost::bind(&LLFloaterTexturePicker::onFilterEdit, this, _2)); - mInventoryPanel = getChild("inventory panel"); + mInventoryPanel = getChild("inventory panel"); - mModeSelector = getChild("mode_selection"); - mModeSelector->setCommitCallback(onModeSelect, this); - mModeSelector->selectByValue(0); + mModeSelector = getChild("mode_selection"); + mModeSelector->setCommitCallback(onModeSelect, this); + mModeSelector->selectByValue(0); - if(mInventoryPanel) - { + if(mInventoryPanel) + { // to avoid having to make an assumption about which option is // selected at startup, we call the same function that is triggered // when a texture/materials/both choice is made and let it take care // of setting the filters refreshInventoryFilter(); - mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); - mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2)); - mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); + mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask); + mInventoryPanel->setSelectCallback(boost::bind(&LLFloaterTexturePicker::onSelectionChange, this, _1, _2)); + mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - // Disable auto selecting first filtered item because it takes away - // selection from the item set by LLTextureCtrl owning this floater. - mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE); + // Disable auto selecting first filtered item because it takes away + // selection from the item set by LLTextureCtrl owning this floater. + mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE); - // Commented out to scroll to currently selected texture. See EXT-5403. - // // store this filter as the default one - // mInventoryPanel->getRootFolder()->getFilter().markDefault(); + // Commented out to scroll to currently selected texture. See EXT-5403. + // // store this filter as the default one + // mInventoryPanel->getRootFolder()->getFilter().markDefault(); - // Commented out to stop opening all folders with textures - // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); + // Commented out to stop opening all folders with textures + // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE); - // don't put keyboard focus on selected item, because the selection callback - // will assume that this was user input + // don't put keyboard focus on selected item, because the selection callback + // will assume that this was user input - if(!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL) - { - mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); - } - } + if(!mImageAssetID.isNull() || mInventoryPickType == PICK_MATERIAL) + { + mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO); + } + } - childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this); - childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this); - childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this); + childSetAction("l_add_btn", LLFloaterTexturePicker::onBtnAdd, this); + childSetAction("l_rem_btn", LLFloaterTexturePicker::onBtnRemove, this); + childSetAction("l_upl_btn", LLFloaterTexturePicker::onBtnUpload, this); - mLocalScrollCtrl = getChild("l_name_list"); - mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this); + mLocalScrollCtrl = getChild("l_name_list"); + mLocalScrollCtrl->setCommitCallback(onLocalScrollCommit, this); refreshLocalList(); - mNoCopyTextureSelected = FALSE; + mNoCopyTextureSelected = FALSE; - getChild("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")); - childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); + getChild("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")); + childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this); getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately); - getChild("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); - childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); - childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); + getChild("Pipette")->setCommitCallback( boost::bind(&LLFloaterTexturePicker::onBtnPipette, this)); + childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this); + childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this); + + mSavedFolderState.setApply(FALSE); - mSavedFolderState.setApply(FALSE); + LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); - LLToolPipette::getInstance()->setToolSelectCallback(boost::bind(&LLFloaterTexturePicker::onTextureSelect, this, _1)); - - getChild("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this); + getChild("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this); - setBakeTextureEnabled(TRUE); - return TRUE; + setBakeTextureEnabled(TRUE); + return TRUE; } // virtual @@ -650,18 +650,18 @@ void LLFloaterTexturePicker::draw() // This is going to spam mOnUpdateImageStatsCallback, // either move elsewhere or fix to cause update once per image - bool valid_dims = updateImageStats(); + bool valid_dims = updateImageStats(); - // if we're inactive, gray out "apply immediate" checkbox - getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); - mSelectBtn->setEnabled(mActive && mCanApply && valid_dims); - mPipetteBtn->setEnabled(mActive); + // if we're inactive, gray out "apply immediate" checkbox + getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); + mSelectBtn->setEnabled(mActive && mCanApply && valid_dims); + mPipetteBtn->setEnabled(mActive); mPipetteBtn->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); - //BOOL allow_copy = FALSE; - if( mOwner ) - { - mTexturep = NULL; + //BOOL allow_copy = FALSE; + if( mOwner ) + { + mTexturep = NULL; LLPointer old_material = mGLTFMaterial; mGLTFMaterial = NULL; if (mImageAssetID.notNull()) @@ -700,7 +700,7 @@ void LLFloaterTexturePicker::draw() if (obj) { LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); - texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + texture = viewerTexture ? dynamic_cast(viewerTexture) : NULL; } } @@ -714,33 +714,33 @@ void LLFloaterTexturePicker::draw() } } - if (mTentativeLabel) - { - mTentativeLabel->setVisible( FALSE ); - } + if (mTentativeLabel) + { + mTentativeLabel->setVisible( FALSE ); + } - mDefaultBtn->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); - mBlankBtn->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative); - mNoneBtn->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative)); + mDefaultBtn->setEnabled(mImageAssetID != mDefaultImageAssetID || mTentative); + mBlankBtn->setEnabled((mImageAssetID != mBlankImageAssetID && mBlankImageAssetID.notNull()) || mTentative); + mNoneBtn->setEnabled(mAllowNoTexture && (!mImageAssetID.isNull() || mTentative)); - LLFloater::draw(); + LLFloater::draw(); - if( isMinimized() ) - { - return; - } + if( isMinimized() ) + { + return; + } - // Border - LLRect border = getChildView("preview_widget")->getRect(); - gl_rect_2d( border, LLColor4::black, FALSE ); + // Border + LLRect border = getChildView("preview_widget")->getRect(); + gl_rect_2d( border, LLColor4::black, FALSE ); - // Interior - LLRect interior = border; - interior.stretch( -1 ); + // Interior + LLRect interior = border; + interior.stretch( -1 ); - // If the floater is focused, don't apply its alpha to the texture (STORM-677). - const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + // If the floater is focused, don't apply its alpha to the texture (STORM-677). + const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); LLViewerTexture* preview; if (mGLTFMaterial) { @@ -751,66 +751,66 @@ void LLFloaterTexturePicker::draw() preview = mTexturep.get(); } - if( preview ) - { + if( preview ) + { preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); - if( preview->getComponents() == 4 ) - { - gl_rect_2d_checkerboard( interior, alpha ); - } - - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha ); - } - else if (!mFallbackImage.isNull()) - { - mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); - } - else - { - gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); - - // Draw X - gl_draw_x(interior, LLColor4::black ); - } - - // Draw Tentative Label over the image - if( mTentative && !mViewModel->isDirty() ) - { - mTentativeLabel->setVisible( TRUE ); - drawChild(mTentativeLabel); - } - - if (mSelectedItemPinned) return; - - LLFolderView* folder_view = mInventoryPanel->getRootFolder(); - if (!folder_view) return; - - LLFolderViewFilter& filter = static_cast(folder_view->getFolderViewModel())->getFilter(); - - bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && - filter.isNotDefault(); - - // After inventory panel filter is applied we have to update - // constraint rect for the selected item because of folder view - // AutoSelectOverride set to TRUE. We force PinningSelectedItem - // flag to FALSE state and setting filter "dirty" to update - // scroll container to show selected item (see LLFolderView::doIdle()). - if (!is_filter_active && !mSelectedItemPinned) - { - folder_view->setPinningSelectedItem(mSelectedItemPinned); - folder_view->getViewModelItem()->dirtyFilter(); - mSelectedItemPinned = TRUE; - } - } + if( preview->getComponents() == 4 ) + { + gl_rect_2d_checkerboard( interior, alpha ); + } + + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha ); + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); + } + else + { + gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); + + // Draw X + gl_draw_x(interior, LLColor4::black ); + } + + // Draw Tentative Label over the image + if( mTentative && !mViewModel->isDirty() ) + { + mTentativeLabel->setVisible( TRUE ); + drawChild(mTentativeLabel); + } + + if (mSelectedItemPinned) return; + + LLFolderView* folder_view = mInventoryPanel->getRootFolder(); + if (!folder_view) return; + + LLFolderViewFilter& filter = static_cast(folder_view->getFolderViewModel())->getFilter(); + + bool is_filter_active = folder_view->getViewModelItem()->getLastFilterGeneration() < filter.getCurrentGeneration() && + filter.isNotDefault(); + + // After inventory panel filter is applied we have to update + // constraint rect for the selected item because of folder view + // AutoSelectOverride set to TRUE. We force PinningSelectedItem + // flag to FALSE state and setting filter "dirty" to update + // scroll container to show selected item (see LLFolderView::doIdle()). + if (!is_filter_active && !mSelectedItemPinned) + { + folder_view->setPinningSelectedItem(mSelectedItemPinned); + folder_view->getViewModelItem()->dirtyFilter(); + mSelectedItemPinned = TRUE; + } + } } const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library) { - if (asset_id.isNull()) - { + if (asset_id.isNull()) + { // null asset id means, no material or texture assigned return LLUUID::null; - } + } LLUUID loockup_id = asset_id; if (mInventoryPickType == PICK_MATERIAL && loockup_id == BLANK_MATERIAL_ASSET_ID) @@ -819,8 +819,8 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co loockup_id = LLUUID::null; } - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; if (loockup_id.isNull()) { @@ -844,44 +844,44 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co } - if (items.size()) - { - // search for copyable version first - for (S32 i = 0; i < items.size(); i++) - { - LLInventoryItem* itemp = items[i]; - LLPermissions item_permissions = itemp->getPermissions(); - if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) - { - if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID())) - { - return itemp->getUUID(); - } - } - } - // otherwise just return first instance, unless copyable requested - if (copyable_only) - { - return LLUUID::null; - } - else - { - if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID())) - { - return items[0]->getUUID(); - } - } - } - - return LLUUID::null; + if (items.size()) + { + // search for copyable version first + for (S32 i = 0; i < items.size(); i++) + { + LLInventoryItem* itemp = items[i]; + LLPermissions item_permissions = itemp->getPermissions(); + if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + { + if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID())) + { + return itemp->getUUID(); + } + } + } + // otherwise just return first instance, unless copyable requested + if (copyable_only) + { + return LLUUID::null; + } + else + { + if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID())) + { + return items[0]->getUUID(); + } + } + } + + return LLUUID::null; } void LLFloaterTexturePicker::commitIfImmediateSet() { - if (!mNoCopyTextureSelected && mCanApply) - { + if (!mNoCopyTextureSelected && mCanApply) + { commitCallback(LLTextureCtrl::TEXTURE_CHANGE); - } + } } void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) @@ -963,40 +963,40 @@ void LLFloaterTexturePicker::commitCallback(LLTextureCtrl::ETexturePickOp op) } void LLFloaterTexturePicker::commitCancel() { - if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) - { - mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null, LLUUID::null); - } + if (!mNoCopyTextureSelected && mOnFloaterCommitCallback && mCanApply) + { + mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, mOriginalImageAssetID, LLUUID::null, LLUUID::null); + } } // static void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - self->setCanApply(true, true); - if (self->mOwner) - { - self->setImageID( self->getDefaultImageAssetID() ); - } - self->commitIfImmediateSet(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); + if (self->mOwner) + { + self->setImageID( self->getDefaultImageAssetID() ); + } + self->commitIfImmediateSet(); } // static void LLFloaterTexturePicker::onBtnBlank(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - self->setCanApply(true, true); - self->setImageID( self->getBlankImageAssetID() ); - self->commitIfImmediateSet(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); + self->setImageID( self->getBlankImageAssetID() ); + self->commitIfImmediateSet(); } // static void LLFloaterTexturePicker::onBtnNone(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; self->setCanApply(true, true); - self->setImageID( LLUUID::null ); + self->setImageID( LLUUID::null ); self->commitIfImmediateSet(); } @@ -1004,88 +1004,88 @@ void LLFloaterTexturePicker::onBtnNone(void* userdata) // static void LLFloaterTexturePicker::onBtnRevert(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - self->setImageID( self->mOriginalImageAssetID ); - // TODO: Change this to tell the owner to cancel. It needs to be - // smart enough to restore multi-texture selections. - self->mOwner->onFloaterCommit(); - self->mViewModel->resetDirty(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( self->mOriginalImageAssetID ); + // TODO: Change this to tell the owner to cancel. It needs to be + // smart enough to restore multi-texture selections. + self->mOwner->onFloaterCommit(); + self->mViewModel->resetDirty(); }*/ // static void LLFloaterTexturePicker::onBtnCancel(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - self->setImageID( self->mOriginalImageAssetID ); - if (self->mOnFloaterCommitCallback) - { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null, LLUUID::null); - } - self->mViewModel->resetDirty(); - self->closeFloater(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setImageID( self->mOriginalImageAssetID ); + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CANCEL, PICKER_UNKNOWN, self->mOriginalImageAssetID, LLUUID::null, LLUUID::null); + } + self->mViewModel->resetDirty(); + self->closeFloater(); } // static void LLFloaterTexturePicker::onBtnSelect(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - if (self->mOnFloaterCommitCallback) - { - self->commitCallback(LLTextureCtrl::TEXTURE_SELECT); - } - self->closeFloater(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + if (self->mOnFloaterCommitCallback) + { + self->commitCallback(LLTextureCtrl::TEXTURE_SELECT); + } + self->closeFloater(); } void LLFloaterTexturePicker::onBtnPipette() { - BOOL pipette_active = getChild("Pipette")->getValue().asBoolean(); - pipette_active = !pipette_active; - if (pipette_active) - { - LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); - } - else - { - LLToolMgr::getInstance()->clearTransientTool(); - } + BOOL pipette_active = getChild("Pipette")->getValue().asBoolean(); + pipette_active = !pipette_active; + if (pipette_active) + { + LLToolMgr::getInstance()->setTransientTool(LLToolPipette::getInstance()); + } + else + { + LLToolMgr::getInstance()->clearTransientTool(); + } } void LLFloaterTexturePicker::onSelectionChange(const std::deque &items, BOOL user_action) { - if (items.size()) - { - LLFolderViewItem* first_item = items.front(); - LLInventoryItem* itemp = gInventory.getItem(static_cast(first_item->getViewModelItem())->getUUID()); - mNoCopyTextureSelected = FALSE; - if (itemp) - { - if (!mTextureSelectedCallback.empty()) - { - mTextureSelectedCallback(itemp); - } - if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - mNoCopyTextureSelected = TRUE; - } + if (items.size()) + { + LLFolderViewItem* first_item = items.front(); + LLInventoryItem* itemp = gInventory.getItem(static_cast(first_item->getViewModelItem())->getUUID()); + mNoCopyTextureSelected = FALSE; + if (itemp) + { + if (!mTextureSelectedCallback.empty()) + { + mTextureSelectedCallback(itemp); + } + if (!itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + mNoCopyTextureSelected = TRUE; + } setImageIDFromItem(itemp, false); - mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - - if(!mPreviewSettingChanged) - { - mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"); - } - else - { - mPreviewSettingChanged = false; - } - - if (user_action && mCanPreview) - { - // only commit intentional selections, not implicit ones - commitIfImmediateSet(); - } - } - } + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if(!mPreviewSettingChanged) + { + mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"); + } + else + { + mPreviewSettingChanged = false; + } + + if (user_action && mCanPreview) + { + // only commit intentional selections, not implicit ones + commitIfImmediateSet(); + } + } + } } // static @@ -1117,18 +1117,18 @@ void LLFloaterTexturePicker::onBtnAdd(void* userdata) // static void LLFloaterTexturePicker::onBtnRemove(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); - if (!selected_items.empty()) - { + if (!selected_items.empty()) + { - for(std::vector::iterator iter = selected_items.begin(); - iter != selected_items.end(); iter++) - { - LLScrollListItem* list_item = *iter; - if (list_item) - { + for(std::vector::iterator iter = selected_items.begin(); + iter != selected_items.end(); iter++) + { + LLScrollListItem* list_item = *iter; + if (list_item) + { LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); LLUUID tracking_id = data["id"]; S32 asset_type = data["type"].asInteger(); @@ -1141,28 +1141,28 @@ void LLFloaterTexturePicker::onBtnRemove(void* userdata) { LLLocalBitmapMgr::getInstance()->delUnit(tracking_id); } - } - } + } + } - self->getChild("l_rem_btn")->setEnabled(false); - self->getChild("l_upl_btn")->setEnabled(false); + self->getChild("l_rem_btn")->setEnabled(false); + self->getChild("l_upl_btn")->setEnabled(false); self->refreshLocalList(); - } + } } // static void LLFloaterTexturePicker::onBtnUpload(void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); - if (selected_items.empty()) - { - return; - } + if (selected_items.empty()) + { + return; + } - /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!) - in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */ + /* currently only allows uploading one by one, picks the first item from the selection list. (not the vector!) + in the future, it might be a good idea to check the vector size and if more than one units is selected - opt for multi-image upload. */ LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); LLUUID tracking_id = data["id"]; @@ -1191,16 +1191,16 @@ void LLFloaterTexturePicker::onBtnUpload(void* userdata) //static void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; - std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); - bool has_selection = !selected_items.empty(); + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + std::vector selected_items = self->mLocalScrollCtrl->getAllSelected(); + bool has_selection = !selected_items.empty(); - self->getChild("l_rem_btn")->setEnabled(has_selection); - self->getChild("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2)); - /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */ + self->getChild("l_rem_btn")->setEnabled(has_selection); + self->getChild("l_upl_btn")->setEnabled(has_selection && (selected_items.size() < 2)); + /* since multiple-localbitmap upload is not implemented, upl button gets disabled if more than one is selected. */ - if (has_selection) - { + if (has_selection) + { LLSD data = self->mLocalScrollCtrl->getFirstSelected()->getValue(); LLUUID tracking_id = data["id"]; S32 asset_type = data["type"].asInteger(); @@ -1215,114 +1215,114 @@ void LLFloaterTexturePicker::onLocalScrollCommit(LLUICtrl* ctrl, void* userdata) inworld_id = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); } - if (self->mSetImageAssetIDCallback) - { - self->mSetImageAssetIDCallback(inworld_id); - } + if (self->mSetImageAssetIDCallback) + { + self->mSetImageAssetIDCallback(inworld_id); + } - if (self->childGetValue("apply_immediate_check").asBoolean()) - { - if (self->mOnFloaterCommitCallback) - { - self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null, tracking_id); - } - } - } + if (self->childGetValue("apply_immediate_check").asBoolean()) + { + if (self->mOnFloaterCommitCallback) + { + self->mOnFloaterCommitCallback(LLTextureCtrl::TEXTURE_CHANGE, PICKER_LOCAL, inworld_id, LLUUID::null, tracking_id); + } + } + } } // static void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data) { - LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; + LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; - LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; - gSavedSettings.setBOOL("TextureLivePreview", check_box->get()); + LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; + gSavedSettings.setBOOL("TextureLivePreview", check_box->get()); - picker->commitIfImmediateSet(); + picker->commitIfImmediateSet(); } //static void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data) { - LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)user_data; - LLComboBox* combo_box = (LLComboBox*)ctrl; - - S8 type = combo_box->getValue().asInteger(); - - LLUUID imageID = self->mDefaultImageAssetID; - if (type == 0) - { - imageID = IMG_USE_BAKED_HEAD; - } - else if (type == 1) - { - imageID = IMG_USE_BAKED_UPPER; - } - else if (type == 2) - { - imageID = IMG_USE_BAKED_LOWER; - } - else if (type == 3) - { - imageID = IMG_USE_BAKED_EYES; - } - else if (type == 4) - { - imageID = IMG_USE_BAKED_SKIRT; - } - else if (type == 5) - { - imageID = IMG_USE_BAKED_HAIR; - } - else if (type == 6) - { - imageID = IMG_USE_BAKED_LEFTARM; - } - else if (type == 7) - { - imageID = IMG_USE_BAKED_LEFTLEG; - } - else if (type == 8) - { - imageID = IMG_USE_BAKED_AUX1; - } - else if (type == 9) - { - imageID = IMG_USE_BAKED_AUX2; - } - else if (type == 10) - { - imageID = IMG_USE_BAKED_AUX3; - } - - self->setImageID(imageID); - self->mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - - if (!self->mPreviewSettingChanged) - { - self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"); - } - else - { - self->mPreviewSettingChanged = false; - } - - if (self->mCanPreview) - { - // only commit intentional selections, not implicit ones - self->commitIfImmediateSet(); - } + LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)user_data; + LLComboBox* combo_box = (LLComboBox*)ctrl; + + S8 type = combo_box->getValue().asInteger(); + + LLUUID imageID = self->mDefaultImageAssetID; + if (type == 0) + { + imageID = IMG_USE_BAKED_HEAD; + } + else if (type == 1) + { + imageID = IMG_USE_BAKED_UPPER; + } + else if (type == 2) + { + imageID = IMG_USE_BAKED_LOWER; + } + else if (type == 3) + { + imageID = IMG_USE_BAKED_EYES; + } + else if (type == 4) + { + imageID = IMG_USE_BAKED_SKIRT; + } + else if (type == 5) + { + imageID = IMG_USE_BAKED_HAIR; + } + else if (type == 6) + { + imageID = IMG_USE_BAKED_LEFTARM; + } + else if (type == 7) + { + imageID = IMG_USE_BAKED_LEFTLEG; + } + else if (type == 8) + { + imageID = IMG_USE_BAKED_AUX1; + } + else if (type == 9) + { + imageID = IMG_USE_BAKED_AUX2; + } + else if (type == 10) + { + imageID = IMG_USE_BAKED_AUX3; + } + + self->setImageID(imageID); + self->mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if (!self->mPreviewSettingChanged) + { + self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"); + } + else + { + self->mPreviewSettingChanged = false; + } + + if (self->mCanPreview) + { + // only commit intentional selections, not implicit ones + self->commitIfImmediateSet(); + } } void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply, bool inworld_image) { - mSelectBtn->setEnabled(can_apply); - getChildRef("preview_disabled").setVisible(!can_preview && inworld_image); - getChildRef("apply_immediate_check").setVisible(can_preview); + mSelectBtn->setEnabled(can_apply); + getChildRef("preview_disabled").setVisible(!can_preview && inworld_image); + getChildRef("apply_immediate_check").setVisible(can_preview); - mCanApply = can_apply; - mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false; - mPreviewSettingChanged = true; + mCanApply = can_apply; + mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false; + mPreviewSettingChanged = true; } void LLFloaterTexturePicker::setMinDimentionsLimits(S32 min_dim) @@ -1336,36 +1336,36 @@ void LLFloaterTexturePicker::setMinDimentionsLimits(S32 min_dim) void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { - std::string upper_case_search_string = search_string; - LLStringUtil::toUpper(upper_case_search_string); - - if (upper_case_search_string.empty()) - { - if (mInventoryPanel->getFilterSubString().empty()) - { - // current filter and new filter empty, do nothing - return; - } - - mSavedFolderState.setApply(TRUE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); - // add folder with current item to list of previously opened folders - LLOpenFoldersWithSelection opener; - mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); - mInventoryPanel->getRootFolder()->scrollToShowSelection(); - - } - else if (mInventoryPanel->getFilterSubString().empty()) - { - // first letter in search term, save existing folder open state - if (!mInventoryPanel->getFilter().isNotDefault()) - { - mSavedFolderState.setApply(FALSE); - mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); - } - } - - mInventoryPanel->setFilterSubString(search_string); + std::string upper_case_search_string = search_string; + LLStringUtil::toUpper(upper_case_search_string); + + if (upper_case_search_string.empty()) + { + if (mInventoryPanel->getFilterSubString().empty()) + { + // current filter and new filter empty, do nothing + return; + } + + mSavedFolderState.setApply(TRUE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); + // add folder with current item to list of previously opened folders + LLOpenFoldersWithSelection opener; + mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); + mInventoryPanel->getRootFolder()->scrollToShowSelection(); + + } + else if (mInventoryPanel->getFilterSubString().empty()) + { + // first letter in search term, save existing folder open state + if (!mInventoryPanel->getFilter().isNotDefault()) + { + mSavedFolderState.setApply(FALSE); + mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); + } + } + + mInventoryPanel->setFilterSubString(search_string); } void LLFloaterTexturePicker::changeMode() @@ -1495,24 +1495,24 @@ void LLFloaterTexturePicker::setLocalTextureEnabled(BOOL enabled) void LLFloaterTexturePicker::setBakeTextureEnabled(BOOL enabled) { - BOOL changed = (enabled != mBakeTextureEnabled); + BOOL changed = (enabled != mBakeTextureEnabled); + + mBakeTextureEnabled = enabled; + mModeSelector->setEnabledByValue(2, enabled); - mBakeTextureEnabled = enabled; - mModeSelector->setEnabledByValue(2, enabled); + if (!mBakeTextureEnabled && (mModeSelector->getValue().asInteger() == 2)) + { + mModeSelector->selectByValue(0); + } - if (!mBakeTextureEnabled && (mModeSelector->getValue().asInteger() == 2)) - { - mModeSelector->selectByValue(0); - } - - if (changed && mBakeTextureEnabled && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) - { - if (mModeSelector->getValue().asInteger() != 2) - { - mModeSelector->selectByValue(2); - } - } - onModeSelect(0, this); + if (changed && mBakeTextureEnabled && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + if (mModeSelector->getValue().asInteger() != 2) + { + mModeSelector->selectByValue(2); + } + } + onModeSelect(0, this); } void LLFloaterTexturePicker::setInventoryPickType(EPickInventoryType type) @@ -1603,10 +1603,10 @@ void LLFloaterTexturePicker::onPickerCallback(const std::vector& fi void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) { - LLUUID inventory_item_id = findItemID(te.getID(), TRUE); - if (inventory_item_id.notNull()) - { - LLToolPipette::getInstance()->setResult(TRUE, ""); + LLUUID inventory_item_id = findItemID(te.getID(), TRUE); + if (inventory_item_id.notNull()) + { + LLToolPipette::getInstance()->setResult(TRUE, ""); if (mInventoryPickType == PICK_MATERIAL) { // tes have no data about material ids @@ -1619,21 +1619,21 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) setImageID(te.getID()); } - mNoCopyTextureSelected = FALSE; - LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); + mNoCopyTextureSelected = FALSE; + LLInventoryItem* itemp = gInventory.getItem(inventory_item_id); - if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - // no copy texture - mNoCopyTextureSelected = TRUE; - } - - commitIfImmediateSet(); - } - else - { - LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture")); - } + if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID())) + { + // no copy texture + mNoCopyTextureSelected = TRUE; + } + + commitIfImmediateSet(); + } + else + { + LLToolPipette::getInstance()->setResult(FALSE, LLTrans::getString("InventoryNoTexture")); + } } /////////////////////////////////////////////////////////////////////// @@ -1642,107 +1642,107 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) static LLDefaultChildRegistry::Register r("texture_picker"); LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p) -: LLUICtrl(p), - mDragCallback(NULL), - mDropCallback(NULL), - mOnCancelCallback(NULL), - mOnCloseCallback(NULL), - mOnSelectCallback(NULL), - mBorderColor( p.border_color() ), - mAllowNoTexture( p.allow_no_texture ), - mAllowLocalTexture( TRUE ), - mImmediateFilterPermMask( PERM_NONE ), - mCanApplyImmediately( FALSE ), - mNeedsRawImageData( FALSE ), - mValid( TRUE ), - mShowLoadingPlaceholder( TRUE ), - mOpenTexPreview(false), +: LLUICtrl(p), + mDragCallback(NULL), + mDropCallback(NULL), + mOnCancelCallback(NULL), + mOnCloseCallback(NULL), + mOnSelectCallback(NULL), + mBorderColor( p.border_color() ), + mAllowNoTexture( p.allow_no_texture ), + mAllowLocalTexture( TRUE ), + mImmediateFilterPermMask( PERM_NONE ), + mCanApplyImmediately( FALSE ), + mNeedsRawImageData( FALSE ), + mValid( TRUE ), + mShowLoadingPlaceholder( TRUE ), + mOpenTexPreview(false), mBakeTextureEnabled(true), mInventoryPickType(p.pick_type), - mImageAssetID(p.image_id), - mDefaultImageAssetID(p.default_image_id), - mDefaultImageName(p.default_image_name), - mFallbackImage(p.fallback_image) -{ - - // Default of defaults is white image for diff tex - // - setBlankImageAssetID(IMG_WHITE); - - setAllowNoTexture(p.allow_no_texture); - setCanApplyImmediately(p.can_apply_immediately); - mCommitOnSelection = !p.no_commit_on_selection; - - LLTextBox::Params params(p.caption_text); - params.name(p.label); - params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 )); - params.initial_value(p.label()); - params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); - mCaption = LLUICtrlFactory::create (params); - addChild( mCaption ); - - S32 image_top = getRect().getHeight(); - S32 image_bottom = BTN_HEIGHT_SMALL; - S32 image_middle = (image_top + image_bottom) / 2; - S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight(); - - LLTextBox::Params tentative_label_p(p.multiselect_text); - tentative_label_p.name("Multiple"); - tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 )); - tentative_label_p.follows.flags(FOLLOWS_ALL); - mTentativeLabel = LLUICtrlFactory::create (tentative_label_p); - - // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion - LLStyle::Params style_params; - style_params.color = LLColor4::white; - - mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params); - mTentativeLabel->setHAlign(LLFontGL::HCENTER); - addChild( mTentativeLabel ); - - LLRect border_rect = getLocalRect(); - border_rect.mBottom += BTN_HEIGHT_SMALL; - LLViewBorder::Params vbparams(p.border); - vbparams.name("border"); - vbparams.rect(border_rect); - mBorder = LLUICtrlFactory::create (vbparams); - addChild(mBorder); - - mLoadingPlaceholderString = LLTrans::getString("texture_loading"); + mImageAssetID(p.image_id), + mDefaultImageAssetID(p.default_image_id), + mDefaultImageName(p.default_image_name), + mFallbackImage(p.fallback_image) +{ + + // Default of defaults is white image for diff tex + // + setBlankImageAssetID(IMG_WHITE); + + setAllowNoTexture(p.allow_no_texture); + setCanApplyImmediately(p.can_apply_immediately); + mCommitOnSelection = !p.no_commit_on_selection; + + LLTextBox::Params params(p.caption_text); + params.name(p.label); + params.rect(LLRect( 0, BTN_HEIGHT_SMALL, getRect().getWidth(), 0 )); + params.initial_value(p.label()); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); + mCaption = LLUICtrlFactory::create (params); + addChild( mCaption ); + + S32 image_top = getRect().getHeight(); + S32 image_bottom = BTN_HEIGHT_SMALL; + S32 image_middle = (image_top + image_bottom) / 2; + S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight(); + + LLTextBox::Params tentative_label_p(p.multiselect_text); + tentative_label_p.name("Multiple"); + tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 )); + tentative_label_p.follows.flags(FOLLOWS_ALL); + mTentativeLabel = LLUICtrlFactory::create (tentative_label_p); + + // It is no longer possible to associate a style with a textbox, so it has to be done in this fashion + LLStyle::Params style_params; + style_params.color = LLColor4::white; + + mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params); + mTentativeLabel->setHAlign(LLFontGL::HCENTER); + addChild( mTentativeLabel ); + + LLRect border_rect = getLocalRect(); + border_rect.mBottom += BTN_HEIGHT_SMALL; + LLViewBorder::Params vbparams(p.border); + vbparams.name("border"); + vbparams.rect(border_rect); + mBorder = LLUICtrlFactory::create (vbparams); + addChild(mBorder); + + mLoadingPlaceholderString = LLTrans::getString("texture_loading"); } LLTextureCtrl::~LLTextureCtrl() { - closeDependentFloater(); + closeDependentFloater(); } void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder) { - mShowLoadingPlaceholder = showLoadingPlaceholder; + mShowLoadingPlaceholder = showLoadingPlaceholder; } void LLTextureCtrl::setCaption(const std::string& caption) { - mCaption->setText( caption ); + mCaption->setText( caption ); } void LLTextureCtrl::setCanApplyImmediately(BOOL b) { - mCanApplyImmediately = b; - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if( floaterp ) - { - floaterp->setCanApplyImmediately(b); - } + mCanApplyImmediately = b; + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp ) + { + floaterp->setCanApplyImmediately(b); + } } void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) { - LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); - if( floaterp ) - { - floaterp->setCanApply(can_preview, can_apply); - } + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if( floaterp ) + { + floaterp->setCanApply(can_preview, can_apply); + } } void LLTextureCtrl::setImmediateFilterPermMask(PermissionMask mask) @@ -1756,7 +1756,7 @@ void LLTextureCtrl::setImmediateFilterPermMask(PermissionMask mask) } } -void LLTextureCtrl::setFilterPermissionMasks(PermissionMask mask) +void LLTextureCtrl::setFilterPermissionMasks(PermissionMask mask) { setImmediateFilterPermMask(mask); setDnDFilterPermMask(mask); @@ -1775,176 +1775,176 @@ void LLTextureCtrl::onVisibilityChange(BOOL new_visibility) } } -void LLTextureCtrl::setVisible( BOOL visible ) +void LLTextureCtrl::setVisible( BOOL visible ) { - if( !visible ) - { - closeDependentFloater(); - } - LLUICtrl::setVisible( visible ); + if( !visible ) + { + closeDependentFloater(); + } + LLUICtrl::setVisible( visible ); } void LLTextureCtrl::setEnabled( BOOL enabled ) { - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if( floaterp ) - { - floaterp->setActive(enabled); - } - if( enabled ) - { - std::string tooltip; - if (floaterp) tooltip = floaterp->getString("choose_picture"); - setToolTip( tooltip ); - } - else - { - setToolTip( std::string() ); - // *TODO: would be better to keep floater open and show - // disabled state. - closeDependentFloater(); - } - - mCaption->setEnabled( enabled ); - - LLView::setEnabled( enabled ); + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp ) + { + floaterp->setActive(enabled); + } + if( enabled ) + { + std::string tooltip; + if (floaterp) tooltip = floaterp->getString("choose_picture"); + setToolTip( tooltip ); + } + else + { + setToolTip( std::string() ); + // *TODO: would be better to keep floater open and show + // disabled state. + closeDependentFloater(); + } + + mCaption->setEnabled( enabled ); + + LLView::setEnabled( enabled ); } void LLTextureCtrl::setValid(BOOL valid ) { - mValid = valid; - if (!valid) - { - LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if (pickerp) - { - pickerp->setActive(FALSE); - } - } + mValid = valid; + if (!valid) + { + LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if (pickerp) + { + pickerp->setActive(FALSE); + } + } } // virtual void LLTextureCtrl::clear() { - setImageAssetID(LLUUID::null); + setImageAssetID(LLUUID::null); } void LLTextureCtrl::setLabel(const std::string& label) { - mLabel = label; - mCaption->setText(label); + mLabel = label; + mCaption->setText(label); } void LLTextureCtrl::showPicker(BOOL take_focus) { - // show hourglass cursor when loading inventory window - // because inventory construction is slooow - getWindow()->setCursor(UI_CURSOR_WAIT); - LLFloater* floaterp = mFloaterHandle.get(); - - // Show the dialog - if( floaterp ) - { - floaterp->openFloater(); - } - else - { - floaterp = new LLFloaterTexturePicker( - this, - getImageAssetID(), - getDefaultImageAssetID(), - getBlankImageAssetID(), - getTentative(), - getAllowNoTexture(), - mLabel, - mImmediateFilterPermMask, - mDnDFilterPermMask, - mCanApplyImmediately, - mFallbackImage, - mInventoryPickType); - mFloaterHandle = floaterp->getHandle(); - - LLFloaterTexturePicker* texture_floaterp = dynamic_cast(floaterp); - if (texture_floaterp && mOnTextureSelectedCallback) - { - texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); - } - if (texture_floaterp && mOnCloseCallback) - { - texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this)); - } - if (texture_floaterp) - { - texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4, _5)); - } - if (texture_floaterp) - { - texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1)); - - texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled); - } - - LLFloater* root_floater = gFloaterView->getParentFloater(this); - if (root_floater) - root_floater->addDependentFloater(floaterp); - floaterp->openFloater(); - } - - LLFloaterTexturePicker* picker_floater = dynamic_cast(floaterp); - if (picker_floater) - { - picker_floater->setLocalTextureEnabled(mAllowLocalTexture); - } - - if (take_focus) - { - floaterp->setFocus(TRUE); - } + // show hourglass cursor when loading inventory window + // because inventory construction is slooow + getWindow()->setCursor(UI_CURSOR_WAIT); + LLFloater* floaterp = mFloaterHandle.get(); + + // Show the dialog + if( floaterp ) + { + floaterp->openFloater(); + } + else + { + floaterp = new LLFloaterTexturePicker( + this, + getImageAssetID(), + getDefaultImageAssetID(), + getBlankImageAssetID(), + getTentative(), + getAllowNoTexture(), + mLabel, + mImmediateFilterPermMask, + mDnDFilterPermMask, + mCanApplyImmediately, + mFallbackImage, + mInventoryPickType); + mFloaterHandle = floaterp->getHandle(); + + LLFloaterTexturePicker* texture_floaterp = dynamic_cast(floaterp); + if (texture_floaterp && mOnTextureSelectedCallback) + { + texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); + } + if (texture_floaterp && mOnCloseCallback) + { + texture_floaterp->setOnFloaterCloseCallback(boost::bind(&LLTextureCtrl::onFloaterClose, this)); + } + if (texture_floaterp) + { + texture_floaterp->setOnFloaterCommitCallback(boost::bind(&LLTextureCtrl::onFloaterCommit, this, _1, _2, _3, _4, _5)); + } + if (texture_floaterp) + { + texture_floaterp->setSetImageAssetIDCallback(boost::bind(&LLTextureCtrl::setImageAssetID, this, _1)); + + texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled); + } + + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + root_floater->addDependentFloater(floaterp); + floaterp->openFloater(); + } + + LLFloaterTexturePicker* picker_floater = dynamic_cast(floaterp); + if (picker_floater) + { + picker_floater->setLocalTextureEnabled(mAllowLocalTexture); + } + + if (take_focus) + { + floaterp->setFocus(TRUE); + } } void LLTextureCtrl::closeDependentFloater() { - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if( floaterp && floaterp->isInVisibleChain()) - { - floaterp->setOwner(NULL); - floaterp->setVisible(FALSE); - floaterp->closeFloater(); - } + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp && floaterp->isInVisibleChain()) + { + floaterp->setOwner(NULL); + floaterp->setVisible(FALSE); + floaterp->closeFloater(); + } } // Allow us to download textures quickly when floater is shown class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver { public: - virtual void done() - { - // We need to find textures in all folders, so get the main - // background download going. - LLInventoryModelBackgroundFetch::instance().start(); - gInventory.removeObserver(this); - delete this; - } + virtual void done() + { + // We need to find textures in all folders, so get the main + // background download going. + LLInventoryModelBackgroundFetch::instance().start(); + gInventory.removeObserver(this); + delete this; + } }; BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask) { - getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW); - return TRUE; + getWindow()->setCursor(mBorder->parentPointInView(x,y) ? UI_CURSOR_HAND : UI_CURSOR_ARROW); + return TRUE; } BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) { - BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); + BOOL handled = LLUICtrl::handleMouseDown( x, y , mask ); - if (!handled && mBorder->parentPointInView(x, y)) - { - if (!mOpenTexPreview) - { - showPicker(FALSE); + if (!handled && mBorder->parentPointInView(x, y)) + { + if (!mOpenTexPreview) + { + showPicker(FALSE); if (mInventoryPickType == PICK_MATERIAL) { //grab materials first... @@ -1955,48 +1955,48 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask) //grab textures first... LLInventoryModelBackgroundFetch::instance().start(gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE)); } - //...then start full inventory fetch. + //...then start full inventory fetch. if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) { LLInventoryModelBackgroundFetch::instance().start(); } - handled = TRUE; - } - else - { - if (getImageAssetID().notNull()) - { - LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", getValue()); - if (preview_texture && !preview_texture->isDependent()) - { - LLFloater* root_floater = gFloaterView->getParentFloater(this); - if (root_floater) - { - root_floater->addDependentFloater(preview_texture); - preview_texture->hideCtrlButtons(); - } - } - } - } - } - - return handled; + handled = TRUE; + } + else + { + if (getImageAssetID().notNull()) + { + LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance("preview_texture", getValue()); + if (preview_texture && !preview_texture->isDependent()) + { + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + { + root_floater->addDependentFloater(preview_texture); + preview_texture->hideCtrlButtons(); + } + } + } + } + } + + return handled; } void LLTextureCtrl::onFloaterClose() { - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if (floaterp) - { - if (mOnCloseCallback) - { - mOnCloseCallback(this,LLSD()); - } - floaterp->setOwner(NULL); - } + if (floaterp) + { + if (mOnCloseCallback) + { + mOnCloseCallback(this,LLSD()); + } + floaterp->setOwner(NULL); + } - mFloaterHandle.markDead(); + mFloaterHandle.markDead(); } void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& asset_id, const LLUUID& inv_id, const LLUUID& tracking_id) @@ -2004,18 +2004,18 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, co LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); if( floaterp && getEnabled()) - { - if (op == TEXTURE_CANCEL) - mViewModel->resetDirty(); - // If the "no_commit_on_selection" parameter is set - // we get dirty only when user presses OK in the picker - // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. - else if (mCommitOnSelection || op == TEXTURE_SELECT) - mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - - if(floaterp->isDirty() || asset_id.notNull()) // mModelView->setDirty does not work. - { - setTentative( FALSE ); + { + if (op == TEXTURE_CANCEL) + mViewModel->resetDirty(); + // If the "no_commit_on_selection" parameter is set + // we get dirty only when user presses OK in the picker + // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. + else if (mCommitOnSelection || op == TEXTURE_SELECT) + mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? + + if(floaterp->isDirty() || asset_id.notNull()) // mModelView->setDirty does not work. + { + setTentative( FALSE ); switch(source) { @@ -2044,76 +2044,76 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLPickerSource source, co LL_DEBUGS() << "mImageAssetID: " << mImageAssetID << ", mImageItemID: " << mImageItemID << LL_ENDL; - if (op == TEXTURE_SELECT && mOnSelectCallback) - { + if (op == TEXTURE_SELECT && mOnSelectCallback) + { mOnSelectCallback(this, LLSD()); - } - else if (op == TEXTURE_CANCEL && mOnCancelCallback) - { - mOnCancelCallback( this, LLSD() ); - } - else - { - // If the "no_commit_on_selection" parameter is set - // we commit only when user presses OK in the picker - // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. + } + else if (op == TEXTURE_CANCEL && mOnCancelCallback) + { + mOnCancelCallback( this, LLSD() ); + } + else + { + // If the "no_commit_on_selection" parameter is set + // we commit only when user presses OK in the picker + // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. if (mCommitOnSelection || op == TEXTURE_SELECT) { onCommit(); } - } - } - } + } + } + } } void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) { - mOnTextureSelectedCallback = cb; - LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); - if (floaterp) - { - floaterp->setTextureSelectedCallback(cb); - } + mOnTextureSelectedCallback = cb; + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if (floaterp) + { + floaterp->setTextureSelectedCallback(cb); + } } -void LLTextureCtrl::setImageAssetName(const std::string& name) +void LLTextureCtrl::setImageAssetName(const std::string& name) { - LLPointer imagep = LLUI::getUIImage(name); - if(imagep) - { - LLViewerFetchedTexture* pTexture = dynamic_cast(imagep->getImage().get()); - if(pTexture) - { - LLUUID id = pTexture->getID(); - setImageAssetID(id); - } - } + LLPointer imagep = LLUI::getUIImage(name); + if(imagep) + { + LLViewerFetchedTexture* pTexture = dynamic_cast(imagep->getImage().get()); + if(pTexture) + { + LLUUID id = pTexture->getID(); + setImageAssetID(id); + } + } } void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) { - if( mImageAssetID != asset_id ) - { - mImageItemID.setNull(); - mImageAssetID = asset_id; + if( mImageAssetID != asset_id ) + { + mImageItemID.setNull(); + mImageAssetID = asset_id; mLocalTrackingID.setNull(); - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if( floaterp && getEnabled() ) - { - floaterp->setImageID( asset_id ); - floaterp->resetDirty(); - } - } + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if( floaterp && getEnabled() ) + { + floaterp->setImageID( asset_id ); + floaterp->resetDirty(); + } + } } void LLTextureCtrl::setBakeTextureEnabled(bool enabled) { mBakeTextureEnabled = enabled; - LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); - if (floaterp) - { - floaterp->setBakeTextureEnabled(enabled); - } + LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get(); + if (floaterp) + { + floaterp->setBakeTextureEnabled(enabled); + } } void LLTextureCtrl::setInventoryPickType(EPickInventoryType type) @@ -2127,16 +2127,16 @@ void LLTextureCtrl::setInventoryPickType(EPickInventoryType type) } BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, void *cargo_data, - EAcceptance *accept, - std::string& tooltip_msg) + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg) { - BOOL handled = FALSE; + BOOL handled = FALSE; - // this downcast may be invalid - but if the second test below - // returns true, then the cast was valid, and we can perform - // the third test without problems. - LLInventoryItem* item = (LLInventoryItem*)cargo_data; + // this downcast may be invalid - but if the second test below + // returns true, then the cast was valid, and we can perform + // the third test without problems. + LLInventoryItem* item = (LLInventoryItem*)cargo_data; bool is_mesh = cargo_type == DAD_MESH; bool is_texture = cargo_type == DAD_TEXTURE; @@ -2156,66 +2156,66 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, allow_dnd = is_texture || is_mesh || is_material; } - if (getEnabled() && allow_dnd && allowDrop(item, cargo_type, tooltip_msg)) - { - if (drop) - { - if(doDrop(item)) - { - if (!mCommitOnSelection) - mViewModel->setDirty(); + if (getEnabled() && allow_dnd && allowDrop(item, cargo_type, tooltip_msg)) + { + if (drop) + { + if(doDrop(item)) + { + if (!mCommitOnSelection) + mViewModel->setDirty(); - // This removes the 'Multiple' overlay, since - // there is now only one texture selected. - setTentative( FALSE ); - onCommit(); - } - } + // This removes the 'Multiple' overlay, since + // there is now only one texture selected. + setTentative( FALSE ); + onCommit(); + } + } - *accept = ACCEPT_YES_SINGLE; - } - else - { - *accept = ACCEPT_NO; - } + *accept = ACCEPT_YES_SINGLE; + } + else + { + *accept = ACCEPT_NO; + } - handled = TRUE; - LL_DEBUGS("UserInput") << "dragAndDrop handled by LLTextureCtrl " << getName() << LL_ENDL; + handled = TRUE; + LL_DEBUGS("UserInput") << "dragAndDrop handled by LLTextureCtrl " << getName() << LL_ENDL; - return handled; + return handled; } void LLTextureCtrl::draw() { - mBorder->setKeyboardFocusHighlight(hasFocus()); + mBorder->setKeyboardFocusHighlight(hasFocus()); LLPointer preview = NULL; - if (!mValid) - { - mTexturep = NULL; + if (!mValid) + { + mTexturep = NULL; mGLTFMaterial = NULL; mGLTFPreview = NULL; - } - else if (!mImageAssetID.isNull()) - { - if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) - { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if (obj) - { - LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); - mTexturep = viewerTexture ? dynamic_cast(viewerTexture) : NULL; - mGLTFMaterial = NULL; - mGLTFPreview = NULL; + } + else if (!mImageAssetID.isNull()) + { + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(mImageAssetID)) + { + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (obj) + { + LLViewerTexture* viewerTexture = obj->getBakedTextureForMagicId(mImageAssetID); + mTexturep = viewerTexture ? dynamic_cast(viewerTexture) : NULL; + mGLTFMaterial = NULL; + mGLTFPreview = NULL; preview = mTexturep; - } - - } + } + + } - if (preview.isNull()) - { + if (preview.isNull()) + { LLPointer old_material = mGLTFMaterial; mGLTFMaterial = NULL; mTexturep = NULL; @@ -2243,151 +2243,151 @@ void LLTextureCtrl::draw() } else { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); - mTexturep->forceToSaveRawImage(0); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTexturep->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + mTexturep->forceToSaveRawImage(0); - preview = mTexturep; + preview = mTexturep; } - } - } - else//mImageAssetID == LLUUID::null - { - mTexturep = NULL; + } + } + else//mImageAssetID == LLUUID::null + { + mTexturep = NULL; mGLTFMaterial = NULL; mGLTFPreview = NULL; - } - - // Border - LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); - gl_rect_2d( border, mBorderColor.get(), FALSE ); - - // Interior - LLRect interior = border; - interior.stretch( -1 ); - - // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677). - const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); - if( preview ) - { - if( preview->getComponents() == 4 ) - { - gl_rect_2d_checkerboard( interior, alpha ); - } - - gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha); + } + + // Border + LLRect border( 0, getRect().getHeight(), getRect().getWidth(), BTN_HEIGHT_SMALL ); + gl_rect_2d( border, mBorderColor.get(), FALSE ); + + // Interior + LLRect interior = border; + interior.stretch( -1 ); + + // If we're in a focused floater, don't apply the floater's alpha to the texture (STORM-677). + const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + if( preview ) + { + if( preview->getComponents() == 4 ) + { + gl_rect_2d_checkerboard( interior, alpha ); + } + + gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), preview, UI_VERTEX_COLOR % alpha); preview->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) ); - } - else if (!mFallbackImage.isNull()) - { - mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); - } - else - { - gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); - - // Draw X - gl_draw_x( interior, LLColor4::black ); - } - - mTentativeLabel->setVisible( getTentative() ); - - // Show "Loading..." string on the top left corner while this texture is loading. - // Using the discard level, do not show the string if the texture is almost but not - // fully loaded. - if (mTexturep.notNull() && - (!mTexturep->isFullyLoaded()) && - (mShowLoadingPlaceholder == TRUE)) - { - U32 v_offset = 25; - LLFontGL* font = LLFontGL::getFontSansSerif(); - - // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god - if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike()) - { - font->renderUTF8( - mLoadingPlaceholderString, - 0, - llfloor(interior.mLeft+3), - llfloor(interior.mTop-v_offset), - LLColor4::white, - LLFontGL::LEFT, - LLFontGL::BASELINE, - LLFontGL::DROP_SHADOW); - } - - // Optionally show more detailed information. - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string tdesc; - // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best). - - v_offset += 12; - tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0)); - font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), - LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); - - v_offset += 12; - tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel()); - font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), - LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); - - v_offset += 12; - tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str()); - font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), - LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); - } - } - - LLUICtrl::draw(); + } + else if (!mFallbackImage.isNull()) + { + mFallbackImage->draw(interior, UI_VERTEX_COLOR % alpha); + } + else + { + gl_rect_2d( interior, LLColor4::grey % alpha, TRUE ); + + // Draw X + gl_draw_x( interior, LLColor4::black ); + } + + mTentativeLabel->setVisible( getTentative() ); + + // Show "Loading..." string on the top left corner while this texture is loading. + // Using the discard level, do not show the string if the texture is almost but not + // fully loaded. + if (mTexturep.notNull() && + (!mTexturep->isFullyLoaded()) && + (mShowLoadingPlaceholder == TRUE)) + { + U32 v_offset = 25; + LLFontGL* font = LLFontGL::getFontSansSerif(); + + // Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god + if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike()) + { + font->renderUTF8( + mLoadingPlaceholderString, + 0, + llfloor(interior.mLeft+3), + llfloor(interior.mTop-v_offset), + LLColor4::white, + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::DROP_SHADOW); + } + + // Optionally show more detailed information. + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string tdesc; + // Show what % the texture has loaded (0 to 100%, 100 is highest), and what level of detail (5 to 0, 0 is best). + + v_offset += 12; + tdesc = llformat(" PK : %d%%", U32(mTexturep->getDownloadProgress()*100.0)); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" LVL: %d", mTexturep->getDiscardLevel()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + + v_offset += 12; + tdesc = llformat(" ID : %s...", (mImageAssetID.asString().substr(0,7)).c_str()); + font->renderUTF8(tdesc, 0, llfloor(interior.mLeft+3), llfloor(interior.mTop-v_offset), + LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); + } + } + + LLUICtrl::draw(); } BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg) { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - - PermissionMask item_perm_mask = 0; - if (copy) item_perm_mask |= PERM_COPY; - if (mod) item_perm_mask |= PERM_MODIFY; - if (xfer) item_perm_mask |= PERM_TRANSFER; - - PermissionMask filter_perm_mask = mImmediateFilterPermMask; - if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) - { - if(mDragCallback) - { - return mDragCallback(this, item); - } - else - { - return TRUE; - } - } - else - { + BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); + BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); + BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID()); + + PermissionMask item_perm_mask = 0; + if (copy) item_perm_mask |= PERM_COPY; + if (mod) item_perm_mask |= PERM_MODIFY; + if (xfer) item_perm_mask |= PERM_TRANSFER; + + PermissionMask filter_perm_mask = mImmediateFilterPermMask; + if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) + { + if(mDragCallback) + { + return mDragCallback(this, item); + } + else + { + return TRUE; + } + } + else + { PermissionMask mask = PERM_COPY | PERM_TRANSFER; if ((filter_perm_mask & mask) == mask && cargo_type == DAD_TEXTURE) { tooltip_msg.assign(LLTrans::getString("TooltipTextureRestrictedDrop")); } - return FALSE; - } + return FALSE; + } } BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) { - // call the callback if it exists. - if(mDropCallback) - { - // if it returns TRUE, we return TRUE, and therefore the - // commit is called above. - return mDropCallback(this, item); - } + // call the callback if it exists. + if(mDropCallback) + { + // if it returns TRUE, we return TRUE, and therefore the + // commit is called above. + return mDropCallback(this, item); + } // no callback installed, so just set the image ids and carry on. LLUUID asset_id = item->getAssetUUID(); @@ -2398,29 +2398,29 @@ BOOL LLTextureCtrl::doDrop(LLInventoryItem* item) asset_id = BLANK_MATERIAL_ASSET_ID; } - setImageAssetID(asset_id); - mImageItemID = item->getUUID(); - return TRUE; + setImageAssetID(asset_id); + mImageItemID = item->getUUID(); + return TRUE; } BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char) { - if( ' ' == uni_char ) - { - showPicker(TRUE); - return TRUE; - } - return LLUICtrl::handleUnicodeCharHere(uni_char); + if( ' ' == uni_char ) + { + showPicker(TRUE); + return TRUE; + } + return LLUICtrl::handleUnicodeCharHere(uni_char); } void LLTextureCtrl::setValue( const LLSD& value ) { - setImageAssetID(value.asUUID()); + setImageAssetID(value.asUUID()); } LLSD LLTextureCtrl::getValue() const { - return LLSD(getImageAssetID()); + return LLSD(getImageAssetID()); } namespace LLInitParam diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index f193b0c083..db36ac9cc2 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -1,4 +1,4 @@ -/** +/** * @file lltexturectrl.h * @author Richard Nelson, James Cook * @brief LLTextureCtrl class header file including related functions @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -75,10 +75,10 @@ typedef enum e_pick_inventory_type namespace LLInitParam { template<> - struct TypeValues : public TypeValuesHelper - { - static void declareValues(); - }; + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; } enum LLPickerSource @@ -97,56 +97,56 @@ class LLTextureCtrl : public LLUICtrl { public: - typedef enum e_texture_pick_op - { - TEXTURE_CHANGE, - TEXTURE_SELECT, - TEXTURE_CANCEL - } ETexturePickOp; + typedef enum e_texture_pick_op + { + TEXTURE_CHANGE, + TEXTURE_SELECT, + TEXTURE_CANCEL + } ETexturePickOp; public: - struct Params : public LLInitParam::Block - { - Optional image_id; - Optional default_image_id; - Optional default_image_name; + struct Params : public LLInitParam::Block + { + Optional image_id; + Optional default_image_id; + Optional default_image_name; Optional pick_type; - Optional allow_no_texture; - Optional can_apply_immediately; - Optional no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty - // only on DnD or when OK is pressed in the picker - Optional label_width; - Optional border_color; - Optional fallback_image; - - Optional multiselect_text, - caption_text; - - Optional border; - - Params() - : image_id("image"), - default_image_id("default_image_id"), - default_image_name("default_image_name"), + Optional allow_no_texture; + Optional can_apply_immediately; + Optional no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty + // only on DnD or when OK is pressed in the picker + Optional label_width; + Optional border_color; + Optional fallback_image; + + Optional multiselect_text, + caption_text; + + Optional border; + + Params() + : image_id("image"), + default_image_id("default_image_id"), + default_image_name("default_image_name"), pick_type("pick_type", PICK_TEXTURE), - allow_no_texture("allow_no_texture", false), - can_apply_immediately("can_apply_immediately"), - no_commit_on_selection("no_commit_on_selection", false), - label_width("label_width", -1), - border_color("border_color"), - fallback_image("fallback_image"), - multiselect_text("multiselect_text"), - caption_text("caption_text"), - border("border") - {} - }; + allow_no_texture("allow_no_texture", false), + can_apply_immediately("can_apply_immediately"), + no_commit_on_selection("no_commit_on_selection", false), + label_width("label_width", -1), + border_color("border_color"), + fallback_image("fallback_image"), + multiselect_text("multiselect_text"), + caption_text("caption_text"), + border("border") + {} + }; protected: - LLTextureCtrl(const Params&); - friend class LLUICtrlFactory; + LLTextureCtrl(const Params&); + friend class LLUICtrlFactory; public: - virtual ~LLTextureCtrl(); + virtual ~LLTextureCtrl(); - // LLView interface + // LLView interface BOOL handleMouseDown(S32 x, S32 y, MASK mask) override; BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, @@ -171,77 +171,77 @@ public: void setValue(const LLSD& value) override; LLSD getValue() const override; - // LLTextureCtrl interface - void showPicker(BOOL take_focus); - bool isPickerShown() { return !mFloaterHandle.isDead(); } - void setLabel(const std::string& label); - void setLabelWidth(S32 label_width) {mLabelWidth =label_width;} - const std::string& getLabel() const { return mLabel; } + // LLTextureCtrl interface + void showPicker(BOOL take_focus); + bool isPickerShown() { return !mFloaterHandle.isDead(); } + void setLabel(const std::string& label); + void setLabelWidth(S32 label_width) {mLabelWidth =label_width;} + const std::string& getLabel() const { return mLabel; } - void setAllowNoTexture( BOOL b ) { mAllowNoTexture = b; } - bool getAllowNoTexture() const { return mAllowNoTexture; } + void setAllowNoTexture( BOOL b ) { mAllowNoTexture = b; } + bool getAllowNoTexture() const { return mAllowNoTexture; } - void setAllowLocalTexture(BOOL b) { mAllowLocalTexture = b; } - BOOL getAllowLocalTexture() const { return mAllowLocalTexture; } + void setAllowLocalTexture(BOOL b) { mAllowLocalTexture = b; } + BOOL getAllowLocalTexture() const { return mAllowLocalTexture; } - const LLUUID& getImageItemID() { return mImageItemID; } + const LLUUID& getImageItemID() { return mImageItemID; } - virtual void setImageAssetName(const std::string& name); - - void setImageAssetID(const LLUUID &image_asset_id); - const LLUUID& getImageAssetID() const { return mImageAssetID; } + virtual void setImageAssetName(const std::string& name); - void setDefaultImageAssetID( const LLUUID& id ) { mDefaultImageAssetID = id; } - const LLUUID& getDefaultImageAssetID() const { return mDefaultImageAssetID; } + void setImageAssetID(const LLUUID &image_asset_id); + const LLUUID& getImageAssetID() const { return mImageAssetID; } - const std::string& getDefaultImageName() const { return mDefaultImageName; } + void setDefaultImageAssetID( const LLUUID& id ) { mDefaultImageAssetID = id; } + const LLUUID& getDefaultImageAssetID() const { return mDefaultImageAssetID; } - void setBlankImageAssetID( const LLUUID& id ) { mBlankImageAssetID = id; } - const LLUUID& getBlankImageAssetID() const { return mBlankImageAssetID; } + const std::string& getDefaultImageName() const { return mDefaultImageName; } - void setOpenTexPreview(bool open_preview) { mOpenTexPreview = open_preview; } + void setBlankImageAssetID( const LLUUID& id ) { mBlankImageAssetID = id; } + const LLUUID& getBlankImageAssetID() const { return mBlankImageAssetID; } - void setCaption(const std::string& caption); - void setCanApplyImmediately(BOOL b); + void setOpenTexPreview(bool open_preview) { mOpenTexPreview = open_preview; } - void setCanApply(bool can_preview, bool can_apply); + void setCaption(const std::string& caption); + void setCanApplyImmediately(BOOL b); - void setImmediateFilterPermMask(PermissionMask mask); - void setDnDFilterPermMask(PermissionMask mask) - { mDnDFilterPermMask = mask; } - PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } + void setCanApply(bool can_preview, bool can_apply); + + void setImmediateFilterPermMask(PermissionMask mask); + void setDnDFilterPermMask(PermissionMask mask) + { mDnDFilterPermMask = mask; } + PermissionMask getImmediateFilterPermMask() { return mImmediateFilterPermMask; } void setFilterPermissionMasks(PermissionMask mask); - void closeDependentFloater(); + void closeDependentFloater(); - void onFloaterClose(); - void onFloaterCommit(ETexturePickOp op, + void onFloaterClose(); + void onFloaterCommit(ETexturePickOp op, LLPickerSource source, const LLUUID& local_id, const LLUUID& inv_id, const LLUUID& tracking_id); - // This call is returned when a drag is detected. Your callback - // should return TRUE if the drag is acceptable. - void setDragCallback(drag_n_drop_callback cb) { mDragCallback = cb; } + // This call is returned when a drag is detected. Your callback + // should return TRUE if the drag is acceptable. + void setDragCallback(drag_n_drop_callback cb) { mDragCallback = cb; } + + // This callback is called when the drop happens. Return TRUE if + // the drop happened - resulting in an on commit callback, but not + // necessariliy any other change. + void setDropCallback(drag_n_drop_callback cb) { mDropCallback = cb; } - // This callback is called when the drop happens. Return TRUE if - // the drop happened - resulting in an on commit callback, but not - // necessariliy any other change. - void setDropCallback(drag_n_drop_callback cb) { mDropCallback = cb; } - - void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; } - void setOnCloseCallback(commit_callback_t cb) { mOnCloseCallback = cb; } - void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; } + void setOnCloseCallback(commit_callback_t cb) { mOnCloseCallback = cb; } + void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } - /* - * callback for changing texture selection in inventory list of texture floater - */ - void setOnTextureSelectedCallback(texture_selected_callback cb); + /* + * callback for changing texture selection in inventory list of texture floater + */ + void setOnTextureSelectedCallback(texture_selected_callback cb); - void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); + void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); - LLViewerFetchedTexture* getTexture() { return mTexturep; } + LLViewerFetchedTexture* getTexture() { return mTexturep; } void setBakeTextureEnabled(bool enabled); bool getBakeTextureEnabled() const { return mBakeTextureEnabled; } @@ -253,45 +253,45 @@ public: LLUUID getLocalTrackingID() { return mLocalTrackingID; } private: - BOOL allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg); - BOOL doDrop(LLInventoryItem* item); + BOOL allowDrop(LLInventoryItem* item, EDragAndDropType cargo_type, std::string& tooltip_msg); + BOOL doDrop(LLInventoryItem* item); private: - drag_n_drop_callback mDragCallback; - drag_n_drop_callback mDropCallback; - commit_callback_t mOnCancelCallback; - commit_callback_t mOnSelectCallback; - commit_callback_t mOnCloseCallback; - texture_selected_callback mOnTextureSelectedCallback; - LLPointer mTexturep; - LLPointer mGLTFMaterial; - LLPointer mGLTFPreview; - LLUIColor mBorderColor; - LLUUID mImageItemID; - LLUUID mImageAssetID; - LLUUID mDefaultImageAssetID; - LLUUID mBlankImageAssetID; - LLUUID mLocalTrackingID; - LLUIImagePtr mFallbackImage; - std::string mDefaultImageName; - LLHandle mFloaterHandle; - LLTextBox* mTentativeLabel; - LLTextBox* mCaption; - std::string mLabel; - BOOL mAllowNoTexture; // If true, the user can select "none" as an option - BOOL mAllowLocalTexture; - PermissionMask mImmediateFilterPermMask; - PermissionMask mDnDFilterPermMask; - BOOL mCanApplyImmediately; - BOOL mCommitOnSelection; - BOOL mNeedsRawImageData; - LLViewBorder* mBorder; - BOOL mValid; - BOOL mShowLoadingPlaceholder; - std::string mLoadingPlaceholderString; - S32 mLabelWidth; - bool mOpenTexPreview; - bool mBakeTextureEnabled; + drag_n_drop_callback mDragCallback; + drag_n_drop_callback mDropCallback; + commit_callback_t mOnCancelCallback; + commit_callback_t mOnSelectCallback; + commit_callback_t mOnCloseCallback; + texture_selected_callback mOnTextureSelectedCallback; + LLPointer mTexturep; + LLPointer mGLTFMaterial; + LLPointer mGLTFPreview; + LLUIColor mBorderColor; + LLUUID mImageItemID; + LLUUID mImageAssetID; + LLUUID mDefaultImageAssetID; + LLUUID mBlankImageAssetID; + LLUUID mLocalTrackingID; + LLUIImagePtr mFallbackImage; + std::string mDefaultImageName; + LLHandle mFloaterHandle; + LLTextBox* mTentativeLabel; + LLTextBox* mCaption; + std::string mLabel; + BOOL mAllowNoTexture; // If true, the user can select "none" as an option + BOOL mAllowLocalTexture; + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + BOOL mCanApplyImmediately; + BOOL mCommitOnSelection; + BOOL mNeedsRawImageData; + LLViewBorder* mBorder; + BOOL mValid; + BOOL mShowLoadingPlaceholder; + std::string mLoadingPlaceholderString; + S32 mLabelWidth; + bool mOpenTexPreview; + bool mBakeTextureEnabled; EPickInventoryType mInventoryPickType; }; @@ -305,90 +305,90 @@ typedef boost::function texture)> set_on_update_ class LLFloaterTexturePicker : public LLFloater { public: - LLFloaterTexturePicker( - LLView* owner, - LLUUID image_asset_id, - LLUUID default_image_asset_id, - LLUUID blank_image_asset_id, - BOOL tentative, - BOOL allow_no_texture, - const std::string& label, - PermissionMask immediate_filter_perm_mask, - PermissionMask dnd_filter_perm_mask, - BOOL can_apply_immediately, - LLUIImagePtr fallback_image_name, - EPickInventoryType pick_type); - - virtual ~LLFloaterTexturePicker(); - - // LLView overrides - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, - BOOL drop, EDragAndDropType cargo_type, void *cargo_data, - EAcceptance *accept, - std::string& tooltip_msg); - /*virtual*/ void draw(); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - - // LLFloater overrides - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_settings); - - // New functions - void setImageID(const LLUUID& image_asset_id, bool set_selection = true); - bool updateImageStats(); // true if within limits - const LLUUID& getAssetID() { return mImageAssetID; } - const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library = FALSE); - void setCanApplyImmediately(BOOL b); - - void setActive(BOOL active); - - LLView* getOwner() const { return mOwner; } - void setOwner(LLView* owner) { mOwner = owner; } - void stopUsingPipette(); - - void commitIfImmediateSet(); + LLFloaterTexturePicker( + LLView* owner, + LLUUID image_asset_id, + LLUUID default_image_asset_id, + LLUUID blank_image_asset_id, + BOOL tentative, + BOOL allow_no_texture, + const std::string& label, + PermissionMask immediate_filter_perm_mask, + PermissionMask dnd_filter_perm_mask, + BOOL can_apply_immediately, + LLUIImagePtr fallback_image_name, + EPickInventoryType pick_type); + + virtual ~LLFloaterTexturePicker(); + + // LLView overrides + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, + BOOL drop, EDragAndDropType cargo_type, void *cargo_data, + EAcceptance *accept, + std::string& tooltip_msg); + /*virtual*/ void draw(); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + + // LLFloater overrides + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_settings); + + // New functions + void setImageID(const LLUUID& image_asset_id, bool set_selection = true); + bool updateImageStats(); // true if within limits + const LLUUID& getAssetID() { return mImageAssetID; } + const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library = FALSE); + void setCanApplyImmediately(BOOL b); + + void setActive(BOOL active); + + LLView* getOwner() const { return mOwner; } + void setOwner(LLView* owner) { mOwner = owner; } + void stopUsingPipette(); + + void commitIfImmediateSet(); void commitCallback(LLTextureCtrl::ETexturePickOp op); - void commitCancel(); + void commitCancel(); - void onFilterEdit(const std::string& search_string); + void onFilterEdit(const std::string& search_string); - void setCanApply(bool can_preview, bool can_apply, bool inworld_image = true); + void setCanApply(bool can_preview, bool can_apply, bool inworld_image = true); void setMinDimentionsLimits(S32 min_dim); - void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; } - void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; } - void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; } - void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; } - void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; } - const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; } - const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; } - - static void onBtnSetToDefault(void* userdata); - static void onBtnSelect(void* userdata); - static void onBtnCancel(void* userdata); - void onBtnPipette(); - //static void onBtnRevert( void* userdata ); - static void onBtnBlank(void* userdata); - static void onBtnNone(void* userdata); - void onSelectionChange(const std::deque &items, BOOL user_action); - static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); - void onTextureSelect(const LLTextureEntry& te); - - static void onModeSelect(LLUICtrl* ctrl, void *userdata); - static void onBtnAdd(void* userdata); - static void onBtnRemove(void* userdata); - static void onBtnUpload(void* userdata); - static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); - - static void onBakeTextureSelect(LLUICtrl* ctrl, void *userdata); - - void setLocalTextureEnabled(BOOL enabled); - void setBakeTextureEnabled(BOOL enabled); + void setTextureSelectedCallback(const texture_selected_callback& cb) { mTextureSelectedCallback = cb; } + void setOnFloaterCloseCallback(const floater_close_callback& cb) { mOnFloaterCloseCallback = cb; } + void setOnFloaterCommitCallback(const floater_commit_callback& cb) { mOnFloaterCommitCallback = cb; } + void setSetImageAssetIDCallback(const set_image_asset_id_callback& cb) { mSetImageAssetIDCallback = cb; } + void setOnUpdateImageStatsCallback(const set_on_update_image_stats_callback& cb) { mOnUpdateImageStatsCallback = cb; } + const LLUUID& getDefaultImageAssetID() { return mDefaultImageAssetID; } + const LLUUID& getBlankImageAssetID() { return mBlankImageAssetID; } + + static void onBtnSetToDefault(void* userdata); + static void onBtnSelect(void* userdata); + static void onBtnCancel(void* userdata); + void onBtnPipette(); + //static void onBtnRevert( void* userdata ); + static void onBtnBlank(void* userdata); + static void onBtnNone(void* userdata); + void onSelectionChange(const std::deque &items, BOOL user_action); + static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata); + void onTextureSelect(const LLTextureEntry& te); + + static void onModeSelect(LLUICtrl* ctrl, void *userdata); + static void onBtnAdd(void* userdata); + static void onBtnRemove(void* userdata); + static void onBtnUpload(void* userdata); + static void onLocalScrollCommit(LLUICtrl* ctrl, void* userdata); + + static void onBakeTextureSelect(LLUICtrl* ctrl, void *userdata); + + void setLocalTextureEnabled(BOOL enabled); + void setBakeTextureEnabled(BOOL enabled); void setInventoryPickType(EPickInventoryType type); void setImmediateFilterPermMask(PermissionMask mask); - static void onPickerCallback(const std::vector& filenames, LLHandle handle); + static void onPickerCallback(const std::vector& filenames, LLHandle handle); protected: void changeMode(); @@ -396,41 +396,41 @@ protected: void refreshInventoryFilter(); void setImageIDFromItem(const LLInventoryItem* itemp, bool set_selection = true); - LLPointer mTexturep; + LLPointer mTexturep; LLPointer mGLTFMaterial; LLPointer mGLTFPreview; - LLView* mOwner; + LLView* mOwner; - LLUUID mImageAssetID; // Currently selected texture - LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. - LLUUID mDefaultImageAssetID; - LLUUID mBlankImageAssetID; - BOOL mTentative; - BOOL mAllowNoTexture; - LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. - LLUUID mOriginalImageAssetID; + LLUUID mImageAssetID; // Currently selected texture + LLUIImagePtr mFallbackImage; // What to show if currently selected texture is null. + LLUUID mDefaultImageAssetID; + LLUUID mBlankImageAssetID; + BOOL mTentative; + BOOL mAllowNoTexture; + LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory. + LLUUID mOriginalImageAssetID; - std::string mLabel; + std::string mLabel; - LLTextBox* mTentativeLabel; - LLTextBox* mResolutionLabel; + LLTextBox* mTentativeLabel; + LLTextBox* mResolutionLabel; LLTextBox* mResolutionWarning; - std::string mPendingName; - BOOL mActive; - - LLFilterEditor* mFilterEdit; - LLInventoryPanel* mInventoryPanel; - PermissionMask mImmediateFilterPermMask; - PermissionMask mDnDFilterPermMask; - BOOL mCanApplyImmediately; - BOOL mNoCopyTextureSelected; - F32 mContextConeOpacity; - LLSaveFolderState mSavedFolderState; - BOOL mSelectedItemPinned; - - LLComboBox* mModeSelector; - LLScrollListCtrl* mLocalScrollCtrl; + std::string mPendingName; + BOOL mActive; + + LLFilterEditor* mFilterEdit; + LLInventoryPanel* mInventoryPanel; + PermissionMask mImmediateFilterPermMask; + PermissionMask mDnDFilterPermMask; + BOOL mCanApplyImmediately; + BOOL mNoCopyTextureSelected; + F32 mContextConeOpacity; + LLSaveFolderState mSavedFolderState; + BOOL mSelectedItemPinned; + + LLComboBox* mModeSelector; + LLScrollListCtrl* mLocalScrollCtrl; LLButton* mDefaultBtn; LLButton* mNoneBtn; LLButton* mBlankBtn; @@ -439,22 +439,22 @@ protected: LLButton* mCancelBtn; private: - bool mCanApply; - bool mCanPreview; - bool mPreviewSettingChanged; + bool mCanApply; + bool mCanPreview; + bool mPreviewSettingChanged; bool mLimitsSet; S32 mMaxDim; S32 mMinDim; EPickInventoryType mInventoryPickType; - texture_selected_callback mTextureSelectedCallback; - floater_close_callback mOnFloaterCloseCallback; - floater_commit_callback mOnFloaterCommitCallback; - set_image_asset_id_callback mSetImageAssetIDCallback; - set_on_update_image_stats_callback mOnUpdateImageStatsCallback; + texture_selected_callback mTextureSelectedCallback; + floater_close_callback mOnFloaterCloseCallback; + floater_commit_callback mOnFloaterCommitCallback; + set_image_asset_id_callback mSetImageAssetIDCallback; + set_on_update_image_stats_callback mOnUpdateImageStatsCallback; - BOOL mBakeTextureEnabled; + BOOL mBakeTextureEnabled; static S32 sLastPickerMode; }; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 293c47bf73..8a118232d0 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lltooldraganddrop.cpp * @brief LLToolDragAndDrop class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -69,1123 +69,1123 @@ class LLNoPreferredType : public LLInventoryCollectFunctor { public: - LLNoPreferredType() {} - virtual ~LLNoPreferredType() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) - { - return true; - } - return false; - } + LLNoPreferredType() {} + virtual ~LLNoPreferredType() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) + { + return true; + } + return false; + } }; class LLNoPreferredTypeOrItem : public LLInventoryCollectFunctor { public: - LLNoPreferredTypeOrItem() {} - virtual ~LLNoPreferredTypeOrItem() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - if (item) return true; - if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) - { - return true; - } - return false; - } + LLNoPreferredTypeOrItem() {} + virtual ~LLNoPreferredTypeOrItem() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item) + { + if (item) return true; + if (cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) + { + return true; + } + return false; + } }; class LLDroppableItem : public LLInventoryCollectFunctor { public: - LLDroppableItem(BOOL is_transfer) : - mCountLosing(0), mIsTransfer(is_transfer) {} - virtual ~LLDroppableItem() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item); - S32 countNoCopy() const { return mCountLosing; } + LLDroppableItem(BOOL is_transfer) : + mCountLosing(0), mIsTransfer(is_transfer) {} + virtual ~LLDroppableItem() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); + S32 countNoCopy() const { return mCountLosing; } protected: - S32 mCountLosing; - BOOL mIsTransfer; + S32 mCountLosing; + BOOL mIsTransfer; }; bool LLDroppableItem::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - bool allowed = false; - if (item) - { - allowed = itemTransferCommonlyAllowed(item); - - if (allowed - && mIsTransfer - && !item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID())) - { - allowed = false; - } - if (allowed && !item->getPermissions().allowCopyBy(gAgent.getID())) - { - ++mCountLosing; - } - } - return allowed; + LLInventoryItem* item) +{ + bool allowed = false; + if (item) + { + allowed = itemTransferCommonlyAllowed(item); + + if (allowed + && mIsTransfer + && !item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID())) + { + allowed = false; + } + if (allowed && !item->getPermissions().allowCopyBy(gAgent.getID())) + { + ++mCountLosing; + } + } + return allowed; } class LLDropCopyableItems : public LLInventoryCollectFunctor { public: - LLDropCopyableItems() {} - virtual ~LLDropCopyableItems() {} - virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); + LLDropCopyableItems() {} + virtual ~LLDropCopyableItems() {} + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); }; bool LLDropCopyableItems::operator()( - LLInventoryCategory* cat, - LLInventoryItem* item) -{ - bool allowed = false; - if (item) - { - allowed = itemTransferCommonlyAllowed(item); - if (allowed && - !item->getPermissions().allowCopyBy(gAgent.getID())) - { - // whoops, can't copy it - don't allow it. - allowed = false; - } - } - return allowed; -} - -// Starts a fetch on folders and items. This is really not used + LLInventoryCategory* cat, + LLInventoryItem* item) +{ + bool allowed = false; + if (item) + { + allowed = itemTransferCommonlyAllowed(item); + if (allowed && + !item->getPermissions().allowCopyBy(gAgent.getID())) + { + // whoops, can't copy it - don't allow it. + allowed = false; + } + } + return allowed; +} + +// Starts a fetch on folders and items. This is really not used // as an observer in the traditional sense; we're just using it to // request a fetch and we don't care about when/if the response arrives. class LLCategoryFireAndForget : public LLInventoryFetchComboObserver { public: - LLCategoryFireAndForget(const uuid_vec_t& folder_ids, - const uuid_vec_t& item_ids) : - LLInventoryFetchComboObserver(folder_ids, item_ids) - {} - ~LLCategoryFireAndForget() {} - virtual void done() - { - /* no-op: it's fire n forget right? */ - LL_DEBUGS() << "LLCategoryFireAndForget::done()" << LL_ENDL; - } + LLCategoryFireAndForget(const uuid_vec_t& folder_ids, + const uuid_vec_t& item_ids) : + LLInventoryFetchComboObserver(folder_ids, item_ids) + {} + ~LLCategoryFireAndForget() {} + virtual void done() + { + /* no-op: it's fire n forget right? */ + LL_DEBUGS() << "LLCategoryFireAndForget::done()" << LL_ENDL; + } }; class LLCategoryDropObserver : public LLInventoryFetchItemsObserver { public: - LLCategoryDropObserver( - const uuid_vec_t& ids, - const LLUUID& obj_id, LLToolDragAndDrop::ESource src) : - LLInventoryFetchItemsObserver(ids), - mObjectID(obj_id), - mSource(src) - {} - ~LLCategoryDropObserver() {} - virtual void done(); + LLCategoryDropObserver( + const uuid_vec_t& ids, + const LLUUID& obj_id, LLToolDragAndDrop::ESource src) : + LLInventoryFetchItemsObserver(ids), + mObjectID(obj_id), + mSource(src) + {} + ~LLCategoryDropObserver() {} + virtual void done(); protected: - LLUUID mObjectID; - LLToolDragAndDrop::ESource mSource; + LLUUID mObjectID; + LLToolDragAndDrop::ESource mSource; }; void LLCategoryDropObserver::done() { - gInventory.removeObserver(this); - LLViewerObject* dst_obj = gObjectList.findObject(mObjectID); - if (dst_obj) - { - // *FIX: coalesce these... - LLInventoryItem* item = NULL; - uuid_vec_t::iterator it = mComplete.begin(); - uuid_vec_t::iterator end = mComplete.end(); - for(; it < end; ++it) - { - item = gInventory.getItem(*it); - if (item) - { - LLToolDragAndDrop::dropInventory( - dst_obj, - item, - mSource, - LLUUID::null); - } - } - } - delete this; + gInventory.removeObserver(this); + LLViewerObject* dst_obj = gObjectList.findObject(mObjectID); + if (dst_obj) + { + // *FIX: coalesce these... + LLInventoryItem* item = NULL; + uuid_vec_t::iterator it = mComplete.begin(); + uuid_vec_t::iterator end = mComplete.end(); + for(; it < end; ++it) + { + item = gInventory.getItem(*it); + if (item) + { + LLToolDragAndDrop::dropInventory( + dst_obj, + item, + mSource, + LLUUID::null); + } + } + } + delete this; } S32 LLToolDragAndDrop::sOperationId = 0; LLToolDragAndDrop::DragAndDropEntry::DragAndDropEntry(dragOrDrop3dImpl f_none, - dragOrDrop3dImpl f_self, - dragOrDrop3dImpl f_avatar, - dragOrDrop3dImpl f_object, - dragOrDrop3dImpl f_land) : - LLDictionaryEntry("") + dragOrDrop3dImpl f_self, + dragOrDrop3dImpl f_avatar, + dragOrDrop3dImpl f_object, + dragOrDrop3dImpl f_land) : + LLDictionaryEntry("") { - mFunctions[DT_NONE] = f_none; - mFunctions[DT_SELF] = f_self; - mFunctions[DT_AVATAR] = f_avatar; - mFunctions[DT_OBJECT] = f_object; - mFunctions[DT_LAND] = f_land; + mFunctions[DT_NONE] = f_none; + mFunctions[DT_SELF] = f_self; + mFunctions[DT_AVATAR] = f_avatar; + mFunctions[DT_OBJECT] = f_object; + mFunctions[DT_LAND] = f_land; } LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::LLDragAndDropDictionary::get(EDragAndDropType dad_type, LLToolDragAndDrop::EDropTarget drop_target) { - const DragAndDropEntry *entry = lookup(dad_type); - if (entry) - { - return (entry->mFunctions[(U8)drop_target]); - } - return &LLToolDragAndDrop::dad3dNULL; + const DragAndDropEntry *entry = lookup(dad_type); + if (entry) + { + return (entry->mFunctions[(U8)drop_target]); + } + return &LLToolDragAndDrop::dad3dNULL; } LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() { - // DT_NONE DT_SELF DT_AVATAR DT_OBJECT DT_LAND - // |-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------| - addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL)); + // DT_NONE DT_SELF DT_AVATAR DT_OBJECT DT_LAND + // |-------------------------------|----------------------------------------------|-----------------------------------------------|---------------------------------------------------|--------------------------------| + addEntry(DAD_NONE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_TEXTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dTextureObject, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_MATERIAL, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMaterialObject, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_CLOTHING, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_OBJECT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject, &LLToolDragAndDrop::dad3dRezObjectOnLand)); - addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dRezCategoryOnObject, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_SOUND, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_CALLINGCARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_LANDMARK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_SCRIPT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dRezScript, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_CLOTHING, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_OBJECT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject, &LLToolDragAndDrop::dad3dRezObjectOnLand)); + addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dRezCategoryOnObject, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_MESH, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dMeshObject, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_SETTINGS, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - + // TODO: animation on self could play it? edit it? - // TODO: gesture on self could play it? edit it? + // TODO: gesture on self could play it? edit it? }; LLToolDragAndDrop::LLToolDragAndDrop() -: LLTool(std::string("draganddrop"), NULL), - mCargoCount(0), - mDragStartX(0), - mDragStartY(0), - mSource(SOURCE_AGENT), - mCursor(UI_CURSOR_NO), - mLastAccept(ACCEPT_NO), - mDrop(FALSE), - mCurItemIndex(0) +: LLTool(std::string("draganddrop"), NULL), + mCargoCount(0), + mDragStartX(0), + mDragStartY(0), + mSource(SOURCE_AGENT), + mCursor(UI_CURSOR_NO), + mLastAccept(ACCEPT_NO), + mDrop(FALSE), + mCurItemIndex(0) { } void LLToolDragAndDrop::setDragStart(S32 x, S32 y) { - mDragStartX = x; - mDragStartY = y; + mDragStartX = x; + mDragStartY = y; } BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y) { - static LLCachedControl drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold", 3); - - S32 mouse_delta_x = x - mDragStartX; - S32 mouse_delta_y = y - mDragStartY; - - return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > drag_and_drop_threshold * drag_and_drop_threshold; + static LLCachedControl drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold", 3); + + S32 mouse_delta_x = x - mDragStartX; + S32 mouse_delta_y = y - mDragStartY; + + return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > drag_and_drop_threshold * drag_and_drop_threshold; } void LLToolDragAndDrop::beginDrag(EDragAndDropType type, - const LLUUID& cargo_id, - ESource source, - const LLUUID& source_id, - const LLUUID& object_id) -{ - if (type == DAD_NONE) - { - LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL; - return; - } - mCargoTypes.clear(); - mCargoTypes.push_back(type); - mCargoIDs.clear(); - mCargoIDs.push_back(cargo_id); - mSource = source; - mSourceID = source_id; - mObjectID = object_id; - - setMouseCapture( TRUE ); - LLToolMgr::getInstance()->setTransientTool( this ); - mCursor = UI_CURSOR_NO; - if ((mCargoTypes[0] == DAD_CATEGORY) - && ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))) - { - LLInventoryCategory* cat = gInventory.getCategory(cargo_id); - // go ahead and fire & forget the descendents if we are not - // dragging a protected folder. - if (cat) - { - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLNoPreferredTypeOrItem is_not_preferred; - uuid_vec_t folder_ids; - uuid_vec_t item_ids; - if (is_not_preferred(cat, NULL)) - { - folder_ids.push_back(cargo_id); - } - gInventory.collectDescendentsIf( - cargo_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_not_preferred); - S32 count = cats.size(); - S32 i; - for(i = 0; i < count; ++i) - { - folder_ids.push_back(cats.at(i)->getUUID()); - } - count = items.size(); - for(i = 0; i < count; ++i) - { - item_ids.push_back(items.at(i)->getUUID()); - } - if (!folder_ids.empty() || !item_ids.empty()) - { - LLCategoryFireAndForget *fetcher = new LLCategoryFireAndForget(folder_ids, item_ids); - fetcher->startFetch(); - delete fetcher; - } - } - } + const LLUUID& cargo_id, + ESource source, + const LLUUID& source_id, + const LLUUID& object_id) +{ + if (type == DAD_NONE) + { + LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL; + return; + } + mCargoTypes.clear(); + mCargoTypes.push_back(type); + mCargoIDs.clear(); + mCargoIDs.push_back(cargo_id); + mSource = source; + mSourceID = source_id; + mObjectID = object_id; + + setMouseCapture( TRUE ); + LLToolMgr::getInstance()->setTransientTool( this ); + mCursor = UI_CURSOR_NO; + if ((mCargoTypes[0] == DAD_CATEGORY) + && ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY))) + { + LLInventoryCategory* cat = gInventory.getCategory(cargo_id); + // go ahead and fire & forget the descendents if we are not + // dragging a protected folder. + if (cat) + { + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLNoPreferredTypeOrItem is_not_preferred; + uuid_vec_t folder_ids; + uuid_vec_t item_ids; + if (is_not_preferred(cat, NULL)) + { + folder_ids.push_back(cargo_id); + } + gInventory.collectDescendentsIf( + cargo_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_not_preferred); + S32 count = cats.size(); + S32 i; + for(i = 0; i < count; ++i) + { + folder_ids.push_back(cats.at(i)->getUUID()); + } + count = items.size(); + for(i = 0; i < count; ++i) + { + item_ids.push_back(items.at(i)->getUUID()); + } + if (!folder_ids.empty() || !item_ids.empty()) + { + LLCategoryFireAndForget *fetcher = new LLCategoryFireAndForget(folder_ids, item_ids); + fetcher->startFetch(); + delete fetcher; + } + } + } } void LLToolDragAndDrop::beginMultiDrag( - const std::vector types, - const uuid_vec_t& cargo_ids, - ESource source, - const LLUUID& source_id) -{ - // assert on public api is evil - //llassert( type != DAD_NONE ); - - std::vector::const_iterator types_it; - for (types_it = types.begin(); types_it != types.end(); ++types_it) - { - if (DAD_NONE == *types_it) - { - LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL; - return; - } - } - mCargoTypes = types; - mCargoIDs = cargo_ids; - mSource = source; - mSourceID = source_id; - - setMouseCapture( TRUE ); - LLToolMgr::getInstance()->setTransientTool( this ); - mCursor = UI_CURSOR_NO; - if ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) - { - // find categories (i.e. inventory folders) in the cargo. - LLInventoryCategory* cat = NULL; - S32 count = llmin(cargo_ids.size(), types.size()); - std::set cat_ids; - for(S32 i = 0; i < count; ++i) - { - cat = gInventory.getCategory(cargo_ids[i]); - if (cat) - { - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLNoPreferredType is_not_preferred; - if (is_not_preferred(cat, NULL)) - { - cat_ids.insert(cat->getUUID()); - } - gInventory.collectDescendentsIf( - cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_not_preferred); - S32 cat_count = cats.size(); - for(S32 i = 0; i < cat_count; ++i) - { - cat_ids.insert(cat->getUUID()); - } - } - } - if (!cat_ids.empty()) - { - uuid_vec_t folder_ids; - uuid_vec_t item_ids; - std::back_insert_iterator copier(folder_ids); - std::copy(cat_ids.begin(), cat_ids.end(), copier); - LLCategoryFireAndForget fetcher(folder_ids, item_ids); - } - } + const std::vector types, + const uuid_vec_t& cargo_ids, + ESource source, + const LLUUID& source_id) +{ + // assert on public api is evil + //llassert( type != DAD_NONE ); + + std::vector::const_iterator types_it; + for (types_it = types.begin(); types_it != types.end(); ++types_it) + { + if (DAD_NONE == *types_it) + { + LL_WARNS() << "Attempted to start drag without a cargo type" << LL_ENDL; + return; + } + } + mCargoTypes = types; + mCargoIDs = cargo_ids; + mSource = source; + mSourceID = source_id; + + setMouseCapture( TRUE ); + LLToolMgr::getInstance()->setTransientTool( this ); + mCursor = UI_CURSOR_NO; + if ((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) + { + // find categories (i.e. inventory folders) in the cargo. + LLInventoryCategory* cat = NULL; + S32 count = llmin(cargo_ids.size(), types.size()); + std::set cat_ids; + for(S32 i = 0; i < count; ++i) + { + cat = gInventory.getCategory(cargo_ids[i]); + if (cat) + { + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLNoPreferredType is_not_preferred; + if (is_not_preferred(cat, NULL)) + { + cat_ids.insert(cat->getUUID()); + } + gInventory.collectDescendentsIf( + cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + is_not_preferred); + S32 cat_count = cats.size(); + for(S32 i = 0; i < cat_count; ++i) + { + cat_ids.insert(cat->getUUID()); + } + } + } + if (!cat_ids.empty()) + { + uuid_vec_t folder_ids; + uuid_vec_t item_ids; + std::back_insert_iterator copier(folder_ids); + std::copy(cat_ids.begin(), cat_ids.end(), copier); + LLCategoryFireAndForget fetcher(folder_ids, item_ids); + } + } } void LLToolDragAndDrop::endDrag() { - mEndDragSignal(); - LLSelectMgr::getInstance()->unhighlightAll(); - setMouseCapture(FALSE); + mEndDragSignal(); + LLSelectMgr::getInstance()->unhighlightAll(); + setMouseCapture(FALSE); } void LLToolDragAndDrop::onMouseCaptureLost() { - // Called whenever the drag ends or if mouse capture is simply lost - LLToolMgr::getInstance()->clearTransientTool(); - mCargoTypes.clear(); - mCargoIDs.clear(); - mSource = SOURCE_AGENT; - mSourceID.setNull(); - mObjectID.setNull(); - mCustomMsg.clear(); + // Called whenever the drag ends or if mouse capture is simply lost + LLToolMgr::getInstance()->clearTransientTool(); + mCargoTypes.clear(); + mCargoIDs.clear(); + mSource = SOURCE_AGENT; + mSourceID.setNull(); + mObjectID.setNull(); + mCustomMsg.clear(); } BOOL LLToolDragAndDrop::handleMouseUp( S32 x, S32 y, MASK mask ) { - if (hasMouseCapture()) - { - EAcceptance acceptance = ACCEPT_NO; - dragOrDrop( x, y, mask, TRUE, &acceptance ); - endDrag(); - } - return TRUE; + if (hasMouseCapture()) + { + EAcceptance acceptance = ACCEPT_NO; + dragOrDrop( x, y, mask, TRUE, &acceptance ); + endDrag(); + } + return TRUE; } ECursorType LLToolDragAndDrop::acceptanceToCursor( EAcceptance acceptance ) { - switch (acceptance) - { - case ACCEPT_YES_MULTI: - if (mCargoIDs.size() > 1) - { - mCursor = UI_CURSOR_ARROWDRAGMULTI; - } - else - { - mCursor = UI_CURSOR_ARROWDRAG; - } - break; - case ACCEPT_YES_SINGLE: - if (mCargoIDs.size() > 1) - { - mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop"); - mCursor = UI_CURSOR_NO; - } - else - { - mCursor = UI_CURSOR_ARROWDRAG; - } - break; - - case ACCEPT_NO_LOCKED: - mCursor = UI_CURSOR_NOLOCKED; - break; - - case ACCEPT_NO_CUSTOM: - mToolTipMsg = mCustomMsg; - mCursor = UI_CURSOR_NO; - break; - - - case ACCEPT_NO: - mCursor = UI_CURSOR_NO; - break; - - case ACCEPT_YES_COPY_MULTI: - if (mCargoIDs.size() > 1) - { - mCursor = UI_CURSOR_ARROWCOPYMULTI; - } - else - { - mCursor = UI_CURSOR_ARROWCOPY; - } - break; - case ACCEPT_YES_COPY_SINGLE: - if (mCargoIDs.size() > 1) - { - mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop"); - mCursor = UI_CURSOR_NO; - } - else - { - mCursor = UI_CURSOR_ARROWCOPY; - } - break; - case ACCEPT_POSTPONED: - break; - default: - llassert( FALSE ); - } - - return mCursor; + switch (acceptance) + { + case ACCEPT_YES_MULTI: + if (mCargoIDs.size() > 1) + { + mCursor = UI_CURSOR_ARROWDRAGMULTI; + } + else + { + mCursor = UI_CURSOR_ARROWDRAG; + } + break; + case ACCEPT_YES_SINGLE: + if (mCargoIDs.size() > 1) + { + mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop"); + mCursor = UI_CURSOR_NO; + } + else + { + mCursor = UI_CURSOR_ARROWDRAG; + } + break; + + case ACCEPT_NO_LOCKED: + mCursor = UI_CURSOR_NOLOCKED; + break; + + case ACCEPT_NO_CUSTOM: + mToolTipMsg = mCustomMsg; + mCursor = UI_CURSOR_NO; + break; + + + case ACCEPT_NO: + mCursor = UI_CURSOR_NO; + break; + + case ACCEPT_YES_COPY_MULTI: + if (mCargoIDs.size() > 1) + { + mCursor = UI_CURSOR_ARROWCOPYMULTI; + } + else + { + mCursor = UI_CURSOR_ARROWCOPY; + } + break; + case ACCEPT_YES_COPY_SINGLE: + if (mCargoIDs.size() > 1) + { + mToolTipMsg = LLTrans::getString("TooltipMustSingleDrop"); + mCursor = UI_CURSOR_NO; + } + else + { + mCursor = UI_CURSOR_ARROWCOPY; + } + break; + case ACCEPT_POSTPONED: + break; + default: + llassert( FALSE ); + } + + return mCursor; } BOOL LLToolDragAndDrop::handleHover( S32 x, S32 y, MASK mask ) { - EAcceptance acceptance = ACCEPT_NO; - dragOrDrop( x, y, mask, FALSE, &acceptance ); + EAcceptance acceptance = ACCEPT_NO; + dragOrDrop( x, y, mask, FALSE, &acceptance ); - ECursorType cursor = acceptanceToCursor(acceptance); - gViewerWindow->getWindow()->setCursor( cursor ); + ECursorType cursor = acceptanceToCursor(acceptance); + gViewerWindow->getWindow()->setCursor( cursor ); - LL_DEBUGS("UserInput") << "hover handled by LLToolDragAndDrop" << LL_ENDL; - return TRUE; + LL_DEBUGS("UserInput") << "hover handled by LLToolDragAndDrop" << LL_ENDL; + return TRUE; } BOOL LLToolDragAndDrop::handleKey(KEY key, MASK mask) { - if (key == KEY_ESCAPE) - { - // cancel drag and drop operation - endDrag(); - return TRUE; - } + if (key == KEY_ESCAPE) + { + // cancel drag and drop operation + endDrag(); + return TRUE; + } - return FALSE; + return FALSE; } BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask) { - if (!mToolTipMsg.empty()) - { - LLToolTipMgr::instance().unblockToolTips(); - LLToolTipMgr::instance().show(LLToolTip::Params() - .message(mToolTipMsg) - .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" ))); - return TRUE; - } - return FALSE; + if (!mToolTipMsg.empty()) + { + LLToolTipMgr::instance().unblockToolTips(); + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(mToolTipMsg) + .delay_time(gSavedSettings.getF32( "DragAndDropToolTipDelay" ))); + return TRUE; + } + return FALSE; } void LLToolDragAndDrop::handleDeselect() { - mToolTipMsg.clear(); - mCustomMsg.clear(); + mToolTipMsg.clear(); + mCustomMsg.clear(); - LLToolTipMgr::instance().blockToolTips(); + LLToolTipMgr::instance().blockToolTips(); } // protected -void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, - EAcceptance* acceptance) -{ - *acceptance = ACCEPT_YES_MULTI; - - BOOL handled = FALSE; - - LLView* top_view = gFocusMgr.getTopCtrl(); - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - - mToolTipMsg.clear(); - - // Increment the operation id for every drop - if (drop) - { - sOperationId++; - } - - // For people drag and drop we don't need an actual inventory object, - // instead we need the current cargo id, which should be a person id. - bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); - - if (top_view) - { - handled = TRUE; - - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - S32 local_x, local_y; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); - EAcceptance item_acceptance = ACCEPT_NO; - - LLInventoryObject* cargo = locateInventory(item, cat); - if (cargo) - { - handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); - } - else if (is_uuid_dragged) - { - handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)&mCargoIDs[mCurItemIndex], - &item_acceptance, - mToolTipMsg); - } - if (handled) - { - // use sort order to determine priority of acceptance - *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); - } - } - - // all objects passed, go ahead and perform drop if necessary - if (handled && drop && (U32)*acceptance >= ACCEPT_YES_COPY_SINGLE) - { - if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI && - mCargoIDs.size() > 1) - { - // tried to give multi-cargo to a single-acceptor - refuse and return. - *acceptance = ACCEPT_NO; - return; - } - - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - S32 local_x, local_y; - EAcceptance item_acceptance; - top_view->screenPointToLocal( x, y, &local_x, &local_y ); - - LLInventoryObject* cargo = locateInventory(item, cat); - if (cargo) - { - handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); - } - else if (is_uuid_dragged) - { - handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)&mCargoIDs[mCurItemIndex], - &item_acceptance, - mToolTipMsg); - } - } - } - if (handled) - { - mLastAccept = (EAcceptance)*acceptance; - } - } - - if (!handled) - { - handled = TRUE; - - LLRootView* root_view = gViewerWindow->getRootView(); - - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - EAcceptance item_acceptance = ACCEPT_NO; - - LLInventoryObject* cargo = locateInventory(item, cat); - - // fix for EXT-3191 - if (cargo) - { - handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); - } - else if (is_uuid_dragged) - { - handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, - mCargoTypes[mCurItemIndex], - (void*)&mCargoIDs[mCurItemIndex], - &item_acceptance, - mToolTipMsg); - } - if (handled) - { - // use sort order to determine priority of acceptance - *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); - } - } - // all objects passed, go ahead and perform drop if necessary - if (handled && drop && (U32)*acceptance > ACCEPT_NO_LOCKED) - { - if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI && - mCargoIDs.size() > 1) - { - // tried to give multi-cargo to a single-acceptor - refuse and return. - *acceptance = ACCEPT_NO; - return; - } - - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - EAcceptance item_acceptance; - - LLInventoryObject* cargo = locateInventory(item, cat); - if (cargo) - { - handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, - mCargoTypes[mCurItemIndex], - (void*)cargo, - &item_acceptance, - mToolTipMsg); - } - else if (is_uuid_dragged) - { - handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, - mCargoTypes[mCurItemIndex], - (void*)&mCargoIDs[mCurItemIndex], - &item_acceptance, - mToolTipMsg); - } - } - } - - if (handled) - { - mLastAccept = (EAcceptance)*acceptance; - } - } - - if (!handled) - { - // Disallow drag and drop to 3D from the marketplace - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if (marketplacelistings_id.notNull()) - { - for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) - { - if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], marketplacelistings_id)) - { - *acceptance = ACCEPT_NO; - mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld"); - return; - } - } - } - - dragOrDrop3D( x, y, mask, drop, acceptance ); - } -} - -void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance ) +void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, + EAcceptance* acceptance) { - mDrop = drop; - if (mDrop) - { - // don't allow drag and drop onto rigged or transparent objects - pick(gViewerWindow->pickImmediate(x, y, FALSE, FALSE)); - } - else - { - // don't allow drag and drop onto transparent objects - gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, FALSE); - } + *acceptance = ACCEPT_YES_MULTI; - *acceptance = mLastAccept; -} + BOOL handled = FALSE; -void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) -{ - if (getInstance() != NULL) - { - getInstance()->pick(pick_info); - } -} + LLView* top_view = gFocusMgr.getTopCtrl(); + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; -void LLToolDragAndDrop::pick(const LLPickInfo& pick_info) -{ - EDropTarget target = DT_NONE; - S32 hit_face = -1; - - LLViewerObject* hit_obj = pick_info.getObject(); - LLSelectMgr::getInstance()->unhighlightAll(); - bool highlight_object = false; - // Treat attachments as part of the avatar they are attached to. - if (hit_obj != NULL) - { - // don't allow drag and drop on grass, trees, etc. - if (pick_info.mPickType == LLPickInfo::PICK_FLORA) - { - mCursor = UI_CURSOR_NO; - gViewerWindow->getWindow()->setCursor( mCursor ); - return; - } - - if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment()) - { - LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj ); - if (!avatar) - { - mLastAccept = ACCEPT_NO; - mCursor = UI_CURSOR_NO; - gViewerWindow->getWindow()->setCursor( mCursor ); - return; - } - hit_obj = avatar; - } - - if (hit_obj->isAvatar()) - { - if (((LLVOAvatar*) hit_obj)->isSelf()) - { - target = DT_SELF; - hit_face = -1; - } - else - { - target = DT_AVATAR; - hit_face = -1; - } - } - else - { - target = DT_OBJECT; - hit_face = pick_info.mObjectFace; - highlight_object = true; - } - } - else if (pick_info.mPickType == LLPickInfo::PICK_LAND) - { - target = DT_LAND; - hit_face = -1; - } - - mLastAccept = ACCEPT_YES_MULTI; - - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - const S32 item_index = mCurItemIndex; - const EDragAndDropType dad_type = mCargoTypes[item_index]; - // Call the right implementation function - mLastAccept = (EAcceptance)llmin( - (U32)mLastAccept, - (U32)callMemberFunction(*this, - LLDragAndDropDictionary::instance().get(dad_type, target)) - (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); - } - - if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE)) - { - // if target allows multi-drop or there is only one item being dropped, go ahead - if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1)) - { - // Target accepts multi, or cargo is a single-drop - for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) - { - const S32 item_index = mCurItemIndex; - const EDragAndDropType dad_type = mCargoTypes[item_index]; - // Call the right implementation function - callMemberFunction(*this, LLDragAndDropDictionary::instance().get(dad_type, target)) - (hit_obj, hit_face, pick_info.mKeyMask, TRUE); - } - } - else - { - // Target does not accept multi, but cargo is multi - mLastAccept = ACCEPT_NO; - } - } - - if (highlight_object && mLastAccept > ACCEPT_NO_LOCKED) - { - // if any item being dragged will be applied to the object under our cursor - // highlight that object - for (S32 i = 0; i < (S32)mCargoIDs.size(); i++) - { - if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL)) - { - LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj); - break; - } - } - } - ECursorType cursor = acceptanceToCursor( mLastAccept ); - gViewerWindow->getWindow()->setCursor( cursor ); - - mLastHitPos = pick_info.mPosGlobal; - mLastCameraPos = gAgentCamera.getCameraPositionGlobal(); -} + mToolTipMsg.clear(); -// static -BOOL LLToolDragAndDrop::handleDropMaterialProtections(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id) -{ - if (!item) return FALSE; - - // Always succeed if.... - // material is from the library - // or already in the contents of the object - if (SOURCE_LIBRARY == source) - { - // dropping a material from the library always just works. - return TRUE; - } - - // In case the inventory has not been loaded (e.g. due to some recent operation - // causing a dirty inventory) and we can do an update, stall the user - // while fetching the inventory. - // - // Fetch if inventory is dirty and listener is present (otherwise we will not receive update) - if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) - { - hit_obj->requestInventory(); - LLSD args; - if (LLAssetType::AT_MATERIAL == item->getType()) + // Increment the operation id for every drop + if (drop) + { + sOperationId++; + } + + // For people drag and drop we don't need an actual inventory object, + // instead we need the current cargo id, which should be a person id. + bool is_uuid_dragged = (mSource == SOURCE_PEOPLE); + + if (top_view) + { + handled = TRUE; + + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - args["ERROR_MESSAGE"] = "Unable to add material.\nPlease wait a few seconds and try again."; + S32 local_x, local_y; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + EAcceptance item_acceptance = ACCEPT_NO; + + LLInventoryObject* cargo = locateInventory(item, cat); + if (cargo) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); + } + else if (is_uuid_dragged) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } + if (handled) + { + // use sort order to determine priority of acceptance + *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); + } } - else + + // all objects passed, go ahead and perform drop if necessary + if (handled && drop && (U32)*acceptance >= ACCEPT_YES_COPY_SINGLE) { - args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again."; + if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI && + mCargoIDs.size() > 1) + { + // tried to give multi-cargo to a single-acceptor - refuse and return. + *acceptance = ACCEPT_NO; + return; + } + + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) + { + S32 local_x, local_y; + EAcceptance item_acceptance; + top_view->screenPointToLocal( x, y, &local_x, &local_y ); + + LLInventoryObject* cargo = locateInventory(item, cat); + if (cargo) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, TRUE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); + } + else if (is_uuid_dragged) + { + handled = handled && top_view->handleDragAndDrop(local_x, local_y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } + } } - LLNotificationsUtil::add("ErrorMessage", args); - return FALSE; - } - // Make sure to verify both id and type since 'null' - // is a shared default for some asset types. - if (hit_obj->getInventoryItemByAsset(item->getAssetUUID(), item->getType())) - { - // if the asset is already in the object's inventory - // then it can always be added to a side. - // This saves some work if the task's inventory is already loaded - // and ensures that the asset item is only added once. - return TRUE; - } - - LLPointer new_item = new LLViewerInventoryItem(item); - if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) - { - // Check that we can add the material as inventory to the object - if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) - { - return FALSE; - } - // make sure the object has the material in it's inventory. - if (SOURCE_AGENT == source) - { - // Remove the material from local inventory. The server - // will actually remove the item from agent inventory. - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - } - else if (SOURCE_WORLD == source) - { - // *FIX: if the objects are in different regions, and the - // source region has crashed, you can bypass these - // permissions. - LLViewerObject* src_obj = gObjectList.findObject(src_id); - if (src_obj) - { - src_obj->removeInventory(item->getUUID()); - } - else - { - LL_WARNS() << "Unable to find source object." << LL_ENDL; - return FALSE; - } - } - // Add the asset item to the target object's inventory. - if (LLAssetType::AT_TEXTURE == new_item->getType() - || LLAssetType::AT_MATERIAL == new_item->getType()) + if (handled) { - hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + mLastAccept = (EAcceptance)*acceptance; } - else - { - hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); - } - // Force the object to update and refetch its inventory so it has this asset. - hit_obj->dirtyInventory(); - hit_obj->requestInventory(); - // TODO: Check to see if adding the item was successful; if not, then - // we should return false here. This will requre a separate listener - // since without listener, we have no way to receive update - } - else if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID())) - { - // Check that we can add the asset as inventory to the object - if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) - { - return FALSE; - } - // *FIX: may want to make sure agent can paint hit_obj. - - // Add the asset item to the target object's inventory. - if (LLAssetType::AT_TEXTURE == new_item->getType() - || LLAssetType::AT_MATERIAL == new_item->getType()) - { - hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); - } - else - { - hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); - } - // Force the object to update and refetch its inventory so it has this asset. - hit_obj->dirtyInventory(); - hit_obj->requestInventory(); - // TODO: Check to see if adding the item was successful; if not, then - // we should return false here. This will requre a separate listener - // since without listener, we have no way to receive update - } - else if (LLAssetType::AT_MATERIAL == new_item->getType() && - !item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) - { - // Check that we can add the material as inventory to the object - if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) - { - return FALSE; - } - // *FIX: may want to make sure agent can paint hit_obj. - - // Add the material item to the target object's inventory. - hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); - - // Force the object to update and refetch its inventory so it has this material. - hit_obj->dirtyInventory(); - hit_obj->requestInventory(); - // TODO: Check to see if adding the item was successful; if not, then - // we should return false here. This will requre a separate listener - // since without listener, we have no way to receive update - } - return TRUE; -} - -void set_texture_to_material(LLViewerObject* hit_obj, - S32 hit_face, - const LLUUID& asset_id, - LLGLTFMaterial::TextureInfo drop_channel) -{ - LLTextureEntry* te = hit_obj->getTE(hit_face); - if (!te) - { - return; - } - - const LLUUID base_mat_id = hit_obj->getRenderMaterialID(hit_face); - if (base_mat_id.isNull()) - { - return; } - if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) + if (!handled) { - hit_obj->requestInventory(); - return; - } + handled = TRUE; - LLViewerInventoryItem* mat_item = hit_obj->getInventoryItemByAsset(base_mat_id); - if (mat_item && !mat_item->getPermissions().allowModifyBy(gAgentID)) - { - return; - } + LLRootView* root_view = gViewerWindow->getRootView(); - LLPointer material = te->getGLTFMaterialOverride(); + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) + { + EAcceptance item_acceptance = ACCEPT_NO; - // make a copy to not invalidate existing - // material for multiple objects - if (material.isNull()) - { - // Start with a material override which does not make any changes - material = new LLGLTFMaterial(); - } - else - { - material = new LLGLTFMaterial(*material); - } + LLInventoryObject* cargo = locateInventory(item, cat); - switch (drop_channel) - { - case LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR: - default: + // fix for EXT-3191 + if (cargo) { - material->setBaseColorId(asset_id); + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); } - break; - - case LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS: + else if (is_uuid_dragged) { - material->setOcclusionRoughnessMetallicId(asset_id); + handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); } - break; - - case LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE: + if (handled) { - material->setEmissiveId(asset_id); + // use sort order to determine priority of acceptance + *acceptance = (EAcceptance)llmin((U32)item_acceptance, (U32)*acceptance); + } + } + // all objects passed, go ahead and perform drop if necessary + if (handled && drop && (U32)*acceptance > ACCEPT_NO_LOCKED) + { + if ((U32)*acceptance < ACCEPT_YES_COPY_MULTI && + mCargoIDs.size() > 1) + { + // tried to give multi-cargo to a single-acceptor - refuse and return. + *acceptance = ACCEPT_NO; + return; } - break; - case LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL: + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) { - material->setNormalId(asset_id); + EAcceptance item_acceptance; + + LLInventoryObject* cargo = locateInventory(item, cat); + if (cargo) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, + mCargoTypes[mCurItemIndex], + (void*)cargo, + &item_acceptance, + mToolTipMsg); + } + else if (is_uuid_dragged) + { + handled = handled && root_view->handleDragAndDrop(x, y, mask, TRUE, + mCargoTypes[mCurItemIndex], + (void*)&mCargoIDs[mCurItemIndex], + &item_acceptance, + mToolTipMsg); + } } - break; - } - LLGLTFMaterialList::queueModify(hit_obj, hit_face, material); -} + } -void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id, - bool remove_pbr) -{ - if (!item) - { - LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << LL_ENDL; - return; - } - S32 num_faces = hit_obj->getNumTEs(); - bool has_non_pbr_faces = false; - for (S32 face = 0; face < num_faces; face++) - { - if (hit_obj->getRenderMaterialID(face).isNull()) + if (handled) { - has_non_pbr_faces = true; - break; + mLastAccept = (EAcceptance)*acceptance; } } - if (has_non_pbr_faces || remove_pbr) + if (!handled) { - BOOL res = handleDropMaterialProtections(hit_obj, item, source, src_id); - if (!res) + // Disallow drag and drop to 3D from the marketplace + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (marketplacelistings_id.notNull()) { - return; + for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) + { + if (gInventory.isObjectDescendentOf(mCargoIDs[item_index], marketplacelistings_id)) + { + *acceptance = ACCEPT_NO; + mToolTipMsg = LLTrans::getString("TooltipOutboxDragToWorld"); + return; + } + } } - } - LLUUID asset_id = item->getAssetUUID(); - // Overrides require textures to be copy and transfer free - LLPermissions item_permissions = item->getPermissions(); - bool allow_adding_to_override = item_permissions.allowOperationBy(PERM_COPY, gAgent.getID()); - allow_adding_to_override &= item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); + dragOrDrop3D( x, y, mask, drop, acceptance ); + } +} - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); - add(LLStatViewer::EDIT_TEXTURE, 1); - for( S32 face = 0; face < num_faces; face++ ) - { - if (remove_pbr) +void LLToolDragAndDrop::dragOrDrop3D( S32 x, S32 y, MASK mask, BOOL drop, EAcceptance* acceptance ) +{ + mDrop = drop; + if (mDrop) + { + // don't allow drag and drop onto rigged or transparent objects + pick(gViewerWindow->pickImmediate(x, y, FALSE, FALSE)); + } + else + { + // don't allow drag and drop onto transparent objects + gViewerWindow->pickAsync(x, y, mask, pickCallback, FALSE, FALSE); + } + + *acceptance = mLastAccept; +} + +void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) +{ + if (getInstance() != NULL) + { + getInstance()->pick(pick_info); + } +} + +void LLToolDragAndDrop::pick(const LLPickInfo& pick_info) +{ + EDropTarget target = DT_NONE; + S32 hit_face = -1; + + LLViewerObject* hit_obj = pick_info.getObject(); + LLSelectMgr::getInstance()->unhighlightAll(); + bool highlight_object = false; + // Treat attachments as part of the avatar they are attached to. + if (hit_obj != NULL) + { + // don't allow drag and drop on grass, trees, etc. + if (pick_info.mPickType == LLPickInfo::PICK_FLORA) + { + mCursor = UI_CURSOR_NO; + gViewerWindow->getWindow()->setCursor( mCursor ); + return; + } + + if (hit_obj->isAttachment() && !hit_obj->isHUDAttachment()) + { + LLVOAvatar* avatar = LLVOAvatar::findAvatarFromAttachment( hit_obj ); + if (!avatar) + { + mLastAccept = ACCEPT_NO; + mCursor = UI_CURSOR_NO; + gViewerWindow->getWindow()->setCursor( mCursor ); + return; + } + hit_obj = avatar; + } + + if (hit_obj->isAvatar()) + { + if (((LLVOAvatar*) hit_obj)->isSelf()) + { + target = DT_SELF; + hit_face = -1; + } + else + { + target = DT_AVATAR; + hit_face = -1; + } + } + else + { + target = DT_OBJECT; + hit_face = pick_info.mObjectFace; + highlight_object = true; + } + } + else if (pick_info.mPickType == LLPickInfo::PICK_LAND) + { + target = DT_LAND; + hit_face = -1; + } + + mLastAccept = ACCEPT_YES_MULTI; + + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) + { + const S32 item_index = mCurItemIndex; + const EDragAndDropType dad_type = mCargoTypes[item_index]; + // Call the right implementation function + mLastAccept = (EAcceptance)llmin( + (U32)mLastAccept, + (U32)callMemberFunction(*this, + LLDragAndDropDictionary::instance().get(dad_type, target)) + (hit_obj, hit_face, pick_info.mKeyMask, FALSE)); + } + + if (mDrop && ((U32)mLastAccept >= ACCEPT_YES_COPY_SINGLE)) + { + // if target allows multi-drop or there is only one item being dropped, go ahead + if ((mLastAccept >= ACCEPT_YES_COPY_MULTI) || (mCargoIDs.size() == 1)) + { + // Target accepts multi, or cargo is a single-drop + for (mCurItemIndex = 0; mCurItemIndex < (S32)mCargoIDs.size(); mCurItemIndex++) + { + const S32 item_index = mCurItemIndex; + const EDragAndDropType dad_type = mCargoTypes[item_index]; + // Call the right implementation function + callMemberFunction(*this, LLDragAndDropDictionary::instance().get(dad_type, target)) + (hit_obj, hit_face, pick_info.mKeyMask, TRUE); + } + } + else + { + // Target does not accept multi, but cargo is multi + mLastAccept = ACCEPT_NO; + } + } + + if (highlight_object && mLastAccept > ACCEPT_NO_LOCKED) + { + // if any item being dragged will be applied to the object under our cursor + // highlight that object + for (S32 i = 0; i < (S32)mCargoIDs.size(); i++) + { + if (mCargoTypes[i] != DAD_OBJECT || (pick_info.mKeyMask & MASK_CONTROL)) + { + LLSelectMgr::getInstance()->highlightObjectAndFamily(hit_obj); + break; + } + } + } + ECursorType cursor = acceptanceToCursor( mLastAccept ); + gViewerWindow->getWindow()->setCursor( cursor ); + + mLastHitPos = pick_info.mPosGlobal; + mLastCameraPos = gAgentCamera.getCameraPositionGlobal(); +} + +// static +BOOL LLToolDragAndDrop::handleDropMaterialProtections(LLViewerObject* hit_obj, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id) +{ + if (!item) return FALSE; + + // Always succeed if.... + // material is from the library + // or already in the contents of the object + if (SOURCE_LIBRARY == source) + { + // dropping a material from the library always just works. + return TRUE; + } + + // In case the inventory has not been loaded (e.g. due to some recent operation + // causing a dirty inventory) and we can do an update, stall the user + // while fetching the inventory. + // + // Fetch if inventory is dirty and listener is present (otherwise we will not receive update) + if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) + { + hit_obj->requestInventory(); + LLSD args; + if (LLAssetType::AT_MATERIAL == item->getType()) + { + args["ERROR_MESSAGE"] = "Unable to add material.\nPlease wait a few seconds and try again."; + } + else + { + args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again."; + } + LLNotificationsUtil::add("ErrorMessage", args); + return FALSE; + } + // Make sure to verify both id and type since 'null' + // is a shared default for some asset types. + if (hit_obj->getInventoryItemByAsset(item->getAssetUUID(), item->getType())) + { + // if the asset is already in the object's inventory + // then it can always be added to a side. + // This saves some work if the task's inventory is already loaded + // and ensures that the asset item is only added once. + return TRUE; + } + + LLPointer new_item = new LLViewerInventoryItem(item); + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) + { + // Check that we can add the material as inventory to the object + if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) + { + return FALSE; + } + // make sure the object has the material in it's inventory. + if (SOURCE_AGENT == source) + { + // Remove the material from local inventory. The server + // will actually remove the item from agent inventory. + gInventory.deleteObject(item->getUUID()); + gInventory.notifyObservers(); + } + else if (SOURCE_WORLD == source) + { + // *FIX: if the objects are in different regions, and the + // source region has crashed, you can bypass these + // permissions. + LLViewerObject* src_obj = gObjectList.findObject(src_id); + if (src_obj) + { + src_obj->removeInventory(item->getUUID()); + } + else + { + LL_WARNS() << "Unable to find source object." << LL_ENDL; + return FALSE; + } + } + // Add the asset item to the target object's inventory. + if (LLAssetType::AT_TEXTURE == new_item->getType() + || LLAssetType::AT_MATERIAL == new_item->getType()) + { + hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + else + { + hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + // Force the object to update and refetch its inventory so it has this asset. + hit_obj->dirtyInventory(); + hit_obj->requestInventory(); + // TODO: Check to see if adding the item was successful; if not, then + // we should return false here. This will requre a separate listener + // since without listener, we have no way to receive update + } + else if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, + gAgent.getID())) + { + // Check that we can add the asset as inventory to the object + if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) + { + return FALSE; + } + // *FIX: may want to make sure agent can paint hit_obj. + + // Add the asset item to the target object's inventory. + if (LLAssetType::AT_TEXTURE == new_item->getType() + || LLAssetType::AT_MATERIAL == new_item->getType()) + { + hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + else + { + hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + } + // Force the object to update and refetch its inventory so it has this asset. + hit_obj->dirtyInventory(); + hit_obj->requestInventory(); + // TODO: Check to see if adding the item was successful; if not, then + // we should return false here. This will requre a separate listener + // since without listener, we have no way to receive update + } + else if (LLAssetType::AT_MATERIAL == new_item->getType() && + !item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID())) + { + // Check that we can add the material as inventory to the object + if (willObjectAcceptInventory(hit_obj,item) < ACCEPT_YES_COPY_SINGLE ) + { + return FALSE; + } + // *FIX: may want to make sure agent can paint hit_obj. + + // Add the material item to the target object's inventory. + hit_obj->updateMaterialInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + + // Force the object to update and refetch its inventory so it has this material. + hit_obj->dirtyInventory(); + hit_obj->requestInventory(); + // TODO: Check to see if adding the item was successful; if not, then + // we should return false here. This will requre a separate listener + // since without listener, we have no way to receive update + } + return TRUE; +} + +void set_texture_to_material(LLViewerObject* hit_obj, + S32 hit_face, + const LLUUID& asset_id, + LLGLTFMaterial::TextureInfo drop_channel) +{ + LLTextureEntry* te = hit_obj->getTE(hit_face); + if (!te) + { + return; + } + + const LLUUID base_mat_id = hit_obj->getRenderMaterialID(hit_face); + if (base_mat_id.isNull()) + { + return; + } + + if (hit_obj->isInventoryDirty() && hit_obj->hasInventoryListeners()) + { + hit_obj->requestInventory(); + return; + } + + LLViewerInventoryItem* mat_item = hit_obj->getInventoryItemByAsset(base_mat_id); + if (mat_item && !mat_item->getPermissions().allowModifyBy(gAgentID)) + { + return; + } + + LLPointer material = te->getGLTFMaterialOverride(); + + // make a copy to not invalidate existing + // material for multiple objects + if (material.isNull()) + { + // Start with a material override which does not make any changes + material = new LLGLTFMaterial(); + } + else + { + material = new LLGLTFMaterial(*material); + } + + switch (drop_channel) + { + case LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR: + default: + { + material->setBaseColorId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS: + { + material->setOcclusionRoughnessMetallicId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE: + { + material->setEmissiveId(asset_id); + } + break; + + case LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL: + { + material->setNormalId(asset_id); + } + break; + } + LLGLTFMaterialList::queueModify(hit_obj, hit_face, material); +} + +void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id, + bool remove_pbr) +{ + if (!item) + { + LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << LL_ENDL; + return; + } + S32 num_faces = hit_obj->getNumTEs(); + bool has_non_pbr_faces = false; + for (S32 face = 0; face < num_faces; face++) + { + if (hit_obj->getRenderMaterialID(face).isNull()) + { + has_non_pbr_faces = true; + break; + } + } + + if (has_non_pbr_faces || remove_pbr) + { + BOOL res = handleDropMaterialProtections(hit_obj, item, source, src_id); + if (!res) + { + return; + } + } + LLUUID asset_id = item->getAssetUUID(); + + // Overrides require textures to be copy and transfer free + LLPermissions item_permissions = item->getPermissions(); + bool allow_adding_to_override = item_permissions.allowOperationBy(PERM_COPY, gAgent.getID()); + allow_adding_to_override &= item_permissions.allowOperationBy(PERM_TRANSFER, gAgent.getID()); + + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); + add(LLStatViewer::EDIT_TEXTURE, 1); + for( S32 face = 0; face < num_faces; face++ ) + { + if (remove_pbr) { hit_obj->setRenderMaterialID(face, LLUUID::null); hit_obj->setTEImage(face, image); @@ -1201,11 +1201,11 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, { set_texture_to_material(hit_obj, face, asset_id, LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR); } - } + } - // send the update to the simulator + // send the update to the simulator LLGLTFMaterialList::flushUpdates(nullptr); - hit_obj->sendTEUpdate(); + hit_obj->sendTEUpdate(); } void LLToolDragAndDrop::dropMaterial(LLViewerObject* hit_obj, @@ -1329,35 +1329,35 @@ void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj, void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id) -{ - if (!item) - { - LL_WARNS() << "no inventory item." << LL_ENDL; - return; - } - LLUUID asset_id = item->getAssetUUID(); - BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); - if(!success) - { - return; - } - - LLSculptParams sculpt_params; - sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH); - hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); - - dialog_refresh_all(); -} - -void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj, - S32 hit_face, - LLInventoryItem* item, - ESource source, - const LLUUID& src_id, - bool all_faces, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id) +{ + if (!item) + { + LL_WARNS() << "no inventory item." << LL_ENDL; + return; + } + LLUUID asset_id = item->getAssetUUID(); + BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); + if(!success) + { + return; + } + + LLSculptParams sculpt_params; + sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH); + hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); + + dialog_refresh_all(); +} + +void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj, + S32 hit_face, + LLInventoryItem* item, + ESource source, + const LLUUID& src_id, + bool all_faces, bool remove_pbr, S32 tex_channel) { @@ -1454,19 +1454,19 @@ void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj, } void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, - S32 hit_face, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id, + S32 hit_face, + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id, bool remove_pbr, S32 tex_channel) { - if (hit_face == -1) return; - if (!item) - { - LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no texture item." << LL_ENDL; - return; - } + if (hit_face == -1) return; + if (!item) + { + LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no texture item." << LL_ENDL; + return; + } LLUUID asset_id = item->getAssetUUID(); @@ -1490,593 +1490,593 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, } return; } - BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); - if (!success) - { - return; - } + BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); + if (!success) + { + return; + } if (remove_pbr) { hit_obj->setRenderMaterialID(hit_face, LLUUID::null); } - // update viewer side image in anticipation of update from simulator - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); - add(LLStatViewer::EDIT_TEXTURE, 1); + // update viewer side image in anticipation of update from simulator + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); + add(LLStatViewer::EDIT_TEXTURE, 1); - LLTextureEntry* tep = hit_obj->getTE(hit_face); + LLTextureEntry* tep = hit_obj->getTE(hit_face); - LLPanelFace* panel_face = gFloaterTools->getPanelFace(); + LLPanelFace* panel_face = gFloaterTools->getPanelFace(); - if (gFloaterTools->getVisible() && panel_face) - { + if (gFloaterTools->getVisible() && panel_face) + { tex_channel = (tex_channel > -1) ? tex_channel : panel_face->getTextureDropChannel(); switch (tex_channel) - { + { - case 0: - default: - { - hit_obj->setTEImage(hit_face, image); - } - break; + case 0: + default: + { + hit_obj->setTEImage(hit_face, image); + } + break; - case 1: + case 1: if (tep) - { - LLMaterialPtr old_mat = tep->getMaterialParams(); - LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); - new_mat->setNormalID(asset_id); - tep->setMaterialParams(new_mat); - hit_obj->setTENormalMap(hit_face, asset_id); - LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); - } - break; - - case 2: + { + LLMaterialPtr old_mat = tep->getMaterialParams(); + LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); + new_mat->setNormalID(asset_id); + tep->setMaterialParams(new_mat); + hit_obj->setTENormalMap(hit_face, asset_id); + LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); + } + break; + + case 2: if (tep) - { - LLMaterialPtr old_mat = tep->getMaterialParams(); - LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); - new_mat->setSpecularID(asset_id); - tep->setMaterialParams(new_mat); - hit_obj->setTESpecularMap(hit_face, asset_id); - LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); - } - break; - } - } - else - { - hit_obj->setTEImage(hit_face, image); - } - - dialog_refresh_all(); - - // send the update to the simulator - hit_obj->sendTEUpdate(); + { + LLMaterialPtr old_mat = tep->getMaterialParams(); + LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); + new_mat->setSpecularID(asset_id); + tep->setMaterialParams(new_mat); + hit_obj->setTESpecularMap(hit_face, asset_id); + LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); + } + break; + } + } + else + { + hit_obj->setTEImage(hit_face, image); + } + + dialog_refresh_all(); + + // send the update to the simulator + hit_obj->sendTEUpdate(); } void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj, - LLInventoryItem* item, - BOOL active, - ESource source, - const LLUUID& src_id) -{ - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource) - || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource)) - { - LL_WARNS() << "Call to LLToolDragAndDrop::dropScript() from world" - << " or notecard." << LL_ENDL; - return; - } - if (hit_obj && item) - { - LLPointer new_script = new LLViewerInventoryItem(item); - if (!item->getPermissions().allowCopyBy(gAgent.getID())) - { - if (SOURCE_AGENT == source) - { - // Remove the script from local inventory. The server - // will actually remove the item from agent inventory. - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - } - else if (SOURCE_WORLD == source) - { - // *FIX: if the objects are in different regions, and - // the source region has crashed, you can bypass - // these permissions. - LLViewerObject* src_obj = gObjectList.findObject(src_id); - if (src_obj) - { - src_obj->removeInventory(item->getUUID()); - } - else - { - LL_WARNS() << "Unable to find source object." << LL_ENDL; - return; - } - } - } - hit_obj->saveScript(new_script, active, true); - gFloaterTools->dirty(); - - // VEFFECT: SetScript - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgentAvatarp); - effectp->setTargetObject(hit_obj); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - } + LLInventoryItem* item, + BOOL active, + ESource source, + const LLUUID& src_id) +{ + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource) + || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource)) + { + LL_WARNS() << "Call to LLToolDragAndDrop::dropScript() from world" + << " or notecard." << LL_ENDL; + return; + } + if (hit_obj && item) + { + LLPointer new_script = new LLViewerInventoryItem(item); + if (!item->getPermissions().allowCopyBy(gAgent.getID())) + { + if (SOURCE_AGENT == source) + { + // Remove the script from local inventory. The server + // will actually remove the item from agent inventory. + gInventory.deleteObject(item->getUUID()); + gInventory.notifyObservers(); + } + else if (SOURCE_WORLD == source) + { + // *FIX: if the objects are in different regions, and + // the source region has crashed, you can bypass + // these permissions. + LLViewerObject* src_obj = gObjectList.findObject(src_id); + if (src_obj) + { + src_obj->removeInventory(item->getUUID()); + } + else + { + LL_WARNS() << "Unable to find source object." << LL_ENDL; + return; + } + } + } + hit_obj->saveScript(new_script, active, true); + gFloaterTools->dirty(); + + // VEFFECT: SetScript + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(hit_obj); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + } } void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, - BOOL bypass_sim_raycast, - BOOL from_task_inventory, - BOOL remove_from_inventory) -{ - LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(mLastHitPos); - if (!regionp) - { - LL_WARNS() << "Couldn't find region to rez object" << LL_ENDL; - return; - } - - //LL_INFOS() << "Rezzing object" << LL_ENDL; - make_ui_sound("UISndObjectRezIn"); - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return; - - //if (regionp - // && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))) - //{ - // LLFirstUse::useSandbox(); - //} - // check if it cannot be copied, and mark as remove if it is - - // this will remove the object from inventory after rez. Only - // bother with this check if we would not normally remove from - // inventory. - if (!remove_from_inventory - && !item->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = TRUE; - } - - // Limit raycast to a single object. - // Speeds up server raycast + avoid problems with server ray - // hitting objects that were clipped by the near plane or culled - // on the viewer. - LLUUID ray_target_id; - if (raycast_target) - { - ray_target_id = raycast_target->getID(); - } - else - { - ray_target_id.setNull(); - } - - // Check if it's in the trash. - bool is_in_trash = false; - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if (gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) - { - is_in_trash = true; - } - - LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null; - - // Select the object only if we're editing. - BOOL rez_selected = LLToolMgr::getInstance()->inEdit(); - - - LLVector3 ray_start = regionp->getPosRegionFromGlobal(mLastCameraPos); - LLVector3 ray_end = regionp->getPosRegionFromGlobal(mLastHitPos); - // currently the ray's end point is an approximation, - // and is sometimes too short (causing failure.) so we - // double the ray's length: - if (bypass_sim_raycast == FALSE) - { - LLVector3 ray_direction = ray_start - ray_end; - ray_end = ray_end - ray_direction; - } - - - // Message packing code should be it's own uninterrupted block - LLMessageSystem* msg = gMessageSystem; - if (mSource == SOURCE_NOTECARD) - { - LLUIUsage::instance().logCommand("Object.RezObjectFromNotecard"); - msg->newMessageFast(_PREHASH_RezObjectFromNotecard); - } - else - { - LLUIUsage::instance().logCommand("Object.RezObject"); - msg->newMessageFast(_PREHASH_RezObject); - } - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - - msg->nextBlock("RezData"); - // if it's being rezzed from task inventory, we need to enable - // saving it back into the task inventory. - // *FIX: We can probably compress this to a single byte, since I - // think folderid == mSourceID. This will be a later - // optimization. - msg->addUUIDFast(_PREHASH_FromTaskID, source_id); - msg->addU8Fast(_PREHASH_BypassRaycast, (U8) bypass_sim_raycast); - msg->addVector3Fast(_PREHASH_RayStart, ray_start); - msg->addVector3Fast(_PREHASH_RayEnd, ray_end); - msg->addUUIDFast(_PREHASH_RayTargetID, ray_target_id ); - msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE); - msg->addBOOLFast(_PREHASH_RezSelected, rez_selected); - msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory); - - // deal with permissions slam logic - pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); - - LLUUID folder_id = item->getParentUUID(); - if ((SOURCE_LIBRARY == mSource) || (is_in_trash)) - { - // since it's coming from the library or trash, we want to not - // 'take' it back to the same place. - item->setParent(LLUUID::null); - // *TODO this code isn't working - the parent (FolderID) is still - // set when the object is "taken". so code on the "take" side is - // checking for trash and library as well (llviewermenu.cpp) - } - if (mSource == SOURCE_NOTECARD) - { - msg->nextBlockFast(_PREHASH_NotecardData); - msg->addUUIDFast(_PREHASH_NotecardItemID, mSourceID); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - } - else - { - msg->nextBlockFast(_PREHASH_InventoryData); - item->packMessage(msg); - } - msg->sendReliable(regionp->getHost()); - // back out the change. no actual internal changes take place. - item->setParent(folder_id); - - // If we're going to select it, get ready for the incoming - // selected object. - if (rez_selected) - { - LLSelectMgr::getInstance()->deselectAll(); - gViewerWindow->getWindow()->incBusyCount(); - } - - if (remove_from_inventory) - { - // Delete it from inventory immediately so that users cannot - // easily bypass copy protection in laggy situations. If the - // rez fails, we will put it back on the server. - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - } - - // VEFFECT: DropObject - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgentAvatarp); - effectp->setPositionGlobal(mLastHitPos); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - - add(LLStatViewer::OBJECT_REZ, 1); + BOOL bypass_sim_raycast, + BOOL from_task_inventory, + BOOL remove_from_inventory) +{ + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(mLastHitPos); + if (!regionp) + { + LL_WARNS() << "Couldn't find region to rez object" << LL_ENDL; + return; + } + + //LL_INFOS() << "Rezzing object" << LL_ENDL; + make_ui_sound("UISndObjectRezIn"); + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return; + + //if (regionp + // && (regionp->getRegionFlag(REGION_FLAGS_SANDBOX))) + //{ + // LLFirstUse::useSandbox(); + //} + // check if it cannot be copied, and mark as remove if it is - + // this will remove the object from inventory after rez. Only + // bother with this check if we would not normally remove from + // inventory. + if (!remove_from_inventory + && !item->getPermissions().allowCopyBy(gAgent.getID())) + { + remove_from_inventory = TRUE; + } + + // Limit raycast to a single object. + // Speeds up server raycast + avoid problems with server ray + // hitting objects that were clipped by the near plane or culled + // on the viewer. + LLUUID ray_target_id; + if (raycast_target) + { + ray_target_id = raycast_target->getID(); + } + else + { + ray_target_id.setNull(); + } + + // Check if it's in the trash. + bool is_in_trash = false; + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + is_in_trash = true; + } + + LLUUID source_id = from_task_inventory ? mSourceID : LLUUID::null; + + // Select the object only if we're editing. + BOOL rez_selected = LLToolMgr::getInstance()->inEdit(); + + + LLVector3 ray_start = regionp->getPosRegionFromGlobal(mLastCameraPos); + LLVector3 ray_end = regionp->getPosRegionFromGlobal(mLastHitPos); + // currently the ray's end point is an approximation, + // and is sometimes too short (causing failure.) so we + // double the ray's length: + if (bypass_sim_raycast == FALSE) + { + LLVector3 ray_direction = ray_start - ray_end; + ray_end = ray_end - ray_direction; + } + + + // Message packing code should be it's own uninterrupted block + LLMessageSystem* msg = gMessageSystem; + if (mSource == SOURCE_NOTECARD) + { + LLUIUsage::instance().logCommand("Object.RezObjectFromNotecard"); + msg->newMessageFast(_PREHASH_RezObjectFromNotecard); + } + else + { + LLUIUsage::instance().logCommand("Object.RezObject"); + msg->newMessageFast(_PREHASH_RezObject); + } + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + + msg->nextBlock("RezData"); + // if it's being rezzed from task inventory, we need to enable + // saving it back into the task inventory. + // *FIX: We can probably compress this to a single byte, since I + // think folderid == mSourceID. This will be a later + // optimization. + msg->addUUIDFast(_PREHASH_FromTaskID, source_id); + msg->addU8Fast(_PREHASH_BypassRaycast, (U8) bypass_sim_raycast); + msg->addVector3Fast(_PREHASH_RayStart, ray_start); + msg->addVector3Fast(_PREHASH_RayEnd, ray_end); + msg->addUUIDFast(_PREHASH_RayTargetID, ray_target_id ); + msg->addBOOLFast(_PREHASH_RayEndIsIntersection, FALSE); + msg->addBOOLFast(_PREHASH_RezSelected, rez_selected); + msg->addBOOLFast(_PREHASH_RemoveItem, remove_from_inventory); + + // deal with permissions slam logic + pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); + + LLUUID folder_id = item->getParentUUID(); + if ((SOURCE_LIBRARY == mSource) || (is_in_trash)) + { + // since it's coming from the library or trash, we want to not + // 'take' it back to the same place. + item->setParent(LLUUID::null); + // *TODO this code isn't working - the parent (FolderID) is still + // set when the object is "taken". so code on the "take" side is + // checking for trash and library as well (llviewermenu.cpp) + } + if (mSource == SOURCE_NOTECARD) + { + msg->nextBlockFast(_PREHASH_NotecardData); + msg->addUUIDFast(_PREHASH_NotecardItemID, mSourceID); + msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); + } + else + { + msg->nextBlockFast(_PREHASH_InventoryData); + item->packMessage(msg); + } + msg->sendReliable(regionp->getHost()); + // back out the change. no actual internal changes take place. + item->setParent(folder_id); + + // If we're going to select it, get ready for the incoming + // selected object. + if (rez_selected) + { + LLSelectMgr::getInstance()->deselectAll(); + gViewerWindow->getWindow()->incBusyCount(); + } + + if (remove_from_inventory) + { + // Delete it from inventory immediately so that users cannot + // easily bypass copy protection in laggy situations. If the + // rez fails, we will put it back on the server. + gInventory.deleteObject(item->getUUID()); + gInventory.notifyObservers(); + } + + // VEFFECT: DropObject + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setPositionGlobal(mLastHitPos); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + + add(LLStatViewer::OBJECT_REZ, 1); } void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, - LLInventoryItem* item, - LLToolDragAndDrop::ESource source, - const LLUUID& src_id) -{ - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource) - || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource)) - { - LL_WARNS() << "Call to LLToolDragAndDrop::dropInventory() from world" - << " or notecard." << LL_ENDL; - return; - } - - LLPointer new_item = new LLViewerInventoryItem(item); - time_t creation_date = time_corrected(); - new_item->setCreationDate(creation_date); - - if (!item->getPermissions().allowCopyBy(gAgent.getID())) - { - if (SOURCE_AGENT == source) - { - // Remove the inventory item from local inventory. The - // server will actually remove the item from agent - // inventory. - gInventory.deleteObject(item->getUUID()); - gInventory.notifyObservers(); - } - else if (SOURCE_WORLD == source) - { - // *FIX: if the objects are in different regions, and the - // source region has crashed, you can bypass these - // permissions. - LLViewerObject* src_obj = gObjectList.findObject(src_id); - if (src_obj) - { - src_obj->removeInventory(item->getUUID()); - } - else - { - LL_WARNS() << "Unable to find source object." << LL_ENDL; - return; - } - } - } - hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); - if (LLFloaterReg::instanceVisible("build")) - { - // *FIX: only show this if panel not expanded? - LLFloaterReg::showInstance("build", "Content"); - } - - // VEFFECT: AddToInventory - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgentAvatarp); - effectp->setTargetObject(hit_obj); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - gFloaterTools->dirty(); + LLInventoryItem* item, + LLToolDragAndDrop::ESource source, + const LLUUID& src_id) +{ + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if ((SOURCE_WORLD == LLToolDragAndDrop::getInstance()->mSource) + || (SOURCE_NOTECARD == LLToolDragAndDrop::getInstance()->mSource)) + { + LL_WARNS() << "Call to LLToolDragAndDrop::dropInventory() from world" + << " or notecard." << LL_ENDL; + return; + } + + LLPointer new_item = new LLViewerInventoryItem(item); + time_t creation_date = time_corrected(); + new_item->setCreationDate(creation_date); + + if (!item->getPermissions().allowCopyBy(gAgent.getID())) + { + if (SOURCE_AGENT == source) + { + // Remove the inventory item from local inventory. The + // server will actually remove the item from agent + // inventory. + gInventory.deleteObject(item->getUUID()); + gInventory.notifyObservers(); + } + else if (SOURCE_WORLD == source) + { + // *FIX: if the objects are in different regions, and the + // source region has crashed, you can bypass these + // permissions. + LLViewerObject* src_obj = gObjectList.findObject(src_id); + if (src_obj) + { + src_obj->removeInventory(item->getUUID()); + } + else + { + LL_WARNS() << "Unable to find source object." << LL_ENDL; + return; + } + } + } + hit_obj->updateInventory(new_item, TASK_INVENTORY_ITEM_KEY, true); + if (LLFloaterReg::instanceVisible("build")) + { + // *FIX: only show this if panel not expanded? + LLFloaterReg::showInstance("build", "Content"); + } + + // VEFFECT: AddToInventory + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(hit_obj); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + gFloaterTools->dirty(); } // accessor that looks at permissions, copyability, and names of // inventory items to determine if a drop would be ok. EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item, EDragAndDropType type) { - // check the basics - if (!item || !obj) return ACCEPT_NO; - // HACK: downcast - LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; - if (!vitem->isFinished() && (type != DAD_CATEGORY)) - { - // Note: for DAD_CATEGORY we assume that folder version check passed and folder - // is complete, meaning that items inside are up to date. - // (isFinished() == false) at the moment shows that item was loaded from cache. - // Library or agent inventory only. - return ACCEPT_NO; - } - if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links - - // deny attempts to drop from an object onto itself. This is to - // help make sure that drops that are from an object to an object - // don't have to worry about order of evaluation. Think of this - // like check for self in assignment. - if(obj->getID() == item->getParentUUID()) - { - return ACCEPT_NO; - } - - //BOOL copy = (perm.allowCopyBy(gAgent.getID(), - // gAgent.getGroupID()) - // && (obj->mPermModify || obj->mFlagAllowInventoryAdd)); - BOOL worn = FALSE; - LLVOAvatarSelf* my_avatar = NULL; - switch(item->getType()) - { - case LLAssetType::AT_OBJECT: - my_avatar = gAgentAvatarp; - if(my_avatar && my_avatar->isWearingAttachment(item->getUUID())) - { - worn = TRUE; - } - break; - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_CLOTHING: - if(gAgentWearables.isWearingItem(item->getUUID())) - { - worn = TRUE; - } - break; - case LLAssetType::AT_CALLINGCARD: - // Calling Cards in object are disabled for now - // because of incomplete LSL support. See STORM-1117. - return ACCEPT_NO; - default: - break; - } - const LLPermissions& perm = item->getPermissions(); - BOOL modify = (obj->permModify() || obj->flagAllowInventoryAdd()); - BOOL transfer = FALSE; - if((obj->permYouOwner() && (perm.getOwner() == gAgent.getID())) - || perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - transfer = TRUE; - } - BOOL volume = (LL_PCODE_VOLUME == obj->getPCode()); - BOOL attached = obj->isAttachment(); - BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; - if(attached && !unrestricted) - { + // check the basics + if (!item || !obj) return ACCEPT_NO; + // HACK: downcast + LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; + if (!vitem->isFinished() && (type != DAD_CATEGORY)) + { + // Note: for DAD_CATEGORY we assume that folder version check passed and folder + // is complete, meaning that items inside are up to date. + // (isFinished() == false) at the moment shows that item was loaded from cache. + // Library or agent inventory only. + return ACCEPT_NO; + } + if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links + + // deny attempts to drop from an object onto itself. This is to + // help make sure that drops that are from an object to an object + // don't have to worry about order of evaluation. Think of this + // like check for self in assignment. + if(obj->getID() == item->getParentUUID()) + { + return ACCEPT_NO; + } + + //BOOL copy = (perm.allowCopyBy(gAgent.getID(), + // gAgent.getGroupID()) + // && (obj->mPermModify || obj->mFlagAllowInventoryAdd)); + BOOL worn = FALSE; + LLVOAvatarSelf* my_avatar = NULL; + switch(item->getType()) + { + case LLAssetType::AT_OBJECT: + my_avatar = gAgentAvatarp; + if(my_avatar && my_avatar->isWearingAttachment(item->getUUID())) + { + worn = TRUE; + } + break; + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_CLOTHING: + if(gAgentWearables.isWearingItem(item->getUUID())) + { + worn = TRUE; + } + break; + case LLAssetType::AT_CALLINGCARD: + // Calling Cards in object are disabled for now + // because of incomplete LSL support. See STORM-1117. + return ACCEPT_NO; + default: + break; + } + const LLPermissions& perm = item->getPermissions(); + BOOL modify = (obj->permModify() || obj->flagAllowInventoryAdd()); + BOOL transfer = FALSE; + if((obj->permYouOwner() && (perm.getOwner() == gAgent.getID())) + || perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + transfer = TRUE; + } + BOOL volume = (LL_PCODE_VOLUME == obj->getPCode()); + BOOL attached = obj->isAttachment(); + BOOL unrestricted = ((perm.getMaskBase() & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) ? TRUE : FALSE; + if(attached && !unrestricted) + { // Attachments are in world and in inventory simultaneously, // at the moment server doesn't support such a situation. - return ACCEPT_NO_LOCKED; - } - else if(modify && transfer && volume && !worn) - { - return ACCEPT_YES_MULTI; - } - else if(!modify) - { - return ACCEPT_NO_LOCKED; - } - return ACCEPT_NO; + return ACCEPT_NO_LOCKED; + } + else if(modify && transfer && volume && !worn) + { + return ACCEPT_YES_MULTI; + } + else if(!modify) + { + return ACCEPT_NO_LOCKED; + } + return ACCEPT_NO; } static void give_inventory_cb(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - // if Cancel pressed - if (option == 1) - { - return; - } - - LLSD payload = notification["payload"]; - const LLUUID& session_id = payload["session_id"]; - const LLUUID& agent_id = payload["agent_id"]; - LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]); - LLViewerInventoryCategory * inv_cat = gInventory.getCategory(payload["item_id"]); - if (NULL == inv_item && NULL == inv_cat) - { - llassert( FALSE ); - return; - } - bool successfully_shared; - if (inv_item) - { - successfully_shared = LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id); - } - else - { - successfully_shared = LLGiveInventory::doGiveInventoryCategory(agent_id, inv_cat, session_id); - } - if (successfully_shared) - { - if ("avatarpicker" == payload["d&d_dest"].asString()) - { - LLFloaterReg::hideInstance("avatar_picker"); - } - LLNotificationsUtil::add("ItemsShared"); - } + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // if Cancel pressed + if (option == 1) + { + return; + } + + LLSD payload = notification["payload"]; + const LLUUID& session_id = payload["session_id"]; + const LLUUID& agent_id = payload["agent_id"]; + LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]); + LLViewerInventoryCategory * inv_cat = gInventory.getCategory(payload["item_id"]); + if (NULL == inv_item && NULL == inv_cat) + { + llassert( FALSE ); + return; + } + bool successfully_shared; + if (inv_item) + { + successfully_shared = LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id); + } + else + { + successfully_shared = LLGiveInventory::doGiveInventoryCategory(agent_id, inv_cat, session_id); + } + if (successfully_shared) + { + if ("avatarpicker" == payload["d&d_dest"].asString()) + { + LLFloaterReg::hideInstance("avatar_picker"); + } + LLNotificationsUtil::add("ItemsShared"); + } } static void show_object_sharing_confirmation(const std::string name, - LLInventoryObject* inv_item, - const LLSD& dest, - const LLUUID& dest_agent, - const LLUUID& session_id = LLUUID::null) -{ - if (!inv_item) - { - llassert(NULL != inv_item); - return; - } - LLSD substitutions; - substitutions["RESIDENTS"] = name; - substitutions["ITEMS"] = inv_item->getName(); - LLSD payload; - payload["agent_id"] = dest_agent; - payload["item_id"] = inv_item->getUUID(); - payload["session_id"] = session_id; - payload["d&d_dest"] = dest.asString(); - LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); + LLInventoryObject* inv_item, + const LLSD& dest, + const LLUUID& dest_agent, + const LLUUID& session_id = LLUUID::null) +{ + if (!inv_item) + { + llassert(NULL != inv_item); + return; + } + LLSD substitutions; + substitutions["RESIDENTS"] = name; + substitutions["ITEMS"] = inv_item->getName(); + LLSD payload; + payload["agent_id"] = dest_agent; + payload["item_id"] = inv_item->getUUID(); + payload["session_id"] = session_id; + payload["d&d_dest"] = dest.asString(); + LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); } static void get_name_cb(const LLUUID& id, - const LLAvatarName& av_name, - LLInventoryObject* inv_obj, - const LLSD& dest, - const LLUUID& dest_agent) + const LLAvatarName& av_name, + LLInventoryObject* inv_obj, + const LLSD& dest, + const LLUUID& dest_agent) { - show_object_sharing_confirmation(av_name.getUserName(), - inv_obj, - dest, - id, - LLUUID::null); + show_object_sharing_confirmation(av_name.getUserName(), + inv_obj, + dest, + id, + LLUUID::null); } // function used as drag-and-drop handler for simple agent give inventory requests //static bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_id, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - const LLSD& dest) -{ - // check the type - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_CLOTHING: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - case DAD_CALLINGCARD: - case DAD_MESH: - case DAD_CATEGORY: + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + const LLSD& dest) +{ + // check the type + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_CLOTHING: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + case DAD_CALLINGCARD: + case DAD_MESH: + case DAD_CATEGORY: case DAD_SETTINGS: case DAD_MATERIAL: - { - LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data; - if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID()) - && LLGiveInventory::isInventoryGiveAcceptable(dynamic_cast(inv_obj)))) - { - // *TODO: get multiple object transfers working - *accept = ACCEPT_YES_COPY_SINGLE; - if(drop) - { - LLIMModel::LLIMSession * session = LLIMModel::instance().findIMSession(session_id); - - // If no IM session found get the destination agent's name by id. - if (NULL == session) - { - LLAvatarName av_name; - - // If destination agent's name is found in cash proceed to showing the confirmation dialog. - // Otherwise set up a callback to show the dialog when the name arrives. - if (LLAvatarNameCache::get(dest_agent, &av_name)) - { - show_object_sharing_confirmation(av_name.getUserName(), inv_obj, dest, dest_agent, LLUUID::null); - } - else - { - LLAvatarNameCache::get(dest_agent, boost::bind(&get_name_cb, _1, _2, inv_obj, dest, dest_agent)); - } - - return true; - } - std::string dest_name = session->mName; - LLAvatarName av_name; - if(LLAvatarNameCache::get(dest_agent, &av_name)) - { - dest_name = av_name.getCompleteName(); - } - // If an IM session with destination agent is found item offer will be logged in this session. - show_object_sharing_confirmation(dest_name, inv_obj, dest, dest_agent, session_id); - } - } - else - { - // It's not in the user's inventory (it's probably - // in an object's contents), so disallow dragging - // it here. You can't give something you don't - // yet have. - *accept = ACCEPT_NO; - } - break; - } - default: - *accept = ACCEPT_NO; - break; - } - - return TRUE; + { + LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data; + if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID()) + && LLGiveInventory::isInventoryGiveAcceptable(dynamic_cast(inv_obj)))) + { + // *TODO: get multiple object transfers working + *accept = ACCEPT_YES_COPY_SINGLE; + if(drop) + { + LLIMModel::LLIMSession * session = LLIMModel::instance().findIMSession(session_id); + + // If no IM session found get the destination agent's name by id. + if (NULL == session) + { + LLAvatarName av_name; + + // If destination agent's name is found in cash proceed to showing the confirmation dialog. + // Otherwise set up a callback to show the dialog when the name arrives. + if (LLAvatarNameCache::get(dest_agent, &av_name)) + { + show_object_sharing_confirmation(av_name.getUserName(), inv_obj, dest, dest_agent, LLUUID::null); + } + else + { + LLAvatarNameCache::get(dest_agent, boost::bind(&get_name_cb, _1, _2, inv_obj, dest, dest_agent)); + } + + return true; + } + std::string dest_name = session->mName; + LLAvatarName av_name; + if(LLAvatarNameCache::get(dest_agent, &av_name)) + { + dest_name = av_name.getCompleteName(); + } + // If an IM session with destination agent is found item offer will be logged in this session. + show_object_sharing_confirmation(dest_name, inv_obj, dest, dest_agent, session_id); + } + } + else + { + // It's not in the user's inventory (it's probably + // in an object's contents), so disallow dragging + // it here. You can't give something you don't + // yet have. + *accept = ACCEPT_NO; + } + break; + } + default: + *accept = ACCEPT_NO; + break; + } + + return TRUE; } @@ -2086,278 +2086,278 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ /// EAcceptance LLToolDragAndDrop::dad3dNULL( - LLViewerObject*, S32, MASK, BOOL) + LLViewerObject*, S32, MASK, BOOL) { - LL_DEBUGS() << "LLToolDragAndDrop::dad3dNULL()" << LL_ENDL; - return ACCEPT_NO; + LL_DEBUGS() << "LLToolDragAndDrop::dad3dNULL()" << LL_ENDL; + return ACCEPT_NO; } EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezAttachmentFromInv()" << LL_ENDL; - // must be in the user's inventory - if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) - { - return ACCEPT_NO; - } - - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - - // must not be in the trash - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) - { - return ACCEPT_NO; - } - - // must not be already wearing it - LLVOAvatarSelf* avatar = gAgentAvatarp; - if( !avatar || avatar->isWearingAttachment(item->getUUID()) ) - { - return ACCEPT_NO; - } - - const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); - if(outbox_id.notNull() && gInventory.isObjectDescendentOf(item->getUUID(), outbox_id)) - { - // Legacy - return ACCEPT_NO; - } - - - if( drop ) - { - if(mSource == SOURCE_LIBRARY) - { - LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - rez_attachment(item, 0); - } - } - return ACCEPT_YES_SINGLE; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezAttachmentFromInv()" << LL_ENDL; + // must be in the user's inventory + if(mSource != SOURCE_AGENT && mSource != SOURCE_LIBRARY) + { + return ACCEPT_NO; + } + + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + + // must not be in the trash + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) + { + return ACCEPT_NO; + } + + // must not be already wearing it + LLVOAvatarSelf* avatar = gAgentAvatarp; + if( !avatar || avatar->isWearingAttachment(item->getUUID()) ) + { + return ACCEPT_NO; + } + + const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); + if(outbox_id.notNull() && gInventory.isObjectDescendentOf(item->getUUID(), outbox_id)) + { + // Legacy + return ACCEPT_NO; + } + + + if( drop ) + { + if(mSource == SOURCE_LIBRARY) + { + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + rez_attachment(item, 0); + } + } + return ACCEPT_YES_SINGLE; +} + + +EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + if (mSource == SOURCE_WORLD) + { + return dad3dRezFromObjectOnLand(obj, face, mask, drop); + } + + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezObjectOnLand()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + + LLVOAvatarSelf* my_avatar = gAgentAvatarp; + if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) + { + return ACCEPT_NO; + } + + EAcceptance accept; + BOOL remove_inventory; + + // Get initial settings based on shift key + if (mask & MASK_SHIFT) + { + // For now, always make copy + //accept = ACCEPT_YES_SINGLE; + //remove_inventory = TRUE; + accept = ACCEPT_YES_COPY_SINGLE; + remove_inventory = FALSE; + } + else + { + accept = ACCEPT_YES_COPY_SINGLE; + remove_inventory = FALSE; + } + + // check if the item can be copied. If not, send that to the sim + // which will remove the inventory item. + if(!item->getPermissions().allowCopyBy(gAgent.getID())) + { + accept = ACCEPT_YES_SINGLE; + remove_inventory = TRUE; + } + + // Check if it's in the trash. + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + accept = ACCEPT_YES_SINGLE; + } + + if(drop) + { + dropObject(obj, TRUE, FALSE, remove_inventory); + } + + return accept; +} + +EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + // handle objects coming from object inventory + if (mSource == SOURCE_WORLD) + { + return dad3dRezFromObjectOnObject(obj, face, mask, drop); + } + + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezObjectOnObject()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + LLVOAvatarSelf* my_avatar = gAgentAvatarp; + if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) + { + return ACCEPT_NO; + } + + if((mask & MASK_CONTROL)) + { + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if(mSource == SOURCE_NOTECARD) + { + return ACCEPT_NO; + } + + EAcceptance rv = willObjectAcceptInventory(obj, item); + if(drop && (ACCEPT_YES_SINGLE <= rv)) + { + dropInventory(obj, item, mSource, mSourceID); + } + return rv; + } + + EAcceptance accept; + BOOL remove_inventory; + + if (mask & MASK_SHIFT) + { + // For now, always make copy + //accept = ACCEPT_YES_SINGLE; + //remove_inventory = TRUE; + accept = ACCEPT_YES_COPY_SINGLE; + remove_inventory = FALSE; + } + else + { + accept = ACCEPT_YES_COPY_SINGLE; + remove_inventory = FALSE; + } + + // check if the item can be copied. If not, send that to the sim + // which will remove the inventory item. + if(!item->getPermissions().allowCopyBy(gAgent.getID())) + { + accept = ACCEPT_YES_SINGLE; + remove_inventory = TRUE; + } + + // Check if it's in the trash. + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) + { + accept = ACCEPT_YES_SINGLE; + remove_inventory = TRUE; + } + + if(drop) + { + dropObject(obj, FALSE, FALSE, remove_inventory); + } + + return accept; } +EAcceptance LLToolDragAndDrop::dad3dRezScript( + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezScript()" << LL_ENDL; + + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) + { + return ACCEPT_NO; + } -EAcceptance LLToolDragAndDrop::dad3dRezObjectOnLand( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - if (mSource == SOURCE_WORLD) - { - return dad3dRezFromObjectOnLand(obj, face, mask, drop); - } - - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezObjectOnLand()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - - LLVOAvatarSelf* my_avatar = gAgentAvatarp; - if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) - { - return ACCEPT_NO; - } - - EAcceptance accept; - BOOL remove_inventory; - - // Get initial settings based on shift key - if (mask & MASK_SHIFT) - { - // For now, always make copy - //accept = ACCEPT_YES_SINGLE; - //remove_inventory = TRUE; - accept = ACCEPT_YES_COPY_SINGLE; - remove_inventory = FALSE; - } - else - { - accept = ACCEPT_YES_COPY_SINGLE; - remove_inventory = FALSE; - } - - // check if the item can be copied. If not, send that to the sim - // which will remove the inventory item. - if(!item->getPermissions().allowCopyBy(gAgent.getID())) - { - accept = ACCEPT_YES_SINGLE; - remove_inventory = TRUE; - } - - // Check if it's in the trash. - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) - { - accept = ACCEPT_YES_SINGLE; - } - - if(drop) - { - dropObject(obj, TRUE, FALSE, remove_inventory); - } - - return accept; -} + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + EAcceptance rv = willObjectAcceptInventory(obj, item); + if(drop && (ACCEPT_YES_SINGLE <= rv)) + { + // rez in the script active by default, rez in inactive if the + // control key is being held down. + BOOL active = ((mask & MASK_CONTROL) == 0); -EAcceptance LLToolDragAndDrop::dad3dRezObjectOnObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - // handle objects coming from object inventory - if (mSource == SOURCE_WORLD) - { - return dad3dRezFromObjectOnObject(obj, face, mask, drop); - } - - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezObjectOnObject()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - LLVOAvatarSelf* my_avatar = gAgentAvatarp; - if( !my_avatar || my_avatar->isWearingAttachment( item->getUUID() ) ) - { - return ACCEPT_NO; - } - - if((mask & MASK_CONTROL)) - { - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if(mSource == SOURCE_NOTECARD) - { - return ACCEPT_NO; - } - - EAcceptance rv = willObjectAcceptInventory(obj, item); - if(drop && (ACCEPT_YES_SINGLE <= rv)) - { - dropInventory(obj, item, mSource, mSourceID); - } - return rv; - } - - EAcceptance accept; - BOOL remove_inventory; - - if (mask & MASK_SHIFT) - { - // For now, always make copy - //accept = ACCEPT_YES_SINGLE; - //remove_inventory = TRUE; - accept = ACCEPT_YES_COPY_SINGLE; - remove_inventory = FALSE; - } - else - { - accept = ACCEPT_YES_COPY_SINGLE; - remove_inventory = FALSE; - } - - // check if the item can be copied. If not, send that to the sim - // which will remove the inventory item. - if(!item->getPermissions().allowCopyBy(gAgent.getID())) - { - accept = ACCEPT_YES_SINGLE; - remove_inventory = TRUE; - } - - // Check if it's in the trash. - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(item->getUUID(), trash_id)) - { - accept = ACCEPT_YES_SINGLE; - remove_inventory = TRUE; - } - - if(drop) - { - dropObject(obj, FALSE, FALSE, remove_inventory); - } - - return accept; -} + LLViewerObject* root_object = obj; + if (obj && obj->getParent()) + { + LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); + if (!parent_obj->isAvatar()) + { + root_object = parent_obj; + } + } -EAcceptance LLToolDragAndDrop::dad3dRezScript( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezScript()" << LL_ENDL; - - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) - { - return ACCEPT_NO; - } - - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - EAcceptance rv = willObjectAcceptInventory(obj, item); - if(drop && (ACCEPT_YES_SINGLE <= rv)) - { - // rez in the script active by default, rez in inactive if the - // control key is being held down. - BOOL active = ((mask & MASK_CONTROL) == 0); - - LLViewerObject* root_object = obj; - if (obj && obj->getParent()) - { - LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); - if (!parent_obj->isAvatar()) - { - root_object = parent_obj; - } - } - - dropScript(root_object, item, active, mSource, mSourceID); - } - return rv; + dropScript(root_object, item, active, mSource, mSourceID); + } + return rv; } EAcceptance LLToolDragAndDrop::dad3dApplyToObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop, EDragAndDropType cargo_type) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dApplyToObject()" << LL_ENDL; - - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) - { - return ACCEPT_NO; - } - - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop, EDragAndDropType cargo_type) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dApplyToObject()" << LL_ENDL; + + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) + { + return ACCEPT_NO; + } + + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; LLPermissions item_permissions = item->getPermissions(); - EAcceptance rv = willObjectAcceptInventory(obj, item); - if((mask & MASK_CONTROL)) - { - if((ACCEPT_YES_SINGLE <= rv) && drop) - { - dropInventory(obj, item, mSource, mSourceID); - } - return rv; - } - if(!obj->permModify()) - { - return ACCEPT_NO_LOCKED; - } + EAcceptance rv = willObjectAcceptInventory(obj, item); + if((mask & MASK_CONTROL)) + { + if((ACCEPT_YES_SINGLE <= rv) && drop) + { + dropInventory(obj, item, mSource, mSourceID); + } + return rv; + } + if(!obj->permModify()) + { + return ACCEPT_NO_LOCKED; + } if (cargo_type == DAD_TEXTURE && (mask & MASK_ALT) == 0) { @@ -2389,10 +2389,10 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( } } - if(drop && (ACCEPT_YES_SINGLE <= rv)) - { - if (cargo_type == DAD_TEXTURE) - { + if(drop && (ACCEPT_YES_SINGLE <= rv)) + { + if (cargo_type == DAD_TEXTURE) + { bool all_faces = mask & MASK_SHIFT; bool remove_pbr = mask & MASK_ALT; if (item_permissions.allowOperationBy(PERM_COPY, gAgent.getID())) @@ -2414,7 +2414,7 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( dropTexture(obj, face, item, source, source_id, all_faces, remove_pbr); }); } - } + } else if (cargo_type == DAD_MATERIAL) { bool all_faces = mask & MASK_SHIFT; @@ -2438,32 +2438,32 @@ EAcceptance LLToolDragAndDrop::dad3dApplyToObject( }); } } - else if (cargo_type == DAD_MESH) - { - dropMesh(obj, item, mSource, mSourceID); - } - else - { - LL_WARNS() << "unsupported asset type" << LL_ENDL; - } - - // VEFFECT: SetTexture - LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); - effectp->setSourceObject(gAgentAvatarp); - effectp->setTargetObject(obj); - effectp->setDuration(LL_HUD_DUR_SHORT); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - } + else if (cargo_type == DAD_MESH) + { + dropMesh(obj, item, mSource, mSourceID); + } + else + { + LL_WARNS() << "unsupported asset type" << LL_ENDL; + } + + // VEFFECT: SetTexture + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); + effectp->setSourceObject(gAgentAvatarp); + effectp->setTargetObject(obj); + effectp->setDuration(LL_HUD_DUR_SHORT); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + } - // enable multi-drop, although last texture will win - return ACCEPT_YES_MULTI; + // enable multi-drop, although last texture will win + return ACCEPT_YES_MULTI; } EAcceptance LLToolDragAndDrop::dad3dTextureObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { - return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE); + return dad3dApplyToObject(obj, face, mask, drop, DAD_TEXTURE); } EAcceptance LLToolDragAndDrop::dad3dMaterialObject( @@ -2473,506 +2473,506 @@ EAcceptance LLToolDragAndDrop::dad3dMaterialObject( } EAcceptance LLToolDragAndDrop::dad3dMeshObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { - return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH); + return dad3dApplyToObject(obj, face, mask, drop, DAD_MESH); } EAcceptance LLToolDragAndDrop::dad3dWearItem( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dWearItem()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - - if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) - { - // it's in the agent inventory - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) - { - return ACCEPT_NO; - } - - if( drop ) - { - // TODO: investigate wearables may not be loaded at this point EXT-8231 - - LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(),true, !(mask & MASK_CONTROL)); - } - return ACCEPT_YES_MULTI; - } - else - { - // TODO: copy/move item to avatar's inventory and then wear it. - return ACCEPT_NO; - } + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dWearItem()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + + if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) + { + // it's in the agent inventory + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) + { + return ACCEPT_NO; + } + + if( drop ) + { + // TODO: investigate wearables may not be loaded at this point EXT-8231 + + LLAppearanceMgr::instance().wearItemOnAvatar(item->getUUID(),true, !(mask & MASK_CONTROL)); + } + return ACCEPT_YES_MULTI; + } + else + { + // TODO: copy/move item to avatar's inventory and then wear it. + return ACCEPT_NO; + } } EAcceptance LLToolDragAndDrop::dad3dActivateGesture( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dActivateGesture()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - - if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) - { - // it's in the agent inventory - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) - { - return ACCEPT_NO; - } - - if( drop ) - { - LLUUID item_id; - if(mSource == SOURCE_LIBRARY) - { - // create item based on that one, and put it on if that - // was a success. - LLPointer cb = new LLBoostFuncInventoryCallback(activate_gesture_cb); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - LLGestureMgr::instance().activateGesture(item->getUUID()); - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - } - return ACCEPT_YES_MULTI; - } - else - { - return ACCEPT_NO; - } + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dActivateGesture()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + + if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY) + { + // it's in the agent inventory + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) ) + { + return ACCEPT_NO; + } + + if( drop ) + { + LLUUID item_id; + if(mSource == SOURCE_LIBRARY) + { + // create item based on that one, and put it on if that + // was a success. + LLPointer cb = new LLBoostFuncInventoryCallback(activate_gesture_cb); + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + LLUUID::null, + std::string(), + cb); + } + else + { + LLGestureMgr::instance().activateGesture(item->getUUID()); + gInventory.updateItem(item); + gInventory.notifyObservers(); + } + } + return ACCEPT_YES_MULTI; + } + else + { + return ACCEPT_NO; + } } EAcceptance LLToolDragAndDrop::dad3dWearCategory( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dWearCategory()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* category; - locateInventory(item, category); - if(!category) return ACCEPT_NO; - - if (drop) - { - // TODO: investigate wearables may not be loaded at this point EXT-8231 - } - - U32 max_items = gSavedSettings.getU32("WearFolderLimit"); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(category->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - if (items.size() > max_items) - { - LLStringUtil::format_map_t args; - args["AMOUNT"] = llformat("%d", max_items); - mCustomMsg = LLTrans::getString("TooltipTooManyWearables",args); - return ACCEPT_NO_CUSTOM; - } - - if(mSource == SOURCE_AGENT) - { - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) ) - { - return ACCEPT_NO; - } - - const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); - if(outbox_id.notNull() && gInventory.isObjectDescendentOf(category->getUUID(), outbox_id)) - { - // Legacy - return ACCEPT_NO; - } - - if(drop) - { - BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE ); - LLAppearanceMgr::instance().wearInventoryCategory(category, false, append); - } - return ACCEPT_YES_MULTI; - } - else if(mSource == SOURCE_LIBRARY) - { - if(drop) - { - LLAppearanceMgr::instance().wearInventoryCategory(category, true, false); - } - return ACCEPT_YES_MULTI; - } - else - { - // TODO: copy/move category to avatar's inventory and then wear it. - return ACCEPT_NO; - } + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dWearCategory()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* category; + locateInventory(item, category); + if(!category) return ACCEPT_NO; + + if (drop) + { + // TODO: investigate wearables may not be loaded at this point EXT-8231 + } + + U32 max_items = gSavedSettings.getU32("WearFolderLimit"); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + gInventory.collectDescendentsIf(category->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + not_worn); + if (items.size() > max_items) + { + LLStringUtil::format_map_t args; + args["AMOUNT"] = llformat("%d", max_items); + mCustomMsg = LLTrans::getString("TooltipTooManyWearables",args); + return ACCEPT_NO_CUSTOM; + } + + if(mSource == SOURCE_AGENT) + { + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if( gInventory.isObjectDescendentOf( category->getUUID(), trash_id ) ) + { + return ACCEPT_NO; + } + + const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); + if(outbox_id.notNull() && gInventory.isObjectDescendentOf(category->getUUID(), outbox_id)) + { + // Legacy + return ACCEPT_NO; + } + + if(drop) + { + BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE ); + LLAppearanceMgr::instance().wearInventoryCategory(category, false, append); + } + return ACCEPT_YES_MULTI; + } + else if(mSource == SOURCE_LIBRARY) + { + if(drop) + { + LLAppearanceMgr::instance().wearInventoryCategory(category, true, false); + } + return ACCEPT_YES_MULTI; + } + else + { + // TODO: copy/move category to avatar's inventory and then wear it. + return ACCEPT_NO; + } } EAcceptance LLToolDragAndDrop::dad3dUpdateInventory( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dadUpdateInventory()" << LL_ENDL; - - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) - { - return ACCEPT_NO; - } - - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - LLViewerObject* root_object = obj; - if (obj && obj->getParent()) - { - LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); - if (!parent_obj->isAvatar()) - { - root_object = parent_obj; - } - } - - EAcceptance rv = willObjectAcceptInventory(root_object, item); - if(root_object && drop && (ACCEPT_YES_COPY_SINGLE <= rv)) - { - dropInventory(root_object, item, mSource, mSourceID); - } - return rv; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dadUpdateInventory()" << LL_ENDL; + + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + if((SOURCE_WORLD == mSource) || (SOURCE_NOTECARD == mSource)) + { + return ACCEPT_NO; + } + + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + LLViewerObject* root_object = obj; + if (obj && obj->getParent()) + { + LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); + if (!parent_obj->isAvatar()) + { + root_object = parent_obj; + } + } + + EAcceptance rv = willObjectAcceptInventory(root_object, item); + if(root_object && drop && (ACCEPT_YES_COPY_SINGLE <= rv)) + { + dropInventory(root_object, item, mSource, mSourceID); + } + return rv; } BOOL LLToolDragAndDrop::dadUpdateInventory(LLViewerObject* obj, BOOL drop) { - EAcceptance rv = dad3dUpdateInventory(obj, -1, MASK_NONE, drop); - return (rv >= ACCEPT_YES_COPY_SINGLE); + EAcceptance rv = dad3dUpdateInventory(obj, -1, MASK_NONE, drop); + return (rv >= ACCEPT_YES_COPY_SINGLE); } EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << LL_ENDL; - if (obj == NULL) - { - LL_WARNS() << "obj is NULL; aborting func with ACCEPT_NO" << LL_ENDL; - return ACCEPT_NO; - } - - if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY)) - { - return ACCEPT_NO; - } - if (obj->isAttachment()) - { - return ACCEPT_NO_LOCKED; - } - - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - locateInventory(item, cat); - if (!cat) - { - return ACCEPT_NO; - } - - // Find all the items in the category - LLDroppableItem droppable(!obj->permYouOwner()); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendentsIf(cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - droppable); - cats.push_back(cat); - if (droppable.countNoCopy() > 0) - { - LL_WARNS() << "*** Need to confirm this step" << LL_ENDL; - } - LLViewerObject* root_object = obj; - if (obj->getParent()) - { - LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); - if (!parent_obj->isAvatar()) - { - root_object = parent_obj; - } - } - - EAcceptance rv = ACCEPT_NO; - - // Check for accept - for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); - cat_iter != cats.end(); - ++cat_iter) - { - const LLViewerInventoryCategory *cat = (*cat_iter); - rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; - if(rv < ACCEPT_YES_SINGLE) - { - LL_DEBUGS() << "Category " << cat->getUUID() << "is not complete." << LL_ENDL; - break; - } - } - if (ACCEPT_YES_COPY_SINGLE <= rv) - { - for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); - item_iter != items.end(); - ++item_iter) - { - LLViewerInventoryItem *item = (*item_iter); - /* - // Pass the base objects, not the links. - if (item && item->getIsLinkType()) - { - item = item->getLinkedItem(); - (*item_iter) = item; - } - */ - rv = willObjectAcceptInventory(root_object, item, DAD_CATEGORY); - if (rv < ACCEPT_YES_COPY_SINGLE) - { - LL_DEBUGS() << "Object will not accept " << item->getUUID() << LL_ENDL; - break; - } - } - } - - // If every item is accepted, send it on - if (drop && (ACCEPT_YES_COPY_SINGLE <= rv)) - { - uuid_vec_t ids; - for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); - item_iter != items.end(); - ++item_iter) - { - const LLViewerInventoryItem *item = (*item_iter); - ids.push_back(item->getUUID()); - } - LLCategoryDropObserver* dropper = new LLCategoryDropObserver(ids, obj->getID(), mSource); - dropper->startFetch(); - if (dropper->isFinished()) - { - dropper->done(); - } - else - { - gInventory.addObserver(dropper); - } - } - return rv; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dUpdateInventoryCategory()" << LL_ENDL; + if (obj == NULL) + { + LL_WARNS() << "obj is NULL; aborting func with ACCEPT_NO" << LL_ENDL; + return ACCEPT_NO; + } + + if ((mSource != SOURCE_AGENT) && (mSource != SOURCE_LIBRARY)) + { + return ACCEPT_NO; + } + if (obj->isAttachment()) + { + return ACCEPT_NO_LOCKED; + } + + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + locateInventory(item, cat); + if (!cat) + { + return ACCEPT_NO; + } + + // Find all the items in the category + LLDroppableItem droppable(!obj->permYouOwner()); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendentsIf(cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + droppable); + cats.push_back(cat); + if (droppable.countNoCopy() > 0) + { + LL_WARNS() << "*** Need to confirm this step" << LL_ENDL; + } + LLViewerObject* root_object = obj; + if (obj->getParent()) + { + LLViewerObject* parent_obj = (LLViewerObject*)obj->getParent(); + if (!parent_obj->isAvatar()) + { + root_object = parent_obj; + } + } + + EAcceptance rv = ACCEPT_NO; + + // Check for accept + for (LLInventoryModel::cat_array_t::const_iterator cat_iter = cats.begin(); + cat_iter != cats.end(); + ++cat_iter) + { + const LLViewerInventoryCategory *cat = (*cat_iter); + rv = gInventory.isCategoryComplete(cat->getUUID()) ? ACCEPT_YES_MULTI : ACCEPT_NO; + if(rv < ACCEPT_YES_SINGLE) + { + LL_DEBUGS() << "Category " << cat->getUUID() << "is not complete." << LL_ENDL; + break; + } + } + if (ACCEPT_YES_COPY_SINGLE <= rv) + { + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + LLViewerInventoryItem *item = (*item_iter); + /* + // Pass the base objects, not the links. + if (item && item->getIsLinkType()) + { + item = item->getLinkedItem(); + (*item_iter) = item; + } + */ + rv = willObjectAcceptInventory(root_object, item, DAD_CATEGORY); + if (rv < ACCEPT_YES_COPY_SINGLE) + { + LL_DEBUGS() << "Object will not accept " << item->getUUID() << LL_ENDL; + break; + } + } + } + + // If every item is accepted, send it on + if (drop && (ACCEPT_YES_COPY_SINGLE <= rv)) + { + uuid_vec_t ids; + for (LLInventoryModel::item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLViewerInventoryItem *item = (*item_iter); + ids.push_back(item->getUUID()); + } + LLCategoryDropObserver* dropper = new LLCategoryDropObserver(ids, obj->getID(), mSource); + dropper->startFetch(); + if (dropper->isFinished()) + { + dropper->done(); + } + else + { + gInventory.addObserver(dropper); + } + } + return rv; } EAcceptance LLToolDragAndDrop::dad3dRezCategoryOnObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { - if ((mask & MASK_CONTROL)) - { - return dad3dUpdateInventoryCategory(obj, face, mask, drop); - } - else - { - return ACCEPT_NO; - } + if ((mask & MASK_CONTROL)) + { + return dad3dUpdateInventoryCategory(obj, face, mask, drop); + } + else + { + return ACCEPT_NO; + } } BOOL LLToolDragAndDrop::dadUpdateInventoryCategory(LLViewerObject* obj, - BOOL drop) + BOOL drop) { - EAcceptance rv = dad3dUpdateInventoryCategory(obj, -1, MASK_NONE, drop); - return (rv >= ACCEPT_YES_COPY_SINGLE); + EAcceptance rv = dad3dUpdateInventoryCategory(obj, -1, MASK_NONE, drop); + return (rv >= ACCEPT_YES_COPY_SINGLE); } EAcceptance LLToolDragAndDrop::dad3dGiveInventoryObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventoryObject()" << LL_ENDL; - - // item has to be in agent inventory. - if(mSource != SOURCE_AGENT) return ACCEPT_NO; - - // find the item now. - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - // cannot give away no-transfer objects - return ACCEPT_NO; - } - LLVOAvatarSelf* avatar = gAgentAvatarp; - if(avatar && avatar->isWearingAttachment( item->getUUID() ) ) - { - // You can't give objects that are attached to you - return ACCEPT_NO; - } - if( obj && avatar ) - { - if(drop) - { - LLGiveInventory::doGiveInventoryItem(obj->getID(), item ); - } - // *TODO: deal with all the issues surrounding multi-object - // inventory transfers. - return ACCEPT_YES_SINGLE; - } - return ACCEPT_NO; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventoryObject()" << LL_ENDL; + + // item has to be in agent inventory. + if(mSource != SOURCE_AGENT) return ACCEPT_NO; + + // find the item now. + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + if(!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) + { + // cannot give away no-transfer objects + return ACCEPT_NO; + } + LLVOAvatarSelf* avatar = gAgentAvatarp; + if(avatar && avatar->isWearingAttachment( item->getUUID() ) ) + { + // You can't give objects that are attached to you + return ACCEPT_NO; + } + if( obj && avatar ) + { + if(drop) + { + LLGiveInventory::doGiveInventoryItem(obj->getID(), item ); + } + // *TODO: deal with all the issues surrounding multi-object + // inventory transfers. + return ACCEPT_YES_SINGLE; + } + return ACCEPT_NO; } EAcceptance LLToolDragAndDrop::dad3dGiveInventory( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventory()" << LL_ENDL; - // item has to be in agent inventory. - if(mSource != SOURCE_AGENT) return ACCEPT_NO; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - if (!LLGiveInventory::isInventoryGiveAcceptable(item)) - { - return ACCEPT_NO; - } - if (drop && obj) - { - LLGiveInventory::doGiveInventoryItem(obj->getID(), item); - } - // *TODO: deal with all the issues surrounding multi-object - // inventory transfers. - return ACCEPT_YES_SINGLE; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventory()" << LL_ENDL; + // item has to be in agent inventory. + if(mSource != SOURCE_AGENT) return ACCEPT_NO; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + if (!LLGiveInventory::isInventoryGiveAcceptable(item)) + { + return ACCEPT_NO; + } + if (drop && obj) + { + LLGiveInventory::doGiveInventoryItem(obj->getID(), item); + } + // *TODO: deal with all the issues surrounding multi-object + // inventory transfers. + return ACCEPT_YES_SINGLE; } EAcceptance LLToolDragAndDrop::dad3dGiveInventoryCategory( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) { - LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventoryCategory()" << LL_ENDL; - if(drop && obj) - { - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if(!cat) return ACCEPT_NO; - LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat); - } - // *TODO: deal with all the issues surrounding multi-object - // inventory transfers. - return ACCEPT_YES_SINGLE; + LL_DEBUGS() << "LLToolDragAndDrop::dad3dGiveInventoryCategory()" << LL_ENDL; + if(drop && obj) + { + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if(!cat) return ACCEPT_NO; + LLGiveInventory::doGiveInventoryCategory(obj->getID(), cat); + } + // *TODO: deal with all the issues surrounding multi-object + // inventory transfers. + return ACCEPT_YES_SINGLE; } EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnLand( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << LL_ENDL; - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - - if(!gAgent.allowOperation(PERM_COPY, item->getPermissions()) - || !item->getPermissions().allowTransferTo(LLUUID::null)) - { - return ACCEPT_NO_LOCKED; - } - if(drop) - { - dropObject(obj, TRUE, TRUE, FALSE); - } - return ACCEPT_YES_SINGLE; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezFromObjectOnLand()" << LL_ENDL; + LLViewerInventoryItem* item = NULL; + LLViewerInventoryCategory* cat = NULL; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + + if(!gAgent.allowOperation(PERM_COPY, item->getPermissions()) + || !item->getPermissions().allowTransferTo(LLUUID::null)) + { + return ACCEPT_NO_LOCKED; + } + if(drop) + { + dropObject(obj, TRUE, TRUE, FALSE); + } + return ACCEPT_YES_SINGLE; } EAcceptance LLToolDragAndDrop::dad3dRezFromObjectOnObject( - LLViewerObject* obj, S32 face, MASK mask, BOOL drop) -{ - LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << LL_ENDL; - LLViewerInventoryItem* item; - LLViewerInventoryCategory* cat; - locateInventory(item, cat); - if (!item || !item->isFinished()) return ACCEPT_NO; - if((mask & MASK_CONTROL)) - { - // *HACK: In order to resolve SL-22177, we need to block drags - // from notecards and objects onto other objects. - return ACCEPT_NO; - - // *HACK: uncomment this when appropriate - //EAcceptance rv = willObjectAcceptInventory(obj, item); - //if(drop && (ACCEPT_YES_SINGLE <= rv)) - //{ - // dropInventory(obj, item, mSource, mSourceID); - //} - //return rv; - } - if(!item->getPermissions().allowCopyBy(gAgent.getID(), - gAgent.getGroupID()) - || !item->getPermissions().allowTransferTo(LLUUID::null)) - { - return ACCEPT_NO_LOCKED; - } - if(drop) - { - dropObject(obj, FALSE, TRUE, FALSE); - } - return ACCEPT_YES_SINGLE; + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + LL_DEBUGS() << "LLToolDragAndDrop::dad3dRezFromObjectOnObject()" << LL_ENDL; + LLViewerInventoryItem* item; + LLViewerInventoryCategory* cat; + locateInventory(item, cat); + if (!item || !item->isFinished()) return ACCEPT_NO; + if((mask & MASK_CONTROL)) + { + // *HACK: In order to resolve SL-22177, we need to block drags + // from notecards and objects onto other objects. + return ACCEPT_NO; + + // *HACK: uncomment this when appropriate + //EAcceptance rv = willObjectAcceptInventory(obj, item); + //if(drop && (ACCEPT_YES_SINGLE <= rv)) + //{ + // dropInventory(obj, item, mSource, mSourceID); + //} + //return rv; + } + if(!item->getPermissions().allowCopyBy(gAgent.getID(), + gAgent.getGroupID()) + || !item->getPermissions().allowTransferTo(LLUUID::null)) + { + return ACCEPT_NO_LOCKED; + } + if(drop) + { + dropObject(obj, FALSE, TRUE, FALSE); + } + return ACCEPT_YES_SINGLE; } EAcceptance LLToolDragAndDrop::dad3dCategoryOnLand( - LLViewerObject *obj, S32 face, MASK mask, BOOL drop) -{ - return ACCEPT_NO; - /* - LL_DEBUGS() << "LLToolDragAndDrop::dad3dCategoryOnLand()" << LL_ENDL; - LLInventoryItem* item; - LLInventoryCategory* cat; - locateInventory(item, cat); - if(!cat) return ACCEPT_NO; - EAcceptance rv = ACCEPT_NO; - - // find all the items in the category - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLDropCopyableItems droppable; - gInventory.collectDescendentsIf(cat->getUUID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - droppable); - if(items.size() > 0) - { - rv = ACCEPT_YES_SINGLE; - } - if((rv >= ACCEPT_YES_COPY_SINGLE) && drop) - { - createContainer(items, cat->getName()); - return ACCEPT_NO; - } - return rv; - */ + LLViewerObject *obj, S32 face, MASK mask, BOOL drop) +{ + return ACCEPT_NO; + /* + LL_DEBUGS() << "LLToolDragAndDrop::dad3dCategoryOnLand()" << LL_ENDL; + LLInventoryItem* item; + LLInventoryCategory* cat; + locateInventory(item, cat); + if(!cat) return ACCEPT_NO; + EAcceptance rv = ACCEPT_NO; + + // find all the items in the category + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLDropCopyableItems droppable; + gInventory.collectDescendentsIf(cat->getUUID(), + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + droppable); + if(items.size() > 0) + { + rv = ACCEPT_YES_SINGLE; + } + if((rv >= ACCEPT_YES_COPY_SINGLE) && drop) + { + createContainer(items, cat->getName()); + return ACCEPT_NO; + } + return rv; + */ } @@ -2980,163 +2980,163 @@ EAcceptance LLToolDragAndDrop::dad3dCategoryOnLand( // This shortcuts alot of steps to make a basic object // w/ an inventory and a special permissions set EAcceptance LLToolDragAndDrop::dad3dAssetOnLand( - LLViewerObject *obj, S32 face, MASK mask, BOOL drop) -{ - return ACCEPT_NO; - /* - LL_DEBUGS() << "LLToolDragAndDrop::dad3dAssetOnLand()" << LL_ENDL; - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLViewerInventoryItem::item_array_t copyable_items; - locateMultipleInventory(items, cats); - if(!items.size()) return ACCEPT_NO; - EAcceptance rv = ACCEPT_NO; - for (S32 i = 0; i < items.size(); i++) - { - LLInventoryItem* item = items[i]; - if(item->getPermissions().allowCopyBy(gAgent.getID())) - { - copyable_items.push_back(item); - rv = ACCEPT_YES_SINGLE; - } - } - - if((rv >= ACCEPT_YES_COPY_SINGLE) && drop) - { - createContainer(copyable_items, NULL); - } - - return rv; - */ + LLViewerObject *obj, S32 face, MASK mask, BOOL drop) +{ + return ACCEPT_NO; + /* + LL_DEBUGS() << "LLToolDragAndDrop::dad3dAssetOnLand()" << LL_ENDL; + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLViewerInventoryItem::item_array_t copyable_items; + locateMultipleInventory(items, cats); + if(!items.size()) return ACCEPT_NO; + EAcceptance rv = ACCEPT_NO; + for (S32 i = 0; i < items.size(); i++) + { + LLInventoryItem* item = items[i]; + if(item->getPermissions().allowCopyBy(gAgent.getID())) + { + copyable_items.push_back(item); + rv = ACCEPT_YES_SINGLE; + } + } + + if((rv >= ACCEPT_YES_COPY_SINGLE) && drop) + { + createContainer(copyable_items, NULL); + } + + return rv; + */ } LLInventoryObject* LLToolDragAndDrop::locateInventory( - LLViewerInventoryItem*& item, - LLViewerInventoryCategory*& cat) -{ - item = NULL; - cat = NULL; - - if (mCargoIDs.empty() - || (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. - { - return NULL; - } - - if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) - { - // The object should be in user inventory. - item = (LLViewerInventoryItem*)gInventory.getItem(mCargoIDs[mCurItemIndex]); - cat = (LLViewerInventoryCategory*)gInventory.getCategory(mCargoIDs[mCurItemIndex]); - } - else if(mSource == SOURCE_WORLD) - { - // This object is in some task inventory somewhere. - LLViewerObject* obj = gObjectList.findObject(mSourceID); - if(obj) - { - if((mCargoTypes[mCurItemIndex] == DAD_CATEGORY) - || (mCargoTypes[mCurItemIndex] == DAD_ROOT_CATEGORY)) - { - cat = (LLViewerInventoryCategory*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]); - } - else - { - item = (LLViewerInventoryItem*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]); - } - } - } - else if(mSource == SOURCE_NOTECARD) - { - LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance("preview_notecard", mSourceID); - if(preview) - { - item = (LLViewerInventoryItem*)preview->getDragItem(); - } - } - else if(mSource == SOURCE_VIEWER) - { - item = (LLViewerInventoryItem*)gToolBarView->getDragItem(); - } - - if(item) return item; - if(cat) return cat; - return NULL; + LLViewerInventoryItem*& item, + LLViewerInventoryCategory*& cat) +{ + item = NULL; + cat = NULL; + + if (mCargoIDs.empty() + || (mSource == SOURCE_PEOPLE)) ///< There is no inventory item for people drag and drop. + { + return NULL; + } + + if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) + { + // The object should be in user inventory. + item = (LLViewerInventoryItem*)gInventory.getItem(mCargoIDs[mCurItemIndex]); + cat = (LLViewerInventoryCategory*)gInventory.getCategory(mCargoIDs[mCurItemIndex]); + } + else if(mSource == SOURCE_WORLD) + { + // This object is in some task inventory somewhere. + LLViewerObject* obj = gObjectList.findObject(mSourceID); + if(obj) + { + if((mCargoTypes[mCurItemIndex] == DAD_CATEGORY) + || (mCargoTypes[mCurItemIndex] == DAD_ROOT_CATEGORY)) + { + cat = (LLViewerInventoryCategory*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]); + } + else + { + item = (LLViewerInventoryItem*)obj->getInventoryObject(mCargoIDs[mCurItemIndex]); + } + } + } + else if(mSource == SOURCE_NOTECARD) + { + LLPreviewNotecard* preview = LLFloaterReg::findTypedInstance("preview_notecard", mSourceID); + if(preview) + { + item = (LLViewerInventoryItem*)preview->getDragItem(); + } + } + else if(mSource == SOURCE_VIEWER) + { + item = (LLViewerInventoryItem*)gToolBarView->getDragItem(); + } + + if(item) return item; + if(cat) return cat; + return NULL; } /* LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryCategory::cat_array_t& cats, - LLViewerInventoryItem::item_array_t& items) -{ - if(mCargoIDs.size() == 0) return NULL; - if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) - { - // The object should be in user inventory. - for (S32 i = 0; i < mCargoIDs.size(); i++) - { - LLInventoryItem* item = gInventory.getItem(mCargoIDs[i]); - if (item) - { - items.push_back(item); - } - LLInventoryCategory* category = gInventory.getCategory(mCargoIDs[i]); - if (category) - { - cats.push_back(category); - } - } - } - else if(mSource == SOURCE_WORLD) - { - // This object is in some task inventory somewhere. - LLViewerObject* obj = gObjectList.findObject(mSourceID); - if(obj) - { - if((mCargoType == DAD_CATEGORY) - || (mCargoType == DAD_ROOT_CATEGORY)) - { - // The object should be in user inventory. - for (S32 i = 0; i < mCargoIDs.size(); i++) - { - LLInventoryCategory* category = (LLInventoryCategory*)obj->getInventoryObject(mCargoIDs[i]); - if (category) - { - cats.push_back(category); - } - } - } - else - { - for (S32 i = 0; i < mCargoIDs.size(); i++) - { - LLInventoryItem* item = (LLInventoryItem*)obj->getInventoryObject(mCargoIDs[i]); - if (item) - { - items.push_back(item); - } - } - } - } - } - else if(mSource == SOURCE_NOTECARD) - { - LLPreviewNotecard* card; - card = (LLPreviewNotecard*)LLPreview::find(mSourceID); - if(card) - { - items.push_back((LLInventoryItem*)card->getDragItem()); - } - } - if(items.size()) return items[0]; - if(cats.size()) return cats[0]; - return NULL; + LLViewerInventoryItem::item_array_t& items) +{ + if(mCargoIDs.size() == 0) return NULL; + if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) + { + // The object should be in user inventory. + for (S32 i = 0; i < mCargoIDs.size(); i++) + { + LLInventoryItem* item = gInventory.getItem(mCargoIDs[i]); + if (item) + { + items.push_back(item); + } + LLInventoryCategory* category = gInventory.getCategory(mCargoIDs[i]); + if (category) + { + cats.push_back(category); + } + } + } + else if(mSource == SOURCE_WORLD) + { + // This object is in some task inventory somewhere. + LLViewerObject* obj = gObjectList.findObject(mSourceID); + if(obj) + { + if((mCargoType == DAD_CATEGORY) + || (mCargoType == DAD_ROOT_CATEGORY)) + { + // The object should be in user inventory. + for (S32 i = 0; i < mCargoIDs.size(); i++) + { + LLInventoryCategory* category = (LLInventoryCategory*)obj->getInventoryObject(mCargoIDs[i]); + if (category) + { + cats.push_back(category); + } + } + } + else + { + for (S32 i = 0; i < mCargoIDs.size(); i++) + { + LLInventoryItem* item = (LLInventoryItem*)obj->getInventoryObject(mCargoIDs[i]); + if (item) + { + items.push_back(item); + } + } + } + } + } + else if(mSource == SOURCE_NOTECARD) + { + LLPreviewNotecard* card; + card = (LLPreviewNotecard*)LLPreview::find(mSourceID); + if(card) + { + items.push_back((LLInventoryItem*)card->getDragItem()); + } + } + if(items.size()) return items[0]; + if(cats.size()) return cats[0]; + return NULL; } */ // void LLToolDragAndDrop::createContainer(LLViewerInventoryItem::item_array_t &items, const char* preferred_name ) // { -// LL_WARNS() << "LLToolDragAndDrop::createContainer()" << LL_ENDL; -// return; +// LL_WARNS() << "LLToolDragAndDrop::createContainer()" << LL_ENDL; +// return; // } @@ -3144,13 +3144,13 @@ LLInventoryObject* LLToolDragAndDrop::locateMultipleInventory(LLViewerInventoryC void pack_permissions_slam(LLMessageSystem* msg, U32 flags, const LLPermissions& perms) { - // CRUFT -- the server no longer pays attention to this data - U32 group_mask = perms.getMaskGroup(); - U32 everyone_mask = perms.getMaskEveryone(); - U32 next_owner_mask = perms.getMaskNextOwner(); - - msg->addU32Fast(_PREHASH_ItemFlags, flags); - msg->addU32Fast(_PREHASH_GroupMask, group_mask); - msg->addU32Fast(_PREHASH_EveryoneMask, everyone_mask); - msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_mask); + // CRUFT -- the server no longer pays attention to this data + U32 group_mask = perms.getMaskGroup(); + U32 everyone_mask = perms.getMaskEveryone(); + U32 next_owner_mask = perms.getMaskNextOwner(); + + msg->addU32Fast(_PREHASH_ItemFlags, flags); + msg->addU32Fast(_PREHASH_GroupMask, group_mask); + msg->addU32Fast(_PREHASH_EveryoneMask, everyone_mask); + msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_mask); } diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 907cec4d17..5960989166 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -1,25 +1,25 @@ -/** +/** * @file lltoolselect.cpp * @brief LLToolSelect class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -42,8 +42,8 @@ #include "llviewercamera.h" #include "llviewermenu.h" #include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llworld.h" @@ -55,235 +55,235 @@ const F32 SELECTION_ROTATION_TRESHOLD = 0.1f; const F32 SELECTION_SITTING_ROTATION_TRESHOLD = 3.2f; //radian LLToolSelect::LLToolSelect( LLToolComposite* composite ) -: LLTool( std::string("Select"), composite ), - mIgnoreGroup( FALSE ) +: LLTool( std::string("Select"), composite ), + mIgnoreGroup( FALSE ) { } // True if you selected an object. BOOL LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { - // do immediate pick query + // do immediate pick query BOOL pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); BOOL pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects"); BOOL pick_reflection_probe = gSavedSettings.getBOOL("SelectReflectionProbes"); - mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged, FALSE, TRUE, pick_reflection_probe); + mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged, FALSE, TRUE, pick_reflection_probe); - // Pass mousedown to agent - LLTool::handleMouseDown(x, y, mask); + // Pass mousedown to agent + LLTool::handleMouseDown(x, y, mask); - return mPick.getObject().notNull(); + return mPick.getObject().notNull(); } // static LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root) { - LLViewerObject* object = pick.getObject(); - if (select_root) - { - object = object->getRootEdit(); - } - BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); - BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); + LLViewerObject* object = pick.getObject(); + if (select_root) + { + object = object->getRootEdit(); + } + BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); + BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); // *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); - LLSelectMgr::getInstance()->setForceSelection(TRUE); - } - - BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL); - - // If no object, check for icon, then just deselect - if (!object) - { - LLHUDIcon* last_hit_hud_icon = pick.mHUDIcon; - - if (last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) - { - LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); - } - else if (!extend_select) - { - LLSelectMgr::getInstance()->deselectAll(); - } - } - else - { - BOOL already_selected = object->isSelected(); - - if (already_selected && - object->getNumTEs() > 0 && - !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES)) - { - const LLTextureEntry* tep = object->getTE(pick.mObjectFace); - if (tep && !tep->isSelected() && !LLViewerMediaFocus::getInstance()->getFocusedObjectID().isNull()) - { - // we were interacting with media and clicked on non selected face, drop media focus - LLViewerMediaFocus::getInstance()->clearFocus(); - // selection was removed and zoom preserved by clearFocus(), continue with regular selection - already_selected = false; - extend_select = true; - } - } - - if ( extend_select ) - { - if ( already_selected ) - { - if ( ignore_group ) - { - LLSelectMgr::getInstance()->deselectObjectOnly(object); - } - else - { - LLSelectMgr::getInstance()->deselectObjectAndFamily(object, TRUE, TRUE); - } - } - else - { - if ( ignore_group ) - { - LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); - } - else - { - LLSelectMgr::getInstance()->selectObjectAndFamily(object); - } - } - } - else - { - // Save the current zoom values because deselect resets them. - F32 target_zoom; - F32 current_zoom; - LLSelectMgr::getInstance()->getAgentHUDZoom(target_zoom, current_zoom); - - // JC - Change behavior to make it easier to select children - // of linked sets. 9/3/2002 - if( !already_selected || ignore_group) - { - // ...lose current selection in favor of just this object - LLSelectMgr::getInstance()->deselectAll(); - } - - if ( ignore_group ) - { - LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES, pick.mGLTFNodeIndex, pick.mGLTFPrimitiveIndex); - } - else - { - LLSelectMgr::getInstance()->selectObjectAndFamily(object); - } - - // restore the zoom to the previously stored values. - LLSelectMgr::getInstance()->setAgentHUDZoom(target_zoom, current_zoom); - } - - if (!gAgentCamera.getFocusOnAvatar() && // if camera not glued to avatar - LLVOAvatar::findAvatarFromAttachment(object) != gAgentAvatarp && // and it's not one of your attachments - object != gAgentAvatarp) // and it's not you - { - // have avatar turn to face the selected object(s) - LLVector3d selection_center = LLSelectMgr::getInstance()->getSelectionCenterGlobal(); - selection_center = selection_center - gAgent.getPositionGlobal(); - LLVector3 selection_dir; - selection_dir.setVec(selection_center); - selection_dir.mV[VZ] = 0.f; - selection_dir.normVec(); - if (!object->isAvatar() && gAgent.getAtAxis() * selection_dir < 0.6f) - { - LLQuaternion target_rot; - target_rot.shortestArc(LLVector3::x_axis, selection_dir); - gAgent.startAutoPilotGlobal(gAgent.getPositionGlobal(), - "", - &target_rot, - NULL, - NULL, - MAX_FAR_CLIP /*stop_distance, don't care since we are looking, not moving*/, - gAgentAvatarp->isSitting() ? SELECTION_SITTING_ROTATION_TRESHOLD : SELECTION_ROTATION_TRESHOLD); - } - } - - if (temp_select) - { - if (!already_selected) - { - LLViewerObject* root_object = (LLViewerObject*)object->getRootEdit(); - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - // this is just a temporary selection - LLSelectNode* select_node = selection->findNode(root_object); - if (select_node) - { - select_node->setTransient(TRUE); - } - - LLViewerObject::const_child_list_t& child_list = root_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - select_node = selection->findNode(child); - if (select_node) - { - select_node->setTransient(TRUE); - } - } - - } - } //if(temp_select) - } //if(!object) - - // Cleanup temp select settings above. - if (temp_select ||LLSelectMgr::getInstance()->mAllowSelectAvatar) - { - gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); - gSavedSettings.setBOOL("SelectMovableOnly", select_movable); - LLSelectMgr::getInstance()->setForceSelection(FALSE); - } - - return LLSelectMgr::getInstance()->getSelection(); + if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar) + { + gSavedSettings.setBOOL("SelectOwnedOnly", FALSE); + gSavedSettings.setBOOL("SelectMovableOnly", FALSE); + LLSelectMgr::getInstance()->setForceSelection(TRUE); + } + + BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL); + + // If no object, check for icon, then just deselect + if (!object) + { + LLHUDIcon* last_hit_hud_icon = pick.mHUDIcon; + + if (last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) + { + LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); + } + else if (!extend_select) + { + LLSelectMgr::getInstance()->deselectAll(); + } + } + else + { + BOOL already_selected = object->isSelected(); + + if (already_selected && + object->getNumTEs() > 0 && + !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES)) + { + const LLTextureEntry* tep = object->getTE(pick.mObjectFace); + if (tep && !tep->isSelected() && !LLViewerMediaFocus::getInstance()->getFocusedObjectID().isNull()) + { + // we were interacting with media and clicked on non selected face, drop media focus + LLViewerMediaFocus::getInstance()->clearFocus(); + // selection was removed and zoom preserved by clearFocus(), continue with regular selection + already_selected = false; + extend_select = true; + } + } + + if ( extend_select ) + { + if ( already_selected ) + { + if ( ignore_group ) + { + LLSelectMgr::getInstance()->deselectObjectOnly(object); + } + else + { + LLSelectMgr::getInstance()->deselectObjectAndFamily(object, TRUE, TRUE); + } + } + else + { + if ( ignore_group ) + { + LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); + } + else + { + LLSelectMgr::getInstance()->selectObjectAndFamily(object); + } + } + } + else + { + // Save the current zoom values because deselect resets them. + F32 target_zoom; + F32 current_zoom; + LLSelectMgr::getInstance()->getAgentHUDZoom(target_zoom, current_zoom); + + // JC - Change behavior to make it easier to select children + // of linked sets. 9/3/2002 + if( !already_selected || ignore_group) + { + // ...lose current selection in favor of just this object + LLSelectMgr::getInstance()->deselectAll(); + } + + if ( ignore_group ) + { + LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES, pick.mGLTFNodeIndex, pick.mGLTFPrimitiveIndex); + } + else + { + LLSelectMgr::getInstance()->selectObjectAndFamily(object); + } + + // restore the zoom to the previously stored values. + LLSelectMgr::getInstance()->setAgentHUDZoom(target_zoom, current_zoom); + } + + if (!gAgentCamera.getFocusOnAvatar() && // if camera not glued to avatar + LLVOAvatar::findAvatarFromAttachment(object) != gAgentAvatarp && // and it's not one of your attachments + object != gAgentAvatarp) // and it's not you + { + // have avatar turn to face the selected object(s) + LLVector3d selection_center = LLSelectMgr::getInstance()->getSelectionCenterGlobal(); + selection_center = selection_center - gAgent.getPositionGlobal(); + LLVector3 selection_dir; + selection_dir.setVec(selection_center); + selection_dir.mV[VZ] = 0.f; + selection_dir.normVec(); + if (!object->isAvatar() && gAgent.getAtAxis() * selection_dir < 0.6f) + { + LLQuaternion target_rot; + target_rot.shortestArc(LLVector3::x_axis, selection_dir); + gAgent.startAutoPilotGlobal(gAgent.getPositionGlobal(), + "", + &target_rot, + NULL, + NULL, + MAX_FAR_CLIP /*stop_distance, don't care since we are looking, not moving*/, + gAgentAvatarp->isSitting() ? SELECTION_SITTING_ROTATION_TRESHOLD : SELECTION_ROTATION_TRESHOLD); + } + } + + if (temp_select) + { + if (!already_selected) + { + LLViewerObject* root_object = (LLViewerObject*)object->getRootEdit(); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + // this is just a temporary selection + LLSelectNode* select_node = selection->findNode(root_object); + if (select_node) + { + select_node->setTransient(TRUE); + } + + LLViewerObject::const_child_list_t& child_list = root_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + select_node = selection->findNode(child); + if (select_node) + { + select_node->setTransient(TRUE); + } + } + + } + } //if(temp_select) + } //if(!object) + + // Cleanup temp select settings above. + if (temp_select ||LLSelectMgr::getInstance()->mAllowSelectAvatar) + { + gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); + gSavedSettings.setBOOL("SelectMovableOnly", select_movable); + LLSelectMgr::getInstance()->setForceSelection(FALSE); + } + + return LLSelectMgr::getInstance()->getSelection(); } BOOL LLToolSelect::handleMouseUp(S32 x, S32 y, MASK mask) { - mIgnoreGroup = gSavedSettings.getBOOL("EditLinkedParts"); + mIgnoreGroup = gSavedSettings.getBOOL("EditLinkedParts"); - handleObjectSelection(mPick, mIgnoreGroup, FALSE); + handleObjectSelection(mPick, mIgnoreGroup, FALSE); - return LLTool::handleMouseUp(x, y, mask); + return LLTool::handleMouseUp(x, y, mask); } void LLToolSelect::handleDeselect() { - if( hasMouseCapture() ) - { - setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly - } + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly + } } void LLToolSelect::stopEditing() { - if( hasMouseCapture() ) - { - setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly - } + if( hasMouseCapture() ) + { + setMouseCapture( FALSE ); // Calls onMouseCaptureLost() indirectly + } } void LLToolSelect::onMouseCaptureLost() { - // Finish drag + // Finish drag - LLSelectMgr::getInstance()->enableSilhouette(TRUE); + LLSelectMgr::getInstance()->enableSilhouette(TRUE); - // Clean up drag-specific variables - mIgnoreGroup = FALSE; + // Clean up drag-specific variables + mIgnoreGroup = FALSE; } diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 882e08935c..b2072218ac 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -81,9 +81,9 @@ LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId, { } -LLResourceUploadInfo::LLResourceUploadInfo(std::string name, - std::string description, S32 compressionInfo, - LLFolderType::EType destinationType, LLInventoryType::EType inventoryType, +LLResourceUploadInfo::LLResourceUploadInfo(std::string name, + std::string description, S32 compressionInfo, + LLFolderType::EType destinationType, LLInventoryType::EType inventoryType, U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) : mName(name), mDescription(description), @@ -100,7 +100,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(std::string name, mFolderId(LLUUID::null), mItemId(LLUUID::null), mAssetId(LLAssetID::null) -{ +{ mTransactionId.generate(); } @@ -311,39 +311,39 @@ std::string LLResourceUploadInfo::getDisplayName() const bool LLResourceUploadInfo::findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type) { - U32 codec; - return findAssetTypeAndCodecOfExtension(exten, asset_type, codec, false); + U32 codec; + return findAssetTypeAndCodecOfExtension(exten, asset_type, codec, false); } // static bool LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload) { - bool succ = false; - std::string exten_lc(exten); - LLStringUtil::toLower(exten_lc); - codec = LLImageBase::getCodecFromExtension(exten_lc); - if (codec != IMG_CODEC_INVALID) - { - asset_type = LLAssetType::AT_TEXTURE; - succ = true; - } - else if (exten_lc == "wav") - { - asset_type = LLAssetType::AT_SOUND; - succ = true; - } - else if (exten_lc == "anim") - { - asset_type = LLAssetType::AT_ANIMATION; - succ = true; - } - else if (!bulk_upload && (exten_lc == "bvh")) - { - asset_type = LLAssetType::AT_ANIMATION; - succ = true; - } - - return succ; + bool succ = false; + std::string exten_lc(exten); + LLStringUtil::toLower(exten_lc); + codec = LLImageBase::getCodecFromExtension(exten_lc); + if (codec != IMG_CODEC_INVALID) + { + asset_type = LLAssetType::AT_TEXTURE; + succ = true; + } + else if (exten_lc == "wav") + { + asset_type = LLAssetType::AT_SOUND; + succ = true; + } + else if (exten_lc == "anim") + { + asset_type = LLAssetType::AT_ANIMATION; + succ = true; + } + else if (!bulk_upload && (exten_lc == "bvh")) + { + asset_type = LLAssetType::AT_ANIMATION; + succ = true; + } + + return succ; } //========================================================================= @@ -385,8 +385,8 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() std::string exten = gDirUtilp->getExtension(getFileName()); LLAssetType::EType assetType = LLAssetType::AT_NONE; - U32 codec = IMG_CODEC_INVALID; - bool found_type = findAssetTypeAndCodecOfExtension(exten, assetType, codec); + U32 codec = IMG_CODEC_INVALID; + bool found_type = findAssetTypeAndCodecOfExtension(exten, assetType, codec); std::string errorMessage; std::string errorLabel; @@ -455,53 +455,53 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() } else if (exten == "anim") { - // Default unless everything succeeds - errorLabel = "ProblemWithFile"; - error = true; + // Default unless everything succeeds + errorLabel = "ProblemWithFile"; + error = true; // read from getFileName() - LLAPRFile infile; - infile.open(getFileName(),LL_APR_RB); - if (!infile.getFileHandle()) - { - LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL; - errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str()); - } - else - { - S32 size = LLAPRFile::size(getFileName()); - U8* buffer = new U8[size]; - S32 size_read = infile.read(buffer,size); - if (size_read != size) - { - errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read); - } - else - { - LLDataPackerBinaryBuffer dp(buffer, size); - LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId()); - motionp->setCharacter(gAgentAvatarp); - if (motionp->deserialize(dp, getAssetId(), false)) - { - // write to temp file - bool succ = motionp->dumpToFile(filename); - if (succ) - { - assetType = LLAssetType::AT_ANIMATION; - errorLabel = ""; - error = false; - } - else - { - errorMessage = "Failed saving temporary animation file"; - } - } - else - { - errorMessage = "Failed reading animation file"; - } - } - } + LLAPRFile infile; + infile.open(getFileName(),LL_APR_RB); + if (!infile.getFileHandle()) + { + LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL; + errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str()); + } + else + { + S32 size = LLAPRFile::size(getFileName()); + U8* buffer = new U8[size]; + S32 size_read = infile.read(buffer,size); + if (size_read != size) + { + errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read); + } + else + { + LLDataPackerBinaryBuffer dp(buffer, size); + LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId()); + motionp->setCharacter(gAgentAvatarp); + if (motionp->deserialize(dp, getAssetId(), false)) + { + // write to temp file + bool succ = motionp->dumpToFile(filename); + if (succ) + { + assetType = LLAssetType::AT_ANIMATION; + errorLabel = ""; + error = false; + } + else + { + errorMessage = "Failed saving temporary animation file"; + } + } + else + { + errorMessage = "Failed reading animation file"; + } + } + } } else { @@ -596,10 +596,10 @@ LLSD LLNewBufferedResourceUploadInfo::exportTempFile() { std::string filename = gDirUtilp->getTempFilename(); - // copy buffer to the cache for upload + // copy buffer to the cache for upload LLFileSystem file(getAssetId(), getAssetType(), LLFileSystem::APPEND); file.write((U8*) mBuffer.c_str(), mBuffer.size()); - + return LLSD(); } @@ -828,8 +828,8 @@ LLSD LLScriptAssetUpload::generatePostBody() LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const LLResourceUploadInfo::ptr_t &uploadInfo) { std::string procName("LLViewerAssetUpload::AssetInventoryUploadCoproc("); - - LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload", + + LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("Upload", procName + LLAssetType::lookup(uploadInfo->getAssetType()) + ")", boost::bind(&LLViewerAssetUpload::AssetInventoryUploadCoproc, _1, _2, url, uploadInfo)); @@ -838,7 +838,7 @@ LLUUID LLViewerAssetUpload::EnqueueInventoryUpload(const std::string &url, const //========================================================================= /*static*/ -void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, +void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, const LLUUID &id, std::string url, LLResourceUploadInfo::ptr_t uploadInfo) { LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 9ba42e4f47..437f1239bf 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewercamera.cpp * @brief LLViewerCamera class implementation * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -48,7 +48,7 @@ #include "llgl.h" #include "llglheaders.h" #include "llquaternion.h" -#include "llwindow.h" // getPixelAspectRatio() +#include "llwindow.h" // getPixelAspectRatio() #include "lltracerecording.h" #include "llenvironment.h" @@ -63,38 +63,38 @@ LLViewerCamera::eCameraID LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_ //glu pick matrix implementation borrowed from Mesa3D glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport) { - GLfloat m[16]; - GLfloat sx, sy; - GLfloat tx, ty; - - sx = viewport[2] / width; - sy = viewport[3] / height; - tx = (viewport[2] + 2.f * (viewport[0] - x)) / width; - ty = (viewport[3] + 2.f * (viewport[1] - y)) / height; - - #define M(row,col) m[col*4+row] - M(0,0) = sx; M(0,1) = 0.f; M(0,2) = 0.f; M(0,3) = tx; - M(1,0) = 0.f; M(1,1) = sy; M(1,2) = 0.f; M(1,3) = ty; - M(2,0) = 0.f; M(2,1) = 0.f; M(2,2) = 1.f; M(2,3) = 0.f; - M(3,0) = 0.f; M(3,1) = 0.f; M(3,2) = 0.f; M(3,3) = 1.f; - #undef M - - return glh::matrix4f(m); + GLfloat m[16]; + GLfloat sx, sy; + GLfloat tx, ty; + + sx = viewport[2] / width; + sy = viewport[3] / height; + tx = (viewport[2] + 2.f * (viewport[0] - x)) / width; + ty = (viewport[3] + 2.f * (viewport[1] - y)) / height; + + #define M(row,col) m[col*4+row] + M(0,0) = sx; M(0,1) = 0.f; M(0,2) = 0.f; M(0,3) = tx; + M(1,0) = 0.f; M(1,1) = sy; M(1,2) = 0.f; M(1,3) = ty; + M(2,0) = 0.f; M(2,1) = 0.f; M(2,2) = 1.f; M(2,3) = 0.f; + M(3,0) = 0.f; M(3,1) = 0.f; M(3,2) = 0.f; M(3,3) = 1.f; + #undef M + + return glh::matrix4f(m); } LLViewerCamera::LLViewerCamera() : LLCamera() { - calcProjection(getFar()); - mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; - mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; - mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); - mPixelMeterRatio = 0.f; - mScreenPixelArea = 0; - mZoomFactor = 1.f; - mZoomSubregion = 1; - mAverageSpeed = 0.f; - mAverageAngularSpeed = 0.f; - gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2)); + calcProjection(getFar()); + mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; + mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; + mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); + mPixelMeterRatio = 0.f; + mScreenPixelArea = 0; + mZoomFactor = 1.f; + mZoomSubregion = 1; + mAverageSpeed = 0.f; + mAverageAngularSpeed = 0.f; + gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2)); } void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest) @@ -133,61 +133,61 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, const LLVecto } } - setOriginAndLookAt(origin, up_direction, point_of_interest); + setOriginAndLookAt(origin, up_direction, point_of_interest); + + mVelocityDir = origin - last_position ; + F32 dpos = mVelocityDir.normVec() ; + LLQuaternion rotation; + rotation.shortestArc(last_axis, getAtAxis()); - mVelocityDir = origin - last_position ; - F32 dpos = mVelocityDir.normVec() ; - LLQuaternion rotation; - rotation.shortestArc(last_axis, getAtAxis()); + F32 x, y, z; + F32 drot; + rotation.getAngleAxis(&drot, &x, &y, &z); - F32 x, y, z; - F32 drot; - rotation.getAngleAxis(&drot, &x, &y, &z); + add(sVelocityStat, dpos); + add(sAngularVelocityStat, drot); - add(sVelocityStat, dpos); - add(sAngularVelocityStat, drot); - - mAverageSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sVelocityStat, 50); - mAverageAngularSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sAngularVelocityStat); - mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect())); + mAverageSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sVelocityStat, 50); + mAverageAngularSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sAngularVelocityStat); + mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect())); - // update pixel meter ratio using default fov, not modified one - mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); - // update screen pixel area - mScreenPixelArea =(S32)((F32)getViewHeightInPixels() * ((F32)getViewHeightInPixels() * getAspect())); + // update pixel meter ratio using default fov, not modified one + mPixelMeterRatio = getViewHeightInPixels()/ (2.f*tanf(mCameraFOVDefault*0.5)); + // update screen pixel area + mScreenPixelArea =(S32)((F32)getViewHeightInPixels() * ((F32)getViewHeightInPixels() * getAspect())); } const LLMatrix4 &LLViewerCamera::getProjection() const { - calcProjection(getFar()); - return mProjectionMatrix; + calcProjection(getFar()); + return mProjectionMatrix; } const LLMatrix4 &LLViewerCamera::getModelview() const { - LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - getMatrixToLocal(mModelviewMatrix); - mModelviewMatrix *= cfr; - return mModelviewMatrix; + LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + getMatrixToLocal(mModelviewMatrix); + mModelviewMatrix *= cfr; + return mModelviewMatrix; } void LLViewerCamera::calcProjection(const F32 far_distance) const { - F32 fov_y, z_far, z_near, aspect, f; - fov_y = getView(); - z_far = far_distance; - z_near = getNear(); - aspect = getAspect(); - - f = 1/tan(fov_y*0.5f); - - mProjectionMatrix.setZero(); - mProjectionMatrix.mMatrix[0][0] = f/aspect; - mProjectionMatrix.mMatrix[1][1] = f; - mProjectionMatrix.mMatrix[2][2] = (z_far + z_near)/(z_near - z_far); - mProjectionMatrix.mMatrix[3][2] = (2*z_far*z_near)/(z_near - z_far); - mProjectionMatrix.mMatrix[2][3] = -1; + F32 fov_y, z_far, z_near, aspect, f; + fov_y = getView(); + z_far = far_distance; + z_near = getNear(); + aspect = getAspect(); + + f = 1/tan(fov_y*0.5f); + + mProjectionMatrix.setZero(); + mProjectionMatrix.mMatrix[0][0] = f/aspect; + mProjectionMatrix.mMatrix[1][1] = f; + mProjectionMatrix.mMatrix[2][2] = (z_far + z_near)/(z_near - z_far); + mProjectionMatrix.mMatrix[3][2] = (2*z_far*z_near)/(z_near - z_far); + mProjectionMatrix.mMatrix[2][3] = -1; } // Sets up opengl state for 3D drawing. If for selection, also @@ -198,222 +198,222 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const //static void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho, BOOL zflip, BOOL no_hacks) { - GLint* viewport = (GLint*) gGLViewport; - F64 model[16]; - F64 proj[16]; - - for (U32 i = 0; i < 16; i++) - { - model[i] = (F64) gGLModelView[i]; - proj[i] = (F64) gGLProjection[i]; - } - - GLdouble objX,objY,objZ; - - LLVector3 frust[8]; - - if (no_hacks) - { - gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); - - gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); - } - else if (zflip) - { - gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); - - gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); - - for (U32 i = 0; i < 4; i++) - { - frust[i+4] = frust[i+4]-frust[i]; - frust[i+4].normVec(); - frust[i+4] = frust[i] + frust[i+4]*camera.getFar(); - } - } - else - { - gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); - frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); - frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); - - if (ortho) - { - LLVector3 far_shift = camera.getAtAxis()*camera.getFar()*2.f; - for (U32 i = 0; i < 4; i++) - { - frust[i+4] = frust[i] + far_shift; - } - } - else - { - for (U32 i = 0; i < 4; i++) - { - LLVector3 vec = frust[i] - camera.getOrigin(); - vec.normVec(); - frust[i+4] = camera.getOrigin() + vec*camera.getFar(); - } - } - } - - camera.calcAgentFrustumPlanes(frust); + GLint* viewport = (GLint*) gGLViewport; + F64 model[16]; + F64 proj[16]; + + for (U32 i = 0; i < 16; i++) + { + model[i] = (F64) gGLModelView[i]; + proj[i] = (F64) gGLProjection[i]; + } + + GLdouble objX,objY,objZ; + + LLVector3 frust[8]; + + if (no_hacks) + { + gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); + + gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); + } + else if (zflip) + { + gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); + + gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); + frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); + frust[7].setVec((F32)objX,(F32)objY,(F32)objZ); + + for (U32 i = 0; i < 4; i++) + { + frust[i+4] = frust[i+4]-frust[i]; + frust[i+4].normVec(); + frust[i+4] = frust[i] + frust[i+4]*camera.getFar(); + } + } + else + { + gluUnProject(viewport[0],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[0].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1],0,model,proj,viewport,&objX,&objY,&objZ); + frust[1].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); + gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); + frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); + + if (ortho) + { + LLVector3 far_shift = camera.getAtAxis()*camera.getFar()*2.f; + for (U32 i = 0; i < 4; i++) + { + frust[i+4] = frust[i] + far_shift; + } + } + else + { + for (U32 i = 0; i < 4; i++) + { + LLVector3 vec = frust[i] - camera.getOrigin(); + vec.normVec(); + frust[i+4] = camera.getOrigin() + vec*camera.getFar(); + } + } + } + + camera.calcAgentFrustumPlanes(frust); } void LLViewerCamera::setPerspective(BOOL for_selection, - S32 x, S32 y_from_bot, S32 width, S32 height, - BOOL limit_select_distance, - F32 z_near, F32 z_far) + S32 x, S32 y_from_bot, S32 width, S32 height, + BOOL limit_select_distance, + F32 z_near, F32 z_far) { - F32 fov_y, aspect; - fov_y = RAD_TO_DEG * getView(); - BOOL z_default_far = FALSE; - if (z_far <= 0) - { - z_default_far = TRUE; - z_far = getFar(); - } - if (z_near <= 0) - { - z_near = getNear(); - } - aspect = getAspect(); - - // Load camera view matrix - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadIdentity(); - - glh::matrix4f proj_mat; - - if (for_selection) - { - // make a tiny little viewport - // anything drawn into this viewport will be "selected" - - GLint viewport[4]; - viewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - viewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - viewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - viewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - - proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport); - - if (limit_select_distance) - { - // ...select distance from control - z_far = gSavedSettings.getF32("MaxSelectDistance"); - } - else - { - z_far = gAgentCamera.mDrawDistance; - } - } - else - { - // Only override the far clip if it's not passed in explicitly. - if (z_default_far) - { - z_far = MAX_FAR_CLIP; - } - glViewport(x, y_from_bot, width, height); - gGLViewport[0] = x; - gGLViewport[1] = y_from_bot; - gGLViewport[2] = width; - gGLViewport[3] = height; - } - - if (mZoomFactor > 1.f) - { - float offset = mZoomFactor - 1.f; - int pos_y = mZoomSubregion / llceil(mZoomFactor); - int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); - glh::matrix4f translate; - translate.set_translate(glh::vec3f(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f)); - glh::matrix4f scale; - scale.set_scale(glh::vec3f(mZoomFactor, mZoomFactor, 1.f)); - - proj_mat = scale*proj_mat; - proj_mat = translate*proj_mat; - } - - calcProjection(z_far); // Update the projection matrix cache - - proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far); - - gGL.loadMatrix(proj_mat.m); - - for (U32 i = 0; i < 16; i++) - { - gGLProjection[i] = proj_mat.m[i]; - } - - gGL.matrixMode(LLRender::MM_MODELVIEW); - - glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION); - - GLfloat ogl_matrix[16]; - - getOpenGLTransform(ogl_matrix); - - modelview *= glh::matrix4f(ogl_matrix); - - gGL.loadMatrix(modelview.m); - - if (for_selection && (width > 1 || height > 1)) - { - // NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window) - // however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not - // comfortable hacking on it. - calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, - (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f, - (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, - (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f); - - } - - // if not picking and not doing a snapshot, cache various GL matrices - if (!for_selection && mZoomFactor == 1.f) - { - // Save GL matrices for access elsewhere in code, especially project_world_to_screen - for (U32 i = 0; i < 16; i++) - { - gGLModelView[i] = modelview.m[i]; - } - } - - updateFrustumPlanes(*this); + F32 fov_y, aspect; + fov_y = RAD_TO_DEG * getView(); + BOOL z_default_far = FALSE; + if (z_far <= 0) + { + z_default_far = TRUE; + z_far = getFar(); + } + if (z_near <= 0) + { + z_near = getNear(); + } + aspect = getAspect(); + + // Load camera view matrix + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadIdentity(); + + glh::matrix4f proj_mat; + + if (for_selection) + { + // make a tiny little viewport + // anything drawn into this viewport will be "selected" + + GLint viewport[4]; + viewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + viewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + viewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + viewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + + proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport); + + if (limit_select_distance) + { + // ...select distance from control + z_far = gSavedSettings.getF32("MaxSelectDistance"); + } + else + { + z_far = gAgentCamera.mDrawDistance; + } + } + else + { + // Only override the far clip if it's not passed in explicitly. + if (z_default_far) + { + z_far = MAX_FAR_CLIP; + } + glViewport(x, y_from_bot, width, height); + gGLViewport[0] = x; + gGLViewport[1] = y_from_bot; + gGLViewport[2] = width; + gGLViewport[3] = height; + } + + if (mZoomFactor > 1.f) + { + float offset = mZoomFactor - 1.f; + int pos_y = mZoomSubregion / llceil(mZoomFactor); + int pos_x = mZoomSubregion - (pos_y*llceil(mZoomFactor)); + glh::matrix4f translate; + translate.set_translate(glh::vec3f(offset - (F32)pos_x * 2.f, offset - (F32)pos_y * 2.f, 0.f)); + glh::matrix4f scale; + scale.set_scale(glh::vec3f(mZoomFactor, mZoomFactor, 1.f)); + + proj_mat = scale*proj_mat; + proj_mat = translate*proj_mat; + } + + calcProjection(z_far); // Update the projection matrix cache + + proj_mat *= gl_perspective(fov_y,aspect,z_near,z_far); + + gGL.loadMatrix(proj_mat.m); + + for (U32 i = 0; i < 16; i++) + { + gGLProjection[i] = proj_mat.m[i]; + } + + gGL.matrixMode(LLRender::MM_MODELVIEW); + + glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION); + + GLfloat ogl_matrix[16]; + + getOpenGLTransform(ogl_matrix); + + modelview *= glh::matrix4f(ogl_matrix); + + gGL.loadMatrix(modelview.m); + + if (for_selection && (width > 1 || height > 1)) + { + // NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window) + // however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not + // comfortable hacking on it. + calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, + (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f, + (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, + (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f); + + } + + // if not picking and not doing a snapshot, cache various GL matrices + if (!for_selection && mZoomFactor == 1.f) + { + // Save GL matrices for access elsewhere in code, especially project_world_to_screen + for (U32 i = 0; i < 16; i++) + { + gGLModelView[i] = modelview.m[i]; + } + } + + updateFrustumPlanes(*this); } @@ -421,24 +421,24 @@ void LLViewerCamera::setPerspective(BOOL for_selection, // screen coordinates to the agent's region. void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 screen_y, LLVector3* pos_agent) const { - GLdouble x, y, z; - - F64 mdlv[16]; - F64 proj[16]; - - for (U32 i = 0; i < 16; i++) - { - mdlv[i] = (F64) gGLModelView[i]; - proj[i] = (F64) gGLProjection[i]; - } - - gluUnProject( - GLdouble(screen_x), GLdouble(screen_y), 0.0, - mdlv, proj, (GLint*)gGLViewport, - &x, - &y, - &z ); - pos_agent->setVec( (F32)x, (F32)y, (F32)z ); + GLdouble x, y, z; + + F64 mdlv[16]; + F64 proj[16]; + + for (U32 i = 0; i < 16; i++) + { + mdlv[i] = (F64) gGLModelView[i]; + proj[i] = (F64) gGLProjection[i]; + } + + gluUnProject( + GLdouble(screen_x), GLdouble(screen_y), 0.0, + mdlv, proj, (GLint*)gGLViewport, + &x, + &y, + &z ); + pos_agent->setVec( (F32)x, (F32)y, (F32)z ); } // Uses the last GL matrices set in set_perspective to project a point from @@ -446,318 +446,318 @@ void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 scree // the current window. BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp) const { - BOOL in_front = TRUE; - GLdouble x, y, z; // object's window coords, GL-style - - LLVector3 dir_to_point = pos_agent - getOrigin(); - dir_to_point /= dir_to_point.magVec(); - - if (dir_to_point * getAtAxis() < 0.f) - { - if (clamp) - { - return FALSE; - } - else - { - in_front = FALSE; - } - } - - LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); - S32 viewport[4]; - viewport[0] = world_view_rect.mLeft; - viewport[1] = world_view_rect.mBottom; - viewport[2] = world_view_rect.getWidth(); - viewport[3] = world_view_rect.getHeight(); - - F64 mdlv[16]; - F64 proj[16]; - - for (U32 i = 0; i < 16; i++) - { - mdlv[i] = (F64) gGLModelView[i]; - proj[i] = (F64) gGLProjection[i]; - } - - if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], - mdlv, proj, (GLint*)viewport, - &x, &y, &z)) - { - // convert screen coordinates to virtual UI coordinates - x /= gViewerWindow->getDisplayScale().mV[VX]; - y /= gViewerWindow->getDisplayScale().mV[VY]; - - // should now have the x,y coords of grab_point in screen space - LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); - - // convert to pixel coordinates - S32 int_x = lltrunc(x); - S32 int_y = lltrunc(y); - - BOOL valid = TRUE; - - if (clamp) - { - if (int_x < world_rect.mLeft) - { - out_point.mX = world_rect.mLeft; - valid = FALSE; - } - else if (int_x > world_rect.mRight) - { - out_point.mX = world_rect.mRight; - valid = FALSE; - } - else - { - out_point.mX = int_x; - } - - if (int_y < world_rect.mBottom) - { - out_point.mY = world_rect.mBottom; - valid = FALSE; - } - else if (int_y > world_rect.mTop) - { - out_point.mY = world_rect.mTop; - valid = FALSE; - } - else - { - out_point.mY = int_y; - } - return valid; - } - else - { - out_point.mX = int_x; - out_point.mY = int_y; - - if (int_x < world_rect.mLeft) - { - valid = FALSE; - } - else if (int_x > world_rect.mRight) - { - valid = FALSE; - } - if (int_y < world_rect.mBottom) - { - valid = FALSE; - } - else if (int_y > world_rect.mTop) - { - valid = FALSE; - } - - return in_front && valid; - } - } - else - { - return FALSE; - } + BOOL in_front = TRUE; + GLdouble x, y, z; // object's window coords, GL-style + + LLVector3 dir_to_point = pos_agent - getOrigin(); + dir_to_point /= dir_to_point.magVec(); + + if (dir_to_point * getAtAxis() < 0.f) + { + if (clamp) + { + return FALSE; + } + else + { + in_front = FALSE; + } + } + + LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); + S32 viewport[4]; + viewport[0] = world_view_rect.mLeft; + viewport[1] = world_view_rect.mBottom; + viewport[2] = world_view_rect.getWidth(); + viewport[3] = world_view_rect.getHeight(); + + F64 mdlv[16]; + F64 proj[16]; + + for (U32 i = 0; i < 16; i++) + { + mdlv[i] = (F64) gGLModelView[i]; + proj[i] = (F64) gGLProjection[i]; + } + + if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], + mdlv, proj, (GLint*)viewport, + &x, &y, &z)) + { + // convert screen coordinates to virtual UI coordinates + x /= gViewerWindow->getDisplayScale().mV[VX]; + y /= gViewerWindow->getDisplayScale().mV[VY]; + + // should now have the x,y coords of grab_point in screen space + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); + + // convert to pixel coordinates + S32 int_x = lltrunc(x); + S32 int_y = lltrunc(y); + + BOOL valid = TRUE; + + if (clamp) + { + if (int_x < world_rect.mLeft) + { + out_point.mX = world_rect.mLeft; + valid = FALSE; + } + else if (int_x > world_rect.mRight) + { + out_point.mX = world_rect.mRight; + valid = FALSE; + } + else + { + out_point.mX = int_x; + } + + if (int_y < world_rect.mBottom) + { + out_point.mY = world_rect.mBottom; + valid = FALSE; + } + else if (int_y > world_rect.mTop) + { + out_point.mY = world_rect.mTop; + valid = FALSE; + } + else + { + out_point.mY = int_y; + } + return valid; + } + else + { + out_point.mX = int_x; + out_point.mY = int_y; + + if (int_x < world_rect.mLeft) + { + valid = FALSE; + } + else if (int_x > world_rect.mRight) + { + valid = FALSE; + } + if (int_y < world_rect.mBottom) + { + valid = FALSE; + } + else if (int_y > world_rect.mTop) + { + valid = FALSE; + } + + return in_front && valid; + } + } + else + { + return FALSE; + } } // Uses the last GL matrices set in set_perspective to project a point from // the agent's region space to the nearest edge in screen coordinates. // Returns TRUE if projection succeeds. BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, - LLCoordGL &out_point) const + LLCoordGL &out_point) const { - LLVector3 dir_to_point = pos_agent - getOrigin(); - dir_to_point /= dir_to_point.magVec(); - - BOOL in_front = TRUE; - if (dir_to_point * getAtAxis() < 0.f) - { - in_front = FALSE; - } - - LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); - S32 viewport[4]; - viewport[0] = world_view_rect.mLeft; - viewport[1] = world_view_rect.mBottom; - viewport[2] = world_view_rect.getWidth(); - viewport[3] = world_view_rect.getHeight(); - GLdouble x, y, z; // object's window coords, GL-style - - F64 mdlv[16]; - F64 proj[16]; - - for (U32 i = 0; i < 16; i++) - { - mdlv[i] = (F64) gGLModelView[i]; - proj[i] = (F64) gGLProjection[i]; - } - - if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], - pos_agent.mV[VZ], mdlv, - proj, (GLint*)viewport, - &x, &y, &z)) - { - x /= gViewerWindow->getDisplayScale().mV[VX]; - y /= gViewerWindow->getDisplayScale().mV[VY]; - // should now have the x,y coords of grab_point in screen space - const LLRect& world_rect = gViewerWindow->getWorldViewRectScaled(); - - // ...sanity check - S32 int_x = lltrunc(x); - S32 int_y = lltrunc(y); - - // find the center - GLdouble center_x = (GLdouble)world_rect.getCenterX(); - GLdouble center_y = (GLdouble)world_rect.getCenterY(); - - if (x == center_x && y == center_y) - { - // can't project to edge from exact center - return FALSE; - } - - // find the line from center to local - GLdouble line_x = x - center_x; - GLdouble line_y = y - center_y; - - int_x = lltrunc(center_x); - int_y = lltrunc(center_y); - - - if (0.f == line_x) - { - // the slope of the line is undefined - if (line_y > 0.f) - { - int_y = world_rect.mTop; - } - else - { - int_y = world_rect.mBottom; - } - } - else if (0 == world_rect.getWidth()) - { - // the diagonal slope of the view is undefined - if (y < world_rect.mBottom) - { - int_y = world_rect.mBottom; - } - else if ( y > world_rect.mTop) - { - int_y = world_rect.mTop; - } - } - else - { - F32 line_slope = (F32)(line_y / line_x); - F32 rect_slope = ((F32)world_rect.getHeight()) / ((F32)world_rect.getWidth()); - - if (fabs(line_slope) > rect_slope) - { - if (line_y < 0.f) - { - // bottom - int_y = world_rect.mBottom; - } - else - { - // top - int_y = world_rect.mTop; - } - int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x); - } - else if (fabs(line_slope) < rect_slope) - { - if (line_x < 0.f) - { - // left - int_x = world_rect.mLeft; - } - else - { - // right - int_x = world_rect.mRight; - } - int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y); - } - else - { - // exactly parallel ==> push to the corners - if (line_x > 0.f) - { - int_x = world_rect.mRight; - } - else - { - int_x = world_rect.mLeft; - } - if (line_y > 0.0f) - { - int_y = world_rect.mTop; - } - else - { - int_y = world_rect.mBottom; - } - } - } - if (!in_front) - { - int_x = world_rect.mLeft + world_rect.mRight - int_x; - int_y = world_rect.mBottom + world_rect.mTop - int_y; - } - - out_point.mX = int_x + world_rect.mLeft; - out_point.mY = int_y + world_rect.mBottom; - return TRUE; - } - return FALSE; + LLVector3 dir_to_point = pos_agent - getOrigin(); + dir_to_point /= dir_to_point.magVec(); + + BOOL in_front = TRUE; + if (dir_to_point * getAtAxis() < 0.f) + { + in_front = FALSE; + } + + LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); + S32 viewport[4]; + viewport[0] = world_view_rect.mLeft; + viewport[1] = world_view_rect.mBottom; + viewport[2] = world_view_rect.getWidth(); + viewport[3] = world_view_rect.getHeight(); + GLdouble x, y, z; // object's window coords, GL-style + + F64 mdlv[16]; + F64 proj[16]; + + for (U32 i = 0; i < 16; i++) + { + mdlv[i] = (F64) gGLModelView[i]; + proj[i] = (F64) gGLProjection[i]; + } + + if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], + pos_agent.mV[VZ], mdlv, + proj, (GLint*)viewport, + &x, &y, &z)) + { + x /= gViewerWindow->getDisplayScale().mV[VX]; + y /= gViewerWindow->getDisplayScale().mV[VY]; + // should now have the x,y coords of grab_point in screen space + const LLRect& world_rect = gViewerWindow->getWorldViewRectScaled(); + + // ...sanity check + S32 int_x = lltrunc(x); + S32 int_y = lltrunc(y); + + // find the center + GLdouble center_x = (GLdouble)world_rect.getCenterX(); + GLdouble center_y = (GLdouble)world_rect.getCenterY(); + + if (x == center_x && y == center_y) + { + // can't project to edge from exact center + return FALSE; + } + + // find the line from center to local + GLdouble line_x = x - center_x; + GLdouble line_y = y - center_y; + + int_x = lltrunc(center_x); + int_y = lltrunc(center_y); + + + if (0.f == line_x) + { + // the slope of the line is undefined + if (line_y > 0.f) + { + int_y = world_rect.mTop; + } + else + { + int_y = world_rect.mBottom; + } + } + else if (0 == world_rect.getWidth()) + { + // the diagonal slope of the view is undefined + if (y < world_rect.mBottom) + { + int_y = world_rect.mBottom; + } + else if ( y > world_rect.mTop) + { + int_y = world_rect.mTop; + } + } + else + { + F32 line_slope = (F32)(line_y / line_x); + F32 rect_slope = ((F32)world_rect.getHeight()) / ((F32)world_rect.getWidth()); + + if (fabs(line_slope) > rect_slope) + { + if (line_y < 0.f) + { + // bottom + int_y = world_rect.mBottom; + } + else + { + // top + int_y = world_rect.mTop; + } + int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x); + } + else if (fabs(line_slope) < rect_slope) + { + if (line_x < 0.f) + { + // left + int_x = world_rect.mLeft; + } + else + { + // right + int_x = world_rect.mRight; + } + int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y); + } + else + { + // exactly parallel ==> push to the corners + if (line_x > 0.f) + { + int_x = world_rect.mRight; + } + else + { + int_x = world_rect.mLeft; + } + if (line_y > 0.0f) + { + int_y = world_rect.mTop; + } + else + { + int_y = world_rect.mBottom; + } + } + } + if (!in_front) + { + int_x = world_rect.mLeft + world_rect.mRight - int_x; + int_y = world_rect.mBottom + world_rect.mTop - int_y; + } + + out_point.mX = int_x + world_rect.mLeft; + out_point.mY = int_y + world_rect.mBottom; + return TRUE; + } + return FALSE; } void LLViewerCamera::getPixelVectors(const LLVector3 &pos_agent, LLVector3 &up, LLVector3 &right) { - LLVector3 to_vec = pos_agent - getOrigin(); + LLVector3 to_vec = pos_agent - getOrigin(); - F32 at_dist = to_vec * getAtAxis(); + F32 at_dist = to_vec * getAtAxis(); - F32 height_meters = at_dist* (F32)tan(getView()/2.f); - F32 height_pixels = getViewHeightInPixels()/2.f; + F32 height_meters = at_dist* (F32)tan(getView()/2.f); + F32 height_pixels = getViewHeightInPixels()/2.f; - F32 pixel_aspect = gViewerWindow->getWindow()->getPixelAspectRatio(); + F32 pixel_aspect = gViewerWindow->getWindow()->getPixelAspectRatio(); - F32 meters_per_pixel = height_meters / height_pixels; - up = getUpAxis() * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY]; - right = -1.f * pixel_aspect * meters_per_pixel * getLeftAxis() * gViewerWindow->getDisplayScale().mV[VX]; + F32 meters_per_pixel = height_meters / height_pixels; + up = getUpAxis() * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY]; + right = -1.f * pixel_aspect * meters_per_pixel * getLeftAxis() * gViewerWindow->getDisplayScale().mV[VX]; } LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent) { - F32 dist = (pos_agent - getOrigin()).magVec(); - // Convert to screen space and back, preserving the depth. - LLCoordGL screen_point; - if (!projectPosAgentToScreen(pos_agent, screen_point, FALSE)) - { - // Off the screen, just return the original position. - return pos_agent; - } - - LLVector3 ray_dir; - - projectScreenToPosAgent(screen_point.mX, screen_point.mY, &ray_dir); - ray_dir -= getOrigin(); - ray_dir.normVec(); - - LLVector3 pos_agent_rounded = getOrigin() + ray_dir*dist; - - /* - LLVector3 pixel_x, pixel_y; - getPixelVectors(pos_agent_rounded, pixel_y, pixel_x); - pos_agent_rounded += 0.5f*pixel_x, 0.5f*pixel_y; - */ - return pos_agent_rounded; + F32 dist = (pos_agent - getOrigin()).magVec(); + // Convert to screen space and back, preserving the depth. + LLCoordGL screen_point; + if (!projectPosAgentToScreen(pos_agent, screen_point, FALSE)) + { + // Off the screen, just return the original position. + return pos_agent; + } + + LLVector3 ray_dir; + + projectScreenToPosAgent(screen_point.mX, screen_point.mY, &ray_dir); + ray_dir -= getOrigin(); + ray_dir.normVec(); + + LLVector3 pos_agent_rounded = getOrigin() + ray_dir*dist; + + /* + LLVector3 pixel_x, pixel_y; + getPixelVectors(pos_agent_rounded, pixel_y, pixel_x); + pos_agent_rounded += 0.5f*pixel_x, 0.5f*pixel_y; + */ + return pos_agent_rounded; } BOOL LLViewerCamera::cameraUnderWater() const @@ -775,69 +775,69 @@ BOOL LLViewerCamera::cameraUnderWater() const regionp = gAgent.getRegion(); } - if(!regionp) - { - return FALSE ; - } + if(!regionp) + { + return FALSE ; + } - return getOrigin().mV[VZ] < regionp->getWaterHeight(); + return getOrigin().mV[VZ] < regionp->getWaterHeight(); } BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) { - S32 i, num_faces; - LLDrawable* drawablep = volumep->mDrawable; - - if (!drawablep) - { - return FALSE; - } - - LLVolume* volume = volumep->getVolume(); - if (!volume) - { - return FALSE; - } - - LLVOVolume* vo_volume = (LLVOVolume*) volumep; - - vo_volume->updateRelativeXform(); - LLMatrix4 mat = vo_volume->getRelativeXform(); - - LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition())); - - LLMatrix4a render_mata; - render_mata.loadu(render_mat); - LLMatrix4a mata; - mata.loadu(mat); - - num_faces = volume->getNumVolumeFaces(); - for (i = 0; i < num_faces; i++) - { - const LLVolumeFace& face = volume->getVolumeFace(i); - - for (U32 v = 0; v < face.mNumVertices; v++) - { - const LLVector4a& src_vec = face.mPositions[v]; - LLVector4a vec; - mata.affineTransform(src_vec, vec); - - if (drawablep->isActive()) - { - LLVector4a t = vec; - render_mata.affineTransform(t, vec); - } - - BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0; - - if (( !in_frustum && all_verts) || - (in_frustum && !all_verts)) - { - return !all_verts; - } - } - } - return all_verts; + S32 i, num_faces; + LLDrawable* drawablep = volumep->mDrawable; + + if (!drawablep) + { + return FALSE; + } + + LLVolume* volume = volumep->getVolume(); + if (!volume) + { + return FALSE; + } + + LLVOVolume* vo_volume = (LLVOVolume*) volumep; + + vo_volume->updateRelativeXform(); + LLMatrix4 mat = vo_volume->getRelativeXform(); + + LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition())); + + LLMatrix4a render_mata; + render_mata.loadu(render_mat); + LLMatrix4a mata; + mata.loadu(mat); + + num_faces = volume->getNumVolumeFaces(); + for (i = 0; i < num_faces; i++) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + for (U32 v = 0; v < face.mNumVertices; v++) + { + const LLVector4a& src_vec = face.mPositions[v]; + LLVector4a vec; + mata.affineTransform(src_vec, vec); + + if (drawablep->isActive()) + { + LLVector4a t = vec; + render_mata.affineTransform(t, vec); + } + + BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0; + + if (( !in_frustum && all_verts) || + (in_frustum && !all_verts)) + { + return !all_verts; + } + } + } + return all_verts; } extern BOOL gCubeSnapshot; @@ -847,29 +847,29 @@ extern BOOL gCubeSnapshot; { llassert(!gCubeSnapshot); - F32 old_fov = LLViewerCamera::getInstance()->getView(); + F32 old_fov = LLViewerCamera::getInstance()->getView(); - // cap the FoV - vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); + // cap the FoV + vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); - if (vertical_fov_rads == old_fov) return; + if (vertical_fov_rads == old_fov) return; - // send the new value to the simulator - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_AgentFOV); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); + // send the new value to the simulator + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_AgentFOV); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); - msg->nextBlockFast(_PREHASH_FOVBlock); - msg->addU32Fast(_PREHASH_GenCounter, 0); - msg->addF32Fast(_PREHASH_VerticalAngle, vertical_fov_rads); + msg->nextBlockFast(_PREHASH_FOVBlock); + msg->addU32Fast(_PREHASH_GenCounter, 0); + msg->addF32Fast(_PREHASH_VerticalAngle, vertical_fov_rads); - gAgent.sendReliableMessage(); + gAgent.sendReliableMessage(); - // sync the camera with the new value - LLCamera::setView(vertical_fov_rads); // call base implementation + // sync the camera with the new value + LLCamera::setView(vertical_fov_rads); // call base implementation } void LLViewerCamera::setViewNoBroadcast(F32 vertical_fov_rads) @@ -877,28 +877,28 @@ void LLViewerCamera::setViewNoBroadcast(F32 vertical_fov_rads) LLCamera::setView(vertical_fov_rads); } -void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) +void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) { - vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); - setView(vertical_fov_rads); - mCameraFOVDefault = vertical_fov_rads; - mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); + vertical_fov_rads = llclamp(vertical_fov_rads, getMinView(), getMaxView()); + setView(vertical_fov_rads); + mCameraFOVDefault = vertical_fov_rads; + mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); } BOOL LLViewerCamera::isDefaultFOVChanged() { - if(mPrevCameraFOVDefault != mCameraFOVDefault) - { - mPrevCameraFOVDefault = mCameraFOVDefault; - return !gSavedSettings.getBOOL("IgnoreFOVZoomForLODs"); - } - return FALSE; + if(mPrevCameraFOVDefault != mCameraFOVDefault) + { + mPrevCameraFOVDefault = mCameraFOVDefault; + return !gSavedSettings.getBOOL("IgnoreFOVZoomForLODs"); + } + return FALSE; } // static void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value) { - LLViewerCamera* self=(LLViewerCamera*)user_data; - self->setDefaultFOV(value.asReal()); + LLViewerCamera* self=(LLViewerCamera*)user_data; + self->setDefaultFOV(value.asReal()); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 1fc51ac23c..9f2e9a62b7 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llviewercontrol.cpp * @brief Viewer configuration * @author Richard Nelson @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -30,7 +30,7 @@ #include "llviewercontrol.h" // Library includes -#include "llwindow.h" // getGamma() +#include "llwindow.h" // getGamma() // For Listeners #include "llaudioengine.h" @@ -81,15 +81,15 @@ #include #ifdef TOGGLE_HACKED_GODLIKE_VIEWER -BOOL gHackGodmode = FALSE; +BOOL gHackGodmode = FALSE; #endif // Should you contemplate changing the name "Global", please first grep for // that string literal. There are at least a couple other places in the C++ // code that assume the LLControlGroup named "Global" is gSavedSettings. -LLControlGroup gSavedSettings("Global"); // saved at end of session +LLControlGroup gSavedSettings("Global"); // saved at end of session LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session -LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session +LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warnings std::string gLastRunVersion; @@ -102,8 +102,8 @@ extern BOOL gDebugGL; static bool handleRenderAvatarMouselookChanged(const LLSD& newvalue) { - LLVOAvatar::sVisibleInFirstPerson = newvalue.asBoolean(); - return true; + LLVOAvatar::sVisibleInFirstPerson = newvalue.asBoolean(); + return true; } static bool handleRenderFarClipChanged(const LLSD& newvalue) @@ -111,9 +111,9 @@ static bool handleRenderFarClipChanged(const LLSD& newvalue) if (LLStartUp::getStartupState() >= STATE_STARTED) { F32 draw_distance = (F32)newvalue.asReal(); - gAgentCamera.mDrawDistance = draw_distance; - LLWorld::getInstance()->setLandFarClip(draw_distance); - return true; + gAgentCamera.mDrawDistance = draw_distance; + LLWorld::getInstance()->setLandFarClip(draw_distance); + return true; } return false; } @@ -125,7 +125,7 @@ static bool handleTerrainScaleChanged(const LLSD& newvalue) { LLDrawPoolTerrain::sDetailScale = F32(1.0 / scale); } - return true; + return true; } static bool handlePBRTerrainScaleChanged(const LLSD& newvalue) @@ -135,7 +135,7 @@ static bool handlePBRTerrainScaleChanged(const LLSD& newvalue) { LLDrawPoolTerrain::sPBRDetailScale = F32(1.0 / scale); } - return true; + return true; } static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) @@ -147,19 +147,19 @@ static bool handleDebugAvatarJointsChanged(const LLSD& newvalue) static bool handleAvatarHoverOffsetChanged(const LLSD& newvalue) { - if (isAgentAvatarValid()) - { - gAgentAvatarp->setHoverIfRegionEnabled(); - } - return true; + if (isAgentAvatarValid()) + { + gAgentAvatarp->setHoverIfRegionEnabled(); + } + return true; } static bool handleSetShaderChanged(const LLSD& newvalue) { - // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache - gBumpImageList.destroyGL(); - gBumpImageList.restoreGL(); + // changing shader level may invalidate existing cached bump maps, as the shader type determines the format of the bump map it expects - clear and repopulate the bump cache + gBumpImageList.destroyGL(); + gBumpImageList.restoreGL(); if (gPipeline.isInit()) { @@ -167,9 +167,9 @@ static bool handleSetShaderChanged(const LLSD& newvalue) LLPipeline::refreshCachedSettings(); } - // else, leave terrain detail as is - LLViewerShaderMgr::instance()->setShaders(); - return true; + // else, leave terrain detail as is + LLViewerShaderMgr::instance()->setShaders(); + return true; } static bool handleRenderPerfTestChanged(const LLSD& newvalue) @@ -186,10 +186,10 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue) LLPipeline::RENDER_TYPE_HUD, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_HUD_PARTICLES, - LLPipeline::END_RENDER_TYPES); + LLPipeline::END_RENDER_TYPES); gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_FEATURE_UI, false); } - else + else { gPipeline.setRenderTypeMask(LLPipeline::RENDER_TYPE_WL_SKY, LLPipeline::RENDER_TYPE_TERRAIN, @@ -209,55 +209,55 @@ static bool handleRenderPerfTestChanged(const LLSD& newvalue) bool handleRenderTransparentWaterChanged(const LLSD& newvalue) { - if (gPipeline.isInit()) - { - gPipeline.updateRenderTransparentWater(); - gPipeline.releaseGLBuffers(); - gPipeline.createGLBuffers(); - LLViewerShaderMgr::instance()->setShaders(); - } - LLWorld::getInstance()->updateWaterObjects(); - return true; + if (gPipeline.isInit()) + { + gPipeline.updateRenderTransparentWater(); + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); + LLViewerShaderMgr::instance()->setShaders(); + } + LLWorld::getInstance()->updateWaterObjects(); + return true; } static bool handleShadowsResized(const LLSD& newvalue) { - gPipeline.requestResizeShadowTexture(); - return true; + gPipeline.requestResizeShadowTexture(); + return true; } static bool handleWindowResized(const LLSD& newvalue) { - gPipeline.requestResizeScreenTexture(); - return true; + gPipeline.requestResizeScreenTexture(); + return true; } static bool handleReleaseGLBufferChanged(const LLSD& newvalue) { - if (gPipeline.isInit()) - { - gPipeline.releaseGLBuffers(); - gPipeline.createGLBuffers(); - } - return true; + if (gPipeline.isInit()) + { + gPipeline.releaseGLBuffers(); + gPipeline.createGLBuffers(); + } + return true; } static bool handleLUTBufferChanged(const LLSD& newvalue) { - if (gPipeline.isInit()) - { - gPipeline.releaseLUTBuffers(); - gPipeline.createLUTBuffers(); - } - return true; + if (gPipeline.isInit()) + { + gPipeline.releaseLUTBuffers(); + gPipeline.createLUTBuffers(); + } + return true; } static bool handleAnisotropicChanged(const LLSD& newvalue) { - LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean(); - LLImageGL::dirtyTexOptions(); - return true; + LLImageGL::sGlobalUseAnisotropic = newvalue.asBoolean(); + LLImageGL::dirtyTexOptions(); + return true; } static bool handleVSyncChanged(const LLSD& newvalue) @@ -276,62 +276,62 @@ static bool handleVSyncChanged(const LLSD& newvalue) static bool handleVolumeLODChanged(const LLSD& newvalue) { - LLVOVolume::sLODFactor = llclamp((F32) newvalue.asReal(), 0.01f, MAX_LOD_FACTOR); - LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; - return true; + LLVOVolume::sLODFactor = llclamp((F32) newvalue.asReal(), 0.01f, MAX_LOD_FACTOR); + LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; + return true; } static bool handleAvatarLODChanged(const LLSD& newvalue) { - LLVOAvatar::sLODFactor = llclamp((F32) newvalue.asReal(), 0.f, MAX_AVATAR_LOD_FACTOR); - return true; + LLVOAvatar::sLODFactor = llclamp((F32) newvalue.asReal(), 0.f, MAX_AVATAR_LOD_FACTOR); + return true; } static bool handleAvatarPhysicsLODChanged(const LLSD& newvalue) { - LLVOAvatar::sPhysicsLODFactor = llclamp((F32) newvalue.asReal(), 0.f, MAX_AVATAR_LOD_FACTOR); - return true; + LLVOAvatar::sPhysicsLODFactor = llclamp((F32) newvalue.asReal(), 0.f, MAX_AVATAR_LOD_FACTOR); + return true; } static bool handleTerrainLODChanged(const LLSD& newvalue) { - LLVOSurfacePatch::sLODFactor = (F32)newvalue.asReal(); - //sqaure lod factor to get exponential range of [0,4] and keep - //a value of 1 in the middle of the detail slider for consistency - //with other detail sliders (see panel_preferences_graphics1.xml) - LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; - return true; + LLVOSurfacePatch::sLODFactor = (F32)newvalue.asReal(); + //sqaure lod factor to get exponential range of [0,4] and keep + //a value of 1 in the middle of the detail slider for consistency + //with other detail sliders (see panel_preferences_graphics1.xml) + LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; + return true; } static bool handleTreeLODChanged(const LLSD& newvalue) { - LLVOTree::sTreeFactor = (F32) newvalue.asReal(); - return true; + LLVOTree::sTreeFactor = (F32) newvalue.asReal(); + return true; } static bool handleFlexLODChanged(const LLSD& newvalue) { - LLVolumeImplFlexible::sUpdateFactor = (F32) newvalue.asReal(); - return true; + LLVolumeImplFlexible::sUpdateFactor = (F32) newvalue.asReal(); + return true; } static bool handleGammaChanged(const LLSD& newvalue) { - F32 gamma = (F32) newvalue.asReal(); - if (gamma == 0.0f) - { - gamma = 1.0f; // restore normal gamma - } - if (gViewerWindow && gViewerWindow->getWindow() && gamma != gViewerWindow->getWindow()->getGamma()) - { - // Only save it if it's changed - if (!gViewerWindow->getWindow()->setGamma(gamma)) - { - LL_WARNS() << "setGamma failed!" << LL_ENDL; - } - } + F32 gamma = (F32) newvalue.asReal(); + if (gamma == 0.0f) + { + gamma = 1.0f; // restore normal gamma + } + if (gViewerWindow && gViewerWindow->getWindow() && gamma != gViewerWindow->getWindow()->getGamma()) + { + // Only save it if it's changed + if (!gViewerWindow->getWindow()->setGamma(gamma)) + { + LL_WARNS() << "setGamma failed!" << LL_ENDL; + } + } - return true; + return true; } const F32 MAX_USER_FOG_RATIO = 10.f; @@ -339,93 +339,93 @@ const F32 MIN_USER_FOG_RATIO = 0.5f; static bool handleFogRatioChanged(const LLSD& newvalue) { - F32 fog_ratio = llmax(MIN_USER_FOG_RATIO, llmin((F32) newvalue.asReal(), MAX_USER_FOG_RATIO)); - gSky.setFogRatio(fog_ratio); - return true; + F32 fog_ratio = llmax(MIN_USER_FOG_RATIO, llmin((F32) newvalue.asReal(), MAX_USER_FOG_RATIO)); + gSky.setFogRatio(fog_ratio); + return true; } static bool handleMaxPartCountChanged(const LLSD& newvalue) { - LLViewerPartSim::setMaxPartCount(newvalue.asInteger()); - return true; + LLViewerPartSim::setMaxPartCount(newvalue.asInteger()); + return true; } static bool handleChatFontSizeChanged(const LLSD& newvalue) { - if(gConsole) - { - gConsole->setFontSize(newvalue.asInteger()); - } - return true; + if(gConsole) + { + gConsole->setFontSize(newvalue.asInteger()); + } + return true; } static bool handleChatPersistTimeChanged(const LLSD& newvalue) { - if(gConsole) - { - gConsole->setLinePersistTime((F32) newvalue.asReal()); - } - return true; + if(gConsole) + { + gConsole->setLinePersistTime((F32) newvalue.asReal()); + } + return true; } static bool handleConsoleMaxLinesChanged(const LLSD& newvalue) { - if(gConsole) - { - gConsole->setMaxLines(newvalue.asInteger()); - } - return true; + if(gConsole) + { + gConsole->setMaxLines(newvalue.asInteger()); + } + return true; } static void handleAudioVolumeChanged(const LLSD& newvalue) { - audio_update_volume(true); + audio_update_volume(true); } static bool handleJoystickChanged(const LLSD& newvalue) { - LLViewerJoystick::getInstance()->setCameraNeedsUpdate(TRUE); - return true; + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(TRUE); + return true; } static bool handleUseOcclusionChanged(const LLSD& newvalue) { - LLPipeline::sUseOcclusion = (newvalue.asBoolean() - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0; - return true; + LLPipeline::sUseOcclusion = (newvalue.asBoolean() + && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0; + return true; } static bool handleUploadBakedTexOldChanged(const LLSD& newvalue) { - LLPipeline::sForceOldBakedUpload = newvalue.asBoolean(); - return true; + LLPipeline::sForceOldBakedUpload = newvalue.asBoolean(); + return true; } static bool handleWLSkyDetailChanged(const LLSD&) { - if (gSky.mVOWLSkyp.notNull()) - { - gSky.mVOWLSkyp->updateGeometry(gSky.mVOWLSkyp->mDrawable); - } - return true; + if (gSky.mVOWLSkyp.notNull()) + { + gSky.mVOWLSkyp->updateGeometry(gSky.mVOWLSkyp->mDrawable); + } + return true; } static bool handleRepartition(const LLSD&) { - if (gPipeline.isInit()) - { - gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); - gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); - gObjectList.repartitionObjects(); - } - return true; + if (gPipeline.isInit()) + { + gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); + gObjectList.repartitionObjects(); + } + return true; } static bool handleRenderDynamicLODChanged(const LLSD& newvalue) { - LLPipeline::sDynamicLOD = newvalue.asBoolean(); - return true; + LLPipeline::sDynamicLOD = newvalue.asBoolean(); + return true; } static bool handleReflectionProbeDetailChanged(const LLSD& newvalue) @@ -456,161 +456,161 @@ static bool handleHeroProbeResolutionChanged(const LLSD &newvalue) static bool handleRenderDebugPipelineChanged(const LLSD& newvalue) { - gDebugPipeline = newvalue.asBoolean(); - return true; + gDebugPipeline = newvalue.asBoolean(); + return true; } static bool handleRenderResolutionDivisorChanged(const LLSD&) { - gResizeScreenTexture = TRUE; - return true; + gResizeScreenTexture = TRUE; + return true; } static bool handleDebugViewsChanged(const LLSD& newvalue) { - LLView::sDebugRects = newvalue.asBoolean(); - return true; + LLView::sDebugRects = newvalue.asBoolean(); + return true; } static bool handleLogFileChanged(const LLSD& newvalue) { - std::string log_filename = newvalue.asString(); - LLFile::remove(log_filename); - LLError::logToFile(log_filename); - return true; + std::string log_filename = newvalue.asString(); + LLFile::remove(log_filename); + LLError::logToFile(log_filename); + return true; } bool handleHideGroupTitleChanged(const LLSD& newvalue) { - gAgent.setHideGroupTitle(newvalue); - return true; + gAgent.setHideGroupTitle(newvalue); + return true; } bool handleEffectColorChanged(const LLSD& newvalue) { - gAgent.setEffectColor(LLColor4(newvalue)); - return true; + gAgent.setEffectColor(LLColor4(newvalue)); + return true; } bool handleHighResSnapshotChanged(const LLSD& newvalue) { - // High Res Snapshot active, must uncheck RenderUIInSnapshot - if (newvalue.asBoolean()) - { - gSavedSettings.setBOOL( "RenderUIInSnapshot", FALSE ); - } - return true; + // High Res Snapshot active, must uncheck RenderUIInSnapshot + if (newvalue.asBoolean()) + { + gSavedSettings.setBOOL( "RenderUIInSnapshot", FALSE ); + } + return true; } bool handleVoiceClientPrefsChanged(const LLSD& newvalue) { - if (LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->updateSettings(); - } - return true; + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->updateSettings(); + } + return true; } bool handleVelocityInterpolate(const LLSD& newvalue) { - LLMessageSystem* msg = gMessageSystem; - if ( newvalue.asBoolean() ) - { - msg->newMessageFast(_PREHASH_VelocityInterpolateOn); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - LL_INFOS() << "Velocity Interpolation On" << LL_ENDL; - } - else - { - msg->newMessageFast(_PREHASH_VelocityInterpolateOff); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - LL_INFOS() << "Velocity Interpolation Off" << LL_ENDL; - } - return true; + LLMessageSystem* msg = gMessageSystem; + if ( newvalue.asBoolean() ) + { + msg->newMessageFast(_PREHASH_VelocityInterpolateOn); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + LL_INFOS() << "Velocity Interpolation On" << LL_ENDL; + } + else + { + msg->newMessageFast(_PREHASH_VelocityInterpolateOff); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + LL_INFOS() << "Velocity Interpolation Off" << LL_ENDL; + } + return true; } bool handleForceShowGrid(const LLSD& newvalue) { - LLPanelLogin::updateLocationSelectorsVisibility(); - return true; + LLPanelLogin::updateLocationSelectorsVisibility(); + return true; } bool handleLoginLocationChanged() { - /* - * This connects the default preference setting to the state of the login - * panel if it is displayed; if you open the preferences panel before - * logging in, and change the default login location there, the login - * panel immediately changes to match your new preference. - */ - std::string new_login_location = gSavedSettings.getString("LoginLocation"); - LL_DEBUGS("AppInit")< dict_list; - std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); - boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); - if (!dict_list.empty()) - { - LLSpellChecker::setUseSpellCheck(dict_list.front()); - dict_list.pop_front(); - LLSpellChecker::instance().setSecondaryDictionaries(dict_list); - return true; - } - } - LLSpellChecker::setUseSpellCheck(LLStringUtil::null); - return true; + if (gSavedSettings.getBOOL("SpellCheck")) + { + std::list dict_list; + std::string dict_setting = gSavedSettings.getString("SpellCheckDictionary"); + boost::split(dict_list, dict_setting, boost::is_any_of(std::string(","))); + if (!dict_list.empty()) + { + LLSpellChecker::setUseSpellCheck(dict_list.front()); + dict_list.pop_front(); + LLSpellChecker::instance().setSecondaryDictionaries(dict_list); + return true; + } + } + LLSpellChecker::setUseSpellCheck(LLStringUtil::null); + return true; } bool toggle_agent_pause(const LLSD& newvalue) { - if ( newvalue.asBoolean() ) - { - send_agent_pause(); - } - else - { - send_agent_resume(); - } - return true; + if ( newvalue.asBoolean() ) + { + send_agent_pause(); + } + else + { + send_agent_resume(); + } + return true; } bool toggle_show_navigation_panel(const LLSD& newvalue) { - bool value = newvalue.asBoolean(); + bool value = newvalue.asBoolean(); - LLNavigationBar::getInstance()->setVisible(value); - gSavedSettings.setBOOL("ShowMiniLocationPanel", !value); + LLNavigationBar::getInstance()->setVisible(value); + gSavedSettings.setBOOL("ShowMiniLocationPanel", !value); gViewerWindow->reshapeStatusBarContainer(); - return true; + return true; } bool toggle_show_mini_location_panel(const LLSD& newvalue) { - bool value = newvalue.asBoolean(); + bool value = newvalue.asBoolean(); - LLPanelTopInfoBar::getInstance()->setVisible(value); - gSavedSettings.setBOOL("ShowNavbarNavigationPanel", !value); + LLPanelTopInfoBar::getInstance()->setVisible(value); + gSavedSettings.setBOOL("ShowNavbarNavigationPanel", !value); - return true; + return true; } bool toggle_show_object_render_cost(const LLSD& newvalue) { - LLFloaterTools::sShowObjectCost = newvalue.asBoolean(); - return true; + LLFloaterTools::sShowObjectCost = newvalue.asBoolean(); + return true; } void handleTargetFPSChanged(const LLSD& newValue) @@ -757,7 +757,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderFogRatio", handleFogRatioChanged); setting_setup_signal_listener(gSavedSettings, "RenderMaxPartCount", handleMaxPartCountChanged); setting_setup_signal_listener(gSavedSettings, "RenderDynamicLOD", handleRenderDynamicLODChanged); - setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged); + setting_setup_signal_listener(gSavedSettings, "RenderVSyncEnable", handleVSyncChanged); setting_setup_signal_listener(gSavedSettings, "RenderDeferredNoise", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderDebugPipeline", handleRenderDebugPipelineChanged); setting_setup_signal_listener(gSavedSettings, "RenderResolutionDivisor", handleRenderResolutionDivisorChanged); @@ -848,7 +848,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "VoiceInputAudioDevice", handleVoiceClientPrefsChanged); setting_setup_signal_listener(gSavedSettings, "VoiceOutputAudioDevice", handleVoiceClientPrefsChanged); setting_setup_signal_listener(gSavedSettings, "AudioLevelMic", handleVoiceClientPrefsChanged); - setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged); + setting_setup_signal_listener(gSavedSettings, "LipSyncEnabled", handleVoiceClientPrefsChanged); setting_setup_signal_listener(gSavedSettings, "VelocityInterpolate", handleVelocityInterpolate); setting_setup_signal_listener(gSavedSettings, "QAMode", show_debug_menus); setting_setup_signal_listener(gSavedSettings, "UseDebugMenus", show_debug_menus); @@ -904,21 +904,21 @@ static LLCachedControl test_BrowserHomePage("BrowserHomePage", "hah void test_cached_control() { #define do { TEST_LLCC(T, V) if((T)mySetting_##T != V) LL_ERRS() << "Fail "#T << LL_ENDL; } while(0) - TEST_LLCC(U32, 666); - TEST_LLCC(S32, (S32)-666); - TEST_LLCC(F32, (F32)-666.666); - TEST_LLCC(bool, true); - TEST_LLCC(BOOL, FALSE); - if((std::string)mySetting_string != "Default String Value") LL_ERRS() << "Fail string" << LL_ENDL; - TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f)); - TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f)); - TEST_LLCC(LLRect, LLRect(0, 0, 100, 500)); - TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f)); - TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f)); - TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); -//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd); - - if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL; + TEST_LLCC(U32, 666); + TEST_LLCC(S32, (S32)-666); + TEST_LLCC(F32, (F32)-666.666); + TEST_LLCC(bool, true); + TEST_LLCC(BOOL, FALSE); + if((std::string)mySetting_string != "Default String Value") LL_ERRS() << "Fail string" << LL_ENDL; + TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f)); + TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f)); + TEST_LLCC(LLRect, LLRect(0, 0, 100, 500)); + TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f)); + TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f)); + TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255)); +//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd); + + if((std::string)test_BrowserHomePage != "http://www.secondlife.com") LL_ERRS() << "Fail BrowserHomePage" << LL_ENDL; } #endif // TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 2a77146101..75e5049370 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerdisplay.cpp * @brief LLViewerDisplay class implementation * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -87,10 +87,10 @@ extern bool gShiftFrame; LLPointer gDisconnectedImagep = NULL; // used to toggle renderer back on after teleport -BOOL gTeleportDisplay = FALSE; +BOOL gTeleportDisplay = FALSE; LLFrameTimer gTeleportDisplayTimer; LLFrameTimer gTeleportArrivalTimer; -const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain +const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain BOOL gForceRenderLandFence = FALSE; BOOL gDisplaySwapBuffers = FALSE; @@ -125,84 +125,84 @@ void render_disconnected_background(); void display_startup() { - if ( !gViewerWindow - || !gViewerWindow->getActive() - || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() - || gNonInteractive) - { - return; - } - - gPipeline.updateGL(); - - // Written as branch to appease GCC which doesn't like different - // pointer types across ternary ops - // - if (!LLViewerFetchedTexture::sWhiteImagep.isNull()) - { - LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); - } - - LLGLSDefault gls_default; - - // Required for HTML update in login screen - static S32 frame_count = 0; - - LLGLState::checkStates(); - - if (frame_count++ > 1) // make sure we have rendered a frame first - { - LLViewerDynamicTexture::updateAllInstances(); - } + if ( !gViewerWindow + || !gViewerWindow->getActive() + || !gViewerWindow->getWindow()->getVisible() + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) + { + return; + } + + gPipeline.updateGL(); + + // Written as branch to appease GCC which doesn't like different + // pointer types across ternary ops + // + if (!LLViewerFetchedTexture::sWhiteImagep.isNull()) + { + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); + } + + LLGLSDefault gls_default; + + // Required for HTML update in login screen + static S32 frame_count = 0; + + LLGLState::checkStates(); + + if (frame_count++ > 1) // make sure we have rendered a frame first + { + LLViewerDynamicTexture::updateAllInstances(); + } else { LL_DEBUGS("Window") << "First display_startup frame" << LL_ENDL; } - LLGLState::checkStates(); + LLGLState::checkStates(); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // | GL_STENCIL_BUFFER_BIT); - LLGLSUIDefault gls_ui; - gPipeline.disableLights(); + LLGLSUIDefault gls_ui; + gPipeline.disableLights(); - if (gViewerWindow) - gViewerWindow->setup2DRender(); - if (gViewerWindow) - gViewerWindow->draw(); - gGL.flush(); + if (gViewerWindow) + gViewerWindow->setup2DRender(); + if (gViewerWindow) + gViewerWindow->draw(); + gGL.flush(); - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - LLGLState::checkStates(); + LLGLState::checkStates(); - if (gViewerWindow && gViewerWindow->getWindow()) - gViewerWindow->getWindow()->swapBuffers(); + if (gViewerWindow && gViewerWindow->getWindow()) + gViewerWindow->getWindow()->swapBuffers(); - glClear(GL_DEPTH_BUFFER_BIT); + glClear(GL_DEPTH_BUFFER_BIT); } void display_update_camera() { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Camera"); - // TODO: cut draw distance down if customizing avatar? - // TODO: cut draw distance on per-parcel basis? + // TODO: cut draw distance down if customizing avatar? + // TODO: cut draw distance on per-parcel basis? - // Cut draw distance in half when customizing avatar, - // but on the viewer only. - F32 final_far = gAgentCamera.mDrawDistance; + // Cut draw distance in half when customizing avatar, + // but on the viewer only. + F32 final_far = gAgentCamera.mDrawDistance; if (gCubeSnapshot) { final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance"); } else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode()) - - { - final_far *= 0.5f; - } - LLViewerCamera::getInstance()->setFar(final_far); - gViewerWindow->setup3DRender(); - + + { + final_far *= 0.5f; + } + LLViewerCamera::getInstance()->setFar(final_far); + gViewerWindow->setup3DRender(); + if (!gCubeSnapshot) { // Update land visibility too @@ -213,30 +213,30 @@ void display_update_camera() // Write some stats to LL_INFOS() void display_stats() { - LL_PROFILE_ZONE_SCOPED - F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency"); - if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - FPS"); - F32 fps = gRecentFrameCount / fps_log_freq; - LL_INFOS() << llformat("FPS: %.02f", fps) << LL_ENDL; - gRecentFrameCount = 0; - gRecentFPSTime.reset(); - } - F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); - if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Memory"); - gMemoryAllocated = U64Bytes(LLMemory::getCurrentRSS()); - U32Megabytes memory = gMemoryAllocated; - LL_INFOS() << "MEMORY: " << memory << LL_ENDL; - LLMemory::logMemoryInfo(TRUE) ; - gRecentMemoryTime.reset(); - } + LL_PROFILE_ZONE_SCOPED + F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency"); + if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - FPS"); + F32 fps = gRecentFrameCount / fps_log_freq; + LL_INFOS() << llformat("FPS: %.02f", fps) << LL_ENDL; + gRecentFrameCount = 0; + gRecentFPSTime.reset(); + } + F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); + if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Memory"); + gMemoryAllocated = U64Bytes(LLMemory::getCurrentRSS()); + U32Megabytes memory = gMemoryAllocated; + LL_INFOS() << "MEMORY: " << memory << LL_ENDL; + LLMemory::logMemoryInfo(TRUE) ; + gRecentMemoryTime.reset(); + } F32 asset_storage_log_freq = gSavedSettings.getF32("AssetStorageLogFrequency"); if (asset_storage_log_freq > 0.f && gAssetStorageLogTime.getElapsedTimeF32() >= asset_storage_log_freq) { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Asset Storage"); + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Asset Storage"); gAssetStorageLogTime.reset(); gAssetStorage->logAssetStorageInfo(); } @@ -244,144 +244,144 @@ void display_stats() static void update_tp_display(bool minimized) { - static LLCachedControl teleport_arrival_delay(gSavedSettings, "TeleportArrivalDelay"); - static LLCachedControl teleport_local_delay(gSavedSettings, "TeleportLocalDelay"); - - S32 attach_count = 0; - if (isAgentAvatarValid()) - { - attach_count = gAgentAvatarp->getAttachmentCount(); - } - F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count; - F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32(); - F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time); - if (gAgent.getTeleportState() != LLAgent::TELEPORT_START && teleport_percent > 100.f) - { - // Give up. Don't keep the UI locked forever. - LL_WARNS("Teleport") << "Giving up on teleport. elapsed time " << teleport_elapsed << " exceeds max time " << teleport_save_time << LL_ENDL; - gAgent.setTeleportState(LLAgent::TELEPORT_NONE); - gAgent.setTeleportMessage(std::string()); - } - - // Make sure the TP progress panel gets hidden in case the viewer window - // is minimized *during* a TP. HB - if (minimized) - { - gViewerWindow->setShowProgress(FALSE); - } - - const std::string& message = gAgent.getTeleportMessage(); - switch (gAgent.getTeleportState()) - { - case LLAgent::TELEPORT_PENDING: - { - gTeleportDisplayTimer.reset(); - const std::string& msg = LLAgent::sTeleportProgressMessages["pending"]; - if (!minimized) - { - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); - gViewerWindow->setProgressString(msg); - } - gAgent.setTeleportMessage(msg); - break; - } - - case LLAgent::TELEPORT_START: - { - // Transition to REQUESTED. Viewer has sent some kind - // of TeleportRequest to the source simulator - gTeleportDisplayTimer.reset(); - const std::string& msg = LLAgent::sTeleportProgressMessages["requesting"]; - LL_INFOS("Teleport") << "A teleport request has been sent, setting state to TELEPORT_REQUESTED" << LL_ENDL; - gAgent.setTeleportState(LLAgent::TELEPORT_REQUESTED); - gAgent.setTeleportMessage(msg); - if (!minimized) - { - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); - gViewerWindow->setProgressString(msg); - gViewerWindow->setProgressMessage(gAgent.mMOTD); - } - break; - } - - case LLAgent::TELEPORT_REQUESTED: - // Waiting for source simulator to respond - if (!minimized) - { - gViewerWindow->setProgressPercent(llmin(teleport_percent, 37.5f)); - gViewerWindow->setProgressString(message); - } - break; - - case LLAgent::TELEPORT_MOVING: - // Viewer has received destination location from source simulator - if (!minimized) - { - gViewerWindow->setProgressPercent(llmin(teleport_percent, 75.f)); - gViewerWindow->setProgressString(message); - } - break; - - case LLAgent::TELEPORT_START_ARRIVAL: - // Transition to ARRIVING. Viewer has received avatar update, etc., - // from destination simulator - gTeleportArrivalTimer.reset(); - LL_INFOS("Teleport") << "Changing state to TELEPORT_ARRIVING" << LL_ENDL; - gAgent.setTeleportState(LLAgent::TELEPORT_ARRIVING); - gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["arriving"]); - gAgent.sheduleTeleportIM(); - gTextureList.mForceResetTextureStats = TRUE; - gAgentCamera.resetView(TRUE, TRUE); - if (!minimized) - { - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent(75.f); - } - break; - - case LLAgent::TELEPORT_ARRIVING: - // Make the user wait while content "pre-caches" - { - F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / teleport_arrival_delay()); - if (arrival_fraction > 1.f) - { - arrival_fraction = 1.f; - //LLFirstUse::useTeleport(); - LL_INFOS("Teleport") << "arrival_fraction is " << arrival_fraction << " changing state to TELEPORT_NONE" << LL_ENDL; - gAgent.setTeleportState(LLAgent::TELEPORT_NONE); - } - if (!minimized) - { - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent(arrival_fraction * 25.f + 75.f); - gViewerWindow->setProgressString(message); - } - break; - } - - case LLAgent::TELEPORT_LOCAL: - // Short delay when teleporting in the same sim (progress screen active but not shown - did not - // fall-through from TELEPORT_START) - { - if (gTeleportDisplayTimer.getElapsedTimeF32() > teleport_local_delay()) - { - //LLFirstUse::useTeleport(); - LL_INFOS("Teleport") << "State is local and gTeleportDisplayTimer " << gTeleportDisplayTimer.getElapsedTimeF32() - << " exceeds teleport_local_delete " << teleport_local_delay - << "; setting state to TELEPORT_NONE" - << LL_ENDL; - gAgent.setTeleportState(LLAgent::TELEPORT_NONE); - } - break; - } - - case LLAgent::TELEPORT_NONE: - // No teleport in progress - gViewerWindow->setShowProgress(FALSE); - gTeleportDisplay = FALSE; - } + static LLCachedControl teleport_arrival_delay(gSavedSettings, "TeleportArrivalDelay"); + static LLCachedControl teleport_local_delay(gSavedSettings, "TeleportLocalDelay"); + + S32 attach_count = 0; + if (isAgentAvatarValid()) + { + attach_count = gAgentAvatarp->getAttachmentCount(); + } + F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count; + F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32(); + F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time); + if (gAgent.getTeleportState() != LLAgent::TELEPORT_START && teleport_percent > 100.f) + { + // Give up. Don't keep the UI locked forever. + LL_WARNS("Teleport") << "Giving up on teleport. elapsed time " << teleport_elapsed << " exceeds max time " << teleport_save_time << LL_ENDL; + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); + gAgent.setTeleportMessage(std::string()); + } + + // Make sure the TP progress panel gets hidden in case the viewer window + // is minimized *during* a TP. HB + if (minimized) + { + gViewerWindow->setShowProgress(FALSE); + } + + const std::string& message = gAgent.getTeleportMessage(); + switch (gAgent.getTeleportState()) + { + case LLAgent::TELEPORT_PENDING: + { + gTeleportDisplayTimer.reset(); + const std::string& msg = LLAgent::sTeleportProgressMessages["pending"]; + if (!minimized) + { + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + gViewerWindow->setProgressString(msg); + } + gAgent.setTeleportMessage(msg); + break; + } + + case LLAgent::TELEPORT_START: + { + // Transition to REQUESTED. Viewer has sent some kind + // of TeleportRequest to the source simulator + gTeleportDisplayTimer.reset(); + const std::string& msg = LLAgent::sTeleportProgressMessages["requesting"]; + LL_INFOS("Teleport") << "A teleport request has been sent, setting state to TELEPORT_REQUESTED" << LL_ENDL; + gAgent.setTeleportState(LLAgent::TELEPORT_REQUESTED); + gAgent.setTeleportMessage(msg); + if (!minimized) + { + gViewerWindow->setShowProgress(TRUE); + gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + gViewerWindow->setProgressString(msg); + gViewerWindow->setProgressMessage(gAgent.mMOTD); + } + break; + } + + case LLAgent::TELEPORT_REQUESTED: + // Waiting for source simulator to respond + if (!minimized) + { + gViewerWindow->setProgressPercent(llmin(teleport_percent, 37.5f)); + gViewerWindow->setProgressString(message); + } + break; + + case LLAgent::TELEPORT_MOVING: + // Viewer has received destination location from source simulator + if (!minimized) + { + gViewerWindow->setProgressPercent(llmin(teleport_percent, 75.f)); + gViewerWindow->setProgressString(message); + } + break; + + case LLAgent::TELEPORT_START_ARRIVAL: + // Transition to ARRIVING. Viewer has received avatar update, etc., + // from destination simulator + gTeleportArrivalTimer.reset(); + LL_INFOS("Teleport") << "Changing state to TELEPORT_ARRIVING" << LL_ENDL; + gAgent.setTeleportState(LLAgent::TELEPORT_ARRIVING); + gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["arriving"]); + gAgent.sheduleTeleportIM(); + gTextureList.mForceResetTextureStats = TRUE; + gAgentCamera.resetView(TRUE, TRUE); + if (!minimized) + { + gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); + gViewerWindow->setProgressPercent(75.f); + } + break; + + case LLAgent::TELEPORT_ARRIVING: + // Make the user wait while content "pre-caches" + { + F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / teleport_arrival_delay()); + if (arrival_fraction > 1.f) + { + arrival_fraction = 1.f; + //LLFirstUse::useTeleport(); + LL_INFOS("Teleport") << "arrival_fraction is " << arrival_fraction << " changing state to TELEPORT_NONE" << LL_ENDL; + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); + } + if (!minimized) + { + gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); + gViewerWindow->setProgressPercent(arrival_fraction * 25.f + 75.f); + gViewerWindow->setProgressString(message); + } + break; + } + + case LLAgent::TELEPORT_LOCAL: + // Short delay when teleporting in the same sim (progress screen active but not shown - did not + // fall-through from TELEPORT_START) + { + if (gTeleportDisplayTimer.getElapsedTimeF32() > teleport_local_delay()) + { + //LLFirstUse::useTeleport(); + LL_INFOS("Teleport") << "State is local and gTeleportDisplayTimer " << gTeleportDisplayTimer.getElapsedTimeF32() + << " exceeds teleport_local_delete " << teleport_local_delay + << "; setting state to TELEPORT_NONE" + << LL_ENDL; + gAgent.setTeleportState(LLAgent::TELEPORT_NONE); + } + break; + } + + case LLAgent::TELEPORT_NONE: + // No teleport in progress + gViewerWindow->setShowProgress(FALSE); + gTeleportDisplay = FALSE; + } } // Paint the display! @@ -390,521 +390,521 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Render"); LLPerfStats::RecordSceneTime T (LLPerfStats::StatType_t::RENDER_DISPLAY); // render time capture - This is the main stat for overall rendering. - - if (gWindowResized) - { //skip render on frames where window has been resized - LL_DEBUGS("Window") << "Resizing window" << LL_ENDL; + + if (gWindowResized) + { //skip render on frames where window has been resized + LL_DEBUGS("Window") << "Resizing window" << LL_ENDL; LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Resize Window"); - gGL.flush(); - glClear(GL_COLOR_BUFFER_BIT); - gViewerWindow->getWindow()->swapBuffers(); - LLPipeline::refreshCachedSettings(); - gPipeline.resizeScreenTexture(); - gResizeScreenTexture = FALSE; - gWindowResized = FALSE; - return; - } + gGL.flush(); + glClear(GL_COLOR_BUFFER_BIT); + gViewerWindow->getWindow()->swapBuffers(); + LLPipeline::refreshCachedSettings(); + gPipeline.resizeScreenTexture(); + gResizeScreenTexture = FALSE; + gWindowResized = FALSE; + return; + } if (gResizeShadowTexture) - { //skip render on frames where window has been resized - gPipeline.resizeShadowTexture(); - gResizeShadowTexture = FALSE; - } - - gSnapshot = for_snapshot; - - if (LLPipeline::sRenderDeferred) - { //hack to make sky show up in deferred snapshots - for_snapshot = FALSE; - } - - LLGLSDefault gls_default; - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); - - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); - - gPipeline.disableLights(); - - // Don't draw if the window is hidden or minimized. - // In fact, must explicitly check the minimized state before drawing. - // Attempting to draw into a minimized window causes a GL error. JC - if ( !gViewerWindow->getActive() - || !gViewerWindow->getWindow()->getVisible() - || gViewerWindow->getWindow()->getMinimized() - || gNonInteractive) - { - // Clean up memory the pools may have allocated - if (rebuild) - { - stop_glerror(); - gPipeline.rebuildPools(); - stop_glerror(); - } - - stop_glerror(); - gViewerWindow->returnEmptyPicks(); - stop_glerror(); - - // We still need to update the teleport progress (to get changes done - // in TP states, else the sim does not get the messages signaling the - // agent's arrival). This fixes BUG-230616. HB - if (gTeleportDisplay) - { - // true = minimized, do not show/update the TP screen. HB - update_tp_display(true); - } - return; - } - - gViewerWindow->checkSettings(); - - { + { //skip render on frames where window has been resized + gPipeline.resizeShadowTexture(); + gResizeShadowTexture = FALSE; + } + + gSnapshot = for_snapshot; + + if (LLPipeline::sRenderDeferred) + { //hack to make sky show up in deferred snapshots + for_snapshot = FALSE; + } + + LLGLSDefault gls_default; + LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); + + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + + gPipeline.disableLights(); + + // Don't draw if the window is hidden or minimized. + // In fact, must explicitly check the minimized state before drawing. + // Attempting to draw into a minimized window causes a GL error. JC + if ( !gViewerWindow->getActive() + || !gViewerWindow->getWindow()->getVisible() + || gViewerWindow->getWindow()->getMinimized() + || gNonInteractive) + { + // Clean up memory the pools may have allocated + if (rebuild) + { + stop_glerror(); + gPipeline.rebuildPools(); + stop_glerror(); + } + + stop_glerror(); + gViewerWindow->returnEmptyPicks(); + stop_glerror(); + + // We still need to update the teleport progress (to get changes done + // in TP states, else the sim does not get the messages signaling the + // agent's arrival). This fixes BUG-230616. HB + if (gTeleportDisplay) + { + // true = minimized, do not show/update the TP screen. HB + update_tp_display(true); + } + return; + } + + gViewerWindow->checkSettings(); + + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Picking"); - gViewerWindow->performPick(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); - LLGLState::checkStates(); - - ////////////////////////////////////////////////////////// - // - // Logic for forcing window updates if we're in drone mode. - // - - // *TODO: Investigate running display() during gHeadlessClient. See if this early exit is needed DK 2011-02-18 - if (gHeadlessClient) - { + gViewerWindow->performPick(); + } + + LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); + LLGLState::checkStates(); + + ////////////////////////////////////////////////////////// + // + // Logic for forcing window updates if we're in drone mode. + // + + // *TODO: Investigate running display() during gHeadlessClient. See if this early exit is needed DK 2011-02-18 + if (gHeadlessClient) + { #if LL_WINDOWS - static F32 last_update_time = 0.f; - if ((gFrameTimeSeconds - last_update_time) > 1.f) - { - InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); - last_update_time = gFrameTimeSeconds; - } + static F32 last_update_time = 0.f; + if ((gFrameTimeSeconds - last_update_time) > 1.f) + { + InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); + last_update_time = gFrameTimeSeconds; + } #elif LL_DARWIN - // MBW -- Do something clever here. + // MBW -- Do something clever here. #endif - // Not actually rendering, don't bother. - return; - } - - - // - // Bail out if we're in the startup state and don't want to try to - // render the world. - // - if (LLStartUp::getStartupState() < STATE_PRECACHE) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); - display_startup(); - return; - } - - - if (gShaderProfileFrame) - { - LLGLSLShader::initProfile(); - } - - //LLGLState::verify(FALSE); - - ///////////////////////////////////////////////// - // - // Update GL Texture statistics (used for discard logic?) - // - - LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); - stop_glerror(); - - LLImageGL::updateStats(gFrameTimeSeconds); - - LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode"); - LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode")); - - gPipeline.mBackfaceCull = TRUE; - gFrameCount++; - gRecentFrameCount++; - if (gFocusMgr.getAppHasFocus()) - { - gForegroundFrameCount++; - } - - ////////////////////////////////////////////////////////// - // - // Display start screen if we're teleporting, and skip render - // - - if (gTeleportDisplay) - { + // Not actually rendering, don't bother. + return; + } + + + // + // Bail out if we're in the startup state and don't want to try to + // render the world. + // + if (LLStartUp::getStartupState() < STATE_PRECACHE) + { + LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); + display_startup(); + return; + } + + + if (gShaderProfileFrame) + { + LLGLSLShader::initProfile(); + } + + //LLGLState::verify(FALSE); + + ///////////////////////////////////////////////// + // + // Update GL Texture statistics (used for discard logic?) + // + + LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); + stop_glerror(); + + LLImageGL::updateStats(gFrameTimeSeconds); + + LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode"); + LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode")); + + gPipeline.mBackfaceCull = TRUE; + gFrameCount++; + gRecentFrameCount++; + if (gFocusMgr.getAppHasFocus()) + { + gForegroundFrameCount++; + } + + ////////////////////////////////////////////////////////// + // + // Display start screen if we're teleporting, and skip render + // + + if (gTeleportDisplay) + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Teleport Display"); - LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); - // Note: false = not minimized, do update the TP screen. HB - update_tp_display(false); - } + LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); + // Note: false = not minimized, do update the TP screen. HB + update_tp_display(false); + } else if(LLAppViewer::instance()->logoutRequestSent()) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); - F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; - if (percent_done > 100.f) - { - percent_done = 100.f; - } - - if( LLApp::isExiting() ) - { - percent_done = 100.f; - } - - gViewerWindow->setProgressPercent( percent_done ); - gViewerWindow->setProgressMessage(std::string()); - } - else - if (gRestoreGL) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); - F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; - if( percent_done > 100.f ) - { - gViewerWindow->setShowProgress(FALSE); - gRestoreGL = FALSE; - } - else - { - - if( LLApp::isExiting() ) - { - percent_done = 100.f; - } - - gViewerWindow->setProgressPercent( percent_done ); - } - gViewerWindow->setProgressMessage(std::string()); - } - - ////////////////////////// - // - // Prepare for the next frame - // - - ///////////////////////////// - // - // Update the camera - // - // - - LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); + { + LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); + F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; + if (percent_done > 100.f) + { + percent_done = 100.f; + } + + if( LLApp::isExiting() ) + { + percent_done = 100.f; + } + + gViewerWindow->setProgressPercent( percent_done ); + gViewerWindow->setProgressMessage(std::string()); + } + else + if (gRestoreGL) + { + LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); + F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; + if( percent_done > 100.f ) + { + gViewerWindow->setShowProgress(FALSE); + gRestoreGL = FALSE; + } + else + { + + if( LLApp::isExiting() ) + { + percent_done = 100.f; + } + + gViewerWindow->setProgressPercent( percent_done ); + } + gViewerWindow->setProgressMessage(std::string()); + } + + ////////////////////////// + // + // Prepare for the next frame + // + + ///////////////////////////// + // + // Update the camera + // + // + + LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); if (LLViewerCamera::instanceExists()) { LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); } - ////////////////////////// - // - // clear the next buffer - // (must follow dynamic texture writing since that uses the frame buffer) - // - - if (gDisconnected) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); - render_ui(); - swap(); - } - - ////////////////////////// - // - // Set rendering options - // - // - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); - stop_glerror(); - - /////////////////////////////////////// - // - // Slam lighting parameters back to our defaults. - // Note that these are not the same as GL defaults... - - stop_glerror(); - gGL.setAmbientLightColor(LLColor4::white); - stop_glerror(); - - ///////////////////////////////////// - // - // Render - // - // Actually push all of our triangles to the screen. - // - - // do render-to-texture stuff here - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); + ////////////////////////// + // + // clear the next buffer + // (must follow dynamic texture writing since that uses the frame buffer) + // + + if (gDisconnected) + { + LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); + render_ui(); + swap(); + } + + ////////////////////////// + // + // Set rendering options + // + // + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); + stop_glerror(); + + /////////////////////////////////////// + // + // Slam lighting parameters back to our defaults. + // Note that these are not the same as GL defaults... + + stop_glerror(); + gGL.setAmbientLightColor(LLColor4::white); + stop_glerror(); + + ///////////////////////////////////// + // + // Render + // + // Actually push all of our triangles to the screen. + // + + // do render-to-texture stuff here + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) + { + LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Dynamic Textures"); - if (LLViewerDynamicTexture::updateAllInstances()) - { - gGL.setColorMask(true, true); - glClear(GL_DEPTH_BUFFER_BIT); - } - } - - gViewerWindow->setup3DViewport(); - - gPipeline.resetFrameStats(); // Reset per-frame statistics. - - if (!gDisconnected) - { - // Render mirrors and associated hero probes before we render the rest of the scene. - // This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it. + if (LLViewerDynamicTexture::updateAllInstances()) + { + gGL.setColorMask(true, true); + glClear(GL_DEPTH_BUFFER_BIT); + } + } + + gViewerWindow->setup3DViewport(); + + gPipeline.resetFrameStats(); // Reset per-frame statistics. + + if (!gDisconnected) + { + // Render mirrors and associated hero probes before we render the rest of the scene. + // This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it. if (gPipeline.RenderMirrors && !gSnapshot && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0)) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes"); gPipeline.mHeroProbeManager.update(); } - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 1"); - LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { //don't draw hud objects in this frame - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - } - - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES)) - { //don't draw hud particles in this frame - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - } - - stop_glerror(); - display_update_camera(); - stop_glerror(); - - { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 1"); + LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { //don't draw hud objects in this frame + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES)) + { //don't draw hud particles in this frame + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); + } + + stop_glerror(); + display_update_camera(); + stop_glerror(); + + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Env Update"); // update all the sky/atmospheric/water settings LLEnvironment::instance().update(LLViewerCamera::getInstance()); - } + } - // *TODO: merge these two methods - { + // *TODO: merge these two methods + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("HUD Update"); - LLHUDManager::getInstance()->updateEffects(); - LLHUDObject::updateAll(); - stop_glerror(); - } + LLHUDManager::getInstance()->updateEffects(); + LLHUDObject::updateAll(); + stop_glerror(); + } - { + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update Geom"); - const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time - gPipeline.createObjects(max_geom_update_time); - gPipeline.processPartitionQ(); - gPipeline.updateGeom(max_geom_update_time); - stop_glerror(); - } - - gPipeline.updateGL(); - - stop_glerror(); - - LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); - - //Increment drawable frame counter - LLDrawable::incrementVisible(); - - LLSpatialGroup::sNoDelete = TRUE; - LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); - - S32 occlusion = LLPipeline::sUseOcclusion; - if (gDepthDirty) - { //depth buffer is invalid, don't overwrite occlusion state - LLPipeline::sUseOcclusion = llmin(occlusion, 1); - } - gDepthDirty = FALSE; - - LLGLState::checkStates(); - - static LLCullResult result; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater(); - gPipeline.updateCull(*LLViewerCamera::getInstance(), result); - stop_glerror(); - - LLGLState::checkStates(); - - LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 2") - if (gResizeScreenTexture) - { - gPipeline.resizeScreenTexture(); + const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time + gPipeline.createObjects(max_geom_update_time); + gPipeline.processPartitionQ(); + gPipeline.updateGeom(max_geom_update_time); + stop_glerror(); + } + + gPipeline.updateGL(); + + stop_glerror(); + + LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); + + //Increment drawable frame counter + LLDrawable::incrementVisible(); + + LLSpatialGroup::sNoDelete = TRUE; + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); + + S32 occlusion = LLPipeline::sUseOcclusion; + if (gDepthDirty) + { //depth buffer is invalid, don't overwrite occlusion state + LLPipeline::sUseOcclusion = llmin(occlusion, 1); + } + gDepthDirty = FALSE; + + LLGLState::checkStates(); + + static LLCullResult result; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater(); + gPipeline.updateCull(*LLViewerCamera::getInstance(), result); + stop_glerror(); + + LLGLState::checkStates(); + + LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 2") + if (gResizeScreenTexture) + { + gPipeline.resizeScreenTexture(); gResizeScreenTexture = FALSE; - } + } - gGL.setColorMask(true, true); - glClearColor(0,0,0,0); + gGL.setColorMask(true, true); + glClearColor(0,0,0,0); - LLGLState::checkStates(); + LLGLState::checkStates(); - if (!for_snapshot) - { + if (!for_snapshot) + { if (gFrameCount > 1 && !for_snapshot) - { //for some reason, ATI 4800 series will error out if you + { //for some reason, ATI 4800 series will error out if you //try to generate a shadow before the first frame is through gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); } - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - LLGLState::checkStates(); + LLGLState::checkStates(); - glh::matrix4f proj = get_current_projection(); - glh::matrix4f mod = get_current_modelview(); - glViewport(0,0,512,512); + glh::matrix4f proj = get_current_projection(); + glh::matrix4f mod = get_current_modelview(); + glViewport(0,0,512,512); - LLVOAvatar::updateImpostors(); + LLVOAvatar::updateImpostors(); - set_current_projection(proj); - set_current_modelview(mod); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadMatrix(proj.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(mod.m); - gViewerWindow->setup3DViewport(); + set_current_projection(proj); + set_current_modelview(mod); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadMatrix(proj.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(mod.m); + gViewerWindow->setup3DViewport(); - LLGLState::checkStates(); - } + LLGLState::checkStates(); + } glClear(GL_DEPTH_BUFFER_BIT); - } - - ////////////////////////////////////// - // - // Update images, using the image stats generated during object update/culling - // - // Can put objects onto the retextured list. - // - // Doing this here gives hardware occlusion queries extra time to complete - LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); - - { + } + + ////////////////////////////////////// + // + // Update images, using the image stats generated during object update/culling + // + // Can put objects onto the retextured list. + // + // Doing this here gives hardware occlusion queries extra time to complete + LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); + + { LL_PROFILE_ZONE_NAMED("Update Images"); - - { + + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Class"); - LLViewerTexture::updateClass(); - } + LLViewerTexture::updateClass(); + } - { + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Image Update Bump"); - gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. - } + gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. + } - { + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("List"); - F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time - max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) - gTextureList.updateImages(max_image_decode_time); - } + F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time + max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) + gTextureList.updateImages(max_image_decode_time); + } - { + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("GLTF Materials Cleanup"); - //remove dead gltf materials + //remove dead gltf materials gGLTFMaterialList.flushMaterials(); - } - } - - LLGLState::checkStates(); - - /////////////////////////////////// - // - // StateSort - // - // Responsible for taking visible objects, and adding them to the appropriate draw orders. - // In the case of alpha objects, z-sorts them first. - // Also creates special lists for outlines and selected face rendering. - // - LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 4") - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - gPipeline.stateSort(*LLViewerCamera::getInstance(), result); - stop_glerror(); - - if (rebuild) - { - ////////////////////////////////////// - // - // rebuildPools - // - // - gPipeline.rebuildPools(); - stop_glerror(); - } - } - - LLSceneMonitor::getInstance()->fetchQueryResult(); - - LLGLState::checkStates(); - - LLPipeline::sUseOcclusion = occlusion; - - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); - LL_PROFILE_ZONE_NAMED_CATEGORY_ENVIRONMENT("update sky"); //LL_RECORD_BLOCK_TIME(FTM_UPDATE_SKY); - gSky.updateSky(); - } - - if(gUseWireframe) - { - glClearColor(0.5f, 0.5f, 0.5f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); - - //// render frontmost floater opaque for occlusion culling purposes - //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); - //// assumes frontmost floater with focus is opaque - //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) - //{ - // gGL.matrixMode(LLRender::MM_MODELVIEW); - // gGL.pushMatrix(); - // { - // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - // gGL.loadIdentity(); - - // LLRect floater_rect = frontmost_floaterp->calcScreenRect(); - // // deflate by one pixel so rounding errors don't occlude outside of floater extents - // floater_rect.stretch(-1); - // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), - // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(), - // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(), - // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled()); - // floater_3d_rect.translate(-0.5f, -0.5f); - // gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); - // gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); - // gGL.color4fv(LLColor4::white.mV); - // gGL.begin(LLVertexBuffer::QUADS); - // { - // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); - // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); - // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); - // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); - // } - // gGL.end(); - // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - // } - // gGL.popMatrix(); - //} - - LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; - - LLGLState::checkStates(); - - stop_glerror(); + } + } + + LLGLState::checkStates(); + + /////////////////////////////////// + // + // StateSort + // + // Responsible for taking visible objects, and adding them to the appropriate draw orders. + // In the case of alpha objects, z-sorts them first. + // Also creates special lists for outlines and selected face rendering. + // + LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 4") + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + gPipeline.stateSort(*LLViewerCamera::getInstance(), result); + stop_glerror(); + + if (rebuild) + { + ////////////////////////////////////// + // + // rebuildPools + // + // + gPipeline.rebuildPools(); + stop_glerror(); + } + } + + LLSceneMonitor::getInstance()->fetchQueryResult(); + + LLGLState::checkStates(); + + LLPipeline::sUseOcclusion = occlusion; + + { + LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); + LL_PROFILE_ZONE_NAMED_CATEGORY_ENVIRONMENT("update sky"); //LL_RECORD_BLOCK_TIME(FTM_UPDATE_SKY); + gSky.updateSky(); + } + + if(gUseWireframe) + { + glClearColor(0.5f, 0.5f, 0.5f, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + } + + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); + + //// render frontmost floater opaque for occlusion culling purposes + //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); + //// assumes frontmost floater with focus is opaque + //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) + //{ + // gGL.matrixMode(LLRender::MM_MODELVIEW); + // gGL.pushMatrix(); + // { + // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + // gGL.loadIdentity(); + + // LLRect floater_rect = frontmost_floaterp->calcScreenRect(); + // // deflate by one pixel so rounding errors don't occlude outside of floater extents + // floater_rect.stretch(-1); + // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), + // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(), + // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(), + // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled()); + // floater_3d_rect.translate(-0.5f, -0.5f); + // gGL.translatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); + // gGL.scalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); + // gGL.color4fv(LLColor4::white.mV); + // gGL.begin(LLVertexBuffer::QUADS); + // { + // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); + // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); + // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); + // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); + // } + // gGL.end(); + // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + // } + // gGL.popMatrix(); + //} + + LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; + + LLGLState::checkStates(); + + stop_glerror(); gGL.setColorMask(true, true); @@ -936,94 +936,94 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gGL.setColorMask(true, false); LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom"); - - if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) - && !gRestoreGL) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 5") - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - - if (gSavedSettings.getBOOL("RenderDepthPrePass")) - { - gGL.setColorMask(false, false); - - static const U32 types[] = { - LLRenderPass::PASS_SIMPLE, - LLRenderPass::PASS_FULLBRIGHT, - LLRenderPass::PASS_SHINY - }; - - U32 num_types = LL_ARRAY_SIZE(types); - gOcclusionProgram.bind(); - for (U32 i = 0; i < num_types; i++) - { - gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); - } - - gOcclusionProgram.unbind(); - - } - - gGL.setColorMask(true, true); - gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance(), true); - } - - { + + if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) + && !gRestoreGL) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 5") + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + + if (gSavedSettings.getBOOL("RenderDepthPrePass")) + { + gGL.setColorMask(false, false); + + static const U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY + }; + + U32 num_types = LL_ARRAY_SIZE(types); + gOcclusionProgram.bind(); + for (U32 i = 0; i < num_types; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + gOcclusionProgram.unbind(); + + } + + gGL.setColorMask(true, true); + gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance(), true); + } + + { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Texture Unbind"); - for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) - { //dummy cleanup of any currently bound textures - if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) - { - gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); - gGL.getTexUnit(i)->disable(); - } - } - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); + for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } + } + + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mRT->deferredScreen : gPipeline.mRT->screen); rt.flush(); if (LLPipeline::sRenderDeferred) { - gPipeline.renderDeferredLighting(); - } - - LLPipeline::sUnderWaterRender = FALSE; - - { - //capture the frame buffer. - LLSceneMonitor::getInstance()->capture(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); - if (!for_snapshot) - { - render_ui(); - swap(); - } - - - LLSpatialGroup::sNoDelete = FALSE; - gPipeline.clearReferences(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); - - stop_glerror(); - - display_stats(); - - LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); - - gShiftFrame = false; - - if (gShaderProfileFrame) - { - gShaderProfileFrame = FALSE; - LLGLSLShader::finishProfile(); - } + gPipeline.renderDeferredLighting(); + } + + LLPipeline::sUnderWaterRender = FALSE; + + { + //capture the frame buffer. + LLSceneMonitor::getInstance()->capture(); + } + + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); + if (!for_snapshot) + { + render_ui(); + swap(); + } + + + LLSpatialGroup::sNoDelete = FALSE; + gPipeline.clearReferences(); + } + + LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); + + stop_glerror(); + + display_stats(); + + LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); + + gShiftFrame = false; + + if (gShaderProfileFrame) + { + gShaderProfileFrame = FALSE; + LLGLSLShader::finishProfile(); + } } // WIP simplified copy of display() that does minimal work @@ -1070,7 +1070,7 @@ void display_cube_face() } LLSpatialGroup::sNoDelete = TRUE; - + S32 occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data @@ -1084,7 +1084,7 @@ void display_cube_face() glClearColor(0, 0, 0, 0); gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); - + glClear(GL_DEPTH_BUFFER_BIT); // | GL_STENCIL_BUFFER_BIT); { @@ -1102,7 +1102,7 @@ void display_cube_face() stop_glerror(); } } - + LLPipeline::sUseOcclusion = occlusion; LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); @@ -1121,13 +1121,13 @@ void display_cube_face() glClearColor(1, 0, 1, 1); } gPipeline.mRT->deferredScreen.clear(); - + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); gPipeline.mRT->deferredScreen.flush(); - + gPipeline.renderDeferredLighting(); LLPipeline::sUnderWaterRender = FALSE; @@ -1143,200 +1143,200 @@ void render_hud_attachments() { LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_HUDS); // render time capture - Primary contributor to HUDs (though these end up in render batches) gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - - glh::matrix4f current_proj = get_current_projection(); - glh::matrix4f current_mod = get_current_modelview(); - - // clamp target zoom level to reasonable values - gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f); - // smoothly interpolate current zoom level - gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.getAgentHUDTargetZoom(), LLSmoothInterpolation::getInterpolant(0.03f)); - - if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) - { - LLPipeline::sRenderingHUDs = TRUE; - LLCamera hud_cam = *LLViewerCamera::getInstance(); - hud_cam.setOrigin(-1.f,0,0); - hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); - LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); - - bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); - - //only render hud objects - gPipeline.pushRenderTypeMask(); - - // turn off everything - gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); - // turn on HUD - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - // turn on HUD particles - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - - // if particles are off, turn off hud-particles as well - if (!render_particles) - { - // turn back off HUD particles - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - } - - bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - if (has_ui) - { - gPipeline.toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - S32 use_occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - - //cull, sort, and render hud objects - static LLCullResult result; - LLSpatialGroup::sNoDelete = TRUE; - - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - gPipeline.updateCull(hud_cam, result); + gGL.pushMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + + glh::matrix4f current_proj = get_current_projection(); + glh::matrix4f current_mod = get_current_modelview(); + + // clamp target zoom level to reasonable values + gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f); + // smoothly interpolate current zoom level + gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.getAgentHUDTargetZoom(), LLSmoothInterpolation::getInterpolant(0.03f)); + + if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) + { + LLPipeline::sRenderingHUDs = TRUE; + LLCamera hud_cam = *LLViewerCamera::getInstance(); + hud_cam.setOrigin(-1.f,0,0); + hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); + LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); + + bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); + + //only render hud objects + gPipeline.pushRenderTypeMask(); + + // turn off everything + gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); + // turn on HUD + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + // turn on HUD particles + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); + + // if particles are off, turn off hud-particles as well + if (!render_particles) + { + // turn back off HUD particles + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); + } + + bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); + if (has_ui) + { + gPipeline.toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + S32 use_occlusion = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 0; + + //cull, sort, and render hud objects + static LLCullResult result; + LLSpatialGroup::sNoDelete = TRUE; + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + gPipeline.updateCull(hud_cam, result); // Toggle render types - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_GLTF_PBR); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_GLTF_PBR_ALPHA_MASK); // Toggle render passes - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MATERIAL); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MATERIAL); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_GLTF_PBR); gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK); - - gPipeline.stateSort(hud_cam, result); - - gPipeline.renderGeomPostDeferred(hud_cam); - - LLSpatialGroup::sNoDelete = FALSE; - //gPipeline.clearReferences(); - - render_hud_elements(); - - //restore type mask - gPipeline.popRenderTypeMask(); - - if (has_ui) - { - gPipeline.toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - LLPipeline::sUseOcclusion = use_occlusion; - LLPipeline::sRenderingHUDs = FALSE; - } - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - - set_current_projection(current_proj); - set_current_modelview(current_mod); + + gPipeline.stateSort(hud_cam, result); + + gPipeline.renderGeomPostDeferred(hud_cam); + + LLSpatialGroup::sNoDelete = FALSE; + //gPipeline.clearReferences(); + + render_hud_elements(); + + //restore type mask + gPipeline.popRenderTypeMask(); + + if (has_ui) + { + gPipeline.toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + LLPipeline::sUseOcclusion = use_occlusion; + LLPipeline::sRenderingHUDs = FALSE; + } + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + + set_current_projection(current_proj); + set_current_modelview(current_mod); } LLRect get_whole_screen_region() { - LLRect whole_screen = gViewerWindow->getWorldViewRectScaled(); - - // apply camera zoom transform (for high res screenshots) - F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); - S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - S32 num_horizontal_tiles = llceil(zoom_factor); - S32 tile_width = ll_round((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor); - S32 tile_height = ll_round((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor); - int tile_y = sub_region / num_horizontal_tiles; - int tile_x = sub_region - (tile_y * num_horizontal_tiles); - - whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height); - } - return whole_screen; + LLRect whole_screen = gViewerWindow->getWorldViewRectScaled(); + + // apply camera zoom transform (for high res screenshots) + F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); + S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); + if (zoom_factor > 1.f) + { + S32 num_horizontal_tiles = llceil(zoom_factor); + S32 tile_width = ll_round((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor); + S32 tile_height = ll_round((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor); + int tile_y = sub_region / num_horizontal_tiles; + int tile_x = sub_region - (tile_y * num_horizontal_tiles); + + whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height); + } + return whole_screen; } bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model) { - if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment()) - { - F32 zoom_level = gAgentCamera.mHUDCurZoom; - LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); - - F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); - proj.element(2,2) = -0.01f; - - F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); - - glh::matrix4f mat; - F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth(); - F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight(); - mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); - mat.set_translate( - glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), - clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), - 0.f)); - proj *= mat; - - glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION); - - mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); - mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); - - tmp_model *= mat; - model = tmp_model; - return TRUE; - } - else - { - return FALSE; - } + if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment()) + { + F32 zoom_level = gAgentCamera.mHUDCurZoom; + LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); + + F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); + proj.element(2,2) = -0.01f; + + F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); + + glh::matrix4f mat; + F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth(); + F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight(); + mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); + mat.set_translate( + glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), + clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), + 0.f)); + proj *= mat; + + glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION); + + mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); + mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); + + tmp_model *= mat; + model = tmp_model; + return TRUE; + } + else + { + return FALSE; + } } bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model) { - LLRect whole_screen = get_whole_screen_region(); - return get_hud_matrices(whole_screen, proj, model); + LLRect whole_screen = get_whole_screen_region(); + return get_hud_matrices(whole_screen, proj, model); } bool setup_hud_matrices() { - LLRect whole_screen = get_whole_screen_region(); - return setup_hud_matrices(whole_screen); + LLRect whole_screen = get_whole_screen_region(); + return setup_hud_matrices(whole_screen); } bool setup_hud_matrices(const LLRect& screen_region) { - glh::matrix4f proj, model; - bool result = get_hud_matrices(screen_region, proj, model); - if (!result) return result; - - // set up transform to keep HUD objects in front of camera - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadMatrix(proj.m); - set_current_projection(proj); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(model.m); - set_current_modelview(model); - return TRUE; + glh::matrix4f proj, model; + bool result = get_hud_matrices(screen_region, proj, model); + if (!result) return result; + + // set up transform to keep HUD objects in front of camera + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadMatrix(proj.m); + set_current_projection(proj); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(model.m); + set_current_modelview(model); + return TRUE; } void render_ui(F32 zoom_factor, int subfield) @@ -1344,45 +1344,45 @@ void render_ui(F32 zoom_factor, int subfield) LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_UI ); // render time capture - Primary UI stat can have HUD time overlap (TODO) LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); LL_PROFILE_GPU_ZONE("ui"); - LLGLState::checkStates(); - - glh::matrix4f saved_view = get_current_modelview(); - - if (!gSnapshot) - { - gGL.pushMatrix(); - gGL.loadMatrix(gGLLastModelView); - set_current_modelview(copy_matrix(gGLLastModelView)); - } - - if(LLSceneMonitor::getInstance()->needsUpdate()) - { - gGL.pushMatrix(); - gViewerWindow->setup2DRender(); - LLSceneMonitor::getInstance()->compare(); - gViewerWindow->setup3DRender(); - gGL.popMatrix(); - } + LLGLState::checkStates(); + + glh::matrix4f saved_view = get_current_modelview(); + + if (!gSnapshot) + { + gGL.pushMatrix(); + gGL.loadMatrix(gGLLastModelView); + set_current_modelview(copy_matrix(gGLLastModelView)); + } + + if(LLSceneMonitor::getInstance()->needsUpdate()) + { + gGL.pushMatrix(); + gViewerWindow->setup2DRender(); + LLSceneMonitor::getInstance()->compare(); + gViewerWindow->setup3DRender(); + gGL.popMatrix(); + } // apply gamma correction and post effects gPipeline.renderFinalize(); - { + { LLGLState::checkStates(); LL_PROFILE_ZONE_NAMED_CATEGORY_UI("HUD"); - render_hud_elements(); + render_hud_elements(); LLGLState::checkStates(); - render_hud_attachments(); + render_hud_attachments(); LLGLState::checkStates(); - LLGLSDefault gls_default; - LLGLSUIDefault gls_ui; - { - gPipeline.disableLights(); - } + LLGLSDefault gls_default; + LLGLSUIDefault gls_ui; + { + gPipeline.disableLights(); + } bool render_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); if (render_ui) @@ -1410,13 +1410,13 @@ void render_ui(F32 zoom_factor, int subfield) gViewerWindow->setup2DRender(); gViewerWindow->updateDebugText(); gViewerWindow->drawDebugText(); - } + } - if (!gSnapshot) - { - set_current_modelview(saved_view); - gGL.popMatrix(); - } + if (!gSnapshot) + { + set_current_modelview(saved_view); + gGL.popMatrix(); + } } void swap() @@ -1424,112 +1424,112 @@ void swap() LLPerfStats::RecordSceneTime T ( LLPerfStats::StatType_t::RENDER_SWAP ); // render time capture - Swap buffer time - can signify excessive data transfer to/from GPU LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Swap"); LL_PROFILE_GPU_ZONE("swap"); - if (gDisplaySwapBuffers) - { - gViewerWindow->getWindow()->swapBuffers(); - } - gDisplaySwapBuffers = TRUE; + if (gDisplaySwapBuffers) + { + gViewerWindow->getWindow()->swapBuffers(); + } + gDisplaySwapBuffers = TRUE; } void renderCoordinateAxes() { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::LINES); - gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(2.0f, 0.0f, 0.0f); - gGL.vertex3f(3.0f, 0.0f, 0.0f); - gGL.vertex3f(5.0f, 0.0f, 0.0f); - gGL.vertex3f(6.0f, 0.0f, 0.0f); - gGL.vertex3f(8.0f, 0.0f, 0.0f); - // Make an X - gGL.vertex3f(11.0f, 1.0f, 1.0f); - gGL.vertex3f(11.0f, -1.0f, -1.0f); - gGL.vertex3f(11.0f, 1.0f, -1.0f); - gGL.vertex3f(11.0f, -1.0f, 1.0f); - - gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 2.0f, 0.0f); - gGL.vertex3f(0.0f, 3.0f, 0.0f); - gGL.vertex3f(0.0f, 5.0f, 0.0f); - gGL.vertex3f(0.0f, 6.0f, 0.0f); - gGL.vertex3f(0.0f, 8.0f, 0.0f); - // Make a Y - gGL.vertex3f(1.0f, 11.0f, 1.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(-1.0f, 11.0f, 1.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(0.0f, 11.0f, -1.0f); - - gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 2.0f); - gGL.vertex3f(0.0f, 0.0f, 3.0f); - gGL.vertex3f(0.0f, 0.0f, 5.0f); - gGL.vertex3f(0.0f, 0.0f, 6.0f); - gGL.vertex3f(0.0f, 0.0f, 8.0f); - // Make a Z - gGL.vertex3f(-1.0f, 1.0f, 11.0f); - gGL.vertex3f(1.0f, 1.0f, 11.0f); - gGL.vertex3f(1.0f, 1.0f, 11.0f); - gGL.vertex3f(-1.0f, -1.0f, 11.0f); - gGL.vertex3f(-1.0f, -1.0f, 11.0f); - gGL.vertex3f(1.0f, -1.0f, 11.0f); - gGL.end(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.begin(LLRender::LINES); + gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(2.0f, 0.0f, 0.0f); + gGL.vertex3f(3.0f, 0.0f, 0.0f); + gGL.vertex3f(5.0f, 0.0f, 0.0f); + gGL.vertex3f(6.0f, 0.0f, 0.0f); + gGL.vertex3f(8.0f, 0.0f, 0.0f); + // Make an X + gGL.vertex3f(11.0f, 1.0f, 1.0f); + gGL.vertex3f(11.0f, -1.0f, -1.0f); + gGL.vertex3f(11.0f, 1.0f, -1.0f); + gGL.vertex3f(11.0f, -1.0f, 1.0f); + + gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(0.0f, 2.0f, 0.0f); + gGL.vertex3f(0.0f, 3.0f, 0.0f); + gGL.vertex3f(0.0f, 5.0f, 0.0f); + gGL.vertex3f(0.0f, 6.0f, 0.0f); + gGL.vertex3f(0.0f, 8.0f, 0.0f); + // Make a Y + gGL.vertex3f(1.0f, 11.0f, 1.0f); + gGL.vertex3f(0.0f, 11.0f, 0.0f); + gGL.vertex3f(-1.0f, 11.0f, 1.0f); + gGL.vertex3f(0.0f, 11.0f, 0.0f); + gGL.vertex3f(0.0f, 11.0f, 0.0f); + gGL.vertex3f(0.0f, 11.0f, -1.0f); + + gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(0.0f, 0.0f, 2.0f); + gGL.vertex3f(0.0f, 0.0f, 3.0f); + gGL.vertex3f(0.0f, 0.0f, 5.0f); + gGL.vertex3f(0.0f, 0.0f, 6.0f); + gGL.vertex3f(0.0f, 0.0f, 8.0f); + // Make a Z + gGL.vertex3f(-1.0f, 1.0f, 11.0f); + gGL.vertex3f(1.0f, 1.0f, 11.0f); + gGL.vertex3f(1.0f, 1.0f, 11.0f); + gGL.vertex3f(-1.0f, -1.0f, 11.0f); + gGL.vertex3f(-1.0f, -1.0f, 11.0f); + gGL.vertex3f(1.0f, -1.0f, 11.0f); + gGL.end(); } -void draw_axes() +void draw_axes() { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // A vertical white line at origin - LLVector3 v = gAgent.getPositionAgent(); - gGL.begin(LLRender::LINES); - gGL.color3f(1.0f, 1.0f, 1.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 40.0f); - gGL.end(); - // Some coordinate axes - gGL.pushMatrix(); - gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] ); - renderCoordinateAxes(); - gGL.popMatrix(); + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + // A vertical white line at origin + LLVector3 v = gAgent.getPositionAgent(); + gGL.begin(LLRender::LINES); + gGL.color3f(1.0f, 1.0f, 1.0f); + gGL.vertex3f(0.0f, 0.0f, 0.0f); + gGL.vertex3f(0.0f, 0.0f, 40.0f); + gGL.end(); + // Some coordinate axes + gGL.pushMatrix(); + gGL.translatef( v.mV[VX], v.mV[VY], v.mV[VZ] ); + renderCoordinateAxes(); + gGL.popMatrix(); } void render_ui_3d() { - LLGLSPipeline gls_pipeline; - - ////////////////////////////////////// - // - // Render 3D UI elements - // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD, - // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD - // - - ///////////////////////////////////////////////////////////// - // - // Render 2.5D elements (2D elements in the world) - // Stuff without z writes - // - - // Debugging stuff goes before the UI. - - stop_glerror(); - - gUIProgram.bind(); + LLGLSPipeline gls_pipeline; + + ////////////////////////////////////// + // + // Render 3D UI elements + // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD, + // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD + // + + ///////////////////////////////////////////////////////////// + // + // Render 2.5D elements (2D elements in the world) + // Stuff without z writes + // + + // Debugging stuff goes before the UI. + + stop_glerror(); + + gUIProgram.bind(); gGL.color4f(1, 1, 1, 1); - // Coordinate axes - if (gSavedSettings.getBOOL("ShowAxes")) - { - draw_axes(); - } + // Coordinate axes + if (gSavedSettings.getBOOL("ShowAxes")) + { + draw_axes(); + } - gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements + gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { @@ -1539,205 +1539,205 @@ void render_ui_3d() gSky.addSunMoonBeacons(); } - stop_glerror(); + stop_glerror(); } void render_ui_2d() { - LLGLSUIDefault gls_ui; + LLGLSUIDefault gls_ui; - ///////////////////////////////////////////////////////////// - // - // Render 2D UI elements that overlay the world (no z compare) + ///////////////////////////////////////////////////////////// + // + // Render 2D UI elements that overlay the world (no z compare) - // Disable wireframe mode below here, as this is HUD/menus - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // Disable wireframe mode below here, as this is HUD/menus + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - // Menu overlays, HUD, etc - gViewerWindow->setup2DRender(); + // Menu overlays, HUD, etc + gViewerWindow->setup2DRender(); - F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); - S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); + F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); + S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - //decompose subregion number to x and y values - int pos_y = sub_region / llceil(zoom_factor); - int pos_x = sub_region - (pos_y*llceil(zoom_factor)); - // offset for this tile - LLFontGL::sCurOrigin.mX -= ll_round((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor); - LLFontGL::sCurOrigin.mY -= ll_round((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor); - } + if (zoom_factor > 1.f) + { + //decompose subregion number to x and y values + int pos_y = sub_region / llceil(zoom_factor); + int pos_x = sub_region - (pos_y*llceil(zoom_factor)); + // offset for this tile + LLFontGL::sCurOrigin.mX -= ll_round((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor); + LLFontGL::sCurOrigin.mY -= ll_round((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor); + } - stop_glerror(); + stop_glerror(); - // render outline for HUD - if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) - { + // render outline for HUD + if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) + { gUIProgram.bind(); - gGL.pushMatrix(); - S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); - S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); - gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f); - gGL.translatef((F32)half_width, (F32)half_height, 0.f); - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom,zoom,1.f); - gGL.color4fv(LLColor4::white.mV); - gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); - gGL.popMatrix(); + gGL.pushMatrix(); + S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); + S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); + gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f); + gGL.translatef((F32)half_width, (F32)half_height, 0.f); + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom,zoom,1.f); + gGL.color4fv(LLColor4::white.mV); + gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); + gGL.popMatrix(); gUIProgram.unbind(); - stop_glerror(); - } - - - if (gSavedSettings.getBOOL("RenderUIBuffer")) - { - if (LLView::sIsRectDirty) - { + stop_glerror(); + } + + + if (gSavedSettings.getBOOL("RenderUIBuffer")) + { + if (LLView::sIsRectDirty) + { LLView::sIsRectDirty = false; - LLRect t_rect; + LLRect t_rect; - gPipeline.mRT->uiScreen.bindTarget(); - gGL.setColorMask(true, true); - { - static const S32 pad = 8; + gPipeline.mRT->uiScreen.bindTarget(); + gGL.setColorMask(true, true); + { + static const S32 pad = 8; LLView::sDirtyRect.mLeft -= pad; LLView::sDirtyRect.mRight += pad; LLView::sDirtyRect.mBottom -= pad; LLView::sDirtyRect.mTop += pad; - LLGLEnable scissor(GL_SCISSOR_TEST); - static LLRect last_rect = LLView::sDirtyRect; + LLGLEnable scissor(GL_SCISSOR_TEST); + static LLRect last_rect = LLView::sDirtyRect; + + //union with last rect to avoid mouse poop + last_rect.unionWith(LLView::sDirtyRect); - //union with last rect to avoid mouse poop - last_rect.unionWith(LLView::sDirtyRect); - - t_rect = LLView::sDirtyRect; + t_rect = LLView::sDirtyRect; LLView::sDirtyRect = last_rect; - last_rect = t_rect; + last_rect = t_rect; + + last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); + last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); + last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); + last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]); - last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::getScaleFactor().mV[0]); - last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::getScaleFactor().mV[0]); - last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::getScaleFactor().mV[1]); - last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::getScaleFactor().mV[1]); + LLRect clip_rect(last_rect); - LLRect clip_rect(last_rect); - - glClear(GL_COLOR_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); - gViewerWindow->draw(); - } + gViewerWindow->draw(); + } - gPipeline.mRT->uiScreen.flush(); - gGL.setColorMask(true, false); + gPipeline.mRT->uiScreen.flush(); + gGL.setColorMask(true, false); LLView::sDirtyRect = t_rect; - } - - LLGLDisable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - S32 width = gViewerWindow->getWindowWidthScaled(); - S32 height = gViewerWindow->getWindowHeightScaled(); - gGL.getTexUnit(0)->bind(&gPipeline.mRT->uiScreen); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0); - gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0); - gGL.texCoord2f(0, height); gGL.vertex2i(0, height); - gGL.texCoord2f(width, height); gGL.vertex2i(width, height); - gGL.end(); - } - else - { - gViewerWindow->draw(); - } - - - - // reset current origin for font rendering, in case of tiling render - LLFontGL::sCurOrigin.set(0, 0); + } + + LLGLDisable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + S32 width = gViewerWindow->getWindowWidthScaled(); + S32 height = gViewerWindow->getWindowHeightScaled(); + gGL.getTexUnit(0)->bind(&gPipeline.mRT->uiScreen); + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.color4f(1,1,1,1); + gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0); + gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0); + gGL.texCoord2f(0, height); gGL.vertex2i(0, height); + gGL.texCoord2f(width, height); gGL.vertex2i(width, height); + gGL.end(); + } + else + { + gViewerWindow->draw(); + } + + + + // reset current origin for font rendering, in case of tiling render + LLFontGL::sCurOrigin.set(0, 0); } void render_disconnected_background() { - gUIProgram.bind(); - - gGL.color4f(1,1,1,1); - if (!gDisconnectedImagep && gDisconnected) - { - LL_INFOS() << "Loading last bitmap..." << LL_ENDL; - - std::string temp_str; - temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getScreenLastFilename(); - - LLPointer image_png = new LLImagePNG; - if( !image_png->load(temp_str) ) - { - //LL_INFOS() << "Bitmap load failed" << LL_ENDL; - return; - } - - LLPointer raw = new LLImageRaw; - if (!image_png->decode(raw, 0.0f)) - { - LL_INFOS() << "Bitmap decode failed" << LL_ENDL; - gDisconnectedImagep = NULL; - return; - } - - U8 *rawp = raw->getData(); - S32 npixels = (S32)image_png->getWidth()*(S32)image_png->getHeight(); - for (S32 i = 0; i < npixels; i++) - { - S32 sum = 0; - sum = *rawp + *(rawp+1) + *(rawp+2); - sum /= 3; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - } - - - raw->expandToPowerOfTwo(); - gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE ); - gStartTexture = gDisconnectedImagep; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - - // Make sure the progress view always fills the entire window. - S32 width = gViewerWindow->getWindowWidthScaled(); - S32 height = gViewerWindow->getWindowHeightScaled(); - - if (gDisconnectedImagep) - { - LLGLSUIDefault gls_ui; - gViewerWindow->setup2DRender(); - gGL.pushMatrix(); - { - // scale ui to reflect UIScaleFactor - // this can't be done in setup2DRender because it requires a - // pushMatrix/popMatrix pair - const LLVector2& display_scale = gViewerWindow->getDisplayScale(); - gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); - - gGL.getTexUnit(0)->bind(gDisconnectedImagep); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - gl_rect_2d_simple_tex(width, height); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - gGL.popMatrix(); - } - gGL.flush(); - - gUIProgram.unbind(); + gUIProgram.bind(); + + gGL.color4f(1,1,1,1); + if (!gDisconnectedImagep && gDisconnected) + { + LL_INFOS() << "Loading last bitmap..." << LL_ENDL; + + std::string temp_str; + temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getScreenLastFilename(); + + LLPointer image_png = new LLImagePNG; + if( !image_png->load(temp_str) ) + { + //LL_INFOS() << "Bitmap load failed" << LL_ENDL; + return; + } + + LLPointer raw = new LLImageRaw; + if (!image_png->decode(raw, 0.0f)) + { + LL_INFOS() << "Bitmap decode failed" << LL_ENDL; + gDisconnectedImagep = NULL; + return; + } + + U8 *rawp = raw->getData(); + S32 npixels = (S32)image_png->getWidth()*(S32)image_png->getHeight(); + for (S32 i = 0; i < npixels; i++) + { + S32 sum = 0; + sum = *rawp + *(rawp+1) + *(rawp+2); + sum /= 3; + *rawp = ((S32)sum*6 + *rawp)/7; + rawp++; + *rawp = ((S32)sum*6 + *rawp)/7; + rawp++; + *rawp = ((S32)sum*6 + *rawp)/7; + rawp++; + } + + + raw->expandToPowerOfTwo(); + gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE ); + gStartTexture = gDisconnectedImagep; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + + // Make sure the progress view always fills the entire window. + S32 width = gViewerWindow->getWindowWidthScaled(); + S32 height = gViewerWindow->getWindowHeightScaled(); + + if (gDisconnectedImagep) + { + LLGLSUIDefault gls_ui; + gViewerWindow->setup2DRender(); + gGL.pushMatrix(); + { + // scale ui to reflect UIScaleFactor + // this can't be done in setup2DRender because it requires a + // pushMatrix/popMatrix pair + const LLVector2& display_scale = gViewerWindow->getDisplayScale(); + gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); + + gGL.getTexUnit(0)->bind(gDisconnectedImagep); + gGL.color4f(1.f, 1.f, 1.f, 1.f); + gl_rect_2d_simple_tex(width, height); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + gGL.popMatrix(); + } + gGL.flush(); + + gUIProgram.unbind(); } void display_cleanup() { - gDisconnectedImagep = NULL; + gDisconnectedImagep = NULL; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c1a8c5df9e..8da467021d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewermenu.cpp * @brief Builds menus out of items. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2014, 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$ */ @@ -30,7 +30,7 @@ #include "vld.h" #endif -#include "llviewermenu.h" +#include "llviewermenu.h" // linden library includes #include "llavatarnamecache.h" // IDEVO (I Are Not Men!) @@ -115,7 +115,7 @@ #include "llviewerdisplay.h" //for gWindowResized #include "llviewergenericmessage.h" #include "llviewerhelp.h" -#include "llviewermenufile.h" // init_menu_file() +#include "llviewermenufile.h" // init_menu_file() #include "llviewermessage.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -160,7 +160,7 @@ void handle_test_load_url(void*); // // Evil hackish imported globals -//extern BOOL gHideSelectedObjects; +//extern BOOL gHideSelectedObjects; //extern BOOL gAllowSelectAvatar; //extern BOOL gDebugAvatarRotation; extern BOOL gDebugClicks; @@ -174,20 +174,20 @@ extern BOOL gShaderProfileFrame; // Globals // -LLMenuBarGL *gMenuBarView = NULL; -LLViewerMenuHolderGL *gMenuHolder = NULL; -LLMenuGL *gPopupMenuView = NULL; -LLMenuGL *gEditMenu = NULL; -LLMenuBarGL *gLoginMenuBarView = NULL; +LLMenuBarGL *gMenuBarView = NULL; +LLViewerMenuHolderGL *gMenuHolder = NULL; +LLMenuGL *gPopupMenuView = NULL; +LLMenuGL *gEditMenu = NULL; +LLMenuBarGL *gLoginMenuBarView = NULL; // Pie menus -LLContextMenu *gMenuAvatarSelf = NULL; -LLContextMenu *gMenuAvatarOther = NULL; -LLContextMenu *gMenuObject = NULL; -LLContextMenu *gMenuAttachmentSelf = NULL; -LLContextMenu *gMenuAttachmentOther = NULL; -LLContextMenu *gMenuLand = NULL; -LLContextMenu *gMenuMuteParticle = NULL; +LLContextMenu *gMenuAvatarSelf = NULL; +LLContextMenu *gMenuAvatarOther = NULL; +LLContextMenu *gMenuObject = NULL; +LLContextMenu *gMenuAttachmentSelf = NULL; +LLContextMenu *gMenuAttachmentOther = NULL; +LLContextMenu *gMenuLand = NULL; +LLContextMenu *gMenuMuteParticle = NULL; const std::string SAVE_INTO_TASK_INVENTORY("Save Object Back to Object Contents"); @@ -285,7 +285,7 @@ void handle_force_parcel_owner_to_me(void*); void handle_force_parcel_to_content(void*); void handle_claim_public_land(void*); -void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry +void handle_god_request_avatar_geometry(void *); // Hack for easy testing of new avatar geometry void reload_vertex_shader(void *); void handle_disconnect_viewer(void *); @@ -345,9 +345,9 @@ void menu_toggle_attached_particles(void* user_data); class LLMenuParcelObserver : public LLParcelObserver { public: - LLMenuParcelObserver(); - ~LLMenuParcelObserver(); - virtual void changed(); + LLMenuParcelObserver(); + ~LLMenuParcelObserver(); + virtual void changed(); }; static LLMenuParcelObserver* gMenuParcelObserver = NULL; @@ -356,17 +356,17 @@ static LLUIListener sUIListener; LLMenuParcelObserver::LLMenuParcelObserver() { - LLViewerParcelMgr::getInstance()->addObserver(this); + LLViewerParcelMgr::getInstance()->addObserver(this); } LLMenuParcelObserver::~LLMenuParcelObserver() { - LLViewerParcelMgr::getInstance()->removeObserver(this); + LLViewerParcelMgr::getInstance()->removeObserver(this); } void LLMenuParcelObserver::changed() { - LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(); + LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(); if (gMenuLand && parcel) { LLView* child = gMenuLand->findChild("Land Buy Pass"); @@ -439,129 +439,129 @@ void check_merchant_status(bool force) void init_menus() { - // Initialize actions - initialize_menus(); - - /// - /// Popup menu - /// - /// The popup menu is now populated by the show_context_menu() - /// method. - - LLMenuGL::Params menu_params; - menu_params.name = "Popup"; - menu_params.visible = false; - gPopupMenuView = LLUICtrlFactory::create(menu_params); - gMenuHolder->addChild( gPopupMenuView ); - - /// - /// Context menus - /// - - const widget_registry_t& registry = - LLViewerMenuHolderGL::child_registry_t::instance(); - gEditMenu = LLUICtrlFactory::createFromFile("menu_edit.xml", gMenuHolder, registry); - gMenuAvatarSelf = LLUICtrlFactory::createFromFile( - "menu_avatar_self.xml", gMenuHolder, registry); - gMenuAvatarOther = LLUICtrlFactory::createFromFile( - "menu_avatar_other.xml", gMenuHolder, registry); - - gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); - gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); - - gMenuObject = LLUICtrlFactory::createFromFile( - "menu_object.xml", gMenuHolder, registry); - - gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); - gAttachPieMenu = gMenuHolder->getChild("Object Attach"); - - gMenuAttachmentSelf = LLUICtrlFactory::createFromFile( - "menu_attachment_self.xml", gMenuHolder, registry); - gMenuAttachmentOther = LLUICtrlFactory::createFromFile( - "menu_attachment_other.xml", gMenuHolder, registry); - - gDetachHUDAttSelfMenu = gMenuHolder->getChild("Detach Self HUD", true); - gDetachAttSelfMenu = gMenuHolder->getChild("Detach Self", true); - - gMenuLand = LLUICtrlFactory::createFromFile( - "menu_land.xml", gMenuHolder, registry); - - gMenuMuteParticle = LLUICtrlFactory::createFromFile( - "menu_mute_particle.xml", gMenuHolder, registry); - - /// - /// set up the colors - /// - LLColor4 color; - - LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor"); - - gMenuAvatarSelf->setBackgroundColor( context_menu_color ); - gMenuAvatarOther->setBackgroundColor( context_menu_color ); - gMenuObject->setBackgroundColor( context_menu_color ); - gMenuAttachmentSelf->setBackgroundColor( context_menu_color ); - gMenuAttachmentOther->setBackgroundColor( context_menu_color ); - - gMenuLand->setBackgroundColor( context_menu_color ); - - color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" ); - gPopupMenuView->setBackgroundColor( color ); - - // If we are not in production, use a different color to make it apparent. - if (LLGridManager::getInstance()->isInProductionGrid()) - { - color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); - } - else - { - color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); - } - - LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); - - gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT)); - gMenuBarView->setBackgroundColor( color ); - - menu_bar_holder->addChild(gMenuBarView); - - gViewerWindow->setMenuBackgroundColor(false, + // Initialize actions + initialize_menus(); + + /// + /// Popup menu + /// + /// The popup menu is now populated by the show_context_menu() + /// method. + + LLMenuGL::Params menu_params; + menu_params.name = "Popup"; + menu_params.visible = false; + gPopupMenuView = LLUICtrlFactory::create(menu_params); + gMenuHolder->addChild( gPopupMenuView ); + + /// + /// Context menus + /// + + const widget_registry_t& registry = + LLViewerMenuHolderGL::child_registry_t::instance(); + gEditMenu = LLUICtrlFactory::createFromFile("menu_edit.xml", gMenuHolder, registry); + gMenuAvatarSelf = LLUICtrlFactory::createFromFile( + "menu_avatar_self.xml", gMenuHolder, registry); + gMenuAvatarOther = LLUICtrlFactory::createFromFile( + "menu_avatar_other.xml", gMenuHolder, registry); + + gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); + gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); + + gMenuObject = LLUICtrlFactory::createFromFile( + "menu_object.xml", gMenuHolder, registry); + + gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); + gAttachPieMenu = gMenuHolder->getChild("Object Attach"); + + gMenuAttachmentSelf = LLUICtrlFactory::createFromFile( + "menu_attachment_self.xml", gMenuHolder, registry); + gMenuAttachmentOther = LLUICtrlFactory::createFromFile( + "menu_attachment_other.xml", gMenuHolder, registry); + + gDetachHUDAttSelfMenu = gMenuHolder->getChild("Detach Self HUD", true); + gDetachAttSelfMenu = gMenuHolder->getChild("Detach Self", true); + + gMenuLand = LLUICtrlFactory::createFromFile( + "menu_land.xml", gMenuHolder, registry); + + gMenuMuteParticle = LLUICtrlFactory::createFromFile( + "menu_mute_particle.xml", gMenuHolder, registry); + + /// + /// set up the colors + /// + LLColor4 color; + + LLColor4 context_menu_color = LLUIColorTable::instance().getColor("MenuPopupBgColor"); + + gMenuAvatarSelf->setBackgroundColor( context_menu_color ); + gMenuAvatarOther->setBackgroundColor( context_menu_color ); + gMenuObject->setBackgroundColor( context_menu_color ); + gMenuAttachmentSelf->setBackgroundColor( context_menu_color ); + gMenuAttachmentOther->setBackgroundColor( context_menu_color ); + + gMenuLand->setBackgroundColor( context_menu_color ); + + color = LLUIColorTable::instance().getColor( "MenuPopupBgColor" ); + gPopupMenuView->setBackgroundColor( color ); + + // If we are not in production, use a different color to make it apparent. + if (LLGridManager::getInstance()->isInProductionGrid()) + { + color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); + } + else + { + color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); + } + + LLView* menu_bar_holder = gViewerWindow->getRootView()->getChildView("menu_bar_holder"); + + gMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_viewer.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuBarView->setRect(LLRect(0, menu_bar_holder->getRect().mTop, 0, menu_bar_holder->getRect().mTop - MENU_BAR_HEIGHT)); + gMenuBarView->setBackgroundColor( color ); + + menu_bar_holder->addChild(gMenuBarView); + + gViewerWindow->setMenuBackgroundColor(false, LLGridManager::getInstance()->isInProductionGrid()); - // *TODO:Also fix cost in llfolderview.cpp for Inventory menus - const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); - const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); - gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); - gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); - - gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); - gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); - - gDetachAvatarMenu = gMenuHolder->getChild("Avatar Detach", true); - gDetachHUDAvatarMenu = gMenuHolder->getChild("Avatar Detach HUD", true); - - // Don't display the Memory console menu if the feature is turned off - LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild("Memory", TRUE); - if (memoryMenu) - { - memoryMenu->setVisible(FALSE); - } - - gMenuBarView->createJumpKeys(); - - // Let land based option enable when parcel changes - gMenuParcelObserver = new LLMenuParcelObserver(); - - gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gLoginMenuBarView->arrangeAndClear(); - LLRect menuBarRect = gLoginMenuBarView->getRect(); - menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight()); - gLoginMenuBarView->setRect(menuBarRect); - gLoginMenuBarView->setBackgroundColor( color ); - menu_bar_holder->addChild(gLoginMenuBarView); - - // tooltips are on top of EVERYTHING, including menus - gViewerWindow->getRootView()->sendChildToFront(gToolTipView); + // *TODO:Also fix cost in llfolderview.cpp for Inventory menus + const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost()); + const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost()); + gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str); + gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str); + + gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); + gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE); + + gDetachAvatarMenu = gMenuHolder->getChild("Avatar Detach", true); + gDetachHUDAvatarMenu = gMenuHolder->getChild("Avatar Detach HUD", true); + + // Don't display the Memory console menu if the feature is turned off + LLMenuItemCheckGL *memoryMenu = gMenuBarView->getChild("Memory", TRUE); + if (memoryMenu) + { + memoryMenu->setVisible(FALSE); + } + + gMenuBarView->createJumpKeys(); + + // Let land based option enable when parcel changes + gMenuParcelObserver = new LLMenuParcelObserver(); + + gLoginMenuBarView = LLUICtrlFactory::getInstance()->createFromFile("menu_login.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gLoginMenuBarView->arrangeAndClear(); + LLRect menuBarRect = gLoginMenuBarView->getRect(); + menuBarRect.setLeftTopAndSize(0, menu_bar_holder->getRect().getHeight(), menuBarRect.getWidth(), menuBarRect.getHeight()); + gLoginMenuBarView->setRect(menuBarRect); + gLoginMenuBarView->setBackgroundColor( color ); + menu_bar_holder->addChild(gLoginMenuBarView); + + // tooltips are on top of EVERYTHING, including menus + gViewerWindow->getRootView()->sendChildToFront(gToolTipView); } /////////////////// @@ -571,62 +571,62 @@ void init_menus() class LLAdvancedToggleConsole : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string console_type = userdata.asString(); - if ("texture" == console_type) - { - toggle_visibility( (void*)gTextureView ); - } - else if ("debug" == console_type) - { - toggle_visibility( (void*)static_cast(gDebugView->mDebugConsolep)); - } - else if ("fast timers" == console_type) - { - LLFloaterReg::toggleInstance("block_timers"); - } - else if ("scene view" == console_type) - { - toggle_visibility( (void*)gSceneView); - } - else if ("scene monitor" == console_type) - { - toggle_visibility( (void*)gSceneMonitorView); - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string console_type = userdata.asString(); + if ("texture" == console_type) + { + toggle_visibility( (void*)gTextureView ); + } + else if ("debug" == console_type) + { + toggle_visibility( (void*)static_cast(gDebugView->mDebugConsolep)); + } + else if ("fast timers" == console_type) + { + LLFloaterReg::toggleInstance("block_timers"); + } + else if ("scene view" == console_type) + { + toggle_visibility( (void*)gSceneView); + } + else if ("scene monitor" == console_type) + { + toggle_visibility( (void*)gSceneMonitorView); + } + + return true; + } }; class LLAdvancedCheckConsole : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string console_type = userdata.asString(); - bool new_value = false; - if ("texture" == console_type) - { - new_value = get_visibility( (void*)gTextureView ); - } - else if ("debug" == console_type) - { - new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); - } - else if ("fast timers" == console_type) - { - new_value = LLFloaterReg::instanceVisible("block_timers"); - } - else if ("scene view" == console_type) - { - new_value = get_visibility( (void*) gSceneView); - } - else if ("scene monitor" == console_type) - { - new_value = get_visibility( (void*) gSceneMonitorView); - } - - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + std::string console_type = userdata.asString(); + bool new_value = false; + if ("texture" == console_type) + { + new_value = get_visibility( (void*)gTextureView ); + } + else if ("debug" == console_type) + { + new_value = get_visibility( (void*)((LLView*)gDebugView->mDebugConsolep) ); + } + else if ("fast timers" == console_type) + { + new_value = LLFloaterReg::instanceVisible("block_timers"); + } + else if ("scene view" == console_type) + { + new_value = get_visibility( (void*) gSceneView); + } + else if ("scene monitor" == console_type) + { + new_value = get_visibility( (void*) gSceneMonitorView); + } + + return new_value; + } }; @@ -637,24 +637,24 @@ class LLAdvancedCheckConsole : public view_listener_t class LLAdvancedDumpInfoToConsole : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gDebugView->mDebugConsolep->setVisible(TRUE); - std::string info_type = userdata.asString(); - if ("region" == info_type) - { - handle_region_dump_settings(NULL); - } - else if ("group" == info_type) - { - handle_dump_group_info(NULL); - } - else if ("capabilities" == info_type) - { - handle_dump_capabilities_info(NULL); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + gDebugView->mDebugConsolep->setVisible(TRUE); + std::string info_type = userdata.asString(); + if ("region" == info_type) + { + handle_region_dump_settings(NULL); + } + else if ("group" == info_type) + { + handle_dump_group_info(NULL); + } + else if ("capabilities" == info_type) + { + handle_dump_capabilities_info(NULL); + } + return true; + } }; @@ -665,54 +665,54 @@ class LLAdvancedDumpInfoToConsole : public view_listener_t class LLAdvancedToggleHUDInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string info_type = userdata.asString(); - - if ("camera" == info_type) - { - gDisplayCameraPos = !(gDisplayCameraPos); - } - else if ("wind" == info_type) - { - gDisplayWindInfo = !(gDisplayWindInfo); - } - else if ("fov" == info_type) - { - gDisplayFOV = !(gDisplayFOV); - } - else if ("badge" == info_type) - { - gDisplayBadge = !(gDisplayBadge); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string info_type = userdata.asString(); + + if ("camera" == info_type) + { + gDisplayCameraPos = !(gDisplayCameraPos); + } + else if ("wind" == info_type) + { + gDisplayWindInfo = !(gDisplayWindInfo); + } + else if ("fov" == info_type) + { + gDisplayFOV = !(gDisplayFOV); + } + else if ("badge" == info_type) + { + gDisplayBadge = !(gDisplayBadge); + } + return true; + } }; class LLAdvancedCheckHUDInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string info_type = userdata.asString(); - bool new_value = false; - if ("camera" == info_type) - { - new_value = gDisplayCameraPos; - } - else if ("wind" == info_type) - { - new_value = gDisplayWindInfo; - } - else if ("fov" == info_type) - { - new_value = gDisplayFOV; - } - else if ("badge" == info_type) - { - new_value = gDisplayBadge; - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + std::string info_type = userdata.asString(); + bool new_value = false; + if ("camera" == info_type) + { + new_value = gDisplayCameraPos; + } + else if ("wind" == info_type) + { + new_value = gDisplayWindInfo; + } + else if ("fov" == info_type) + { + new_value = gDisplayFOV; + } + else if ("badge" == info_type) + { + new_value = gDisplayBadge; + } + return new_value; + } }; @@ -722,11 +722,11 @@ class LLAdvancedCheckHUDInfo : public view_listener_t class LLAdvancedClearGroupCache : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLGroupMgr::debugClearAllGroups(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLGroupMgr::debugClearAllGroups(NULL); + return true; + } }; @@ -737,18 +737,18 @@ class LLAdvancedClearGroupCache : public view_listener_t ///////////////// U32 render_type_from_string(std::string render_type) { - if ("simple" == render_type) - { - return LLPipeline::RENDER_TYPE_SIMPLE; - } + if ("simple" == render_type) + { + return LLPipeline::RENDER_TYPE_SIMPLE; + } if ("materials" == render_type) { return LLPipeline::RENDER_TYPE_MATERIALS; } - else if ("alpha" == render_type) - { - return LLPipeline::RENDER_TYPE_ALPHA; - } + else if ("alpha" == render_type) + { + return LLPipeline::RENDER_TYPE_ALPHA; + } else if ("alpha_mask" == render_type) { return LLPipeline::RENDER_TYPE_ALPHA_MASK; @@ -765,89 +765,89 @@ U32 render_type_from_string(std::string render_type) { return LLPipeline::RENDER_TYPE_GLOW; } - else if ("tree" == render_type) - { - return LLPipeline::RENDER_TYPE_TREE; - } - else if ("character" == render_type) - { - return LLPipeline::RENDER_TYPE_AVATAR; - } - else if ("controlAV" == render_type) // Animesh - { - return LLPipeline::RENDER_TYPE_CONTROL_AV; - } - else if ("surfacePatch" == render_type) - { - return LLPipeline::RENDER_TYPE_TERRAIN; - } - else if ("sky" == render_type) - { - return LLPipeline::RENDER_TYPE_SKY; - } - else if ("water" == render_type) - { - return LLPipeline::RENDER_TYPE_WATER; - } - else if ("volume" == render_type) - { - return LLPipeline::RENDER_TYPE_VOLUME; - } - else if ("grass" == render_type) - { - return LLPipeline::RENDER_TYPE_GRASS; - } - else if ("clouds" == render_type) - { - return LLPipeline::RENDER_TYPE_CLOUDS; - } - else if ("particles" == render_type) - { - return LLPipeline::RENDER_TYPE_PARTICLES; - } - else if ("bump" == render_type) - { - return LLPipeline::RENDER_TYPE_BUMP; - } - else if ("pbr" == render_type) + else if ("tree" == render_type) + { + return LLPipeline::RENDER_TYPE_TREE; + } + else if ("character" == render_type) + { + return LLPipeline::RENDER_TYPE_AVATAR; + } + else if ("controlAV" == render_type) // Animesh + { + return LLPipeline::RENDER_TYPE_CONTROL_AV; + } + else if ("surfacePatch" == render_type) + { + return LLPipeline::RENDER_TYPE_TERRAIN; + } + else if ("sky" == render_type) + { + return LLPipeline::RENDER_TYPE_SKY; + } + else if ("water" == render_type) + { + return LLPipeline::RENDER_TYPE_WATER; + } + else if ("volume" == render_type) + { + return LLPipeline::RENDER_TYPE_VOLUME; + } + else if ("grass" == render_type) + { + return LLPipeline::RENDER_TYPE_GRASS; + } + else if ("clouds" == render_type) + { + return LLPipeline::RENDER_TYPE_CLOUDS; + } + else if ("particles" == render_type) + { + return LLPipeline::RENDER_TYPE_PARTICLES; + } + else if ("bump" == render_type) + { + return LLPipeline::RENDER_TYPE_BUMP; + } + else if ("pbr" == render_type) { return LLPipeline::RENDER_TYPE_GLTF_PBR; } - else - { - return 0; - } + else + { + return 0; + } } class LLAdvancedToggleRenderType : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - U32 render_type = render_type_from_string( userdata.asString() ); - if ( render_type != 0 ) - { - LLPipeline::toggleRenderTypeControl( render_type ); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + U32 render_type = render_type_from_string( userdata.asString() ); + if ( render_type != 0 ) + { + LLPipeline::toggleRenderTypeControl( render_type ); + } + return true; + } }; class LLAdvancedCheckRenderType : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - U32 render_type = render_type_from_string( userdata.asString() ); - bool new_value = false; + bool handleEvent(const LLSD& userdata) + { + U32 render_type = render_type_from_string( userdata.asString() ); + bool new_value = false; - if ( render_type != 0 ) - { - new_value = LLPipeline::hasRenderTypeControl( render_type ); - } + if ( render_type != 0 ) + { + new_value = LLPipeline::hasRenderTypeControl( render_type ); + } - return new_value; - } + return new_value; + } }; @@ -855,140 +855,140 @@ class LLAdvancedCheckRenderType : public view_listener_t // FEATURE // ///////////// U32 feature_from_string(std::string feature) -{ - if ("ui" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_UI; - } - else if ("selected" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED; - } - else if ("highlighted" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED; - } - else if ("dynamic textures" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES; - } - else if ("foot shadows" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS; - } - else if ("fog" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_FOG; - } - else if ("fr info" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO; - } - else if ("flexible" == feature) - { - return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE; - } - else - { - return 0; - } +{ + if ("ui" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_UI; + } + else if ("selected" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_SELECTED; + } + else if ("highlighted" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_HIGHLIGHTED; + } + else if ("dynamic textures" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES; + } + else if ("foot shadows" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS; + } + else if ("fog" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_FOG; + } + else if ("fr info" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO; + } + else if ("flexible" == feature) + { + return LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE; + } + else + { + return 0; + } }; class LLAdvancedToggleFeature : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - U32 feature = feature_from_string( userdata.asString() ); - if ( feature != 0 ) - { - LLPipeline::toggleRenderDebugFeature( feature ); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + U32 feature = feature_from_string( userdata.asString() ); + if ( feature != 0 ) + { + LLPipeline::toggleRenderDebugFeature( feature ); + } + return true; + } }; class LLAdvancedCheckFeature : public view_listener_t { - bool handleEvent(const LLSD& userdata) + bool handleEvent(const LLSD& userdata) { - U32 feature = feature_from_string( userdata.asString() ); - bool new_value = false; + U32 feature = feature_from_string( userdata.asString() ); + bool new_value = false; - if ( feature != 0 ) - { - new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); - } + if ( feature != 0 ) + { + new_value = LLPipeline::toggleRenderDebugFeatureControl( feature ); + } - return new_value; + return new_value; } }; class LLAdvancedCheckDisplayTextureDensity : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string mode = userdata.asString(); - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) - { - return mode == "none"; - } - if (mode == "current") - { - return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT; - } - else if (mode == "desired") - { - return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED; - } - else if (mode == "full") - { - return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL; - } - return false; - } + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + return mode == "none"; + } + if (mode == "current") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + return LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_FULL; + } + return false; + } }; class LLAdvancedSetDisplayTextureDensity : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string mode = userdata.asString(); - if (mode == "none") - { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE) - { - gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); - } - LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; - } - else if (mode == "current") - { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) - { - gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); - } - LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT; - } - else if (mode == "desired") - { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) - { - gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); - } - gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true); - LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED; - } - else if (mode == "full") - { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) - { - gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); - } - LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL; - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string mode = userdata.asString(); + if (mode == "none") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == TRUE) + { + gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_OFF; + } + else if (mode == "current") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_CURRENT; + } + else if (mode == "desired") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY, true); + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_DESIRED; + } + else if (mode == "full") + { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY) == FALSE) + { + gPipeline.toggleRenderDebug(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY); + } + LLViewerTexture::sDebugTexelsMode = LLViewerTexture::DEBUG_TEXELS_FULL; + } + return true; + } }; @@ -997,236 +997,236 @@ class LLAdvancedSetDisplayTextureDensity : public view_listener_t ////////////////// U64 info_display_from_string(std::string info_display) { - if ("verify" == info_display) - { - return LLPipeline::RENDER_DEBUG_VERIFY; - } - else if ("bboxes" == info_display) - { - return LLPipeline::RENDER_DEBUG_BBOXES; - } - else if ("normals" == info_display) - { - return LLPipeline::RENDER_DEBUG_NORMALS; - } - else if ("points" == info_display) - { - return LLPipeline::RENDER_DEBUG_POINTS; - } - else if ("octree" == info_display) - { - return LLPipeline::RENDER_DEBUG_OCTREE; - } + if ("verify" == info_display) + { + return LLPipeline::RENDER_DEBUG_VERIFY; + } + else if ("bboxes" == info_display) + { + return LLPipeline::RENDER_DEBUG_BBOXES; + } + else if ("normals" == info_display) + { + return LLPipeline::RENDER_DEBUG_NORMALS; + } + else if ("points" == info_display) + { + return LLPipeline::RENDER_DEBUG_POINTS; + } + else if ("octree" == info_display) + { + return LLPipeline::RENDER_DEBUG_OCTREE; + } else if ("nodes" == info_display) { return LLPipeline::RENDER_DEBUG_NODES; } - else if ("shadow frusta" == info_display) - { - return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA; - } - else if ("physics shapes" == info_display) - { - return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES; - } - else if ("occlusion" == info_display) - { - return LLPipeline::RENDER_DEBUG_OCCLUSION; - } - else if ("render batches" == info_display) - { - return LLPipeline::RENDER_DEBUG_BATCH_SIZE; - } - else if ("update type" == info_display) - { - return LLPipeline::RENDER_DEBUG_UPDATE_TYPE; - } - else if ("texture anim" == info_display) - { - return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM; - } - else if ("texture priority" == info_display) - { - return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY; - } - else if ("texture area" == info_display) - { - return LLPipeline::RENDER_DEBUG_TEXTURE_AREA; - } - else if ("face area" == info_display) - { - return LLPipeline::RENDER_DEBUG_FACE_AREA; - } - else if ("lod info" == info_display) - { - return LLPipeline::RENDER_DEBUG_LOD_INFO; - } - else if ("lights" == info_display) - { - return LLPipeline::RENDER_DEBUG_LIGHTS; - } - else if ("particles" == info_display) - { - return LLPipeline::RENDER_DEBUG_PARTICLES; - } - else if ("composition" == info_display) - { - return LLPipeline::RENDER_DEBUG_COMPOSITION; - } - else if ("avatardrawinfo" == info_display) - { - return (LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO); - } - else if ("glow" == info_display) - { - return LLPipeline::RENDER_DEBUG_GLOW; - } - else if ("collision skeleton" == info_display) - { - return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME; - } - else if ("joints" == info_display) - { - return LLPipeline::RENDER_DEBUG_AVATAR_JOINTS; - } - else if ("raycast" == info_display) - { - return LLPipeline::RENDER_DEBUG_RAYCAST; - } - else if ("agent target" == info_display) - { - return LLPipeline::RENDER_DEBUG_AGENT_TARGET; - } - else if ("sculpt" == info_display) - { - return LLPipeline::RENDER_DEBUG_SCULPTED; - } - else if ("wind vectors" == info_display) - { - return LLPipeline::RENDER_DEBUG_WIND_VECTORS; - } - else if ("texel density" == info_display) - { - return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY; - } - else if ("triangle count" == info_display) - { - return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT; - } - else if ("impostors" == info_display) - { - return LLPipeline::RENDER_DEBUG_IMPOSTORS; - } - else if ("reflection probes" == info_display) + else if ("shadow frusta" == info_display) { - return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES; + return LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA; } - else if ("probe updates" == info_display) + else if ("physics shapes" == info_display) { - return LLPipeline::RENDER_DEBUG_PROBE_UPDATES; + return LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES; } - else - { - LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL; - return 0; - } -}; - -class LLAdvancedToggleInfoDisplay : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - U64 info_display = info_display_from_string( userdata.asString() ); - - LL_INFOS("ViewerMenu") << "toggle " << userdata.asString() << LL_ENDL; - - if ( info_display != 0 ) - { - LLPipeline::toggleRenderDebug( info_display ); - } - - return true; - } -}; - - -class LLAdvancedCheckInfoDisplay : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - U64 info_display = info_display_from_string( userdata.asString() ); - bool new_value = false; - - if ( info_display != 0 ) - { - new_value = LLPipeline::toggleRenderDebugControl( info_display ); - } - - return new_value; - } -}; - - -/////////////////////////// -//// RANDOMIZE FRAMERATE // -/////////////////////////// - - -class LLAdvancedToggleRandomizeFramerate : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - gRandomizeFramerate = !(gRandomizeFramerate); - return true; - } -}; - -class LLAdvancedCheckRandomizeFramerate : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - bool new_value = gRandomizeFramerate; - return new_value; - } -}; - -/////////////////////////// -//// PERIODIC SLOW FRAME // -/////////////////////////// - - -class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t + else if ("occlusion" == info_display) + { + return LLPipeline::RENDER_DEBUG_OCCLUSION; + } + else if ("render batches" == info_display) + { + return LLPipeline::RENDER_DEBUG_BATCH_SIZE; + } + else if ("update type" == info_display) + { + return LLPipeline::RENDER_DEBUG_UPDATE_TYPE; + } + else if ("texture anim" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXTURE_ANIM; + } + else if ("texture priority" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY; + } + else if ("texture area" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXTURE_AREA; + } + else if ("face area" == info_display) + { + return LLPipeline::RENDER_DEBUG_FACE_AREA; + } + else if ("lod info" == info_display) + { + return LLPipeline::RENDER_DEBUG_LOD_INFO; + } + else if ("lights" == info_display) + { + return LLPipeline::RENDER_DEBUG_LIGHTS; + } + else if ("particles" == info_display) + { + return LLPipeline::RENDER_DEBUG_PARTICLES; + } + else if ("composition" == info_display) + { + return LLPipeline::RENDER_DEBUG_COMPOSITION; + } + else if ("avatardrawinfo" == info_display) + { + return (LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO); + } + else if ("glow" == info_display) + { + return LLPipeline::RENDER_DEBUG_GLOW; + } + else if ("collision skeleton" == info_display) + { + return LLPipeline::RENDER_DEBUG_AVATAR_VOLUME; + } + else if ("joints" == info_display) + { + return LLPipeline::RENDER_DEBUG_AVATAR_JOINTS; + } + else if ("raycast" == info_display) + { + return LLPipeline::RENDER_DEBUG_RAYCAST; + } + else if ("agent target" == info_display) + { + return LLPipeline::RENDER_DEBUG_AGENT_TARGET; + } + else if ("sculpt" == info_display) + { + return LLPipeline::RENDER_DEBUG_SCULPTED; + } + else if ("wind vectors" == info_display) + { + return LLPipeline::RENDER_DEBUG_WIND_VECTORS; + } + else if ("texel density" == info_display) + { + return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY; + } + else if ("triangle count" == info_display) + { + return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT; + } + else if ("impostors" == info_display) + { + return LLPipeline::RENDER_DEBUG_IMPOSTORS; + } + else if ("reflection probes" == info_display) + { + return LLPipeline::RENDER_DEBUG_REFLECTION_PROBES; + } + else if ("probe updates" == info_display) + { + return LLPipeline::RENDER_DEBUG_PROBE_UPDATES; + } + else + { + LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL; + return 0; + } +}; + +class LLAdvancedToggleInfoDisplay : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + U64 info_display = info_display_from_string( userdata.asString() ); + + LL_INFOS("ViewerMenu") << "toggle " << userdata.asString() << LL_ENDL; + + if ( info_display != 0 ) + { + LLPipeline::toggleRenderDebug( info_display ); + } + + return true; + } +}; + + +class LLAdvancedCheckInfoDisplay : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + U64 info_display = info_display_from_string( userdata.asString() ); + bool new_value = false; + + if ( info_display != 0 ) + { + new_value = LLPipeline::toggleRenderDebugControl( info_display ); + } + + return new_value; + } +}; + + +/////////////////////////// +//// RANDOMIZE FRAMERATE // +/////////////////////////// + + +class LLAdvancedToggleRandomizeFramerate : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + gRandomizeFramerate = !(gRandomizeFramerate); + return true; + } +}; + +class LLAdvancedCheckRandomizeFramerate : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + bool new_value = gRandomizeFramerate; + return new_value; + } +}; + +/////////////////////////// +//// PERIODIC SLOW FRAME // +/////////////////////////// + + +class LLAdvancedTogglePeriodicSlowFrame : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gPeriodicSlowFrame = !(gPeriodicSlowFrame); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gPeriodicSlowFrame = !(gPeriodicSlowFrame); + return true; + } }; class LLAdvancedCheckPeriodicSlowFrame : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gPeriodicSlowFrame; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gPeriodicSlowFrame; + return new_value; + } }; /////////////////////////// // SELECTED TEXTURE INFO // -// +// /////////////////////////// class LLAdvancedSelectedTextureInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_selected_texture_info(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_selected_texture_info(NULL); + return true; + } }; ////////////////////// @@ -1235,33 +1235,33 @@ class LLAdvancedSelectedTextureInfo : public view_listener_t class LLAdvancedToggleWireframe : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gUseWireframe = !(gUseWireframe); + bool handleEvent(const LLSD& userdata) + { + gUseWireframe = !(gUseWireframe); - return true; - } + return true; + } }; class LLAdvancedCheckWireframe : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gUseWireframe; - } + bool handleEvent(const LLSD& userdata) + { + return gUseWireframe; + } }; - + ////////////////////////// // DUMP SCRIPTED CAMERA // ////////////////////////// - + class LLAdvancedDumpScriptedCamera : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_dump_followcam(NULL); - return true; + bool handleEvent(const LLSD& userdata) + { + handle_dump_followcam(NULL); + return true; } }; @@ -1274,11 +1274,11 @@ class LLAdvancedDumpScriptedCamera : public view_listener_t class LLAdvancedDumpRegionObjectCache : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_dump_region_object_cache(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_dump_region_object_cache(NULL); + return true; + } }; class LLAdvancedToggleInterestList360Mode : public view_listener_t @@ -1289,22 +1289,22 @@ public: // Toggle the mode - regions will get updated if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360) { - gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_DEFAULT); - } - else - { - gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360); - } + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_DEFAULT); + } + else + { + gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360); + } return true; } }; class LLAdvancedCheckInterestList360Mode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360); - } + bool handleEvent(const LLSD& userdata) + { + return (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360); + } }; class LLAdvancedToggleStatsRecorder : public view_listener_t @@ -1312,13 +1312,13 @@ class LLAdvancedToggleStatsRecorder : public view_listener_t bool handleEvent(const LLSD &userdata) { if (LLViewerStatsRecorder::instance().isEnabled()) - { // Turn off both recording and logging - LLViewerStatsRecorder::instance().enableObjectStatsRecording(false); - } - else - { // Turn on both recording and logging - LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true); - } + { // Turn off both recording and logging + LLViewerStatsRecorder::instance().enableObjectStatsRecording(false); + } + else + { // Turn on both recording and logging + LLViewerStatsRecorder::instance().enableObjectStatsRecording(true, true); + } return true; } }; @@ -1326,7 +1326,7 @@ class LLAdvancedToggleStatsRecorder : public view_listener_t class LLAdvancedCheckStatsRecorder : public view_listener_t { bool handleEvent(const LLSD &userdata) - { // Use the logging state as the indicator of whether the stats recorder is on + { // Use the logging state as the indicator of whether the stats recorder is on return LLViewerStatsRecorder::instance().isLogging(); } }; @@ -1334,7 +1334,7 @@ class LLAdvancedCheckStatsRecorder : public view_listener_t class LLAdvancedResetInterestLists : public view_listener_t { bool handleEvent(const LLSD &userdata) - { // Reset all region interest lists + { // Reset all region interest lists handle_reset_interest_lists(NULL); return true; } @@ -1342,12 +1342,12 @@ class LLAdvancedResetInterestLists : public view_listener_t class LLAdvancedBuyCurrencyTest : public view_listener_t - { - bool handleEvent(const LLSD& userdata) - { - handle_buy_currency_test(NULL); - return true; - } + { + bool handleEvent(const LLSD& userdata) + { + handle_buy_currency_test(NULL); + return true; + } }; @@ -1358,11 +1358,11 @@ class LLAdvancedBuyCurrencyTest : public view_listener_t class LLAdvancedDumpSelectMgr : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - dump_select_mgr(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + dump_select_mgr(NULL); + return true; + } }; @@ -1374,11 +1374,11 @@ class LLAdvancedDumpSelectMgr : public view_listener_t class LLAdvancedDumpInventory : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - dump_inventory(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + dump_inventory(NULL); + return true; + } }; @@ -1390,11 +1390,11 @@ class LLAdvancedDumpInventory : public view_listener_t class LLAdvancedPrintSelectedObjectInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - print_object_info(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + print_object_info(NULL); + return true; + } }; @@ -1406,11 +1406,11 @@ class LLAdvancedPrintSelectedObjectInfo : public view_listener_t class LLAdvancedPrintAgentInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - print_agent_nvpairs(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + print_agent_nvpairs(NULL); + return true; + } }; ////////////////// @@ -1420,20 +1420,20 @@ class LLAdvancedPrintAgentInfo : public view_listener_t class LLAdvancedToggleDebugClicks : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gDebugClicks = !(gDebugClicks); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gDebugClicks = !(gDebugClicks); + return true; + } }; class LLAdvancedCheckDebugClicks : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gDebugClicks; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gDebugClicks; + return new_value; + } }; @@ -1445,20 +1445,20 @@ class LLAdvancedCheckDebugClicks : public view_listener_t class LLAdvancedToggleDebugViews : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLView::sDebugRects = !(LLView::sDebugRects); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLView::sDebugRects = !(LLView::sDebugRects); + return true; + } }; class LLAdvancedCheckDebugViews : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLView::sDebugRects; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLView::sDebugRects; + return new_value; + } }; @@ -1470,19 +1470,19 @@ class LLAdvancedCheckDebugViews : public view_listener_t class LLAdvancedToggleDebugUnicode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLView::sDebugUnicode = !(LLView::sDebugUnicode); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLView::sDebugUnicode = !(LLView::sDebugUnicode); + return true; + } }; class LLAdvancedCheckDebugUnicode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return LLView::sDebugUnicode; - } + bool handleEvent(const LLSD& userdata) + { + return LLView::sDebugUnicode; + } }; @@ -1494,20 +1494,20 @@ class LLAdvancedCheckDebugUnicode : public view_listener_t class LLAdvancedToggleDebugCamera : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLView::sDebugCamera = !(LLView::sDebugCamera); - LLFloaterCamera::onDebugCameraToggled(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLView::sDebugCamera = !(LLView::sDebugCamera); + LLFloaterCamera::onDebugCameraToggled(); + return true; + } }; class LLAdvancedCheckDebugCamera : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return LLView::sDebugCamera; - } + bool handleEvent(const LLSD& userdata) + { + return LLView::sDebugCamera; + } }; @@ -1519,20 +1519,20 @@ class LLAdvancedCheckDebugCamera : public view_listener_t class LLAdvancedToggleXUINameTooltips : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - toggle_show_xui_names(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + toggle_show_xui_names(NULL); + return true; + } }; class LLAdvancedCheckXUINameTooltips : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = check_show_xui_names(NULL); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = check_show_xui_names(NULL); + return new_value; + } }; @@ -1544,20 +1544,20 @@ class LLAdvancedCheckXUINameTooltips : public view_listener_t class LLAdvancedToggleDebugMouseEvents : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLView::sDebugMouseHandling = !(LLView::sDebugMouseHandling); + return true; + } }; class LLAdvancedCheckDebugMouseEvents : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLView::sDebugMouseHandling; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLView::sDebugMouseHandling; + return new_value; + } }; @@ -1569,22 +1569,22 @@ class LLAdvancedCheckDebugMouseEvents : public view_listener_t class LLAdvancedToggleDebugKeys : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLView::sDebugKeys = !(LLView::sDebugKeys); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLView::sDebugKeys = !(LLView::sDebugKeys); + return true; + } }; - + class LLAdvancedCheckDebugKeys : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLView::sDebugKeys; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLView::sDebugKeys; + return new_value; + } }; - + /////////////////////// @@ -1594,30 +1594,30 @@ class LLAdvancedCheckDebugKeys : public view_listener_t class LLAdvancedToggleDebugWindowProc : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gDebugWindowProc = !(gDebugWindowProc); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gDebugWindowProc = !(gDebugWindowProc); + return true; + } }; class LLAdvancedCheckDebugWindowProc : public view_listener_t - { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gDebugWindowProc; - return new_value; - } + { + bool handleEvent(const LLSD& userdata) + { + bool new_value = gDebugWindowProc; + return new_value; + } }; // ------------------------------XUI MENU --------------------------- class LLAdvancedSendTestIms : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLIMModel::instance().testMessages(); - return true; + bool handleEvent(const LLSD& userdata) + { + LLIMModel::instance().testMessages(); + return true; } }; @@ -1629,20 +1629,20 @@ class LLAdvancedSendTestIms : public view_listener_t class LLAdvancedToggleXUINames : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - toggle_show_xui_names(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + toggle_show_xui_names(NULL); + return true; + } }; class LLAdvancedCheckXUINames : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = check_show_xui_names(NULL); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = check_show_xui_names(NULL); + return new_value; + } }; @@ -1653,73 +1653,73 @@ class LLAdvancedCheckXUINames : public view_listener_t class LLAdvancedGrabBakedTexture : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string texture_type = userdata.asString(); - if ("iris" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_EYES ); - } - else if ("head" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_HEAD ); - } - else if ("upper" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_UPPER ); - } - else if ("lower" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_LOWER ); - } - else if ("skirt" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_SKIRT ); - } - else if ("hair" == texture_type) - { - handle_grab_baked_texture( (void*)BAKED_HAIR ); - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string texture_type = userdata.asString(); + if ("iris" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_EYES ); + } + else if ("head" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_HEAD ); + } + else if ("upper" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_UPPER ); + } + else if ("lower" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_LOWER ); + } + else if ("skirt" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_SKIRT ); + } + else if ("hair" == texture_type) + { + handle_grab_baked_texture( (void*)BAKED_HAIR ); + } + + return true; + } }; class LLAdvancedEnableGrabBakedTexture : public view_listener_t { - bool handleEvent(const LLSD& userdata) -{ - std::string texture_type = userdata.asString(); - bool new_value = false; - - if ("iris" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_EYES ); - } - else if ("head" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_HEAD ); - } - else if ("upper" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_UPPER ); - } - else if ("lower" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_LOWER ); - } - else if ("skirt" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT ); - } - else if ("hair" == texture_type) - { - new_value = enable_grab_baked_texture( (void*)BAKED_HAIR ); - } - - return new_value; -} -}; + bool handleEvent(const LLSD& userdata) +{ + std::string texture_type = userdata.asString(); + bool new_value = false; + + if ("iris" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_EYES ); + } + else if ("head" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_HEAD ); + } + else if ("upper" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_UPPER ); + } + else if ("lower" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_LOWER ); + } + else if ("skirt" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_SKIRT ); + } + else if ("hair" == texture_type) + { + new_value = enable_grab_baked_texture( (void*)BAKED_HAIR ); + } + + return new_value; +} +}; /////////////////////// // APPEARANCE TO XML // @@ -1728,8 +1728,8 @@ class LLAdvancedEnableGrabBakedTexture : public view_listener_t class LLAdvancedEnableAppearanceToXML : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (obj && obj->isAnimatedObject() && obj->getControlAvatar()) { @@ -1744,18 +1744,18 @@ class LLAdvancedEnableAppearanceToXML : public view_listener_t // This has to be a non-control avatar, because control avs are invisible and unclickable. return gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); } - else - { - return false; - } - } + else + { + return false; + } + } }; class LLAdvancedAppearanceToXML : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string emptyname; + bool handleEvent(const LLSD& userdata) + { + std::string emptyname; LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); LLVOAvatar *avatar = NULL; if (obj) @@ -1778,14 +1778,14 @@ class LLAdvancedAppearanceToXML : public view_listener_t else { // If no selection, use the self avatar. - avatar = gAgentAvatarp; + avatar = gAgentAvatarp; } if (avatar) { avatar->dumpArchetypeXML(emptyname); } - return true; - } + return true; + } }; @@ -1797,44 +1797,44 @@ class LLAdvancedAppearanceToXML : public view_listener_t class LLAdvancedToggleCharacterGeometry : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_god_request_avatar_geometry(NULL); - return true; + bool handleEvent(const LLSD& userdata) + { + handle_god_request_avatar_geometry(NULL); + return true; } }; - ///////////////////////////// + ///////////////////////////// // TEST MALE / TEST FEMALE // ///////////////////////////// class LLAdvancedTestMale : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_test_male(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_test_male(NULL); + return true; + } }; class LLAdvancedTestFemale : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_test_female(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_test_female(NULL); + return true; + } }; class LLAdvancedForceParamsToDefault : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLAgent::clearVisualParams(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLAgent::clearVisualParams(NULL); + return true; + } }; @@ -1843,47 +1843,47 @@ class LLAdvancedForceParamsToDefault : public view_listener_t ////////////////////////// // Utility function to set all AV time factors to the same global value -static void set_all_animation_time_factors(F32 time_factor) +static void set_all_animation_time_factors(F32 time_factor) { - LLMotionController::setCurrentTimeFactor(time_factor); - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - (*iter)->setAnimTimeFactor(time_factor); - } + LLMotionController::setCurrentTimeFactor(time_factor); + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + (*iter)->setAnimTimeFactor(time_factor); + } } class LLAdvancedAnimTenFaster : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - //LL_INFOS() << "LLAdvancedAnimTenFaster" << LL_ENDL; - F32 time_factor = LLMotionController::getCurrentTimeFactor(); - time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed - set_all_animation_time_factors(time_factor); - return true; - } + bool handleEvent(const LLSD& userdata) + { + //LL_INFOS() << "LLAdvancedAnimTenFaster" << LL_ENDL; + F32 time_factor = LLMotionController::getCurrentTimeFactor(); + time_factor = llmin(time_factor + 0.1f, 2.f); // Upper limit is 200% speed + set_all_animation_time_factors(time_factor); + return true; + } }; class LLAdvancedAnimTenSlower : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - //LL_INFOS() << "LLAdvancedAnimTenSlower" << LL_ENDL; - F32 time_factor = LLMotionController::getCurrentTimeFactor(); - time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed - set_all_animation_time_factors(time_factor); - return true; - } + bool handleEvent(const LLSD& userdata) + { + //LL_INFOS() << "LLAdvancedAnimTenSlower" << LL_ENDL; + F32 time_factor = LLMotionController::getCurrentTimeFactor(); + time_factor = llmax(time_factor - 0.1f, 0.1f); // Lower limit is at 10% of normal speed + set_all_animation_time_factors(time_factor); + return true; + } }; class LLAdvancedAnimResetAll : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - set_all_animation_time_factors(1.f); - return true; - } + bool handleEvent(const LLSD& userdata) + { + set_all_animation_time_factors(1.f); + return true; + } }; @@ -1894,11 +1894,11 @@ class LLAdvancedAnimResetAll : public view_listener_t class LLAdvancedReloadVertexShader : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - reload_vertex_shader(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + reload_vertex_shader(NULL); + return true; + } }; @@ -1910,20 +1910,20 @@ class LLAdvancedReloadVertexShader : public view_listener_t class LLAdvancedToggleAnimationInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar::sShowAnimationDebug = !(LLVOAvatar::sShowAnimationDebug); + return true; + } }; class LLAdvancedCheckAnimationInfo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLVOAvatar::sShowAnimationDebug; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLVOAvatar::sShowAnimationDebug; + return new_value; + } }; @@ -1934,20 +1934,20 @@ class LLAdvancedCheckAnimationInfo : public view_listener_t class LLAdvancedToggleShowLookAt : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLHUDEffectLookAt::sDebugLookAt = !(LLHUDEffectLookAt::sDebugLookAt); + return true; + } }; class LLAdvancedCheckShowLookAt : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLHUDEffectLookAt::sDebugLookAt; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLHUDEffectLookAt::sDebugLookAt; + return new_value; + } }; @@ -1959,20 +1959,20 @@ class LLAdvancedCheckShowLookAt : public view_listener_t class LLAdvancedToggleShowPointAt : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLHUDEffectPointAt::sDebugPointAt = !(LLHUDEffectPointAt::sDebugPointAt); + return true; + } }; class LLAdvancedCheckShowPointAt : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLHUDEffectPointAt::sDebugPointAt; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLHUDEffectPointAt::sDebugPointAt; + return new_value; + } }; @@ -1984,20 +1984,20 @@ class LLAdvancedCheckShowPointAt : public view_listener_t class LLAdvancedToggleDebugJointUpdates : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar::sJointDebug = !(LLVOAvatar::sJointDebug); + return true; + } }; class LLAdvancedCheckDebugJointUpdates : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLVOAvatar::sJointDebug; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLVOAvatar::sJointDebug; + return new_value; + } }; @@ -2009,20 +2009,20 @@ class LLAdvancedCheckDebugJointUpdates : public view_listener_t class LLAdvancedToggleDisableLOD : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLViewerJoint::sDisableLOD = !(LLViewerJoint::sDisableLOD); + return true; + } }; - + class LLAdvancedCheckDisableLOD : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLViewerJoint::sDisableLOD; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLViewerJoint::sDisableLOD; + return new_value; + } }; @@ -2034,20 +2034,20 @@ class LLAdvancedCheckDisableLOD : public view_listener_t class LLAdvancedToggleDebugCharacterVis : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar::sDebugInvisible = !(LLVOAvatar::sDebugInvisible); + return true; + } }; class LLAdvancedCheckDebugCharacterVis : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLVOAvatar::sDebugInvisible; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLVOAvatar::sDebugInvisible; + return new_value; + } }; @@ -2055,33 +2055,33 @@ class LLAdvancedCheckDebugCharacterVis : public view_listener_t // DUMP ATTACHMENTS // ////////////////////// - + class LLAdvancedDumpAttachments : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_dump_attachments(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_dump_attachments(NULL); + return true; + } }; - + ///////////////////// // REBAKE TEXTURES // ///////////////////// - - + + class LLAdvancedRebakeTextures : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_rebake_textures(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_rebake_textures(NULL); + return true; + } }; - - + + #if 1 //ndef LL_RELEASE_FOR_DOWNLOAD /////////////////////////// // DEBUG AVATAR TEXTURES // @@ -2090,14 +2090,14 @@ class LLAdvancedRebakeTextures : public view_listener_t class LLAdvancedDebugAvatarTextures : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgent.isGodlike()) - { - handle_debug_avatar_textures(NULL); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgent.isGodlike()) + { + handle_debug_avatar_textures(NULL); + } + return true; + } }; //////////////////////////////// @@ -2107,17 +2107,17 @@ class LLAdvancedDebugAvatarTextures : public view_listener_t class LLAdvancedDumpAvatarLocalTextures : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { #ifndef LL_RELEASE_FOR_DOWNLOAD - handle_dump_avatar_local_textures(NULL); + handle_dump_avatar_local_textures(NULL); #endif - return true; - } + return true; + } }; #endif - + ///////////////// // MESSAGE LOG // ///////////////// @@ -2125,20 +2125,20 @@ class LLAdvancedDumpAvatarLocalTextures : public view_listener_t class LLAdvancedEnableMessageLog : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_viewer_enable_message_log(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_viewer_enable_message_log(NULL); + return true; + } }; class LLAdvancedDisableMessageLog : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_viewer_disable_message_log(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_viewer_disable_message_log(NULL); + return true; + } }; ///////////////// @@ -2148,11 +2148,11 @@ class LLAdvancedDisableMessageLog : public view_listener_t class LLAdvancedDropPacket : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gMessageSystem->mPacketRing.dropPackets(1); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gMessageSystem->mPacketRing.dropPackets(1); + return true; + } }; ////////////////////// @@ -2162,8 +2162,8 @@ class LLAdvancedDropPacket : public view_listener_t class LLAdvancedPurgeDiskCache : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); LL::WorkQueue::ptr_t general_queue = LL::WorkQueue::getInstance("General"); llassert_always(main_queue); @@ -2177,8 +2177,8 @@ class LLAdvancedPurgeDiskCache : public view_listener_t }, [](){}); // Callback to main thread is empty as there is nothing left to do - return true; - } + return true; + } }; @@ -2189,12 +2189,12 @@ class LLAdvancedPurgeDiskCache : public view_listener_t class LLAdvancedPurgeShaderCache : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerShaderMgr::instance()->clearShaderCache(); - LLViewerShaderMgr::instance()->setShaders(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLViewerShaderMgr::instance()->clearShaderCache(); + LLViewerShaderMgr::instance()->setShaders(); + return true; + } }; ///////////////////// @@ -2204,11 +2204,11 @@ class LLAdvancedPurgeShaderCache : public view_listener_t class LLAdvancedRebuildTerrain : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { gPipeline.rebuildTerrain(); - return true; - } + return true; + } }; //////////////////// @@ -2218,32 +2218,32 @@ class LLAdvancedRebuildTerrain : public view_listener_t class LLAdvancedViewerEventRecorder : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string command = userdata.asString(); - if ("start playback" == command) - { - LL_INFOS() << "Event Playback starting" << LL_ENDL; - LLViewerEventRecorder::instance().playbackRecording(); - LL_INFOS() << "Event Playback completed" << LL_ENDL; - } - else if ("stop playback" == command) - { - // Future - } - else if ("start recording" == command) - { - LLViewerEventRecorder::instance().setEventLoggingOn(); - LL_INFOS() << "Event recording started" << LL_ENDL; - } - else if ("stop recording" == command) - { - LLViewerEventRecorder::instance().setEventLoggingOff(); - LL_INFOS() << "Event recording stopped" << LL_ENDL; - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string command = userdata.asString(); + if ("start playback" == command) + { + LL_INFOS() << "Event Playback starting" << LL_ENDL; + LLViewerEventRecorder::instance().playbackRecording(); + LL_INFOS() << "Event Playback completed" << LL_ENDL; + } + else if ("stop playback" == command) + { + // Future + } + else if ("start recording" == command) + { + LLViewerEventRecorder::instance().setEventLoggingOn(); + LL_INFOS() << "Event recording started" << LL_ENDL; + } + else if ("stop recording" == command) + { + LLViewerEventRecorder::instance().setEventLoggingOff(); + LL_INFOS() << "Event recording stopped" << LL_ENDL; + } + + return true; + } }; @@ -2256,29 +2256,29 @@ class LLAdvancedViewerEventRecorder : public view_listener_t class LLAdvancedAgentPilot : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string command = userdata.asString(); - if ("start playback" == command) - { - gAgentPilot.setNumRuns(-1); - gAgentPilot.startPlayback(); - } - else if ("stop playback" == command) - { - gAgentPilot.stopPlayback(); - } - else if ("start record" == command) - { - gAgentPilot.startRecord(); - } - else if ("stop record" == command) - { - gAgentPilot.stopRecord(); - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string command = userdata.asString(); + if ("start playback" == command) + { + gAgentPilot.setNumRuns(-1); + gAgentPilot.startPlayback(); + } + else if ("stop playback" == command) + { + gAgentPilot.stopPlayback(); + } + else if ("start record" == command) + { + gAgentPilot.startRecord(); + } + else if ("stop record" == command) + { + gAgentPilot.stopRecord(); + } + + return true; + } }; @@ -2290,20 +2290,20 @@ class LLAdvancedAgentPilot : public view_listener_t class LLAdvancedToggleAgentPilotLoop : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgentPilot.setLoop(!gAgentPilot.getLoop()); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gAgentPilot.setLoop(!gAgentPilot.getLoop()); + return true; + } }; class LLAdvancedCheckAgentPilotLoop : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gAgentPilot.getLoop(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gAgentPilot.getLoop(); + return new_value; + } }; @@ -2314,20 +2314,20 @@ class LLAdvancedCheckAgentPilotLoop : public view_listener_t class LLAdvancedToggleShowObjectUpdates : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gShowObjectUpdates = !(gShowObjectUpdates); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gShowObjectUpdates = !(gShowObjectUpdates); + return true; + } }; class LLAdvancedCheckShowObjectUpdates : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gShowObjectUpdates; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gShowObjectUpdates; + return new_value; + } }; @@ -2339,11 +2339,11 @@ class LLAdvancedCheckShowObjectUpdates : public view_listener_t class LLAdvancedCompressImage : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_compress_image(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_compress_image(NULL); + return true; + } }; @@ -2369,11 +2369,11 @@ class LLAdvancedCompressFileTest : public view_listener_t class LLAdvancedShowDebugSettings : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterReg::showInstance("settings_debug",userdata); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloaterReg::showInstance("settings_debug",userdata); + return true; + } }; @@ -2384,40 +2384,40 @@ class LLAdvancedShowDebugSettings : public view_listener_t class LLAdvancedEnableViewAdminOptions : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // Don't enable in god mode since the admin menu is shown anyway. - // Only enable if the user has set the appropriate debug setting. - bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu"); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + // Don't enable in god mode since the admin menu is shown anyway. + // Only enable if the user has set the appropriate debug setting. + bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu"); + return new_value; + } }; class LLAdvancedToggleViewAdminOptions : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_admin_override_toggle(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_admin_override_toggle(NULL); + return true; + } }; class LLAdvancedToggleVisualLeakDetector : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_visual_leak_detector_toggle(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_visual_leak_detector_toggle(NULL); + return true; + } }; class LLAdvancedCheckViewAdminOptions : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = check_admin_override(NULL) || gAgent.isGodlike(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = check_admin_override(NULL) || gAgent.isGodlike(); + return new_value; + } }; ////////////////// @@ -2427,20 +2427,20 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t class LLAdvancedRequestAdminStatus : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_god_mode(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_god_mode(NULL); + return true; + } }; class LLAdvancedLeaveAdminStatus : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_leave_god_mode(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_leave_god_mode(NULL); + return true; + } }; ////////////////////////// @@ -2449,20 +2449,20 @@ class LLAdvancedLeaveAdminStatus : public view_listener_t class LLAdvancedForceErrorBreakpoint : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_breakpoint(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_breakpoint(NULL); + return true; + } }; class LLAdvancedForceErrorLlerror : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_llerror(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_llerror(NULL); + return true; + } }; class LLAdvancedForceErrorLlerrorMsg: public view_listener_t @@ -2476,11 +2476,11 @@ class LLAdvancedForceErrorLlerrorMsg: public view_listener_t class LLAdvancedForceErrorBadMemoryAccess : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_bad_memory_access(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_bad_memory_access(NULL); + return true; + } }; class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t @@ -2501,20 +2501,20 @@ class LLAdvancedForceErrorBadMemoryAccessCoro : public view_listener_t class LLAdvancedForceErrorInfiniteLoop : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_infinite_loop(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_infinite_loop(NULL); + return true; + } }; class LLAdvancedForceErrorSoftwareException : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_software_exception(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_software_exception(NULL); + return true; + } }; class LLAdvancedForceOSException: public view_listener_t @@ -2544,11 +2544,11 @@ class LLAdvancedForceErrorSoftwareExceptionCoro : public view_listener_t class LLAdvancedForceErrorDriverCrash : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_error_driver_crash(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_error_driver_crash(NULL); + return true; + } }; class LLAdvancedForceErrorCoroutineCrash : public view_listener_t @@ -2571,10 +2571,10 @@ class LLAdvancedForceErrorThreadCrash : public view_listener_t class LLAdvancedForceErrorDisconnectViewer : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_disconnect_viewer(NULL); - return true; + bool handleEvent(const LLSD& userdata) + { + handle_disconnect_viewer(NULL); + return true; } }; @@ -2583,29 +2583,29 @@ class LLAdvancedForceErrorDisconnectViewer : public view_listener_t class LLAdvancedHandleToggleHackedGodmode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_toggle_hacked_godmode(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_toggle_hacked_godmode(NULL); + return true; + } }; class LLAdvancedCheckToggleHackedGodmode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - check_toggle_hacked_godmode(NULL); - return true; - } -}; + bool handleEvent(const LLSD& userdata) + { + check_toggle_hacked_godmode(NULL); + return true; + } +}; class LLAdvancedEnableToggleHackedGodmode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = enable_toggle_hacked_godmode(NULL); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = enable_toggle_hacked_godmode(NULL); + return new_value; + } }; #endif @@ -2622,21 +2622,21 @@ class LLAdvancedEnableToggleHackedGodmode : public view_listener_t class LLDevelopCheckLoggingLevel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - U32 level = userdata.asInteger(); - return (static_cast(level) == LLError::getDefaultLevel()); - } + bool handleEvent(const LLSD& userdata) + { + U32 level = userdata.asInteger(); + return (static_cast(level) == LLError::getDefaultLevel()); + } }; class LLDevelopSetLoggingLevel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - U32 level = userdata.asInteger(); - LLError::setDefaultLevel(static_cast(level)); - return true; - } + bool handleEvent(const LLSD& userdata) + { + U32 level = userdata.asInteger(); + LLError::setDefaultLevel(static_cast(level)); + return true; + } }; ////////////////// @@ -2646,100 +2646,100 @@ class LLDevelopSetLoggingLevel : public view_listener_t // Admin > Object class LLAdminForceTakeCopy : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - force_take_copy(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + force_take_copy(NULL); + return true; + } }; class LLAdminHandleObjectOwnerSelf : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_object_owner_self(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_object_owner_self(NULL); + return true; + } }; class LLAdminHandleObjectOwnerPermissive : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_object_owner_permissive(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_object_owner_permissive(NULL); + return true; + } }; class LLAdminHandleForceDelete : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_force_delete(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_force_delete(NULL); + return true; + } }; class LLAdminHandleObjectLock : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_object_lock(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_object_lock(NULL); + return true; + } }; class LLAdminHandleObjectAssetIDs: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_object_asset_ids(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_object_asset_ids(NULL); + return true; + } }; //Admin >Parcel class LLAdminHandleForceParcelOwnerToMe: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_force_parcel_owner_to_me(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_force_parcel_owner_to_me(NULL); + return true; + } }; class LLAdminHandleForceParcelToContent: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_force_parcel_to_content(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_force_parcel_to_content(NULL); + return true; + } }; class LLAdminHandleClaimPublicLand: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_claim_public_land(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_claim_public_land(NULL); + return true; + } }; // Admin > Region class LLAdminHandleRegionDumpTempAssetData: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_region_dump_temp_asset_data(NULL); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_region_dump_temp_asset_data(NULL); + return true; + } }; //Admin (Top Level) class LLAdminOnSaveState: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLPanelRegionTools::onSaveState(NULL); - return true; + bool handleEvent(const LLSD& userdata) + { + LLPanelRegionTools::onSaveState(NULL); + return true; } }; @@ -2749,38 +2749,38 @@ class LLAdminOnSaveState: public view_listener_t //----------------------------------------------------------------------------- void cleanup_menus() { - delete gMenuParcelObserver; - gMenuParcelObserver = NULL; + delete gMenuParcelObserver; + gMenuParcelObserver = NULL; - delete gMenuAvatarSelf; - gMenuAvatarSelf = NULL; + delete gMenuAvatarSelf; + gMenuAvatarSelf = NULL; - delete gMenuAvatarOther; - gMenuAvatarOther = NULL; + delete gMenuAvatarOther; + gMenuAvatarOther = NULL; - delete gMenuObject; - gMenuObject = NULL; + delete gMenuObject; + gMenuObject = NULL; - delete gMenuAttachmentSelf; - gMenuAttachmentSelf = NULL; + delete gMenuAttachmentSelf; + gMenuAttachmentSelf = NULL; - delete gMenuAttachmentOther; - gMenuAttachmentSelf = NULL; + delete gMenuAttachmentOther; + gMenuAttachmentSelf = NULL; - delete gMenuLand; - gMenuLand = NULL; + delete gMenuLand; + gMenuLand = NULL; - delete gMenuMuteParticle; - gMenuMuteParticle = NULL; + delete gMenuMuteParticle; + gMenuMuteParticle = NULL; - delete gMenuBarView; - gMenuBarView = NULL; + delete gMenuBarView; + gMenuBarView = NULL; - delete gPopupMenuView; - gPopupMenuView = NULL; + delete gPopupMenuView; + gPopupMenuView = NULL; - delete gMenuHolder; - gMenuHolder = NULL; + delete gMenuHolder; + gMenuHolder = NULL; } //----------------------------------------------------------------------------- @@ -2789,40 +2789,40 @@ void cleanup_menus() class LLObjectReportAbuse : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (objectp) - { - LLFloaterReporter::showFromObject(objectp->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (objectp) + { + LLFloaterReporter::showFromObject(objectp->getID()); + } + return true; + } }; // Enabled it you clicked an object class LLObjectEnableReportAbuse : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 0; + return new_value; + } }; void handle_object_touch() { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return; + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return; - LLPickInfo pick = LLToolPie::getInstance()->getPick(); + LLPickInfo pick = LLToolPie::getInstance()->getPick(); - // *NOTE: Hope the packets arrive safely and in order or else - // there will be some problems. - // *TODO: Just fix this bad assumption. - send_ObjectGrab_message(object, pick, LLVector3::zero); - send_ObjectDeGrab_message(object, pick); + // *NOTE: Hope the packets arrive safely and in order or else + // there will be some problems. + // *TODO: Just fix this bad assumption. + send_ObjectGrab_message(object, pick, LLVector3::zero); + send_ObjectDeGrab_message(object, pick); } void handle_object_show_original() @@ -2855,75 +2855,75 @@ void handle_object_show_original() static void init_default_item_label(LLUICtrl* ctrl) { - const std::string& item_name = ctrl->getName(); - boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); - if (it == sDefaultItemLabels.end()) - { - // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value - // (doesn't seem to matter much ATM). - LLStringExplicit default_label = ctrl->getValue().asString(); - if (!default_label.empty()) - { - sDefaultItemLabels.insert(std::pair(item_name, default_label)); - } - } + const std::string& item_name = ctrl->getName(); + boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); + if (it == sDefaultItemLabels.end()) + { + // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value + // (doesn't seem to matter much ATM). + LLStringExplicit default_label = ctrl->getValue().asString(); + if (!default_label.empty()) + { + sDefaultItemLabels.insert(std::pair(item_name, default_label)); + } + } } static LLStringExplicit get_default_item_label(const std::string& item_name) { - LLStringExplicit res(""); - boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); - if (it != sDefaultItemLabels.end()) - { - res = it->second; - } + LLStringExplicit res(""); + boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); + if (it != sDefaultItemLabels.end()) + { + res = it->second; + } - return res; + return res; } bool enable_object_touch(LLUICtrl* ctrl) { - bool new_value = false; - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (obj) - { - LLViewerObject* parent = (LLViewerObject*)obj->getParent(); - new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch()); - } + bool new_value = false; + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (obj) + { + LLViewerObject* parent = (LLViewerObject*)obj->getParent(); + new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch()); + } - init_default_item_label(ctrl); + init_default_item_label(ctrl); - // Update label based on the node touch name if available. - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (node && node->mValid && !node->mTouchName.empty()) - { - ctrl->setValue(node->mTouchName); - } - else - { - ctrl->setValue(get_default_item_label(ctrl->getName())); - } + // Update label based on the node touch name if available. + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node && node->mValid && !node->mTouchName.empty()) + { + ctrl->setValue(node->mTouchName); + } + else + { + ctrl->setValue(get_default_item_label(ctrl->getName())); + } - return new_value; + return new_value; }; //void label_touch(std::string& label, void*) //{ -// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); -// if (node && node->mValid && !node->mTouchName.empty()) -// { -// label.assign(node->mTouchName); -// } -// else -// { -// label.assign("Touch"); -// } +// LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); +// if (node && node->mValid && !node->mTouchName.empty()) +// { +// label.assign(node->mTouchName); +// } +// else +// { +// label.assign("Touch"); +// } //} void handle_object_open() { - LLFloaterReg::showInstance("openobject"); + LLFloaterReg::showInstance("openobject"); } bool enable_object_inspect() @@ -2978,67 +2978,67 @@ bool enable_object_edit_gltf_material() bool enable_object_open() { - // Look for contents in root object, which is all the LLFloaterOpenObject - // understands. - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!obj) return false; + // Look for contents in root object, which is all the LLFloaterOpenObject + // understands. + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!obj) return false; - LLViewerObject* root = obj->getRootEdit(); - if (!root) return false; + LLViewerObject* root = obj->getRootEdit(); + if (!root) return false; - return root->allowOpen(); + return root->allowOpen(); } class LLViewJoystickFlycam : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_toggle_flycam(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_toggle_flycam(); + return true; + } }; class LLViewCheckJoystickFlycam : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLViewerJoystick::getInstance()->getOverrideCamera(); + return new_value; + } }; void handle_toggle_flycam() { - LLViewerJoystick::getInstance()->toggleFlycam(); + LLViewerJoystick::getInstance()->toggleFlycam(); } class LLObjectBuild : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) - { - // zoom in if we're looking at the avatar - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gAgentCamera.cameraZoomIn(0.666f); - gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); - gViewerWindow->moveCursorToCenter(); - } - else if ( gSavedSettings.getBOOL("EditCameraMovement") ) - { - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gViewerWindow->moveCursorToCenter(); - } - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); - - // Could be first use - //LLFirstUse::useBuild(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) + { + // zoom in if we're looking at the avatar + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + gAgentCamera.cameraZoomIn(0.666f); + gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); + gViewerWindow->moveCursorToCenter(); + } + else if ( gSavedSettings.getBOOL("EditCameraMovement") ) + { + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + gViewerWindow->moveCursorToCenter(); + } + + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); + + // Could be first use + //LLFirstUse::useBuild(); + return true; + } }; void update_camera() @@ -3077,17 +3077,17 @@ void handle_object_edit() { update_camera(); - LLFloaterReg::showInstance("build"); - - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); - - LLViewerJoystick::getInstance()->moveObjects(true); - LLViewerJoystick::getInstance()->setNeedsReset(true); - - // Could be first use - //LLFirstUse::useBuild(); - return; + LLFloaterReg::showInstance("build"); + + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); + + LLViewerJoystick::getInstance()->moveObjects(true); + LLViewerJoystick::getInstance()->setNeedsReset(true); + + // Could be first use + //LLFirstUse::useBuild(); + return; } void handle_object_edit_gltf_material() @@ -3109,68 +3109,68 @@ void handle_object_edit_gltf_material() void handle_attachment_edit(const LLUUID& inv_item_id) { - if (isAgentAvatarValid()) - { - if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id)) - { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj); + if (isAgentAvatarValid()) + { + if (LLViewerObject* attached_obj = gAgentAvatarp->getWornAttachment(inv_item_id)) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(attached_obj); - handle_object_edit(); - } - } + handle_object_edit(); + } + } } void handle_attachment_touch(const LLUUID& inv_item_id) { - if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) ) - { - if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id))) - { - LLSelectMgr::getInstance()->deselectAll(); - - LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj); - if (!LLToolMgr::getInstance()->inBuildMode()) - { - struct SetTransient : public LLSelectedNodeFunctor - { - bool apply(LLSelectNode* node) - { - node->setTransient(TRUE); - return true; - } - } f; - sel->applyToNodes(&f); - } - - handle_object_touch(); - } - } + if ( (isAgentAvatarValid()) && (enable_attachment_touch(inv_item_id)) ) + { + if (LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id))) + { + LLSelectMgr::getInstance()->deselectAll(); + + LLObjectSelectionHandle sel = LLSelectMgr::getInstance()->selectObjectAndFamily(attach_obj); + if (!LLToolMgr::getInstance()->inBuildMode()) + { + struct SetTransient : public LLSelectedNodeFunctor + { + bool apply(LLSelectNode* node) + { + node->setTransient(TRUE); + return true; + } + } f; + sel->applyToNodes(&f); + } + + handle_object_touch(); + } + } } bool enable_attachment_touch(const LLUUID& inv_item_id) { - if (isAgentAvatarValid()) - { - const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)); - return (attach_obj) && (attach_obj->flagHandleTouch()); - } - return false; + if (isAgentAvatarValid()) + { + const LLViewerObject* attach_obj = gAgentAvatarp->getWornAttachment(gInventory.getLinkedItemID(inv_item_id)); + return (attach_obj) && (attach_obj->flagHandleTouch()); + } + return false; } void handle_object_inspect() { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - LLViewerObject* selected_objectp = selection->getFirstRootObject(); - if (selected_objectp) - { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* selected_objectp = selection->getFirstRootObject(); + if (selected_objectp) + { LLFloaterReg::showInstance("task_properties"); - } - - /* - // Old floater properties - LLFloaterReg::showInstance("inspect", LLSD()); - */ + } + + /* + // Old floater properties + LLFloaterReg::showInstance("inspect", LLSD()); + */ } //--------------------------------------------------------------------------- @@ -3178,133 +3178,133 @@ void handle_object_inspect() //--------------------------------------------------------------------------- class LLLandBuild : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerParcelMgr::getInstance()->deselectLand(); + bool handleEvent(const LLSD& userdata) + { + LLViewerParcelMgr::getInstance()->deselectLand(); - if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) - { - // zoom in if we're looking at the avatar - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gAgentCamera.cameraZoomIn(0.666f); - gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); - gViewerWindow->moveCursorToCenter(); - } - else if ( gSavedSettings.getBOOL("EditCameraMovement") ) - { - // otherwise just move focus - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gViewerWindow->moveCursorToCenter(); - } + if (gAgentCamera.getFocusOnAvatar() && !LLToolMgr::getInstance()->inEdit() && gSavedSettings.getBOOL("EditCameraMovement") ) + { + // zoom in if we're looking at the avatar + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + gAgentCamera.cameraZoomIn(0.666f); + gAgentCamera.cameraOrbitOver( 30.f * DEG_TO_RAD ); + gViewerWindow->moveCursorToCenter(); + } + else if ( gSavedSettings.getBOOL("EditCameraMovement") ) + { + // otherwise just move focus + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + gViewerWindow->moveCursorToCenter(); + } - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompCreate::getInstance() ); - // Could be first use - //LLFirstUse::useBuild(); - return true; - } + // Could be first use + //LLFirstUse::useBuild(); + return true; + } }; class LLLandBuyPass : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLPanelLandGeneral::onClickBuyPass((void *)FALSE); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLPanelLandGeneral::onClickBuyPass((void *)FALSE); + return true; + } }; class LLLandEnableBuyPass : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLPanelLandGeneral::enableBuyPass(NULL); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLPanelLandGeneral::enableBuyPass(NULL); + return new_value; + } }; // BUG: Should really check if CLICK POINT is in a parcel where you can build. BOOL enable_land_build(void*) { - if (gAgent.isGodlike()) return TRUE; - if (gAgent.inPrelude()) return FALSE; + if (gAgent.isGodlike()) return TRUE; + if (gAgent.inPrelude()) return FALSE; - BOOL can_build = FALSE; - LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (agent_parcel) - { - can_build = agent_parcel->getAllowModify(); - } - return can_build; + BOOL can_build = FALSE; + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (agent_parcel) + { + can_build = agent_parcel->getAllowModify(); + } + return can_build; } // BUG: Should really check if OBJECT is in a parcel where you can build. BOOL enable_object_build(void*) { - if (gAgent.isGodlike()) return TRUE; - if (gAgent.inPrelude()) return FALSE; + if (gAgent.isGodlike()) return TRUE; + if (gAgent.inPrelude()) return FALSE; - BOOL can_build = FALSE; - LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (agent_parcel) - { - can_build = agent_parcel->getAllowModify(); - } - return can_build; + BOOL can_build = FALSE; + LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (agent_parcel) + { + can_build = agent_parcel->getAllowModify(); + } + return can_build; } bool enable_object_edit() { - if (!isAgentAvatarValid()) return false; - - // *HACK: The new "prelude" Help Islands have a build sandbox area, - // so users need the Edit and Create pie menu options when they are - // there. Eventually this needs to be replaced with code that only - // lets you edit objects if you have permission to do so (edit perms, - // group edit, god). See also lltoolbar.cpp. JC - bool enable = false; - if (gAgent.inPrelude()) - { - enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() - || LLSelectMgr::getInstance()->getSelection()->isAttachment(); - } - else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound()) - { - enable = true; - } - - return enable; + if (!isAgentAvatarValid()) return false; + + // *HACK: The new "prelude" Help Islands have a build sandbox area, + // so users need the Edit and Create pie menu options when they are + // there. Eventually this needs to be replaced with code that only + // lets you edit objects if you have permission to do so (edit perms, + // group edit, god). See also lltoolbar.cpp. JC + bool enable = false; + if (gAgent.inPrelude()) + { + enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() + || LLSelectMgr::getInstance()->getSelection()->isAttachment(); + } + else if (LLSelectMgr::getInstance()->selectGetAllValidAndObjectsFound()) + { + enable = true; + } + + return enable; } bool enable_mute_particle() { - const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); + const LLPickInfo& pick = LLToolPie::getInstance()->getPick(); - return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID(); + return pick.mParticleOwnerID != LLUUID::null && pick.mParticleOwnerID != gAgent.getID(); } // mutually exclusive - show either edit option or build in menu bool enable_object_build() { - return !enable_object_edit(); + return !enable_object_edit(); } bool enable_object_select_in_pathfinding_linksets() { - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); } bool visible_object_select_in_pathfinding_linksets() { - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); } bool enable_object_select_in_pathfinding_characters() { - return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); } bool enable_os_exception() @@ -3318,40 +3318,40 @@ bool enable_os_exception() class LLSelfRemoveAllAttachments : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLAppearanceMgr::instance().removeAllAttachmentsFromAvatar(); + return true; + } }; class LLSelfEnableRemoveAllAttachments : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = false; - 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->getNumObjects() > 0) - { - new_value = true; - break; - } - } - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = false; + 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->getNumObjects() > 0) + { + new_value = true; + break; + } + } + } + return new_value; + } }; BOOL enable_has_attachments(void*) { - return FALSE; + return FALSE; } //--------------------------------------------------------------------------- @@ -3359,229 +3359,229 @@ BOOL enable_has_attachments(void*) //--------------------------------------------------------------------------- //void handle_follow(void *userdata) //{ -// // follow a given avatar by ID -// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); -// if (objectp) -// { -// gAgent.startFollowPilot(objectp->getID()); -// } +// // follow a given avatar by ID +// LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +// if (objectp) +// { +// gAgent.startFollowPilot(objectp->getID()); +// } //} bool enable_object_mute() { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return false; - - LLVOAvatar* avatar = find_avatar_from_object(object); - if (avatar) - { - // It's an avatar - LLNameValue *lastname = avatar->getNVPair("LastName"); - bool is_linden = - lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); - bool is_self = avatar->isSelf(); - return !is_linden && !is_self; - } - else - { - // Just a regular object - return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && - !LLMuteList::getInstance()->isMuted(object->getID()); - } + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; + + LLVOAvatar* avatar = find_avatar_from_object(object); + if (avatar) + { + // It's an avatar + LLNameValue *lastname = avatar->getNVPair("LastName"); + bool is_linden = + lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); + bool is_self = avatar->isSelf(); + return !is_linden && !is_self; + } + else + { + // Just a regular object + return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && + !LLMuteList::getInstance()->isMuted(object->getID()); + } } bool enable_object_unmute() { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return false; + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; - LLVOAvatar* avatar = find_avatar_from_object(object); - if (avatar) - { - // It's an avatar - LLNameValue *lastname = avatar->getNVPair("LastName"); - bool is_linden = - lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); - bool is_self = avatar->isSelf(); - return !is_linden && !is_self; - } - else - { - // Just a regular object - return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && - LLMuteList::getInstance()->isMuted(object->getID());; - } + LLVOAvatar* avatar = find_avatar_from_object(object); + if (avatar) + { + // It's an avatar + LLNameValue *lastname = avatar->getNVPair("LastName"); + bool is_linden = + lastname && !LLStringUtil::compareStrings(lastname->getString(), "Linden"); + bool is_self = avatar->isSelf(); + return !is_linden && !is_self; + } + else + { + // Just a regular object + return LLSelectMgr::getInstance()->getSelection()->contains( object, SELECT_ALL_TES ) && + LLMuteList::getInstance()->isMuted(object->getID());; + } } // 0 = normal, 1 = always, 2 = never class LLAvatarCheckImpostorMode : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return false; - - LLVOAvatar* avatar = find_avatar_from_object(object); - if (!avatar) return false; - - U32 mode = userdata.asInteger(); - switch (mode) - { - case 0: - return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_RENDER_NORMALLY); - case 1: - return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER); - case 2: - return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER); +{ + bool handleEvent(const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; + + LLVOAvatar* avatar = find_avatar_from_object(object); + if (!avatar) return false; + + U32 mode = userdata.asInteger(); + switch (mode) + { + case 0: + return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_RENDER_NORMALLY); + case 1: + return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_DO_NOT_RENDER); + case 2: + return (avatar->getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER); case 4: return (avatar->getVisualMuteSettings() != LLVOAvatar::AV_RENDER_NORMALLY); - default: - return false; - } - } // handleEvent() + default: + return false; + } + } // handleEvent() }; // 0 = normal, 1 = always, 2 = never class LLAvatarSetImpostorMode : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return false; - - LLVOAvatar* avatar = find_avatar_from_object(object); - if (!avatar) return false; - - U32 mode = userdata.asInteger(); - switch (mode) - { - case 0: - avatar->setVisualMuteSettings(LLVOAvatar::AV_RENDER_NORMALLY); - break; - case 1: - avatar->setVisualMuteSettings(LLVOAvatar::AV_DO_NOT_RENDER); - break; - case 2: - avatar->setVisualMuteSettings(LLVOAvatar::AV_ALWAYS_RENDER); - break; - default: - return false; - } - - LLVOAvatar::cullAvatarsByPixelArea(); - return true; - } // handleEvent() + bool handleEvent(const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return false; + + LLVOAvatar* avatar = find_avatar_from_object(object); + if (!avatar) return false; + + U32 mode = userdata.asInteger(); + switch (mode) + { + case 0: + avatar->setVisualMuteSettings(LLVOAvatar::AV_RENDER_NORMALLY); + break; + case 1: + avatar->setVisualMuteSettings(LLVOAvatar::AV_DO_NOT_RENDER); + break; + case 2: + avatar->setVisualMuteSettings(LLVOAvatar::AV_ALWAYS_RENDER); + break; + default: + return false; + } + + LLVOAvatar::cullAvatarsByPixelArea(); + return true; + } // handleEvent() }; class LLObjectMute : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return true; - - LLUUID id; - std::string name; - LLMute::EType type; - LLVOAvatar* avatar = find_avatar_from_object(object); - if (avatar) - { - avatar->mNeedsImpostorUpdate = TRUE; - avatar->mLastImpostorUpdateReason = 9; - - id = avatar->getID(); - - LLNameValue *firstname = avatar->getNVPair("FirstName"); - LLNameValue *lastname = avatar->getNVPair("LastName"); - if (firstname && lastname) - { - name = LLCacheName::buildFullName( - firstname->getString(), lastname->getString()); - } - - type = LLMute::AGENT; - } - else - { - // it's an object - id = object->getID(); - - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (node) - { - name = node->mName; - } - - type = LLMute::OBJECT; - } - - LLMute mute(id, name, type); - if (LLMuteList::getInstance()->isMuted(mute.mID)) - { - LLMuteList::getInstance()->remove(mute); - } - else - { - LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) return true; + + LLUUID id; + std::string name; + LLMute::EType type; + LLVOAvatar* avatar = find_avatar_from_object(object); + if (avatar) + { + avatar->mNeedsImpostorUpdate = TRUE; + avatar->mLastImpostorUpdateReason = 9; + + id = avatar->getID(); + + LLNameValue *firstname = avatar->getNVPair("FirstName"); + LLNameValue *lastname = avatar->getNVPair("LastName"); + if (firstname && lastname) + { + name = LLCacheName::buildFullName( + firstname->getString(), lastname->getString()); + } + + type = LLMute::AGENT; + } + else + { + // it's an object + id = object->getID(); + + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node) + { + name = node->mName; + } + + type = LLMute::OBJECT; + } + + LLMute mute(id, name, type); + if (LLMuteList::getInstance()->isMuted(mute.mID)) + { + LLMuteList::getInstance()->remove(mute); + } + else + { + LLMuteList::getInstance()->add(mute); + LLPanelBlockedList::showPanelAndSelect(mute.mID); + } + + return true; + } }; bool handle_go_to() { - // try simulator autopilot - std::vector strings; - std::string val; - LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; - val = llformat("%g", pos.mdV[VX]); - strings.push_back(val); - val = llformat("%g", pos.mdV[VY]); - strings.push_back(val); - val = llformat("%g", pos.mdV[VZ]); - strings.push_back(val); - send_generic_message("autopilot", strings); - - LLViewerParcelMgr::getInstance()->deselectLand(); - - if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera")) - { - gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID()); - } - else - { - // Snap camera back to behind avatar - gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE); - } - - // Could be first use - //LLFirstUse::useGoTo(); - return true; + // try simulator autopilot + std::vector strings; + std::string val; + LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; + val = llformat("%g", pos.mdV[VX]); + strings.push_back(val); + val = llformat("%g", pos.mdV[VY]); + strings.push_back(val); + val = llformat("%g", pos.mdV[VZ]); + strings.push_back(val); + send_generic_message("autopilot", strings); + + LLViewerParcelMgr::getInstance()->deselectLand(); + + if (isAgentAvatarValid() && !gSavedSettings.getBOOL("AutoPilotLocksCamera")) + { + gAgentCamera.setFocusGlobal(gAgentCamera.getFocusTargetGlobal(), gAgentAvatarp->getID()); + } + else + { + // Snap camera back to behind avatar + gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE); + } + + // Could be first use + //LLFirstUse::useGoTo(); + return true; } class LLGoToObject : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return handle_go_to(); - } + bool handleEvent(const LLSD& userdata) + { + return handle_go_to(); + } }; class LLAvatarReportAbuse : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLFloaterReporter::showFromObject(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLFloaterReporter::showFromObject(avatar->getID()); + } + return true; + } }; @@ -3590,230 +3590,230 @@ class LLAvatarReportAbuse : public view_listener_t //--------------------------------------------------------------------------- bool callback_freeze(const LLSD& notification, const LLSD& response) { - LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if (0 == option || 1 == option) - { - U32 flags = 0x0; - if (1 == option) - { - // unfreeze - flags |= 0x1; - } - - LLMessageSystem* msg = gMessageSystem; - LLViewerObject* avatar = gObjectList.findObject(avatar_id); - - if (avatar) - { - msg->newMessage("FreezeUser"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("Data"); - msg->addUUID("TargetID", avatar_id ); - msg->addU32("Flags", flags ); - msg->sendReliable( avatar->getRegion()->getHost() ); - } - } - return false; -} + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (0 == option || 1 == option) + { + U32 flags = 0x0; + if (1 == option) + { + // unfreeze + flags |= 0x1; + } + LLMessageSystem* msg = gMessageSystem; + LLViewerObject* avatar = gObjectList.findObject(avatar_id); -void handle_avatar_freeze(const LLSD& avatar_id) -{ - // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; - if (avatar_id.asUUID().notNull()) - { - avatar = find_avatar_from_object(avatar_id.asUUID()); - } - else - { - avatar = find_avatar_from_object( - LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - } - - if( avatar ) - { - std::string fullname = avatar->getFullname(); - LLSD payload; - payload["avatar_id"] = avatar->getID(); - - if (!fullname.empty()) - { - LLSD args; - args["AVATAR_NAME"] = fullname; - LLNotificationsUtil::add("FreezeAvatarFullname", - args, - payload, - callback_freeze); - } - else - { - LLNotificationsUtil::add("FreezeAvatar", - LLSD(), - payload, - callback_freeze); - } - } + if (avatar) + { + msg->newMessage("FreezeUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + msg->sendReliable( avatar->getRegion()->getHost() ); + } + } + return false; } -class LLAvatarVisibleDebug : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - return gAgent.isGodlike(); - } -}; + +void handle_avatar_freeze(const LLSD& avatar_id) +{ + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + + if( avatar ) + { + std::string fullname = avatar->getFullname(); + LLSD payload; + payload["avatar_id"] = avatar->getID(); + + if (!fullname.empty()) + { + LLSD args; + args["AVATAR_NAME"] = fullname; + LLNotificationsUtil::add("FreezeAvatarFullname", + args, + payload, + callback_freeze); + } + else + { + LLNotificationsUtil::add("FreezeAvatar", + LLSD(), + payload, + callback_freeze); + } + } +} + +class LLAvatarVisibleDebug : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + return gAgent.isGodlike(); + } +}; class LLAvatarDebug : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if( avatar ) - { - if (avatar->isSelf()) - { - ((LLVOAvatarSelf *)avatar)->dumpLocalTextures(); - } - LL_INFOS() << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << LL_ENDL; - std::vector strings; - strings.push_back(avatar->getID().asString()); - LLUUID invoice; - send_generic_message("dumptempassetdata", strings, invoice); - LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) ); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if( avatar ) + { + if (avatar->isSelf()) + { + ((LLVOAvatarSelf *)avatar)->dumpLocalTextures(); + } + LL_INFOS() << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << LL_ENDL; + std::vector strings; + strings.push_back(avatar->getID().asString()); + LLUUID invoice; + send_generic_message("dumptempassetdata", strings, invoice); + LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) ); + } + return true; + } }; bool callback_eject(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (2 == option) - { - // Cancel button. - return false; - } - LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); - bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean(); - - if (0 == option) - { - // Eject button - LLMessageSystem* msg = gMessageSystem; - LLViewerObject* avatar = gObjectList.findObject(avatar_id); - - if (avatar) - { - U32 flags = 0x0; - msg->newMessage("EjectUser"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID() ); - msg->addUUID("SessionID", gAgent.getSessionID() ); - msg->nextBlock("Data"); - msg->addUUID("TargetID", avatar_id ); - msg->addU32("Flags", flags ); - msg->sendReliable( avatar->getRegion()->getHost() ); - } - } - else if (ban_enabled) - { - // This is tricky. It is similar to say if it is not an 'Eject' button, - // and it is also not an 'Cancle' button, and ban_enabled==ture, - // it should be the 'Eject and Ban' button. - LLMessageSystem* msg = gMessageSystem; - LLViewerObject* avatar = gObjectList.findObject(avatar_id); - - if (avatar) - { - U32 flags = 0x1; - msg->newMessage("EjectUser"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID() ); - msg->addUUID("SessionID", gAgent.getSessionID() ); - msg->nextBlock("Data"); - msg->addUUID("TargetID", avatar_id ); - msg->addU32("Flags", flags ); - msg->sendReliable( avatar->getRegion()->getHost() ); - } - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (2 == option) + { + // Cancel button. + return false; + } + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean(); + + if (0 == option) + { + // Eject button + LLMessageSystem* msg = gMessageSystem; + LLViewerObject* avatar = gObjectList.findObject(avatar_id); + + if (avatar) + { + U32 flags = 0x0; + msg->newMessage("EjectUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID() ); + msg->addUUID("SessionID", gAgent.getSessionID() ); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + msg->sendReliable( avatar->getRegion()->getHost() ); + } + } + else if (ban_enabled) + { + // This is tricky. It is similar to say if it is not an 'Eject' button, + // and it is also not an 'Cancle' button, and ban_enabled==ture, + // it should be the 'Eject and Ban' button. + LLMessageSystem* msg = gMessageSystem; + LLViewerObject* avatar = gObjectList.findObject(avatar_id); + + if (avatar) + { + U32 flags = 0x1; + msg->newMessage("EjectUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID() ); + msg->addUUID("SessionID", gAgent.getSessionID() ); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + msg->sendReliable( avatar->getRegion()->getHost() ); + } + } + return false; } void handle_avatar_eject(const LLSD& avatar_id) { - // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; - if (avatar_id.asUUID().notNull()) - { - avatar = find_avatar_from_object(avatar_id.asUUID()); - } - else - { - avatar = find_avatar_from_object( - LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - } - - if( avatar ) - { - LLSD payload; - payload["avatar_id"] = avatar->getID(); - std::string fullname = avatar->getFullname(); - - const LLVector3d& pos = avatar->getPositionGlobal(); - LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); - - if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED)) - { + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + + if( avatar ) + { + LLSD payload; + payload["avatar_id"] = avatar->getID(); + std::string fullname = avatar->getFullname(); + + const LLVector3d& pos = avatar->getPositionGlobal(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); + + if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED)) + { payload["ban_enabled"] = true; - if (!fullname.empty()) - { - LLSD args; - args["AVATAR_NAME"] = fullname; - LLNotificationsUtil::add("EjectAvatarFullname", - args, - payload, - callback_eject); - } - else - { - LLNotificationsUtil::add("EjectAvatarFullname", - LLSD(), - payload, - callback_eject); - } - } - else - { + if (!fullname.empty()) + { + LLSD args; + args["AVATAR_NAME"] = fullname; + LLNotificationsUtil::add("EjectAvatarFullname", + args, + payload, + callback_eject); + } + else + { + LLNotificationsUtil::add("EjectAvatarFullname", + LLSD(), + payload, + callback_eject); + } + } + else + { payload["ban_enabled"] = false; - if (!fullname.empty()) - { - LLSD args; - args["AVATAR_NAME"] = fullname; - LLNotificationsUtil::add("EjectAvatarFullnameNoBan", - args, - payload, - callback_eject); - } - else - { - LLNotificationsUtil::add("EjectAvatarNoBan", - LLSD(), - payload, - callback_eject); - } - } - } + if (!fullname.empty()) + { + LLSD args; + args["AVATAR_NAME"] = fullname; + LLNotificationsUtil::add("EjectAvatarFullnameNoBan", + args, + payload, + callback_eject); + } + else + { + LLNotificationsUtil::add("EjectAvatarNoBan", + LLSD(), + payload, + callback_eject); + } + } + } } bool my_profile_visible() { - LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID); - return floaterp && floaterp->isInVisibleChain(); + LLFloater* floaterp = LLAvatarActions::getProfileFloater(gAgentID); + return floaterp && floaterp->isInVisibleChain(); } bool picks_tab_visible() @@ -3823,192 +3823,192 @@ bool picks_tab_visible() bool enable_freeze_eject(const LLSD& avatar_id) { - // Use avatar_id if available, otherwise default to right-click avatar - LLVOAvatar* avatar = NULL; - if (avatar_id.asUUID().notNull()) - { - avatar = find_avatar_from_object(avatar_id.asUUID()); - } - else - { - avatar = find_avatar_from_object( - LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - } - if (!avatar) return false; - - // Gods can always freeze - if (gAgent.isGodlike()) return true; - - // Estate owners / managers can freeze - // Parcel owners can also freeze - const LLVector3& pos = avatar->getPositionRegion(); - const LLVector3d& pos_global = avatar->getPositionGlobal(); - LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); - LLViewerRegion* region = avatar->getRegion(); - if (!region) return false; - - bool new_value = region->isOwnedSelf(pos); - if (!new_value || region->isOwnedGroup(pos)) - { - new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); - } - return new_value; + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (avatar_id.asUUID().notNull()) + { + avatar = find_avatar_from_object(avatar_id.asUUID()); + } + else + { + avatar = find_avatar_from_object( + LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + } + if (!avatar) return false; + + // Gods can always freeze + if (gAgent.isGodlike()) return true; + + // Estate owners / managers can freeze + // Parcel owners can also freeze + const LLVector3& pos = avatar->getPositionRegion(); + const LLVector3d& pos_global = avatar->getPositionGlobal(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); + LLViewerRegion* region = avatar->getRegion(); + if (!region) return false; + + bool new_value = region->isOwnedSelf(pos); + if (!new_value || region->isOwnedGroup(pos)) + { + new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); + } + return new_value; } bool callback_leave_group(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_LeaveGroupRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_GroupData); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); - gAgent.sendReliableMessage(); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + LLMessageSystem *msg = gMessageSystem; + + msg->newMessageFast(_PREHASH_LeaveGroupRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_GroupData); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID() ); + gAgent.sendReliableMessage(); + } + return false; } void append_aggregate(std::string& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt) { - LLAggregatePermissions::EValue val = ag_perm.getValue(bit); - std::string buffer; - switch(val) - { - case LLAggregatePermissions::AP_NONE: - buffer = llformat( "* %s None\n", txt); - break; - case LLAggregatePermissions::AP_SOME: - buffer = llformat( "* %s Some\n", txt); - break; - case LLAggregatePermissions::AP_ALL: - buffer = llformat( "* %s All\n", txt); - break; - case LLAggregatePermissions::AP_EMPTY: - default: - break; - } - string.append(buffer); + LLAggregatePermissions::EValue val = ag_perm.getValue(bit); + std::string buffer; + switch(val) + { + case LLAggregatePermissions::AP_NONE: + buffer = llformat( "* %s None\n", txt); + break; + case LLAggregatePermissions::AP_SOME: + buffer = llformat( "* %s Some\n", txt); + break; + case LLAggregatePermissions::AP_ALL: + buffer = llformat( "* %s All\n", txt); + break; + case LLAggregatePermissions::AP_EMPTY: + default: + break; + } + string.append(buffer); } bool enable_buy_object() { // In order to buy, there must only be 1 purchaseable object in // the selection manager. - if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false; + if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() != 1) return false; LLViewerObject* obj = NULL; LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if(node) + if(node) { obj = node->getObject(); if(!obj) return false; - if( for_sale_selection(node) ) - { - // *NOTE: Is this needed? This checks to see if anyone owns the - // object, dating back to when we had "public" objects owned by - // no one. JC - if(obj->permAnyOwner()) return true; - } + if( for_sale_selection(node) ) + { + // *NOTE: Is this needed? This checks to see if anyone owns the + // object, dating back to when we had "public" objects owned by + // no one. JC + if(obj->permAnyOwner()) return true; + } } - return false; + return false; } // Note: This will only work if the selected object's data has been // received by the viewer and cached in the selection manager. void handle_buy_object(LLSaleInfo sale_info) { - if(!LLSelectMgr::getInstance()->selectGetAllRootsValid()) - { - LLNotificationsUtil::add("UnableToBuyWhileDownloading"); - return; - } + if(!LLSelectMgr::getInstance()->selectGetAllRootsValid()) + { + LLNotificationsUtil::add("UnableToBuyWhileDownloading"); + return; + } - LLUUID owner_id; - std::string owner_name; - BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); - if (!owners_identical) - { - LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners"); - return; - } + LLUUID owner_id; + std::string owner_name; + BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); + if (!owners_identical) + { + LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners"); + return; + } - LLPermissions perm; - BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm); - LLAggregatePermissions ag_perm; - valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm); - if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID())) - { - LLNotificationsUtil::add("ObjectNotForSale"); - return; - } + LLPermissions perm; + BOOL valid = LLSelectMgr::getInstance()->selectGetPermissions(perm); + LLAggregatePermissions ag_perm; + valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm); + if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID())) + { + LLNotificationsUtil::add("ObjectNotForSale"); + return; + } - LLFloaterBuy::show(sale_info); + LLFloaterBuy::show(sale_info); } void handle_buy_contents(LLSaleInfo sale_info) { - LLFloaterBuyContents::show(sale_info); + LLFloaterBuyContents::show(sale_info); } void handle_region_dump_temp_asset_data(void*) { - LL_INFOS() << "Dumping temporary asset data to simulator logs" << LL_ENDL; - std::vector strings; - LLUUID invoice; - send_generic_message("dumptempassetdata", strings, invoice); + LL_INFOS() << "Dumping temporary asset data to simulator logs" << LL_ENDL; + std::vector strings; + LLUUID invoice; + send_generic_message("dumptempassetdata", strings, invoice); } void handle_region_clear_temp_asset_data(void*) { - LL_INFOS() << "Clearing temporary asset data" << LL_ENDL; - std::vector strings; - LLUUID invoice; - send_generic_message("cleartempassetdata", strings, invoice); + LL_INFOS() << "Clearing temporary asset data" << LL_ENDL; + std::vector strings; + LLUUID invoice; + send_generic_message("cleartempassetdata", strings, invoice); } void handle_region_dump_settings(void*) { - LLViewerRegion* regionp = gAgent.getRegion(); - if (regionp) - { - LL_INFOS() << "Damage: " << (regionp->getAllowDamage() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "Landmark: " << (regionp->getAllowLandmark() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "SetHome: " << (regionp->getAllowSetHome() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "SunFixed: " << (regionp->getSunFixed() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "BlockFly: " << (regionp->getBlockFly() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "AllowP2P: " << (regionp->getAllowDirectTeleport() ? "on" : "off") << LL_ENDL; - LL_INFOS() << "Water: " << (regionp->getWaterHeight()) << LL_ENDL; - } + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + LL_INFOS() << "Damage: " << (regionp->getAllowDamage() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "Landmark: " << (regionp->getAllowLandmark() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "SetHome: " << (regionp->getAllowSetHome() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "ResetHome: " << (regionp->getResetHomeOnTeleport() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "SunFixed: " << (regionp->getSunFixed() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "BlockFly: " << (regionp->getBlockFly() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "AllowP2P: " << (regionp->getAllowDirectTeleport() ? "on" : "off") << LL_ENDL; + LL_INFOS() << "Water: " << (regionp->getWaterHeight()) << LL_ENDL; + } } void handle_dump_group_info(void *) { - gAgent.dumpGroupInfo(); + gAgent.dumpGroupInfo(); } void handle_dump_capabilities_info(void *) { - LLViewerRegion* regionp = gAgent.getRegion(); - if (regionp) - { - regionp->logActiveCapabilities(); - } + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->logActiveCapabilities(); + } } void handle_dump_region_object_cache(void*) { - LLViewerRegion* regionp = gAgent.getRegion(); - if (regionp) - { - regionp->dumpCache(); - } + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->dumpCache(); + } } void handle_reset_interest_lists(void *) @@ -4029,18 +4029,18 @@ void handle_reset_interest_lists(void *) void handle_dump_focus() { - LLUICtrl *ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); + LLUICtrl *ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); - LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL; + LL_INFOS() << "Keyboard focus " << (ctrl ? ctrl->getName() : "(none)") << LL_ENDL; } class LLSelfStandUp : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgent.standUp(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gAgent.standUp(); + return true; + } }; bool enable_standup_self() @@ -4061,202 +4061,202 @@ class LLSelfSitDown : public view_listener_t bool show_sitdown_self() { - return isAgentAvatarValid() && !gAgentAvatarp->isSitting(); + return isAgentAvatarValid() && !gAgentAvatarp->isSitting(); } bool enable_sitdown_self() { - return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); + return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); } class LLSelfToggleSitStand : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (isAgentAvatarValid()) - { - if (gAgentAvatarp->isSitting()) - { - gAgent.standUp(); - } - else - { - gAgent.sitDown(); - } - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (isAgentAvatarValid()) + { + if (gAgentAvatarp->isSitting()) + { + gAgent.standUp(); + } + else + { + gAgent.sitDown(); + } + } + return true; + } }; bool enable_sit_stand() { - return enable_sitdown_self() || enable_standup_self(); + return enable_sitdown_self() || enable_standup_self(); } bool enable_fly_land() { - return gAgent.getFlying() || LLAgent::enableFlying(); + return gAgent.getFlying() || LLAgent::enableFlying(); } class LLCheckPanelPeopleTab : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string panel_name = userdata.asString(); + bool handleEvent(const LLSD& userdata) + { + std::string panel_name = userdata.asString(); - LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); - if(panel && panel->isInVisibleChain()) - { - return true; - } - return false; - } + LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); + if(panel && panel->isInVisibleChain()) + { + return true; + } + return false; + } }; // Toggle one of "People" panel tabs in side tray. class LLTogglePanelPeopleTab : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string panel_name = userdata.asString(); - - LLSD param; - param["people_panel_tab_name"] = panel_name; - - if ( panel_name == "friends_panel" - || panel_name == "groups_panel" - || panel_name == "nearby_panel" - || panel_name == "blocked_panel") - { - return togglePeoplePanel(panel_name, param); - } - else - { - return false; - } - } - - static bool togglePeoplePanel(const std::string& panel_name, const LLSD& param) - { - LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); - if(!panel) - return false; - - if (panel->isInVisibleChain()) - { - LLFloaterReg::hideInstance("people"); - } - else - { - LLFloaterSidePanelContainer::showPanel("people", "panel_people", param) ; - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string panel_name = userdata.asString(); + + LLSD param; + param["people_panel_tab_name"] = panel_name; + + if ( panel_name == "friends_panel" + || panel_name == "groups_panel" + || panel_name == "nearby_panel" + || panel_name == "blocked_panel") + { + return togglePeoplePanel(panel_name, param); + } + else + { + return false; + } + } + + static bool togglePeoplePanel(const std::string& panel_name, const LLSD& param) + { + LLPanel *panel = LLFloaterSidePanelContainer::getPanel("people", panel_name); + if(!panel) + return false; + + if (panel->isInVisibleChain()) + { + LLFloaterReg::hideInstance("people"); + } + else + { + LLFloaterSidePanelContainer::showPanel("people", "panel_people", param) ; + } + + return true; + } }; BOOL check_admin_override(void*) { - return gAgent.getAdminOverride(); + return gAgent.getAdminOverride(); } void handle_admin_override_toggle(void*) { - gAgent.setAdminOverride(!gAgent.getAdminOverride()); + gAgent.setAdminOverride(!gAgent.getAdminOverride()); - // The above may have affected which debug menus are visible - show_debug_menus(); + // The above may have affected which debug menus are visible + show_debug_menus(); } void handle_visual_leak_detector_toggle(void*) { - static bool vld_enabled = false; + static bool vld_enabled = false; - if ( vld_enabled ) - { + if ( vld_enabled ) + { #ifdef INCLUDE_VLD - // only works for debug builds (hard coded into vld.h) + // only works for debug builds (hard coded into vld.h) #ifdef _DEBUG - // start with Visual Leak Detector turned off - VLDDisable(); + // start with Visual Leak Detector turned off + VLDDisable(); #endif // _DEBUG #endif // INCLUDE_VLD - vld_enabled = false; - } - else - { + vld_enabled = false; + } + else + { #ifdef INCLUDE_VLD - // only works for debug builds (hard coded into vld.h) - #ifdef _DEBUG - // start with Visual Leak Detector turned off - VLDEnable(); - #endif // _DEBUG + // only works for debug builds (hard coded into vld.h) + #ifdef _DEBUG + // start with Visual Leak Detector turned off + VLDEnable(); + #endif // _DEBUG #endif // INCLUDE_VLD - vld_enabled = true; - }; + vld_enabled = true; + }; } void handle_god_mode(void*) { - gAgent.requestEnterGodMode(); + gAgent.requestEnterGodMode(); } void handle_leave_god_mode(void*) { - gAgent.requestLeaveGodMode(); + gAgent.requestLeaveGodMode(); } void set_god_level(U8 god_level) { - U8 old_god_level = gAgent.getGodLevel(); - gAgent.setGodLevel( god_level ); - LLViewerParcelMgr::getInstance()->notifyObservers(); + U8 old_god_level = gAgent.getGodLevel(); + gAgent.setGodLevel( god_level ); + LLViewerParcelMgr::getInstance()->notifyObservers(); - // God mode changes region visibility - LLWorldMap::getInstance()->reloadItems(true); + // God mode changes region visibility + LLWorldMap::getInstance()->reloadItems(true); - // inventory in items may change in god mode - gObjectList.dirtyAllObjectInventory(); + // inventory in items may change in god mode + gObjectList.dirtyAllObjectInventory(); if(gViewerWindow) { gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT, LLGridManager::getInstance()->isInProductionGrid()); } - + LLSD args; - if(god_level > GOD_NOT) - { - args["LEVEL"] = llformat("%d",(S32)god_level); - LLNotificationsUtil::add("EnteringGodMode", args); - } - else - { - args["LEVEL"] = llformat("%d",(S32)old_god_level); - LLNotificationsUtil::add("LeavingGodMode", args); - } - - // changing god-level can affect which menus we see - show_debug_menus(); - - // changing god-level can invalidate search results - LLFloaterSearch *search = dynamic_cast(LLFloaterReg::getInstance("search")); - if (search) - { - search->godLevelChanged(god_level); - } + if(god_level > GOD_NOT) + { + args["LEVEL"] = llformat("%d",(S32)god_level); + LLNotificationsUtil::add("EnteringGodMode", args); + } + else + { + args["LEVEL"] = llformat("%d",(S32)old_god_level); + LLNotificationsUtil::add("LeavingGodMode", args); + } + + // changing god-level can affect which menus we see + show_debug_menus(); + + // changing god-level can invalidate search results + LLFloaterSearch *search = dynamic_cast(LLFloaterReg::getInstance("search")); + if (search) + { + search->godLevelChanged(god_level); + } } #ifdef TOGGLE_HACKED_GODLIKE_VIEWER void handle_toggle_hacked_godmode(void*) { - gHackGodmode = !gHackGodmode; - set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT); + gHackGodmode = !gHackGodmode; + set_god_level(gHackGodmode ? GOD_MAINTENANCE : GOD_NOT); } BOOL check_toggle_hacked_godmode(void*) { - return gHackGodmode; + return gHackGodmode; } bool enable_toggle_hacked_godmode(void*) @@ -4267,174 +4267,174 @@ bool enable_toggle_hacked_godmode(void*) void process_grant_godlike_powers(LLMessageSystem* msg, void**) { - LLUUID agent_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); - LLUUID session_id; - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); - if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID())) - { - U8 god_level; - msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level); - set_god_level(god_level); - } - else - { - LL_WARNS() << "Grant godlike for wrong agent " << agent_id << LL_ENDL; - } + LLUUID agent_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + LLUUID session_id; + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_SessionID, session_id); + if((agent_id == gAgent.getID()) && (session_id == gAgent.getSessionID())) + { + U8 god_level; + msg->getU8Fast(_PREHASH_GrantData, _PREHASH_GodLevel, god_level); + set_god_level(god_level); + } + else + { + LL_WARNS() << "Grant godlike for wrong agent " << agent_id << LL_ENDL; + } } /* class LLHaveCallingcard : public LLInventoryCollectFunctor { public: - LLHaveCallingcard(const LLUUID& agent_id); - virtual ~LLHaveCallingcard() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item); - BOOL isThere() const { return mIsThere;} + LLHaveCallingcard(const LLUUID& agent_id); + virtual ~LLHaveCallingcard() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); + BOOL isThere() const { return mIsThere;} protected: - LLUUID mID; - BOOL mIsThere; + LLUUID mID; + BOOL mIsThere; }; LLHaveCallingcard::LLHaveCallingcard(const LLUUID& agent_id) : - mID(agent_id), - mIsThere(FALSE) + mID(agent_id), + mIsThere(FALSE) { } bool LLHaveCallingcard::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - if(item) - { - if((item->getType() == LLAssetType::AT_CALLINGCARD) - && (item->getCreatorUUID() == mID)) - { - mIsThere = TRUE; - } - } - return FALSE; + LLInventoryItem* item) +{ + if(item) + { + if((item->getType() == LLAssetType::AT_CALLINGCARD) + && (item->getCreatorUUID() == mID)) + { + mIsThere = TRUE; + } + } + return FALSE; } */ BOOL is_agent_mappable(const LLUUID& agent_id) { - const LLRelationship* buddy_info = NULL; - bool is_friend = LLAvatarActions::isFriend(agent_id); + const LLRelationship* buddy_info = NULL; + bool is_friend = LLAvatarActions::isFriend(agent_id); - if (is_friend) - buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id); + if (is_friend) + buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id); - return (buddy_info && - buddy_info->isOnline() && - buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) - ); + return (buddy_info && + buddy_info->isOnline() && + buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION) + ); } // Enable a menu item when you don't have someone's card. class LLAvatarEnableAddFriend : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID()); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + bool new_value = avatar && !LLAvatarActions::isFriend(avatar->getID()); + return new_value; + } }; void request_friendship(const LLUUID& dest_id) { - LLViewerObject* dest = gObjectList.findObject(dest_id); - if(dest && dest->isAvatar()) - { - std::string full_name; - LLNameValue* nvfirst = dest->getNVPair("FirstName"); - LLNameValue* nvlast = dest->getNVPair("LastName"); - if(nvfirst && nvlast) - { - full_name = LLCacheName::buildFullName( - nvfirst->getString(), nvlast->getString()); - } - if (!full_name.empty()) - { - LLAvatarActions::requestFriendshipDialog(dest_id, full_name); - } - else - { - LLNotificationsUtil::add("CantOfferFriendship"); - } - } + LLViewerObject* dest = gObjectList.findObject(dest_id); + if(dest && dest->isAvatar()) + { + std::string full_name; + LLNameValue* nvfirst = dest->getNVPair("FirstName"); + LLNameValue* nvlast = dest->getNVPair("LastName"); + if(nvfirst && nvlast) + { + full_name = LLCacheName::buildFullName( + nvfirst->getString(), nvlast->getString()); + } + if (!full_name.empty()) + { + LLAvatarActions::requestFriendshipDialog(dest_id, full_name); + } + else + { + LLNotificationsUtil::add("CantOfferFriendship"); + } + } } class LLEditEnableCustomizeAvatar : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gAgentWearables.areWearablesLoaded(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gAgentWearables.areWearablesLoaded(); + return new_value; + } }; class LLEnableEditShape : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); - } + bool handleEvent(const LLSD& userdata) + { + return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); + } }; class LLEnableHoverHeight : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled(); - } + bool handleEvent(const LLSD& userdata) + { + return gAgent.getRegion() && gAgent.getRegion()->avatarHoverHeightEnabled(); + } }; class LLEnableEditPhysics : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); - return TRUE; - } + bool handleEvent(const LLSD& userdata) + { + //return gAgentWearables.isWearableModifiable(LLWearableType::WT_SHAPE, 0); + return TRUE; + } }; bool is_object_sittable() { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (object && object->getPCode() == LL_PCODE_VOLUME) - { - return true; - } - else - { - return false; - } + if (object && object->getPCode() == LL_PCODE_VOLUME) + { + return true; + } + else + { + return false; + } } // only works on pie menu void handle_object_sit(LLViewerObject *object, const LLVector3 &offset) { - // get object selection offset + // get object selection offset - if (object && object->getPCode() == LL_PCODE_VOLUME) - { + if (object && object->getPCode() == LL_PCODE_VOLUME) + { - gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_TargetObject); - gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); - gMessageSystem->addVector3Fast(_PREHASH_Offset, offset); + gMessageSystem->newMessageFast(_PREHASH_AgentRequestSit); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_TargetObject); + gMessageSystem->addUUIDFast(_PREHASH_TargetID, object->mID); + gMessageSystem->addVector3Fast(_PREHASH_Offset, offset); - object->getRegion()->sendReliableMessage(); - } + object->getRegion()->sendReliableMessage(); + } } void handle_object_sit_or_stand() @@ -4469,12 +4469,12 @@ void handle_object_sit(const LLUUID& object_id) void near_sit_down_point(BOOL success, void *) { - if (success) - { - gAgent.setFlying(FALSE); - gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot - gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); - } + if (success) + { + gAgent.setFlying(FALSE); + gAgent.clearControlFlags(AGENT_CONTROL_STAND_UP); // might have been set by autopilot + gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + } } class LLLandSit : public view_listener_t @@ -4521,120 +4521,120 @@ void reset_view_final( BOOL proceed ); void handle_reset_view() { - if (gAgentCamera.cameraCustomizeAvatar()) - { - // switching to outfit selector should automagically save any currently edited wearable - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); - } - gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE); - reset_view_final( TRUE ); - LLFloaterCamera::resetCameraMode(); + if (gAgentCamera.cameraCustomizeAvatar()) + { + // switching to outfit selector should automagically save any currently edited wearable + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); + } + gAgentCamera.setFocusOnAvatar(TRUE, FALSE, FALSE); + reset_view_final( TRUE ); + LLFloaterCamera::resetCameraMode(); } class LLViewResetView : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - handle_reset_view(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + handle_reset_view(); + return true; + } }; // Note: extra parameters allow this function to be called from dialog. -void reset_view_final( BOOL proceed ) +void reset_view_final( BOOL proceed ) { - if( !proceed ) - { - return; - } + if( !proceed ) + { + return; + } - gAgentCamera.resetView(TRUE, TRUE); - gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); + gAgentCamera.resetView(TRUE, TRUE); + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); } class LLViewLookAtLastChatter : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgentCamera.lookAtLastChat(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gAgentCamera.lookAtLastChat(); + return true; + } }; class LLViewMouselook : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (!gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToMouselook(); - } - else - { - gAgentCamera.changeCameraToDefault(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (!gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToMouselook(); + } + else + { + gAgentCamera.changeCameraToDefault(); + } + return true; + } }; class LLViewDefaultUISize : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gSavedSettings.setF32("UIScaleFactor", 1.0f); - gSavedSettings.setBOOL("UIAutoScale", FALSE); - gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gSavedSettings.setF32("UIScaleFactor", 1.0f); + gSavedSettings.setBOOL("UIAutoScale", FALSE); + gViewerWindow->reshape(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); + return true; + } }; class LLViewToggleUI : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) - { - LLNotification::Params params("ConfirmHideUI"); - params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); - LLSD substitutions; + bool handleEvent(const LLSD& userdata) + { + if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) + { + LLNotification::Params params("ConfirmHideUI"); + params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); + LLSD substitutions; #if LL_DARWIN - substitutions["SHORTCUT"] = "Cmd+Shift+U"; + substitutions["SHORTCUT"] = "Cmd+Shift+U"; #else - substitutions["SHORTCUT"] = "Ctrl+Shift+U"; + substitutions["SHORTCUT"] = "Ctrl+Shift+U"; #endif - params.substitutions = substitutions; - if (!gSavedSettings.getBOOL("HideUIControls")) - { - // hiding, so show notification - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } - } - return true; - } - - void confirm(const LLSD& notification, const LLSD& response) - { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if (option == 0) // OK - { - gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls")); - LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls")); - gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls")); - } - } + params.substitutions = substitutions; + if (!gSavedSettings.getBOOL("HideUIControls")) + { + // hiding, so show notification + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } + } + return true; + } + + void confirm(const LLSD& notification, const LLSD& response) + { + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + if (option == 0) // OK + { + gViewerWindow->setUIVisibility(gSavedSettings.getBOOL("HideUIControls")); + LLPanelStandStopFlying::getInstance()->setVisible(gSavedSettings.getBOOL("HideUIControls")); + gSavedSettings.setBOOL("HideUIControls",!gSavedSettings.getBOOL("HideUIControls")); + } + } }; void handle_duplicate_in_place(void*) { - LL_INFOS() << "handle_duplicate_in_place" << LL_ENDL; + LL_INFOS() << "handle_duplicate_in_place" << LL_ENDL; - LLVector3 offset(0.f, 0.f, 0.f); - LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE); + LLVector3 offset(0.f, 0.f, 0.f); + LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE); } @@ -4643,121 +4643,121 @@ void handle_duplicate_in_place(void*) * No longer able to support viewer side manipulations in this way * void god_force_inv_owner_permissive(LLViewerObject* object, - LLInventoryObject::object_list_t* inventory, - S32 serial_num, - void*) -{ - typedef std::vector > item_array_t; - item_array_t items; - - LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin(); - LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end(); - for ( ; inv_it != inv_end; ++inv_it) - { - if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY)) - { - LLInventoryObject* obj = *inv_it; - LLPointer new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj); - LLPermissions perm(new_item->getPermissions()); - perm.setMaskBase(PERM_ALL); - perm.setMaskOwner(PERM_ALL); - new_item->setPermissions(perm); - items.push_back(new_item); - } - } - item_array_t::iterator end = items.end(); - item_array_t::iterator it; - for(it = items.begin(); it != end; ++it) - { - // since we have the inventory item in the callback, it should not - // invalidate iteration through the selection manager. - object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false); - } + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void*) +{ + typedef std::vector > item_array_t; + item_array_t items; + + LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin(); + LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end(); + for ( ; inv_it != inv_end; ++inv_it) + { + if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY)) + { + LLInventoryObject* obj = *inv_it; + LLPointer new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj); + LLPermissions perm(new_item->getPermissions()); + perm.setMaskBase(PERM_ALL); + perm.setMaskOwner(PERM_ALL); + new_item->setPermissions(perm); + items.push_back(new_item); + } + } + item_array_t::iterator end = items.end(); + item_array_t::iterator it; + for(it = items.begin(); it != end; ++it) + { + // since we have the inventory item in the callback, it should not + // invalidate iteration through the selection manager. + object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false); + } } */ void handle_object_owner_permissive(void*) { - // only send this if they're a god. - if(gAgent.isGodlike()) - { - // do the objects. - LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE); - LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE); - } + // only send this if they're a god. + if(gAgent.isGodlike()) + { + // do the objects. + LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE); + LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE); + } } void handle_object_owner_self(void*) { - // only send this if they're a god. - if(gAgent.isGodlike()) - { - LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE); - } + // only send this if they're a god. + if(gAgent.isGodlike()) + { + LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID(), TRUE); + } } // Shortcut to set owner permissions to not editable. void handle_object_lock(void*) { - LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY); + LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY); } void handle_object_asset_ids(void*) { - // only send this if they're a god. - if (gAgent.isGodlike()) - { - LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids"); - } + // only send this if they're a god. + if (gAgent.isGodlike()) + { + LLSelectMgr::getInstance()->sendGodlikeRequest("objectinfo", "assetids"); + } } void handle_force_parcel_owner_to_me(void*) { - LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() ); + LLViewerParcelMgr::getInstance()->sendParcelGodForceOwner( gAgent.getID() ); } void handle_force_parcel_to_content(void*) { - LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent(); + LLViewerParcelMgr::getInstance()->sendParcelGodForceToContent(); } void handle_claim_public_land(void*) { - if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion()) - { - LLNotificationsUtil::add("ClaimPublicLand"); - return; - } - - LLVector3d west_south_global; - LLVector3d east_north_global; - LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global); - LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global); - LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("GodlikeMessage"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used - msg->nextBlock("MethodData"); - msg->addString("Method", "claimpublicland"); - msg->addUUID("Invoice", LLUUID::null); - std::string buffer; - buffer = llformat( "%f", west_south.mV[VX]); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buffer); - buffer = llformat( "%f", west_south.mV[VY]); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buffer); - buffer = llformat( "%f", east_north.mV[VX]); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buffer); - buffer = llformat( "%f", east_north.mV[VY]); - msg->nextBlock("ParamList"); - msg->addString("Parameter", buffer); - gAgent.sendReliableMessage(); + if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion()) + { + LLNotificationsUtil::add("ClaimPublicLand"); + return; + } + + LLVector3d west_south_global; + LLVector3d east_north_global; + LLViewerParcelMgr::getInstance()->getSelection(west_south_global, east_north_global); + LLVector3 west_south = gAgent.getPosAgentFromGlobal(west_south_global); + LLVector3 east_north = gAgent.getPosAgentFromGlobal(east_north_global); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("GodlikeMessage"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null); //not used + msg->nextBlock("MethodData"); + msg->addString("Method", "claimpublicland"); + msg->addUUID("Invoice", LLUUID::null); + std::string buffer; + buffer = llformat( "%f", west_south.mV[VX]); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buffer); + buffer = llformat( "%f", west_south.mV[VY]); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buffer); + buffer = llformat( "%f", east_north.mV[VX]); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buffer); + buffer = llformat( "%f", east_north.mV[VY]); + msg->nextBlock("ParamList"); + msg->addString("Parameter", buffer); + gAgent.sendReliableMessage(); } @@ -4765,286 +4765,286 @@ void handle_claim_public_land(void*) // HACK for easily testing new avatar geometry void handle_god_request_avatar_geometry(void *) { - if (gAgent.isGodlike()) - { - LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", ""); - } + if (gAgent.isGodlike()) + { + LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", ""); + } } static bool get_derezzable_objects( - EDeRezDestination dest, - std::string& error, - LLViewerRegion*& first_region, - std::vector* derez_objectsp, - bool only_check = false) -{ - bool found = false; - - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (derez_objectsp) - derez_objectsp->reserve(selection->getRootObjectCount()); - - // Check conditions that we can't deal with, building a list of - // everything that we'll actually be derezzing. - for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin(); - iter != selection->valid_root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - LLViewerRegion* region = object->getRegion(); - if (!first_region) - { - first_region = region; - } - else - { - if(region != first_region) - { - // Derez doesn't work at all if the some of the objects - // are in regions besides the first object selected. - - // ...crosses region boundaries - error = "AcquireErrorObjectSpan"; - break; - } - } - if (object->isAvatar()) - { - // ...don't acquire avatars - continue; - } - - // If AssetContainers are being sent back, they will appear as - // boxes in the owner's inventory. - if (object->getNVPair("AssetContainer") - && dest != DRD_RETURN_TO_OWNER) - { - // this object is an asset container, derez its contents, not it - LL_WARNS() << "Attempt to derez deprecated AssetContainer object type not supported." << LL_ENDL; - /* - object->requestInventory(container_inventory_arrived, - (void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest)); - */ - continue; - } - BOOL can_derez_current = FALSE; - switch(dest) - { - case DRD_TAKE_INTO_AGENT_INVENTORY: - case DRD_TRASH: - if (!object->isPermanentEnforced() && - ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) - || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)))) - { - can_derez_current = TRUE; - } - break; - - case DRD_RETURN_TO_OWNER: - if(!object->isAttachment()) - { - can_derez_current = TRUE; - } - break; - - default: - if((node->mPermissions->allowTransferTo(gAgent.getID()) - && object->permCopy()) - || gAgent.isGodlike()) - { - can_derez_current = TRUE; - } - break; - } - if(can_derez_current) - { - found = true; - - if (only_check) - // one found, no need to traverse to the end - break; - - if (derez_objectsp) - derez_objectsp->push_back(object); - - } - } - - return found; + EDeRezDestination dest, + std::string& error, + LLViewerRegion*& first_region, + std::vector* derez_objectsp, + bool only_check = false) +{ + bool found = false; + + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (derez_objectsp) + derez_objectsp->reserve(selection->getRootObjectCount()); + + // Check conditions that we can't deal with, building a list of + // everything that we'll actually be derezzing. + for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin(); + iter != selection->valid_root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + LLViewerRegion* region = object->getRegion(); + if (!first_region) + { + first_region = region; + } + else + { + if(region != first_region) + { + // Derez doesn't work at all if the some of the objects + // are in regions besides the first object selected. + + // ...crosses region boundaries + error = "AcquireErrorObjectSpan"; + break; + } + } + if (object->isAvatar()) + { + // ...don't acquire avatars + continue; + } + + // If AssetContainers are being sent back, they will appear as + // boxes in the owner's inventory. + if (object->getNVPair("AssetContainer") + && dest != DRD_RETURN_TO_OWNER) + { + // this object is an asset container, derez its contents, not it + LL_WARNS() << "Attempt to derez deprecated AssetContainer object type not supported." << LL_ENDL; + /* + object->requestInventory(container_inventory_arrived, + (void *)(BOOL)(DRD_TAKE_INTO_AGENT_INVENTORY == dest)); + */ + continue; + } + BOOL can_derez_current = FALSE; + switch(dest) + { + case DRD_TAKE_INTO_AGENT_INVENTORY: + case DRD_TRASH: + if (!object->isPermanentEnforced() && + ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) + || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)))) + { + can_derez_current = TRUE; + } + break; + + case DRD_RETURN_TO_OWNER: + if(!object->isAttachment()) + { + can_derez_current = TRUE; + } + break; + + default: + if((node->mPermissions->allowTransferTo(gAgent.getID()) + && object->permCopy()) + || gAgent.isGodlike()) + { + can_derez_current = TRUE; + } + break; + } + if(can_derez_current) + { + found = true; + + if (only_check) + // one found, no need to traverse to the end + break; + + if (derez_objectsp) + derez_objectsp->push_back(object); + + } + } + + return found; } static bool can_derez(EDeRezDestination dest) { - LLViewerRegion* first_region = NULL; - std::string error; - return get_derezzable_objects(dest, error, first_region, NULL, true); + LLViewerRegion* first_region = NULL; + std::string error; + return get_derezzable_objects(dest, error, first_region, NULL, true); } static void derez_objects( - EDeRezDestination dest, - const LLUUID& dest_id, - LLViewerRegion*& first_region, - std::string& error, - std::vector* objectsp) -{ - std::vector derez_objects; - - if (!objectsp) // if objects to derez not specified - { - // get them from selection - if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false)) - { - LL_WARNS() << "No objects to derez" << LL_ENDL; - return; - } - - objectsp = &derez_objects; - } - - - if(gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - - // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per - // root. I lopped off a few (33) to provide a bit - // pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs. - // This gives us a maximum of 63500 root objects - which should - // satisfy anybody. - const S32 MAX_ROOTS_PER_PACKET = 250; - const S32 MAX_PACKET_COUNT = 254; - F32 packets = ceil((F32)objectsp->size() / (F32)MAX_ROOTS_PER_PACKET); - if(packets > (F32)MAX_PACKET_COUNT) - { - error = "AcquireErrorTooManyObjects"; - } - - if(error.empty() && objectsp->size() > 0) - { - U8 d = (U8)dest; - LLUUID tid; - tid.generate(); - U8 packet_count = (U8)packets; - S32 object_index = 0; - S32 objects_in_packet = 0; - LLMessageSystem* msg = gMessageSystem; - for(U8 packet_number = 0; - packet_number < packet_count; - ++packet_number) - { - msg->newMessageFast(_PREHASH_DeRezObject); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_AgentBlock); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - msg->addU8Fast(_PREHASH_Destination, d); - msg->addUUIDFast(_PREHASH_DestinationID, dest_id); - msg->addUUIDFast(_PREHASH_TransactionID, tid); - msg->addU8Fast(_PREHASH_PacketCount, packet_count); - msg->addU8Fast(_PREHASH_PacketNumber, packet_number); - objects_in_packet = 0; - while((object_index < objectsp->size()) - && (objects_in_packet++ < MAX_ROOTS_PER_PACKET)) - - { - LLViewerObject* object = objectsp->at(object_index++); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); - // VEFFECT: DerezObject - LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal(object->getPositionGlobal()); - effectp->setColor(LLColor4U(gAgent.getEffectColor())); - } - msg->sendReliable(first_region->getHost()); - } - make_ui_sound("UISndObjectRezOut"); - - // Busy count decremented by inventory update, so only increment - // if will be causing an update. - if (dest != DRD_RETURN_TO_OWNER) - { - gViewerWindow->getWindow()->incBusyCount(); - } - } - else if(!error.empty()) - { - LLNotificationsUtil::add(error); - } + EDeRezDestination dest, + const LLUUID& dest_id, + LLViewerRegion*& first_region, + std::string& error, + std::vector* objectsp) +{ + std::vector derez_objects; + + if (!objectsp) // if objects to derez not specified + { + // get them from selection + if (!get_derezzable_objects(dest, error, first_region, &derez_objects, false)) + { + LL_WARNS() << "No objects to derez" << LL_ENDL; + return; + } + + objectsp = &derez_objects; + } + + + if(gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); + } + + // This constant is based on (1200 - HEADER_SIZE) / 4 bytes per + // root. I lopped off a few (33) to provide a bit + // pad. HEADER_SIZE is currently 67 bytes, most of which is UUIDs. + // This gives us a maximum of 63500 root objects - which should + // satisfy anybody. + const S32 MAX_ROOTS_PER_PACKET = 250; + const S32 MAX_PACKET_COUNT = 254; + F32 packets = ceil((F32)objectsp->size() / (F32)MAX_ROOTS_PER_PACKET); + if(packets > (F32)MAX_PACKET_COUNT) + { + error = "AcquireErrorTooManyObjects"; + } + + if(error.empty() && objectsp->size() > 0) + { + U8 d = (U8)dest; + LLUUID tid; + tid.generate(); + U8 packet_count = (U8)packets; + S32 object_index = 0; + S32 objects_in_packet = 0; + LLMessageSystem* msg = gMessageSystem; + for(U8 packet_number = 0; + packet_number < packet_count; + ++packet_number) + { + msg->newMessageFast(_PREHASH_DeRezObject); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_AgentBlock); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + msg->addU8Fast(_PREHASH_Destination, d); + msg->addUUIDFast(_PREHASH_DestinationID, dest_id); + msg->addUUIDFast(_PREHASH_TransactionID, tid); + msg->addU8Fast(_PREHASH_PacketCount, packet_count); + msg->addU8Fast(_PREHASH_PacketNumber, packet_number); + objects_in_packet = 0; + while((object_index < objectsp->size()) + && (objects_in_packet++ < MAX_ROOTS_PER_PACKET)) + + { + LLViewerObject* object = objectsp->at(object_index++); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, object->getLocalID()); + // VEFFECT: DerezObject + LLHUDEffectSpiral* effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); + effectp->setPositionGlobal(object->getPositionGlobal()); + effectp->setColor(LLColor4U(gAgent.getEffectColor())); + } + msg->sendReliable(first_region->getHost()); + } + make_ui_sound("UISndObjectRezOut"); + + // Busy count decremented by inventory update, so only increment + // if will be causing an update. + if (dest != DRD_RETURN_TO_OWNER) + { + gViewerWindow->getWindow()->incBusyCount(); + } + } + else if(!error.empty()) + { + LLNotificationsUtil::add(error); + } } static void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) { - LLViewerRegion* first_region = NULL; - std::string error; - derez_objects(dest, dest_id, first_region, error, NULL); + LLViewerRegion* first_region = NULL; + std::string error; + derez_objects(dest, dest_id, first_region, error, NULL); } void handle_take_copy() { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; - const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); - derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); + const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); + derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); } void handle_link_objects() { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - LLFloaterReg::toggleInstanceOrBringToFront("places"); - } - else - { - LLSelectMgr::getInstance()->linkObjects(); - } + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + LLFloaterReg::toggleInstanceOrBringToFront("places"); + } + else + { + LLSelectMgr::getInstance()->linkObjects(); + } } // You can return an object to its owner if it is on your land. class LLObjectReturn : public view_listener_t { public: - LLObjectReturn() : mFirstRegion(NULL) {} + LLObjectReturn() : mFirstRegion(NULL) {} private: - bool handleEvent(const LLSD& userdata) - { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; - - mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + bool handleEvent(const LLSD& userdata) + { + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return true; + + mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); - // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. - get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects); + // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. + get_derezzable_objects(DRD_RETURN_TO_OWNER, mError, mFirstRegion, &mReturnableObjects); - LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); - return true; - } + LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); + return true; + } - bool onReturnToOwner(const LLSD& notification, const LLSD& response) - { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - // Ignore category ID for this derez destination. - derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects); - } + bool onReturnToOwner(const LLSD& notification, const LLSD& response) + { + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + // Ignore category ID for this derez destination. + derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, mFirstRegion, mError, &mReturnableObjects); + } - mReturnableObjects.clear(); - mError.clear(); - mFirstRegion = NULL; + mReturnableObjects.clear(); + mError.clear(); + mFirstRegion = NULL; - // drop reference to current selection - mObjectSelection = NULL; - return false; - } + // drop reference to current selection + mObjectSelection = NULL; + return false; + } - LLObjectSelectionHandle mObjectSelection; + LLObjectSelectionHandle mObjectSelection; - std::vector mReturnableObjects; - std::string mError; - LLViewerRegion* mFirstRegion; + std::vector mReturnableObjects; + std::string mError; + LLViewerRegion* mFirstRegion; }; @@ -5052,187 +5052,187 @@ private: // over land you own. class LLObjectEnableReturn : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - // Do not enable if nothing selected - return false; - } + bool handleEvent(const LLSD& userdata) + { + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + // Do not enable if nothing selected + return false; + } #ifdef HACKED_GODLIKE_VIEWER - bool new_value = true; + bool new_value = true; #else - bool new_value = false; - if (gAgent.isGodlike()) - { - new_value = true; - } - else - { - new_value = can_derez(DRD_RETURN_TO_OWNER); - } + bool new_value = false; + if (gAgent.isGodlike()) + { + new_value = true; + } + else + { + new_value = can_derez(DRD_RETURN_TO_OWNER); + } #endif - return new_value; - } + return new_value; + } }; void force_take_copy(void*) { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; - const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); - derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id); + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; + const LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); + derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id); } void handle_take() { - // we want to use the folder this was derezzed from if it's - // available. Otherwise, derez to the normal place. - if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - return; - } - - BOOL you_own_everything = TRUE; - BOOL locked_but_takeable_object = FALSE; - LLUUID category_id; - - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if(object) - { - if(!object->permYouOwner()) - { - you_own_everything = FALSE; - } - - if(!object->permMove()) - { - locked_but_takeable_object = TRUE; - } - } - if(node->mFolderID.notNull()) - { - if(category_id.isNull()) - { - category_id = node->mFolderID; - } - else if(category_id != node->mFolderID) - { - // we have found two potential destinations. break out - // now and send to the default location. - category_id.setNull(); - break; - } - } - } - if(category_id.notNull()) - { - // there is an unambiguous destination. See if this agent has - // such a location and it is not in the trash or library - if(!gInventory.getCategory(category_id)) - { - // nope, set to NULL. - category_id.setNull(); - } - if(category_id.notNull()) - { - // check trash - const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash)) - { - category_id.setNull(); - } - - // check library - if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID())) - { - category_id.setNull(); - } - - // check inbox - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); - if (category_id == inbox_id || gInventory.isObjectDescendentOf(category_id, inbox_id)) - { - category_id.setNull(); - } - } - } - if(category_id.isNull()) - { - category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); - } - LLSD payload; - payload["folder_id"] = category_id; - - LLNotification::Params params("ConfirmObjectTakeLock"); - params.payload(payload); - // MAINT-290 - // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. - // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened - params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection())); - - if(locked_but_takeable_object || - !you_own_everything) - { - if(locked_but_takeable_object && you_own_everything) - { - params.name("ConfirmObjectTakeLock"); - } - else if(!locked_but_takeable_object && !you_own_everything) - { - params.name("ConfirmObjectTakeNoOwn"); - } - else - { - params.name("ConfirmObjectTakeLockNoOwn"); - } - - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } + // we want to use the folder this was derezzed from if it's + // available. Otherwise, derez to the normal place. + if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + return; + } + + BOOL you_own_everything = TRUE; + BOOL locked_but_takeable_object = FALSE; + LLUUID category_id; + + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if(object) + { + if(!object->permYouOwner()) + { + you_own_everything = FALSE; + } + + if(!object->permMove()) + { + locked_but_takeable_object = TRUE; + } + } + if(node->mFolderID.notNull()) + { + if(category_id.isNull()) + { + category_id = node->mFolderID; + } + else if(category_id != node->mFolderID) + { + // we have found two potential destinations. break out + // now and send to the default location. + category_id.setNull(); + break; + } + } + } + if(category_id.notNull()) + { + // there is an unambiguous destination. See if this agent has + // such a location and it is not in the trash or library + if(!gInventory.getCategory(category_id)) + { + // nope, set to NULL. + category_id.setNull(); + } + if(category_id.notNull()) + { + // check trash + const LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash)) + { + category_id.setNull(); + } + + // check library + if(gInventory.isObjectDescendentOf(category_id, gInventory.getLibraryRootFolderID())) + { + category_id.setNull(); + } + + // check inbox + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); + if (category_id == inbox_id || gInventory.isObjectDescendentOf(category_id, inbox_id)) + { + category_id.setNull(); + } + } + } + if(category_id.isNull()) + { + category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); + } + LLSD payload; + payload["folder_id"] = category_id; + + LLNotification::Params params("ConfirmObjectTakeLock"); + params.payload(payload); + // MAINT-290 + // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. + // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened + params.functor.function(boost::bind(confirm_take, _1, _2, LLSelectMgr::instance().getSelection())); + + if(locked_but_takeable_object || + !you_own_everything) + { + if(locked_but_takeable_object && you_own_everything) + { + params.name("ConfirmObjectTakeLock"); + } + else if(!locked_but_takeable_object && !you_own_everything) + { + params.name("ConfirmObjectTakeNoOwn"); + } + else + { + params.name("ConfirmObjectTakeLockNoOwn"); + } + + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } } void handle_object_show_inspector() { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - LLViewerObject* objectp = selection->getFirstRootObject(TRUE); - if (!objectp) - { - return; - } + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* objectp = selection->getFirstRootObject(TRUE); + if (!objectp) + { + return; + } - LLSD params; - params["object_id"] = objectp->getID(); - LLFloaterReg::showInstance("inspect_object", params); + LLSD params; + params["object_id"] = objectp->getID(); + LLFloaterReg::showInstance("inspect_object", params); } void handle_avatar_show_inspector() { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLSD params; - params["avatar_id"] = avatar->getID(); - LLFloaterReg::showInstance("inspect_avatar", params); - } + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLSD params; + params["avatar_id"] = avatar->getID(); + LLFloaterReg::showInstance("inspect_avatar", params); + } } bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if(enable_take() && (option == 0)) - { - derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID()); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(enable_take() && (option == 0)) + { + derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID()); + } + return false; } // You can take an item when it is public and transferrable, or when @@ -5240,101 +5240,101 @@ bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelect // one item selected can be copied to inventory. BOOL enable_take() { - if (sitting_on_selection()) - { - return FALSE; - } - - for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - if (object->isAvatar()) - { - // ...don't acquire avatars - continue; - } + if (sitting_on_selection()) + { + return FALSE; + } + + for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if (object->isAvatar()) + { + // ...don't acquire avatars + continue; + } #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && gAgent.isGodlike()) - { - return TRUE; - } + { + return TRUE; + } # endif - if(!object->isPermanentEnforced() && - ((node->mPermissions->allowTransferTo(gAgent.getID()) - && object->permModify()) - || (node->mPermissions->getOwner() == gAgent.getID()))) - { - return !object->isAttachment(); - } + if(!object->isPermanentEnforced() && + ((node->mPermissions->allowTransferTo(gAgent.getID()) + && object->permModify()) + || (node->mPermissions->getOwner() == gAgent.getID()))) + { + return !object->isAttachment(); + } #endif - } - return FALSE; + } + return FALSE; } void handle_buy_or_take() { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - return; - } - - if (is_selection_buy_not_take()) - { - S32 total_price = selection_price(); - - if (total_price <= gStatusBar->getBalance() || total_price == 0) - { - handle_buy(); - } - else - { - LLStringUtil::format_map_t args; - args["AMOUNT"] = llformat("%d", total_price); - LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price ); - } - } - else - { - handle_take(); - } + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + return; + } + + if (is_selection_buy_not_take()) + { + S32 total_price = selection_price(); + + if (total_price <= gStatusBar->getBalance() || total_price == 0) + { + handle_buy(); + } + else + { + LLStringUtil::format_map_t args; + args["AMOUNT"] = llformat("%d", total_price); + LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString( "this_object_costs", args ), total_price ); + } + } + else + { + handle_take(); + } } bool visible_buy_object() { - return is_selection_buy_not_take() && enable_buy_object(); + return is_selection_buy_not_take() && enable_buy_object(); } bool visible_take_object() { - return !is_selection_buy_not_take() && enable_take(); + return !is_selection_buy_not_take() && enable_take(); } bool tools_visible_buy_object() { - return is_selection_buy_not_take(); + return is_selection_buy_not_take(); } bool tools_visible_take_object() { - return !is_selection_buy_not_take(); + return !is_selection_buy_not_take(); } class LLToolsEnableBuyOrTake : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool is_buy = is_selection_buy_not_take(); - bool new_value = is_buy ? enable_buy_object() : enable_take(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool is_buy = is_selection_buy_not_take(); + bool new_value = is_buy ? enable_buy_object() : enable_take(); + return new_value; + } }; // This is a small helper function to determine if we have a buy or a @@ -5355,255 +5355,255 @@ class LLToolsEnableBuyOrTake : public view_listener_t // FALSE if selection is a 'take' BOOL is_selection_buy_not_take() { - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* obj = node->getObject(); - if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) - { - // you do not own the object and it is for sale, thus, - // it's a buy - return TRUE; - } - } - return FALSE; + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* obj = node->getObject(); + if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) + { + // you do not own the object and it is for sale, thus, + // it's a buy + return TRUE; + } + } + return FALSE; } S32 selection_price() { - S32 total_price = 0; - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* obj = node->getObject(); - if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) - { - // you do not own the object and it is for sale. - // Add its price. - total_price += node->mSaleInfo.getSalePrice(); - } - } - - return total_price; + S32 total_price = 0; + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* obj = node->getObject(); + if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) + { + // you do not own the object and it is for sale. + // Add its price. + total_price += node->mSaleInfo.getSalePrice(); + } + } + + return total_price; } /* bool callback_show_buy_currency(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - LL_INFOS() << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << LL_ENDL; - LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LL_INFOS() << "Loading page " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL") << LL_ENDL; + LLWeb::loadURL(LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")); + } + return false; } */ void show_buy_currency(const char* extra) { - // Don't show currency web page for branded clients. + // Don't show currency web page for branded clients. /* - std::ostringstream mesg; - if (extra != NULL) - { - mesg << extra << "\n \n"; - } - mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?"; + std::ostringstream mesg; + if (extra != NULL) + { + mesg << extra << "\n \n"; + } + mesg << "Go to " << LLNotifications::instance().getGlobalString("BUY_CURRENCY_URL")<< "\nfor information on purchasing currency?"; */ - LLSD args; - if (extra != NULL) - { - args["EXTRA"] = extra; - } - LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency); + LLSD args; + if (extra != NULL) + { + args["EXTRA"] = extra; + } + LLNotificationsUtil::add("PromptGoToCurrencyPage", args);//, LLSD(), callback_show_buy_currency); } void handle_buy() { - if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return; - LLSaleInfo sale_info; - BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); - if (!valid) return; + LLSaleInfo sale_info; + BOOL valid = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); + if (!valid) return; - S32 price = sale_info.getSalePrice(); - - if (price > 0 && price > gStatusBar->getBalance()) - { - LLStringUtil::format_map_t args; - args["AMOUNT"] = llformat("%d", price); - LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price ); - return; - } + S32 price = sale_info.getSalePrice(); - if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS) - { - handle_buy_contents(sale_info); - } - else - { - handle_buy_object(sale_info); - } + if (price > 0 && price > gStatusBar->getBalance()) + { + LLStringUtil::format_map_t args; + args["AMOUNT"] = llformat("%d", price); + LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("this_object_costs", args), price ); + return; + } + + if (sale_info.getSaleType() == LLSaleInfo::FS_CONTENTS) + { + handle_buy_contents(sale_info); + } + else + { + handle_buy_object(sale_info); + } } bool anyone_copy_selection(LLSelectNode* nodep) { - bool perm_copy = (bool)(nodep->getObject()->permCopy()); - bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY); - return perm_copy && all_copy; + bool perm_copy = (bool)(nodep->getObject()->permCopy()); + bool all_copy = (bool)(nodep->mPermissions->getMaskEveryone() & PERM_COPY); + return perm_copy && all_copy; } bool for_sale_selection(LLSelectNode* nodep) { - return nodep->mSaleInfo.isForSale() - && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER - && (nodep->mPermissions->getMaskOwner() & PERM_COPY - || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY); + return nodep->mSaleInfo.isForSale() + && nodep->mPermissions->getMaskOwner() & PERM_TRANSFER + && (nodep->mPermissions->getMaskOwner() & PERM_COPY + || nodep->mSaleInfo.getSaleType() != LLSaleInfo::FS_COPY); } BOOL sitting_on_selection() { - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (!node) - { - return FALSE; - } + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (!node) + { + return FALSE; + } - if (!node->mValid) - { - return FALSE; - } + if (!node->mValid) + { + return FALSE; + } - LLViewerObject* root_object = node->getObject(); - if (!root_object) - { - return FALSE; - } + LLViewerObject* root_object = node->getObject(); + if (!root_object) + { + return FALSE; + } - // Need to determine if avatar is sitting on this object - if (!isAgentAvatarValid()) return FALSE; + // Need to determine if avatar is sitting on this object + if (!isAgentAvatarValid()) return FALSE; - return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object); + return (gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == root_object); } class LLToolsSaveToObjectInventory : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if(node && (node->mValid) && (!node->mFromTaskID.isNull())) - { - // *TODO: check to see if the fromtaskid object exists. - derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if(node && (node->mValid) && (!node->mFromTaskID.isNull())) + { + // *TODO: check to see if the fromtaskid object exists. + derez_objects(DRD_SAVE_INTO_TASK_INVENTORY, node->mFromTaskID); + } + return true; + } }; class LLToolsEnablePathfinding : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); - } + bool handleEvent(const LLSD& userdata) + { + return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); + } }; class LLToolsEnablePathfindingView : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); - } + bool handleEvent(const LLSD& userdata) + { + return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); + } }; class LLToolsDoPathfindingRebakeRegion : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL); + bool handleEvent(const LLSD& userdata) + { + bool hasPathfinding = (LLPathfindingManager::getInstance() != NULL); - if (hasPathfinding) - { - LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); - } + if (hasPathfinding) + { + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); + } - return hasPathfinding; - } + return hasPathfinding; + } }; class LLToolsEnablePathfindingRebakeRegion : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool returnValue = false; + bool handleEvent(const LLSD& userdata) + { + bool returnValue = false; if (LLNavigationBar::instanceExists()) { returnValue = LLNavigationBar::getInstance()->isRebakeNavMeshAvailable(); } - return returnValue; - } + return returnValue; + } }; // Round the position of all root objects to the grid class LLToolsSnapObjectXY : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - F64 snap_size = (F64)gSavedSettings.getF32("GridResolution"); - - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* obj = node->getObject(); - if (obj->permModify()) - { - LLVector3d pos_global = obj->getPositionGlobal(); - F64 round_x = fmod(pos_global.mdV[VX], snap_size); - if (round_x < snap_size * 0.5) - { - // closer to round down - pos_global.mdV[VX] -= round_x; - } - else - { - // closer to round up - pos_global.mdV[VX] -= round_x; - pos_global.mdV[VX] += snap_size; - } - - F64 round_y = fmod(pos_global.mdV[VY], snap_size); - if (round_y < snap_size * 0.5) - { - pos_global.mdV[VY] -= round_y; - } - else - { - pos_global.mdV[VY] -= round_y; - pos_global.mdV[VY] += snap_size; - } - - obj->setPositionGlobal(pos_global, FALSE); - } - } - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); - return true; - } -}; + bool handleEvent(const LLSD& userdata) + { + F64 snap_size = (F64)gSavedSettings.getF32("GridResolution"); + + for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* obj = node->getObject(); + if (obj->permModify()) + { + LLVector3d pos_global = obj->getPositionGlobal(); + F64 round_x = fmod(pos_global.mdV[VX], snap_size); + if (round_x < snap_size * 0.5) + { + // closer to round down + pos_global.mdV[VX] -= round_x; + } + else + { + // closer to round up + pos_global.mdV[VX] -= round_x; + pos_global.mdV[VX] += snap_size; + } + + F64 round_y = fmod(pos_global.mdV[VY], snap_size); + if (round_y < snap_size * 0.5) + { + pos_global.mdV[VY] -= round_y; + } + else + { + pos_global.mdV[VY] -= round_y; + pos_global.mdV[VY] += snap_size; + } + + obj->setPositionGlobal(pos_global, FALSE); + } + } + LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); + return true; + } +}; // Determine if the option to cycle between linked prims is shown class LLToolsEnableSelectNextPart : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { bool new_value = (!LLSelectMgr::getInstance()->getSelection()->isEmpty() && (gSavedSettings.getBOOL("EditLinkedParts") || LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool())); - return new_value; - } + return new_value; + } }; // Cycle selection through linked children or/and faces in selected object. @@ -5678,61 +5678,61 @@ class LLToolsSelectNextPartFace : public view_listener_t } } - S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - if (cycle_linked && object_count && restart_face_on_part) - { - LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if (selected && selected->getRootEdit()) - { - LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); - children.push_front(selected->getRootEdit()); // need root in the list too - - for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter) - { - if ((*iter)->isSelected()) - { - if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include - { - to_select = *iter; - if (fwd) - { - // stop searching if going forward; repeat to get last hit if backward - break; - } - } - else if ((object_count == 1) || (ifwd || iprev)) // single selection or include - { - if (fwd || ifwd) - { - ++iter; - while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected()))) - { - ++iter; // skip sitting avatars and selected if include - } - } - else // backward - { - iter = (iter == children.begin() ? children.end() : iter); - --iter; - while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected()))) - { - --iter; // skip sitting avatars and selected if include - } - } - iter = (iter == children.end() ? children.begin() : iter); - to_select = *iter; - break; - } - } - } - } - } + S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (cycle_linked && object_count && restart_face_on_part) + { + LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + if (selected && selected->getRootEdit()) + { + LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); + children.push_front(selected->getRootEdit()); // need root in the list too + + for (LLViewerObject::child_list_t::iterator iter = children.begin(); iter != children.end(); ++iter) + { + if ((*iter)->isSelected()) + { + if (object_count > 1 && (fwd || prev)) // multiple selection, find first or last selected if not include + { + to_select = *iter; + if (fwd) + { + // stop searching if going forward; repeat to get last hit if backward + break; + } + } + else if ((object_count == 1) || (ifwd || iprev)) // single selection or include + { + if (fwd || ifwd) + { + ++iter; + while (iter != children.end() && ((*iter)->isAvatar() || (ifwd && (*iter)->isSelected()))) + { + ++iter; // skip sitting avatars and selected if include + } + } + else // backward + { + iter = (iter == children.begin() ? children.end() : iter); + --iter; + while (iter != children.begin() && ((*iter)->isAvatar() || (iprev && (*iter)->isSelected()))) + { + --iter; // skip sitting avatars and selected if include + } + } + iter = (iter == children.end() ? children.begin() : iter); + to_select = *iter; + break; + } + } + } + } + } if (to_select) { if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) { - gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes + gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes } if (fwd || prev) { @@ -5760,455 +5760,455 @@ class LLToolsSelectNextPartFace : public view_listener_t } return true; } - return true; - } + return true; + } }; class LLToolsStopAllAnimations : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgent.stopCurrentAnimations(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gAgent.stopCurrentAnimations(); + return true; + } }; class LLToolsReleaseKeys : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgent.forceReleaseControls(); + bool handleEvent(const LLSD& userdata) + { + gAgent.forceReleaseControls(); - return true; - } + return true; + } }; class LLToolsEnableReleaseKeys : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gAgent.anyControlGrabbed(); - } + bool handleEvent(const LLSD& userdata) + { + return gAgent.anyControlGrabbed(); + } }; class LLEditEnableCut : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCut(); + return new_value; + } }; class LLEditCut : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler ) - { - LLEditMenuHandler::gEditMenuHandler->cut(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler ) + { + LLEditMenuHandler::gEditMenuHandler->cut(); + } + return true; + } }; class LLEditEnableCopy : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canCopy(); + return new_value; + } }; class LLEditCopy : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler ) - { - LLEditMenuHandler::gEditMenuHandler->copy(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler ) + { + LLEditMenuHandler::gEditMenuHandler->copy(); + } + return true; + } }; class LLEditEnablePaste : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canPaste(); + return new_value; + } }; class LLEditPaste : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler ) - { - LLEditMenuHandler::gEditMenuHandler->paste(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler ) + { + LLEditMenuHandler::gEditMenuHandler->paste(); + } + return true; + } }; class LLEditEnableDelete : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete(); + return new_value; + } }; class LLEditDelete : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // If a text field can do a deletion, it gets precedence over deleting - // an object in the world. - if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) - { - LLEditMenuHandler::gEditMenuHandler->doDelete(); - } + bool handleEvent(const LLSD& userdata) + { + // If a text field can do a deletion, it gets precedence over deleting + // an object in the world. + if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDoDelete()) + { + LLEditMenuHandler::gEditMenuHandler->doDelete(); + } - // and close any pie/context menus when done - gMenuHolder->hideMenus(); + // and close any pie/context menus when done + gMenuHolder->hideMenus(); - // When deleting an object we may not actually be done - // Keep selection so we know what to delete when confirmation is needed about the delete - gMenuObject->hide(); - return true; - } + // When deleting an object we may not actually be done + // Keep selection so we know what to delete when confirmation is needed about the delete + gMenuObject->hide(); + return true; + } }; void handle_spellcheck_replace_with_suggestion(const LLUICtrl* ctrl, const LLSD& param) { - const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); - LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) - { - return; - } + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return; + } - U32 index = 0; - if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) - { - return; - } + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return; + } - spellcheck_handler->replaceWithSuggestion(index); + spellcheck_handler->replaceWithSuggestion(index); } bool visible_spellcheck_suggestion(LLUICtrl* ctrl, const LLSD& param) { - LLMenuItemGL* item = dynamic_cast(ctrl); - const LLContextMenu* menu = (item) ? dynamic_cast(item->getParent()) : NULL; - const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) - { - return false; - } + LLMenuItemGL* item = dynamic_cast(ctrl); + const LLContextMenu* menu = (item) ? dynamic_cast(item->getParent()) : NULL; + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + if ( (!spellcheck_handler) || (!spellcheck_handler->getSpellCheck()) ) + { + return false; + } - U32 index = 0; - if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) - { - return false; - } + U32 index = 0; + if ( (!LLStringUtil::convertToU32(param.asString(), index)) || (index >= spellcheck_handler->getSuggestionCount()) ) + { + return false; + } - item->setLabel(spellcheck_handler->getSuggestion(index)); - return true; + item->setLabel(spellcheck_handler->getSuggestion(index)); + return true; } void handle_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) { - const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); - LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) ) - { - spellcheck_handler->addToDictionary(); - } + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()) ) + { + spellcheck_handler->addToDictionary(); + } } bool enable_spellcheck_add_to_dictionary(const LLUICtrl* ctrl) { - const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); - const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToDictionary()); } void handle_spellcheck_add_to_ignore(const LLUICtrl* ctrl) { - const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); - LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) ) - { - spellcheck_handler->addToIgnore(); - } + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + if ( (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()) ) + { + spellcheck_handler->addToIgnore(); + } } bool enable_spellcheck_add_to_ignore(const LLUICtrl* ctrl) { - const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); - const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; - return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); + const LLContextMenu* menu = dynamic_cast(ctrl->getParent()); + const LLSpellCheckMenuHandler* spellcheck_handler = (menu) ? dynamic_cast(menu->getSpawningView()) : NULL; + return (spellcheck_handler) && (spellcheck_handler->canAddToIgnore()); } bool enable_object_return() { - return (!LLSelectMgr::getInstance()->getSelection()->isEmpty() && - (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER))); + return (!LLSelectMgr::getInstance()->getSelection()->isEmpty() && + (gAgent.isGodlike() || can_derez(DRD_RETURN_TO_OWNER))); } bool enable_object_delete() { - bool new_value = + bool new_value = #ifdef HACKED_GODLIKE_VIEWER - TRUE; + TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - (!LLGridManager::getInstance()->isInProductionGrid() + (!LLGridManager::getInstance()->isInProductionGrid() && gAgent.isGodlike()) || # endif - LLSelectMgr::getInstance()->canDoDelete(); + LLSelectMgr::getInstance()->canDoDelete(); #endif - return new_value; + return new_value; } class LLObjectsReturnPackage { public: - LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(NULL) {}; - ~LLObjectsReturnPackage() - { - mObjectSelection.clear(); - mReturnableObjects.clear(); - mError.clear(); - mFirstRegion = NULL; - }; + LLObjectsReturnPackage() : mObjectSelection(), mReturnableObjects(), mError(), mFirstRegion(NULL) {}; + ~LLObjectsReturnPackage() + { + mObjectSelection.clear(); + mReturnableObjects.clear(); + mError.clear(); + mFirstRegion = NULL; + }; - LLObjectSelectionHandle mObjectSelection; - std::vector mReturnableObjects; - std::string mError; - LLViewerRegion *mFirstRegion; + LLObjectSelectionHandle mObjectSelection; + std::vector mReturnableObjects; + std::string mError; + LLViewerRegion *mFirstRegion; }; static void return_objects(LLObjectsReturnPackage *objectsReturnPackage, const LLSD& notification, const LLSD& response) { - if (LLNotificationsUtil::getSelectedOption(notification, response) == 0) - { - // Ignore category ID for this derez destination. - derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, objectsReturnPackage->mFirstRegion, objectsReturnPackage->mError, &objectsReturnPackage->mReturnableObjects); - } + if (LLNotificationsUtil::getSelectedOption(notification, response) == 0) + { + // Ignore category ID for this derez destination. + derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null, objectsReturnPackage->mFirstRegion, objectsReturnPackage->mError, &objectsReturnPackage->mReturnableObjects); + } - delete objectsReturnPackage; + delete objectsReturnPackage; } void handle_object_return() { - if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - LLObjectsReturnPackage *objectsReturnPackage = new LLObjectsReturnPackage(); - objectsReturnPackage->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + LLObjectsReturnPackage *objectsReturnPackage = new LLObjectsReturnPackage(); + objectsReturnPackage->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); - // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. - get_derezzable_objects(DRD_RETURN_TO_OWNER, objectsReturnPackage->mError, objectsReturnPackage->mFirstRegion, &objectsReturnPackage->mReturnableObjects); + // Save selected objects, so that we still know what to return after the confirmation dialog resets selection. + get_derezzable_objects(DRD_RETURN_TO_OWNER, objectsReturnPackage->mError, objectsReturnPackage->mFirstRegion, &objectsReturnPackage->mReturnableObjects); - LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&return_objects, objectsReturnPackage, _1, _2)); - } + LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&return_objects, objectsReturnPackage, _1, _2)); + } } void handle_object_delete() { - if (LLSelectMgr::getInstance()) - { - LLSelectMgr::getInstance()->doDelete(); - } + if (LLSelectMgr::getInstance()) + { + LLSelectMgr::getInstance()->doDelete(); + } - // and close any pie/context menus when done - gMenuHolder->hideMenus(); + // and close any pie/context menus when done + gMenuHolder->hideMenus(); - // When deleting an object we may not actually be done - // Keep selection so we know what to delete when confirmation is needed about the delete - gMenuObject->hide(); - return; + // When deleting an object we may not actually be done + // Keep selection so we know what to delete when confirmation is needed about the delete + gMenuObject->hide(); + return; } void handle_force_delete(void*) { - LLSelectMgr::getInstance()->selectForceDelete(); + LLSelectMgr::getInstance()->selectForceDelete(); } class LLViewEnableJoystickFlycam : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled")); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = (gSavedSettings.getBOOL("JoystickEnabled") && gSavedSettings.getBOOL("JoystickFlycamEnabled")); + return new_value; + } }; class LLViewEnableLastChatter : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // *TODO: add check that last chatter is in range - bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull()); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + // *TODO: add check that last chatter is in range + bool new_value = (gAgentCamera.cameraThirdPerson() && gAgent.getLastChatter().notNull()); + return new_value; + } }; class LLEditEnableDeselect : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canDeselect(); + return new_value; + } }; class LLEditDeselect : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler ) - { - LLEditMenuHandler::gEditMenuHandler->deselect(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler ) + { + LLEditMenuHandler::gEditMenuHandler->deselect(); + } + return true; + } }; class LLEditEnableSelectAll : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canSelectAll(); + return new_value; + } }; class LLEditSelectAll : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler ) - { - LLEditMenuHandler::gEditMenuHandler->selectAll(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler ) + { + LLEditMenuHandler::gEditMenuHandler->selectAll(); + } + return true; + } }; class LLEditEnableUndo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo(); + return new_value; + } }; class LLEditUndo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() ) - { - LLEditMenuHandler::gEditMenuHandler->undo(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canUndo() ) + { + LLEditMenuHandler::gEditMenuHandler->undo(); + } + return true; + } }; class LLEditEnableRedo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo(); + return new_value; + } }; class LLEditRedo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() ) - { - LLEditMenuHandler::gEditMenuHandler->redo(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if( LLEditMenuHandler::gEditMenuHandler && LLEditMenuHandler::gEditMenuHandler->canRedo() ) + { + LLEditMenuHandler::gEditMenuHandler->redo(); + } + return true; + } }; void print_object_info(void*) { - LLSelectMgr::getInstance()->selectionDump(); + LLSelectMgr::getInstance()->selectionDump(); } void print_agent_nvpairs(void*) { - LLViewerObject *objectp; + LLViewerObject *objectp; - LL_INFOS() << "Agent Name Value Pairs" << LL_ENDL; + LL_INFOS() << "Agent Name Value Pairs" << LL_ENDL; - objectp = gObjectList.findObject(gAgentID); - if (objectp) - { - objectp->printNameValuePairs(); - } - else - { - LL_INFOS() << "Can't find agent object" << LL_ENDL; - } + objectp = gObjectList.findObject(gAgentID); + if (objectp) + { + objectp->printNameValuePairs(); + } + else + { + LL_INFOS() << "Can't find agent object" << LL_ENDL; + } - LL_INFOS() << "Camera at " << gAgentCamera.getCameraPositionGlobal() << LL_ENDL; + LL_INFOS() << "Camera at " << gAgentCamera.getCameraPositionGlobal() << LL_ENDL; } void show_debug_menus() { - // this might get called at login screen where there is no menu so only toggle it if one exists - if ( gMenuBarView ) - { - BOOL debug = gSavedSettings.getBOOL("UseDebugMenus"); - BOOL qamode = gSavedSettings.getBOOL("QAMode"); - - gMenuBarView->setItemVisible("Advanced", debug); -// gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden - - gMenuBarView->setItemVisible("Debug", qamode); - gMenuBarView->setItemEnabled("Debug", qamode); - - gMenuBarView->setItemVisible("Develop", qamode); - gMenuBarView->setItemEnabled("Develop", qamode); - - // Server ('Admin') menu hidden when not in godmode. - const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride())); - gMenuBarView->setItemVisible("Admin", show_server_menu); - gMenuBarView->setItemEnabled("Admin", show_server_menu); - } - if (gLoginMenuBarView) - { - BOOL debug = gSavedSettings.getBOOL("UseDebugMenus"); - gLoginMenuBarView->setItemVisible("Debug", debug); - gLoginMenuBarView->setItemEnabled("Debug", debug); - } + // this might get called at login screen where there is no menu so only toggle it if one exists + if ( gMenuBarView ) + { + BOOL debug = gSavedSettings.getBOOL("UseDebugMenus"); + BOOL qamode = gSavedSettings.getBOOL("QAMode"); + + gMenuBarView->setItemVisible("Advanced", debug); +// gMenuBarView->setItemEnabled("Advanced", debug); // Don't disable Advanced keyboard shortcuts when hidden + + gMenuBarView->setItemVisible("Debug", qamode); + gMenuBarView->setItemEnabled("Debug", qamode); + + gMenuBarView->setItemVisible("Develop", qamode); + gMenuBarView->setItemEnabled("Develop", qamode); + + // Server ('Admin') menu hidden when not in godmode. + const bool show_server_menu = (gAgent.getGodLevel() > GOD_NOT || (debug && gAgent.getAdminOverride())); + gMenuBarView->setItemVisible("Admin", show_server_menu); + gMenuBarView->setItemEnabled("Admin", show_server_menu); + } + if (gLoginMenuBarView) + { + BOOL debug = gSavedSettings.getBOOL("UseDebugMenus"); + gLoginMenuBarView->setItemVisible("Debug", debug); + gLoginMenuBarView->setItemEnabled("Debug", debug); + } } void toggle_debug_menus(void*) { - BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus"); - gSavedSettings.setBOOL("UseDebugMenus", visible); - show_debug_menus(); + BOOL visible = ! gSavedSettings.getBOOL("UseDebugMenus"); + gSavedSettings.setBOOL("UseDebugMenus", visible); + show_debug_menus(); } @@ -6219,299 +6219,299 @@ void toggle_debug_menus(void*) // void handle_export_selected( void * ) // { -// LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); -// if (selection->isEmpty()) -// { -// return; -// } -// LL_INFOS() << "Exporting selected objects:" << LL_ENDL; - -// gExporterRequestID.generate(); -// gExportDirectory = ""; - -// LLMessageSystem* msg = gMessageSystem; -// msg->newMessageFast(_PREHASH_ObjectExportSelected); -// msg->nextBlockFast(_PREHASH_AgentData); -// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -// msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID); -// msg->addS16Fast(_PREHASH_VolumeDetail, 4); - -// for (LLObjectSelection::root_iterator iter = selection->root_begin(); -// iter != selection->root_end(); iter++) -// { -// LLSelectNode* node = *iter; -// LLViewerObject* object = node->getObject(); -// msg->nextBlockFast(_PREHASH_ObjectData); -// msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); -// LL_INFOS() << "Object: " << object->getID() << LL_ENDL; -// } -// msg->sendReliable(gAgent.getRegion()->getHost()); - -// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects..."); +// LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); +// if (selection->isEmpty()) +// { +// return; +// } +// LL_INFOS() << "Exporting selected objects:" << LL_ENDL; + +// gExporterRequestID.generate(); +// gExportDirectory = ""; + +// LLMessageSystem* msg = gMessageSystem; +// msg->newMessageFast(_PREHASH_ObjectExportSelected); +// msg->nextBlockFast(_PREHASH_AgentData); +// msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +// msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID); +// msg->addS16Fast(_PREHASH_VolumeDetail, 4); + +// for (LLObjectSelection::root_iterator iter = selection->root_begin(); +// iter != selection->root_end(); iter++) +// { +// LLSelectNode* node = *iter; +// LLViewerObject* object = node->getObject(); +// msg->nextBlockFast(_PREHASH_ObjectData); +// msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); +// LL_INFOS() << "Object: " << object->getID() << LL_ENDL; +// } +// msg->sendReliable(gAgent.getRegion()->getHost()); + +// gExportDialog = LLUploadDialog::modalUploadDialog("Exporting selected objects..."); // } // class LLCommunicateNearbyChat : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance(); + bool handleEvent(const LLSD& userdata) + { + LLFloaterIMContainer* im_box = LLFloaterIMContainer::getInstance(); LLFloaterIMNearbyChat* floater_nearby = LLFloaterReg::getTypedInstance("nearby_chat"); - if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff() + if (floater_nearby->isInVisibleChain() && !floater_nearby->isTornOff() && im_box->getSelectedSession() == LLUUID() && im_box->getConversationListItemSize() > 1) - { - im_box->selectNextorPreviousConversation(false); - } - else - { - LLFloaterReg::toggleInstanceOrBringToFront("nearby_chat"); - } - return true; - } + { + im_box->selectNextorPreviousConversation(false); + } + else + { + LLFloaterReg::toggleInstanceOrBringToFront("nearby_chat"); + } + return true; + } }; class LLWorldSetHomeLocation : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // we just send the message and let the server check for failure cases - // server will echo back a "Home position set." alert if it succeeds - // and the home location screencapture happens when that alert is recieved - gAgent.setStartPosition(START_LOCATION_ID_HOME); - return true; - } + bool handleEvent(const LLSD& userdata) + { + // we just send the message and let the server check for failure cases + // server will echo back a "Home position set." alert if it succeeds + // and the home location screencapture happens when that alert is recieved + gAgent.setStartPosition(START_LOCATION_ID_HOME); + return true; + } }; class LLWorldLindenHome : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url"); - LLWeb::loadURL(url); - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string url = LLFloaterLandHoldings::sHasLindenHome ? LLTrans::getString("lindenhomes_my_home_url") : LLTrans::getString("lindenhomes_get_home_url"); + LLWeb::loadURL(url); + return true; + } }; class LLWorldTeleportHome : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gAgent.teleportHome(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gAgent.teleportHome(); + return true; + } }; class LLWorldAlwaysRun : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // as well as altering the default walk-vs-run state, - // we also change the *current* walk-vs-run state. - if (gAgent.getAlwaysRun()) - { - gAgent.clearAlwaysRun(); - gAgent.clearRunning(); - } - else - { - gAgent.setAlwaysRun(); - gAgent.setRunning(); - } + bool handleEvent(const LLSD& userdata) + { + // as well as altering the default walk-vs-run state, + // we also change the *current* walk-vs-run state. + if (gAgent.getAlwaysRun()) + { + gAgent.clearAlwaysRun(); + gAgent.clearRunning(); + } + else + { + gAgent.setAlwaysRun(); + gAgent.setRunning(); + } - // tell the simulator. - gAgent.sendWalkRun(gAgent.getAlwaysRun()); + // tell the simulator. + gAgent.sendWalkRun(gAgent.getAlwaysRun()); - // Update Movement Controls according to AlwaysRun mode - LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun()); + // Update Movement Controls according to AlwaysRun mode + LLFloaterMove::setAlwaysRunMode(gAgent.getAlwaysRun()); - return true; - } + return true; + } }; class LLWorldCheckAlwaysRun : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gAgent.getAlwaysRun(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gAgent.getAlwaysRun(); + return new_value; + } }; class LLWorldSetAway : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgent.getAFK()) - { - gAgent.clearAFK(); - } - else - { - gAgent.setAFK(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgent.getAFK()) + { + gAgent.clearAFK(); + } + else + { + gAgent.setAFK(); + } + return true; + } }; class LLWorldSetDoNotDisturb : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgent.isDoNotDisturb()) - { - gAgent.setDoNotDisturb(false); - } - else - { - gAgent.setDoNotDisturb(true); - LLNotificationsUtil::add("DoNotDisturbModeSet"); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgent.isDoNotDisturb()) + { + gAgent.setDoNotDisturb(false); + } + else + { + gAgent.setDoNotDisturb(true); + LLNotificationsUtil::add("DoNotDisturbModeSet"); + } + return true; + } }; class LLWorldCreateLandmark : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterReg::showInstance("add_landmark"); + bool handleEvent(const LLSD& userdata) + { + LLFloaterReg::showInstance("add_landmark"); - return true; - } + return true; + } }; class LLWorldPlaceProfile : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent")); + bool handleEvent(const LLSD& userdata) + { + LLFloaterSidePanelContainer::showPanel("places", LLSD().with("type", "agent")); - return true; - } + return true; + } }; void handle_look_at_selection(const LLSD& param) { - const F32 PADDING_FACTOR = 1.75f; - BOOL zoom = (param.asString() == "zoom"); - if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) - { - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - - LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); - F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); - F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); - - LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent(); - obj_to_cam.normVec(); - - LLUUID object_id; - if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) - { - object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID; - } - if (zoom) - { - // Make sure we are not increasing the distance between the camera and object - LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal(); - distance = llmin(distance, (F32) orig_distance.length()); - - gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), - LLSelectMgr::getInstance()->getSelectionCenterGlobal(), - object_id ); - - } - else - { - gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); - } - } + const F32 PADDING_FACTOR = 1.75f; + BOOL zoom = (param.asString() == "zoom"); + if (!LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection(); + F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); + F32 distance = selection_bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); + + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - selection_bbox.getCenterAgent(); + obj_to_cam.normVec(); + + LLUUID object_id; + if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) + { + object_id = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()->mID; + } + if (zoom) + { + // Make sure we are not increasing the distance between the camera and object + LLVector3d orig_distance = gAgentCamera.getCameraPositionGlobal() - LLSelectMgr::getInstance()->getSelectionCenterGlobal(); + distance = llmin(distance, (F32) orig_distance.length()); + + gAgentCamera.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), + LLSelectMgr::getInstance()->getSelectionCenterGlobal(), + object_id ); + + } + else + { + gAgentCamera.setFocusGlobal( LLSelectMgr::getInstance()->getSelectionCenterGlobal(), object_id ); + } + } } void handle_zoom_to_object(LLUUID object_id) { - const F32 PADDING_FACTOR = 2.f; + const F32 PADDING_FACTOR = 2.f; - LLViewerObject* object = gObjectList.findObject(object_id); + LLViewerObject* object = gObjectList.findObject(object_id); - if (object) - { - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + if (object) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - LLBBox bbox = object->getBoundingBoxAgent() ; - F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); - F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); + LLBBox bbox = object->getBoundingBoxAgent() ; + F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); + F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); - LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); - obj_to_cam.normVec(); + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); + obj_to_cam.normVec(); - LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); + LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); - gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), - object_center_global, - object_id ); - } + gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), + object_center_global, + object_id ); + } } class LLAvatarInviteToGroup : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLAvatarActions::inviteToGroup(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLAvatarActions::inviteToGroup(avatar->getID()); + } + return true; + } }; class LLAvatarAddFriend : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar && !LLAvatarActions::isFriend(avatar->getID())) - { - request_friendship(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar && !LLAvatarActions::isFriend(avatar->getID())) + { + request_friendship(avatar->getID()); + } + return true; + } }; class LLAvatarToggleMyProfile : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - LLFloater* instance = LLAvatarActions::getProfileFloater(gAgent.getID()); - if (LLFloater::isMinimized(instance)) - { - instance->setMinimized(FALSE); - instance->setFocus(TRUE); - } - else if (!LLFloater::isShown(instance)) - { - LLAvatarActions::showProfile(gAgent.getID()); - } - else if (!instance->hasFocus() && !instance->getIsChrome()) - { - instance->setFocus(TRUE); - } - else - { - instance->closeFloater(); - } - return true; - } -}; - -class LLAvatarTogglePicks : public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLFloater * instance = LLAvatarActions::getProfileFloater(gAgent.getID()); + LLFloater* instance = LLAvatarActions::getProfileFloater(gAgent.getID()); + if (LLFloater::isMinimized(instance)) + { + instance->setMinimized(FALSE); + instance->setFocus(TRUE); + } + else if (!LLFloater::isShown(instance)) + { + LLAvatarActions::showProfile(gAgent.getID()); + } + else if (!instance->hasFocus() && !instance->getIsChrome()) + { + instance->setFocus(TRUE); + } + else + { + instance->closeFloater(); + } + return true; + } +}; + +class LLAvatarTogglePicks : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + LLFloater * instance = LLAvatarActions::getProfileFloater(gAgent.getID()); if (LLFloater::isMinimized(instance) || (instance && !instance->hasFocus() && !instance->getIsChrome())) { instance->setMinimized(FALSE); @@ -6532,41 +6532,41 @@ class LLAvatarTogglePicks : public view_listener_t class LLAvatarToggleSearch : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloater* instance = LLFloaterReg::findInstance("search"); - if (LLFloater::isMinimized(instance)) - { - instance->setMinimized(FALSE); - instance->setFocus(TRUE); - } - else if (!LLFloater::isShown(instance)) - { - LLFloaterReg::showInstance("search"); - } - else if (!instance->hasFocus() && !instance->getIsChrome()) - { - instance->setFocus(TRUE); - } - else - { - instance->closeFloater(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloater* instance = LLFloaterReg::findInstance("search"); + if (LLFloater::isMinimized(instance)) + { + instance->setMinimized(FALSE); + instance->setFocus(TRUE); + } + else if (!LLFloater::isShown(instance)) + { + LLFloaterReg::showInstance("search"); + } + else if (!instance->hasFocus() && !instance->getIsChrome()) + { + instance->setFocus(TRUE); + } + else + { + instance->closeFloater(); + } + return true; + } }; class LLAvatarResetSkeleton: public view_listener_t { bool handleEvent(const LLSD& userdata) { - LLVOAvatar* avatar = NULL; + LLVOAvatar* avatar = NULL; LLViewerObject *obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); if (obj) { avatar = obj->getAvatar(); } - if(avatar) + if(avatar) { avatar->resetSkeleton(false); } @@ -6590,184 +6590,184 @@ class LLAvatarEnableResetSkeleton: public view_listener_t class LLAvatarResetSkeletonAndAnimations : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - if (avatar) - { - avatar->resetSkeleton(true); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) + { + avatar->resetSkeleton(true); + } + return true; + } }; class LLAvatarResetSelfSkeletonAndAnimations : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); - if (avatar) - { - avatar->resetSkeleton(true); - } - else - { - gAgentAvatarp->resetSkeleton(true); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object(LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()); + if (avatar) + { + avatar->resetSkeleton(true); + } + else + { + gAgentAvatarp->resetSkeleton(true); + } + return true; + } }; class LLAvatarAddContact : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - create_inventory_callingcard(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + create_inventory_callingcard(avatar->getID()); + } + return true; + } }; bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option == 0) - { - gAgent.setDoNotDisturb(false); - } - - LLViewerObject* objectp = selection->getPrimaryObject(); - - // Show avatar's name if paying attachment - if (objectp && objectp->isAttachment()) - { - while (objectp && !objectp->isAvatar()) - { - objectp = (LLViewerObject*)objectp->getParent(); - } - } - - if (objectp) - { - if (objectp->isAvatar()) - { - const bool is_group = false; - LLFloaterPayUtil::payDirectly(&give_money, - objectp->getID(), - is_group); - } - else - { - LLFloaterPayUtil::payViaObject(&give_money, selection); - } - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + gAgent.setDoNotDisturb(false); + } + + LLViewerObject* objectp = selection->getPrimaryObject(); + + // Show avatar's name if paying attachment + if (objectp && objectp->isAttachment()) + { + while (objectp && !objectp->isAvatar()) + { + objectp = (LLViewerObject*)objectp->getParent(); + } + } + + if (objectp) + { + if (objectp->isAvatar()) + { + const bool is_group = false; + LLFloaterPayUtil::payDirectly(&give_money, + objectp->getID(), + is_group); + } + else + { + LLFloaterPayUtil::payViaObject(&give_money, selection); + } + } + return false; } void handle_give_money_dialog() { - LLNotification::Params params("DoNotDisturbModePay"); - params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); + LLNotification::Params params("DoNotDisturbModePay"); + params.functor.function(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection())); - if (gAgent.isDoNotDisturb()) - { - // warn users of being in do not disturb mode during a transaction - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 1); - } + if (gAgent.isDoNotDisturb()) + { + // warn users of being in do not disturb mode during a transaction + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 1); + } } bool enable_pay_avatar() { - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - LLVOAvatar* avatar = find_avatar_from_object(obj); - return (avatar != NULL); + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLVOAvatar* avatar = find_avatar_from_object(obj); + return (avatar != NULL); } bool enable_pay_object() { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if( object ) - { - LLViewerObject *parent = (LLViewerObject *)object->getParent(); - if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) - { - return true; - } - } - return false; + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if( object ) + { + LLViewerObject *parent = (LLViewerObject *)object->getParent(); + if((object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) + { + return true; + } + } + return false; } bool enable_object_stand_up() { - // 'Object Stand Up' menu item is enabled when agent is sitting on selection - return sitting_on_selection(); + // 'Object Stand Up' menu item is enabled when agent is sitting on selection + return sitting_on_selection(); } bool enable_object_sit(LLUICtrl* ctrl) { - // 'Object Sit' menu item is enabled when agent is not sitting on selection - bool sitting_on_sel = sitting_on_selection(); - if (!sitting_on_sel) - { - // init default labels - init_default_item_label(ctrl); - - // Update label - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if (node && node->mValid && !node->mSitName.empty()) - { - ctrl->setValue(node->mSitName); - } - else - { - ctrl->setValue(get_default_item_label(ctrl->getName())); - } - } - return !sitting_on_sel && is_object_sittable(); + // 'Object Sit' menu item is enabled when agent is not sitting on selection + bool sitting_on_sel = sitting_on_selection(); + if (!sitting_on_sel) + { + // init default labels + init_default_item_label(ctrl); + + // Update label + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if (node && node->mValid && !node->mSitName.empty()) + { + ctrl->setValue(node->mSitName); + } + else + { + ctrl->setValue(get_default_item_label(ctrl->getName())); + } + } + return !sitting_on_sel && is_object_sittable(); } void dump_select_mgr(void*) { - LLSelectMgr::getInstance()->dump(); + LLSelectMgr::getInstance()->dump(); } void dump_inventory(void*) { - gInventory.dumpInventory(); + gInventory.dumpInventory(); } void handle_dump_followcam(void*) { - LLFollowCamMgr::getInstance()->dump(); + LLFollowCamMgr::getInstance()->dump(); } void handle_viewer_enable_message_log(void*) { - gMessageSystem->startLogging(); + gMessageSystem->startLogging(); } void handle_viewer_disable_message_log(void*) { - gMessageSystem->stopLogging(); + gMessageSystem->stopLogging(); } void handle_customize_avatar() { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "my_outfits")); } void handle_edit_outfit() { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_outfit")); } void handle_now_wearing() @@ -6784,225 +6784,225 @@ void handle_now_wearing() void handle_edit_shape() { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape")); + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_shape")); } void handle_hover_height() { - LLFloaterReg::showInstance("edit_hover_height"); + LLFloaterReg::showInstance("edit_hover_height"); } void handle_edit_physics() { - LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics")); + LLFloaterSidePanelContainer::showPanel("appearance", LLSD().with("type", "edit_physics")); } void handle_report_abuse() { - // Prevent menu from appearing in screen shot. - gMenuHolder->hideMenus(); - LLFloaterReporter::showFromMenu(COMPLAINT_REPORT); + // Prevent menu from appearing in screen shot. + gMenuHolder->hideMenus(); + LLFloaterReporter::showFromMenu(COMPLAINT_REPORT); } void handle_buy_currency() { - LLBuyCurrencyHTML::openCurrencyFloater(); + LLBuyCurrencyHTML::openCurrencyFloater(); } class LLFloaterVisible : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string floater_name = userdata.asString(); - bool new_value = false; - { - new_value = LLFloaterReg::instanceVisible(floater_name); - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + std::string floater_name = userdata.asString(); + bool new_value = false; + { + new_value = LLFloaterReg::instanceVisible(floater_name); + } + return new_value; + } }; class LLShowHelp : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string help_topic = userdata.asString(); - LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - vhelp->showTopic(help_topic); - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string help_topic = userdata.asString(); + LLViewerHelp* vhelp = LLViewerHelp::getInstance(); + vhelp->showTopic(help_topic); + return true; + } }; class LLToggleHelp : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser")); - if (help_browser && help_browser->isInVisibleChain()) - { - help_browser->closeFloater(); - } - else - { - std::string help_topic = userdata.asString(); - LLViewerHelp* vhelp = LLViewerHelp::getInstance(); - vhelp->showTopic(help_topic); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloater* help_browser = (LLFloaterReg::findInstance("help_browser")); + if (help_browser && help_browser->isInVisibleChain()) + { + help_browser->closeFloater(); + } + else + { + std::string help_topic = userdata.asString(); + LLViewerHelp* vhelp = LLViewerHelp::getInstance(); + vhelp->showTopic(help_topic); + } + return true; + } }; class LLToggleSpeak : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVoiceClient::getInstance()->toggleUserPTTState(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVoiceClient::getInstance()->toggleUserPTTState(); + return true; + } }; class LLShowSidetrayPanel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string floater_name = userdata.asString(); - - LLPanel* panel = LLFloaterSidePanelContainer::getPanel(floater_name); - if (panel) - { - if (panel->isInVisibleChain()) - { - LLFloaterReg::getInstance(floater_name)->closeFloater(); - } - else - { - LLFloaterReg::getInstance(floater_name)->openFloater(); - } - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string floater_name = userdata.asString(); + + LLPanel* panel = LLFloaterSidePanelContainer::getPanel(floater_name); + if (panel) + { + if (panel->isInVisibleChain()) + { + LLFloaterReg::getInstance(floater_name)->closeFloater(); + } + else + { + LLFloaterReg::getInstance(floater_name)->openFloater(); + } + } + return true; + } }; class LLSidetrayPanelVisible : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string floater_name = userdata.asString(); - // Toggle the panel - if (LLFloaterReg::getInstance(floater_name)->isInVisibleChain()) - { - return true; - } - else - { - return false; - } - - } + bool handleEvent(const LLSD& userdata) + { + std::string floater_name = userdata.asString(); + // Toggle the panel + if (LLFloaterReg::getInstance(floater_name)->isInVisibleChain()) + { + return true; + } + else + { + return false; + } + + } }; bool callback_show_url(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - LLWeb::loadURL(notification["payload"]["url"].asString()); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LLWeb::loadURL(notification["payload"]["url"].asString()); + } + return false; } class LLPromptShowURL : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string param = userdata.asString(); - std::string::size_type offset = param.find(","); - if (offset != param.npos) - { - std::string alert = param.substr(0, offset); - std::string url = param.substr(offset+1); - - if (LLWeb::useExternalBrowser(url)) - { - LLSD payload; - payload["url"] = url; - LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url); - } - else - { - LLWeb::loadURL(url); - } - } - else - { - LL_INFOS() << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << LL_ENDL; - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string param = userdata.asString(); + std::string::size_type offset = param.find(","); + if (offset != param.npos) + { + std::string alert = param.substr(0, offset); + std::string url = param.substr(offset+1); + + if (LLWeb::useExternalBrowser(url)) + { + LLSD payload; + payload["url"] = url; + LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_url); + } + else + { + LLWeb::loadURL(url); + } + } + else + { + LL_INFOS() << "PromptShowURL invalid parameters! Expecting \"ALERT,URL\"." << LL_ENDL; + } + return true; + } }; bool callback_show_file(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (0 == option) - { - LLWeb::loadURL(notification["payload"]["url"]); - } - return false; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) + { + LLWeb::loadURL(notification["payload"]["url"]); + } + return false; } class LLPromptShowFile : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string param = userdata.asString(); - std::string::size_type offset = param.find(","); - if (offset != param.npos) - { - std::string alert = param.substr(0, offset); - std::string file = param.substr(offset+1); - - LLSD payload; - payload["url"] = file; - LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file); - } - else - { - LL_INFOS() << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << LL_ENDL; - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string param = userdata.asString(); + std::string::size_type offset = param.find(","); + if (offset != param.npos) + { + std::string alert = param.substr(0, offset); + std::string file = param.substr(offset+1); + + LLSD payload; + payload["url"] = file; + LLNotificationsUtil::add(alert, LLSD(), payload, callback_show_file); + } + else + { + LL_INFOS() << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << LL_ENDL; + } + return true; + } }; class LLShowAgentProfile : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLUUID agent_id; - if (userdata.asString() == "agent") - { - agent_id = gAgent.getID(); - } - else if (userdata.asString() == "hit object") - { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (objectp) - { - agent_id = objectp->getID(); - } - } - else - { - agent_id = userdata.asUUID(); - } - - LLVOAvatar* avatar = find_avatar_from_object(agent_id); - if (avatar) - { - LLAvatarActions::showProfile(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLUUID agent_id; + if (userdata.asString() == "agent") + { + agent_id = gAgent.getID(); + } + else if (userdata.asString() == "hit object") + { + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (objectp) + { + agent_id = objectp->getID(); + } + } + else + { + agent_id = userdata.asUUID(); + } + + LLVOAvatar* avatar = find_avatar_from_object(agent_id); + if (avatar) + { + LLAvatarActions::showProfile(avatar->getID()); + } + return true; + } }; class LLShowAgentProfilePicks : public view_listener_t @@ -7016,164 +7016,164 @@ class LLShowAgentProfilePicks : public view_listener_t class LLToggleAgentProfile : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLUUID agent_id; - if (userdata.asString() == "agent") - { - agent_id = gAgent.getID(); - } - else if (userdata.asString() == "hit object") - { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (objectp) - { - agent_id = objectp->getID(); - } - } - else - { - agent_id = userdata.asUUID(); - } - - LLVOAvatar* avatar = find_avatar_from_object(agent_id); - if (avatar) - { - if (!LLAvatarActions::profileVisible(avatar->getID())) - { - LLAvatarActions::showProfile(avatar->getID()); - } - else - { - LLAvatarActions::hideProfile(avatar->getID()); - } - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLUUID agent_id; + if (userdata.asString() == "agent") + { + agent_id = gAgent.getID(); + } + else if (userdata.asString() == "hit object") + { + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (objectp) + { + agent_id = objectp->getID(); + } + } + else + { + agent_id = userdata.asUUID(); + } + + LLVOAvatar* avatar = find_avatar_from_object(agent_id); + if (avatar) + { + if (!LLAvatarActions::profileVisible(avatar->getID())) + { + LLAvatarActions::showProfile(avatar->getID()); + } + else + { + LLAvatarActions::hideProfile(avatar->getID()); + } + } + return true; + } }; class LLLandEdit : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) - { - // zoom in if we're looking at the avatar - gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") ) + { + // zoom in if we're looking at the avatar + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gAgentCamera.cameraOrbitOver( F_PI * 0.25f ); - gViewerWindow->moveCursorToCenter(); - } - else if ( gSavedSettings.getBOOL("EditCameraMovement") ) - { - gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); - gViewerWindow->moveCursorToCenter(); - } + gAgentCamera.cameraOrbitOver( F_PI * 0.25f ); + gViewerWindow->moveCursorToCenter(); + } + else if ( gSavedSettings.getBOOL("EditCameraMovement") ) + { + gAgentCamera.setFocusGlobal(LLToolPie::getInstance()->getPick()); + gViewerWindow->moveCursorToCenter(); + } - LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal ); + LLViewerParcelMgr::getInstance()->selectParcelAt( LLToolPie::getInstance()->getPick().mPosGlobal ); - LLFloaterReg::showInstance("build"); + LLFloaterReg::showInstance("build"); - // Switch to land edit toolset - LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() ); - return true; - } + // Switch to land edit toolset + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolSelectLand::getInstance() ); + return true; + } }; class LLMuteParticle : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID; - - if (id.notNull()) - { - LLAvatarName av_name; - LLAvatarNameCache::get(id, &av_name); - - LLMute mute(id, av_name.getUserName(), LLMute::AGENT); - if (LLMuteList::getInstance()->isMuted(mute.mID)) - { - LLMuteList::getInstance()->remove(mute); - } - else - { - LLMuteList::getInstance()->add(mute); - LLPanelBlockedList::showPanelAndSelect(mute.mID); - } - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLUUID id = LLToolPie::getInstance()->getPick().mParticleOwnerID; + + if (id.notNull()) + { + LLAvatarName av_name; + LLAvatarNameCache::get(id, &av_name); + + LLMute mute(id, av_name.getUserName(), LLMute::AGENT); + if (LLMuteList::getInstance()->isMuted(mute.mID)) + { + LLMuteList::getInstance()->remove(mute); + } + else + { + LLMuteList::getInstance()->add(mute); + LLPanelBlockedList::showPanelAndSelect(mute.mID); + } + } + + return true; + } }; class LLWorldEnableBuyLand : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel( - LLViewerParcelMgr::getInstance()->selectionEmpty() - ? LLViewerParcelMgr::getInstance()->getAgentParcel() - : LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), - false); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLViewerParcelMgr::getInstance()->canAgentBuyParcel( + LLViewerParcelMgr::getInstance()->selectionEmpty() + ? LLViewerParcelMgr::getInstance()->getAgentParcel() + : LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), + false); + return new_value; + } }; BOOL enable_buy_land(void*) { - return LLViewerParcelMgr::getInstance()->canAgentBuyParcel( - LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false); + return LLViewerParcelMgr::getInstance()->canAgentBuyParcel( + LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel(), false); } void handle_buy_land() { - LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance(); - if (vpm->selectionEmpty()) - { - vpm->selectParcelAt(gAgent.getPositionGlobal()); - } - vpm->startBuyLand(); + LLViewerParcelMgr* vpm = LLViewerParcelMgr::getInstance(); + if (vpm->selectionEmpty()) + { + vpm->selectParcelAt(gAgent.getPositionGlobal()); + } + vpm->startBuyLand(); } class LLObjectAttachToAvatar : public view_listener_t { public: - LLObjectAttachToAvatar(bool replace) : mReplace(replace) {} - static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; } + LLObjectAttachToAvatar(bool replace) : mReplace(replace) {} + static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; } private: - bool handleEvent(const LLSD& userdata) - { - setObjectSelection(LLSelectMgr::getInstance()->getSelection()); - LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject(); - if (selectedObject) - { - S32 index = userdata.asInteger(); - LLViewerJointAttachment* attachment_point = NULL; - if (index > 0) - attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); - confirmReplaceAttachment(0, attachment_point); - } - return true; - } - - static void onNearAttachObject(BOOL success, void *user_data); - void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point); - class CallbackData : public LLSelectionCallbackData - { - public: - CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {} - - LLViewerJointAttachment* mAttachmentPoint; - bool mReplace; - }; + bool handleEvent(const LLSD& userdata) + { + setObjectSelection(LLSelectMgr::getInstance()->getSelection()); + LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject(); + if (selectedObject) + { + S32 index = userdata.asInteger(); + LLViewerJointAttachment* attachment_point = NULL; + if (index > 0) + attachment_point = get_if_there(gAgentAvatarp->mAttachmentPoints, index, (LLViewerJointAttachment*)NULL); + confirmReplaceAttachment(0, attachment_point); + } + return true; + } + + static void onNearAttachObject(BOOL success, void *user_data); + void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point); + class CallbackData : public LLSelectionCallbackData + { + public: + CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {} + + LLViewerJointAttachment* mAttachmentPoint; + bool mReplace; + }; protected: - static LLObjectSelectionHandle sObjectSelection; - bool mReplace; + static LLObjectSelectionHandle sObjectSelection; + bool mReplace; }; LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection; @@ -7181,238 +7181,238 @@ LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection; // static void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data) { - if (!user_data) return; - CallbackData* cb_data = static_cast(user_data); - - if (success) - { - const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint; - - U8 attachment_id = 0; - if (attachment) - { - for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); - iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) - { - if (iter->second == attachment) - { - attachment_id = iter->first; - break; - } - } - } - else - { - // interpret 0 as "default location" - attachment_id = 0; - } - LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace); - } - LLObjectAttachToAvatar::setObjectSelection(NULL); - - delete cb_data; + if (!user_data) return; + CallbackData* cb_data = static_cast(user_data); + + if (success) + { + const LLViewerJointAttachment *attachment = cb_data->mAttachmentPoint; + + U8 attachment_id = 0; + if (attachment) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); + iter != gAgentAvatarp->mAttachmentPoints.end(); ++iter) + { + if (iter->second == attachment) + { + attachment_id = iter->first; + break; + } + } + } + else + { + // interpret 0 as "default location" + attachment_id = 0; + } + LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace); + } + LLObjectAttachToAvatar::setObjectSelection(NULL); + + delete cb_data; } // static void LLObjectAttachToAvatar::confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point) { - if (option == 0/*YES*/) - { - LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); - if (selectedObject) - { - const F32 MIN_STOP_DISTANCE = 1.f; // meters - const F32 ARM_LENGTH = 0.5f; // meters - const F32 SCALE_FUDGE = 1.5f; - - F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH; - if (stop_distance < MIN_STOP_DISTANCE) - { - stop_distance = MIN_STOP_DISTANCE; - } - - LLVector3 walkToSpot = selectedObject->getPositionAgent(); - - // make sure we stop in front of the object - LLVector3 delta = walkToSpot - gAgent.getPositionAgent(); - delta.normVec(); - delta = delta * 0.5f; - walkToSpot -= delta; - - // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak. - CallbackData* user_data = new CallbackData(attachment_point, mReplace); - gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance); - gAgentCamera.clearFocusObject(); - } - } + if (option == 0/*YES*/) + { + LLViewerObject* selectedObject = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); + if (selectedObject) + { + const F32 MIN_STOP_DISTANCE = 1.f; // meters + const F32 ARM_LENGTH = 0.5f; // meters + const F32 SCALE_FUDGE = 1.5f; + + F32 stop_distance = SCALE_FUDGE * selectedObject->getMaxScale() + ARM_LENGTH; + if (stop_distance < MIN_STOP_DISTANCE) + { + stop_distance = MIN_STOP_DISTANCE; + } + + LLVector3 walkToSpot = selectedObject->getPositionAgent(); + + // make sure we stop in front of the object + LLVector3 delta = walkToSpot - gAgent.getPositionAgent(); + delta.normVec(); + delta = delta * 0.5f; + walkToSpot -= delta; + + // The callback will be called even if avatar fails to get close enough to the object, so we won't get a memory leak. + CallbackData* user_data = new CallbackData(attachment_point, mReplace); + gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(walkToSpot), "Attach", NULL, onNearAttachObject, user_data, stop_distance); + gAgentCamera.clearFocusObject(); + } + } } void callback_attachment_drop(const LLSD& notification, const LLSD& response) { - // Ensure user confirmed the drop - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; - - // Called when the user clicked on an object attached to them - // and selected "Drop". - LLUUID object_id = notification["payload"]["object_id"].asUUID(); - LLViewerObject *object = gObjectList.findObject(object_id); - - if (!object) - { - LL_WARNS() << "handle_drop_attachment() - no object to drop" << LL_ENDL; - return; - } - - LLViewerObject *parent = (LLViewerObject*)object->getParent(); - while (parent) - { - if(parent->isAvatar()) - { - break; - } - object = parent; - parent = (LLViewerObject*)parent->getParent(); - } - - if (!object) - { - LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; - return; - } - - if (object->isAvatar()) - { - LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; - return; - } - - // reselect the object - LLSelectMgr::getInstance()->selectObjectAndFamily(object); - - LLSelectMgr::getInstance()->sendDropAttachment(); - - return; + // Ensure user confirmed the drop + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; + + // Called when the user clicked on an object attached to them + // and selected "Drop". + LLUUID object_id = notification["payload"]["object_id"].asUUID(); + LLViewerObject *object = gObjectList.findObject(object_id); + + if (!object) + { + LL_WARNS() << "handle_drop_attachment() - no object to drop" << LL_ENDL; + return; + } + + LLViewerObject *parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if(parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + + if (!object) + { + LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; + return; + } + + if (object->isAvatar()) + { + LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; + return; + } + + // reselect the object + LLSelectMgr::getInstance()->selectObjectAndFamily(object); + + LLSelectMgr::getInstance()->sendDropAttachment(); + + return; } class LLAttachmentDrop : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLSD payload; - LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + bool handleEvent(const LLSD& userdata) + { + LLSD payload; + LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (object) - { - payload["object_id"] = object->getID(); - } - else - { - LL_WARNS() << "Drop object not found" << LL_ENDL; - return true; - } + if (object) + { + payload["object_id"] = object->getID(); + } + else + { + LL_WARNS() << "Drop object not found" << LL_ENDL; + return true; + } - LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop); - return true; - } + LLNotificationsUtil::add("AttachmentDrop", LLSD(), payload, &callback_attachment_drop); + return true; + } }; // called from avatar pie menu class LLAttachmentDetachFromPoint : public view_listener_t { - bool handleEvent(const LLSD& user_data) - { - uuid_vec_t ids_to_remove; - const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL); - if (attachment->getNumObjects() > 0) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin(); - iter != attachment->mAttachedObjects.end(); - iter++) - { - LLViewerObject *attached_object = iter->get(); - ids_to_remove.push_back(attached_object->getAttachmentItemID()); - } - } - if (!ids_to_remove.empty()) - { - LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); - } - return true; - } + bool handleEvent(const LLSD& user_data) + { + uuid_vec_t ids_to_remove; + const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL); + if (attachment->getNumObjects() > 0) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator iter = attachment->mAttachedObjects.begin(); + iter != attachment->mAttachedObjects.end(); + iter++) + { + LLViewerObject *attached_object = iter->get(); + ids_to_remove.push_back(attached_object->getAttachmentItemID()); + } + } + if (!ids_to_remove.empty()) + { + LLAppearanceMgr::instance().removeItemsFromAvatar(ids_to_remove); + } + return true; + } }; static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data) { - std::string label; - LLMenuItemGL* menu = dynamic_cast(ctrl); - if (menu) - { - const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL); - if (attachment) - { - label = data["label"].asString(); - for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object) - { - LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID()); - if (itemp) - { - label += std::string(" (") + itemp->getName() + std::string(")"); - break; - } - } - } - } - menu->setLabel(label); - } - return true; + std::string label; + LLMenuItemGL* menu = dynamic_cast(ctrl); + if (menu) + { + const LLViewerJointAttachment *attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL); + if (attachment) + { + label = data["label"].asString(); + for (LLViewerJointAttachment::attachedobjs_vec_t::const_iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + const LLViewerObject* attached_object = attachment_iter->get(); + if (attached_object) + { + LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID()); + if (itemp) + { + label += std::string(" (") + itemp->getName() + std::string(")"); + break; + } + } + } + } + menu->setLabel(label); + } + return true; } class LLAttachmentDetach : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // Called when the user clicked on an object attached to them - // and selected "Detach". - LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) - { - LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; - return true; - } - - LLViewerObject *parent = (LLViewerObject*)object->getParent(); - while (parent) - { - if(parent->isAvatar()) - { - break; - } - object = parent; - parent = (LLViewerObject*)parent->getParent(); - } - - if (!object) - { - LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; - return true; - } - - if (object->isAvatar()) - { - LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; - return true; - } - - LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID()); - - return true; - } + bool handleEvent(const LLSD& userdata) + { + // Called when the user clicked on an object attached to them + // and selected "Detach". + LLViewerObject *object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (!object) + { + LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; + return true; + } + + LLViewerObject *parent = (LLViewerObject*)object->getParent(); + while (parent) + { + if(parent->isAvatar()) + { + break; + } + object = parent; + parent = (LLViewerObject*)parent->getParent(); + } + + if (!object) + { + LL_WARNS() << "handle_detach() - no object to detach" << LL_ENDL; + return true; + } + + if (object->isAvatar()) + { + LL_WARNS() << "Trying to detach avatar from avatar." << LL_ENDL; + return true; + } + + LLAppearanceMgr::instance().removeItemFromAvatar(object->getAttachmentItemID()); + + return true; + } }; //Adding an observer for a Jira 2422 and needs to be a fetch observer @@ -7420,468 +7420,468 @@ class LLAttachmentDetach : public view_listener_t class LLWornItemFetchedObserver : public LLInventoryFetchItemsObserver { public: - LLWornItemFetchedObserver(const LLUUID& worn_item_id) : - LLInventoryFetchItemsObserver(worn_item_id) - {} - virtual ~LLWornItemFetchedObserver() {} + LLWornItemFetchedObserver(const LLUUID& worn_item_id) : + LLInventoryFetchItemsObserver(worn_item_id) + {} + virtual ~LLWornItemFetchedObserver() {} protected: - virtual void done() - { - gMenuAttachmentSelf->buildDrawLabels(); - gInventory.removeObserver(this); - delete this; - } + virtual void done() + { + gMenuAttachmentSelf->buildDrawLabels(); + gInventory.removeObserver(this); + delete this; + } }; // You can only drop items on parcels where you can build. class LLAttachmentEnableDrop : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); - - //Add an inventory observer to only allow dropping the newly attached item - //once it exists in your inventory. Look at Jira 2422. - //-jwolk - - // A bug occurs when you wear/drop an item before it actively is added to your inventory - // if this is the case (you're on a slow sim, etc.) a copy of the object, - // well, a newly created object with the same properties, is placed - // in your inventory. Therefore, we disable the drop option until the - // item is in your inventory - - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - LLViewerJointAttachment* attachment = NULL; - LLInventoryItem* item = NULL; - - // Do not enable drop if all faces of object are not enabled - if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) - { - S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState()); - attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); - - if (attachment) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - // make sure item is in your inventory (it could be a delayed attach message being sent from the sim) - // so check to see if the item is in the inventory already - item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID()); - if (!item) - { - // Item does not exist, make an observer to enable the pie menu - // when the item finishes fetching worst case scenario - // if a fetch is already out there (being sent from a slow sim) - // we refetch and there are 2 fetches - LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID()); - worn_item_fetched->startFetch(); - gInventory.addObserver(worn_item_fetched); - } - } - } - } - - //now check to make sure that the item is actually in the inventory before we enable dropping it - bool new_value = enable_detach() && can_build && item; - - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); + + //Add an inventory observer to only allow dropping the newly attached item + //once it exists in your inventory. Look at Jira 2422. + //-jwolk + + // A bug occurs when you wear/drop an item before it actively is added to your inventory + // if this is the case (you're on a slow sim, etc.) a copy of the object, + // well, a newly created object with the same properties, is placed + // in your inventory. Therefore, we disable the drop option until the + // item is in your inventory + + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + LLViewerJointAttachment* attachment = NULL; + LLInventoryItem* item = NULL; + + // Do not enable drop if all faces of object are not enabled + if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) + { + S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState()); + attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); + + if (attachment) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + // make sure item is in your inventory (it could be a delayed attach message being sent from the sim) + // so check to see if the item is in the inventory already + item = gInventory.getItem(attachment_iter->get()->getAttachmentItemID()); + if (!item) + { + // Item does not exist, make an observer to enable the pie menu + // when the item finishes fetching worst case scenario + // if a fetch is already out there (being sent from a slow sim) + // we refetch and there are 2 fetches + LLWornItemFetchedObserver* worn_item_fetched = new LLWornItemFetchedObserver((*attachment_iter)->getAttachmentItemID()); + worn_item_fetched->startFetch(); + gInventory.addObserver(worn_item_fetched); + } + } + } + } + + //now check to make sure that the item is actually in the inventory before we enable dropping it + bool new_value = enable_detach() && can_build && item; + + return new_value; + } }; BOOL enable_detach(const LLSD&) { - LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - - // Only enable detach if all faces of object are selected - if (!object || - !object->isAttachment() || - !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) - { - return FALSE; - } + LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + + // Only enable detach if all faces of object are selected + if (!object || + !object->isAttachment() || + !LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES )) + { + return FALSE; + } - // Find the avatar who owns this attachment - LLViewerObject* avatar = object; - while (avatar) - { - // ...if it's you, good to detach - if (avatar->getID() == gAgent.getID()) - { - return TRUE; - } + // Find the avatar who owns this attachment + LLViewerObject* avatar = object; + while (avatar) + { + // ...if it's you, good to detach + if (avatar->getID() == gAgent.getID()) + { + return TRUE; + } - avatar = (LLViewerObject*)avatar->getParent(); - } + avatar = (LLViewerObject*)avatar->getParent(); + } - return FALSE; + return FALSE; } class LLAttachmentEnableDetach : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = enable_detach(); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = enable_detach(); + return new_value; + } }; // Used to tell if the selected object can be attached to your avatar. BOOL object_selected_and_point_valid() { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - for (LLObjectSelection::root_iterator iter = selection->root_begin(); - iter != selection->root_end(); iter++) - { - LLSelectNode* node = *iter; - LLViewerObject* object = node->getObject(); - LLViewerObject::const_child_list_t& child_list = object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - if (child->isAvatar()) - { - return FALSE; - } - } - } - - return (selection->getRootObjectCount() == 1) && - (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && - selection->getFirstRootObject()->permYouOwner() && - selection->getFirstRootObject()->flagObjectMove() && - !selection->getFirstRootObject()->flagObjectPermanent() && - !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && - (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + for (LLObjectSelection::root_iterator iter = selection->root_begin(); + iter != selection->root_end(); iter++) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + LLViewerObject::const_child_list_t& child_list = object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + if (child->isAvatar()) + { + return FALSE; + } + } + } + + return (selection->getRootObjectCount() == 1) && + (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && + selection->getFirstRootObject()->permYouOwner() && + selection->getFirstRootObject()->flagObjectMove() && + !selection->getFirstRootObject()->flagObjectPermanent() && + !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && + (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); } BOOL object_is_wearable() { - if (!isAgentAvatarValid()) - { - return FALSE; - } - if (!object_selected_and_point_valid()) - { - return FALSE; - } - if (sitting_on_selection()) - { - return FALSE; - } + if (!isAgentAvatarValid()) + { + return FALSE; + } + if (!object_selected_and_point_valid()) + { + return FALSE; + } + if (sitting_on_selection()) + { + return FALSE; + } if (!gAgentAvatarp->canAttachMoreObjects()) { return FALSE; } - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) - { - LLSelectNode* node = *iter; - if (node->mPermissions->getOwner() == gAgent.getID()) - { - return TRUE; - } - } - return FALSE; + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++) + { + LLSelectNode* node = *iter; + if (node->mPermissions->getOwner() == gAgent.getID()) + { + return TRUE; + } + } + return FALSE; } class LLAttachmentPointFilled : public view_listener_t { - bool handleEvent(const LLSD& user_data) - { - bool enable = false; - LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger()); - if (found_it != gAgentAvatarp->mAttachmentPoints.end()) - { - enable = found_it->second->getNumObjects() > 0; - } - return enable; - } + bool handleEvent(const LLSD& user_data) + { + bool enable = false; + LLVOAvatar::attachment_map_t::iterator found_it = gAgentAvatarp->mAttachmentPoints.find(user_data.asInteger()); + if (found_it != gAgentAvatarp->mAttachmentPoints.end()) + { + enable = found_it->second->getNumObjects() > 0; + } + return enable; + } }; class LLAvatarSendIM : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLAvatarActions::startIM(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLAvatarActions::startIM(avatar->getID()); + } + return true; + } }; class LLAvatarCall : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); - if(avatar) - { - LLAvatarActions::startCall(avatar->getID()); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() ); + if(avatar) + { + LLAvatarActions::startCall(avatar->getID()); + } + return true; + } }; namespace { - struct QueueObjects : public LLSelectedNodeFunctor - { - BOOL scripted; - BOOL modifiable; - LLFloaterScriptQueue* mQueue; - QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {} - virtual bool apply(LLSelectNode* node) - { - LLViewerObject* obj = node->getObject(); - if (!obj) - { - return true; - } - scripted = obj->flagScripted(); - modifiable = obj->permModify(); - - if( scripted && modifiable ) - { - mQueue->addObject(obj->getID(), node->mName); - return false; - } - else - { - return true; // fail: stop applying - } - } - }; + struct QueueObjects : public LLSelectedNodeFunctor + { + BOOL scripted; + BOOL modifiable; + LLFloaterScriptQueue* mQueue; + QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {} + virtual bool apply(LLSelectNode* node) + { + LLViewerObject* obj = node->getObject(); + if (!obj) + { + return true; + } + scripted = obj->flagScripted(); + modifiable = obj->permModify(); + + if( scripted && modifiable ) + { + mQueue->addObject(obj->getID(), node->mName); + return false; + } + else + { + return true; // fail: stop applying + } + } + }; } bool queue_actions(LLFloaterScriptQueue* q, const std::string& msg) { - QueueObjects func(q); - LLSelectMgr *mgr = LLSelectMgr::getInstance(); - LLObjectSelectionHandle selectHandle = mgr->getSelection(); - bool fail = selectHandle->applyToNodes(&func); - if(fail) - { - if ( !func.scripted ) - { - std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts"; - LLNotificationsUtil::add(noscriptmsg); - } - else if ( !func.modifiable ) - { - std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission"; - LLNotificationsUtil::add(nomodmsg); - } - else - { - LL_ERRS() << "Bad logic." << LL_ENDL; - } - q->closeFloater(); - } - else - { - if (!q->start()) - { - LL_WARNS() << "Unexpected script compile failure." << LL_ENDL; - } - } - return !fail; + QueueObjects func(q); + LLSelectMgr *mgr = LLSelectMgr::getInstance(); + LLObjectSelectionHandle selectHandle = mgr->getSelection(); + bool fail = selectHandle->applyToNodes(&func); + if(fail) + { + if ( !func.scripted ) + { + std::string noscriptmsg = std::string("Cannot") + msg + "SelectObjectsNoScripts"; + LLNotificationsUtil::add(noscriptmsg); + } + else if ( !func.modifiable ) + { + std::string nomodmsg = std::string("Cannot") + msg + "SelectObjectsNoPermission"; + LLNotificationsUtil::add(nomodmsg); + } + else + { + LL_ERRS() << "Bad logic." << LL_ENDL; + } + q->closeFloater(); + } + else + { + if (!q->start()) + { + LL_WARNS() << "Unexpected script compile failure." << LL_ENDL; + } + } + return !fail; } class LLToolsSelectedScriptAction : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string action = userdata.asString(); - bool mono = false; - std::string msg, name; - std::string title; - if (action == "compile mono") - { - name = "compile_queue"; - mono = true; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - if (action == "compile lsl") - { - name = "compile_queue"; - msg = "Recompile"; - title = LLTrans::getString("CompileQueueTitle"); - } - else if (action == "reset") - { - name = "reset_queue"; - msg = "Reset"; - title = LLTrans::getString("ResetQueueTitle"); - } - else if (action == "start") - { - name = "start_queue"; - msg = "SetRunning"; - title = LLTrans::getString("RunQueueTitle"); - } - else if (action == "stop") - { - name = "stop_queue"; - msg = "SetRunningNot"; - title = LLTrans::getString("NotRunQueueTitle"); - } - LLUUID id; id.generate(); - - LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance(name, LLSD(id)); - if (queue) - { - queue->setMono(mono); - if (queue_actions(queue, msg)) - { - queue->setTitle(title); - } - } - else - { - LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string action = userdata.asString(); + bool mono = false; + std::string msg, name; + std::string title; + if (action == "compile mono") + { + name = "compile_queue"; + mono = true; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); + } + if (action == "compile lsl") + { + name = "compile_queue"; + msg = "Recompile"; + title = LLTrans::getString("CompileQueueTitle"); + } + else if (action == "reset") + { + name = "reset_queue"; + msg = "Reset"; + title = LLTrans::getString("ResetQueueTitle"); + } + else if (action == "start") + { + name = "start_queue"; + msg = "SetRunning"; + title = LLTrans::getString("RunQueueTitle"); + } + else if (action == "stop") + { + name = "stop_queue"; + msg = "SetRunningNot"; + title = LLTrans::getString("NotRunQueueTitle"); + } + LLUUID id; id.generate(); + + LLFloaterScriptQueue* queue =LLFloaterReg::getTypedInstance(name, LLSD(id)); + if (queue) + { + queue->setMono(mono); + if (queue_actions(queue, msg)) + { + queue->setTitle(title); + } + } + else + { + LL_WARNS() << "Failed to generate LLFloaterScriptQueue with action: " << action << LL_ENDL; + } + return true; + } }; void handle_selected_texture_info(void*) { - for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) - { - LLSelectNode* node = *iter; - - std::string msg; - msg.assign("Texture info for: "); - msg.append(node->mName); - - U8 te_count = node->getObject()->getNumTEs(); - // map from texture ID to list of faces using it - typedef std::map< LLUUID, std::vector > map_t; - map_t faces_per_texture; - for (U8 i = 0; i < te_count; i++) - { - if (!node->isTESelected(i)) continue; - - LLViewerTexture* img = node->getObject()->getTEImage(i); - LLUUID image_id = img->getID(); - faces_per_texture[image_id].push_back(i); - } - // Per-texture, dump which faces are using it. - map_t::iterator it; - for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it) - { - U8 te = it->second[0]; - LLViewerTexture* img = node->getObject()->getTEImage(te); - S32 height = img->getHeight(); - S32 width = img->getWidth(); - S32 components = img->getComponents(); - msg.append(llformat("\n%dx%d %s on face ", - width, - height, - (components == 4 ? "alpha" : "opaque"))); - for (U8 i = 0; i < it->second.size(); ++i) - { - msg.append( llformat("%d ", (S32)(it->second[i]))); - } - } - LLSD args; - args["MESSAGE"] = msg; - LLNotificationsUtil::add("SystemMessage", args); - } + for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) + { + LLSelectNode* node = *iter; + + std::string msg; + msg.assign("Texture info for: "); + msg.append(node->mName); + + U8 te_count = node->getObject()->getNumTEs(); + // map from texture ID to list of faces using it + typedef std::map< LLUUID, std::vector > map_t; + map_t faces_per_texture; + for (U8 i = 0; i < te_count; i++) + { + if (!node->isTESelected(i)) continue; + + LLViewerTexture* img = node->getObject()->getTEImage(i); + LLUUID image_id = img->getID(); + faces_per_texture[image_id].push_back(i); + } + // Per-texture, dump which faces are using it. + map_t::iterator it; + for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it) + { + U8 te = it->second[0]; + LLViewerTexture* img = node->getObject()->getTEImage(te); + S32 height = img->getHeight(); + S32 width = img->getWidth(); + S32 components = img->getComponents(); + msg.append(llformat("\n%dx%d %s on face ", + width, + height, + (components == 4 ? "alpha" : "opaque"))); + for (U8 i = 0; i < it->second.size(); ++i) + { + msg.append( llformat("%d ", (S32)(it->second[i]))); + } + } + LLSD args; + args["MESSAGE"] = msg; + LLNotificationsUtil::add("SystemMessage", args); + } } void handle_selected_material_info() { - for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) - { - LLSelectNode* node = *iter; - - std::string msg; - msg.assign("Material info for: \n"); - msg.append(node->mName); - - U8 te_count = node->getObject()->getNumTEs(); - // map from material ID to list of faces using it - typedef std::map > map_t; - map_t faces_per_material; - for (U8 i = 0; i < te_count; i++) - { - if (!node->isTESelected(i)) continue; - - const LLMaterialID& material_id = node->getObject()->getTE(i)->getMaterialID(); - faces_per_material[material_id].push_back(i); - } - // Per-material, dump which faces are using it. - map_t::iterator it; - for (it = faces_per_material.begin(); it != faces_per_material.end(); ++it) - { - const LLMaterialID& material_id = it->first; - msg += llformat("%s on face ", material_id.asString().c_str()); - for (U8 i = 0; i < it->second.size(); ++i) - { - msg.append( llformat("%d ", (S32)(it->second[i]))); - } - msg.append("\n"); - } - - LLSD args; - args["MESSAGE"] = msg; - LLNotificationsUtil::add("SystemMessage", args); - } + for (LLObjectSelection::valid_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_begin(); + iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) + { + LLSelectNode* node = *iter; + + std::string msg; + msg.assign("Material info for: \n"); + msg.append(node->mName); + + U8 te_count = node->getObject()->getNumTEs(); + // map from material ID to list of faces using it + typedef std::map > map_t; + map_t faces_per_material; + for (U8 i = 0; i < te_count; i++) + { + if (!node->isTESelected(i)) continue; + + const LLMaterialID& material_id = node->getObject()->getTE(i)->getMaterialID(); + faces_per_material[material_id].push_back(i); + } + // Per-material, dump which faces are using it. + map_t::iterator it; + for (it = faces_per_material.begin(); it != faces_per_material.end(); ++it) + { + const LLMaterialID& material_id = it->first; + msg += llformat("%s on face ", material_id.asString().c_str()); + for (U8 i = 0; i < it->second.size(); ++i) + { + msg.append( llformat("%d ", (S32)(it->second[i]))); + } + msg.append("\n"); + } + + LLSD args; + args["MESSAGE"] = msg; + LLNotificationsUtil::add("SystemMessage", args); + } } void handle_test_male(void*) { - LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit"); - //gGestureList.requestResetFromServer( TRUE ); + LLAppearanceMgr::instance().wearOutfitByName("Male Shape & Outfit"); + //gGestureList.requestResetFromServer( TRUE ); } void handle_test_female(void*) { - LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit"); - //gGestureList.requestResetFromServer( FALSE ); + LLAppearanceMgr::instance().wearOutfitByName("Female Shape & Outfit"); + //gGestureList.requestResetFromServer( FALSE ); } void handle_dump_attachments(void*) { - if(!isAgentAvatarValid()) return; - - 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; - S32 key = curiter->first; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *attached_object = attachment_iter->get(); - BOOL visible = (attached_object != NULL && - attached_object->mDrawable.notNull() && - !attached_object->mDrawable->isRenderType(0)); - LLVector3 pos; - if (visible) pos = attached_object->mDrawable->getPosition(); - LL_INFOS() << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID() - << (attached_object ? " present " : " absent ") - << (visible ? "visible " : "invisible ") - << " at " << pos - << " and " << (visible ? attached_object->getPosition() : LLVector3::zero) - << LL_ENDL; - } - } + if(!isAgentAvatarValid()) return; + + 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; + S32 key = curiter->first; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = attachment_iter->get(); + BOOL visible = (attached_object != NULL && + attached_object->mDrawable.notNull() && + !attached_object->mDrawable->isRenderType(0)); + LLVector3 pos; + if (visible) pos = attached_object->mDrawable->getPosition(); + LL_INFOS() << "ATTACHMENT " << key << ": item_id=" << attached_object->getAttachmentItemID() + << (attached_object ? " present " : " absent ") + << (visible ? "visible " : "invisible ") + << " at " << pos + << " and " << (visible ? attached_object->getPosition() : LLVector3::zero) + << LL_ENDL; + } + } } @@ -7890,80 +7890,80 @@ class LLToggleControl : public view_listener_t { protected: - bool handleEvent(const LLSD& userdata) - { - std::string control_name = userdata.asString(); - BOOL checked = gSavedSettings.getBOOL( control_name ); - gSavedSettings.setBOOL( control_name, !checked ); - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string control_name = userdata.asString(); + BOOL checked = gSavedSettings.getBOOL( control_name ); + gSavedSettings.setBOOL( control_name, !checked ); + return true; + } }; class LLCheckControl : public view_listener_t { - bool handleEvent( const LLSD& userdata) - { - std::string callback_data = userdata.asString(); - bool new_value = gSavedSettings.getBOOL(callback_data); - return new_value; - } + bool handleEvent( const LLSD& userdata) + { + std::string callback_data = userdata.asString(); + bool new_value = gSavedSettings.getBOOL(callback_data); + return new_value; + } }; // not so generic class LLAdvancedCheckRenderShadowOption: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string control_name = userdata.asString(); - S32 current_shadow_level = gSavedSettings.getS32(control_name); - if (current_shadow_level == 0) // is off - { - return false; - } - else // is on - { - return true; - } - } + bool handleEvent(const LLSD& userdata) + { + std::string control_name = userdata.asString(); + S32 current_shadow_level = gSavedSettings.getS32(control_name); + if (current_shadow_level == 0) // is off + { + return false; + } + else // is on + { + return true; + } + } }; class LLAdvancedClickRenderShadowOption: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string control_name = userdata.asString(); - S32 current_shadow_level = gSavedSettings.getS32(control_name); - if (current_shadow_level == 0) // upgrade to level 2 - { - gSavedSettings.setS32(control_name, 2); - } - else // downgrade to level 0 - { - gSavedSettings.setS32(control_name, 0); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string control_name = userdata.asString(); + S32 current_shadow_level = gSavedSettings.getS32(control_name); + if (current_shadow_level == 0) // upgrade to level 2 + { + gSavedSettings.setS32(control_name, 2); + } + else // downgrade to level 0 + { + gSavedSettings.setS32(control_name, 0); + } + return true; + } }; class LLAdvancedClickRenderProfile: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gShaderProfileFrame = TRUE; - return true; - } + bool handleEvent(const LLSD& userdata) + { + gShaderProfileFrame = TRUE; + return true; + } }; F32 gpu_benchmark(); class LLAdvancedClickRenderBenchmark: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gpu_benchmark(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gpu_benchmark(); + return true; + } }; void hdri_preview(); @@ -7993,290 +7993,290 @@ class LLAdvancedClickGLTFScenePreview : public view_listener_t // these are used in the gl menus to set control values that require shader recompilation class LLToggleShaderControl : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { std::string control_name = userdata.asString(); - BOOL checked = gSavedSettings.getBOOL( control_name ); - gSavedSettings.setBOOL( control_name, !checked ); + BOOL checked = gSavedSettings.getBOOL( control_name ); + gSavedSettings.setBOOL( control_name, !checked ); LLPipeline::refreshCachedSettings(); LLViewerShaderMgr::instance()->setShaders(); - return !checked; - } + return !checked; + } }; void menu_toggle_attached_lights(void* user_data) { - LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); + LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); } void menu_toggle_attached_particles(void* user_data) { - LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); + LLPipeline::sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); } class LLAdvancedHandleAttachedLightParticles: public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string control_name = userdata.asString(); + bool handleEvent(const LLSD& userdata) + { + std::string control_name = userdata.asString(); - // toggle the control - gSavedSettings.setBOOL(control_name, - !gSavedSettings.getBOOL(control_name)); + // toggle the control + gSavedSettings.setBOOL(control_name, + !gSavedSettings.getBOOL(control_name)); - // update internal flags - if (control_name == "RenderAttachedLights") - { - menu_toggle_attached_lights(NULL); - } - else if (control_name == "RenderAttachedParticles") - { - menu_toggle_attached_particles(NULL); - } - return true; - } + // update internal flags + if (control_name == "RenderAttachedLights") + { + menu_toggle_attached_lights(NULL); + } + else if (control_name == "RenderAttachedParticles") + { + menu_toggle_attached_particles(NULL); + } + return true; + } }; class LLSomethingSelected : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty()); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = !(LLSelectMgr::getInstance()->getSelection()->isEmpty()); + return new_value; + } }; class LLSomethingSelectedNoHUD : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD); + return new_value; + } }; static bool is_editable_selected() { - return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); + return (LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() != NULL); } class LLEditableSelected : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return is_editable_selected(); - } + bool handleEvent(const LLSD& userdata) + { + return is_editable_selected(); + } }; class LLEditableSelectedMono : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = false; - LLViewerRegion* region = gAgent.getRegion(); - if(region && gMenuHolder) - { - bool have_cap = (! region->getCapability("UpdateScriptTask").empty()); - new_value = is_editable_selected() && have_cap; - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = false; + LLViewerRegion* region = gAgent.getRegion(); + if(region && gMenuHolder) + { + bool have_cap = (! region->getCapability("UpdateScriptTask").empty()); + new_value = is_editable_selected() && have_cap; + } + return new_value; + } }; bool enable_object_take_copy() { - bool all_valid = false; - if (LLSelectMgr::getInstance()) - { - if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 0) - { - all_valid = true; + bool all_valid = false; + if (LLSelectMgr::getInstance()) + { + if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 0) + { + all_valid = true; #ifndef HACKED_GODLIKE_VIEWER # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (LLGridManager::getInstance()->isInProductionGrid() + if (LLGridManager::getInstance()->isInProductionGrid() || !gAgent.isGodlike()) # endif - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* obj) - { - return (!obj->permCopy() || obj->isAttachment()); - } - } func; - const bool firstonly = true; - bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); - all_valid = !any_invalid; - } + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* obj) + { + return (!obj->permCopy() || obj->isAttachment()); + } + } func; + const bool firstonly = true; + bool any_invalid = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); + all_valid = !any_invalid; + } #endif // HACKED_GODLIKE_VIEWER - } - } + } + } - return all_valid; + return all_valid; } class LLHasAsset : public LLInventoryCollectFunctor { public: - LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {} - virtual ~LLHasAsset() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item); - BOOL hasAsset() const { return mHasAsset; } + LLHasAsset(const LLUUID& id) : mAssetID(id), mHasAsset(FALSE) {} + virtual ~LLHasAsset() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); + BOOL hasAsset() const { return mHasAsset; } protected: - LLUUID mAssetID; - BOOL mHasAsset; + LLUUID mAssetID; + BOOL mHasAsset; }; bool LLHasAsset::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) + LLInventoryItem* item) { - if(item && item->getAssetUUID() == mAssetID) - { - mHasAsset = TRUE; - } - return FALSE; + if(item && item->getAssetUUID() == mAssetID) + { + mHasAsset = TRUE; + } + return FALSE; } BOOL enable_save_into_task_inventory(void*) { - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); - if(node && (node->mValid) && (!node->mFromTaskID.isNull())) - { - // *TODO: check to see if the fromtaskid object exists. - LLViewerObject* obj = node->getObject(); - if( obj && !obj->isAttachment() ) - { - return TRUE; - } - } - return FALSE; + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); + if(node && (node->mValid) && (!node->mFromTaskID.isNull())) + { + // *TODO: check to see if the fromtaskid object exists. + LLViewerObject* obj = node->getObject(); + if( obj && !obj->isAttachment() ) + { + return TRUE; + } + } + return FALSE; } class LLToolsEnableSaveToObjectInventory : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = enable_save_into_task_inventory(NULL); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = enable_save_into_task_inventory(NULL); + return new_value; + } }; class LLToggleHowTo : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterReg::toggleInstanceOrBringToFront("guidebook"); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloaterReg::toggleInstanceOrBringToFront("guidebook"); + return true; + } }; class LLViewEnableMouselook : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // You can't go directly from customize avatar to mouselook. - // TODO: write code with appropriate dialogs to handle this transition. - bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime")); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + // You can't go directly from customize avatar to mouselook. + // TODO: write code with appropriate dialogs to handle this transition. + bool new_value = (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && !gSavedSettings.getBOOL("FreezeTime")); + return new_value; + } }; class LLToolsEnableToolNotPie : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() ); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = ( LLToolMgr::getInstance()->getBaseTool() != LLToolPie::getInstance() ); + return new_value; + } }; class LLWorldEnableCreateLandmark : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return !LLLandmarkActions::landmarkAlreadyExists(); - } + bool handleEvent(const LLSD& userdata) + { + return !LLLandmarkActions::landmarkAlreadyExists(); + } }; class LLWorldEnableSetHomeLocation : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gAgent.isGodlike() || - (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome()); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gAgent.isGodlike() || + (gAgent.getRegion() && gAgent.getRegion()->getAllowSetHome()); + return new_value; + } }; class LLWorldEnableTeleportHome : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLViewerRegion* regionp = gAgent.getRegion(); - bool agent_on_prelude = (regionp && regionp->isPrelude()); - bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude; - return enable_teleport_home; - } + bool handleEvent(const LLSD& userdata) + { + LLViewerRegion* regionp = gAgent.getRegion(); + bool agent_on_prelude = (regionp && regionp->isPrelude()); + bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude; + return enable_teleport_home; + } }; BOOL enable_god_full(void*) { - return gAgent.getGodLevel() >= GOD_FULL; + return gAgent.getGodLevel() >= GOD_FULL; } BOOL enable_god_liaison(void*) { - return gAgent.getGodLevel() >= GOD_LIAISON; + return gAgent.getGodLevel() >= GOD_LIAISON; } bool is_god_customer_service() { - return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE; + return gAgent.getGodLevel() >= GOD_CUSTOMER_SERVICE; } BOOL enable_god_basic(void*) { - return gAgent.getGodLevel() > GOD_NOT; + return gAgent.getGodLevel() > GOD_NOT; } void toggle_show_xui_names(void *) { - gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames")); + gSavedSettings.setBOOL("DebugShowXUINames", !gSavedSettings.getBOOL("DebugShowXUINames")); } BOOL check_show_xui_names(void *) { - return gSavedSettings.getBOOL("DebugShowXUINames"); + return gSavedSettings.getBOOL("DebugShowXUINames"); } class LLToolsSelectOnlyMyObjects : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly"); + bool handleEvent(const LLSD& userdata) + { + BOOL cur_val = gSavedSettings.getBOOL("SelectOwnedOnly"); - gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val ); + gSavedSettings.setBOOL("SelectOwnedOnly", ! cur_val ); - return true; - } + return true; + } }; class LLToolsSelectOnlyMovableObjects : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly"); + bool handleEvent(const LLSD& userdata) + { + BOOL cur_val = gSavedSettings.getBOOL("SelectMovableOnly"); - gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val ); + gSavedSettings.setBOOL("SelectMovableOnly", ! cur_val ); - return true; - } + return true; + } }; class LLToolsSelectInvisibleObjects : public view_listener_t @@ -8305,178 +8305,178 @@ class LLToolsSelectReflectionProbes: public view_listener_t class LLToolsSelectBySurrounding : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive; + bool handleEvent(const LLSD& userdata) + { + LLSelectMgr::sRectSelectInclusive = !LLSelectMgr::sRectSelectInclusive; - gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive); - return true; - } + gSavedSettings.setBOOL("RectangleSelectInclusive", LLSelectMgr::sRectSelectInclusive); + return true; + } }; class LLToolsShowHiddenSelection : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // TomY TODO Merge these - LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections; + bool handleEvent(const LLSD& userdata) + { + // TomY TODO Merge these + LLSelectMgr::sRenderHiddenSelections = !LLSelectMgr::sRenderHiddenSelections; - gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections); - return true; - } + gSavedSettings.setBOOL("RenderHiddenSelections", LLSelectMgr::sRenderHiddenSelections); + return true; + } }; class LLToolsShowSelectionLightRadius : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - // TomY TODO merge these - LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius; + bool handleEvent(const LLSD& userdata) + { + // TomY TODO merge these + LLSelectMgr::sRenderLightRadius = !LLSelectMgr::sRenderLightRadius; - gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius); - return true; - } + gSavedSettings.setBOOL("RenderLightRadius", LLSelectMgr::sRenderLightRadius); + return true; + } }; class LLToolsEditLinkedParts : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts"); - gSavedSettings.setBOOL( "EditLinkedParts", select_individuals ); - if (select_individuals) - { - LLSelectMgr::getInstance()->demoteSelectionToIndividuals(); - } - else - { - LLSelectMgr::getInstance()->promoteSelectionToRoot(); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + BOOL select_individuals = !gSavedSettings.getBOOL("EditLinkedParts"); + gSavedSettings.setBOOL( "EditLinkedParts", select_individuals ); + if (select_individuals) + { + LLSelectMgr::getInstance()->demoteSelectionToIndividuals(); + } + else + { + LLSelectMgr::getInstance()->promoteSelectionToRoot(); + } + return true; + } }; void reload_vertex_shader(void *) { - //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP + //THIS WOULD BE AN AWESOME PLACE TO RELOAD SHADERS... just a thought - DaveP } void handle_dump_avatar_local_textures(void*) { - gAgentAvatarp->dumpLocalTextures(); + gAgentAvatarp->dumpLocalTextures(); } void handle_dump_timers() { - LLTrace::BlockTimer::dumpCurTimes(); + LLTrace::BlockTimer::dumpCurTimes(); } void handle_debug_avatar_textures(void*) { - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (objectp) - { - LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) ); - } + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); + if (objectp) + { + LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) ); + } } void handle_grab_baked_texture(void* data) { - EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data); - if (!isAgentAvatarValid()) return; - - const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index); - LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << LL_ENDL; - LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE; - LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE; - const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type)); - if(folder_id.notNull()) - { - std::string name; - name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; - - LLUUID item_id; - item_id.generate(); - LLPermissions perm; - perm.init(gAgentID, - gAgentID, - LLUUID::null, - LLUUID::null); - U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER; - perm.initMasks(PERM_ALL, - PERM_ALL, - PERM_NONE, - PERM_NONE, - next_owner_perm); - time_t creation_date_now = time_corrected(); - LLPointer item - = new LLViewerInventoryItem(item_id, - folder_id, - perm, - asset_id, - asset_type, - inv_type, - name, - LLStringUtil::null, - LLSaleInfo::DEFAULT, - LLInventoryItemFlags::II_FLAGS_NONE, - creation_date_now); - - item->updateServer(TRUE); - gInventory.updateItem(item); - gInventory.notifyObservers(); - - // Show the preview panel for textures to let - // user know that the image is now in inventory. - LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); - if(active_panel) - { - LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); - - active_panel->setSelection(item_id, TAKE_FOCUS_NO); - active_panel->openSelected(); - //LLFloaterInventory::dumpSelectionInformation((void*)view); - // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl); - } - } - else - { - LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; - } + EBakedTextureIndex baked_tex_index = (EBakedTextureIndex)((intptr_t)data); + if (!isAgentAvatarValid()) return; + + const LLUUID& asset_id = gAgentAvatarp->grabBakedTexture(baked_tex_index); + LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << LL_ENDL; + LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE; + LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE; + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(asset_type)); + if(folder_id.notNull()) + { + std::string name; + name = "Baked " + LLAvatarAppearance::getDictionary()->getBakedTexture(baked_tex_index)->mNameCapitalized + " Texture"; + + LLUUID item_id; + item_id.generate(); + LLPermissions perm; + perm.init(gAgentID, + gAgentID, + LLUUID::null, + LLUUID::null); + U32 next_owner_perm = PERM_MOVE | PERM_TRANSFER; + perm.initMasks(PERM_ALL, + PERM_ALL, + PERM_NONE, + PERM_NONE, + next_owner_perm); + time_t creation_date_now = time_corrected(); + LLPointer item + = new LLViewerInventoryItem(item_id, + folder_id, + perm, + asset_id, + asset_type, + inv_type, + name, + LLStringUtil::null, + LLSaleInfo::DEFAULT, + LLInventoryItemFlags::II_FLAGS_NONE, + creation_date_now); + + item->updateServer(TRUE); + gInventory.updateItem(item); + gInventory.notifyObservers(); + + // Show the preview panel for textures to let + // user know that the image is now in inventory. + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); + if(active_panel) + { + LLFocusableElement* focus_ctrl = gFocusMgr.getKeyboardFocus(); + + active_panel->setSelection(item_id, TAKE_FOCUS_NO); + active_panel->openSelected(); + //LLFloaterInventory::dumpSelectionInformation((void*)view); + // restore keyboard focus + gFocusMgr.setKeyboardFocus(focus_ctrl); + } + } + else + { + LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; + } } BOOL enable_grab_baked_texture(void* data) { - EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data); - if (isAgentAvatarValid()) - { - return gAgentAvatarp->canGrabBakedTexture(index); - } - return FALSE; + EBakedTextureIndex index = (EBakedTextureIndex)((intptr_t)data); + if (isAgentAvatarValid()) + { + return gAgentAvatarp->canGrabBakedTexture(index); + } + return FALSE; } // Returns a pointer to the avatar give the UUID of the avatar OR of an attachment the avatar is wearing. // Returns NULL on failure. LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) { - if (object) - { - if( object->isAttachment() ) - { - do - { - object = (LLViewerObject*) object->getParent(); - } - while( object && !object->isAvatar() ); - } - else if( !object->isAvatar() ) - { - object = NULL; - } - } + if (object) + { + if( object->isAttachment() ) + { + do + { + object = (LLViewerObject*) object->getParent(); + } + while( object && !object->isAvatar() ); + } + else if( !object->isAvatar() ) + { + object = NULL; + } + } - return (LLVOAvatar*) object; + return (LLVOAvatar*) object; } @@ -8484,13 +8484,13 @@ LLVOAvatar* find_avatar_from_object( LLViewerObject* object ) // Returns NULL on failure. LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ) { - return find_avatar_from_object( gObjectList.findObject(object_id) ); + return find_avatar_from_object( gObjectList.findObject(object_id) ); } void handle_disconnect_viewer(void *) { - LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect")); + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("TestingDisconnect")); } void force_error_breakpoint(void *) @@ -8545,30 +8545,30 @@ void force_error_thread_crash(void *) class LLToolsUseSelectionForGrid : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLSelectMgr::getInstance()->clearGridObjects(); - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* objectp) - { - LLSelectMgr::getInstance()->addGridObject(objectp); - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); - LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); - LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLSelectMgr::getInstance()->clearGridObjects(); + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* objectp) + { + LLSelectMgr::getInstance()->addGridObject(objectp); + return true; + } + } func; + LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func); + LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); + LLFloaterTools::setGridMode((S32)GRID_MODE_REF_OBJECT); + return true; + } }; void handle_test_load_url(void*) { - LLWeb::loadURL(""); - LLWeb::loadURL("hacker://www.google.com/"); - LLWeb::loadURL("http"); - LLWeb::loadURL("http://www.google.com/"); + LLWeb::loadURL(""); + LLWeb::loadURL("hacker://www.google.com/"); + LLWeb::loadURL("http"); + LLWeb::loadURL("http://www.google.com/"); } // @@ -8582,86 +8582,86 @@ LLViewerMenuHolderGL::LLViewerMenuHolderGL(const LLViewerMenuHolderGL::Params& p BOOL LLViewerMenuHolderGL::hideMenus() { - BOOL handled = FALSE; - - if (LLMenuHolderGL::hideMenus()) - { - handled = TRUE; - } + BOOL handled = FALSE; + + if (LLMenuHolderGL::hideMenus()) + { + handled = TRUE; + } - // drop pie menu selection - mParcelSelection = NULL; - mObjectSelection = NULL; + // drop pie menu selection + mParcelSelection = NULL; + mObjectSelection = NULL; - if (gMenuBarView) - { - gMenuBarView->clearHoverItem(); - gMenuBarView->resetMenuTrigger(); - } + if (gMenuBarView) + { + gMenuBarView->clearHoverItem(); + gMenuBarView->resetMenuTrigger(); + } - return handled; + return handled; } -void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle selection) -{ - mParcelSelection = selection; +void LLViewerMenuHolderGL::setParcelSelection(LLSafeHandle selection) +{ + mParcelSelection = selection; } -void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle selection) -{ - mObjectSelection = selection; +void LLViewerMenuHolderGL::setObjectSelection(LLSafeHandle selection) +{ + mObjectSelection = selection; } const LLRect LLViewerMenuHolderGL::getMenuRect() const { - return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT); + return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT); } void handle_web_browser_test(const LLSD& param) { - std::string url = param.asString(); - if (url.empty()) - { - url = "about:blank"; - } - LLWeb::loadURLInternal(url); + std::string url = param.asString(); + if (url.empty()) + { + url = "about:blank"; + } + LLWeb::loadURLInternal(url); } bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if ( option == 0 ) // YES - { - //clear cache - LLAppViewer::instance()->purgeCacheImmediate(); - } + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) // YES + { + //clear cache + LLAppViewer::instance()->purgeCacheImmediate(); + } - return false; + return false; } void handle_cache_clear_immediately() { - LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); + LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); } void handle_web_content_test(const LLSD& param) { - std::string url = param.asString(); - LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true); + std::string url = param.asString(); + LLWeb::loadURLInternal(url, LLStringUtil::null, LLStringUtil::null, true); } void handle_show_url(const LLSD& param) { - std::string url = param.asString(); - if (LLWeb::useExternalBrowser(url)) - { - LLWeb::loadURLExternal(url); - } - else - { - LLWeb::loadURLInternal(url); - } + std::string url = param.asString(); + if (LLWeb::useExternalBrowser(url)) + { + LLWeb::loadURLExternal(url); + } + else + { + LLWeb::loadURLInternal(url); + } } @@ -8673,383 +8673,383 @@ void handle_report_bug(const LLSD& param) void handle_buy_currency_test(void*) { - std::string url = - "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]"; + std::string url = + "http://sarahd-sl-13041.webdev.lindenlab.com/app/lindex/index.php?agent_id=[AGENT_ID]&secure_session_id=[SESSION_ID]&lang=[LANGUAGE]"; - LLStringUtil::format_map_t replace; - replace["[AGENT_ID]"] = gAgent.getID().asString(); - replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString(); - replace["[LANGUAGE]"] = LLUI::getLanguage(); - LLStringUtil::format(url, replace); + LLStringUtil::format_map_t replace; + replace["[AGENT_ID]"] = gAgent.getID().asString(); + replace["[SESSION_ID]"] = gAgent.getSecureSessionID().asString(); + replace["[LANGUAGE]"] = LLUI::getLanguage(); + LLStringUtil::format(url, replace); - LL_INFOS() << "buy currency url " << url << LL_ENDL; + LL_INFOS() << "buy currency url " << url << LL_ENDL; - LLFloaterReg::showInstance("buy_currency_html", LLSD(url)); + LLFloaterReg::showInstance("buy_currency_html", LLSD(url)); } // SUNSHINE CLEANUP - is only the request update at the end needed now? void handle_rebake_textures(void*) { - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid()) return; - // Slam pending upload count to "unstick" things - bool slam_for_debug = true; - gAgentAvatarp->forceBakeAllTextures(slam_for_debug); - if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) - { - LLAppearanceMgr::instance().requestServerAppearanceUpdate(); - } + // Slam pending upload count to "unstick" things + bool slam_for_debug = true; + gAgentAvatarp->forceBakeAllTextures(slam_for_debug); + if (gAgent.getRegion() && gAgent.getRegion()->getCentralBakeVersion()) + { + LLAppearanceMgr::instance().requestServerAppearanceUpdate(); + } } void toggle_visibility(void* user_data) { - LLView* viewp = (LLView*)user_data; - viewp->setVisible(!viewp->getVisible()); + LLView* viewp = (LLView*)user_data; + viewp->setVisible(!viewp->getVisible()); } BOOL get_visibility(void* user_data) { - LLView* viewp = (LLView*)user_data; - return viewp->getVisible(); + LLView* viewp = (LLView*)user_data; + return viewp->getVisible(); } class LLViewShowHoverTips : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips")); - return true; - } + bool handleEvent(const LLSD& userdata) + { + gSavedSettings.setBOOL("ShowHoverTips", !gSavedSettings.getBOOL("ShowHoverTips")); + return true; + } }; class LLViewCheckShowHoverTips : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = gSavedSettings.getBOOL("ShowHoverTips"); - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = gSavedSettings.getBOOL("ShowHoverTips"); + return new_value; + } }; class LLViewHighlightTransparent : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; + bool handleEvent(const LLSD& userdata) + { + LLDrawPoolAlpha::sShowDebugAlpha = !LLDrawPoolAlpha::sShowDebugAlpha; // invisible objects skip building their render batches unless sShowDebugAlpha is true, so rebuild batches whenever toggling this flag - gPipeline.rebuildDrawInfo(); - return true; - } + gPipeline.rebuildDrawInfo(); + return true; + } }; class LLViewCheckHighlightTransparent : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLDrawPoolAlpha::sShowDebugAlpha; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLDrawPoolAlpha::sShowDebugAlpha; + return new_value; + } }; class LLViewBeaconWidth : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string width = userdata.asString(); - if(width == "1") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 1); - } - else if(width == "4") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 4); - } - else if(width == "16") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 16); - } - else if(width == "32") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 32); - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string width = userdata.asString(); + if(width == "1") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 1); + } + else if(width == "4") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 4); + } + else if(width == "16") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 16); + } + else if(width == "32") + { + gSavedSettings.setS32("DebugBeaconLineWidth", 32); + } + + return true; + } }; class LLViewToggleBeacon : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string beacon = userdata.asString(); - if (beacon == "scriptsbeacon") - { - LLPipeline::toggleRenderScriptedBeacons(); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) - { - LLPipeline::toggleRenderScriptedTouchBeacons(); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); - } - } - else if (beacon == "physicalbeacon") - { - LLPipeline::toggleRenderPhysicalBeacons(); - gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons() ); - } - else if (beacon == "moapbeacon") - { - LLPipeline::toggleRenderMOAPBeacons(); - gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons() ); - } - else if (beacon == "soundsbeacon") - { - LLPipeline::toggleRenderSoundBeacons(); - gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons() ); - } - else if (beacon == "particlesbeacon") - { - LLPipeline::toggleRenderParticleBeacons(); - gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons() ); - } - else if (beacon == "scripttouchbeacon") - { - LLPipeline::toggleRenderScriptedTouchBeacons(); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) - { - LLPipeline::toggleRenderScriptedBeacons(); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); - } - } - else if (beacon == "sunbeacon") - { - gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon")); - } - else if (beacon == "moonbeacon") - { - gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon")); - } - else if (beacon == "renderbeacons") - { - LLPipeline::toggleRenderBeacons(); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) - { - LLPipeline::toggleRenderHighlights(); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); - } - } - else if (beacon == "renderhighlights") - { - LLPipeline::toggleRenderHighlights(); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) - { - LLPipeline::toggleRenderBeacons(); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); - } - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string beacon = userdata.asString(); + if (beacon == "scriptsbeacon") + { + LLPipeline::toggleRenderScriptedBeacons(); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) + { + LLPipeline::toggleRenderScriptedTouchBeacons(); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); + } + } + else if (beacon == "physicalbeacon") + { + LLPipeline::toggleRenderPhysicalBeacons(); + gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons() ); + } + else if (beacon == "moapbeacon") + { + LLPipeline::toggleRenderMOAPBeacons(); + gSavedSettings.setBOOL( "moapbeacon", LLPipeline::getRenderMOAPBeacons() ); + } + else if (beacon == "soundsbeacon") + { + LLPipeline::toggleRenderSoundBeacons(); + gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons() ); + } + else if (beacon == "particlesbeacon") + { + LLPipeline::toggleRenderParticleBeacons(); + gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons() ); + } + else if (beacon == "scripttouchbeacon") + { + LLPipeline::toggleRenderScriptedTouchBeacons(); + gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons() ); + // toggle the other one off if it's on + if (LLPipeline::getRenderScriptedBeacons() && LLPipeline::getRenderScriptedTouchBeacons()) + { + LLPipeline::toggleRenderScriptedBeacons(); + gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() ); + } + } + else if (beacon == "sunbeacon") + { + gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon")); + } + else if (beacon == "moonbeacon") + { + gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon")); + } + else if (beacon == "renderbeacons") + { + LLPipeline::toggleRenderBeacons(); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) + { + LLPipeline::toggleRenderHighlights(); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); + } + } + else if (beacon == "renderhighlights") + { + LLPipeline::toggleRenderHighlights(); + gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights() ); + // toggle the other one on if it's not + if (!LLPipeline::getRenderBeacons() && !LLPipeline::getRenderHighlights()) + { + LLPipeline::toggleRenderBeacons(); + gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons() ); + } + } + + return true; + } }; class LLViewCheckBeaconEnabled : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string beacon = userdata.asString(); - bool new_value = false; - if (beacon == "scriptsbeacon") - { - new_value = gSavedSettings.getBOOL( "scriptsbeacon"); - LLPipeline::setRenderScriptedBeacons(new_value); - } - else if (beacon == "moapbeacon") - { - new_value = gSavedSettings.getBOOL( "moapbeacon"); - LLPipeline::setRenderMOAPBeacons(new_value); - } - else if (beacon == "physicalbeacon") - { - new_value = gSavedSettings.getBOOL( "physicalbeacon"); - LLPipeline::setRenderPhysicalBeacons(new_value); - } - else if (beacon == "soundsbeacon") - { - new_value = gSavedSettings.getBOOL( "soundsbeacon"); - LLPipeline::setRenderSoundBeacons(new_value); - } - else if (beacon == "particlesbeacon") - { - new_value = gSavedSettings.getBOOL( "particlesbeacon"); - LLPipeline::setRenderParticleBeacons(new_value); - } - else if (beacon == "scripttouchbeacon") - { - new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); - LLPipeline::setRenderScriptedTouchBeacons(new_value); - } - else if (beacon == "renderbeacons") - { - new_value = gSavedSettings.getBOOL( "renderbeacons"); - LLPipeline::setRenderBeacons(new_value); - } - else if (beacon == "renderhighlights") - { - new_value = gSavedSettings.getBOOL( "renderhighlights"); - LLPipeline::setRenderHighlights(new_value); - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + std::string beacon = userdata.asString(); + bool new_value = false; + if (beacon == "scriptsbeacon") + { + new_value = gSavedSettings.getBOOL( "scriptsbeacon"); + LLPipeline::setRenderScriptedBeacons(new_value); + } + else if (beacon == "moapbeacon") + { + new_value = gSavedSettings.getBOOL( "moapbeacon"); + LLPipeline::setRenderMOAPBeacons(new_value); + } + else if (beacon == "physicalbeacon") + { + new_value = gSavedSettings.getBOOL( "physicalbeacon"); + LLPipeline::setRenderPhysicalBeacons(new_value); + } + else if (beacon == "soundsbeacon") + { + new_value = gSavedSettings.getBOOL( "soundsbeacon"); + LLPipeline::setRenderSoundBeacons(new_value); + } + else if (beacon == "particlesbeacon") + { + new_value = gSavedSettings.getBOOL( "particlesbeacon"); + LLPipeline::setRenderParticleBeacons(new_value); + } + else if (beacon == "scripttouchbeacon") + { + new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); + LLPipeline::setRenderScriptedTouchBeacons(new_value); + } + else if (beacon == "renderbeacons") + { + new_value = gSavedSettings.getBOOL( "renderbeacons"); + LLPipeline::setRenderBeacons(new_value); + } + else if (beacon == "renderhighlights") + { + new_value = gSavedSettings.getBOOL( "renderhighlights"); + LLPipeline::setRenderHighlights(new_value); + } + return new_value; + } }; class LLViewToggleRenderType : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string type = userdata.asString(); - if (type == "hideparticles") - { - LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string type = userdata.asString(); + if (type == "hideparticles") + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + return true; + } }; class LLViewCheckRenderType : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string type = userdata.asString(); - bool new_value = false; - if (type == "hideparticles") - { - new_value = LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES); - } - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + std::string type = userdata.asString(); + bool new_value = false; + if (type == "hideparticles") + { + new_value = LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES); + } + return new_value; + } }; class LLViewStatusAway : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return (gAgent.isInitialized() && gAgent.getAFK()); - } + bool handleEvent(const LLSD& userdata) + { + return (gAgent.isInitialized() && gAgent.getAFK()); + } }; class LLViewStatusDoNotDisturb : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return (gAgent.isInitialized() && gAgent.isDoNotDisturb()); - } + bool handleEvent(const LLSD& userdata) + { + return (gAgent.isInitialized() && gAgent.isDoNotDisturb()); + } }; class LLViewShowHUDAttachments : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; + return true; + } }; class LLViewCheckHUDAttachments : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool new_value = LLPipeline::sShowHUDAttachments; - return new_value; - } + bool handleEvent(const LLSD& userdata) + { + bool new_value = LLPipeline::sShowHUDAttachments; + return new_value; + } }; class LLEditEnableTakeOff : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string clothing = userdata.asString(); - LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); - if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) - return LLAgentWearables::selfHasWearable(type); - return false; - } + bool handleEvent(const LLSD& userdata) + { + std::string clothing = userdata.asString(); + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); + if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT) + return LLAgentWearables::selfHasWearable(type); + return false; + } }; class LLEditTakeOff : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string clothing = userdata.asString(); - if (clothing == "all") - LLAppearanceMgr::instance().removeAllClothesFromAvatar(); - else - { - LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); - if (type >= LLWearableType::WT_SHAPE - && type < LLWearableType::WT_COUNT - && (gAgentWearables.getWearableCount(type) > 0)) - { - // MULTI-WEARABLES: assuming user wanted to remove top shirt. - U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; - LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); - LLAppearanceMgr::instance().removeItemFromAvatar(item_id); - } - - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string clothing = userdata.asString(); + if (clothing == "all") + LLAppearanceMgr::instance().removeAllClothesFromAvatar(); + else + { + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing); + if (type >= LLWearableType::WT_SHAPE + && type < LLWearableType::WT_COUNT + && (gAgentWearables.getWearableCount(type) > 0)) + { + // MULTI-WEARABLES: assuming user wanted to remove top shirt. + U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); + } + + } + return true; + } }; class LLToolsSelectTool : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string tool_name = userdata.asString(); - if (tool_name == "focus") - { - LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1); - } - else if (tool_name == "move") - { - LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2); - } - else if (tool_name == "edit") - { - LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3); - } - else if (tool_name == "create") - { - LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4); - } - else if (tool_name == "land") - { - LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5); - } - - // Note: if floater is not visible LLViewerWindow::updateLayout() will - // attempt to open it, but it won't bring it to front or de-minimize. - if (gFloaterTools && (gFloaterTools->isMinimized() || !gFloaterTools->isShown() || !gFloaterTools->isFrontmost())) - { - gFloaterTools->setMinimized(FALSE); - gFloaterTools->openFloater(); - gFloaterTools->setVisibleAndFrontmost(TRUE); - } - return true; - } + bool handleEvent(const LLSD& userdata) + { + std::string tool_name = userdata.asString(); + if (tool_name == "focus") + { + LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(1); + } + else if (tool_name == "move") + { + LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(2); + } + else if (tool_name == "edit") + { + LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(3); + } + else if (tool_name == "create") + { + LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(4); + } + else if (tool_name == "land") + { + LLToolMgr::getInstance()->getCurrentToolset()->selectToolByIndex(5); + } + + // Note: if floater is not visible LLViewerWindow::updateLayout() will + // attempt to open it, but it won't bring it to front or de-minimize. + if (gFloaterTools && (gFloaterTools->isMinimized() || !gFloaterTools->isShown() || !gFloaterTools->isFrontmost())) + { + gFloaterTools->setMinimized(FALSE); + gFloaterTools->openFloater(); + gFloaterTools->setVisibleAndFrontmost(TRUE); + } + return true; + } }; /// WINDLIGHT callbacks class LLWorldEnvSettings : public view_listener_t -{ +{ void defocusEnvFloaters() { //currently there is only one instance of each floater @@ -9064,180 +9064,180 @@ class LLWorldEnvSettings : public view_listener_t } } - bool handleEvent(const LLSD& userdata) - { - std::string event_name = userdata.asString(); - - if (event_name == "sunrise") - { + bool handleEvent(const LLSD& userdata) + { + std::string event_name = userdata.asString(); + + if (event_name == "sunrise") + { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); - } - else if (event_name == "noon") - { + } + else if (event_name == "noon") + { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); - } + } else if (event_name == "legacy noon") { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); } - else if (event_name == "sunset") - { + else if (event_name == "sunset") + { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); - } - else if (event_name == "midnight") - { + } + else if (event_name == "midnight") + { LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT, LLEnvironment::TRANSITION_INSTANT); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); - } + } else if (event_name == "region") - { + { // reset probe data when reverting back to region sky setting gPipeline.mReflectionMapManager.reset(); LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); defocusEnvFloaters(); - } + } else if (event_name == "pause_clouds") { if (LLEnvironment::instance().isCloudScrollPaused()) LLEnvironment::instance().resumeCloudScroll(); - else + else LLEnvironment::instance().pauseCloudScroll(); } else if (event_name == "adjust_tool") - { + { LLFloaterReg::showInstance("env_adjust_snapshot"); } else if (event_name == "my_environs") { LLFloaterReg::showInstance("my_environments"); - } + } - return true; - } + return true; + } }; class LLWorldEnableEnvSettings : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool result = false; - std::string event_name = userdata.asString(); + bool handleEvent(const LLSD& userdata) + { + bool result = false; + std::string event_name = userdata.asString(); if (event_name == "pause_clouds") - { + { return LLEnvironment::instance().isCloudScrollPaused(); - } + } LLSettingsSky::ptr_t sky = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL); - if (!sky) - { - return (event_name == "region"); - } + if (!sky) + { + return (event_name == "region"); + } std::string skyname = (sky) ? sky->getName() : ""; LLUUID skyid = (sky) ? sky->getAssetId() : LLUUID::null; - if (event_name == "sunrise") - { + if (event_name == "sunrise") + { result = (skyid == LLEnvironment::KNOWN_SKY_SUNRISE); - } - else if (event_name == "noon") - { + } + else if (event_name == "noon") + { result = (skyid == LLEnvironment::KNOWN_SKY_MIDDAY); - } + } else if (event_name == "legacy noon") { result = (skyid == LLEnvironment::KNOWN_SKY_LEGACY_MIDDAY); } - else if (event_name == "sunset") - { + else if (event_name == "sunset") + { result = (skyid == LLEnvironment::KNOWN_SKY_SUNSET); - } - else if (event_name == "midnight") - { + } + else if (event_name == "midnight") + { result = (skyid == LLEnvironment::KNOWN_SKY_MIDNIGHT); - } - else if (event_name == "region") - { - return false; - } - else - { - LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL; - } - return result; - } + } + else if (event_name == "region") + { + return false; + } + else + { + LL_WARNS() << "Unknown time-of-day item: " << event_name << LL_ENDL; + } + return result; + } }; class LLWorldEnvPreset : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - std::string item = userdata.asString(); + bool handleEvent(const LLSD& userdata) + { + std::string item = userdata.asString(); - if (item == "new_water") - { + if (item == "new_water") + { LLFloaterReg::showInstance("env_fixed_environmentent_water", "new"); - } - else if (item == "edit_water") - { + } + else if (item == "edit_water") + { LLFloaterReg::showInstance("env_fixed_environmentent_water", "edit"); - } - else if (item == "new_sky") - { + } + else if (item == "new_sky") + { LLFloaterReg::showInstance("env_fixed_environmentent_sky", "new"); - } - else if (item == "edit_sky") - { + } + else if (item == "edit_sky") + { LLFloaterReg::showInstance("env_fixed_environmentent_sky", "edit"); - } - else if (item == "new_day_cycle") - { + } + else if (item == "new_day_cycle") + { + LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory")); + } + else if (item == "edit_day_cycle") + { LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory")); - } - else if (item == "edit_day_cycle") - { - LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory")); - } - else - { - LL_WARNS() << "Unknown item selected" << LL_ENDL; - } + } + else + { + LL_WARNS() << "Unknown item selected" << LL_ENDL; + } - return true; - } + return true; + } }; class LLWorldEnableEnvPreset : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { - return false; - } + return false; + } }; /// Post-Process callbacks class LLWorldPostProcess : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterReg::showInstance("env_post_process"); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloaterReg::showInstance("env_post_process"); + return true; + } }; class LLWorldCheckBanLines : public view_listener_t @@ -9261,689 +9261,689 @@ class LLWorldShowBanLines : public view_listener_t void handle_flush_name_caches() { - if (gCacheName) gCacheName->clear(); + if (gCacheName) gCacheName->clear(); } class LLUploadCostCalculator : public view_listener_t { - std::string mCostStr; - - bool handleEvent(const LLSD& userdata) - { - std::vector fields; - std::string str = userdata.asString(); - boost::split(fields, str, boost::is_any_of(",")); - if (fields.size()<1) - { - return false; - } - std::string menu_name = fields[0]; - std::string asset_type_str = "texture"; - if (fields.size()>1) - { - asset_type_str = fields[1]; - } - LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL; - calculateCost(asset_type_str); - gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr); - - return true; - } - - void calculateCost(const std::string& asset_type_str); + std::string mCostStr; + + bool handleEvent(const LLSD& userdata) + { + std::vector fields; + std::string str = userdata.asString(); + boost::split(fields, str, boost::is_any_of(",")); + if (fields.size()<1) + { + return false; + } + std::string menu_name = fields[0]; + std::string asset_type_str = "texture"; + if (fields.size()>1) + { + asset_type_str = fields[1]; + } + LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL; + calculateCost(asset_type_str); + gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr); + + return true; + } + + void calculateCost(const std::string& asset_type_str); public: - LLUploadCostCalculator() - { - } + LLUploadCostCalculator() + { + } }; class LLUpdateMembershipLabel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText"); - gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str); + bool handleEvent(const LLSD& userdata) + { + const std::string label_str = LLAgentBenefitsMgr::isCurrent("Base") ? LLTrans::getString("MembershipUpgradeText") : LLTrans::getString("MembershipPremiumText"); + gMenuHolder->childSetLabelArg("Membership", "[Membership]", label_str); - return true; - } + return true; + } }; void handle_voice_morphing_subscribe() { - LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); + LLWeb::loadURL(LLTrans::getString("voice_morphing_url")); } void handle_premium_voice_morphing_subscribe() { - LLWeb::loadURL(LLTrans::getString("premium_voice_morphing_url")); + LLWeb::loadURL(LLTrans::getString("premium_voice_morphing_url")); } class LLToggleUIHints : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints"); - // toggle - ui_hints_enabled = !ui_hints_enabled; - gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled); - return true; - } + bool handleEvent(const LLSD& userdata) + { + bool ui_hints_enabled = gSavedSettings.getBOOL("EnableUIHints"); + // toggle + ui_hints_enabled = !ui_hints_enabled; + gSavedSettings.setBOOL("EnableUIHints", ui_hints_enabled); + return true; + } }; void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str) { - S32 upload_cost = -1; + S32 upload_cost = -1; - if (asset_type_str == "texture") - { + if (asset_type_str == "texture") + { // This use minimal texture cost to allow bulk and // texture upload menu options to be visible - upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); - } - else if (asset_type_str == "animation") - { - upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost(); - } - else if (asset_type_str == "sound") - { - upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost(); - } - if (upload_cost < 0) - { - LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL; - } - mCostStr = std::to_string(upload_cost); + upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + } + else if (asset_type_str == "animation") + { + upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost(); + } + else if (asset_type_str == "sound") + { + upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost(); + } + if (upload_cost < 0) + { + LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL; + } + mCostStr = std::to_string(upload_cost); } void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y) { - static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", - gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if(gMenuHolder->hasVisibleMenu()) - { - gMenuHolder->hideMenus(); - } - show_navbar_context_menu->buildDrawLabels(); - show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y); + static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", + gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(gMenuHolder->hasVisibleMenu()) + { + gMenuHolder->hideMenus(); + } + show_navbar_context_menu->buildDrawLabels(); + show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y); } void show_topinfobar_context_menu(LLView* ctrl, S32 x, S32 y) { - static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_topinfobar.xml", - gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + static LLMenuGL* show_topbarinfo_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_topinfobar.xml", + gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild("Landmark"); - if (!LLLandmarkActions::landmarkAlreadyExists()) - { - landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu")); - } - else - { - landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu")); - } + LLMenuItemGL* landmark_item = show_topbarinfo_context_menu->getChild("Landmark"); + if (!LLLandmarkActions::landmarkAlreadyExists()) + { + landmark_item->setLabel(LLTrans::getString("AddLandmarkNavBarMenu")); + } + else + { + landmark_item->setLabel(LLTrans::getString("EditLandmarkNavBarMenu")); + } - if(gMenuHolder->hasVisibleMenu()) - { - gMenuHolder->hideMenus(); - } + if(gMenuHolder->hasVisibleMenu()) + { + gMenuHolder->hideMenus(); + } - show_topbarinfo_context_menu->buildDrawLabels(); - show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y); + show_topbarinfo_context_menu->buildDrawLabels(); + show_topbarinfo_context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(ctrl, show_topbarinfo_context_menu, x, y); } void initialize_edit_menu() { - view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo"); - view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo"); - view_listener_t::addMenu(new LLEditCut(), "Edit.Cut"); - view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy"); - view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste"); - view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete"); - view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll"); - view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect"); - view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff"); - view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo"); - view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo"); - view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut"); - view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy"); - view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste"); - view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete"); - view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll"); - view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect"); + view_listener_t::addMenu(new LLEditUndo(), "Edit.Undo"); + view_listener_t::addMenu(new LLEditRedo(), "Edit.Redo"); + view_listener_t::addMenu(new LLEditCut(), "Edit.Cut"); + view_listener_t::addMenu(new LLEditCopy(), "Edit.Copy"); + view_listener_t::addMenu(new LLEditPaste(), "Edit.Paste"); + view_listener_t::addMenu(new LLEditDelete(), "Edit.Delete"); + view_listener_t::addMenu(new LLEditSelectAll(), "Edit.SelectAll"); + view_listener_t::addMenu(new LLEditDeselect(), "Edit.Deselect"); + view_listener_t::addMenu(new LLEditTakeOff(), "Edit.TakeOff"); + view_listener_t::addMenu(new LLEditEnableUndo(), "Edit.EnableUndo"); + view_listener_t::addMenu(new LLEditEnableRedo(), "Edit.EnableRedo"); + view_listener_t::addMenu(new LLEditEnableCut(), "Edit.EnableCut"); + view_listener_t::addMenu(new LLEditEnableCopy(), "Edit.EnableCopy"); + view_listener_t::addMenu(new LLEditEnablePaste(), "Edit.EnablePaste"); + view_listener_t::addMenu(new LLEditEnableDelete(), "Edit.EnableDelete"); + view_listener_t::addMenu(new LLEditEnableSelectAll(), "Edit.EnableSelectAll"); + view_listener_t::addMenu(new LLEditEnableDeselect(), "Edit.EnableDeselect"); } void initialize_spellcheck_menu() { - LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); - LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); + LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); + LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); - commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2)); - enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2)); - commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1)); - enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1)); - commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1)); - enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1)); + commit.add("SpellCheck.ReplaceWithSuggestion", boost::bind(&handle_spellcheck_replace_with_suggestion, _1, _2)); + enable.add("SpellCheck.VisibleSuggestion", boost::bind(&visible_spellcheck_suggestion, _1, _2)); + commit.add("SpellCheck.AddToDictionary", boost::bind(&handle_spellcheck_add_to_dictionary, _1)); + enable.add("SpellCheck.EnableAddToDictionary", boost::bind(&enable_spellcheck_add_to_dictionary, _1)); + commit.add("SpellCheck.AddToIgnore", boost::bind(&handle_spellcheck_add_to_ignore, _1)); + enable.add("SpellCheck.EnableAddToIgnore", boost::bind(&enable_spellcheck_add_to_ignore, _1)); } void initialize_menus() { - // A parameterized event handler used as ctrl-8/9/0 zoom controls below. - class LLZoomer : public view_listener_t - { - public: - // The "mult" parameter says whether "val" is a multiplier or used to set the value. - LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {} - bool handleEvent(const LLSD& userdata) - { - F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal; - LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad); - gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it. - return true; - } - private: - F32 mVal; - bool mMult; - }; - - LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); - LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); - - // Generic enable and visible - // Don't prepend MenuName.Foo because these can be used in any menu. - enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); - - enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); - - view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); - - view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel"); - - enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); - - // Agent - commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying)); - enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land)); - commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2)); - commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2)); - commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2)); - enable.add("Agent.IsMicrophoneOn", boost::bind(&LLAgent::isMicrophoneOn, _2)); - enable.add("Agent.IsActionAllowed", boost::bind(&LLAgent::isActionAllowed, _2)); - - // File menu - init_menu_file(); - - view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff"); - view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar"); - view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape"); - view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight"); - view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics"); - commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar)); + // A parameterized event handler used as ctrl-8/9/0 zoom controls below. + class LLZoomer : public view_listener_t + { + public: + // The "mult" parameter says whether "val" is a multiplier or used to set the value. + LLZoomer(F32 val, bool mult=true) : mVal(val), mMult(mult) {} + bool handleEvent(const LLSD& userdata) + { + F32 new_fov_rad = mMult ? LLViewerCamera::getInstance()->getDefaultFOV() * mVal : mVal; + LLViewerCamera::getInstance()->setDefaultFOV(new_fov_rad); + gSavedSettings.setF32("CameraAngle", LLViewerCamera::getInstance()->getView()); // setView may have clamped it. + return true; + } + private: + F32 mVal; + bool mMult; + }; + + LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar(); + LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar(); + + // Generic enable and visible + // Don't prepend MenuName.Foo because these can be used in any menu. + enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); + + enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); + + view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); + + view_listener_t::addEnable(new LLUpdateMembershipLabel(), "Membership.UpdateLabel"); + + enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); + + // Agent + commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying)); + enable.add("Agent.enableFlyLand", boost::bind(&enable_fly_land)); + commit.add("Agent.PressMicrophone", boost::bind(&LLAgent::pressMicrophone, _2)); + commit.add("Agent.ReleaseMicrophone", boost::bind(&LLAgent::releaseMicrophone, _2)); + commit.add("Agent.ToggleMicrophone", boost::bind(&LLAgent::toggleMicrophone, _2)); + enable.add("Agent.IsMicrophoneOn", boost::bind(&LLAgent::isMicrophoneOn, _2)); + enable.add("Agent.IsActionAllowed", boost::bind(&LLAgent::isActionAllowed, _2)); + + // File menu + init_menu_file(); + + view_listener_t::addMenu(new LLEditEnableTakeOff(), "Edit.EnableTakeOff"); + view_listener_t::addMenu(new LLEditEnableCustomizeAvatar(), "Edit.EnableCustomizeAvatar"); + view_listener_t::addMenu(new LLEnableEditShape(), "Edit.EnableEditShape"); + view_listener_t::addMenu(new LLEnableHoverHeight(), "Edit.EnableHoverHeight"); + view_listener_t::addMenu(new LLEnableEditPhysics(), "Edit.EnableEditPhysics"); + commit.add("CustomizeAvatar", boost::bind(&handle_customize_avatar)); commit.add("NowWearing", boost::bind(&handle_now_wearing)); - commit.add("EditOutfit", boost::bind(&handle_edit_outfit)); - commit.add("EditShape", boost::bind(&handle_edit_shape)); - commit.add("HoverHeight", boost::bind(&handle_hover_height)); - commit.add("EditPhysics", boost::bind(&handle_edit_physics)); - - // View menu - view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook"); - view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam"); - view_listener_t::addMenu(new LLViewResetView(), "View.ResetView"); - view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); - view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); - view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); - view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); - view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); - view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut"); - view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn"); - view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault"); - view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize"); - view_listener_t::addMenu(new LLViewToggleUI(), "View.ToggleUI"); - - view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook"); - view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam"); - view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter"); - - view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); - view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); - view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); - view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); - view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); - view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); - view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); - - //Communicate Nearby chat - view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat"); - - // Communicate > Voice morphing > Subscribe... - commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe)); - // Communicate > Voice morphing > Premium perk... - commit.add("Communicate.VoiceMorphing.PremiumPerk", boost::bind(&handle_premium_voice_morphing_subscribe)); - LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance(); - enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check" - , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing")); - commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click" - , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing")); - - // World menu - view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); - view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); - view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile"); - view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation"); - view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); - view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway"); - view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb"); - view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome"); - - view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark"); - view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation"); - view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome"); - view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand"); - - view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun"); - - view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings"); - view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings"); - view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset"); - view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset"); - view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess"); + commit.add("EditOutfit", boost::bind(&handle_edit_outfit)); + commit.add("EditShape", boost::bind(&handle_edit_shape)); + commit.add("HoverHeight", boost::bind(&handle_hover_height)); + commit.add("EditPhysics", boost::bind(&handle_edit_physics)); + + // View menu + view_listener_t::addMenu(new LLViewMouselook(), "View.Mouselook"); + view_listener_t::addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam"); + view_listener_t::addMenu(new LLViewResetView(), "View.ResetView"); + view_listener_t::addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); + view_listener_t::addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); + view_listener_t::addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); + view_listener_t::addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); + view_listener_t::addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); + view_listener_t::addMenu(new LLZoomer(1.2f), "View.ZoomOut"); + view_listener_t::addMenu(new LLZoomer(1/1.2f), "View.ZoomIn"); + view_listener_t::addMenu(new LLZoomer(DEFAULT_FIELD_OF_VIEW, false), "View.ZoomDefault"); + view_listener_t::addMenu(new LLViewDefaultUISize(), "View.DefaultUISize"); + view_listener_t::addMenu(new LLViewToggleUI(), "View.ToggleUI"); + + view_listener_t::addMenu(new LLViewEnableMouselook(), "View.EnableMouselook"); + view_listener_t::addMenu(new LLViewEnableJoystickFlycam(), "View.EnableJoystickFlycam"); + view_listener_t::addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter"); + + view_listener_t::addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); + view_listener_t::addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); + view_listener_t::addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); + view_listener_t::addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); + view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); + view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); + view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); + + //Communicate Nearby chat + view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat"); + + // Communicate > Voice morphing > Subscribe... + commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe)); + // Communicate > Voice morphing > Premium perk... + commit.add("Communicate.VoiceMorphing.PremiumPerk", boost::bind(&handle_premium_voice_morphing_subscribe)); + LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance(); + enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check" + , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing")); + commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click" + , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing")); + + // World menu + view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); + view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); + view_listener_t::addMenu(new LLWorldPlaceProfile(), "World.PlaceProfile"); + view_listener_t::addMenu(new LLWorldSetHomeLocation(), "World.SetHomeLocation"); + view_listener_t::addMenu(new LLWorldTeleportHome(), "World.TeleportHome"); + view_listener_t::addMenu(new LLWorldSetAway(), "World.SetAway"); + view_listener_t::addMenu(new LLWorldSetDoNotDisturb(), "World.SetDoNotDisturb"); + view_listener_t::addMenu(new LLWorldLindenHome(), "World.LindenHome"); + + view_listener_t::addMenu(new LLWorldEnableCreateLandmark(), "World.EnableCreateLandmark"); + view_listener_t::addMenu(new LLWorldEnableSetHomeLocation(), "World.EnableSetHomeLocation"); + view_listener_t::addMenu(new LLWorldEnableTeleportHome(), "World.EnableTeleportHome"); + view_listener_t::addMenu(new LLWorldEnableBuyLand(), "World.EnableBuyLand"); + + view_listener_t::addMenu(new LLWorldCheckAlwaysRun(), "World.CheckAlwaysRun"); + + view_listener_t::addMenu(new LLWorldEnvSettings(), "World.EnvSettings"); + view_listener_t::addMenu(new LLWorldEnableEnvSettings(), "World.EnableEnvSettings"); + view_listener_t::addMenu(new LLWorldEnvPreset(), "World.EnvPreset"); + view_listener_t::addMenu(new LLWorldEnableEnvPreset(), "World.EnableEnvPreset"); + view_listener_t::addMenu(new LLWorldPostProcess(), "World.PostProcess"); view_listener_t::addMenu(new LLWorldCheckBanLines() , "World.CheckBanLines"); view_listener_t::addMenu(new LLWorldShowBanLines() , "World.ShowBanLines"); - // Tools menu - view_listener_t::addMenu(new LLToolsSelectTool(), "Tools.SelectTool"); - view_listener_t::addMenu(new LLToolsSelectOnlyMyObjects(), "Tools.SelectOnlyMyObjects"); - view_listener_t::addMenu(new LLToolsSelectOnlyMovableObjects(), "Tools.SelectOnlyMovableObjects"); + // Tools menu + 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 LLToolsSelectInvisibleObjects(), "Tools.SelectInvisibleObjects"); 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"); - view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts"); - view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY"); - view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid"); - view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart"); - commit.add("Tools.Link", boost::bind(&handle_link_objects)); - commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance())); - view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations"); - view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys"); - view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys"); - commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2)); - commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take)); - commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy)); - view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory"); - view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction"); - - view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie"); - view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart"); - enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance())); - enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance())); - view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake"); - enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy)); - enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object)); - enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object)); - view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory"); - - view_listener_t::addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); - view_listener_t::addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); - view_listener_t::addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion"); - view_listener_t::addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion"); - - // Help menu - // most items use the ShowFloater method - view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo"); - - // Advanced menu - view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole"); - view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole"); - view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole"); - - // Advanced > HUD Info - view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo"); - view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo"); - - // Advanced Other Settings - view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache"); - - // Advanced > Render > Types - view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType"); - view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType"); - - //// Advanced > Render > Features - view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); - view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); - - view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); - view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); - - // Advanced > Render > Info Displays - view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay"); - view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay"); - view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo"); - commit.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info)); - view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe"); - view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); - // Develop > Render - view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate"); - view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate"); - view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame"); - view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame"); - view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles"); - view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption"); - view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption"); - view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); - view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); + view_listener_t::addMenu(new LLToolsSelectBySurrounding(), "Tools.SelectBySurrounding"); + view_listener_t::addMenu(new LLToolsShowHiddenSelection(), "Tools.ShowHiddenSelection"); + view_listener_t::addMenu(new LLToolsShowSelectionLightRadius(), "Tools.ShowSelectionLightRadius"); + view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts"); + view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY"); + view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid"); + view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart"); + commit.add("Tools.Link", boost::bind(&handle_link_objects)); + commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance())); + view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations"); + view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys"); + view_listener_t::addMenu(new LLToolsEnableReleaseKeys(), "Tools.EnableReleaseKeys"); + commit.add("Tools.LookAtSelection", boost::bind(&handle_look_at_selection, _2)); + commit.add("Tools.BuyOrTake", boost::bind(&handle_buy_or_take)); + commit.add("Tools.TakeCopy", boost::bind(&handle_take_copy)); + view_listener_t::addMenu(new LLToolsSaveToObjectInventory(), "Tools.SaveToObjectInventory"); + view_listener_t::addMenu(new LLToolsSelectedScriptAction(), "Tools.SelectedScriptAction"); + + view_listener_t::addMenu(new LLToolsEnableToolNotPie(), "Tools.EnableToolNotPie"); + view_listener_t::addMenu(new LLToolsEnableSelectNextPart(), "Tools.EnableSelectNextPart"); + enable.add("Tools.EnableLink", boost::bind(&LLSelectMgr::enableLinkObjects, LLSelectMgr::getInstance())); + enable.add("Tools.EnableUnlink", boost::bind(&LLSelectMgr::enableUnlinkObjects, LLSelectMgr::getInstance())); + view_listener_t::addMenu(new LLToolsEnableBuyOrTake(), "Tools.EnableBuyOrTake"); + enable.add("Tools.EnableTakeCopy", boost::bind(&enable_object_take_copy)); + enable.add("Tools.VisibleBuyObject", boost::bind(&tools_visible_buy_object)); + enable.add("Tools.VisibleTakeObject", boost::bind(&tools_visible_take_object)); + view_listener_t::addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.EnableSaveToObjectInventory"); + + view_listener_t::addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); + view_listener_t::addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); + view_listener_t::addMenu(new LLToolsDoPathfindingRebakeRegion(), "Tools.DoPathfindingRebakeRegion"); + view_listener_t::addMenu(new LLToolsEnablePathfindingRebakeRegion(), "Tools.EnablePathfindingRebakeRegion"); + + // Help menu + // most items use the ShowFloater method + view_listener_t::addMenu(new LLToggleHowTo(), "Help.ToggleHowTo"); + + // Advanced menu + view_listener_t::addMenu(new LLAdvancedToggleConsole(), "Advanced.ToggleConsole"); + view_listener_t::addMenu(new LLAdvancedCheckConsole(), "Advanced.CheckConsole"); + view_listener_t::addMenu(new LLAdvancedDumpInfoToConsole(), "Advanced.DumpInfoToConsole"); + + // Advanced > HUD Info + view_listener_t::addMenu(new LLAdvancedToggleHUDInfo(), "Advanced.ToggleHUDInfo"); + view_listener_t::addMenu(new LLAdvancedCheckHUDInfo(), "Advanced.CheckHUDInfo"); + + // Advanced Other Settings + view_listener_t::addMenu(new LLAdvancedClearGroupCache(), "Advanced.ClearGroupCache"); + + // Advanced > Render > Types + view_listener_t::addMenu(new LLAdvancedToggleRenderType(), "Advanced.ToggleRenderType"); + view_listener_t::addMenu(new LLAdvancedCheckRenderType(), "Advanced.CheckRenderType"); + + //// Advanced > Render > Features + view_listener_t::addMenu(new LLAdvancedToggleFeature(), "Advanced.ToggleFeature"); + view_listener_t::addMenu(new LLAdvancedCheckFeature(), "Advanced.CheckFeature"); + + view_listener_t::addMenu(new LLAdvancedCheckDisplayTextureDensity(), "Advanced.CheckDisplayTextureDensity"); + view_listener_t::addMenu(new LLAdvancedSetDisplayTextureDensity(), "Advanced.SetDisplayTextureDensity"); + + // Advanced > Render > Info Displays + view_listener_t::addMenu(new LLAdvancedToggleInfoDisplay(), "Advanced.ToggleInfoDisplay"); + view_listener_t::addMenu(new LLAdvancedCheckInfoDisplay(), "Advanced.CheckInfoDisplay"); + view_listener_t::addMenu(new LLAdvancedSelectedTextureInfo(), "Advanced.SelectedTextureInfo"); + commit.add("Advanced.SelectedMaterialInfo", boost::bind(&handle_selected_material_info)); + view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe"); + view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe"); + // Develop > Render + view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate"); + view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate"); + view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame"); + view_listener_t::addMenu(new LLAdvancedCheckPeriodicSlowFrame(), "Advanced.CheckPeriodicSlowFrame"); + view_listener_t::addMenu(new LLAdvancedHandleAttachedLightParticles(), "Advanced.HandleAttachedLightParticles"); + view_listener_t::addMenu(new LLAdvancedCheckRenderShadowOption(), "Advanced.CheckRenderShadowOption"); + view_listener_t::addMenu(new LLAdvancedClickRenderShadowOption(), "Advanced.ClickRenderShadowOption"); + view_listener_t::addMenu(new LLAdvancedClickRenderProfile(), "Advanced.ClickRenderProfile"); + view_listener_t::addMenu(new LLAdvancedClickRenderBenchmark(), "Advanced.ClickRenderBenchmark"); view_listener_t::addMenu(new LLAdvancedClickHDRIPreview(), "Advanced.ClickHDRIPreview"); view_listener_t::addMenu(new LLAdvancedClickGLTFScenePreview(), "Advanced.ClickGLTFScenePreview"); - view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); + view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache"); view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain"); - #ifdef TOGGLE_HACKED_GODLIKE_VIEWER - view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode"); - view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode"); - view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode"); - #endif + #ifdef TOGGLE_HACKED_GODLIKE_VIEWER + view_listener_t::addMenu(new LLAdvancedHandleToggleHackedGodmode(), "Advanced.HandleToggleHackedGodmode"); + view_listener_t::addMenu(new LLAdvancedCheckToggleHackedGodmode(), "Advanced.CheckToggleHackedGodmode"); + view_listener_t::addMenu(new LLAdvancedEnableToggleHackedGodmode(), "Advanced.EnableToggleHackedGodmode"); + #endif - // Advanced > World - view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera"); - view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache"); + // Advanced > World + view_listener_t::addMenu(new LLAdvancedDumpScriptedCamera(), "Advanced.DumpScriptedCamera"); + view_listener_t::addMenu(new LLAdvancedDumpRegionObjectCache(), "Advanced.DumpRegionObjectCache"); view_listener_t::addMenu(new LLAdvancedToggleStatsRecorder(), "Advanced.ToggleStatsRecorder"); view_listener_t::addMenu(new LLAdvancedCheckStatsRecorder(), "Advanced.CheckStatsRecorder"); view_listener_t::addMenu(new LLAdvancedToggleInterestList360Mode(), "Advanced.ToggleInterestList360Mode"); view_listener_t::addMenu(new LLAdvancedCheckInterestList360Mode(), "Advanced.CheckInterestList360Mode"); view_listener_t::addMenu(new LLAdvancedResetInterestLists(), "Advanced.ResetInterestLists"); - // Advanced > UI - commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser - commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater - commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); - commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2)); - view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); - view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); - view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); - commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) ); - commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) ); - view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo"); - view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo"); - view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks"); - view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks"); - view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews"); - view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews"); - view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode"); - view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode"); - view_listener_t::addMenu(new LLAdvancedCheckDebugCamera(), "Advanced.CheckDebugCamera"); - view_listener_t::addMenu(new LLAdvancedToggleDebugCamera(), "Advanced.ToggleDebugCamera"); - view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips"); - view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips"); - view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents"); - view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents"); - view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys"); - view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys"); - view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc"); - view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc"); - - // Advanced > XUI - commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance())); - view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames"); - view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames"); - view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs"); - commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches)); - - // Advanced > Character > Grab Baked Texture - view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture"); - view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture"); - - // Advanced > Character > Character Tests - view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML"); - view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML"); - view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry"); - - view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); - view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale"); - - // Advanced > Character > Animation Speed - view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster"); - view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower"); - view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll"); - - // Advanced > Character (toplevel) - view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); - view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader"); - view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo"); - view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo"); - view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt"); - view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt"); - view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt"); - view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt"); - view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates"); - view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates"); - view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD"); - view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD"); - view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis"); - view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); - view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); - view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures"); - view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); - view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); - // Advanced > Network - view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog"); - view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog"); - view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket"); + // Advanced > UI + commit.add("Advanced.WebBrowserTest", boost::bind(&handle_web_browser_test, _2)); // sigh! this one opens the MEDIA browser + commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater + commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); + commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2)); + view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); + view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); + view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); + commit.add("Advanced.DumpTimers", boost::bind(&handle_dump_timers) ); + commit.add("Advanced.DumpFocusHolder", boost::bind(&handle_dump_focus) ); + view_listener_t::addMenu(new LLAdvancedPrintSelectedObjectInfo(), "Advanced.PrintSelectedObjectInfo"); + view_listener_t::addMenu(new LLAdvancedPrintAgentInfo(), "Advanced.PrintAgentInfo"); + view_listener_t::addMenu(new LLAdvancedToggleDebugClicks(), "Advanced.ToggleDebugClicks"); + view_listener_t::addMenu(new LLAdvancedCheckDebugClicks(), "Advanced.CheckDebugClicks"); + view_listener_t::addMenu(new LLAdvancedCheckDebugViews(), "Advanced.CheckDebugViews"); + view_listener_t::addMenu(new LLAdvancedToggleDebugViews(), "Advanced.ToggleDebugViews"); + view_listener_t::addMenu(new LLAdvancedCheckDebugUnicode(), "Advanced.CheckDebugUnicode"); + view_listener_t::addMenu(new LLAdvancedToggleDebugUnicode(), "Advanced.ToggleDebugUnicode"); + view_listener_t::addMenu(new LLAdvancedCheckDebugCamera(), "Advanced.CheckDebugCamera"); + view_listener_t::addMenu(new LLAdvancedToggleDebugCamera(), "Advanced.ToggleDebugCamera"); + view_listener_t::addMenu(new LLAdvancedToggleXUINameTooltips(), "Advanced.ToggleXUINameTooltips"); + view_listener_t::addMenu(new LLAdvancedCheckXUINameTooltips(), "Advanced.CheckXUINameTooltips"); + view_listener_t::addMenu(new LLAdvancedToggleDebugMouseEvents(), "Advanced.ToggleDebugMouseEvents"); + view_listener_t::addMenu(new LLAdvancedCheckDebugMouseEvents(), "Advanced.CheckDebugMouseEvents"); + view_listener_t::addMenu(new LLAdvancedToggleDebugKeys(), "Advanced.ToggleDebugKeys"); + view_listener_t::addMenu(new LLAdvancedCheckDebugKeys(), "Advanced.CheckDebugKeys"); + view_listener_t::addMenu(new LLAdvancedToggleDebugWindowProc(), "Advanced.ToggleDebugWindowProc"); + view_listener_t::addMenu(new LLAdvancedCheckDebugWindowProc(), "Advanced.CheckDebugWindowProc"); + + // Advanced > XUI + commit.add("Advanced.ReloadColorSettings", boost::bind(&LLUIColorTable::loadFromSettings, LLUIColorTable::getInstance())); + view_listener_t::addMenu(new LLAdvancedToggleXUINames(), "Advanced.ToggleXUINames"); + view_listener_t::addMenu(new LLAdvancedCheckXUINames(), "Advanced.CheckXUINames"); + view_listener_t::addMenu(new LLAdvancedSendTestIms(), "Advanced.SendTestIMs"); + commit.add("Advanced.FlushNameCaches", boost::bind(&handle_flush_name_caches)); + + // Advanced > Character > Grab Baked Texture + view_listener_t::addMenu(new LLAdvancedGrabBakedTexture(), "Advanced.GrabBakedTexture"); + view_listener_t::addMenu(new LLAdvancedEnableGrabBakedTexture(), "Advanced.EnableGrabBakedTexture"); + + // Advanced > Character > Character Tests + view_listener_t::addMenu(new LLAdvancedAppearanceToXML(), "Advanced.AppearanceToXML"); + view_listener_t::addMenu(new LLAdvancedEnableAppearanceToXML(), "Advanced.EnableAppearanceToXML"); + view_listener_t::addMenu(new LLAdvancedToggleCharacterGeometry(), "Advanced.ToggleCharacterGeometry"); + + view_listener_t::addMenu(new LLAdvancedTestMale(), "Advanced.TestMale"); + view_listener_t::addMenu(new LLAdvancedTestFemale(), "Advanced.TestFemale"); + + // Advanced > Character > Animation Speed + view_listener_t::addMenu(new LLAdvancedAnimTenFaster(), "Advanced.AnimTenFaster"); + view_listener_t::addMenu(new LLAdvancedAnimTenSlower(), "Advanced.AnimTenSlower"); + view_listener_t::addMenu(new LLAdvancedAnimResetAll(), "Advanced.AnimResetAll"); + + // Advanced > Character (toplevel) + view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault"); + view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader"); + view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo"); + view_listener_t::addMenu(new LLAdvancedCheckAnimationInfo(), "Advanced.CheckAnimationInfo"); + view_listener_t::addMenu(new LLAdvancedToggleShowLookAt(), "Advanced.ToggleShowLookAt"); + view_listener_t::addMenu(new LLAdvancedCheckShowLookAt(), "Advanced.CheckShowLookAt"); + view_listener_t::addMenu(new LLAdvancedToggleShowPointAt(), "Advanced.ToggleShowPointAt"); + view_listener_t::addMenu(new LLAdvancedCheckShowPointAt(), "Advanced.CheckShowPointAt"); + view_listener_t::addMenu(new LLAdvancedToggleDebugJointUpdates(), "Advanced.ToggleDebugJointUpdates"); + view_listener_t::addMenu(new LLAdvancedCheckDebugJointUpdates(), "Advanced.CheckDebugJointUpdates"); + view_listener_t::addMenu(new LLAdvancedToggleDisableLOD(), "Advanced.ToggleDisableLOD"); + view_listener_t::addMenu(new LLAdvancedCheckDisableLOD(), "Advanced.CheckDisableLOD"); + view_listener_t::addMenu(new LLAdvancedToggleDebugCharacterVis(), "Advanced.ToggleDebugCharacterVis"); + view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis"); + view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments"); + view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures"); + view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures"); + view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures"); + // Advanced > Network + view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog"); + view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog"); + view_listener_t::addMenu(new LLAdvancedDropPacket(), "Advanced.DropPacket"); // Advanced > Cache view_listener_t::addMenu(new LLAdvancedPurgeDiskCache(), "Advanced.PurgeDiskCache"); - // Advanced > Recorder - view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot"); - view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); - view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); - view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder"); + // Advanced > Recorder + view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot"); + view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); + view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); + view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder"); - // Advanced > Debugging - view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); - view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror"); + // Advanced > Debugging + view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); + view_listener_t::addMenu(new LLAdvancedForceErrorLlerror(), "Advanced.ForceErrorLlerror"); view_listener_t::addMenu(new LLAdvancedForceErrorLlerrorMsg(), "Advanced.ForceErrorLlerrorMsg"); - view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess"); - view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); - view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); - view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); + view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccess(), "Advanced.ForceErrorBadMemoryAccess"); + view_listener_t::addMenu(new LLAdvancedForceErrorBadMemoryAccessCoro(), "Advanced.ForceErrorBadMemoryAccessCoro"); + view_listener_t::addMenu(new LLAdvancedForceErrorInfiniteLoop(), "Advanced.ForceErrorInfiniteLoop"); + view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareException(), "Advanced.ForceErrorSoftwareException"); view_listener_t::addMenu(new LLAdvancedForceOSException(), "Advanced.ForceErrorOSException"); - view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); - view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); + view_listener_t::addMenu(new LLAdvancedForceErrorSoftwareExceptionCoro(), "Advanced.ForceErrorSoftwareExceptionCoro"); + view_listener_t::addMenu(new LLAdvancedForceErrorDriverCrash(), "Advanced.ForceErrorDriverCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorCoroutineCrash(), "Advanced.ForceErrorCoroutineCrash"); view_listener_t::addMenu(new LLAdvancedForceErrorThreadCrash(), "Advanced.ForceErrorThreadCrash"); - view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer"); + view_listener_t::addMenu(new LLAdvancedForceErrorDisconnectViewer(), "Advanced.ForceErrorDisconnectViewer"); - // Advanced (toplevel) - view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates"); - view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); - view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); + // Advanced (toplevel) + view_listener_t::addMenu(new LLAdvancedToggleShowObjectUpdates(), "Advanced.ToggleShowObjectUpdates"); + view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); + view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); view_listener_t::addMenu(new LLAdvancedCompressFileTest(), "Advanced.CompressFileTest"); - view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings"); - view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); - view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); - view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); - view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector"); - - view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); - view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus"); - - // Develop >Set logging level - view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); - view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); - - //Develop (clear cache immediately) - commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); - - // Develop (Fonts debugging) - commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts)); - commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures)); - - // Admin >Object - view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); - view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf"); - view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive"); - view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete"); - view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock"); - view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs"); - - // Admin >Parcel - view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe"); - view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent"); - view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand"); - - // Admin >Region - view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData"); - // Admin top level - view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState"); - - // Self context menu - view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand"); - enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand)); - view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments"); - - view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments"); - - // we don't use boost::bind directly to delay side tray construction - view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab"); - view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab"); - - // Avatar pie menu - view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode"); - view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode"); - view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); - view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend"); - view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); - commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD())); - view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug"); - view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); - view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); - commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD())); - commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector)); - view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM"); - view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call"); - enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall)); - view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse"); - view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); - view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks"); - view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch"); - view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton"); - view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); - view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); - view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations"); - enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible)); + view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings"); + view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); + view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); + view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); + view_listener_t::addMenu(new LLAdvancedToggleVisualLeakDetector(), "Advanced.ToggleVisualLeakDetector"); + + view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); + view_listener_t::addMenu(new LLAdvancedLeaveAdminStatus(), "Advanced.LeaveAdminStatus"); + + // Develop >Set logging level + view_listener_t::addMenu(new LLDevelopCheckLoggingLevel(), "Develop.CheckLoggingLevel"); + view_listener_t::addMenu(new LLDevelopSetLoggingLevel(), "Develop.SetLoggingLevel"); + + //Develop (clear cache immediately) + commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); + + // Develop (Fonts debugging) + commit.add("Develop.Fonts.Dump", boost::bind(&LLFontGL::dumpFonts)); + commit.add("Develop.Fonts.DumpTextures", boost::bind(&LLFontGL::dumpFontTextures)); + + // Admin >Object + view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); + view_listener_t::addMenu(new LLAdminHandleObjectOwnerSelf(), "Admin.HandleObjectOwnerSelf"); + view_listener_t::addMenu(new LLAdminHandleObjectOwnerPermissive(), "Admin.HandleObjectOwnerPermissive"); + view_listener_t::addMenu(new LLAdminHandleForceDelete(), "Admin.HandleForceDelete"); + view_listener_t::addMenu(new LLAdminHandleObjectLock(), "Admin.HandleObjectLock"); + view_listener_t::addMenu(new LLAdminHandleObjectAssetIDs(), "Admin.HandleObjectAssetIDs"); + + // Admin >Parcel + view_listener_t::addMenu(new LLAdminHandleForceParcelOwnerToMe(), "Admin.HandleForceParcelOwnerToMe"); + view_listener_t::addMenu(new LLAdminHandleForceParcelToContent(), "Admin.HandleForceParcelToContent"); + view_listener_t::addMenu(new LLAdminHandleClaimPublicLand(), "Admin.HandleClaimPublicLand"); + + // Admin >Region + view_listener_t::addMenu(new LLAdminHandleRegionDumpTempAssetData(), "Admin.HandleRegionDumpTempAssetData"); + // Admin top level + view_listener_t::addMenu(new LLAdminOnSaveState(), "Admin.OnSaveState"); + + // Self context menu + view_listener_t::addMenu(new LLSelfToggleSitStand(), "Self.ToggleSitStand"); + enable.add("Self.EnableSitStand", boost::bind(&enable_sit_stand)); + view_listener_t::addMenu(new LLSelfRemoveAllAttachments(), "Self.RemoveAllAttachments"); + + view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments"); + + // we don't use boost::bind directly to delay side tray construction + view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab"); + view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab"); + + // Avatar pie menu + view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode"); + view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode"); + view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); + view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend"); + view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); + commit.add("Avatar.Freeze", boost::bind(&handle_avatar_freeze, LLSD())); + view_listener_t::addMenu(new LLAvatarDebug(), "Avatar.Debug"); + view_listener_t::addMenu(new LLAvatarVisibleDebug(), "Avatar.VisibleDebug"); + view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup"); + commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD())); + commit.add("Avatar.ShowInspector", boost::bind(&handle_avatar_show_inspector)); + view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM"); + view_listener_t::addMenu(new LLAvatarCall(), "Avatar.Call"); + enable.add("Avatar.EnableCall", boost::bind(&LLAvatarActions::canCall)); + view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse"); + view_listener_t::addMenu(new LLAvatarToggleMyProfile(), "Avatar.ToggleMyProfile"); + view_listener_t::addMenu(new LLAvatarTogglePicks(), "Avatar.TogglePicks"); + view_listener_t::addMenu(new LLAvatarToggleSearch(), "Avatar.ToggleSearch"); + view_listener_t::addMenu(new LLAvatarResetSkeleton(), "Avatar.ResetSkeleton"); + view_listener_t::addMenu(new LLAvatarEnableResetSkeleton(), "Avatar.EnableResetSkeleton"); + view_listener_t::addMenu(new LLAvatarResetSkeletonAndAnimations(), "Avatar.ResetSkeletonAndAnimations"); + view_listener_t::addMenu(new LLAvatarResetSelfSkeletonAndAnimations(), "Avatar.ResetSelfSkeletonAndAnimations"); + enable.add("Avatar.IsMyProfileOpen", boost::bind(&my_profile_visible)); enable.add("Avatar.IsPicksTabOpen", boost::bind(&picks_tab_visible)); - commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL"))); - - view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); - enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2)); - - // Object pie menu - view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); - commit.add("Object.Touch", boost::bind(&handle_object_touch)); - commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); - commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); - commit.add("Object.Delete", boost::bind(&handle_object_delete)); - view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); - view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar"); - view_listener_t::addMenu(new LLObjectReturn(), "Object.Return"); - commit.add("Object.Duplicate", boost::bind(&LLSelectMgr::duplicate, LLSelectMgr::getInstance())); - view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse"); - view_listener_t::addMenu(new LLObjectMute(), "Object.Mute"); - - enable.add("Object.VisibleTake", boost::bind(&visible_take_object)); - enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object)); - - commit.add("Object.Buy", boost::bind(&handle_buy)); - commit.add("Object.Edit", boost::bind(&handle_object_edit)); + commit.add("Avatar.OpenMarketplace", boost::bind(&LLWeb::loadURLExternal, gSavedSettings.getString("MarketplaceURL"))); + + view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend"); + enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2)); + + // Object pie menu + view_listener_t::addMenu(new LLObjectBuild(), "Object.Build"); + commit.add("Object.Touch", boost::bind(&handle_object_touch)); + commit.add("Object.ShowOriginal", boost::bind(&handle_object_show_original)); + commit.add("Object.SitOrStand", boost::bind(&handle_object_sit_or_stand)); + commit.add("Object.Delete", boost::bind(&handle_object_delete)); + view_listener_t::addMenu(new LLObjectAttachToAvatar(true), "Object.AttachToAvatar"); + view_listener_t::addMenu(new LLObjectAttachToAvatar(false), "Object.AttachAddToAvatar"); + view_listener_t::addMenu(new LLObjectReturn(), "Object.Return"); + commit.add("Object.Duplicate", boost::bind(&LLSelectMgr::duplicate, LLSelectMgr::getInstance())); + view_listener_t::addMenu(new LLObjectReportAbuse(), "Object.ReportAbuse"); + view_listener_t::addMenu(new LLObjectMute(), "Object.Mute"); + + enable.add("Object.VisibleTake", boost::bind(&visible_take_object)); + enable.add("Object.VisibleBuy", boost::bind(&visible_buy_object)); + + commit.add("Object.Buy", boost::bind(&handle_buy)); + commit.add("Object.Edit", boost::bind(&handle_object_edit)); commit.add("Object.Edit", boost::bind(&handle_object_edit)); commit.add("Object.EditGLTFMaterial", boost::bind(&handle_object_edit_gltf_material)); - commit.add("Object.Inspect", boost::bind(&handle_object_inspect)); - commit.add("Object.Open", boost::bind(&handle_object_open)); - commit.add("Object.Take", boost::bind(&handle_take)); - commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector)); + commit.add("Object.Inspect", boost::bind(&handle_object_inspect)); + commit.add("Object.Open", boost::bind(&handle_object_open)); + commit.add("Object.Take", boost::bind(&handle_take)); + commit.add("Object.ShowInspector", boost::bind(&handle_object_show_inspector)); enable.add("Object.EnableInspect", boost::bind(&enable_object_inspect)); enable.add("Object.EnableEditGLTFMaterial", boost::bind(&enable_object_edit_gltf_material)); - enable.add("Object.EnableOpen", boost::bind(&enable_object_open)); - enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1)); - enable.add("Object.EnableDelete", boost::bind(&enable_object_delete)); - enable.add("Object.EnableWear", boost::bind(&object_is_wearable)); - - enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up)); - enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1)); - - view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn"); - enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance())); - view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); - - enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute)); - enable.add("Object.EnableMute", boost::bind(&enable_object_mute)); - enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute)); - enable.add("Object.EnableBuy", boost::bind(&enable_buy_object)); - commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom")); - - // Attachment pie menu - enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2)); - view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop"); - view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint"); - view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach"); - view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled"); - view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop"); - view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach"); - - // Land pie menu - view_listener_t::addMenu(new LLLandBuild(), "Land.Build"); - view_listener_t::addMenu(new LLLandSit(), "Land.Sit"); + enable.add("Object.EnableOpen", boost::bind(&enable_object_open)); + enable.add("Object.EnableTouch", boost::bind(&enable_object_touch, _1)); + enable.add("Object.EnableDelete", boost::bind(&enable_object_delete)); + enable.add("Object.EnableWear", boost::bind(&object_is_wearable)); + + enable.add("Object.EnableStandUp", boost::bind(&enable_object_stand_up)); + enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1)); + + view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn"); + enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance())); + view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse"); + + enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute)); + enable.add("Object.EnableMute", boost::bind(&enable_object_mute)); + enable.add("Object.EnableUnmute", boost::bind(&enable_object_unmute)); + enable.add("Object.EnableBuy", boost::bind(&enable_buy_object)); + commit.add("Object.ZoomIn", boost::bind(&handle_look_at_selection, "zoom")); + + // Attachment pie menu + enable.add("Attachment.Label", boost::bind(&onEnableAttachmentLabel, _1, _2)); + view_listener_t::addMenu(new LLAttachmentDrop(), "Attachment.Drop"); + view_listener_t::addMenu(new LLAttachmentDetachFromPoint(), "Attachment.DetachFromPoint"); + view_listener_t::addMenu(new LLAttachmentDetach(), "Attachment.Detach"); + view_listener_t::addMenu(new LLAttachmentPointFilled(), "Attachment.PointFilled"); + view_listener_t::addMenu(new LLAttachmentEnableDrop(), "Attachment.EnableDrop"); + view_listener_t::addMenu(new LLAttachmentEnableDetach(), "Attachment.EnableDetach"); + + // Land pie menu + view_listener_t::addMenu(new LLLandBuild(), "Land.Build"); + view_listener_t::addMenu(new LLLandSit(), "Land.Sit"); view_listener_t::addMenu(new LLLandCanSit(), "Land.CanSit"); - view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass"); - view_listener_t::addMenu(new LLLandEdit(), "Land.Edit"); - - // Particle muting - view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute"); - - view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass"); - commit.add("Land.Buy", boost::bind(&handle_buy_land)); - - // Generic actions - commit.add("ReportAbuse", boost::bind(&handle_report_abuse)); - commit.add("BuyCurrency", boost::bind(&handle_buy_currency)); - view_listener_t::addMenu(new LLShowHelp(), "ShowHelp"); - view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp"); - view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak"); - view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL"); - view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); + view_listener_t::addMenu(new LLLandBuyPass(), "Land.BuyPass"); + view_listener_t::addMenu(new LLLandEdit(), "Land.Edit"); + + // Particle muting + view_listener_t::addMenu(new LLMuteParticle(), "Particle.Mute"); + + view_listener_t::addMenu(new LLLandEnableBuyPass(), "Land.EnableBuyPass"); + commit.add("Land.Buy", boost::bind(&handle_buy_land)); + + // Generic actions + commit.add("ReportAbuse", boost::bind(&handle_report_abuse)); + commit.add("BuyCurrency", boost::bind(&handle_buy_currency)); + view_listener_t::addMenu(new LLShowHelp(), "ShowHelp"); + view_listener_t::addMenu(new LLToggleHelp(), "ToggleHelp"); + view_listener_t::addMenu(new LLToggleSpeak(), "ToggleSpeak"); + view_listener_t::addMenu(new LLPromptShowURL(), "PromptShowURL"); + view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile"); view_listener_t::addMenu(new LLShowAgentProfilePicks(), "ShowAgentProfilePicks"); - view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile"); - view_listener_t::addMenu(new LLToggleControl(), "ToggleControl"); + view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile"); + view_listener_t::addMenu(new LLToggleControl(), "ToggleControl"); view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl"); - view_listener_t::addMenu(new LLCheckControl(), "CheckControl"); - view_listener_t::addMenu(new LLGoToObject(), "GoToObject"); - commit.add("PayObject", boost::bind(&handle_give_money_dialog)); - - commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow)); - - enable.add("EnablePayObject", boost::bind(&enable_pay_object)); - enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); - enable.add("EnableEdit", boost::bind(&enable_object_edit)); - enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle)); - enable.add("VisibleBuild", boost::bind(&enable_object_build)); - commit.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects)); - enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets)); - enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets)); - commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects)); - enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters)); + view_listener_t::addMenu(new LLCheckControl(), "CheckControl"); + view_listener_t::addMenu(new LLGoToObject(), "GoToObject"); + commit.add("PayObject", boost::bind(&handle_give_money_dialog)); + + commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow)); + + enable.add("EnablePayObject", boost::bind(&enable_pay_object)); + enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); + enable.add("EnableEdit", boost::bind(&enable_object_edit)); + enable.add("EnableMuteParticle", boost::bind(&enable_mute_particle)); + enable.add("VisibleBuild", boost::bind(&enable_object_build)); + commit.add("Pathfinding.Linksets.Select", boost::bind(&LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects)); + enable.add("EnableSelectInPathfindingLinksets", boost::bind(&enable_object_select_in_pathfinding_linksets)); + enable.add("VisibleSelectInPathfindingLinksets", boost::bind(&visible_object_select_in_pathfinding_linksets)); + commit.add("Pathfinding.Characters.Select", boost::bind(&LLFloaterPathfindingCharacters::openCharactersWithSelectedObjects)); + enable.add("EnableSelectInPathfindingCharacters", boost::bind(&enable_object_select_in_pathfinding_characters)); enable.add("Advanced.EnableErrorOSException", boost::bind(&enable_os_exception)); - view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible"); - view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel"); - view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible"); - view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected"); - view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD"); - view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected"); - view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono"); - view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints"); + view_listener_t::addMenu(new LLFloaterVisible(), "FloaterVisible"); + view_listener_t::addMenu(new LLShowSidetrayPanel(), "ShowSidetrayPanel"); + view_listener_t::addMenu(new LLSidetrayPanelVisible(), "SidetrayPanelVisible"); + view_listener_t::addMenu(new LLSomethingSelected(), "SomethingSelected"); + view_listener_t::addMenu(new LLSomethingSelectedNoHUD(), "SomethingSelectedNoHUD"); + view_listener_t::addMenu(new LLEditableSelected(), "EditableSelected"); + view_listener_t::addMenu(new LLEditableSelectedMono(), "EditableSelectedMono"); + view_listener_t::addMenu(new LLToggleUIHints(), "ToggleUIHints"); } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 240c756411..6283a13148 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewermenufile.cpp * @brief "File" menu in the main menu bar. * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -47,17 +47,17 @@ #include "llimagej2c.h" #include "llimagejpeg.h" #include "llimagetga.h" -#include "llinventorymodel.h" // gInventory +#include "llinventorymodel.h" // gInventory #include "llpluginclassmedia.h" #include "llresourcedata.h" #include "llstatusbar.h" #include "lltinygltfhelper.h" #include "lltoast.h" -#include "llviewercontrol.h" // gSavedSettings +#include "llviewercontrol.h" // gSavedSettings #include "llviewertexturelist.h" #include "lluictrlfactory.h" #include "llviewerinventory.h" -#include "llviewermenu.h" // gMenuHolder +#include "llviewermenu.h" // gMenuHolder #include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewerstats.h" @@ -83,24 +83,24 @@ class LLFileEnableUpload : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { return true; - } + } }; class LLFileEnableUploadModel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model"); - if (fmp && fmp->isModelLoading()) - { - return false; - } - - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model"); + if (fmp && fmp->isModelLoading()) + { + return false; + } + + return true; + } }; class LLFileEnableUploadMaterial : public view_listener_t @@ -118,18 +118,18 @@ class LLFileEnableUploadMaterial : public view_listener_t class LLMeshEnabled : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gSavedSettings.getBOOL("MeshEnabled"); - } + bool handleEvent(const LLSD& userdata) + { + return gSavedSettings.getBOOL("MeshEnabled"); + } }; class LLMeshUploadVisible : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - return gMeshRepo.meshUploadEnabled(); - } + bool handleEvent(const LLSD& userdata) + { + return gMeshRepo.meshUploadEnabled(); + } }; LLMutex* LLFilePickerThread::sMutex = NULL; @@ -139,51 +139,51 @@ void LLFilePickerThread::getFile() { #if LL_WINDOWS // Todo: get rid of LLFilePickerThread and make this modeless - start(); + start(); #elif LL_DARWIN runModeless(); #else - run(); + run(); #endif } -//virtual +//virtual void LLFilePickerThread::run() { #if LL_WINDOWS - bool blocking = false; + bool blocking = false; #else - bool blocking = true; // modal + bool blocking = true; // modal #endif - LLFilePicker picker; - - if (mIsSaveDialog) - { - if (picker.getSaveFile(mSaveFilter, mProposedName, blocking)) - { - mResponses.push_back(picker.getFirstFile()); - } - } - else - { - bool result = mIsGetMultiple ? picker.getMultipleOpenFiles(mLoadFilter, blocking) : picker.getOpenFile(mLoadFilter, blocking); - if (result) - { - std::string filename = picker.getFirstFile(); // consider copying mFiles directly - do - { - mResponses.push_back(filename); - filename = picker.getNextFile(); - } - while (mIsGetMultiple && !filename.empty()); - } - } - - { - LLMutexLock lock(sMutex); - sDeadQ.push(this); - } + LLFilePicker picker; + + if (mIsSaveDialog) + { + if (picker.getSaveFile(mSaveFilter, mProposedName, blocking)) + { + mResponses.push_back(picker.getFirstFile()); + } + } + else + { + bool result = mIsGetMultiple ? picker.getMultipleOpenFiles(mLoadFilter, blocking) : picker.getOpenFile(mLoadFilter, blocking); + if (result) + { + std::string filename = picker.getFirstFile(); // consider copying mFiles directly + do + { + mResponses.push_back(filename); + filename = picker.getNextFile(); + } + while (mIsGetMultiple && !filename.empty()); + } + } + + { + LLMutexLock lock(sMutex); + sDeadQ.push(this); + } } void LLFilePickerThread::runModeless() @@ -206,7 +206,7 @@ void LLFilePickerThread::runModeless() { result = picker.getOpenFileModeless(mLoadFilter, modelessVectorCallback, this); } - + if (!result) { LLMutexLock lock(sMutex); @@ -223,7 +223,7 @@ void LLFilePickerThread::modelessStringCallback(bool success, { picker->mResponses.push_back(response); } - + { LLMutexLock lock(sMutex); sDeadQ.push(picker); @@ -255,7 +255,7 @@ void LLFilePickerThread::modelessVectorCallback(bool success, } } } - + { LLMutexLock lock(sMutex); sDeadQ.push(picker); @@ -265,66 +265,66 @@ void LLFilePickerThread::modelessVectorCallback(bool success, //static void LLFilePickerThread::initClass() { - sMutex = new LLMutex(); + sMutex = new LLMutex(); } //static void LLFilePickerThread::cleanupClass() { - clearDead(); - - delete sMutex; - sMutex = NULL; + clearDead(); + + delete sMutex; + sMutex = NULL; } //static void LLFilePickerThread::clearDead() { - if (!sDeadQ.empty()) - { - LLMutexLock lock(sMutex); - while (!sDeadQ.empty()) - { - LLFilePickerThread* thread = sDeadQ.front(); - thread->notify(thread->mResponses); - delete thread; - sDeadQ.pop(); - } - } + if (!sDeadQ.empty()) + { + LLMutexLock lock(sMutex); + while (!sDeadQ.empty()) + { + LLFilePickerThread* thread = sDeadQ.front(); + thread->notify(thread->mResponses); + delete thread; + sDeadQ.pop(); + } + } } LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb) - : LLFilePickerThread(filter, get_multiple), - mLoadFilter(filter), - mSaveFilter(LLFilePicker::FFSAVE_ALL), - mFilePickedSignal(NULL), - mFailureSignal(NULL) + : LLFilePickerThread(filter, get_multiple), + mLoadFilter(filter), + mSaveFilter(LLFilePicker::FFSAVE_ALL), + mFilePickedSignal(NULL), + mFailureSignal(NULL) { - mFilePickedSignal = new file_picked_signal_t(); - mFilePickedSignal->connect(cb); + mFilePickedSignal = new file_picked_signal_t(); + mFilePickedSignal->connect(cb); - mFailureSignal = new file_picked_signal_t(); - mFailureSignal->connect(failure_cb); + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb) - : LLFilePickerThread(filter, proposed_name), - mLoadFilter(LLFilePicker::FFLOAD_ALL), - mSaveFilter(filter), - mFilePickedSignal(NULL), - mFailureSignal(NULL) + : LLFilePickerThread(filter, proposed_name), + mLoadFilter(LLFilePicker::FFLOAD_ALL), + mSaveFilter(filter), + mFilePickedSignal(NULL), + mFailureSignal(NULL) { - mFilePickedSignal = new file_picked_signal_t(); - mFilePickedSignal->connect(cb); + mFilePickedSignal = new file_picked_signal_t(); + mFilePickedSignal->connect(cb); - mFailureSignal = new file_picked_signal_t(); - mFailureSignal->connect(failure_cb); + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } LLFilePickerReplyThread::~LLFilePickerReplyThread() { - delete mFilePickedSignal; - delete mFailureSignal; + delete mFilePickedSignal; + delete mFailureSignal; } void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type & cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type & failure_cb) @@ -339,20 +339,20 @@ void LLFilePickerReplyThread::startPicker(const file_picked_signal_t::slot_type void LLFilePickerReplyThread::notify(const std::vector& filenames) { - if (filenames.empty()) - { - if (mFailureSignal) - { - (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter); - } - } - else - { - if (mFilePickedSignal) - { - (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); - } - } + if (filenames.empty()) + { + if (mFailureSignal) + { + (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter); + } + } + else + { + if (mFilePickedSignal) + { + (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); + } + } } @@ -389,164 +389,164 @@ static std::string MATERIAL_EXTENSIONS = "gltf glb"; std::string build_extensions_string(LLFilePicker::ELoadFilter filter) { - switch(filter) - { + switch(filter) + { #if LL_WINDOWS - case LLFilePicker::FFLOAD_IMAGE: - return IMAGE_EXTENSIONS; - case LLFilePicker::FFLOAD_WAV: - return SOUND_EXTENSIONS; - case LLFilePicker::FFLOAD_ANIM: - return ANIM_EXTENSIONS; - case LLFilePicker::FFLOAD_SLOBJECT: - return SLOBJECT_EXTENSIONS; - case LLFilePicker::FFLOAD_MODEL: - return MODEL_EXTENSIONS; + case LLFilePicker::FFLOAD_IMAGE: + return IMAGE_EXTENSIONS; + case LLFilePicker::FFLOAD_WAV: + return SOUND_EXTENSIONS; + case LLFilePicker::FFLOAD_ANIM: + return ANIM_EXTENSIONS; + case LLFilePicker::FFLOAD_SLOBJECT: + return SLOBJECT_EXTENSIONS; + case LLFilePicker::FFLOAD_MODEL: + return MODEL_EXTENSIONS; case LLFilePicker::FFLOAD_MATERIAL: return MATERIAL_EXTENSIONS; - case LLFilePicker::FFLOAD_XML: - return XML_EXTENSIONS; + case LLFilePicker::FFLOAD_XML: + return XML_EXTENSIONS; case LLFilePicker::FFLOAD_ALL: case LLFilePicker::FFLOAD_EXE: - return ALL_FILE_EXTENSIONS; + return ALL_FILE_EXTENSIONS; #endif default: - return ALL_FILE_EXTENSIONS; - } + return ALL_FILE_EXTENSIONS; + } } const bool check_file_extension(const std::string& filename, LLFilePicker::ELoadFilter type) { - std::string ext = gDirUtilp->getExtension(filename); - - //strincmp doesn't like NULL pointers - if (ext.empty()) - { - std::string short_name = gDirUtilp->getBaseFileName(filename); - - // No extension - LLSD args; - args["FILE"] = short_name; - LLNotificationsUtil::add("NoFileExtension", args); - return false; - } - else - { - //so there is an extension - //loop over the valid extensions and compare to see - //if the extension is valid - - //now grab the set of valid file extensions - std::string valid_extensions = build_extensions_string(type); - - BOOL ext_valid = FALSE; - - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(" "); - tokenizer tokens(valid_extensions, sep); - tokenizer::iterator token_iter; - - //now loop over all valid file extensions - //and compare them to the extension of the file - //to be uploaded - for (token_iter = tokens.begin(); - token_iter != tokens.end() && ext_valid != TRUE; - ++token_iter) - { - const std::string& cur_token = *token_iter; - - if (cur_token == ext || cur_token == "*.*") - { - //valid extension - //or the acceptable extension is any - ext_valid = TRUE; - } - }//end for (loop over all tokens) - - if (ext_valid == FALSE) - { - //should only get here if the extension exists - //but is invalid - LLSD args; - args["EXTENSION"] = ext; - args["VALIDS"] = valid_extensions; - LLNotificationsUtil::add("InvalidFileExtension", args); - return false; - } - }//end else (non-null extension) - return true; + std::string ext = gDirUtilp->getExtension(filename); + + //strincmp doesn't like NULL pointers + if (ext.empty()) + { + std::string short_name = gDirUtilp->getBaseFileName(filename); + + // No extension + LLSD args; + args["FILE"] = short_name; + LLNotificationsUtil::add("NoFileExtension", args); + return false; + } + else + { + //so there is an extension + //loop over the valid extensions and compare to see + //if the extension is valid + + //now grab the set of valid file extensions + std::string valid_extensions = build_extensions_string(type); + + BOOL ext_valid = FALSE; + + typedef boost::tokenizer > tokenizer; + boost::char_separator sep(" "); + tokenizer tokens(valid_extensions, sep); + tokenizer::iterator token_iter; + + //now loop over all valid file extensions + //and compare them to the extension of the file + //to be uploaded + for (token_iter = tokens.begin(); + token_iter != tokens.end() && ext_valid != TRUE; + ++token_iter) + { + const std::string& cur_token = *token_iter; + + if (cur_token == ext || cur_token == "*.*") + { + //valid extension + //or the acceptable extension is any + ext_valid = TRUE; + } + }//end for (loop over all tokens) + + if (ext_valid == FALSE) + { + //should only get here if the extension exists + //but is invalid + LLSD args; + args["EXTENSION"] = ext; + args["VALIDS"] = valid_extensions; + LLNotificationsUtil::add("InvalidFileExtension", args); + return false; + } + }//end else (non-null extension) + return true; } const void upload_single_file(const std::vector& filenames, LLFilePicker::ELoadFilter type) { - std::string filename = filenames[0]; - if (!check_file_extension(filename, type)) return; - - if (!filename.empty()) - { - if (type == LLFilePicker::FFLOAD_WAV) - { - // pre-qualify wavs to make sure the format is acceptable - std::string error_msg; - if (check_for_invalid_wav_formats(filename, error_msg)) - { - LL_INFOS() << error_msg << ": " << filename << LL_ENDL; - LLSD args; - args["FILE"] = filename; - LLNotificationsUtil::add(error_msg, args); - return; - } - else - { - LLFloaterReg::showInstance("upload_sound", LLSD(filename)); - } - } - if (type == LLFilePicker::FFLOAD_IMAGE) - { - LLFloaterReg::showInstance("upload_image", LLSD(filename)); - } - if (type == LLFilePicker::FFLOAD_ANIM) - { - std::string filename_lc(filename); - LLStringUtil::toLower(filename_lc); - if (filename_lc.rfind(".anim") != std::string::npos) - { - LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename)); - } - else - { - LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename)); - } - } - } - return; + std::string filename = filenames[0]; + if (!check_file_extension(filename, type)) return; + + if (!filename.empty()) + { + if (type == LLFilePicker::FFLOAD_WAV) + { + // pre-qualify wavs to make sure the format is acceptable + std::string error_msg; + if (check_for_invalid_wav_formats(filename, error_msg)) + { + LL_INFOS() << error_msg << ": " << filename << LL_ENDL; + LLSD args; + args["FILE"] = filename; + LLNotificationsUtil::add(error_msg, args); + return; + } + else + { + LLFloaterReg::showInstance("upload_sound", LLSD(filename)); + } + } + if (type == LLFilePicker::FFLOAD_IMAGE) + { + LLFloaterReg::showInstance("upload_image", LLSD(filename)); + } + if (type == LLFilePicker::FFLOAD_ANIM) + { + std::string filename_lc(filename); + LLStringUtil::toLower(filename_lc); + if (filename_lc.rfind(".anim") != std::string::npos) + { + LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename)); + } + else + { + LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename)); + } + } + } + return; } void do_bulk_upload(std::vector filenames, const LLSD& notification, const LLSD& response) { - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) - { - // Cancel upload - return; - } - - for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) - { - std::string filename = (*in_iter); - - std::string name = gDirUtilp->getBaseFileName(filename, true); - std::string asset_name = name; - LLStringUtil::replaceNonstandardASCII(asset_name, '?'); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - std::string ext = gDirUtilp->getExtension(filename); - LLAssetType::EType asset_type; - U32 codec; - S32 expected_upload_cost = 0; + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) + { + // Cancel upload + return; + } + + for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) + { + std::string filename = (*in_iter); + + std::string name = gDirUtilp->getBaseFileName(filename, true); + std::string asset_name = name; + LLStringUtil::replaceNonstandardASCII(asset_name, '?'); + LLStringUtil::replaceChar(asset_name, '|', '?'); + LLStringUtil::stripNonprintable(asset_name); + LLStringUtil::trim(asset_name); + + std::string ext = gDirUtilp->getExtension(filename); + LLAssetType::EType asset_type; + U32 codec; + S32 expected_upload_cost = 0; if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec)) { @@ -603,25 +603,25 @@ void do_bulk_upload(std::vector filenames, const LLSD& notification bool get_bulk_upload_expected_cost(const std::vector& filenames, S32& total_cost, S32& file_count, S32& bvh_count) { - total_cost = 0; - file_count = 0; - bvh_count = 0; - for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) - { - std::string filename = (*in_iter); - std::string ext = gDirUtilp->getExtension(filename); - - if (ext == "bvh") - { - bvh_count++; - } - - LLAssetType::EType asset_type; - U32 codec; - S32 cost; - - if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec)) - { + total_cost = 0; + file_count = 0; + bvh_count = 0; + for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) + { + std::string filename = (*in_iter); + std::string ext = gDirUtilp->getExtension(filename); + + if (ext == "bvh") + { + bvh_count++; + } + + LLAssetType::EType asset_type; + U32 codec; + S32 cost; + + if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec)) + { if (asset_type == LLAssetType::AT_TEXTURE) { LLPointer image_frmted = LLImageFormatted::createFromType(codec); @@ -677,87 +677,87 @@ bool get_bulk_upload_expected_cost(const std::vector& filenames, S3 } } } - } - + } + return file_count > 0; } const void upload_bulk(const std::vector& filenames, LLFilePicker::ELoadFilter type) { - // TODO: - // Check user balance for entire cost - // Charge user entire cost - // Loop, uploading - // If an upload fails, refund the user for that one - // - // Also fix single upload to charge first, then refund - - // FIXME PREMIUM what about known types that can't be bulk uploaded - // (bvh)? These will fail in the item by item upload but won't be - // mentioned in the notification. - std::vector filtered_filenames; - for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) - { - const std::string& filename = *in_iter; - if (check_file_extension(filename, type)) - { - filtered_filenames.push_back(filename); - } - } - - S32 expected_upload_cost; - S32 expected_upload_count; - S32 bvh_count; - if (get_bulk_upload_expected_cost(filtered_filenames, expected_upload_cost, expected_upload_count, bvh_count)) - { - LLSD args; - args["COST"] = expected_upload_cost; - args["COUNT"] = expected_upload_count; - LLNotificationsUtil::add("BulkUploadCostConfirmation", args, LLSD(), boost::bind(do_bulk_upload, filtered_filenames, _1, _2)); - - if (filtered_filenames.size() > expected_upload_count) - { - if (bvh_count == filtered_filenames.size() - expected_upload_count) - { - LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload"); - } - else - { - LLNotificationsUtil::add("BulkUploadIncompatibleFiles"); - } - } - } - else if (bvh_count == filtered_filenames.size()) - { - LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload"); - } - else - { - LLNotificationsUtil::add("BulkUploadNoCompatibleFiles"); - } + // TODO: + // Check user balance for entire cost + // Charge user entire cost + // Loop, uploading + // If an upload fails, refund the user for that one + // + // Also fix single upload to charge first, then refund + + // FIXME PREMIUM what about known types that can't be bulk uploaded + // (bvh)? These will fail in the item by item upload but won't be + // mentioned in the notification. + std::vector filtered_filenames; + for (std::vector::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter) + { + const std::string& filename = *in_iter; + if (check_file_extension(filename, type)) + { + filtered_filenames.push_back(filename); + } + } + + S32 expected_upload_cost; + S32 expected_upload_count; + S32 bvh_count; + if (get_bulk_upload_expected_cost(filtered_filenames, expected_upload_cost, expected_upload_count, bvh_count)) + { + LLSD args; + args["COST"] = expected_upload_cost; + args["COUNT"] = expected_upload_count; + LLNotificationsUtil::add("BulkUploadCostConfirmation", args, LLSD(), boost::bind(do_bulk_upload, filtered_filenames, _1, _2)); + + if (filtered_filenames.size() > expected_upload_count) + { + if (bvh_count == filtered_filenames.size() - expected_upload_count) + { + LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload"); + } + else + { + LLNotificationsUtil::add("BulkUploadIncompatibleFiles"); + } + } + } + else if (bvh_count == filtered_filenames.size()) + { + LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload"); + } + else + { + LLNotificationsUtil::add("BulkUploadNoCompatibleFiles"); + } } class LLFileUploadImage : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false); - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); + } + LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_IMAGE, false); + return true; + } }; class LLFileUploadModel : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { LLFloaterModelPreview::showModelPreview(); return TRUE; - } + } }; class LLFileUploadMaterial : public view_listener_t @@ -771,213 +771,213 @@ class LLFileUploadMaterial : public view_listener_t class LLFileUploadSound : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false); - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); + } + LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_WAV, false); + return true; + } }; class LLFileUploadAnim : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false); - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); + } + LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2), LLFilePicker::FFLOAD_ANIM, false); + return true; + } }; class LLFileUploadBulk : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - if (gAgentCamera.cameraMouselook()) - { - gAgentCamera.changeCameraToDefault(); - } - LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true); - return true; - } + bool handleEvent(const LLSD& userdata) + { + if (gAgentCamera.cameraMouselook()) + { + gAgentCamera.changeCameraToDefault(); + } + LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2), LLFilePicker::FFLOAD_ALL, true); + return true; + } }; -void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args) +void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args) { - LL_WARNS() << error_message << LL_ENDL; - LLNotificationsUtil::add(label, args); - if(LLFile::remove(filename) == -1) - { - LL_DEBUGS() << "unable to remove temp file" << LL_ENDL; - } - LLFilePicker::instance().reset(); + LL_WARNS() << error_message << LL_ENDL; + LLNotificationsUtil::add(label, args); + if(LLFile::remove(filename) == -1) + { + LL_DEBUGS() << "unable to remove temp file" << LL_ENDL; + } + LLFilePicker::instance().reset(); } class LLFileEnableCloseWindow : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater()); - bool frontmost_snapshot_fl_exists = (NULL != gSnapshotFloaterView->getFrontmostClosableFloater()); + bool handleEvent(const LLSD& userdata) + { + bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater()); + bool frontmost_snapshot_fl_exists = (NULL != gSnapshotFloaterView->getFrontmostClosableFloater()); - return !LLNotificationsUI::LLToast::isAlertToastShown() && (frontmost_fl_exists || frontmost_snapshot_fl_exists); - } + return !LLNotificationsUI::LLToast::isAlertToastShown() && (frontmost_fl_exists || frontmost_snapshot_fl_exists); + } }; class LLFileCloseWindow : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater()); - LLFloater* snapshot_floater = gSnapshotFloaterView->getFrontmostClosableFloater(); - - if(snapshot_floater && (!frontmost_fl_exists || snapshot_floater->hasFocus())) - { - snapshot_floater->closeFloater(); - if (gFocusMgr.getKeyboardFocus() == NULL) - { - gFloaterView->focusFrontFloater(); - } - } - else - { - LLFloater::closeFrontmostFloater(); - } - if (gMenuHolder) gMenuHolder->hideMenus(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + bool frontmost_fl_exists = (NULL != gFloaterView->getFrontmostClosableFloater()); + LLFloater* snapshot_floater = gSnapshotFloaterView->getFrontmostClosableFloater(); + + if(snapshot_floater && (!frontmost_fl_exists || snapshot_floater->hasFocus())) + { + snapshot_floater->closeFloater(); + if (gFocusMgr.getKeyboardFocus() == NULL) + { + gFloaterView->focusFrontFloater(); + } + } + else + { + LLFloater::closeFrontmostFloater(); + } + if (gMenuHolder) gMenuHolder->hideMenus(); + return true; + } }; class LLFileEnableCloseAllWindows : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); - bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain()); - bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened; - return !open_children && !LLNotificationsUI::LLToast::isAlertToastShown(); - } + bool handleEvent(const LLSD& userdata) + { + LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); + bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain()); + bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened; + return !open_children && !LLNotificationsUI::LLToast::isAlertToastShown(); + } }; class LLFileCloseAllWindows : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - bool app_quitting = false; - gFloaterView->closeAllChildren(app_quitting); - LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); - if (floater_snapshot) - floater_snapshot->closeFloater(app_quitting); - if (gMenuHolder) gMenuHolder->hideMenus(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + bool app_quitting = false; + gFloaterView->closeAllChildren(app_quitting); + LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); + if (floater_snapshot) + floater_snapshot->closeFloater(app_quitting); + if (gMenuHolder) gMenuHolder->hideMenus(); + return true; + } }; class LLFileTakeSnapshotToDisk : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLPointer raw = new LLImageRaw; - - S32 width = gViewerWindow->getWindowWidthRaw(); - S32 height = gViewerWindow->getWindowHeightRaw(); - - BOOL render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot"); - BOOL render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot"); - BOOL render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost"); - - BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot"); - if (high_res) - { - width *= 2; - height *= 2; - // not compatible with UI/HUD - render_ui = false; - render_hud = false; - } - - if (gViewerWindow->rawSnapshot(raw, - width, - height, - TRUE, - FALSE, - render_ui, - render_hud, - FALSE, - render_no_post, - LLSnapshotModel::SNAPSHOT_TYPE_COLOR, - high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side - { - LLPointer formatted; + bool handleEvent(const LLSD& userdata) + { + LLPointer raw = new LLImageRaw; + + S32 width = gViewerWindow->getWindowWidthRaw(); + S32 height = gViewerWindow->getWindowHeightRaw(); + + BOOL render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot"); + BOOL render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot"); + BOOL render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost"); + + BOOL high_res = gSavedSettings.getBOOL("HighResSnapshot"); + if (high_res) + { + width *= 2; + height *= 2; + // not compatible with UI/HUD + render_ui = false; + render_hud = false; + } + + if (gViewerWindow->rawSnapshot(raw, + width, + height, + TRUE, + FALSE, + render_ui, + render_hud, + FALSE, + render_no_post, + LLSnapshotModel::SNAPSHOT_TYPE_COLOR, + high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side + { + LLPointer formatted; LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); - switch (fmt) - { - case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: - formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); - break; - default: - LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; - case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: - formatted = new LLImagePNG; - break; - case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: - formatted = new LLImageBMP; - break; - } - formatted->enableOverSize() ; - formatted->encode(raw, 0); - formatted->disableOverSize() ; - LLSnapshotLivePreview::saveLocal(formatted); - } - return true; - } + switch (fmt) + { + case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: + formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); + break; + default: + LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; + case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: + formatted = new LLImagePNG; + break; + case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: + formatted = new LLImageBMP; + break; + } + formatted->enableOverSize() ; + formatted->encode(raw, 0); + formatted->disableOverSize() ; + LLSnapshotLivePreview::saveLocal(formatted); + } + return true; + } }; class LLFileQuit : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { - LLAppViewer::instance()->userQuit(); - return true; - } + bool handleEvent(const LLSD& userdata) + { + LLAppViewer::instance()->userQuit(); + return true; + } }; void handle_compress_image(void*) { - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE)) - { - std::string infile = picker.getFirstFile(); - while (!infile.empty()) - { - std::string outfile = infile + ".j2c"; - - LL_INFOS() << "Input: " << infile << LL_ENDL; - LL_INFOS() << "Output: " << outfile << LL_ENDL; - - BOOL success; - - success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA); - - if (success) - { - LL_INFOS() << "Compression complete" << LL_ENDL; - } - else - { - LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL; - } - - infile = picker.getNextFile(); - } - } + LLFilePicker& picker = LLFilePicker::instance(); + if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE)) + { + std::string infile = picker.getFirstFile(); + while (!infile.empty()) + { + std::string outfile = infile + ".j2c"; + + LL_INFOS() << "Input: " << infile << LL_ENDL; + LL_INFOS() << "Output: " << outfile << LL_ENDL; + + BOOL success; + + success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA); + + if (success) + { + LL_INFOS() << "Compression complete" << LL_ENDL; + } + else + { + LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL; + } + + infile = picker.getNextFile(); + } + } } // No convinient check in LLFile, and correct way would be something @@ -985,7 +985,7 @@ void handle_compress_image(void*) // so doing dirty, but OS independent fopen and fseek size_t get_file_size(std::string &filename) { - LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ + LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if (!file) { LL_WARNS() << "Error opening " << filename << LL_ENDL; @@ -1070,21 +1070,21 @@ void handle_compress_file_test(void*) LLUUID upload_new_resource( - const std::string& src_filename, - std::string name, - std::string desc, - S32 compression_info, - LLFolderType::EType destination_folder_type, - LLInventoryType::EType inv_type, - U32 next_owner_perms, - U32 group_perms, - U32 everyone_perms, - const std::string& display_name, - LLAssetStorage::LLStoreAssetCallback callback, - S32 expected_upload_cost, - void *userdata, - bool show_inventory) -{ + const std::string& src_filename, + std::string name, + std::string desc, + S32 compression_info, + LLFolderType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms, + const std::string& display_name, + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata, + bool show_inventory) +{ LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared( src_filename, @@ -1098,127 +1098,127 @@ LLUUID upload_new_resource( } void upload_done_callback( - const LLUUID& uuid, - void* user_data, - S32 result, - LLExtStat ext_status) // StoreAssetData callback (fixed) + const LLUUID& uuid, + void* user_data, + S32 result, + LLExtStat ext_status) // StoreAssetData callback (fixed) { - LLResourceData* data = (LLResourceData*)user_data; - S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0; - //LLAssetType::EType pref_loc = data->mPreferredLocation; - BOOL is_balance_sufficient = TRUE; - - if(data) - { - if (result >= 0) - { - LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation; - - if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || - LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || - LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) - { - // Charge the user for the upload. - LLViewerRegion* region = gAgent.getRegion(); - - if(!(can_afford_transaction(expected_upload_cost))) - { - LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost ); - is_balance_sufficient = FALSE; - } - else if(region) - { - // Charge user for upload - gStatusBar->debitBalance(expected_upload_cost); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoneyTransferRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); - msg->addU8("Flags", 0); - // we tell the sim how much we were expecting to pay so it - // can respond to any discrepancy - msg->addS32Fast(_PREHASH_Amount, expected_upload_cost); - msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); - msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); - msg->addStringFast(_PREHASH_Description, NULL); - msg->sendReliable(region->getHost()); - } - } - - if(is_balance_sufficient) - { - // Actually add the upload to inventory - LL_INFOS() << "Adding " << uuid << " to inventory." << LL_ENDL; - const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc); - if(folder_id.notNull()) - { - U32 next_owner_perms = data->mNextOwnerPerm; - if(PERM_NONE == next_owner_perms) - { - next_owner_perms = PERM_MOVE | PERM_TRANSFER; - } - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), - data->mAssetInfo.getDescription(), data->mAssetInfo.mType, + LLResourceData* data = (LLResourceData*)user_data; + S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0; + //LLAssetType::EType pref_loc = data->mPreferredLocation; + BOOL is_balance_sufficient = TRUE; + + if(data) + { + if (result >= 0) + { + LLFolderType::EType dest_loc = (data->mPreferredLocation == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(data->mAssetInfo.mType) : data->mPreferredLocation; + + if (LLAssetType::AT_SOUND == data->mAssetInfo.mType || + LLAssetType::AT_TEXTURE == data->mAssetInfo.mType || + LLAssetType::AT_ANIMATION == data->mAssetInfo.mType) + { + // Charge the user for the upload. + LLViewerRegion* region = gAgent.getRegion(); + + if(!(can_afford_transaction(expected_upload_cost))) + { + LLBuyCurrencyHTML::openCurrencyFloater( "", expected_upload_cost ); + is_balance_sufficient = FALSE; + } + else if(region) + { + // Charge user for upload + gStatusBar->debitBalance(expected_upload_cost); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoneyTransferRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MoneyData); + msg->addUUIDFast(_PREHASH_SourceID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_DestID, LLUUID::null); + msg->addU8("Flags", 0); + // we tell the sim how much we were expecting to pay so it + // can respond to any discrepancy + msg->addS32Fast(_PREHASH_Amount, expected_upload_cost); + msg->addU8Fast(_PREHASH_AggregatePermNextOwner, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addU8Fast(_PREHASH_AggregatePermInventory, (U8)LLAggregatePermissions::AP_EMPTY); + msg->addS32Fast(_PREHASH_TransactionType, TRANS_UPLOAD_CHARGE); + msg->addStringFast(_PREHASH_Description, NULL); + msg->sendReliable(region->getHost()); + } + } + + if(is_balance_sufficient) + { + // Actually add the upload to inventory + LL_INFOS() << "Adding " << uuid << " to inventory." << LL_ENDL; + const LLUUID folder_id = gInventory.findCategoryUUIDForType(dest_loc); + if(folder_id.notNull()) + { + U32 next_owner_perms = data->mNextOwnerPerm; + if(PERM_NONE == next_owner_perms) + { + next_owner_perms = PERM_MOVE | PERM_TRANSFER; + } + create_inventory_item(gAgent.getID(), gAgent.getSessionID(), + folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(), + data->mAssetInfo.getDescription(), data->mAssetInfo.mType, data->mInventoryType, NO_INV_SUBTYPE, next_owner_perms, - LLPointer(NULL)); - } - else - { - LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; - } - } - } - else // if(result >= 0) - { - LLSD args; - args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); - args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotificationsUtil::add("CannotUploadReason", args); - } - - delete data; - data = NULL; - } - - LLUploadDialog::modalUploadFinished(); - - // *NOTE: This is a pretty big hack. What this does is check the - // file picker if there are any more pending uploads. If so, - // upload that file. - const std::string& next_file = LLFilePicker::instance().getNextFile(); - if(is_balance_sufficient && !next_file.empty()) - { - std::string asset_name = gDirUtilp->getBaseFileName(next_file, true); - LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback; - void *userdata = NULL; - upload_new_resource( - next_file, - asset_name, - asset_name, // file - 0, - LLFolderType::FT_NONE, - LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms("Uploads"), - LLFloaterPerms::getGroupPerms("Uploads"), - LLFloaterPerms::getEveryonePerms("Uploads"), - display_name, - callback, - expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost - userdata); - } + LLPointer(NULL)); + } + else + { + LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; + } + } + } + else // if(result >= 0) + { + LLSD args; + args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); + args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); + LLNotificationsUtil::add("CannotUploadReason", args); + } + + delete data; + data = NULL; + } + + LLUploadDialog::modalUploadFinished(); + + // *NOTE: This is a pretty big hack. What this does is check the + // file picker if there are any more pending uploads. If so, + // upload that file. + const std::string& next_file = LLFilePicker::instance().getNextFile(); + if(is_balance_sufficient && !next_file.empty()) + { + std::string asset_name = gDirUtilp->getBaseFileName(next_file, true); + LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); + LLStringUtil::replaceChar(asset_name, '|', '?'); + LLStringUtil::stripNonprintable(asset_name); + LLStringUtil::trim(asset_name); + + std::string display_name = LLStringUtil::null; + LLAssetStorage::LLStoreAssetCallback callback; + void *userdata = NULL; + upload_new_resource( + next_file, + asset_name, + asset_name, // file + 0, + LLFolderType::FT_NONE, + LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), + display_name, + callback, + expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost + userdata); + } } void upload_new_resource( @@ -1226,90 +1226,90 @@ void upload_new_resource( LLAssetStorage::LLStoreAssetCallback callback, void *userdata) { - if(gDisconnected) - { - return ; - } + if(gDisconnected) + { + return ; + } // uploadInfo->setAssetType(assetType); // uploadInfo->setTransactionId(tid); - std::string url = gAgent.getRegionCapability("NewFileAgentInventory"); + std::string url = gAgent.getRegionCapability("NewFileAgentInventory"); - if ( !url.empty() ) - { + if ( !url.empty() ) + { LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); - } - else - { + } + else + { uploadInfo->prepareUpload(); uploadInfo->logPreparedUpload(); - LL_INFOS() << "NewAgentInventory capability not found, new agent inventory via asset system." << LL_ENDL; - // check for adequate funds - // TODO: do this check on the sim - if (LLAssetType::AT_SOUND == uploadInfo->getAssetType() || + LL_INFOS() << "NewAgentInventory capability not found, new agent inventory via asset system." << LL_ENDL; + // check for adequate funds + // TODO: do this check on the sim + if (LLAssetType::AT_SOUND == uploadInfo->getAssetType() || LLAssetType::AT_TEXTURE == uploadInfo->getAssetType() || LLAssetType::AT_ANIMATION == uploadInfo->getAssetType()) - { - S32 balance = gStatusBar->getBalance(); - if (balance < uploadInfo->getExpectedUploadCost()) - { - // insufficient funds, bail on this upload + { + S32 balance = gStatusBar->getBalance(); + if (balance < uploadInfo->getExpectedUploadCost()) + { + // insufficient funds, bail on this upload LLBuyCurrencyHTML::openCurrencyFloater("", uploadInfo->getExpectedUploadCost()); - return; - } - } + return; + } + } - LLResourceData* data = new LLResourceData; - data->mAssetInfo.mTransactionID = uploadInfo->getTransactionId(); - data->mAssetInfo.mUuid = uploadInfo->getAssetId(); + LLResourceData* data = new LLResourceData; + data->mAssetInfo.mTransactionID = uploadInfo->getTransactionId(); + data->mAssetInfo.mUuid = uploadInfo->getAssetId(); data->mAssetInfo.mType = uploadInfo->getAssetType(); - data->mAssetInfo.mCreatorID = gAgentID; - data->mInventoryType = uploadInfo->getInventoryType(); - data->mNextOwnerPerm = uploadInfo->getNextOwnerPerms(); - data->mExpectedUploadCost = uploadInfo->getExpectedUploadCost(); - data->mUserData = userdata; - data->mAssetInfo.setName(uploadInfo->getName()); - data->mAssetInfo.setDescription(uploadInfo->getDescription()); - data->mPreferredLocation = uploadInfo->getDestinationFolderType(); - - LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; - if (callback) - { - asset_callback = callback; - } - gAssetStorage->storeAssetData( - data->mAssetInfo.mTransactionID, - data->mAssetInfo.mType, - asset_callback, - (void*)data, - FALSE); - } + data->mAssetInfo.mCreatorID = gAgentID; + data->mInventoryType = uploadInfo->getInventoryType(); + data->mNextOwnerPerm = uploadInfo->getNextOwnerPerms(); + data->mExpectedUploadCost = uploadInfo->getExpectedUploadCost(); + data->mUserData = userdata; + data->mAssetInfo.setName(uploadInfo->getName()); + data->mAssetInfo.setDescription(uploadInfo->getDescription()); + data->mPreferredLocation = uploadInfo->getDestinationFolderType(); + + LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; + if (callback) + { + asset_callback = callback; + } + gAssetStorage->storeAssetData( + data->mAssetInfo.mTransactionID, + data->mAssetInfo.mType, + asset_callback, + (void*)data, + FALSE); + } } void init_menu_file() { - view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage"); - view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); - view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); - view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); + view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage"); + view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound"); + view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim"); + view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel"); view_listener_t::addCommit(new LLFileUploadMaterial(), "File.UploadMaterial"); - view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); - view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); - view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); - view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow"); - view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows"); - view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk"); - view_listener_t::addCommit(new LLFileQuit(), "File.Quit"); - - view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload"); - view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel"); + view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk"); + view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow"); + view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows"); + view_listener_t::addEnable(new LLFileEnableCloseWindow(), "File.EnableCloseWindow"); + view_listener_t::addEnable(new LLFileEnableCloseAllWindows(), "File.EnableCloseAllWindows"); + view_listener_t::addCommit(new LLFileTakeSnapshotToDisk(), "File.TakeSnapshotToDisk"); + view_listener_t::addCommit(new LLFileQuit(), "File.Quit"); + + view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload"); + view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel"); view_listener_t::addEnable(new LLFileEnableUploadMaterial(), "File.EnableUploadMaterial"); - view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled"); - view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel"); + view_listener_t::addMenu(new LLMeshEnabled(), "File.MeshEnabled"); + view_listener_t::addMenu(new LLMeshUploadVisible(), "File.VisibleUploadModel"); - // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled. + // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled. } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b66d4b1dab..340a1de0d1 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerobject.cpp * @brief Base class for viewer objects * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -110,24 +110,24 @@ //#define DEBUG_UPDATE_TYPE -BOOL LLViewerObject::sVelocityInterpolate = TRUE; -BOOL LLViewerObject::sPingInterpolate = TRUE; +BOOL LLViewerObject::sVelocityInterpolate = TRUE; +BOOL LLViewerObject::sPingInterpolate = TRUE; -U32 LLViewerObject::sNumZombieObjects = 0; -S32 LLViewerObject::sNumObjects = 0; -BOOL LLViewerObject::sMapDebug = TRUE; -LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK -LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit -S32 LLViewerObject::sAxisArrowLength(50); +U32 LLViewerObject::sNumZombieObjects = 0; +S32 LLViewerObject::sNumObjects = 0; +BOOL LLViewerObject::sMapDebug = TRUE; +LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK +LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit +S32 LLViewerObject::sAxisArrowLength(50); -BOOL LLViewerObject::sPulseEnabled(FALSE); -BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE +BOOL LLViewerObject::sPulseEnabled(FALSE); +BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE // sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime -F64Seconds LLViewerObject::sMaxUpdateInterpolationTime(3.0); // For motion interpolation: after X seconds with no updates, don't predict object motion -F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motion interpolation: after Y seconds with no updates, taper off motion prediction -F64Seconds LLViewerObject::sMaxRegionCrossingInterpolationTime(1.0);// For motion interpolation: don't interpolate over this time on region crossing +F64Seconds LLViewerObject::sMaxUpdateInterpolationTime(3.0); // For motion interpolation: after X seconds with no updates, don't predict object motion +F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motion interpolation: after Y seconds with no updates, taper off motion prediction +F64Seconds LLViewerObject::sMaxRegionCrossingInterpolationTime(1.0);// For motion interpolation: don't interpolate over this time on region crossing std::map LLViewerObject::sObjectDataMap; @@ -151,194 +151,194 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco LL_PROFILE_ZONE_SCOPED; LL_DEBUGS("ObjectUpdate") << "creating " << id << LL_ENDL; dumpStack("ObjectUpdateStack"); - - LLViewerObject *res = NULL; - - if (gNonInteractive - && pcode != LL_PCODE_LEGACY_AVATAR - && pcode != LL_VO_SURFACE_PATCH - && pcode != LL_VO_WATER - && pcode != LL_VO_VOID_WATER - && pcode != LL_VO_WL_SKY - && pcode != LL_VO_SKY - && pcode != LL_VO_PART_GROUP - ) - { - return res; - } - switch (pcode) - { - case LL_PCODE_VOLUME: - { - res = new LLVOVolume(id, pcode, regionp); break; - break; - } - case LL_PCODE_LEGACY_AVATAR: - { - if (id == gAgentID) - { - if (!gAgentAvatarp) - { - gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp); - gAgentAvatarp->initInstance(); - gAgentWearables.setAvatarObject(gAgentAvatarp); - } - else - { - if (isAgentAvatarValid()) - { - gAgentAvatarp->updateRegion(regionp); - } - } - res = gAgentAvatarp; - } - else if (flags & CO_FLAG_CONTROL_AVATAR) - { + + LLViewerObject *res = NULL; + + if (gNonInteractive + && pcode != LL_PCODE_LEGACY_AVATAR + && pcode != LL_VO_SURFACE_PATCH + && pcode != LL_VO_WATER + && pcode != LL_VO_VOID_WATER + && pcode != LL_VO_WL_SKY + && pcode != LL_VO_SKY + && pcode != LL_VO_PART_GROUP + ) + { + return res; + } + switch (pcode) + { + case LL_PCODE_VOLUME: + { + res = new LLVOVolume(id, pcode, regionp); break; + break; + } + case LL_PCODE_LEGACY_AVATAR: + { + if (id == gAgentID) + { + if (!gAgentAvatarp) + { + gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp); + gAgentAvatarp->initInstance(); + gAgentWearables.setAvatarObject(gAgentAvatarp); + } + else + { + if (isAgentAvatarValid()) + { + gAgentAvatarp->updateRegion(regionp); + } + } + res = gAgentAvatarp; + } + else if (flags & CO_FLAG_CONTROL_AVATAR) + { LLControlAvatar *control_avatar = new LLControlAvatar(id, pcode, regionp); - control_avatar->initInstance(); - res = control_avatar; - } + control_avatar->initInstance(); + res = control_avatar; + } else if (flags & CO_FLAG_UI_AVATAR) { LLUIAvatar *ui_avatar = new LLUIAvatar(id, pcode, regionp); ui_avatar->initInstance(); res = ui_avatar; } - else - { - LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp); - avatar->initInstance(); - res = avatar; - } - break; - } - case LL_PCODE_LEGACY_GRASS: - res = new LLVOGrass(id, pcode, regionp); break; - case LL_PCODE_LEGACY_PART_SYS: -// LL_WARNS() << "Creating old part sys!" << LL_ENDL; -// res = new LLVOPart(id, pcode, regionp); break; - res = NULL; break; - case LL_PCODE_LEGACY_TREE: - res = new LLVOTree(id, pcode, regionp); break; - case LL_PCODE_TREE_NEW: -// LL_WARNS() << "Creating new tree!" << LL_ENDL; -// res = new LLVOTree(id, pcode, regionp); break; - res = NULL; break; - case LL_VO_SURFACE_PATCH: - res = new LLVOSurfacePatch(id, pcode, regionp); break; - case LL_VO_SKY: - res = new LLVOSky(id, pcode, regionp); break; - case LL_VO_VOID_WATER: - res = new LLVOVoidWater(id, pcode, regionp); break; - case LL_VO_WATER: - res = new LLVOWater(id, pcode, regionp); break; - case LL_VO_PART_GROUP: - res = new LLVOPartGroup(id, pcode, regionp); break; - case LL_VO_HUD_PART_GROUP: - res = new LLVOHUDPartGroup(id, pcode, regionp); break; - case LL_VO_WL_SKY: - res = new LLVOWLSky(id, pcode, regionp); break; - default: - LL_WARNS() << "Unknown object pcode " << (S32)pcode << LL_ENDL; - res = NULL; break; - } - - return res; + else + { + LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp); + avatar->initInstance(); + res = avatar; + } + break; + } + case LL_PCODE_LEGACY_GRASS: + res = new LLVOGrass(id, pcode, regionp); break; + case LL_PCODE_LEGACY_PART_SYS: +// LL_WARNS() << "Creating old part sys!" << LL_ENDL; +// res = new LLVOPart(id, pcode, regionp); break; + res = NULL; break; + case LL_PCODE_LEGACY_TREE: + res = new LLVOTree(id, pcode, regionp); break; + case LL_PCODE_TREE_NEW: +// LL_WARNS() << "Creating new tree!" << LL_ENDL; +// res = new LLVOTree(id, pcode, regionp); break; + res = NULL; break; + case LL_VO_SURFACE_PATCH: + res = new LLVOSurfacePatch(id, pcode, regionp); break; + case LL_VO_SKY: + res = new LLVOSky(id, pcode, regionp); break; + case LL_VO_VOID_WATER: + res = new LLVOVoidWater(id, pcode, regionp); break; + case LL_VO_WATER: + res = new LLVOWater(id, pcode, regionp); break; + case LL_VO_PART_GROUP: + res = new LLVOPartGroup(id, pcode, regionp); break; + case LL_VO_HUD_PART_GROUP: + res = new LLVOHUDPartGroup(id, pcode, regionp); break; + case LL_VO_WL_SKY: + res = new LLVOWLSky(id, pcode, regionp); break; + default: + LL_WARNS() << "Unknown object pcode " << (S32)pcode << LL_ENDL; + res = NULL; break; + } + + return res; } LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global) -: LLPrimitive(), - mChildList(), - mID(id), - mLocalID(0), - mTotalCRC(0), - mListIndex(-1), - mTEImages(NULL), - mTENormalMaps(NULL), - mTESpecularMaps(NULL), - mbCanSelect(TRUE), - mFlags(0), - mPhysicsShapeType(0), - mPhysicsGravity(0), - mPhysicsFriction(0), - mPhysicsDensity(0), - mPhysicsRestitution(0), - mDrawable(), - mCreateSelected(FALSE), - mRenderMedia(FALSE), - mBestUpdatePrecision(0), - mText(), - mHudText(""), - mHudTextColor(LLColor4::white), +: LLPrimitive(), + mChildList(), + mID(id), + mLocalID(0), + mTotalCRC(0), + mListIndex(-1), + mTEImages(NULL), + mTENormalMaps(NULL), + mTESpecularMaps(NULL), + mbCanSelect(TRUE), + mFlags(0), + mPhysicsShapeType(0), + mPhysicsGravity(0), + mPhysicsFriction(0), + mPhysicsDensity(0), + mPhysicsRestitution(0), + mDrawable(), + mCreateSelected(FALSE), + mRenderMedia(FALSE), + mBestUpdatePrecision(0), + mText(), + mHudText(""), + mHudTextColor(LLColor4::white), mControlAvatar(NULL), - mLastInterpUpdateSecs(0.f), - mLastMessageUpdateSecs(0.f), - mLatestRecvPacketID(0), - mRegionCrossExpire(0), - mData(NULL), - mAudioSourcep(NULL), - mAudioGain(1.f), - mSoundCutOffRadius(0.f), - mAppAngle(0.f), - mPixelArea(1024.f), - mInventory(NULL), - mInventorySerialNum(0), - mExpectedInventorySerialNum(0), - mInvRequestState(INVENTORY_REQUEST_STOPPED), - mInvRequestXFerId(0), - mInventoryDirty(FALSE), - mRegionp(regionp), - mDead(FALSE), - mOrphaned(FALSE), - mUserSelected(FALSE), - mOnActiveList(FALSE), - mOnMap(FALSE), - mStatic(FALSE), - mSeatCount(0), - mNumFaces(0), - mRotTime(0.f), - mAngularVelocityRot(), - mPreviousRotation(), - mAttachmentState(0), - mMedia(NULL), - mClickAction(0), - mObjectCost(0), - mLinksetCost(0), - mPhysicsCost(0), - mLinksetPhysicsCost(0.f), - mCostStale(true), - mPhysicsShapeUnknown(true), - mAttachmentItemID(LLUUID::null), - mLastUpdateType(OUT_UNKNOWN), - mLastUpdateCached(FALSE), - mCachedMuteListUpdateTime(0), - mCachedOwnerInMuteList(false), - mRiggedAttachedWarned(false) -{ - if (!is_global) - { - llassert(mRegionp); - } - - LLPrimitive::init_primitive(pcode); - - // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time - mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); - - mPositionRegion = LLVector3(0.f, 0.f, 0.f); - - if (!is_global && mRegionp) - { - mPositionAgent = mRegionp->getOriginAgent(); - } - resetRot(); - - LLViewerObject::sNumObjects++; + mLastInterpUpdateSecs(0.f), + mLastMessageUpdateSecs(0.f), + mLatestRecvPacketID(0), + mRegionCrossExpire(0), + mData(NULL), + mAudioSourcep(NULL), + mAudioGain(1.f), + mSoundCutOffRadius(0.f), + mAppAngle(0.f), + mPixelArea(1024.f), + mInventory(NULL), + mInventorySerialNum(0), + mExpectedInventorySerialNum(0), + mInvRequestState(INVENTORY_REQUEST_STOPPED), + mInvRequestXFerId(0), + mInventoryDirty(FALSE), + mRegionp(regionp), + mDead(FALSE), + mOrphaned(FALSE), + mUserSelected(FALSE), + mOnActiveList(FALSE), + mOnMap(FALSE), + mStatic(FALSE), + mSeatCount(0), + mNumFaces(0), + mRotTime(0.f), + mAngularVelocityRot(), + mPreviousRotation(), + mAttachmentState(0), + mMedia(NULL), + mClickAction(0), + mObjectCost(0), + mLinksetCost(0), + mPhysicsCost(0), + mLinksetPhysicsCost(0.f), + mCostStale(true), + mPhysicsShapeUnknown(true), + mAttachmentItemID(LLUUID::null), + mLastUpdateType(OUT_UNKNOWN), + mLastUpdateCached(FALSE), + mCachedMuteListUpdateTime(0), + mCachedOwnerInMuteList(false), + mRiggedAttachedWarned(false) +{ + if (!is_global) + { + llassert(mRegionp); + } + + LLPrimitive::init_primitive(pcode); + + // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time + mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); + + mPositionRegion = LLVector3(0.f, 0.f, 0.f); + + if (!is_global && mRegionp) + { + mPositionAgent = mRegionp->getOriginAgent(); + } + resetRot(); + + LLViewerObject::sNumObjects++; } LLViewerObject::~LLViewerObject() { - deleteTEImages(); + deleteTEImages(); // unhook from reflection probe manager if (mReflectionProbe.notNull()) @@ -347,18 +347,18 @@ LLViewerObject::~LLViewerObject() mReflectionProbe = nullptr; } - if(mInventory) - { - mInventory->clear(); // will deref and delete entries - delete mInventory; - mInventory = NULL; - } + if(mInventory) + { + mInventory->clear(); // will deref and delete entries + delete mInventory; + mInventory = NULL; + } - if (mPartSourcep) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } + if (mPartSourcep) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } if (mText) { @@ -367,30 +367,30 @@ LLViewerObject::~LLViewerObject() mText = NULL; } - // Delete memory associated with extra parameters. - std::unordered_map::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if(iter->second != NULL) - { - delete iter->second->data; - delete iter->second; - } - } - mExtraParameterList.clear(); - - for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; - mNameValuePairs.clear(); - - delete[] mData; - mData = NULL; - - delete mMedia; - mMedia = NULL; - - sNumObjects--; - sNumZombieObjects--; - llassert(mChildList.size() == 0); + // Delete memory associated with extra parameters. + std::unordered_map::iterator iter; + for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + { + if(iter->second != NULL) + { + delete iter->second->data; + delete iter->second; + } + } + mExtraParameterList.clear(); + + for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; + mNameValuePairs.clear(); + + delete[] mData; + mData = NULL; + + delete mMedia; + mMedia = NULL; + + sNumObjects--; + sNumZombieObjects--; + llassert(mChildList.size() == 0); llassert(mControlAvatar.isNull()); // Should have been cleaned by now if (mControlAvatar.notNull()) { @@ -399,40 +399,40 @@ LLViewerObject::~LLViewerObject() LL_WARNS() << "Dead object owned a live control avatar" << LL_ENDL; } - clearInventoryListeners(); + clearInventoryListeners(); } void LLViewerObject::deleteTEImages() { - delete[] mTEImages; - mTEImages = NULL; - - if (mTENormalMaps != NULL) - { - delete[] mTENormalMaps; - mTENormalMaps = NULL; - } - - if (mTESpecularMaps != NULL) - { - delete[] mTESpecularMaps; - mTESpecularMaps = NULL; - } + delete[] mTEImages; + mTEImages = NULL; + + if (mTENormalMaps != NULL) + { + delete[] mTENormalMaps; + mTENormalMaps = NULL; + } + + if (mTESpecularMaps != NULL) + { + delete[] mTESpecularMaps; + mTESpecularMaps = NULL; + } } void LLViewerObject::markDead() { - if (!mDead) - { + if (!mDead) + { LL_PROFILE_ZONE_SCOPED; - //LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL; - - // Root object of this hierarchy unlinks itself. - if (getParent()) - { - ((LLViewerObject *)getParent())->removeChild(this); - } - LLUUID mesh_id; + //LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL; + + // Root object of this hierarchy unlinks itself. + if (getParent()) + { + ((LLViewerObject *)getParent())->removeChild(this); + } + LLUUID mesh_id; { LLVOAvatar *av = getAvatar(); if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) @@ -446,83 +446,83 @@ void LLViewerObject::markDead() unlinkControlAvatar(); } - // Mark itself as dead - mDead = TRUE; - if(mRegionp) - { - mRegionp->removeFromCreatedList(getLocalID()); - } - gObjectList.cleanupReferences(this); - - LLViewerObject *childp; - while (mChildList.size() > 0) - { - childp = mChildList.back(); - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - //LL_INFOS() << "Marking child " << childp->getLocalID() << " as dead." << LL_ENDL; - childp->setParent(NULL); // LLViewerObject::markDead 1 - childp->markDead(); - } - else - { - // make sure avatar is no longer parented, - // so we can properly set it's position - childp->setDrawableParent(NULL); - ((LLVOAvatar*)childp)->getOffObject(); - childp->setParent(NULL); // LLViewerObject::markDead 2 - } - mChildList.pop_back(); - } - - if (mDrawable.notNull()) - { - // Drawables are reference counted, mark as dead, then nuke the pointer. - mDrawable->markDead(); - mDrawable = NULL; - } - - if (mText) - { - mText->markDead(); - mText = NULL; - } - - if (mIcon) - { - mIcon->markDead(); - mIcon = NULL; - } - - if (mPartSourcep) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - - if (mAudioSourcep) - { - // Do some cleanup - if (gAudiop) - { - gAudiop->cleanupAudioSource(mAudioSourcep); - } - mAudioSourcep = NULL; - } - - if (flagAnimSource()) - { - if (isAgentAvatarValid()) - { - // stop motions associated with this object - gAgentAvatarp->stopMotionFromSource(mID); - } - } - - if (flagCameraSource()) - { - LLFollowCamMgr::getInstance()->removeFollowCamParams(mID); - } + // Mark itself as dead + mDead = TRUE; + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + gObjectList.cleanupReferences(this); + + LLViewerObject *childp; + while (mChildList.size() > 0) + { + childp = mChildList.back(); + if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) + { + //LL_INFOS() << "Marking child " << childp->getLocalID() << " as dead." << LL_ENDL; + childp->setParent(NULL); // LLViewerObject::markDead 1 + childp->markDead(); + } + else + { + // make sure avatar is no longer parented, + // so we can properly set it's position + childp->setDrawableParent(NULL); + ((LLVOAvatar*)childp)->getOffObject(); + childp->setParent(NULL); // LLViewerObject::markDead 2 + } + mChildList.pop_back(); + } + + if (mDrawable.notNull()) + { + // Drawables are reference counted, mark as dead, then nuke the pointer. + mDrawable->markDead(); + mDrawable = NULL; + } + + if (mText) + { + mText->markDead(); + mText = NULL; + } + + if (mIcon) + { + mIcon->markDead(); + mIcon = NULL; + } + + if (mPartSourcep) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } + + if (mAudioSourcep) + { + // Do some cleanup + if (gAudiop) + { + gAudiop->cleanupAudioSource(mAudioSourcep); + } + mAudioSourcep = NULL; + } + + if (flagAnimSource()) + { + if (isAgentAvatarValid()) + { + // stop motions associated with this object + gAgentAvatarp->stopMotionFromSource(mID); + } + } + + if (flagCameraSource()) + { + LLFollowCamMgr::getInstance()->removeFollowCamParams(mID); + } if (mReflectionProbe.notNull()) { @@ -530,225 +530,225 @@ void LLViewerObject::markDead() mReflectionProbe = nullptr; } - sNumZombieObjects++; - } + sNumZombieObjects++; + } } void LLViewerObject::dump() const { - LL_INFOS() << "Type: " << pCodeToString(mPrimitiveCode) << LL_ENDL; - LL_INFOS() << "Drawable: " << (LLDrawable *)mDrawable << LL_ENDL; - LL_INFOS() << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << LL_ENDL; - - LL_INFOS() << "Parent: " << getParent() << LL_ENDL; - LL_INFOS() << "ID: " << mID << LL_ENDL; - LL_INFOS() << "LocalID: " << mLocalID << LL_ENDL; - LL_INFOS() << "PositionRegion: " << getPositionRegion() << LL_ENDL; - LL_INFOS() << "PositionAgent: " << getPositionAgent() << LL_ENDL; - LL_INFOS() << "PositionGlobal: " << getPositionGlobal() << LL_ENDL; - LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; - if (mDrawable.notNull() && - mDrawable->getNumFaces() && - mDrawable->getFace(0)) - { - LLFacePool *poolp = mDrawable->getFace(0)->getPool(); - if (poolp) - { - LL_INFOS() << "Pool: " << poolp << LL_ENDL; - LL_INFOS() << "Pool reference count: " << poolp->mReferences.size() << LL_ENDL; - } - } - //LL_INFOS() << "BoxTree Min: " << mDrawable->getBox()->getMin() << LL_ENDL; - //LL_INFOS() << "BoxTree Max: " << mDrawable->getBox()->getMin() << LL_ENDL; - /* - LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; - LL_INFOS() << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << LL_ENDL; - LL_INFOS() << "UsePhysics: " << flagUsePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << LL_ENDL; - LL_INFOS() << "AppAngle: " << mAppAngle << LL_ENDL; - LL_INFOS() << "PixelArea: " << mPixelArea << LL_ENDL; - - char buffer[1000]; - char *key; - for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() ) - { - mNameValuePairs[key]->printNameValue(buffer); - LL_INFOS() << buffer << LL_ENDL; - } - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - LL_INFOS() << " child " << child->getID() << LL_ENDL; - } - */ + LL_INFOS() << "Type: " << pCodeToString(mPrimitiveCode) << LL_ENDL; + LL_INFOS() << "Drawable: " << (LLDrawable *)mDrawable << LL_ENDL; + LL_INFOS() << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << LL_ENDL; + + LL_INFOS() << "Parent: " << getParent() << LL_ENDL; + LL_INFOS() << "ID: " << mID << LL_ENDL; + LL_INFOS() << "LocalID: " << mLocalID << LL_ENDL; + LL_INFOS() << "PositionRegion: " << getPositionRegion() << LL_ENDL; + LL_INFOS() << "PositionAgent: " << getPositionAgent() << LL_ENDL; + LL_INFOS() << "PositionGlobal: " << getPositionGlobal() << LL_ENDL; + LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; + if (mDrawable.notNull() && + mDrawable->getNumFaces() && + mDrawable->getFace(0)) + { + LLFacePool *poolp = mDrawable->getFace(0)->getPool(); + if (poolp) + { + LL_INFOS() << "Pool: " << poolp << LL_ENDL; + LL_INFOS() << "Pool reference count: " << poolp->mReferences.size() << LL_ENDL; + } + } + //LL_INFOS() << "BoxTree Min: " << mDrawable->getBox()->getMin() << LL_ENDL; + //LL_INFOS() << "BoxTree Max: " << mDrawable->getBox()->getMin() << LL_ENDL; + /* + LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; + LL_INFOS() << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << LL_ENDL; + LL_INFOS() << "UsePhysics: " << flagUsePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << LL_ENDL; + LL_INFOS() << "AppAngle: " << mAppAngle << LL_ENDL; + LL_INFOS() << "PixelArea: " << mPixelArea << LL_ENDL; + + char buffer[1000]; + char *key; + for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() ) + { + mNameValuePairs[key]->printNameValue(buffer); + LL_INFOS() << buffer << LL_ENDL; + } + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + LL_INFOS() << " child " << child->getID() << LL_ENDL; + } + */ } void LLViewerObject::printNameValuePairs() const { - for (name_value_map_t::const_iterator iter = mNameValuePairs.begin(); - iter != mNameValuePairs.end(); iter++) - { - LLNameValue* nv = iter->second; - LL_INFOS() << nv->printNameValue() << LL_ENDL; - } + for (name_value_map_t::const_iterator iter = mNameValuePairs.begin(); + iter != mNameValuePairs.end(); iter++) + { + LLNameValue* nv = iter->second; + LL_INFOS() << nv->printNameValue() << LL_ENDL; + } } void LLViewerObject::initVOClasses() { - // Initialized shared class stuff first. - LLVOAvatar::initClass(); - LLVOTree::initClass(); - LL_INFOS() << "Viewer Object size: " << sizeof(LLViewerObject) << LL_ENDL; - LLVOGrass::initClass(); - LLVOWater::initClass(); - LLVOVolume::initClass(); + // Initialized shared class stuff first. + LLVOAvatar::initClass(); + LLVOTree::initClass(); + LL_INFOS() << "Viewer Object size: " << sizeof(LLViewerObject) << LL_ENDL; + LLVOGrass::initClass(); + LLVOWater::initClass(); + LLVOVolume::initClass(); - initObjectDataMap(); + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() { - SUBSYSTEM_CLEANUP(LLVOGrass); - SUBSYSTEM_CLEANUP(LLVOWater); - SUBSYSTEM_CLEANUP(LLVOTree); - SUBSYSTEM_CLEANUP(LLVOAvatar); - SUBSYSTEM_CLEANUP(LLVOVolume); + SUBSYSTEM_CLEANUP(LLVOGrass); + SUBSYSTEM_CLEANUP(LLVOWater); + SUBSYSTEM_CLEANUP(LLVOTree); + SUBSYSTEM_CLEANUP(LLVOAvatar); + SUBSYSTEM_CLEANUP(LLVOVolume); - sObjectDataMap.clear(); + sObjectDataMap.clear(); } //object data map for compressed && !OUT_TERSE_IMPROVED //static void LLViewerObject::initObjectDataMap() { - U32 count = 0; + U32 count = 0; - sObjectDataMap["ID"] = count; //full id //LLUUID - count += sizeof(LLUUID); + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); - sObjectDataMap["LocalID"] = count; //U32 - count += sizeof(U32); + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); - sObjectDataMap["PCode"] = count; //U8 - count += sizeof(U8); + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); - sObjectDataMap["State"] = count; //U8 - count += sizeof(U8); + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); - sObjectDataMap["CRC"] = count; //U32 - count += sizeof(U32); + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); - sObjectDataMap["Material"] = count; //U8 - count += sizeof(U8); + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); - sObjectDataMap["ClickAction"] = count; //U8 - count += sizeof(U8); + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); - sObjectDataMap["Scale"] = count; //LLVector3 - count += sizeof(LLVector3); + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); - sObjectDataMap["Pos"] = count; //LLVector3 - count += sizeof(LLVector3); + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); - sObjectDataMap["Rot"] = count; //LLVector3 - count += sizeof(LLVector3); + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); - sObjectDataMap["SpecialCode"] = count; //U32 - count += sizeof(U32); + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); - sObjectDataMap["Owner"] = count; //LLUUID - count += sizeof(LLUUID); + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); - sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set - count += sizeof(LLVector3); + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); - //ParentID is after Omega if there is Omega, otherwise is after Owner - sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set - count += sizeof(U32); + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); - //------- - //The rest items are not included here - //------- + //------- + //The rest items are not included here + //------- } -//static +//static void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) { - dp->shift(sObjectDataMap[name]); - dp->unpackVector3(value, name.c_str()); - dp->reset(); + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); } -//static +//static void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) { - dp->shift(sObjectDataMap[name]); - dp->unpackUUID(value, name.c_str()); - dp->reset(); + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); } - -//static + +//static void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) { - dp->shift(sObjectDataMap[name]); - dp->unpackU32(value, name.c_str()); - dp->reset(); + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); } - -//static + +//static void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) { - dp->shift(sObjectDataMap[name]); - dp->unpackU8(value, name.c_str()); - dp->reset(); + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); } -//static +//static U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) { - dp->shift(sObjectDataMap["SpecialCode"]); - U32 value; - dp->unpackU32(value, "SpecialCode"); + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); - parent_id = 0; - if(value & 0x20) - { - S32 offset = sObjectDataMap["ParentID"]; - if(!(value & 0x80)) - { - offset -= sizeof(LLVector3); - } + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } - dp->shift(offset); - dp->unpackU32(parent_id, "ParentID"); - } - dp->reset(); + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); - return parent_id; + return parent_id; } // Replaces all name value pairs with data from \n delimited list // Does not update server void LLViewerObject::setNameValueList(const std::string& name_value_list) { - // Clear out the old - for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; - mNameValuePairs.clear(); - - // Bring in the new - std::string::size_type length = name_value_list.length(); - std::string::size_type start = 0; - while (start < length) - { - std::string::size_type end = name_value_list.find_first_of("\n", start); - if (end == std::string::npos) end = length; - if (end > start) - { - std::string tok = name_value_list.substr(start, end - start); - addNVPair(tok); - } - start = end+1; - } + // Clear out the old + for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; + mNameValuePairs.clear(); + + // Bring in the new + std::string::size_type length = name_value_list.length(); + std::string::size_type start = 0; + while (start < length) + { + std::string::size_type end = name_value_list.find_first_of("\n", start); + if (end == std::string::npos) end = length; + if (end > start) + { + std::string tok = name_value_list.substr(start, end - start); + addNVPair(tok); + } + start = end+1; + } } BOOL LLViewerObject::isAnySelected() const @@ -765,183 +765,183 @@ BOOL LLViewerObject::isAnySelected() const void LLViewerObject::setSelected(BOOL sel) { - mUserSelected = sel; - resetRot(); + mUserSelected = sel; + resetRot(); - if (!sel) - { - setAllTESelected(false); - } + if (!sel) + { + setAllTESelected(false); + } } // This method returns true if the object is over land owned by the // agent. bool LLViewerObject::isReturnable() { - if (isAttachment()) - { - return false; - } - - std::vector boxes; - boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - boxes.push_back( LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); - } - - bool result = (mRegionp && mRegionp->objectIsReturnable(getPositionRegion(), boxes)) ? 1 : 0; - - if ( !result ) - { - //Get list of neighboring regions relative to this vo's region - std::vector uniqueRegions; - mRegionp->getNeighboringRegions( uniqueRegions ); - - //Build aabb's - for root and all children - std::vector returnables; - typedef std::vector::iterator RegionIt; - RegionIt regionStart = uniqueRegions.begin(); - RegionIt regionEnd = uniqueRegions.end(); - - for (; regionStart != regionEnd; ++regionStart ) - { - LLViewerRegion* pTargetRegion = *regionStart; - //Add the root vo as there may be no children and we still want - //to test for any edge overlap - buildReturnablesForChildrenVO( returnables, this, pTargetRegion ); - //Add it's children - for (child_list_t::iterator iter = mChildList.begin(); iter != mChildList.end(); iter++) - { - LLViewerObject* pChild = *iter; - buildReturnablesForChildrenVO( returnables, pChild, pTargetRegion ); - } - } - - //TBD#Eventually create a region -> box list map - typedef std::vector::iterator ReturnablesIt; - ReturnablesIt retCurrentIt = returnables.begin(); - ReturnablesIt retEndIt = returnables.end(); - - for ( ; retCurrentIt !=retEndIt; ++retCurrentIt ) - { - boxes.clear(); - LLViewerRegion* pRegion = (*retCurrentIt).pRegion; - boxes.push_back( (*retCurrentIt).box ); - bool retResult = pRegion - && pRegion->childrenObjectReturnable( boxes ) - && pRegion->canManageEstate(); - if ( retResult ) - { - result = true; - break; - } - } - } - return result; + if (isAttachment()) + { + return false; + } + + std::vector boxes; + boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + boxes.push_back( LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); + } + + bool result = (mRegionp && mRegionp->objectIsReturnable(getPositionRegion(), boxes)) ? 1 : 0; + + if ( !result ) + { + //Get list of neighboring regions relative to this vo's region + std::vector uniqueRegions; + mRegionp->getNeighboringRegions( uniqueRegions ); + + //Build aabb's - for root and all children + std::vector returnables; + typedef std::vector::iterator RegionIt; + RegionIt regionStart = uniqueRegions.begin(); + RegionIt regionEnd = uniqueRegions.end(); + + for (; regionStart != regionEnd; ++regionStart ) + { + LLViewerRegion* pTargetRegion = *regionStart; + //Add the root vo as there may be no children and we still want + //to test for any edge overlap + buildReturnablesForChildrenVO( returnables, this, pTargetRegion ); + //Add it's children + for (child_list_t::iterator iter = mChildList.begin(); iter != mChildList.end(); iter++) + { + LLViewerObject* pChild = *iter; + buildReturnablesForChildrenVO( returnables, pChild, pTargetRegion ); + } + } + + //TBD#Eventually create a region -> box list map + typedef std::vector::iterator ReturnablesIt; + ReturnablesIt retCurrentIt = returnables.begin(); + ReturnablesIt retEndIt = returnables.end(); + + for ( ; retCurrentIt !=retEndIt; ++retCurrentIt ) + { + boxes.clear(); + LLViewerRegion* pRegion = (*retCurrentIt).pRegion; + boxes.push_back( (*retCurrentIt).box ); + bool retResult = pRegion + && pRegion->childrenObjectReturnable( boxes ) + && pRegion->canManageEstate(); + if ( retResult ) + { + result = true; + break; + } + } + } + return result; } void LLViewerObject::buildReturnablesForChildrenVO( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ) { - if ( !pChild ) - { - LL_ERRS()<<"child viewerobject is NULL "<mChildList.begin(); iter != pChild->mChildList.end(); iter++) - { - LLViewerObject* pChildofChild = *iter; - buildReturnablesForChildrenVO( returnables, pChildofChild, pTargetRegion ); - } + if ( !pChild ) + { + LL_ERRS()<<"child viewerobject is NULL "<mChildList.begin(); iter != pChild->mChildList.end(); iter++) + { + LLViewerObject* pChildofChild = *iter; + buildReturnablesForChildrenVO( returnables, pChildofChild, pTargetRegion ); + } } void LLViewerObject::constructAndAddReturnable( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ) { - - LLVector3 targetRegionPos; - targetRegionPos.setVec( pChild->getPositionGlobal() ); - - LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f, - pChild->getScale() * 0.5f).getAxisAligned(); - - LLVector3 edgeA = targetRegionPos + childBBox.getMinLocal(); - LLVector3 edgeB = targetRegionPos + childBBox.getMaxLocal(); - - LLVector3d edgeAd, edgeBd; - edgeAd.setVec(edgeA); - edgeBd.setVec(edgeB); - - //Only add the box when either of the extents are in a neighboring region - if ( pTargetRegion->pointInRegionGlobal( edgeAd ) || pTargetRegion->pointInRegionGlobal( edgeBd ) ) - { - PotentialReturnableObject returnableObj; - returnableObj.box = childBBox; - returnableObj.pRegion = pTargetRegion; - returnables.push_back( returnableObj ); - } + + LLVector3 targetRegionPos; + targetRegionPos.setVec( pChild->getPositionGlobal() ); + + LLBBox childBBox = LLBBox( targetRegionPos, pChild->getRotationRegion(), pChild->getScale() * -0.5f, + pChild->getScale() * 0.5f).getAxisAligned(); + + LLVector3 edgeA = targetRegionPos + childBBox.getMinLocal(); + LLVector3 edgeB = targetRegionPos + childBBox.getMaxLocal(); + + LLVector3d edgeAd, edgeBd; + edgeAd.setVec(edgeA); + edgeBd.setVec(edgeB); + + //Only add the box when either of the extents are in a neighboring region + if ( pTargetRegion->pointInRegionGlobal( edgeAd ) || pTargetRegion->pointInRegionGlobal( edgeBd ) ) + { + PotentialReturnableObject returnableObj; + returnableObj.box = childBBox; + returnableObj.pRegion = pTargetRegion; + returnables.push_back( returnableObj ); + } } bool LLViewerObject::crossesParcelBounds() { - std::vector boxes; - boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); - } + std::vector boxes; + boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); + } - return mRegionp && mRegionp->objectsCrossParcel(boxes); + return mRegionp && mRegionp->objectsCrossParcel(boxes); } BOOL LLViewerObject::setParent(LLViewerObject* parent) { - if(mParent != parent) - { - LLViewerObject* old_parent = (LLViewerObject*)mParent ; - BOOL ret = LLPrimitive::setParent(parent); - if(ret && old_parent && parent) - { - old_parent->removeChild(this) ; - } - return ret ; - } + if(mParent != parent) + { + LLViewerObject* old_parent = (LLViewerObject*)mParent ; + BOOL ret = LLPrimitive::setParent(parent); + if(ret && old_parent && parent) + { + old_parent->removeChild(this) ; + } + return ret ; + } - return FALSE ; + return FALSE ; } void LLViewerObject::addChild(LLViewerObject *childp) { - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - if (*i == childp) - { //already has child - return; - } - } - - if (!isAvatar()) - { - // propagate selection properties - childp->mbCanSelect = mbCanSelect; - } - - if(childp->setParent(this)) - { - mChildList.push_back(childp); - childp->afterReparent(); - - if (childp->isAvatar()) - { - mSeatCount++; - } - } + for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) + { + if (*i == childp) + { //already has child + return; + } + } + + if (!isAvatar()) + { + // propagate selection properties + childp->mbCanSelect = mbCanSelect; + } + + if(childp->setParent(this)) + { + mChildList.push_back(childp); + childp->afterReparent(); + + if (childp->isAvatar()) + { + mSeatCount++; + } + } } void LLViewerObject::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent) @@ -954,149 +954,149 @@ void LLViewerObject::afterReparent() void LLViewerObject::removeChild(LLViewerObject *childp) { - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - if (*i == childp) - { - if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar()) - { - gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME); - } - - mChildList.erase(i); - - if(childp->getParent() == this) - { - childp->setParent(NULL); - } - - if (childp->isAvatar()) - { - mSeatCount--; - } - break; - } - } - - if (childp->isSelected()) - { - LLSelectMgr::getInstance()->deselectObjectAndFamily(childp); - BOOL add_to_end = TRUE; - LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end); - } + for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) + { + if (*i == childp) + { + if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar()) + { + gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME); + } + + mChildList.erase(i); + + if(childp->getParent() == this) + { + childp->setParent(NULL); + } + + if (childp->isAvatar()) + { + mSeatCount--; + } + break; + } + } + + if (childp->isSelected()) + { + LLSelectMgr::getInstance()->deselectObjectAndFamily(childp); + BOOL add_to_end = TRUE; + LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end); + } } void LLViewerObject::addThisAndAllChildren(std::vector& objects) { - objects.push_back(this); - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - if (!child->isAvatar()) - { - child->addThisAndAllChildren(objects); - } - } + objects.push_back(this); + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + if (!child->isAvatar()) + { + child->addThisAndAllChildren(objects); + } + } } void LLViewerObject::addThisAndNonJointChildren(std::vector& objects) { - objects.push_back(this); - // don't add any attachments when temporarily selecting avatar - if (isAvatar()) - { - return; - } - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - if ( (!child->isAvatar())) - { - child->addThisAndNonJointChildren(objects); - } - } + objects.push_back(this); + // don't add any attachments when temporarily selecting avatar + if (isAvatar()) + { + return; + } + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + if ( (!child->isAvatar())) + { + child->addThisAndNonJointChildren(objects); + } + } } BOOL LLViewerObject::isChild(LLViewerObject *childp) const { - for (child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* testchild = *iter; - if (testchild == childp) - return TRUE; - } - return FALSE; + for (child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* testchild = *iter; + if (testchild == childp) + return TRUE; + } + return FALSE; } // returns TRUE if at least one avatar is sitting on this object BOOL LLViewerObject::isSeat() const { - return mSeatCount > 0; + return mSeatCount > 0; } BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) { - if (mDrawable.isNull()) - { - return FALSE; - } - - BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); - if(!ret) - { - return FALSE ; - } - LLDrawable* old_parent = mDrawable->mParent; - mDrawable->mParent = parentp; - - if (parentp && mDrawable->isActive()) - { - parentp->makeActive(); - parentp->setState(LLDrawable::ACTIVE_CHILD); - } - - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - if( (old_parent != parentp && old_parent) - || (parentp && parentp->isActive())) - { - // *TODO we should not be relying on setDrawable parent to call markMoved - gPipeline.markMoved(mDrawable, FALSE); - } - else if (!mDrawable->isAvatar()) - { - mDrawable->updateXform(TRUE); - /*if (!mDrawable->getSpatialGroup()) - { - mDrawable->movePartition(); - }*/ - } - - return ret; + if (mDrawable.isNull()) + { + return FALSE; + } + + BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); + if(!ret) + { + return FALSE ; + } + LLDrawable* old_parent = mDrawable->mParent; + mDrawable->mParent = parentp; + + if (parentp && mDrawable->isActive()) + { + parentp->makeActive(); + parentp->setState(LLDrawable::ACTIVE_CHILD); + } + + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + if( (old_parent != parentp && old_parent) + || (parentp && parentp->isActive())) + { + // *TODO we should not be relying on setDrawable parent to call markMoved + gPipeline.markMoved(mDrawable, FALSE); + } + else if (!mDrawable->isAvatar()) + { + mDrawable->updateXform(TRUE); + /*if (!mDrawable->getSpatialGroup()) + { + mDrawable->movePartition(); + }*/ + } + + return ret; } // Show or hide particles, icon and HUD void LLViewerObject::hideExtraDisplayItems( BOOL hidden ) { - if( mPartSourcep.notNull() ) - { - LLViewerPartSourceScript *partSourceScript = mPartSourcep.get(); - partSourceScript->setSuspended( hidden ); - } + if( mPartSourcep.notNull() ) + { + LLViewerPartSourceScript *partSourceScript = mPartSourcep.get(); + partSourceScript->setSuspended( hidden ); + } - if( mText.notNull() ) - { - LLHUDText *hudText = mText.get(); - hudText->setHidden( hidden ); - } + if( mText.notNull() ) + { + LLHUDText *hudText = mText.get(); + hudText->setHidden( hidden ); + } - if( mIcon.notNull() ) - { - LLHUDIcon *hudIcon = mIcon.get(); - hudIcon->setHidden( hidden ); - } + if( mIcon.notNull() ) + { + LLHUDIcon *hudIcon = mIcon.get(); + hudIcon->setHidden( hidden ); + } } U32 LLViewerObject::checkMediaURL(const std::string &media_url) @@ -1121,9 +1121,9 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test. { /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() && - LLTextureEntry::getVersionFromMediaVersionString(media_url) == + LLTextureEntry::getVersionFromMediaVersionString(media_url) == LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1)) - */ + */ { // If the media URL is different and WE were not the one who // changed it, mark dirty. @@ -1141,1356 +1141,1356 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) //static U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) { - U32 parent_id = 0; - LLViewerObject::unpackParentID(dp, parent_id); + U32 parent_id = 0; + LLViewerObject::unpackParentID(dp, parent_id); - LLViewerObject::unpackVector3(dp, scale, "Scale"); - LLViewerObject::unpackVector3(dp, pos, "Pos"); - - LLVector3 vec; - LLViewerObject::unpackVector3(dp, vec, "Rot"); - rot.unpackFromVector3(vec); - - return parent_id; + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + return parent_id; } U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp) { LL_PROFILE_ZONE_SCOPED; - LL_DEBUGS_ONCE("SceneLoadTiming") << "Received viewer object data" << LL_ENDL; + LL_DEBUGS_ONCE("SceneLoadTiming") << "Received viewer object data" << LL_ENDL; LL_DEBUGS("ObjectUpdate") << " mesgsys " << mesgsys << " dp " << dp << " id " << getID() << " update_type " << (S32) update_type << LL_ENDL; dumpStack("ObjectUpdateStack"); - U32 retval = 0x0; - - // If region is removed from the list it is also deleted. - if (!LLWorld::instance().isRegionListed(mRegionp)) - { - LL_WARNS() << "Updating object in an invalid region" << LL_ENDL; - return retval; - } - - // Coordinates of objects on simulators are region-local. - U64 region_handle = 0; - - if(mesgsys != NULL) - { - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); - LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); - if(regionp != mRegionp && regionp && mRegionp)//region cross - { - //this is the redundant position and region update, but it is necessary in case the viewer misses the following - //position and region update messages from sim. - //this redundant update should not cause any problems. - LLVector3 delta_pos = mRegionp->getOriginAgent() - regionp->getOriginAgent(); - setPositionParent(getPosition() + delta_pos); //update to the new region position immediately. - setRegion(regionp) ; //change the region. - } - else - { - if(regionp != mRegionp) - { - if(mRegionp) - { - mRegionp->removeFromCreatedList(getLocalID()); - } - if(regionp) - { - regionp->addToCreatedList(getLocalID()); - } - } - mRegionp = regionp ; - } - } - - if (!mRegionp) - { - U32 x, y; - from_region_handle(region_handle, &x, &y); - - LL_ERRS() << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL; - return retval; - } - - F32 time_dilation = 1.f; - if(mesgsys != NULL) - { - U16 time_dilation16; - mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); - time_dilation = ((F32) time_dilation16) / 65535.f; - mRegionp->setTimeDilation(time_dilation); - } + U32 retval = 0x0; - // this will be used to determine if we've really changed position - // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. - LLVector3 test_pos_parent = getPosition(); + // If region is removed from the list it is also deleted. + if (!LLWorld::instance().isRegionListed(mRegionp)) + { + LL_WARNS() << "Updating object in an invalid region" << LL_ENDL; + return retval; + } - // This needs to match the largest size below. See switch(length) - U8 data[MAX_OBJECT_BINARY_DATA_SIZE]; + // Coordinates of objects on simulators are region-local. + U64 region_handle = 0; -#ifdef LL_BIG_ENDIAN - U16 valswizzle[4]; -#endif - U16 *val; - const F32 size = LLWorld::getInstance()->getRegionWidthInMeters(); - const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight(); - const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight(); - S32 length; - S32 count; - S32 this_update_precision = 32; // in bits - - // Temporaries, because we need to compare w/ previous to set dirty flags... - LLVector3 new_pos_parent; - LLVector3 new_vel; - LLVector3 new_acc; - LLVector3 new_angv; - LLVector3 old_angv = getAngularVelocity(); - LLQuaternion new_rot; - LLVector3 new_scale = getScale(); - - U32 parent_id = 0; - U8 material = 0; - U8 click_action = 0; - U32 crc = 0; - - bool old_special_hover_cursor = specialHoverCursor(); - - LLViewerObject *cur_parentp = (LLViewerObject *)getParent(); - - if (cur_parentp) - { - parent_id = cur_parentp->mLocalID; - } - - if (!dp) - { - switch(update_type) - { - case OUT_FULL: - { -#ifdef DEBUG_UPDATE_TYPE - LL_INFOS() << "Full:" << getID() << LL_ENDL; + if(mesgsys != NULL) + { + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); + if(regionp != mRegionp && regionp && mRegionp)//region cross + { + //this is the redundant position and region update, but it is necessary in case the viewer misses the following + //position and region update messages from sim. + //this redundant update should not cause any problems. + LLVector3 delta_pos = mRegionp->getOriginAgent() - regionp->getOriginAgent(); + setPositionParent(getPosition() + delta_pos); //update to the new region position immediately. + setRegion(regionp) ; //change the region. + } + else + { + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } + } + mRegionp = regionp ; + } + } + + if (!mRegionp) + { + U32 x, y; + from_region_handle(region_handle, &x, &y); + + LL_ERRS() << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL; + return retval; + } + + F32 time_dilation = 1.f; + if(mesgsys != NULL) + { + U16 time_dilation16; + mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); + time_dilation = ((F32) time_dilation16) / 65535.f; + mRegionp->setTimeDilation(time_dilation); + } + + // this will be used to determine if we've really changed position + // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. + LLVector3 test_pos_parent = getPosition(); + + // This needs to match the largest size below. See switch(length) + U8 data[MAX_OBJECT_BINARY_DATA_SIZE]; + +#ifdef LL_BIG_ENDIAN + U16 valswizzle[4]; #endif - //clear cost and linkset cost - setObjectCostStale(); - if (isSelected()) - { - gFloaterTools->dirty(); - } - - LLUUID audio_uuid; - LLUUID owner_id; // only valid if audio_uuid or particle system is not null - F32 gain; - F32 cutoff; - U8 sound_flags; - - mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num); - mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num); - mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num ); - // HACK: Owner id only valid if non-null sound id or particle system - mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num ); - mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num ); - mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Radius, cutoff, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Material, material, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); - mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num ); - length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE); - - mTotalCRC = crc; + U16 *val; + const F32 size = LLWorld::getInstance()->getRegionWidthInMeters(); + const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight(); + const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight(); + S32 length; + S32 count; + S32 this_update_precision = 32; // in bits + + // Temporaries, because we need to compare w/ previous to set dirty flags... + LLVector3 new_pos_parent; + LLVector3 new_vel; + LLVector3 new_acc; + LLVector3 new_angv; + LLVector3 old_angv = getAngularVelocity(); + LLQuaternion new_rot; + LLVector3 new_scale = getScale(); + + U32 parent_id = 0; + U8 material = 0; + U8 click_action = 0; + U32 crc = 0; + + bool old_special_hover_cursor = specialHoverCursor(); + + LLViewerObject *cur_parentp = (LLViewerObject *)getParent(); + + if (cur_parentp) + { + parent_id = cur_parentp->mLocalID; + } + + if (!dp) + { + switch(update_type) + { + case OUT_FULL: + { +#ifdef DEBUG_UPDATE_TYPE + LL_INFOS() << "Full:" << getID() << LL_ENDL; +#endif + //clear cost and linkset cost + setObjectCostStale(); + if (isSelected()) + { + gFloaterTools->dirty(); + } + + LLUUID audio_uuid; + LLUUID owner_id; // only valid if audio_uuid or particle system is not null + F32 gain; + F32 cutoff; + U8 sound_flags; + + mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num); + mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num); + mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num ); + // HACK: Owner id only valid if non-null sound id or particle system + mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num ); + mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num ); + mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Radius, cutoff, block_num ); + mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num ); + mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Material, material, block_num ); + mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); + mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num ); + length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE); + + mTotalCRC = crc; // Might need to update mSourceMuted here to properly pick up new radius - mSoundCutOffRadius = cutoff; - - // Owner ID used for sound muting or particle system muting - setAttachedSound(audio_uuid, owner_id, gain, sound_flags); - - U8 old_material = getMaterial(); - if (old_material != material) - { - setMaterial(material); - if (mDrawable.notNull()) - { - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - setClickAction(click_action); - - count = 0; - LLVector4 collision_plane; - - switch(length) - { - case (60 + 16): - // pull out collision normal for avatar - htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 60: - this_update_precision = 32; - // this is a terse update - // pos - htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // vel - htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // acc - htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // theta - { - LLVector3 vec; - htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - new_rot.unpackFromVector3(vec); - } - count += sizeof(LLVector3); - // omega - htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); + mSoundCutOffRadius = cutoff; + + // Owner ID used for sound muting or particle system muting + setAttachedSound(audio_uuid, owner_id, gain, sound_flags); + + U8 old_material = getMaterial(); + if (old_material != material) + { + setMaterial(material); + if (mDrawable.notNull()) + { + gPipeline.markMoved(mDrawable, FALSE); // undamped + } + } + setClickAction(click_action); + + count = 0; + LLVector4 collision_plane; + + switch(length) + { + case (60 + 16): + // pull out collision normal for avatar + htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); + ((LLVOAvatar*)this)->setFootPlane(collision_plane); + count += sizeof(LLVector4); + // fall through + case 60: + this_update_precision = 32; + // this is a terse update + // pos + htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // vel + htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // acc + htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // theta + { + LLVector3 vec; + htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + new_rot.unpackFromVector3(vec); + } + count += sizeof(LLVector3); + // omega + htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + if (new_angv.isExactlyZero()) + { + // reset rotation time + resetRot(); + } + setAngularVelocity(new_angv); #if LL_DARWIN - if (length == 76) - { - setAngularVelocity(LLVector3::zero); - } + if (length == 76) + { + setAngularVelocity(LLVector3::zero); + } #endif - break; - case(32 + 16): - // pull out collision normal for avatar - htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 32: - this_update_precision = 16; - test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - - // This is a terse 16 update, so treat data as an array of U16's. + break; + case(32 + 16): + // pull out collision normal for avatar + htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); + ((LLVOAvatar*)this)->setFootPlane(collision_plane); + count += sizeof(LLVector4); + // fall through + case 32: + this_update_precision = 16; + test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); + + // This is a terse 16 update, so treat data as an array of U16's. #ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; #else - val = (U16 *) &data[count]; + val = (U16 *) &data[count]; #endif - count += sizeof(U16)*3; - new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); + count += sizeof(U16)*3; + new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); #ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; #else - val = (U16 *) &data[count]; + val = (U16 *) &data[count]; #endif - count += sizeof(U16)*3; - setVelocity(LLVector3(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size))); + count += sizeof(U16)*3; + setVelocity(LLVector3(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size))); #ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; #else - val = (U16 *) &data[count]; + val = (U16 *) &data[count]; #endif - count += sizeof(U16)*3; - setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size))); + count += sizeof(U16)*3; + setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size))); #ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4); - val = valswizzle; + htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4); + val = valswizzle; #else - val = (U16 *) &data[count]; + val = (U16 *) &data[count]; #endif - count += sizeof(U16)*4; - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); + count += sizeof(U16)*4; + new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); + new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); + new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); + new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + new_angv.setVec(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size)); + if (new_angv.isExactlyZero()) + { + // reset rotation time + resetRot(); + } + setAngularVelocity(new_angv); + break; + + case 16: + this_update_precision = 8; + test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); + // this is a terse 8 update + new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); + + setVelocity(U8_to_F32(data[3], -size, size), + U8_to_F32(data[4], -size, size), + U8_to_F32(data[5], -size, size) ); + + setAcceleration(U8_to_F32(data[6], -size, size), + U8_to_F32(data[7], -size, size), + U8_to_F32(data[8], -size, size) ); + + new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); + new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); + new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); + new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); + + new_angv.setVec(U8_to_F32(data[13], -size, size), + U8_to_F32(data[14], -size, size), + U8_to_F32(data[15], -size, size) ); + if (new_angv.isExactlyZero()) + { + // reset rotation time + resetRot(); + } + setAngularVelocity(new_angv); + break; + } + + //////////////////////////////////////////////////// + // + // Here we handle data specific to the full message. + // + + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); + // clear all but local flags + mFlags &= FLAGS_LOCAL; + mFlags |= flags; + + U8 state; + mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); + mAttachmentState = state; + + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + + // Set all name value pairs + S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue); + if (nv_size > 0) + { + std::string name_value_list; + mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num); + setNameValueList(name_value_list); + } + + // Clear out any existing generic data + if (mData) + { + delete [] mData; + } + + // Check for appended generic data + S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); + if (data_size <= 0) + { + mData = NULL; + } + else + { + // ...has generic data + mData = new U8[data_size]; + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num); + } + + S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text); + if (text_size > 1) + { + // Setup object text + if (!mText) + { + initHudText(); + } + + std::string temp_string; + mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); + + LLColor4U coloru; + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); + + // alpha was flipped so that it zero encoded better + coloru.mV[3] = 255 - coloru.mV[3]; + + mText->setColor(LLColor4(coloru)); + mText->setString(temp_string); + + mHudText = temp_string; + mHudTextColor = LLColor4(coloru); + + setChanged(MOVED | SILHOUETTE); + } + else + { + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); + } + + std::string media_url; + mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num); + retval |= checkMediaURL(media_url); + + // + // Unpack particle system data + // + unpackParticleSource(block_num, owner_id); + + // Mark all extra parameters not used + std::unordered_map::iterator iter; + for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + { + iter->second->in_use = FALSE; + } + + // Unpack extra parameters + S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams); + if (size > 0) + { + U8 *buffer = new U8[size]; + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num); + LLDataPackerBinaryBuffer dp(buffer, size); + + U8 num_parameters; + dp.unpackU8(num_parameters, "num_params"); + U8 param_block[MAX_OBJECT_PARAMS_SIZE]; + for (U8 param=0; paramsecond->in_use) + { + // Send an update message in case it was formerly in use + parameterChanged(iter->first, iter->second->data, FALSE, false); + } + } + + break; + } + + case OUT_TERSE_IMPROVED: + { +#ifdef DEBUG_UPDATE_TYPE + LL_INFOS() << "TI:" << getID() << LL_ENDL; +#endif + length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE); + count = 0; + LLVector4 collision_plane; + + switch(length) + { + case(60 + 16): + // pull out collision normal for avatar + htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); + ((LLVOAvatar*)this)->setFootPlane(collision_plane); + count += sizeof(LLVector4); + // fall through + case 60: + // this is a terse 32 update + // pos + this_update_precision = 32; + htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // vel + htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // acc + htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + count += sizeof(LLVector3); + // theta + { + LLVector3 vec; + htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + new_rot.unpackFromVector3(vec); + } + count += sizeof(LLVector3); + // omega + htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); + if (new_angv.isExactlyZero()) + { + // reset rotation time + resetRot(); + } + setAngularVelocity(new_angv); +#if LL_DARWIN + if (length == 76) + { + setAngularVelocity(LLVector3::zero); + } +#endif + break; + case(32 + 16): + // pull out collision normal for avatar + htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); + ((LLVOAvatar*)this)->setFootPlane(collision_plane); + count += sizeof(LLVector4); + // fall through + case 32: + // this is a terse 16 update + this_update_precision = 16; + test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + count += sizeof(U16)*3; + new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + count += sizeof(U16)*3; + setVelocity(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size)); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + count += sizeof(U16)*3; + setAcceleration(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size)); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Quat, 8); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + count += sizeof(U16)*4; + new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); + new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); + new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); + new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); + +#ifdef LL_BIG_ENDIAN + htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); + val = valswizzle; +#else + val = (U16 *) &data[count]; +#endif + new_angv.set(U16_to_F32(val[VX], -size, size), + U16_to_F32(val[VY], -size, size), + U16_to_F32(val[VZ], -size, size)); + setAngularVelocity(new_angv); + break; + + case 16: + // this is a terse 8 update + this_update_precision = 8; + test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); + new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); + new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); + + setVelocity(U8_to_F32(data[3], -size, size), + U8_to_F32(data[4], -size, size), + U8_to_F32(data[5], -size, size) ); + + setAcceleration(U8_to_F32(data[6], -size, size), + U8_to_F32(data[7], -size, size), + U8_to_F32(data[8], -size, size) ); + + new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); + new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); + new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); + new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); + + new_angv.set(U8_to_F32(data[13], -size, size), + U8_to_F32(data[14], -size, size), + U8_to_F32(data[15], -size, size) ); + setAngularVelocity(new_angv); + break; + } + + U8 state; + mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); + mAttachmentState = state; + break; + } + + default: + break; + + } + } + else + { + // handle the compressed case + LLUUID sound_uuid; + LLUUID owner_id; + F32 gain = 0; + U8 sound_flags = 0; + F32 cutoff = 0; + + U16 val[4]; + + U8 state; + + dp->unpackU8(state, "State"); + mAttachmentState = state; + + switch(update_type) + { + case OUT_TERSE_IMPROVED: + { +#ifdef DEBUG_UPDATE_TYPE + LL_INFOS() << "CompTI:" << getID() << LL_ENDL; +#endif + U8 value; + dp->unpackU8(value, "agent"); + if (value) + { + LLVector4 collision_plane; + dp->unpackVector4(collision_plane, "Plane"); + ((LLVOAvatar*)this)->setFootPlane(collision_plane); + } + test_pos_parent = getPosition(); + dp->unpackVector3(new_pos_parent, "Pos"); + dp->unpackU16(val[VX], "VelX"); + dp->unpackU16(val[VY], "VelY"); + dp->unpackU16(val[VZ], "VelZ"); + setVelocity(U16_to_F32(val[VX], -128.f, 128.f), + U16_to_F32(val[VY], -128.f, 128.f), + U16_to_F32(val[VZ], -128.f, 128.f)); + dp->unpackU16(val[VX], "AccX"); + dp->unpackU16(val[VY], "AccY"); + dp->unpackU16(val[VZ], "AccZ"); + setAcceleration(U16_to_F32(val[VX], -64.f, 64.f), + U16_to_F32(val[VY], -64.f, 64.f), + U16_to_F32(val[VZ], -64.f, 64.f)); + + dp->unpackU16(val[VX], "ThetaX"); + dp->unpackU16(val[VY], "ThetaY"); + dp->unpackU16(val[VZ], "ThetaZ"); + dp->unpackU16(val[VS], "ThetaS"); + new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); + new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); + new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); + new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f); + dp->unpackU16(val[VX], "AccX"); + dp->unpackU16(val[VY], "AccY"); + dp->unpackU16(val[VZ], "AccZ"); + new_angv.set(U16_to_F32(val[VX], -64.f, 64.f), + U16_to_F32(val[VY], -64.f, 64.f), + U16_to_F32(val[VZ], -64.f, 64.f)); + setAngularVelocity(new_angv); + } + break; + case OUT_FULL_COMPRESSED: + case OUT_FULL_CACHED: + { +#ifdef DEBUG_UPDATE_TYPE + LL_INFOS() << "CompFull:" << getID() << LL_ENDL; +#endif + setObjectCostStale(); + + if (isSelected()) + { + gFloaterTools->dirty(); + } + + dp->unpackU32(crc, "CRC"); + mTotalCRC = crc; + dp->unpackU8(material, "Material"); + U8 old_material = getMaterial(); + if (old_material != material) + { + setMaterial(material); + if (mDrawable.notNull()) + { + gPipeline.markMoved(mDrawable, FALSE); // undamped + } + } + dp->unpackU8(click_action, "ClickAction"); + setClickAction(click_action); + dp->unpackVector3(new_scale, "Scale"); + dp->unpackVector3(new_pos_parent, "Pos"); + LLVector3 vec; + dp->unpackVector3(vec, "Rot"); + new_rot.unpackFromVector3(vec); + setAcceleration(LLVector3::zero); + + U32 value; + dp->unpackU32(value, "SpecialCode"); + dp->setPassFlags(value); + dp->unpackUUID(owner_id, "Owner"); + + mOwnerID = owner_id; + + if (value & 0x80) + { + dp->unpackVector3(new_angv, "Omega"); + setAngularVelocity(new_angv); + } + + if (value & 0x20) + { + dp->unpackU32(parent_id, "ParentID"); + } + else + { + parent_id = 0; + } + + S32 sp_size; + U32 size; + if (value & 0x2) + { + sp_size = 1; + delete [] mData; + mData = new U8[1]; + dp->unpackU8(((U8*)mData)[0], "TreeData"); + } + else if (value & 0x1) + { + dp->unpackU32(size, "ScratchPadSize"); + delete [] mData; + mData = new U8[size]; + dp->unpackBinaryData((U8 *)mData, sp_size, "PartData"); + } + else + { + mData = NULL; + } + + // Setup object text + if (!mText && (value & 0x4)) + { + initHudText(); + } + + if (value & 0x4) + { + std::string temp_string; + dp->unpackString(temp_string, "Text"); + + LLColor4U coloru; + dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); + coloru.mV[3] = 255 - coloru.mV[3]; + mText->setColor(LLColor4(coloru)); + mText->setString(temp_string); + + mHudText = temp_string; + mHudTextColor = LLColor4(coloru); + + setChanged(TEXTURE); + } + else + { + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); + } + + std::string media_url; + if (value & 0x200) + { + dp->unpackString(media_url, "MediaURL"); + } + retval |= checkMediaURL(media_url); + + // + // Unpack particle system data (legacy) + // + if (value & 0x8) + { + unpackParticleSource(*dp, owner_id, true); + } + else if (!(value & 0x400)) + { + deleteParticleSource(); + } + + // Mark all extra parameters not used + std::unordered_map::iterator iter; + for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + { + iter->second->in_use = FALSE; + } + + // Unpack extra params + U8 num_parameters; + dp->unpackU8(num_parameters, "num_params"); + U8 param_block[MAX_OBJECT_PARAMS_SIZE]; + for (U8 param=0; paramunpackU16(param_type, "param_type"); + dp->unpackBinaryData(param_block, param_size, "param_data"); + //LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL; + LLDataPackerBinaryBuffer dp2(param_block, param_size); + unpackParameterEntry(param_type, &dp2); + } + + for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + { + if (!iter->second->in_use) + { + // Send an update message in case it was formerly in use + parameterChanged(iter->first, iter->second->data, FALSE, false); + } + } + + if (value & 0x10) + { + dp->unpackUUID(sound_uuid, "SoundUUID"); + dp->unpackF32(gain, "SoundGain"); + dp->unpackU8(sound_flags, "SoundFlags"); + dp->unpackF32(cutoff, "SoundRadius"); + } + + if (value & 0x100) + { + std::string name_value_list; + dp->unpackString(name_value_list, "NV"); + + setNameValueList(name_value_list); + } + + mTotalCRC = crc; + mSoundCutOffRadius = cutoff; + + setAttachedSound(sound_uuid, owner_id, gain, sound_flags); + + // only get these flags on updates from sim, not cached ones + // Preload these five flags for every object. + // Finer shades require the object to be selected, and the selection manager + // stores the extended permission info. + if(mesgsys != NULL) + { + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); + loadFlags(flags); + } + } + break; + + default: + break; + } + } + + // + // Fix object parenting. + // + BOOL b_changed_status = FALSE; + + if (OUT_TERSE_IMPROVED != update_type) + { + // We only need to update parenting on full updates, terse updates + // don't send parenting information. + if (!cur_parentp) + { + if (parent_id == 0) + { + // No parent now, no parent in message -> do nothing + } + else + { + // No parent now, new parent in message -> attach to that parent if possible + LLUUID parent_uuid; + + if(mesgsys != NULL) + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mesgsys->getSenderIP(), + mesgsys->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } + + LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); + + // + // Check to see if we have the corresponding viewer object for the parent. + // + if (sent_parentp && sent_parentp->getParent() == this) + { + // Try to recover if we attempt to attach a parent to its child + LL_WARNS() << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << LL_ENDL; + this->removeChild(sent_parentp); + sent_parentp->setDrawableParent(NULL); + } + + if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead()) + { + if (((LLViewerObject*)sent_parentp)->isAvatar()) + { + //LL_DEBUGS("Avatar") << "ATT got object update for attachment " << LL_ENDL; + } + + // + // We have a viewer object for the parent, and it's not dead. + // Do the actual reparenting here. + // + + // new parent is valid + b_changed_status = TRUE; + // ...no current parent, so don't try to remove child + if (mDrawable.notNull()) + { + if (mDrawable->isDead() || !mDrawable->getVObj()) + { + LL_WARNS() << "Drawable is dead or no VObj!" << LL_ENDL; + sent_parentp->addChild(this); + } + else + { + if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1 + { + // Bad, we got a cycle somehow. + // Kill both the parent and the child, and + // set cache misses for both of them. + LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; + LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; + LL_WARNS() << "Adding to cache miss list" << LL_ENDL; + setParent(NULL); + sent_parentp->setParent(NULL); + getRegion()->addCacheMissFull(getLocalID()); + getRegion()->addCacheMissFull(sent_parentp->getLocalID()); + gObjectList.killObject(sent_parentp); + gObjectList.killObject(this); + return retval; + } + sent_parentp->addChild(this); + // make sure this object gets a non-damped update + if (sent_parentp->mDrawable.notNull()) + { + gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped + } + } + } + else + { + sent_parentp->addChild(this); + } + + // Show particles, icon and HUD + hideExtraDisplayItems( FALSE ); + + setChanged(MOVED | SILHOUETTE); + } + else + { + // + // No corresponding viewer object for the parent, put the various + // pieces on the orphan list. + // + + //parent_id + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } + gObjectList.orphanize(this, parent_id, ip, port); + + // Hide particles, icon and HUD + hideExtraDisplayItems( TRUE ); + } + } + } + else + { + // BUG: this is a bad assumption once border crossing is alowed + if ( (parent_id == cur_parentp->mLocalID) + &&(update_type == OUT_TERSE_IMPROVED)) + { + // Parent now, same parent in message -> do nothing + + // Debugging for suspected problems with local ids. + //LLUUID parent_uuid; + //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() ); + //if (parent_uuid != cur_parentp->getID() ) + //{ + // LL_ERRS() << "Local ID match but UUID mismatch of viewer object" << LL_ENDL; + //} + } + else + { + // Parented now, different parent in message + LLViewerObject *sent_parentp; + if (parent_id == 0) + { + // + // This object is no longer parented, we sent in a zero parent ID. + // + sent_parentp = NULL; + } + else + { + LLUUID parent_uuid; + + if(mesgsys != NULL) + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + gMessageSystem->getSenderIP(), + gMessageSystem->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } + sent_parentp = gObjectList.findObject(parent_uuid); + + if (isAvatar()) + { + // This logic is meant to handle the case where a sitting avatar has reached a new sim + // ahead of the object she was sitting on (which is common as objects are transfered through + // a slower route than agents)... + // In this case, the local id for the object will not be valid, since the viewer has not received + // a full update for the object from that sim yet, so we assume that the agent is still sitting + // where she was originally. --RN + if (!sent_parentp) + { + sent_parentp = cur_parentp; + } + } + else if (!sent_parentp) + { + // + // Switching parents, but we don't know the new parent. + // + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } + + // We're an orphan, flag things appropriately. + gObjectList.orphanize(this, parent_id, ip, port); + } + } + + // Reattach if possible. + if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this) + { + // New parent is valid, detach and reattach + b_changed_status = TRUE; + if (mDrawable.notNull()) + { + if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2 + { + // Bad, we got a cycle somehow. + // Kill both the parent and the child, and + // set cache misses for both of them. + LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; + LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; + LL_WARNS() << "Adding to cache miss list" << LL_ENDL; + setParent(NULL); + sent_parentp->setParent(NULL); + getRegion()->addCacheMissFull(getLocalID()); + getRegion()->addCacheMissFull(sent_parentp->getLocalID()); + gObjectList.killObject(sent_parentp); + gObjectList.killObject(this); + return retval; + } + // make sure this object gets a non-damped update + } + cur_parentp->removeChild(this); + sent_parentp->addChild(this); + setChanged(MOVED | SILHOUETTE); + sent_parentp->setChanged(MOVED | SILHOUETTE); + if (sent_parentp->mDrawable.notNull()) + { + gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped + } + } + else if (!sent_parentp) + { + bool remove_parent = true; + // No new parent, or the parent that we sent doesn't exist on the viewer. + LLViewerObject *parentp = (LLViewerObject *)getParent(); + if (parentp) + { + if (parentp->getRegion() != getRegion()) + { + // This is probably an object flying across a region boundary, the + // object probably ISN'T being reparented, but just got an object + // update out of order (child update before parent). + //LL_INFOS() << "Don't reparent object handoffs!" << LL_ENDL; + remove_parent = false; + } + } + + if (remove_parent) + { + b_changed_status = TRUE; + if (mDrawable.notNull()) + { + // clear parent to removeChild can put the drawable on the damped list + setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3 + } + + cur_parentp->removeChild(this); + + setChanged(MOVED | SILHOUETTE); + + if (mDrawable.notNull()) + { + // make sure this object gets a non-damped update + gPipeline.markMoved(mDrawable, FALSE); // undamped + } + } + } + } + } + } + + new_rot.normQuat(); + + if (sPingInterpolate && mesgsys != NULL) + { + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); + if (cdp) + { + // Note: delay is U32 and usually less then second, + // converting it into seconds with valueInUnits will result in 0 + F32 ping_delay = 0.5f * time_dilation * ( ((F32)cdp->getPingDelay().value()) * 0.001f + gFrameDTClamped); + LLVector3 diff = getVelocity() * ping_delay; + new_pos_parent += diff; + } + else + { + LL_WARNS() << "findCircuit() returned NULL; skipping interpolation" << LL_ENDL; + } + } + + ////////////////////////// + // + // Set the generic change flags... + // + // + + // If we're going to skip this message, why are we + // doing all the parenting, etc above? + if(mesgsys != NULL) + { + U32 packet_id = mesgsys->getCurrentRecvPacketID(); + if (packet_id < mLatestRecvPacketID && + mLatestRecvPacketID - packet_id < 65536) + { + //skip application of this message, it's old + return retval; + } + mLatestRecvPacketID = packet_id; + } + + // Set the change flags for scale + if (new_scale != getScale()) + { + setChanged(SCALED | SILHOUETTE); + setScale(new_scale); // Must follow setting permYouOwner() + } + + // first, let's see if the new position is actually a change + + //static S32 counter = 0; + + F32 vel_mag_sq = getVelocity().magVecSquared(); + F32 accel_mag_sq = getAcceleration().magVecSquared(); + + if ( ((b_changed_status)||(test_pos_parent != new_pos_parent)) + ||( (!isSelected()) + &&( (vel_mag_sq != 0.f) + ||(accel_mag_sq != 0.f) + ||(this_update_precision > mBestUpdatePrecision)))) + { + mBestUpdatePrecision = this_update_precision; + + LLVector3 diff = new_pos_parent - test_pos_parent ; + F32 mag_sqr = diff.magVecSquared() ; + if(llfinite(mag_sqr)) + { + setPositionParent(new_pos_parent); + } + else + { + LL_WARNS() << "Can not move the object/avatar to an infinite location!" << LL_ENDL ; -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - new_angv.setVec(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); - break; - - case 16: - this_update_precision = 8; - test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - // this is a terse 8 update - new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); - - setVelocity(U8_to_F32(data[3], -size, size), - U8_to_F32(data[4], -size, size), - U8_to_F32(data[5], -size, size) ); - - setAcceleration(U8_to_F32(data[6], -size, size), - U8_to_F32(data[7], -size, size), - U8_to_F32(data[8], -size, size) ); - - new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); - new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); - new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); - new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); - - new_angv.setVec(U8_to_F32(data[13], -size, size), - U8_to_F32(data[14], -size, size), - U8_to_F32(data[15], -size, size) ); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); - break; - } - - //////////////////////////////////////////////////// - // - // Here we handle data specific to the full message. - // - - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // clear all but local flags - mFlags &= FLAGS_LOCAL; - mFlags |= flags; - - U8 state; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mAttachmentState = state; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - - // Set all name value pairs - S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue); - if (nv_size > 0) - { - std::string name_value_list; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num); - setNameValueList(name_value_list); - } - - // Clear out any existing generic data - if (mData) - { - delete [] mData; - } - - // Check for appended generic data - S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); - if (data_size <= 0) - { - mData = NULL; - } - else - { - // ...has generic data - mData = new U8[data_size]; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num); - } - - S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text); - if (text_size > 1) - { - // Setup object text - if (!mText) - { - initHudText(); - } - - std::string temp_string; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - - LLColor4U coloru; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); - - // alpha was flipped so that it zero encoded better - coloru.mV[3] = 255 - coloru.mV[3]; - - mText->setColor(LLColor4(coloru)); - mText->setString(temp_string); - - mHudText = temp_string; - mHudTextColor = LLColor4(coloru); - - setChanged(MOVED | SILHOUETTE); - } - else - { - if (mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - mHudText.clear(); - } - - std::string media_url; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num); - retval |= checkMediaURL(media_url); - - // - // Unpack particle system data - // - unpackParticleSource(block_num, owner_id); - - // Mark all extra parameters not used - std::unordered_map::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - iter->second->in_use = FALSE; - } - - // Unpack extra parameters - S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams); - if (size > 0) - { - U8 *buffer = new U8[size]; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num); - LLDataPackerBinaryBuffer dp(buffer, size); - - U8 num_parameters; - dp.unpackU8(num_parameters, "num_params"); - U8 param_block[MAX_OBJECT_PARAMS_SIZE]; - for (U8 param=0; paramsecond->in_use) - { - // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, FALSE, false); - } - } - - break; - } - - case OUT_TERSE_IMPROVED: - { -#ifdef DEBUG_UPDATE_TYPE - LL_INFOS() << "TI:" << getID() << LL_ENDL; -#endif - length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE); - count = 0; - LLVector4 collision_plane; - - switch(length) - { - case(60 + 16): - // pull out collision normal for avatar - htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 60: - // this is a terse 32 update - // pos - this_update_precision = 32; - htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // vel - htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // acc - htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // theta - { - LLVector3 vec; - htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - new_rot.unpackFromVector3(vec); - } - count += sizeof(LLVector3); - // omega - htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); -#if LL_DARWIN - if (length == 76) - { - setAngularVelocity(LLVector3::zero); - } -#endif - break; - case(32 + 16): - // pull out collision normal for avatar - htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 32: - // this is a terse 16 update - this_update_precision = 16; - test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); + retval |= INVALID_UPDATE ; + } -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); + if (mParent && ((LLViewerObject*)mParent)->isAvatar()) + { + // we have changed the position of an attachment, so we need to clamp it + LLVOAvatar *avatar = (LLVOAvatar*)mParent; -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setVelocity(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); + avatar->clampAttachmentPositions(); + } -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setAcceleration(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); + // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps + if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) ) + { + record(LLStatViewer::AGENT_POSITION_SNAP, LLUnit(diff.length())); + } + } -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Quat, 8); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*4; - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); + if ((new_rot.isNotEqualEps(getRotation(), F_ALMOST_ZERO)) + || (new_angv != old_angv)) + { + if (new_rot != mPreviousRotation) + { + resetRot(); + } + else if (new_angv != old_angv) + { + if (flagUsePhysics()) + { + resetRot(); + } + else + { + resetRotTime(); + } + } -#ifdef LL_BIG_ENDIAN - htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - new_angv.set(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - setAngularVelocity(new_angv); - break; - - case 16: - // this is a terse 8 update - this_update_precision = 8; - test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); - - setVelocity(U8_to_F32(data[3], -size, size), - U8_to_F32(data[4], -size, size), - U8_to_F32(data[5], -size, size) ); - - setAcceleration(U8_to_F32(data[6], -size, size), - U8_to_F32(data[7], -size, size), - U8_to_F32(data[8], -size, size) ); - - new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); - new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); - new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); - new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); - - new_angv.set(U8_to_F32(data[13], -size, size), - U8_to_F32(data[14], -size, size), - U8_to_F32(data[15], -size, size) ); - setAngularVelocity(new_angv); - break; - } - - U8 state; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mAttachmentState = state; - break; - } - - default: - break; - - } - } - else - { - // handle the compressed case - LLUUID sound_uuid; - LLUUID owner_id; - F32 gain = 0; - U8 sound_flags = 0; - F32 cutoff = 0; - - U16 val[4]; - - U8 state; - - dp->unpackU8(state, "State"); - mAttachmentState = state; - - switch(update_type) - { - case OUT_TERSE_IMPROVED: - { -#ifdef DEBUG_UPDATE_TYPE - LL_INFOS() << "CompTI:" << getID() << LL_ENDL; -#endif - U8 value; - dp->unpackU8(value, "agent"); - if (value) - { - LLVector4 collision_plane; - dp->unpackVector4(collision_plane, "Plane"); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - } - test_pos_parent = getPosition(); - dp->unpackVector3(new_pos_parent, "Pos"); - dp->unpackU16(val[VX], "VelX"); - dp->unpackU16(val[VY], "VelY"); - dp->unpackU16(val[VZ], "VelZ"); - setVelocity(U16_to_F32(val[VX], -128.f, 128.f), - U16_to_F32(val[VY], -128.f, 128.f), - U16_to_F32(val[VZ], -128.f, 128.f)); - dp->unpackU16(val[VX], "AccX"); - dp->unpackU16(val[VY], "AccY"); - dp->unpackU16(val[VZ], "AccZ"); - setAcceleration(U16_to_F32(val[VX], -64.f, 64.f), - U16_to_F32(val[VY], -64.f, 64.f), - U16_to_F32(val[VZ], -64.f, 64.f)); - - dp->unpackU16(val[VX], "ThetaX"); - dp->unpackU16(val[VY], "ThetaY"); - dp->unpackU16(val[VZ], "ThetaZ"); - dp->unpackU16(val[VS], "ThetaS"); - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f); - dp->unpackU16(val[VX], "AccX"); - dp->unpackU16(val[VY], "AccY"); - dp->unpackU16(val[VZ], "AccZ"); - new_angv.set(U16_to_F32(val[VX], -64.f, 64.f), - U16_to_F32(val[VY], -64.f, 64.f), - U16_to_F32(val[VZ], -64.f, 64.f)); - setAngularVelocity(new_angv); - } - break; - case OUT_FULL_COMPRESSED: - case OUT_FULL_CACHED: - { -#ifdef DEBUG_UPDATE_TYPE - LL_INFOS() << "CompFull:" << getID() << LL_ENDL; -#endif - setObjectCostStale(); - - if (isSelected()) - { - gFloaterTools->dirty(); - } - - dp->unpackU32(crc, "CRC"); - mTotalCRC = crc; - dp->unpackU8(material, "Material"); - U8 old_material = getMaterial(); - if (old_material != material) - { - setMaterial(material); - if (mDrawable.notNull()) - { - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - dp->unpackU8(click_action, "ClickAction"); - setClickAction(click_action); - dp->unpackVector3(new_scale, "Scale"); - dp->unpackVector3(new_pos_parent, "Pos"); - LLVector3 vec; - dp->unpackVector3(vec, "Rot"); - new_rot.unpackFromVector3(vec); - setAcceleration(LLVector3::zero); - - U32 value; - dp->unpackU32(value, "SpecialCode"); - dp->setPassFlags(value); - dp->unpackUUID(owner_id, "Owner"); - - mOwnerID = owner_id; - - if (value & 0x80) - { - dp->unpackVector3(new_angv, "Omega"); - setAngularVelocity(new_angv); - } - - if (value & 0x20) - { - dp->unpackU32(parent_id, "ParentID"); - } - else - { - parent_id = 0; - } - - S32 sp_size; - U32 size; - if (value & 0x2) - { - sp_size = 1; - delete [] mData; - mData = new U8[1]; - dp->unpackU8(((U8*)mData)[0], "TreeData"); - } - else if (value & 0x1) - { - dp->unpackU32(size, "ScratchPadSize"); - delete [] mData; - mData = new U8[size]; - dp->unpackBinaryData((U8 *)mData, sp_size, "PartData"); - } - else - { - mData = NULL; - } - - // Setup object text - if (!mText && (value & 0x4)) - { - initHudText(); - } - - if (value & 0x4) - { - std::string temp_string; - dp->unpackString(temp_string, "Text"); - - LLColor4U coloru; - dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); - coloru.mV[3] = 255 - coloru.mV[3]; - mText->setColor(LLColor4(coloru)); - mText->setString(temp_string); + // Remember the last rotation value + mPreviousRotation = new_rot; - mHudText = temp_string; - mHudTextColor = LLColor4(coloru); + // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) + setRotation(new_rot * mAngularVelocityRot); + setChanged(ROTATED | SILHOUETTE); + } + + if ( gShowObjectUpdates ) + { + LLColor4 color; + if (update_type == OUT_TERSE_IMPROVED) + { + color.setVec(0.f, 0.f, 1.f, 1.f); + } + else + { + color.setVec(1.f, 0.f, 0.f, 1.f); + } + gPipeline.addDebugBlip(getPositionAgent(), color); + LL_DEBUGS("MessageBlip") << "Update type " << (S32)update_type << " blip for local " << mLocalID << " at " << getPositionAgent() << LL_ENDL; + } - setChanged(TEXTURE); - } - else - { - if (mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - mHudText.clear(); - } + const F32 MAG_CUTOFF = F_APPROXIMATELY_ZERO; - std::string media_url; - if (value & 0x200) - { - dp->unpackString(media_url, "MediaURL"); - } - retval |= checkMediaURL(media_url); + llassert(vel_mag_sq >= 0.f); + llassert(accel_mag_sq >= 0.f); + llassert(getAngularVelocity().magVecSquared() >= 0.f); - // - // Unpack particle system data (legacy) - // - if (value & 0x8) - { - unpackParticleSource(*dp, owner_id, true); - } - else if (!(value & 0x400)) - { - deleteParticleSource(); - } - - // Mark all extra parameters not used - std::unordered_map::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - iter->second->in_use = FALSE; - } - - // Unpack extra params - U8 num_parameters; - dp->unpackU8(num_parameters, "num_params"); - U8 param_block[MAX_OBJECT_PARAMS_SIZE]; - for (U8 param=0; paramunpackU16(param_type, "param_type"); - dp->unpackBinaryData(param_block, param_size, "param_data"); - //LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL; - LLDataPackerBinaryBuffer dp2(param_block, param_size); - unpackParameterEntry(param_type, &dp2); - } - - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if (!iter->second->in_use) - { - // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, FALSE, false); - } - } - - if (value & 0x10) - { - dp->unpackUUID(sound_uuid, "SoundUUID"); - dp->unpackF32(gain, "SoundGain"); - dp->unpackU8(sound_flags, "SoundFlags"); - dp->unpackF32(cutoff, "SoundRadius"); - } - - if (value & 0x100) - { - std::string name_value_list; - dp->unpackString(name_value_list, "NV"); - - setNameValueList(name_value_list); - } - - mTotalCRC = crc; - mSoundCutOffRadius = cutoff; - - setAttachedSound(sound_uuid, owner_id, gain, sound_flags); - - // only get these flags on updates from sim, not cached ones - // Preload these five flags for every object. - // Finer shades require the object to be selected, and the selection manager - // stores the extended permission info. - if(mesgsys != NULL) - { - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - loadFlags(flags); - } - } - break; - - default: - break; - } - } - - // - // Fix object parenting. - // - BOOL b_changed_status = FALSE; - - if (OUT_TERSE_IMPROVED != update_type) - { - // We only need to update parenting on full updates, terse updates - // don't send parenting information. - if (!cur_parentp) - { - if (parent_id == 0) - { - // No parent now, no parent in message -> do nothing - } - else - { - // No parent now, new parent in message -> attach to that parent if possible - LLUUID parent_uuid; - - if(mesgsys != NULL) - { - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - mesgsys->getSenderIP(), - mesgsys->getSenderPort()); - } - else - { - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - mRegionp->getHost().getAddress(), - mRegionp->getHost().getPort()); - } - - LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); - - // - // Check to see if we have the corresponding viewer object for the parent. - // - if (sent_parentp && sent_parentp->getParent() == this) - { - // Try to recover if we attempt to attach a parent to its child - LL_WARNS() << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << LL_ENDL; - this->removeChild(sent_parentp); - sent_parentp->setDrawableParent(NULL); - } - - if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead()) - { - if (((LLViewerObject*)sent_parentp)->isAvatar()) - { - //LL_DEBUGS("Avatar") << "ATT got object update for attachment " << LL_ENDL; - } - - // - // We have a viewer object for the parent, and it's not dead. - // Do the actual reparenting here. - // - - // new parent is valid - b_changed_status = TRUE; - // ...no current parent, so don't try to remove child - if (mDrawable.notNull()) - { - if (mDrawable->isDead() || !mDrawable->getVObj()) - { - LL_WARNS() << "Drawable is dead or no VObj!" << LL_ENDL; - sent_parentp->addChild(this); - } - else - { - if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1 - { - // Bad, we got a cycle somehow. - // Kill both the parent and the child, and - // set cache misses for both of them. - LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; - LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; - LL_WARNS() << "Adding to cache miss list" << LL_ENDL; - setParent(NULL); - sent_parentp->setParent(NULL); - getRegion()->addCacheMissFull(getLocalID()); - getRegion()->addCacheMissFull(sent_parentp->getLocalID()); - gObjectList.killObject(sent_parentp); - gObjectList.killObject(this); - return retval; - } - sent_parentp->addChild(this); - // make sure this object gets a non-damped update - if (sent_parentp->mDrawable.notNull()) - { - gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped - } - } - } - else - { - sent_parentp->addChild(this); - } - - // Show particles, icon and HUD - hideExtraDisplayItems( FALSE ); - - setChanged(MOVED | SILHOUETTE); - } - else - { - // - // No corresponding viewer object for the parent, put the various - // pieces on the orphan list. - // - - //parent_id - U32 ip, port; - - if(mesgsys != NULL) - { - ip = mesgsys->getSenderIP(); - port = mesgsys->getSenderPort(); - } - else - { - ip = mRegionp->getHost().getAddress(); - port = mRegionp->getHost().getPort(); - } - gObjectList.orphanize(this, parent_id, ip, port); - - // Hide particles, icon and HUD - hideExtraDisplayItems( TRUE ); - } - } - } - else - { - // BUG: this is a bad assumption once border crossing is alowed - if ( (parent_id == cur_parentp->mLocalID) - &&(update_type == OUT_TERSE_IMPROVED)) - { - // Parent now, same parent in message -> do nothing - - // Debugging for suspected problems with local ids. - //LLUUID parent_uuid; - //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() ); - //if (parent_uuid != cur_parentp->getID() ) - //{ - // LL_ERRS() << "Local ID match but UUID mismatch of viewer object" << LL_ENDL; - //} - } - else - { - // Parented now, different parent in message - LLViewerObject *sent_parentp; - if (parent_id == 0) - { - // - // This object is no longer parented, we sent in a zero parent ID. - // - sent_parentp = NULL; - } - else - { - LLUUID parent_uuid; - - if(mesgsys != NULL) - { - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - } - else - { - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - mRegionp->getHost().getAddress(), - mRegionp->getHost().getPort()); - } - sent_parentp = gObjectList.findObject(parent_uuid); - - if (isAvatar()) - { - // This logic is meant to handle the case where a sitting avatar has reached a new sim - // ahead of the object she was sitting on (which is common as objects are transfered through - // a slower route than agents)... - // In this case, the local id for the object will not be valid, since the viewer has not received - // a full update for the object from that sim yet, so we assume that the agent is still sitting - // where she was originally. --RN - if (!sent_parentp) - { - sent_parentp = cur_parentp; - } - } - else if (!sent_parentp) - { - // - // Switching parents, but we don't know the new parent. - // - U32 ip, port; - - if(mesgsys != NULL) - { - ip = mesgsys->getSenderIP(); - port = mesgsys->getSenderPort(); - } - else - { - ip = mRegionp->getHost().getAddress(); - port = mRegionp->getHost().getPort(); - } - - // We're an orphan, flag things appropriately. - gObjectList.orphanize(this, parent_id, ip, port); - } - } - - // Reattach if possible. - if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this) - { - // New parent is valid, detach and reattach - b_changed_status = TRUE; - if (mDrawable.notNull()) - { - if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2 - { - // Bad, we got a cycle somehow. - // Kill both the parent and the child, and - // set cache misses for both of them. - LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; - LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; - LL_WARNS() << "Adding to cache miss list" << LL_ENDL; - setParent(NULL); - sent_parentp->setParent(NULL); - getRegion()->addCacheMissFull(getLocalID()); - getRegion()->addCacheMissFull(sent_parentp->getLocalID()); - gObjectList.killObject(sent_parentp); - gObjectList.killObject(this); - return retval; - } - // make sure this object gets a non-damped update - } - cur_parentp->removeChild(this); - sent_parentp->addChild(this); - setChanged(MOVED | SILHOUETTE); - sent_parentp->setChanged(MOVED | SILHOUETTE); - if (sent_parentp->mDrawable.notNull()) - { - gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped - } - } - else if (!sent_parentp) - { - bool remove_parent = true; - // No new parent, or the parent that we sent doesn't exist on the viewer. - LLViewerObject *parentp = (LLViewerObject *)getParent(); - if (parentp) - { - if (parentp->getRegion() != getRegion()) - { - // This is probably an object flying across a region boundary, the - // object probably ISN'T being reparented, but just got an object - // update out of order (child update before parent). - //LL_INFOS() << "Don't reparent object handoffs!" << LL_ENDL; - remove_parent = false; - } - } - - if (remove_parent) - { - b_changed_status = TRUE; - if (mDrawable.notNull()) - { - // clear parent to removeChild can put the drawable on the damped list - setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3 - } - - cur_parentp->removeChild(this); - - setChanged(MOVED | SILHOUETTE); - - if (mDrawable.notNull()) - { - // make sure this object gets a non-damped update - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - } - } - } - } - - new_rot.normQuat(); - - if (sPingInterpolate && mesgsys != NULL) - { - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); - if (cdp) - { - // Note: delay is U32 and usually less then second, - // converting it into seconds with valueInUnits will result in 0 - F32 ping_delay = 0.5f * time_dilation * ( ((F32)cdp->getPingDelay().value()) * 0.001f + gFrameDTClamped); - LLVector3 diff = getVelocity() * ping_delay; - new_pos_parent += diff; - } - else - { - LL_WARNS() << "findCircuit() returned NULL; skipping interpolation" << LL_ENDL; - } - } - - ////////////////////////// - // - // Set the generic change flags... - // - // - - // If we're going to skip this message, why are we - // doing all the parenting, etc above? - if(mesgsys != NULL) - { - U32 packet_id = mesgsys->getCurrentRecvPacketID(); - if (packet_id < mLatestRecvPacketID && - mLatestRecvPacketID - packet_id < 65536) - { - //skip application of this message, it's old - return retval; - } - mLatestRecvPacketID = packet_id; - } - - // Set the change flags for scale - if (new_scale != getScale()) - { - setChanged(SCALED | SILHOUETTE); - setScale(new_scale); // Must follow setting permYouOwner() - } - - // first, let's see if the new position is actually a change - - //static S32 counter = 0; - - F32 vel_mag_sq = getVelocity().magVecSquared(); - F32 accel_mag_sq = getAcceleration().magVecSquared(); - - if ( ((b_changed_status)||(test_pos_parent != new_pos_parent)) - ||( (!isSelected()) - &&( (vel_mag_sq != 0.f) - ||(accel_mag_sq != 0.f) - ||(this_update_precision > mBestUpdatePrecision)))) - { - mBestUpdatePrecision = this_update_precision; - - LLVector3 diff = new_pos_parent - test_pos_parent ; - F32 mag_sqr = diff.magVecSquared() ; - if(llfinite(mag_sqr)) - { - setPositionParent(new_pos_parent); - } - else - { - LL_WARNS() << "Can not move the object/avatar to an infinite location!" << LL_ENDL ; - - retval |= INVALID_UPDATE ; - } - - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - - // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps - if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) ) - { - record(LLStatViewer::AGENT_POSITION_SNAP, LLUnit(diff.length())); - } - } - - if ((new_rot.isNotEqualEps(getRotation(), F_ALMOST_ZERO)) - || (new_angv != old_angv)) - { - if (new_rot != mPreviousRotation) - { - resetRot(); - } - else if (new_angv != old_angv) - { - if (flagUsePhysics()) - { - resetRot(); - } - else - { - resetRotTime(); - } - } - - // Remember the last rotation value - mPreviousRotation = new_rot; - - // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) - setRotation(new_rot * mAngularVelocityRot); - setChanged(ROTATED | SILHOUETTE); - } - - if ( gShowObjectUpdates ) - { - LLColor4 color; - if (update_type == OUT_TERSE_IMPROVED) - { - color.setVec(0.f, 0.f, 1.f, 1.f); - } - else - { - color.setVec(1.f, 0.f, 0.f, 1.f); - } - gPipeline.addDebugBlip(getPositionAgent(), color); - LL_DEBUGS("MessageBlip") << "Update type " << (S32)update_type << " blip for local " << mLocalID << " at " << getPositionAgent() << LL_ENDL; - } - - const F32 MAG_CUTOFF = F_APPROXIMATELY_ZERO; - - llassert(vel_mag_sq >= 0.f); - llassert(accel_mag_sq >= 0.f); - llassert(getAngularVelocity().magVecSquared() >= 0.f); - - if ((MAG_CUTOFF >= vel_mag_sq) && - (MAG_CUTOFF >= accel_mag_sq) && - (MAG_CUTOFF >= getAngularVelocity().magVecSquared())) - { - mStatic = TRUE; // This object doesn't move! - } - else - { - mStatic = FALSE; - } + if ((MAG_CUTOFF >= vel_mag_sq) && + (MAG_CUTOFF >= accel_mag_sq) && + (MAG_CUTOFF >= getAngularVelocity().magVecSquared())) + { + mStatic = TRUE; // This object doesn't move! + } + else + { + mStatic = FALSE; + } // BUG: This code leads to problems during group rotate and any scale operation. -// Small discepencies between the simulator and viewer representations cause the +// Small discepencies between the simulator and viewer representations cause the // selection center to creep, leading to objects moving around the wrong center. -// +// // Removing this, however, means that if someone else drags an object you have // selected, your selection center and dialog boxes will be wrong. It also means // that higher precision information on selected objects will be ignored. // // I believe the group rotation problem is fixed. JNC 1.21.2002 // - // Additionally, if any child is selected, need to update the dialogs and selection - // center. - BOOL needs_refresh = mUserSelected; - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - needs_refresh = needs_refresh || child->mUserSelected; - } + // Additionally, if any child is selected, need to update the dialogs and selection + // center. + BOOL needs_refresh = mUserSelected; + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + needs_refresh = needs_refresh || child->mUserSelected; + } static LLCachedControl allow_select_avatar(gSavedSettings, "AllowSelectAvatar", FALSE); - if (needs_refresh) - { - LLSelectMgr::getInstance()->updateSelectionCenter(); - dialog_refresh_all(); - } + if (needs_refresh) + { + LLSelectMgr::getInstance()->updateSelectionCenter(); + dialog_refresh_all(); + } else if (allow_select_avatar && asAvatar()) { // Override any avatar position updates received @@ -2500,280 +2500,280 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } - // Mark update time as approx. now, with the ping delay. - // Ping delay is off because it's not set for velocity interpolation, causing - // much jumping and hopping around... + // Mark update time as approx. now, with the ping delay. + // Ping delay is off because it's not set for velocity interpolation, causing + // much jumping and hopping around... -// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay(); - mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); - mLastMessageUpdateSecs = mLastInterpUpdateSecs; - if (mDrawable.notNull()) - { - // Don't clear invisibility flag on update if still orphaned! - if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned) - { -// LL_DEBUGS() << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << LL_ENDL; - mDrawable->clearState(LLDrawable::FORCE_INVISIBLE); - gPipeline.markRebuild( mDrawable, LLDrawable::REBUILD_ALL); - } - } +// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay(); + mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); + mLastMessageUpdateSecs = mLastInterpUpdateSecs; + if (mDrawable.notNull()) + { + // Don't clear invisibility flag on update if still orphaned! + if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned) + { +// LL_DEBUGS() << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << LL_ENDL; + mDrawable->clearState(LLDrawable::FORCE_INVISIBLE); + gPipeline.markRebuild( mDrawable, LLDrawable::REBUILD_ALL); + } + } - // Update special hover cursor status - bool special_hover_cursor = specialHoverCursor(); - if (old_special_hover_cursor != special_hover_cursor - && mDrawable.notNull()) - { - mDrawable->updateSpecialHoverCursor(special_hover_cursor); - } + // Update special hover cursor status + bool special_hover_cursor = specialHoverCursor(); + if (old_special_hover_cursor != special_hover_cursor + && mDrawable.notNull()) + { + mDrawable->updateSpecialHoverCursor(special_hover_cursor); + } - return retval; + return retval; } BOOL LLViewerObject::isActive() const { - return TRUE; + return TRUE; } //load flags from cache or from message void LLViewerObject::loadFlags(U32 flags) { - if(flags == (U32)(-1)) - { - return; //invalid - } + if(flags == (U32)(-1)) + { + return; //invalid + } - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - return; + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; } void LLViewerObject::idleUpdate(LLAgent &agent, const F64 &frame_time) { - if (!mDead) - { - if (!mStatic && sVelocityInterpolate && !isSelected()) - { - // calculate dt from last update - F32 time_dilation = mRegionp ? mRegionp->getTimeDilation() : 1.0f; - F32 dt_raw = ((F64Seconds)frame_time - mLastInterpUpdateSecs).value(); - F32 dt = time_dilation * dt_raw; + if (!mDead) + { + if (!mStatic && sVelocityInterpolate && !isSelected()) + { + // calculate dt from last update + F32 time_dilation = mRegionp ? mRegionp->getTimeDilation() : 1.0f; + F32 dt_raw = ((F64Seconds)frame_time - mLastInterpUpdateSecs).value(); + F32 dt = time_dilation * dt_raw; - applyAngularVelocity(dt); + applyAngularVelocity(dt); - if (isAttachment()) - { - mLastInterpUpdateSecs = (F64Seconds)frame_time; - return; - } - else - { // Move object based on it's velocity and rotation - interpolateLinearMotion(frame_time, dt); - } - } + if (isAttachment()) + { + mLastInterpUpdateSecs = (F64Seconds)frame_time; + return; + } + else + { // Move object based on it's velocity and rotation + interpolateLinearMotion(frame_time, dt); + } + } - updateDrawable(FALSE); - } + updateDrawable(FALSE); + } } // Move an object due to idle-time viewer side updates by interpolating motion void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& frame_time, const F32SecondsImplicit& dt_seconds) { - // linear motion - // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object - // updates represents the average velocity of the last timestep, rather than the final velocity. - // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically - // - // *TODO: should also wrap linear accel/velocity in check - // to see if object is selected, instead of explicitly - // zeroing it out - - F32 dt = dt_seconds; - F64Seconds time_since_last_update = frame_time - mLastMessageUpdateSecs; - if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f) - { - return; - } - - LLVector3 accel = getAcceleration(); - LLVector3 vel = getVelocity(); - - if (sMaxUpdateInterpolationTime <= (F64Seconds)0.0) - { // Old code path ... unbounded, simple interpolation - if (!(accel.isExactlyZero() && vel.isExactlyZero())) - { - LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - - // region local - setPositionRegion(pos + getPositionRegion()); - setVelocity(vel + accel*dt); - - // for objects that are spinning but not translating, make sure to flag them as having moved - setChanged(MOVED | SILHOUETTE); - } - } - else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving - { // Object is moving, and hasn't been too long since we got an update from the server - - // Calculate predicted position and velocity - LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - LLVector3 new_v = accel * dt; - - if (time_since_last_update > sPhaseOutUpdateInterpolationTime && - sPhaseOutUpdateInterpolationTime > (F64Seconds)0.0) - { // Haven't seen a viewer update in a while, check to see if the circuit is still active - if (mRegionp) - { // The simulator will NOT send updates if the object continues normally on the path - // predicted by the velocity and the acceleration (often gravity) sent to the viewer - // So check to see if the circuit is blocked, which means the sim is likely in a long lag - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() ); - if (cdp) - { - // Find out how many seconds since last packet arrived on the circuit - F64Seconds time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); - - if (!cdp->isAlive() || // Circuit is dead or blocked - cdp->isBlocked() || // or doesn't seem to be getting any packets - (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) - { - // Start to reduce motion interpolation since we haven't seen a server update in a while - F64Seconds time_since_last_interpolation = frame_time - mLastInterpUpdateSecs; - F64 phase_out = 1.0; - if (time_since_last_update > sMaxUpdateInterpolationTime) - { // Past the time limit, so stop the object - phase_out = 0.0; - //LL_INFOS() << "Motion phase out to zero" << LL_ENDL; - - // Kill angular motion as well. Note - not adding this due to paranoia - // about stopping rotation for llTargetOmega objects and not having it restart - // setAngularVelocity(LLVector3::zero); - } - else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime) - { // Last update was already phased out a bit - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / - (sMaxUpdateInterpolationTime - time_since_last_interpolation); - //LL_INFOS() << "Continuing motion phase out of " << (F32) phase_out << LL_ENDL; - } - else - { // Phase out from full value - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / - (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); - //LL_INFOS() << "Starting motion phase out of " << (F32) phase_out << LL_ENDL; - } - phase_out = llclamp(phase_out, 0.0, 1.0); - - new_pos = new_pos * ((F32) phase_out); - new_v = new_v * ((F32) phase_out); - } - } - } - } - - new_pos = new_pos + getPositionRegion(); - new_v = new_v + vel; - - - // Clamp interpolated position to minimum underground and maximum region height - LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); - F32 min_height; - if (isAvatar()) - { // Make a better guess about AVs not going underground - min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global); - min_height += (0.5f * getScale().mV[VZ]); - } - else - { // This will put the object underground, but we can't tell if it will stop - // at ground level or not - min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); - // Cap maximum height - new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); - } - - new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); - - // Check to see if it's going off the region - LLVector3 temp(new_pos.mV[VX], new_pos.mV[VY], 0.f); - if (temp.clamp(0.f, mRegionp->getWidth())) - { // Going off this region, so see if we might end up on another region - LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); - new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above - - // Clip the positions to known regions - LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global); - if (clip_pos_global != new_pos_global) - { - // Was clipped, so this means we hit a edge where there is no region to enter - LLVector3 clip_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); - LL_DEBUGS("Interpolate") << "Hit empty region edge, clipped predicted position to " - << clip_pos - << " from " << new_pos << LL_ENDL; - new_pos = clip_pos; - - // Stop motion and get server update for bouncing on the edge - new_v.clear(); - setAcceleration(LLVector3::zero); - } - else - { - // Check for how long we are crossing. - // Note: theoretically we can find time from velocity, acceleration and - // distance from border to new position, but it is not going to work - // if 'phase_out' activates - if (mRegionCrossExpire == 0) - { - // Workaround: we can't accurately figure out time when we cross border - // so just write down time 'after the fact', it is far from optimal in - // case of lags, but for lags sMaxUpdateInterpolationTime will kick in first - LL_DEBUGS("Interpolate") << "Predicted region crossing, new position " << new_pos << LL_ENDL; - mRegionCrossExpire = frame_time + sMaxRegionCrossingInterpolationTime; - } - else if (frame_time > mRegionCrossExpire) - { - // Predicting crossing over 1s, stop motion - // Stop motion - LL_DEBUGS("Interpolate") << "Predicting region crossing for too long, stopping at " << new_pos << LL_ENDL; - new_v.clear(); - setAcceleration(LLVector3::zero); - mRegionCrossExpire = 0; - } - } - } - else - { - mRegionCrossExpire = 0; - } - - // Set new position and velocity - setPositionRegion(new_pos); - setVelocity(new_v); - - // for objects that are spinning but not translating, make sure to flag them as having moved - setChanged(MOVED | SILHOUETTE); - } - - // Update the last time we did anything - mLastInterpUpdateSecs = frame_time; + // linear motion + // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object + // updates represents the average velocity of the last timestep, rather than the final velocity. + // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically + // + // *TODO: should also wrap linear accel/velocity in check + // to see if object is selected, instead of explicitly + // zeroing it out + + F32 dt = dt_seconds; + F64Seconds time_since_last_update = frame_time - mLastMessageUpdateSecs; + if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f) + { + return; + } + + LLVector3 accel = getAcceleration(); + LLVector3 vel = getVelocity(); + + if (sMaxUpdateInterpolationTime <= (F64Seconds)0.0) + { // Old code path ... unbounded, simple interpolation + if (!(accel.isExactlyZero() && vel.isExactlyZero())) + { + LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + + // region local + setPositionRegion(pos + getPositionRegion()); + setVelocity(vel + accel*dt); + + // for objects that are spinning but not translating, make sure to flag them as having moved + setChanged(MOVED | SILHOUETTE); + } + } + else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving + { // Object is moving, and hasn't been too long since we got an update from the server + + // Calculate predicted position and velocity + LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + LLVector3 new_v = accel * dt; + + if (time_since_last_update > sPhaseOutUpdateInterpolationTime && + sPhaseOutUpdateInterpolationTime > (F64Seconds)0.0) + { // Haven't seen a viewer update in a while, check to see if the circuit is still active + if (mRegionp) + { // The simulator will NOT send updates if the object continues normally on the path + // predicted by the velocity and the acceleration (often gravity) sent to the viewer + // So check to see if the circuit is blocked, which means the sim is likely in a long lag + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() ); + if (cdp) + { + // Find out how many seconds since last packet arrived on the circuit + F64Seconds time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); + + if (!cdp->isAlive() || // Circuit is dead or blocked + cdp->isBlocked() || // or doesn't seem to be getting any packets + (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) + { + // Start to reduce motion interpolation since we haven't seen a server update in a while + F64Seconds time_since_last_interpolation = frame_time - mLastInterpUpdateSecs; + F64 phase_out = 1.0; + if (time_since_last_update > sMaxUpdateInterpolationTime) + { // Past the time limit, so stop the object + phase_out = 0.0; + //LL_INFOS() << "Motion phase out to zero" << LL_ENDL; + + // Kill angular motion as well. Note - not adding this due to paranoia + // about stopping rotation for llTargetOmega objects and not having it restart + // setAngularVelocity(LLVector3::zero); + } + else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime) + { // Last update was already phased out a bit + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + (sMaxUpdateInterpolationTime - time_since_last_interpolation); + //LL_INFOS() << "Continuing motion phase out of " << (F32) phase_out << LL_ENDL; + } + else + { // Phase out from full value + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); + //LL_INFOS() << "Starting motion phase out of " << (F32) phase_out << LL_ENDL; + } + phase_out = llclamp(phase_out, 0.0, 1.0); + + new_pos = new_pos * ((F32) phase_out); + new_v = new_v * ((F32) phase_out); + } + } + } + } + + new_pos = new_pos + getPositionRegion(); + new_v = new_v + vel; + + + // Clamp interpolated position to minimum underground and maximum region height + LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); + F32 min_height; + if (isAvatar()) + { // Make a better guess about AVs not going underground + min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global); + min_height += (0.5f * getScale().mV[VZ]); + } + else + { // This will put the object underground, but we can't tell if it will stop + // at ground level or not + min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); + // Cap maximum height + new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); + } + + new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); + + // Check to see if it's going off the region + LLVector3 temp(new_pos.mV[VX], new_pos.mV[VY], 0.f); + if (temp.clamp(0.f, mRegionp->getWidth())) + { // Going off this region, so see if we might end up on another region + LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); + new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above + + // Clip the positions to known regions + LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global); + if (clip_pos_global != new_pos_global) + { + // Was clipped, so this means we hit a edge where there is no region to enter + LLVector3 clip_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); + LL_DEBUGS("Interpolate") << "Hit empty region edge, clipped predicted position to " + << clip_pos + << " from " << new_pos << LL_ENDL; + new_pos = clip_pos; + + // Stop motion and get server update for bouncing on the edge + new_v.clear(); + setAcceleration(LLVector3::zero); + } + else + { + // Check for how long we are crossing. + // Note: theoretically we can find time from velocity, acceleration and + // distance from border to new position, but it is not going to work + // if 'phase_out' activates + if (mRegionCrossExpire == 0) + { + // Workaround: we can't accurately figure out time when we cross border + // so just write down time 'after the fact', it is far from optimal in + // case of lags, but for lags sMaxUpdateInterpolationTime will kick in first + LL_DEBUGS("Interpolate") << "Predicted region crossing, new position " << new_pos << LL_ENDL; + mRegionCrossExpire = frame_time + sMaxRegionCrossingInterpolationTime; + } + else if (frame_time > mRegionCrossExpire) + { + // Predicting crossing over 1s, stop motion + // Stop motion + LL_DEBUGS("Interpolate") << "Predicting region crossing for too long, stopping at " << new_pos << LL_ENDL; + new_v.clear(); + setAcceleration(LLVector3::zero); + mRegionCrossExpire = 0; + } + } + } + else + { + mRegionCrossExpire = 0; + } + + // Set new position and velocity + setPositionRegion(new_pos); + setVelocity(new_v); + + // for objects that are spinning but not translating, make sure to flag them as having moved + setChanged(MOVED | SILHOUETTE); + } + + // Update the last time we did anything + mLastInterpUpdateSecs = frame_time; } BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size) { - delete [] mData; + delete [] mData; - if (datap) - { - mData = new U8[data_size]; - if (!mData) - { - return FALSE; - } - memcpy(mData, datap, data_size); /* Flawfinder: ignore */ - } - return TRUE; + if (datap) + { + mData = new U8[data_size]; + if (!mData) + { + return FALSE; + } + memcpy(mData, datap, data_size); /* Flawfinder: ignore */ + } + return TRUE; } // delete an item in the inventory, but don't tell the server. This is @@ -2781,213 +2781,213 @@ BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size) // This will only delete the first item with an item_id in the list void LLViewerObject::deleteInventoryItem(const LLUUID& item_id) { - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it ) - { - if((*it)->getUUID() == item_id) - { - // This is safe only because we return immediatly. - mInventory->erase(it); // will deref and delete it - return; - } - } - doInventoryCallback(); - } + if(mInventory) + { + LLInventoryObject::object_list_t::iterator it = mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = mInventory->end(); + for( ; it != end; ++it ) + { + if((*it)->getUUID() == item_id) + { + // This is safe only because we return immediatly. + mInventory->erase(it); // will deref and delete it + return; + } + } + doInventoryCallback(); + } } void LLViewerObject::doUpdateInventory( - LLPointer& item, - U8 key, - bool is_new) -{ - LLViewerInventoryItem* old_item = NULL; - if(TASK_INVENTORY_ITEM_KEY == key) - { - old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID()); - } - else if(TASK_INVENTORY_ASSET_KEY == key) - { - old_item = getInventoryItemByAsset(item->getAssetUUID()); - } - LLUUID item_id; - LLUUID new_owner; - LLUUID new_group; - BOOL group_owned = FALSE; - if(old_item) - { - item_id = old_item->getUUID(); - new_owner = old_item->getPermissions().getOwner(); - new_group = old_item->getPermissions().getGroup(); - group_owned = old_item->getPermissions().isGroupOwned(); - old_item = NULL; - } - else - { - item_id = item->getUUID(); - } - if(!is_new && mInventory) - { - // Attempt to update the local inventory. If we can get the - // object perm, we have perfect visibility, so we want the - // serial number to match. Otherwise, take our best guess and - // make sure that the serial number does not match. - deleteInventoryItem(item_id); - LLPermissions perm(item->getPermissions()); - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true; - if(obj_perm) - { - perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic); - } - else - { - if(group_owned) - { - perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); - } - else if(!new_owner.isNull()) - { - // The object used to be in inventory, so we can - // assume the owner and group will match what they are - // there. - perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); - } - // *FIX: can make an even better guess by using the mPermGroup flags - else if(permYouOwner()) - { - // best guess. - perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic); - --mExpectedInventorySerialNum; - } - else - { - // dummy it up. - perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic); - --mExpectedInventorySerialNum; - } - } - LLViewerInventoryItem* oldItem = item; - LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem); - new_item->setPermissions(perm); - mInventory->push_front(new_item); - doInventoryCallback(); - ++mExpectedInventorySerialNum; - } - else if (is_new) - { - ++mExpectedInventorySerialNum; - } + LLPointer& item, + U8 key, + bool is_new) +{ + LLViewerInventoryItem* old_item = NULL; + if(TASK_INVENTORY_ITEM_KEY == key) + { + old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID()); + } + else if(TASK_INVENTORY_ASSET_KEY == key) + { + old_item = getInventoryItemByAsset(item->getAssetUUID()); + } + LLUUID item_id; + LLUUID new_owner; + LLUUID new_group; + BOOL group_owned = FALSE; + if(old_item) + { + item_id = old_item->getUUID(); + new_owner = old_item->getPermissions().getOwner(); + new_group = old_item->getPermissions().getGroup(); + group_owned = old_item->getPermissions().isGroupOwned(); + old_item = NULL; + } + else + { + item_id = item->getUUID(); + } + if(!is_new && mInventory) + { + // Attempt to update the local inventory. If we can get the + // object perm, we have perfect visibility, so we want the + // serial number to match. Otherwise, take our best guess and + // make sure that the serial number does not match. + deleteInventoryItem(item_id); + LLPermissions perm(item->getPermissions()); + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); + bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true; + if(obj_perm) + { + perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic); + } + else + { + if(group_owned) + { + perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); + } + else if(!new_owner.isNull()) + { + // The object used to be in inventory, so we can + // assume the owner and group will match what they are + // there. + perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); + } + // *FIX: can make an even better guess by using the mPermGroup flags + else if(permYouOwner()) + { + // best guess. + perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic); + --mExpectedInventorySerialNum; + } + else + { + // dummy it up. + perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic); + --mExpectedInventorySerialNum; + } + } + LLViewerInventoryItem* oldItem = item; + LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem); + new_item->setPermissions(perm); + mInventory->push_front(new_item); + doInventoryCallback(); + ++mExpectedInventorySerialNum; + } + else if (is_new) + { + ++mExpectedInventorySerialNum; + } } // save a script, which involves removing the old one, and rezzing // in the new one. This method should be called with the asset id // of the new and old script AFTER the bytecode has been saved. void LLViewerObject::saveScript( - const LLViewerInventoryItem* item, - BOOL active, - bool is_new) -{ - /* - * XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the - * interaction with doUpdateInventory() called below. - */ - LL_DEBUGS() << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << LL_ENDL; - - LLPointer task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), item->getFlags(), - item->getCreationDate()); - task_item->setTransactionID(item->getTransactionID()); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezScript); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - msg->nextBlockFast(_PREHASH_UpdateBlock); - msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID)); - U8 enabled = active; - msg->addBOOLFast(_PREHASH_Enabled, enabled); - msg->nextBlockFast(_PREHASH_InventoryBlock); - task_item->packMessage(msg); - msg->sendReliable(mRegionp->getHost()); - - // do the internal logic - doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new); + const LLViewerInventoryItem* item, + BOOL active, + bool is_new) +{ + /* + * XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the + * interaction with doUpdateInventory() called below. + */ + LL_DEBUGS() << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << LL_ENDL; + + LLPointer task_item = + new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), + item->getAssetUUID(), item->getType(), + item->getInventoryType(), + item->getName(), item->getDescription(), + item->getSaleInfo(), item->getFlags(), + item->getCreationDate()); + task_item->setTransactionID(item->getTransactionID()); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RezScript); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); + msg->nextBlockFast(_PREHASH_UpdateBlock); + msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID)); + U8 enabled = active; + msg->addBOOLFast(_PREHASH_Enabled, enabled); + msg->nextBlockFast(_PREHASH_InventoryBlock); + task_item->packMessage(msg); + msg->sendReliable(mRegionp->getHost()); + + // do the internal logic + doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new); } void LLViewerObject::moveInventory(const LLUUID& folder_id, - const LLUUID& item_id) -{ - LL_DEBUGS() << "LLViewerObject::moveInventory " << item_id << LL_ENDL; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoveTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_FolderID, folder_id); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addUUIDFast(_PREHASH_ItemID, item_id); - msg->sendReliable(mRegionp->getHost()); - - LLInventoryObject* inv_obj = getInventoryObject(item_id); - if(inv_obj) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj; - if(!item->getPermissions().allowCopyBy(gAgent.getID())) - { - deleteInventoryItem(item_id); - ++mExpectedInventorySerialNum; - } - } + const LLUUID& item_id) +{ + LL_DEBUGS() << "LLViewerObject::moveInventory " << item_id << LL_ENDL; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_MoveTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addUUIDFast(_PREHASH_FolderID, folder_id); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_LocalID, mLocalID); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + msg->sendReliable(mRegionp->getHost()); + + LLInventoryObject* inv_obj = getInventoryObject(item_id); + if(inv_obj) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj; + if(!item->getPermissions().allowCopyBy(gAgent.getID())) + { + deleteInventoryItem(item_id); + ++mExpectedInventorySerialNum; + } + } } void LLViewerObject::dirtyInventory() { - // If there aren't any LLVOInventoryListeners, we won't be - // able to update our mInventory when it comes back from the - // simulator, so we should not clear the inventory either. - if(mInventory && !mInventoryCallbacks.empty()) - { - mInventory->clear(); // will deref and delete entries - delete mInventory; - mInventory = NULL; - } - mInventoryDirty = TRUE; + // If there aren't any LLVOInventoryListeners, we won't be + // able to update our mInventory when it comes back from the + // simulator, so we should not clear the inventory either. + if(mInventory && !mInventoryCallbacks.empty()) + { + mInventory->clear(); // will deref and delete entries + delete mInventory; + mInventory = NULL; + } + mInventoryDirty = TRUE; } void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data) { - LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo; - info->mListener = listener; - info->mInventoryData = user_data; - mInventoryCallbacks.push_front(info); + LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo; + info->mListener = listener; + info->mInventoryData = user_data; + mInventoryCallbacks.push_front(info); } void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener) { - if (listener == NULL) - return; - for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); - iter != mInventoryCallbacks.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLInventoryCallbackInfo* info = *curiter; - if (info->mListener == listener) - { - delete info; - mInventoryCallbacks.erase(curiter); - break; - } - } + if (listener == NULL) + return; + for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); + iter != mInventoryCallbacks.end(); ) + { + callback_list_t::iterator curiter = iter++; + LLInventoryCallbackInfo* info = *curiter; + if (info->mListener == listener) + { + delete info; + mInventoryCallbacks.erase(curiter); + break; + } + } } BOOL LLViewerObject::isInventoryPending() @@ -2997,60 +2997,60 @@ BOOL LLViewerObject::isInventoryPending() void LLViewerObject::clearInventoryListeners() { - for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); - mInventoryCallbacks.clear(); + for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); + mInventoryCallbacks.clear(); } bool LLViewerObject::hasInventoryListeners() { - return !mInventoryCallbacks.empty(); + return !mInventoryCallbacks.empty(); } void LLViewerObject::requestInventory() { - if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty()) - { - mInventory->clear(); // will deref and delete entries - delete mInventory; - mInventory = NULL; - } - - if(mInventory) - { - // inventory is either up to date or doesn't has a listener - // if it is dirty, leave it this way in case we gain a listener - doInventoryCallback(); - } - else - { - // since we are going to request it now - mInventoryDirty = FALSE; - - // Note: throws away duplicate requests - fetchInventoryFromServer(); - } + if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty()) + { + mInventory->clear(); // will deref and delete entries + delete mInventory; + mInventory = NULL; + } + + if(mInventory) + { + // inventory is either up to date or doesn't has a listener + // if it is dirty, leave it this way in case we gain a listener + doInventoryCallback(); + } + else + { + // since we are going to request it now + mInventoryDirty = FALSE; + + // Note: throws away duplicate requests + fetchInventoryFromServer(); + } } void LLViewerObject::fetchInventoryFromServer() { - if (!isInventoryPending()) - { - delete mInventory; - mInventory = NULL; - - // Results in processTaskInv - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->sendReliable(mRegionp->getHost()); - - // This will get reset by doInventoryCallback or processTaskInv - mInvRequestState = INVENTORY_REQUEST_PENDING; - } + if (!isInventoryPending()) + { + delete mInventory; + mInventory = NULL; + + // Results in processTaskInv + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_LocalID, mLocalID); + msg->sendReliable(mRegionp->getHost()); + + // This will get reset by doInventoryCallback or processTaskInv + mInvRequestState = INVENTORY_REQUEST_PENDING; + } } void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds) @@ -3166,8 +3166,8 @@ void LLViewerObject::linkControlAvatar() return; } mControlAvatar = LLControlAvatar::createControlAvatar(volp); - LL_DEBUGS("AnimatedObjects") << volp->getID() - << " created control av for " + LL_DEBUGS("AnimatedObjects") << volp->getID() + << " created control av for " << (S32) (1+volp->numChildren()) << " prims" << LL_ENDL; } LLControlAvatar *cav = getControlAvatar(); @@ -3217,26 +3217,26 @@ bool LLViewerObject::isAnimatedObject() const struct LLFilenameAndTask { - LLUUID mTaskID; - std::string mFilename; + LLUUID mTaskID; + std::string mFilename; - // for sequencing in case of multiple updates - S16 mSerial; + // for sequencing in case of multiple updates + S16 mSerial; #ifdef _DEBUG - static S32 sCount; - LLFilenameAndTask() - { - ++sCount; - LL_DEBUGS() << "Constructing LLFilenameAndTask: " << sCount << LL_ENDL; - } - ~LLFilenameAndTask() - { - --sCount; - LL_DEBUGS() << "Destroying LLFilenameAndTask: " << sCount << LL_ENDL; - } + static S32 sCount; + LLFilenameAndTask() + { + ++sCount; + LL_DEBUGS() << "Constructing LLFilenameAndTask: " << sCount << LL_ENDL; + } + ~LLFilenameAndTask() + { + --sCount; + LL_DEBUGS() << "Destroying LLFilenameAndTask: " << sCount << LL_ENDL; + } private: - LLFilenameAndTask(const LLFilenameAndTask& rhs); - const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const; + LLFilenameAndTask(const LLFilenameAndTask& rhs); + const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const; #endif }; @@ -3289,7 +3289,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) LLFilenameAndTask* ft = new LLFilenameAndTask; ft->mTaskID = task_id; ft->mSerial = serial; - + // We received version we expected or newer. Load it. object->mInventorySerialNum = ft->mSerial; object->mExpectedInventorySerialNum = ft->mSerial; @@ -3345,154 +3345,154 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status) { - LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data; - LLViewerObject* object = NULL; - - if (ft - && (0 == error_code) - && (object = gObjectList.findObject(ft->mTaskID)) - && ft->mSerial >= object->mInventorySerialNum) - { - object->mInventorySerialNum = ft->mSerial; - LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL; - if (ft->mSerial < object->mExpectedInventorySerialNum) - { - // User managed to change something while inventory was loading - LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL; - } - - if (object->loadTaskInvFile(ft->mFilename)) - { - - LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); - std::list& pending_lst = object->mPendingInventoryItemsIDs; - - for (; it != end && pending_lst.size(); ++it) - { - LLViewerInventoryItem* item = dynamic_cast(it->get()); - if(item && item->getType() != LLAssetType::AT_CATEGORY) - { - std::list::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); - if (id_it != pending_lst.end()) - { - pending_lst.erase(id_it); - } - } - } - } - else - { - // MAINT-2597 - crash when trying to edit a no-mod object - // Somehow get an contents inventory response, but with an invalid stream (possibly 0 size?) - // Stated repro was specific to no-mod objects so failing without user interaction should be safe. - LL_WARNS() << "Trying to load invalid task inventory file. Ignoring file contents." << LL_ENDL; - } - } - else - { - // This Occurs When two requests were made, and the first one - // has already handled it. - LL_DEBUGS() << "Problem loading task inventory. Return code: " - << error_code << LL_ENDL; - } - delete ft; + LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data; + LLViewerObject* object = NULL; + + if (ft + && (0 == error_code) + && (object = gObjectList.findObject(ft->mTaskID)) + && ft->mSerial >= object->mInventorySerialNum) + { + object->mInventorySerialNum = ft->mSerial; + LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL; + if (ft->mSerial < object->mExpectedInventorySerialNum) + { + // User managed to change something while inventory was loading + LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL; + } + + if (object->loadTaskInvFile(ft->mFilename)) + { + + LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); + std::list& pending_lst = object->mPendingInventoryItemsIDs; + + for (; it != end && pending_lst.size(); ++it) + { + LLViewerInventoryItem* item = dynamic_cast(it->get()); + if(item && item->getType() != LLAssetType::AT_CATEGORY) + { + std::list::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + if (id_it != pending_lst.end()) + { + pending_lst.erase(id_it); + } + } + } + } + else + { + // MAINT-2597 - crash when trying to edit a no-mod object + // Somehow get an contents inventory response, but with an invalid stream (possibly 0 size?) + // Stated repro was specific to no-mod objects so failing without user interaction should be safe. + LL_WARNS() << "Trying to load invalid task inventory file. Ignoring file contents." << LL_ENDL; + } + } + else + { + // This Occurs When two requests were made, and the first one + // has already handled it. + LL_DEBUGS() << "Problem loading task inventory. Return code: " + << error_code << LL_ENDL; + } + delete ft; } BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) { - std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); - llifstream ifs(filename_and_local_path.c_str()); - if(ifs.good()) - { - U32 fail_count = 0; - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - // *NOTE: This buffer size is hard coded into scanf() below. - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - if(mInventory) - { - mInventory->clear(); // will deref and delete it - } - else - { - mInventory = new LLInventoryObject::object_list_t; - } - while(ifs.good()) - { - ifs.getline(buffer, MAX_STRING); - if (sscanf(buffer, " %254s", keyword) == EOF) /* Flawfinder: ignore */ - { - // Blank file? - LL_WARNS() << "Issue reading from file '" - << filename << "'" << LL_ENDL; - break; - } - else if(0 == strcmp("inv_item", keyword)) - { - LLPointer inv = new LLViewerInventoryItem; - inv->importLegacyStream(ifs); - mInventory->push_front(inv); - } - else if(0 == strcmp("inv_object", keyword)) - { - LLPointer inv = new LLInventoryObject; - inv->importLegacyStream(ifs); - inv->rename("Contents"); - mInventory->push_front(inv); - } - else if (fail_count >= MAX_INV_FILE_READ_FAILS) - { - LL_WARNS() << "Encountered too many unknowns while reading from file: '" - << filename << "'" << LL_ENDL; - break; - } - else - { - // Is there really a point to continue processing? We already failing to display full inventory - fail_count++; - LL_WARNS_ONCE() << "Unknown token while reading from inventory file. Token: '" - << keyword << "'" << LL_ENDL; - } - } - ifs.close(); - LLFile::remove(filename_and_local_path); - } - else - { - LL_WARNS() << "unable to load task inventory: " << filename_and_local_path - << LL_ENDL; - return FALSE; - } - doInventoryCallback(); - - return TRUE; + std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); + llifstream ifs(filename_and_local_path.c_str()); + if(ifs.good()) + { + U32 fail_count = 0; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + // *NOTE: This buffer size is hard coded into scanf() below. + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + if(mInventory) + { + mInventory->clear(); // will deref and delete it + } + else + { + mInventory = new LLInventoryObject::object_list_t; + } + while(ifs.good()) + { + ifs.getline(buffer, MAX_STRING); + if (sscanf(buffer, " %254s", keyword) == EOF) /* Flawfinder: ignore */ + { + // Blank file? + LL_WARNS() << "Issue reading from file '" + << filename << "'" << LL_ENDL; + break; + } + else if(0 == strcmp("inv_item", keyword)) + { + LLPointer inv = new LLViewerInventoryItem; + inv->importLegacyStream(ifs); + mInventory->push_front(inv); + } + else if(0 == strcmp("inv_object", keyword)) + { + LLPointer inv = new LLInventoryObject; + inv->importLegacyStream(ifs); + inv->rename("Contents"); + mInventory->push_front(inv); + } + else if (fail_count >= MAX_INV_FILE_READ_FAILS) + { + LL_WARNS() << "Encountered too many unknowns while reading from file: '" + << filename << "'" << LL_ENDL; + break; + } + else + { + // Is there really a point to continue processing? We already failing to display full inventory + fail_count++; + LL_WARNS_ONCE() << "Unknown token while reading from inventory file. Token: '" + << keyword << "'" << LL_ENDL; + } + } + ifs.close(); + LLFile::remove(filename_and_local_path); + } + else + { + LL_WARNS() << "unable to load task inventory: " << filename_and_local_path + << LL_ENDL; + return FALSE; + } + doInventoryCallback(); + + return TRUE; } -void LLViewerObject::doInventoryCallback() -{ - for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); - iter != mInventoryCallbacks.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLInventoryCallbackInfo* info = *curiter; - if (info->mListener != NULL) - { - info->mListener->inventoryChanged(this, - mInventory, - mInventorySerialNum, - info->mInventoryData); - } - else - { - LL_INFOS() << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << LL_ENDL; - delete info; - mInventoryCallbacks.erase(curiter); - } - } - - // release inventory loading state - mInvRequestXFerId = 0; - mInvRequestState = INVENTORY_REQUEST_STOPPED; +void LLViewerObject::doInventoryCallback() +{ + for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); + iter != mInventoryCallbacks.end(); ) + { + callback_list_t::iterator curiter = iter++; + LLInventoryCallbackInfo* info = *curiter; + if (info->mListener != NULL) + { + info->mListener->inventoryChanged(this, + mInventory, + mInventorySerialNum, + info->mInventoryData); + } + else + { + LL_INFOS() << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << LL_ENDL; + delete info; + mInventoryCallbacks.erase(curiter); + } + } + + // release inventory loading state + mInvRequestXFerId = 0; + mInvRequestState = INVENTORY_REQUEST_STOPPED; } void LLViewerObject::removeInventory(const LLUUID& item_id) @@ -3503,17 +3503,17 @@ void LLViewerObject::removeInventory(const LLUUID& item_id) params["object"] = mID; LLFloaterReg::hideInstance("item_properties", params); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addUUIDFast(_PREHASH_ItemID, item_id); - msg->sendReliable(mRegionp->getHost()); - deleteInventoryItem(item_id); - ++mExpectedInventorySerialNum; + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RemoveTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_LocalID, mLocalID); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + msg->sendReliable(mRegionp->getHost()); + deleteInventoryItem(item_id); + ++mExpectedInventorySerialNum; } bool LLViewerObject::isAssetInInventory(LLViewerInventoryItem* item, LLAssetType::EType type) @@ -3565,136 +3565,136 @@ void LLViewerObject::updateMaterialInventory(LLViewerInventoryItem* item, U8 key } void LLViewerObject::updateInventory( - LLViewerInventoryItem* item, - U8 key, - bool is_new) -{ - // This slices the object into what we're concerned about on the - // viewer. The simulator will take the permissions and transfer - // ownership. - LLPointer task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), - item->getFlags(), - item->getCreationDate()); - task_item->setTransactionID(item->getTransactionID()); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_UpdateData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addU8Fast(_PREHASH_Key, key); - msg->nextBlockFast(_PREHASH_InventoryData); - task_item->packMessage(msg); - msg->sendReliable(mRegionp->getHost()); - - // do the internal logic - doUpdateInventory(task_item, key, is_new); + LLViewerInventoryItem* item, + U8 key, + bool is_new) +{ + // This slices the object into what we're concerned about on the + // viewer. The simulator will take the permissions and transfer + // ownership. + LLPointer task_item = + new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), + item->getAssetUUID(), item->getType(), + item->getInventoryType(), + item->getName(), item->getDescription(), + item->getSaleInfo(), + item->getFlags(), + item->getCreationDate()); + task_item->setTransactionID(item->getTransactionID()); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UpdateTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_UpdateData); + msg->addU32Fast(_PREHASH_LocalID, mLocalID); + msg->addU8Fast(_PREHASH_Key, key); + msg->nextBlockFast(_PREHASH_InventoryData); + task_item->packMessage(msg); + msg->sendReliable(mRegionp->getHost()); + + // do the internal logic + doUpdateInventory(task_item, key, is_new); } void LLViewerObject::updateInventoryLocal(LLInventoryItem* item, U8 key) { - LLPointer task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), item->getFlags(), - item->getCreationDate()); + LLPointer task_item = + new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), + item->getAssetUUID(), item->getType(), + item->getInventoryType(), + item->getName(), item->getDescription(), + item->getSaleInfo(), item->getFlags(), + item->getCreationDate()); - // do the internal logic - const bool is_new = false; - doUpdateInventory(task_item, key, is_new); + // do the internal logic + const bool is_new = false; + doUpdateInventory(task_item, key, is_new); } LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id) { - LLInventoryObject* rv = NULL; - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for ( ; it != end; ++it) - { - if((*it)->getUUID() == item_id) - { - rv = *it; - break; - } - } - } - return rv; + LLInventoryObject* rv = NULL; + if(mInventory) + { + LLInventoryObject::object_list_t::iterator it = mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = mInventory->end(); + for ( ; it != end; ++it) + { + if((*it)->getUUID() == item_id) + { + rv = *it; + break; + } + } + } + return rv; } LLInventoryItem* LLViewerObject::getInventoryItem(const LLUUID& item_id) { - LLInventoryObject* iobj = getInventoryObject(item_id); - if (!iobj || iobj->getType() == LLAssetType::AT_CATEGORY) - { - return NULL; - } - LLInventoryItem* item = dynamic_cast(iobj); - return item; + LLInventoryObject* iobj = getInventoryObject(item_id); + if (!iobj || iobj->getType() == LLAssetType::AT_CATEGORY) + { + return NULL; + } + LLInventoryItem* item = dynamic_cast(iobj); + return item; } void LLViewerObject::getInventoryContents(LLInventoryObject::object_list_t& objects) { - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it) - { - if ((*it)->getType() != LLAssetType::AT_CATEGORY) - { - objects.push_back(*it); - } - } - } + if(mInventory) + { + LLInventoryObject::object_list_t::iterator it = mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = mInventory->end(); + for( ; it != end; ++it) + { + if ((*it)->getType() != LLAssetType::AT_CATEGORY) + { + objects.push_back(*it); + } + } + } } LLInventoryObject* LLViewerObject::getInventoryRoot() { - if (!mInventory || !mInventory->size()) - { - return NULL; - } - return mInventory->back(); + if (!mInventory || !mInventory->size()) + { + return NULL; + } + return mInventory->back(); } LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id) { - if (mInventoryDirty) - LL_WARNS() << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << LL_ENDL; - - LLViewerInventoryItem* rv = NULL; - if(mInventory) - { - LLViewerInventoryItem* item = NULL; - - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it) - { - LLInventoryObject* obj = *it; - if(obj->getType() != LLAssetType::AT_CATEGORY) - { - // *FIX: gank-ass down cast! - item = (LLViewerInventoryItem*)obj; - if(item->getAssetUUID() == asset_id) - { - rv = item; - break; - } - } - } - } - return rv; + if (mInventoryDirty) + LL_WARNS() << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << LL_ENDL; + + LLViewerInventoryItem* rv = NULL; + if(mInventory) + { + LLViewerInventoryItem* item = NULL; + + LLInventoryObject::object_list_t::iterator it = mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = mInventory->end(); + for( ; it != end; ++it) + { + LLInventoryObject* obj = *it; + if(obj->getType() != LLAssetType::AT_CATEGORY) + { + // *FIX: gank-ass down cast! + item = (LLViewerInventoryItem*)obj; + if(item->getAssetUUID() == asset_id) + { + rv = item; + break; + } + } + } + } + return rv; } LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id, LLAssetType::EType type) @@ -3736,70 +3736,70 @@ LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& ass } void LLViewerObject::updateViewerInventoryAsset( - const LLViewerInventoryItem* item, - const LLUUID& new_asset) + const LLViewerInventoryItem* item, + const LLUUID& new_asset) { - LLPointer task_item = - new LLViewerInventoryItem(item); - task_item->setAssetUUID(new_asset); + LLPointer task_item = + new LLViewerInventoryItem(item); + task_item->setAssetUUID(new_asset); - // do the internal logic - doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false); + // do the internal logic + doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false); } void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) { - if (getVolume()) - { //volumes calculate pixel area and angle per face - return; - } - - LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 pos_agent = getRenderPosition(); - - F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; - F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; - F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; - - F32 max_scale = getMaxScale(); - F32 mid_scale = getMidScale(); - F32 min_scale = getMinScale(); - - // IW: estimate - when close to large objects, computing range based on distance from center is no good - // to try to get a min distance from face, subtract min_scale/2 from the range. - // This means we'll load too much detail sometimes, but that's better than not enough - // I don't think there's a better way to do this without calculating distance per-poly - F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; - - LLViewerCamera* camera = LLViewerCamera::getInstance(); - if (range < 0.001f || isHUDAttachment()) // range == zero - { - mAppAngle = 180.f; - mPixelArea = (F32)camera->getScreenPixelArea(); - } - else - { - mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG; - - F32 pixels_per_meter = camera->getPixelMeterRatio() / range; - - mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale); - if (mPixelArea > camera->getScreenPixelArea()) - { - mAppAngle = 180.f; - mPixelArea = (F32)camera->getScreenPixelArea(); - } - } + if (getVolume()) + { //volumes calculate pixel area and angle per face + return; + } + + LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); + LLVector3 pos_agent = getRenderPosition(); + + F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; + F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; + F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; + + F32 max_scale = getMaxScale(); + F32 mid_scale = getMidScale(); + F32 min_scale = getMinScale(); + + // IW: estimate - when close to large objects, computing range based on distance from center is no good + // to try to get a min distance from face, subtract min_scale/2 from the range. + // This means we'll load too much detail sometimes, but that's better than not enough + // I don't think there's a better way to do this without calculating distance per-poly + F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + if (range < 0.001f || isHUDAttachment()) // range == zero + { + mAppAngle = 180.f; + mPixelArea = (F32)camera->getScreenPixelArea(); + } + else + { + mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG; + + F32 pixels_per_meter = camera->getPixelMeterRatio() / range; + + mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale); + if (mPixelArea > camera->getScreenPixelArea()) + { + mAppAngle = 180.f; + mPixelArea = (F32)camera->getScreenPixelArea(); + } + } } BOOL LLViewerObject::updateLOD() { - return FALSE; + return FALSE; } BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) { - return TRUE; + return TRUE; } void LLViewerObject::updateGL() @@ -3809,51 +3809,51 @@ void LLViewerObject::updateGL() void LLViewerObject::updateFaceSize(S32 idx) { - + } LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline) { - return NULL; + return NULL; } void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) { - LLPrimitive::setScale(scale); - if (mDrawable.notNull()) - { - //encompass completely sheared objects by taking - //the most extreme point possible (<1,1,0.5>) - mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec()); - updateDrawable(damped); - } - - if( (LL_PCODE_VOLUME == getPCode()) && !isDead() ) - { - if (permYouOwner() || (scale.magVecSquared() > (7.5f * 7.5f)) ) - { - if (!mOnMap) - { - llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle())); - - gObjectList.addToMap(this); - mOnMap = TRUE; - } - } - else - { - if (mOnMap) - { - gObjectList.removeFromMap(this); - mOnMap = FALSE; - } - } - } + LLPrimitive::setScale(scale); + if (mDrawable.notNull()) + { + //encompass completely sheared objects by taking + //the most extreme point possible (<1,1,0.5>) + mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec()); + updateDrawable(damped); + } + + if( (LL_PCODE_VOLUME == getPCode()) && !isDead() ) + { + if (permYouOwner() || (scale.magVecSquared() > (7.5f * 7.5f)) ) + { + if (!mOnMap) + { + llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle())); + + gObjectList.addToMap(this); + mOnMap = TRUE; + } + } + else + { + if (mOnMap) + { + gObjectList.removeFromMap(this); + mOnMap = FALSE; + } + } + } } void LLViewerObject::setObjectCostStale() { - mCostStale = true; + mCostStale = true; // *NOTE: This is harmlessly redundant for Blinn-Phong material updates, as // the root prim currently gets set stale anyway due to other property // updates. But it is needed for GLTF material ID updates. @@ -3863,96 +3863,96 @@ void LLViewerObject::setObjectCostStale() void LLViewerObject::setObjectCost(F32 cost) { - mObjectCost = cost; - mCostStale = false; + mObjectCost = cost; + mCostStale = false; - if (isSelected()) - { - gFloaterTools->dirty(); - } + if (isSelected()) + { + gFloaterTools->dirty(); + } } void LLViewerObject::setLinksetCost(F32 cost) { - mLinksetCost = cost; - mCostStale = false; + mLinksetCost = cost; + mCostStale = false; - BOOL needs_refresh = isSelected(); - child_list_t::iterator iter = mChildList.begin(); - while(iter != mChildList.end() && !needs_refresh) - { - LLViewerObject* child = *iter; - needs_refresh = child->isSelected(); - iter++; - } + BOOL needs_refresh = isSelected(); + child_list_t::iterator iter = mChildList.begin(); + while(iter != mChildList.end() && !needs_refresh) + { + LLViewerObject* child = *iter; + needs_refresh = child->isSelected(); + iter++; + } - if (needs_refresh) - { - gFloaterTools->dirty(); - } + if (needs_refresh) + { + gFloaterTools->dirty(); + } } void LLViewerObject::setPhysicsCost(F32 cost) { - mPhysicsCost = cost; - mCostStale = false; + mPhysicsCost = cost; + mCostStale = false; - if (isSelected()) - { - gFloaterTools->dirty(); - } + if (isSelected()) + { + gFloaterTools->dirty(); + } } void LLViewerObject::setLinksetPhysicsCost(F32 cost) { - mLinksetPhysicsCost = cost; - mCostStale = false; - - if (isSelected()) - { - gFloaterTools->dirty(); - } + mLinksetPhysicsCost = cost; + mCostStale = false; + + if (isSelected()) + { + gFloaterTools->dirty(); + } } F32 LLViewerObject::getObjectCost() { - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mObjectCost; + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mObjectCost; } F32 LLViewerObject::getLinksetCost() { - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } - return mLinksetCost; + return mLinksetCost; } F32 LLViewerObject::getPhysicsCost() { - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mPhysicsCost; + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mPhysicsCost; } F32 LLViewerObject::getLinksetPhysicsCost() { - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } - return mLinksetPhysicsCost; + return mLinksetPhysicsCost; } F32 LLViewerObject::recursiveGetEstTrianglesMax() const @@ -3973,7 +3973,7 @@ F32 LLViewerObject::recursiveGetEstTrianglesMax() const S32 LLViewerObject::getAnimatedObjectMaxTris() const { S32 max_tris = 0; - if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) + if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) { max_tris = S32_MAX; } @@ -4005,7 +4005,7 @@ F32 LLViewerObject::getEstTrianglesStreamingCost() const // virtual F32 LLViewerObject::getStreamingCost() const { - return 0.f; + return 0.f; } // virtual @@ -4017,12 +4017,12 @@ bool LLViewerObject::getCostData(LLMeshCostData& costs) const U32 LLViewerObject::getTriangleCount(S32* vcount) const { - return 0; + return 0; } U32 LLViewerObject::getHighLODTriangleCount() { - return 0; + return 0; } U32 LLViewerObject::recursiveGetTriangleCount(S32* vcount) const @@ -4057,7 +4057,7 @@ F32 LLViewerObject::recursiveGetScaledSurfaceArea() const { if (volume->getVolume()) { - const LLVector3& scale = volume->getScale(); + const LLVector3& scale = volume->getScale(); area += volume->getVolume()->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); } LLViewerObject::const_child_list_t children = volume->getChildren(); @@ -4080,68 +4080,68 @@ F32 LLViewerObject::recursiveGetScaledSurfaceArea() const void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { - LLVector4a center; - center.load3(getRenderPosition().mV); - LLVector4a size; - size.load3(getScale().mV); - newMin.setSub(center, size); - newMax.setAdd(center, size); - - mDrawable->setPositionGroup(center); + LLVector4a center; + center.load3(getRenderPosition().mV); + LLVector4a size; + size.load3(getScale().mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + mDrawable->setPositionGroup(center); } F32 LLViewerObject::getBinRadius() { - if (mDrawable.notNull()) - { - const LLVector4a* ext = mDrawable->getSpatialExtents(); - LLVector4a diff; - diff.setSub(ext[1], ext[0]); - return diff.getLength3().getF32(); - } - - return getScale().magVec(); + if (mDrawable.notNull()) + { + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a diff; + diff.setSub(ext[1], ext[0]); + return diff.getLength3().getF32(); + } + + return getScale().magVec(); } F32 LLViewerObject::getMaxScale() const { - return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]); + return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]); } F32 LLViewerObject::getMinScale() const { - return llmin(getScale().mV[0],getScale().mV[1],getScale().mV[2]); + return llmin(getScale().mV[0],getScale().mV[1],getScale().mV[2]); } F32 LLViewerObject::getMidScale() const { - if (getScale().mV[VX] < getScale().mV[VY]) - { - if (getScale().mV[VY] < getScale().mV[VZ]) - { - return getScale().mV[VY]; - } - else if (getScale().mV[VX] < getScale().mV[VZ]) - { - return getScale().mV[VZ]; - } - else - { - return getScale().mV[VX]; - } - } - else if (getScale().mV[VX] < getScale().mV[VZ]) - { - return getScale().mV[VX]; - } - else if (getScale().mV[VY] < getScale().mV[VZ]) - { - return getScale().mV[VZ]; - } - else - { - return getScale().mV[VY]; - } + if (getScale().mV[VX] < getScale().mV[VY]) + { + if (getScale().mV[VY] < getScale().mV[VZ]) + { + return getScale().mV[VY]; + } + else if (getScale().mV[VX] < getScale().mV[VZ]) + { + return getScale().mV[VZ]; + } + else + { + return getScale().mV[VX]; + } + } + else if (getScale().mV[VX] < getScale().mV[VZ]) + { + return getScale().mV[VX]; + } + else if (getScale().mV[VY] < getScale().mV[VZ]) + { + return getScale().mV[VZ]; + } + else + { + return getScale().mV[VY]; + } } @@ -4151,68 +4151,68 @@ void LLViewerObject::updateTextures() void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) { - if (isDead() || !getVolume()) - { - return; - } - - S32 i; - S32 tex_count = getNumTEs(); - for (i = 0; i < tex_count; i++) - { - getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); - } - - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); - } - - if (boost_children) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->boostTexturePriority(); - } - } + if (isDead() || !getVolume()) + { + return; + } + + S32 i; + S32 tex_count = getNumTEs(); + for (i = 0; i < tex_count; i++) + { + getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + } + + if (isSculpted() && !isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + } + + if (boost_children) + { + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + child->boostTexturePriority(); + } + } } void LLViewerObject::setLineWidthForWindowSize(S32 window_width) { - if (window_width < 700) - { - LLUI::setLineWidth(2.0f); - } - else if (window_width < 1100) - { - LLUI::setLineWidth(3.0f); - } - else if (window_width < 2000) - { - LLUI::setLineWidth(4.0f); - } - else - { - // _damn_, what a nice monitor! - LLUI::setLineWidth(5.0f); - } + if (window_width < 700) + { + LLUI::setLineWidth(2.0f); + } + else if (window_width < 1100) + { + LLUI::setLineWidth(3.0f); + } + else if (window_width < 2000) + { + LLUI::setLineWidth(4.0f); + } + else + { + // _damn_, what a nice monitor! + LLUI::setLineWidth(5.0f); + } } void LLViewerObject::increaseArrowLength() { /* ??? - if (mAxisArrowLength == 50) - { - mAxisArrowLength = 100; - } - else - { - mAxisArrowLength = 150; - } + if (mAxisArrowLength == 50) + { + mAxisArrowLength = 100; + } + else + { + mAxisArrowLength = 150; + } */ } @@ -4220,158 +4220,158 @@ void LLViewerObject::increaseArrowLength() void LLViewerObject::decreaseArrowLength() { /* ??? - if (mAxisArrowLength == 150) - { - mAxisArrowLength = 100; - } - else - { - mAxisArrowLength = 50; - } + if (mAxisArrowLength == 150) + { + mAxisArrowLength = 100; + } + else + { + mAxisArrowLength = 50; + } */ } // Culled from newsim LLTask::addNVPair void LLViewerObject::addNVPair(const std::string& data) { - // cout << "LLViewerObject::addNVPair() with ---" << data << "---" << endl; - LLNameValue *nv = new LLNameValue(data.c_str()); - -// char splat[MAX_STRING]; -// temp->printNameValue(splat); -// LL_INFOS() << "addNVPair " << splat << LL_ENDL; - - name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName); - if (iter != mNameValuePairs.end()) - { - LLNameValue* foundnv = iter->second; - if (foundnv->mClass != NVC_READ_ONLY) - { - delete foundnv; - mNameValuePairs.erase(iter); - } - else - { - delete nv; -// LL_INFOS() << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << LL_ENDL; - return; - } - } - mNameValuePairs[nv->mName] = nv; + // cout << "LLViewerObject::addNVPair() with ---" << data << "---" << endl; + LLNameValue *nv = new LLNameValue(data.c_str()); + +// char splat[MAX_STRING]; +// temp->printNameValue(splat); +// LL_INFOS() << "addNVPair " << splat << LL_ENDL; + + name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName); + if (iter != mNameValuePairs.end()) + { + LLNameValue* foundnv = iter->second; + if (foundnv->mClass != NVC_READ_ONLY) + { + delete foundnv; + mNameValuePairs.erase(iter); + } + else + { + delete nv; +// LL_INFOS() << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << LL_ENDL; + return; + } + } + mNameValuePairs[nv->mName] = nv; } BOOL LLViewerObject::removeNVPair(const std::string& name) { - char* canonical_name = gNVNameTable.addString(name); + char* canonical_name = gNVNameTable.addString(name); - LL_DEBUGS() << "LLViewerObject::removeNVPair(): " << name << LL_ENDL; + LL_DEBUGS() << "LLViewerObject::removeNVPair(): " << name << LL_ENDL; - name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name); - if (iter != mNameValuePairs.end()) - { - if( mRegionp ) - { - LLNameValue* nv = iter->second; + name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name); + if (iter != mNameValuePairs.end()) + { + if( mRegionp ) + { + LLNameValue* nv = iter->second; /* - std::string buffer = nv->printNameValue(); - gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair); - gMessageSystem->nextBlockFast(_PREHASH_TaskData); - gMessageSystem->addUUIDFast(_PREHASH_ID, mID); - - gMessageSystem->nextBlockFast(_PREHASH_NameValueData); - gMessageSystem->addStringFast(_PREHASH_NVPair, buffer); - - gMessageSystem->sendReliable( mRegionp->getHost() ); + std::string buffer = nv->printNameValue(); + gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair); + gMessageSystem->nextBlockFast(_PREHASH_TaskData); + gMessageSystem->addUUIDFast(_PREHASH_ID, mID); + + gMessageSystem->nextBlockFast(_PREHASH_NameValueData); + gMessageSystem->addStringFast(_PREHASH_NVPair, buffer); + + gMessageSystem->sendReliable( mRegionp->getHost() ); */ - // Remove the NV pair from the local list. - delete nv; - mNameValuePairs.erase(iter); - return TRUE; - } - else - { - LL_DEBUGS() << "removeNVPair - No region for object" << LL_ENDL; - } - } - return FALSE; + // Remove the NV pair from the local list. + delete nv; + mNameValuePairs.erase(iter); + return TRUE; + } + else + { + LL_DEBUGS() << "removeNVPair - No region for object" << LL_ENDL; + } + } + return FALSE; } LLNameValue *LLViewerObject::getNVPair(const std::string& name) const { - char *canonical_name; + char *canonical_name; - canonical_name = gNVNameTable.addString(name); + canonical_name = gNVNameTable.addString(name); - // If you access a map with a name that isn't in it, it will add the name and a null pointer. - // So first check if the data is in the map. - name_value_map_t::const_iterator iter = mNameValuePairs.find(canonical_name); - if (iter != mNameValuePairs.end()) - { - return iter->second; - } - else - { - return NULL; - } + // If you access a map with a name that isn't in it, it will add the name and a null pointer. + // So first check if the data is in the map. + name_value_map_t::const_iterator iter = mNameValuePairs.find(canonical_name); + if (iter != mNameValuePairs.end()) + { + return iter->second; + } + else + { + return NULL; + } } void LLViewerObject::updatePositionCaches() const { - // If region is removed from the list it is also deleted. - if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) - { - if (!isRoot()) - { - mPositionRegion = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } - else - { - mPositionRegion = getPosition(); - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } - } + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) + { + if (!isRoot()) + { + mPositionRegion = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); + mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); + } + else + { + mPositionRegion = getPosition(); + mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); + } + } } const LLVector3d LLViewerObject::getPositionGlobal() const -{ - // If region is removed from the list it is also deleted. - if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) - { - LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); - - if (isAttachment()) - { - position_global = gAgent.getPosGlobalFromAgent(getRenderPosition()); - } - return position_global; - } - else - { - LLVector3d position_global(getPosition()); - return position_global; - } +{ + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) + { + LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); + + if (isAttachment()) + { + position_global = gAgent.getPosGlobalFromAgent(getRenderPosition()); + } + return position_global; + } + else + { + LLVector3d position_global(getPosition()); + return position_global; + } } const LLVector3 &LLViewerObject::getPositionAgent() const { - // If region is removed from the list it is also deleted. - if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) - { - if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent())) - { - // Don't return cached position if you have a parent, recalc (until all dirtying is done correctly. - LLVector3 position_region; - position_region = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); - mPositionAgent = mRegionp->getPosAgentFromRegion(position_region); - } - else - { - mPositionAgent = mRegionp->getPosAgentFromRegion(getPosition()); - } - } - return mPositionAgent; + // If region is removed from the list it is also deleted. + if(mRegionp && LLWorld::instance().isRegionListed(mRegionp)) + { + if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent())) + { + // Don't return cached position if you have a parent, recalc (until all dirtying is done correctly. + LLVector3 position_region; + position_region = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); + mPositionAgent = mRegionp->getPosAgentFromRegion(position_region); + } + else + { + mPositionAgent = mRegionp->getPosAgentFromRegion(getPosition()); + } + } + return mPositionAgent; } LLMatrix4a LLViewerObject::getGLTFAssetToAgentTransform() const @@ -4517,7 +4517,7 @@ void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset) LLVector4a origin = LLVector4a::getZero(); LLVector4a offset_v; offset_v.load3(offset.mV); - + agent_to_node.affineTransform(offset_v, offset_v); agent_to_node.affineTransform(origin, origin); @@ -4538,37 +4538,37 @@ void LLViewerObject::moveGLTFNode(S32 node_index, const LLVector3& offset) const LLVector3 &LLViewerObject::getPositionRegion() const { - if (!isRoot()) - { - LLViewerObject *parent = (LLViewerObject *)getParent(); - mPositionRegion = parent->getPositionRegion() + (getPosition() * parent->getRotation()); - } - else - { - mPositionRegion = getPosition(); - } + if (!isRoot()) + { + LLViewerObject *parent = (LLViewerObject *)getParent(); + mPositionRegion = parent->getPositionRegion() + (getPosition() * parent->getRotation()); + } + else + { + mPositionRegion = getPosition(); + } - return mPositionRegion; + return mPositionRegion; } const LLVector3 LLViewerObject::getPositionEdit() const { - if (isRootEdit()) - { - return getPosition(); - } - else - { - LLViewerObject *parent = (LLViewerObject *)getParent(); - LLVector3 position_edit = parent->getPositionEdit() + getPosition() * parent->getRotationEdit(); - return position_edit; - } + if (isRootEdit()) + { + return getPosition(); + } + else + { + LLViewerObject *parent = (LLViewerObject *)getParent(); + LLVector3 position_edit = parent->getPositionEdit() + getPosition() * parent->getRotationEdit(); + return position_edit; + } } const LLVector3 LLViewerObject::getRenderPosition() const { - if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) - { + if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) + { LLControlAvatar *cav = getControlAvatar(); if (isRoot() && cav) { @@ -4581,448 +4581,448 @@ const LLVector3 LLViewerObject::getRenderPosition() const return pos; } } - LLVOAvatar* avatar = getAvatar(); - if ((avatar) && !getControlAvatar()) - { - return avatar->getPositionAgent(); - } - } + LLVOAvatar* avatar = getAvatar(); + if ((avatar) && !getControlAvatar()) + { + return avatar->getPositionAgent(); + } + } - if (mDrawable.isNull() || mDrawable->getGeneration() < 0) - { - return getPositionAgent(); - } - else - { - return mDrawable->getPositionAgent(); - } + if (mDrawable.isNull() || mDrawable->getGeneration() < 0) + { + return getPositionAgent(); + } + else + { + return mDrawable->getPositionAgent(); + } } const LLVector3 LLViewerObject::getPivotPositionAgent() const { - return getRenderPosition(); + return getRenderPosition(); } const LLQuaternion LLViewerObject::getRenderRotation() const { - LLQuaternion ret; - if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED) && !isAnimatedObject()) - { - return ret; - } - - if (mDrawable.isNull() || mDrawable->isStatic()) - { - ret = getRotationEdit(); - } - else - { - if (!mDrawable->isRoot()) - { - ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix()); - } - else - { - ret = LLQuaternion(mDrawable->getWorldMatrix()); - } - } - - return ret; + LLQuaternion ret; + if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED) && !isAnimatedObject()) + { + return ret; + } + + if (mDrawable.isNull() || mDrawable->isStatic()) + { + ret = getRotationEdit(); + } + else + { + if (!mDrawable->isRoot()) + { + ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix()); + } + else + { + ret = LLQuaternion(mDrawable->getWorldMatrix()); + } + } + + return ret; } const LLMatrix4 LLViewerObject::getRenderMatrix() const { - return mDrawable->getWorldMatrix(); + return mDrawable->getWorldMatrix(); } const LLQuaternion LLViewerObject::getRotationRegion() const { - LLQuaternion global_rotation = getRotation(); - if (!((LLXform *)this)->isRoot()) - { - global_rotation = global_rotation * getParent()->getRotation(); - } - return global_rotation; + LLQuaternion global_rotation = getRotation(); + if (!((LLXform *)this)->isRoot()) + { + global_rotation = global_rotation * getParent()->getRotation(); + } + return global_rotation; } const LLQuaternion LLViewerObject::getRotationEdit() const { - LLQuaternion global_rotation = getRotation(); - if (!((LLXform *)this)->isRootEdit()) - { - global_rotation = global_rotation * getParent()->getRotation(); - } - return global_rotation; + LLQuaternion global_rotation = getRotation(); + if (!((LLXform *)this)->isRootEdit()) + { + global_rotation = global_rotation * getParent()->getRotation(); + } + return global_rotation; } void LLViewerObject::setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped ) { - if (isAttachment()) - { - LLVector3 new_pos = mRegionp->getPosRegionFromGlobal(pos_global); - if (isRootEdit()) - { - new_pos -= mDrawable->mXform.getParent()->getWorldPosition(); - LLQuaternion world_rotation = mDrawable->mXform.getParent()->getWorldRotation(); - new_pos = new_pos * ~world_rotation; - } - else - { - LLViewerObject* parentp = (LLViewerObject*)getParent(); - new_pos -= parentp->getPositionAgent(); - new_pos = new_pos * ~parentp->getRotationRegion(); - } - LLViewerObject::setPosition(new_pos); - - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - } - else - { - if( isRoot() ) - { - setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); - } - else - { - // the relative position with the parent is not constant - LLViewerObject* parent = (LLViewerObject *)getParent(); - //RN: this assumes we are only calling this function from the edit tools - gPipeline.updateMoveNormalAsync(parent->mDrawable); - - LLVector3 pos_local = mRegionp->getPosRegionFromGlobal(pos_global) - parent->getPositionRegion(); - pos_local = pos_local * ~parent->getRotationRegion(); - LLViewerObject::setPosition( pos_local ); - } - } - //RN: assumes we always want to snap the object when calling this function - gPipeline.updateMoveNormalAsync(mDrawable); + if (isAttachment()) + { + LLVector3 new_pos = mRegionp->getPosRegionFromGlobal(pos_global); + if (isRootEdit()) + { + new_pos -= mDrawable->mXform.getParent()->getWorldPosition(); + LLQuaternion world_rotation = mDrawable->mXform.getParent()->getWorldRotation(); + new_pos = new_pos * ~world_rotation; + } + else + { + LLViewerObject* parentp = (LLViewerObject*)getParent(); + new_pos -= parentp->getPositionAgent(); + new_pos = new_pos * ~parentp->getRotationRegion(); + } + LLViewerObject::setPosition(new_pos); + + if (mParent && ((LLViewerObject*)mParent)->isAvatar()) + { + // we have changed the position of an attachment, so we need to clamp it + LLVOAvatar *avatar = (LLVOAvatar*)mParent; + + avatar->clampAttachmentPositions(); + } + } + else + { + if( isRoot() ) + { + setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); + } + else + { + // the relative position with the parent is not constant + LLViewerObject* parent = (LLViewerObject *)getParent(); + //RN: this assumes we are only calling this function from the edit tools + gPipeline.updateMoveNormalAsync(parent->mDrawable); + + LLVector3 pos_local = mRegionp->getPosRegionFromGlobal(pos_global) - parent->getPositionRegion(); + pos_local = pos_local * ~parent->getRotationRegion(); + LLViewerObject::setPosition( pos_local ); + } + } + //RN: assumes we always want to snap the object when calling this function + gPipeline.updateMoveNormalAsync(mDrawable); } void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped) { - if (getPosition() != pos) - { - setChanged(TRANSLATED | SILHOUETTE); - } - - LLXform::setPosition(pos); - updateDrawable(damped); - if (isRoot()) - { - // position caches need to be up to date on root objects - updatePositionCaches(); - } + if (getPosition() != pos) + { + setChanged(TRANSLATED | SILHOUETTE); + } + + LLXform::setPosition(pos); + updateDrawable(damped); + if (isRoot()) + { + // position caches need to be up to date on root objects + updatePositionCaches(); + } } void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped) { - if (isAttachment()) - { - if (isRootEdit()) - { - LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); - newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); - - LLQuaternion invWorldRotation = mDrawable->mXform.getParent()->getWorldRotation(); - invWorldRotation.transQuat(); - - newPos = newPos * invWorldRotation; - LLViewerObject::setPosition(newPos); - } - else - { - // assumes parent is root editable (root of attachment) - LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); - newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); - LLVector3 delta_pos = newPos - getPosition(); - - LLQuaternion invRotation = mDrawable->getRotation(); - invRotation.transQuat(); - - delta_pos = delta_pos * invRotation; - - // *FIX: is this right? Shouldn't we be calling the - // LLViewerObject version of setPosition? - LLVector3 old_pos = mDrawable->mXform.getParent()->getPosition(); - mDrawable->mXform.getParent()->setPosition(old_pos + delta_pos); - setChanged(TRANSLATED | SILHOUETTE); - } - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - } - else - { - if (isRoot()) - { - setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); - } - else - { - // the relative position with the parent is constant, but the parent's position needs to be changed - LLVector3d position_offset; - position_offset.setVec(getPosition()*getParent()->getRotation()); - LLVector3d new_pos_global = pos_global - position_offset; - ((LLViewerObject *)getParent())->setPositionGlobal(new_pos_global); - } - } - updateDrawable(damped); + if (isAttachment()) + { + if (isRootEdit()) + { + LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); + newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); + + LLQuaternion invWorldRotation = mDrawable->mXform.getParent()->getWorldRotation(); + invWorldRotation.transQuat(); + + newPos = newPos * invWorldRotation; + LLViewerObject::setPosition(newPos); + } + else + { + // assumes parent is root editable (root of attachment) + LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); + newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); + LLVector3 delta_pos = newPos - getPosition(); + + LLQuaternion invRotation = mDrawable->getRotation(); + invRotation.transQuat(); + + delta_pos = delta_pos * invRotation; + + // *FIX: is this right? Shouldn't we be calling the + // LLViewerObject version of setPosition? + LLVector3 old_pos = mDrawable->mXform.getParent()->getPosition(); + mDrawable->mXform.getParent()->setPosition(old_pos + delta_pos); + setChanged(TRANSLATED | SILHOUETTE); + } + if (mParent && ((LLViewerObject*)mParent)->isAvatar()) + { + // we have changed the position of an attachment, so we need to clamp it + LLVOAvatar *avatar = (LLVOAvatar*)mParent; + + avatar->clampAttachmentPositions(); + } + } + else + { + if (isRoot()) + { + setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); + } + else + { + // the relative position with the parent is constant, but the parent's position needs to be changed + LLVector3d position_offset; + position_offset.setVec(getPosition()*getParent()->getRotation()); + LLVector3d new_pos_global = pos_global - position_offset; + ((LLViewerObject *)getParent())->setPositionGlobal(new_pos_global); + } + } + updateDrawable(damped); } void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped) { - // Set position relative to parent, if no parent, relative to region - if (!isRoot()) - { - LLViewerObject::setPosition(pos_parent, damped); - //updateDrawable(damped); - } - else - { - setPositionRegion(pos_parent, damped); - } + // Set position relative to parent, if no parent, relative to region + if (!isRoot()) + { + LLViewerObject::setPosition(pos_parent, damped); + //updateDrawable(damped); + } + else + { + setPositionRegion(pos_parent, damped); + } } void LLViewerObject::setPositionRegion(const LLVector3 &pos_region, BOOL damped) { - if (!isRootEdit()) - { - LLViewerObject* parent = (LLViewerObject*) getParent(); - LLViewerObject::setPosition((pos_region-parent->getPositionRegion())*~parent->getRotationRegion()); - } - else - { - LLViewerObject::setPosition(pos_region); - mPositionRegion = pos_region; - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } + if (!isRootEdit()) + { + LLViewerObject* parent = (LLViewerObject*) getParent(); + LLViewerObject::setPosition((pos_region-parent->getPositionRegion())*~parent->getRotationRegion()); + } + else + { + LLViewerObject::setPosition(pos_region); + mPositionRegion = pos_region; + mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); + } } void LLViewerObject::setPositionAgent(const LLVector3 &pos_agent, BOOL damped) { - LLVector3 pos_region = getRegion()->getPosRegionFromAgent(pos_agent); - setPositionRegion(pos_region, damped); + LLVector3 pos_region = getRegion()->getPosRegionFromAgent(pos_agent); + setPositionRegion(pos_region, damped); } -// identical to setPositionRegion() except it checks for child-joints +// identical to setPositionRegion() except it checks for child-joints // and doesn't also move the joint-parent // TODO -- implement similar intelligence for joint-parents toward // their joint-children void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped) { - if (!isRootEdit()) - { - // the relative position with the parent is constant, but the parent's position needs to be changed - LLVector3 position_offset = getPosition() * getParent()->getRotation(); + if (!isRootEdit()) + { + // the relative position with the parent is constant, but the parent's position needs to be changed + LLVector3 position_offset = getPosition() * getParent()->getRotation(); - ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset); - updateDrawable(damped); - } - else - { - LLViewerObject::setPosition(pos_edit, damped); - mPositionRegion = pos_edit; - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } + ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset); + updateDrawable(damped); + } + else + { + LLViewerObject::setPosition(pos_edit, damped); + mPositionRegion = pos_edit; + mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); + } } LLViewerObject* LLViewerObject::getRootEdit() const { - const LLViewerObject* root = this; - while (root->mParent - && !((LLViewerObject*)root->mParent)->isAvatar()) - { - root = (LLViewerObject*)root->mParent; - } - return (LLViewerObject*)root; + const LLViewerObject* root = this; + while (root->mParent + && !((LLViewerObject*)root->mParent)->isAvatar()) + { + root = (LLViewerObject*)root->mParent; + } + return (LLViewerObject*)root; } BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face, - BOOL pick_transparent, - BOOL pick_rigged, + S32 face, + BOOL pick_transparent, + BOOL pick_rigged, BOOL pick_unselectable, - S32* face_hit, - LLVector4a* intersection, - LLVector2* tex_coord, - LLVector4a* normal, - LLVector4a* tangent) + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent) { - return false; + return false; } BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector4a& start, const LLVector4a& end) { - if (mDrawable.isNull() || mDrawable->isDead()) - { - return FALSE; - } + if (mDrawable.isNull() || mDrawable->isDead()) + { + return FALSE; + } - const LLVector4a* ext = mDrawable->getSpatialExtents(); + const LLVector4a* ext = mDrawable->getSpatialExtents(); - //VECTORIZE THIS - LLVector4a center; - center.setAdd(ext[1], ext[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); + //VECTORIZE THIS + LLVector4a center; + center.setAdd(ext[1], ext[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - return LLLineSegmentBoxIntersect(start, end, center, size); + return LLLineSegmentBoxIntersect(start, end, center, size); } U8 LLViewerObject::getMediaType() const { - if (mMedia) - { - return mMedia->mMediaType; - } - else - { - return LLViewerObject::MEDIA_NONE; - } + if (mMedia) + { + return mMedia->mMediaType; + } + else + { + return LLViewerObject::MEDIA_NONE; + } } void LLViewerObject::setMediaType(U8 media_type) { - if (!mMedia) - { - // TODO what if we don't have a media pointer? - } - else if (mMedia->mMediaType != media_type) - { - mMedia->mMediaType = media_type; + if (!mMedia) + { + // TODO what if we don't have a media pointer? + } + else if (mMedia->mMediaType != media_type) + { + mMedia->mMediaType = media_type; - // TODO: update materials with new image - } + // TODO: update materials with new image + } } std::string LLViewerObject::getMediaURL() const { - if (mMedia) - { - return mMedia->mMediaURL; - } - else - { - return std::string(); - } + if (mMedia) + { + return mMedia->mMediaURL; + } + else + { + return std::string(); + } } void LLViewerObject::setMediaURL(const std::string& media_url) { - if (!mMedia) - { - mMedia = new LLViewerObjectMedia; - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; + if (!mMedia) + { + mMedia = new LLViewerObjectMedia; + mMedia->mMediaURL = media_url; + mMedia->mPassedWhitelist = FALSE; - // TODO: update materials with new image - } - else if (mMedia->mMediaURL != media_url) - { - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; + // TODO: update materials with new image + } + else if (mMedia->mMediaURL != media_url) + { + mMedia->mMediaURL = media_url; + mMedia->mPassedWhitelist = FALSE; - // TODO: update materials with new image - } + // TODO: update materials with new image + } } BOOL LLViewerObject::getMediaPassedWhitelist() const { - if (mMedia) - { - return mMedia->mPassedWhitelist; - } - else - { - return FALSE; - } + if (mMedia) + { + return mMedia->mPassedWhitelist; + } + else + { + return FALSE; + } } void LLViewerObject::setMediaPassedWhitelist(BOOL passed) { - if (mMedia) - { - mMedia->mPassedWhitelist = passed; - } + if (mMedia) + { + mMedia->mPassedWhitelist = passed; + } } BOOL LLViewerObject::setMaterial(const U8 material) { - BOOL res = LLPrimitive::setMaterial(material); - if (res) - { - setChanged(TEXTURE); - } - return res; + BOOL res = LLPrimitive::setMaterial(material); + if (res) + { + setChanged(TEXTURE); + } + return res; } void LLViewerObject::setNumTEs(const U8 num_tes) { - U32 i; - if (num_tes != getNumTEs()) - { - if (num_tes) - { - LLPointer *new_images; - new_images = new LLPointer[num_tes]; - - LLPointer *new_normmaps; - new_normmaps = new LLPointer[num_tes]; - - LLPointer *new_specmaps; - new_specmaps = new LLPointer[num_tes]; - for (i = 0; i < num_tes; i++) - { - if (i < getNumTEs()) - { - new_images[i] = mTEImages[i]; - new_normmaps[i] = mTENormalMaps[i]; - new_specmaps[i] = mTESpecularMaps[i]; - } - else if (getNumTEs()) - { - new_images[i] = mTEImages[getNumTEs()-1]; - new_normmaps[i] = mTENormalMaps[getNumTEs()-1]; - new_specmaps[i] = mTESpecularMaps[getNumTEs()-1]; - } - else - { - new_images[i] = NULL; - new_normmaps[i] = NULL; - new_specmaps[i] = NULL; - } - } - - deleteTEImages(); - - mTEImages = new_images; - mTENormalMaps = new_normmaps; - mTESpecularMaps = new_specmaps; - } - else - { - deleteTEImages(); - } + U32 i; + if (num_tes != getNumTEs()) + { + if (num_tes) + { + LLPointer *new_images; + new_images = new LLPointer[num_tes]; + + LLPointer *new_normmaps; + new_normmaps = new LLPointer[num_tes]; + + LLPointer *new_specmaps; + new_specmaps = new LLPointer[num_tes]; + for (i = 0; i < num_tes; i++) + { + if (i < getNumTEs()) + { + new_images[i] = mTEImages[i]; + new_normmaps[i] = mTENormalMaps[i]; + new_specmaps[i] = mTESpecularMaps[i]; + } + else if (getNumTEs()) + { + new_images[i] = mTEImages[getNumTEs()-1]; + new_normmaps[i] = mTENormalMaps[getNumTEs()-1]; + new_specmaps[i] = mTESpecularMaps[getNumTEs()-1]; + } + else + { + new_images[i] = NULL; + new_normmaps[i] = NULL; + new_specmaps[i] = NULL; + } + } + + deleteTEImages(); + + mTEImages = new_images; + mTENormalMaps = new_normmaps; + mTESpecularMaps = new_specmaps; + } + else + { + deleteTEImages(); + } S32 original_tes = getNumTEs(); - LLPrimitive::setNumTEs(num_tes); - setChanged(TEXTURE); + LLPrimitive::setNumTEs(num_tes); + setChanged(TEXTURE); // touch up GLTF materials if (original_tes > 0) @@ -5050,124 +5050,124 @@ void LLViewerObject::setNumTEs(const U8 num_tes) } } - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } } void LLViewerObject::sendMaterialUpdate() const { - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessageFast(_PREHASH_ObjectMaterial); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - gMessageSystem->addU8Fast(_PREHASH_Material, getMaterial() ); - gMessageSystem->sendReliable( regionp->getHost() ); + LLViewerRegion* regionp = getRegion(); + if(!regionp) return; + gMessageSystem->newMessageFast(_PREHASH_ObjectMaterial); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); + gMessageSystem->addU8Fast(_PREHASH_Material, getMaterial() ); + gMessageSystem->sendReliable( regionp->getHost() ); } //formerly send_object_shape(LLViewerObject *object) void LLViewerObject::sendShapeUpdate() { - gMessageSystem->newMessageFast(_PREHASH_ObjectShape); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); + gMessageSystem->newMessageFast(_PREHASH_ObjectShape); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - LLVolumeMessage::packVolumeParams(&getVolume()->getParams(), gMessageSystem); + LLVolumeMessage::packVolumeParams(&getVolume()->getParams(), gMessageSystem); - LLViewerRegion *regionp = getRegion(); - gMessageSystem->sendReliable( regionp->getHost() ); + LLViewerRegion *regionp = getRegion(); + gMessageSystem->sendReliable( regionp->getHost() ); } void LLViewerObject::sendTEUpdate() const { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ObjectImage); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectImage); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - if (mMedia) - { - msg->addString("MediaURL", mMedia->mMediaURL); - } - else - { - msg->addString("MediaURL", NULL); - } + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); + if (mMedia) + { + msg->addString("MediaURL", mMedia->mMediaURL); + } + else + { + msg->addString("MediaURL", NULL); + } - // TODO send media type + // TODO send media type - packTEMessage(msg); + packTEMessage(msg); - LLViewerRegion *regionp = getRegion(); - msg->sendReliable( regionp->getHost() ); + LLViewerRegion *regionp = getRegion(); + msg->sendReliable( regionp->getHost() ); } LLViewerTexture* LLViewerObject::getBakedTextureForMagicId(const LLUUID& id) { - if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) - { - return NULL; - } - - LLViewerObject *root = getRootEdit(); - if (root && root->isAnimatedObject()) - { - return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - - LLVOAvatar* avatar = getAvatar(); - if (avatar && !isHUDAttachment()) - { - LLAvatarAppearanceDefines::EBakedTextureIndex texIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(id); - LLViewerTexture* bakedTexture = avatar->getBakedTexture(texIndex); - if (bakedTexture == NULL || bakedTexture->isMissingAsset()) - { - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } - else - { - return bakedTexture; - } - } - else - { - return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } + if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) + { + return NULL; + } + + LLViewerObject *root = getRootEdit(); + if (root && root->isAnimatedObject()) + { + return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + + LLVOAvatar* avatar = getAvatar(); + if (avatar && !isHUDAttachment()) + { + LLAvatarAppearanceDefines::EBakedTextureIndex texIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(id); + LLViewerTexture* bakedTexture = avatar->getBakedTexture(texIndex); + if (bakedTexture == NULL || bakedTexture->isMissingAsset()) + { + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } + else + { + return bakedTexture; + } + } + else + { + return LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } } void LLViewerObject::updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& old_id) { - if (id == old_id) - { - return; - } + if (id == old_id) + { + return; + } - if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(old_id) && !LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) - { - return; - } + if (!LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(old_id) && !LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(id)) + { + return; + } - LLVOAvatar* avatar = getAvatar(); - if (avatar) - { - avatar->updateMeshVisibility(); - } + LLVOAvatar* avatar = getAvatar(); + if (avatar) + { + avatar->updateMeshVisibility(); + } } @@ -5192,14 +5192,14 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry& texture_entry) void LLViewerObject::updateTEMaterialTextures(U8 te) { - if (getTE(te)->getMaterialParams().notNull()) - { - const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); - mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - - const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); - mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } + if (getTE(te)->getMaterialParams().notNull()) + { + const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } LLFetchedGLTFMaterial* mat = (LLFetchedGLTFMaterial*) getTE(te)->getGLTFRenderMaterial(); llassert(mat == nullptr || dynamic_cast(getTE(te)->getGLTFRenderMaterial()) != nullptr); @@ -5259,354 +5259,354 @@ void LLViewerObject::updateTEMaterialTextures(U8 te) void LLViewerObject::refreshBakeTexture() { - for (int face_index = 0; face_index < getNumTEs(); face_index++) - { - LLTextureEntry* tex_entry = getTE(face_index); - if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID())) - { - const LLUUID& image_id = tex_entry->getID(); - LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); - changeTEImage(face_index, bakedTexture); - } - } + for (int face_index = 0; face_index < getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = getTE(face_index); + if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID())) + { + const LLUUID& image_id = tex_entry->getID(); + LLViewerTexture* bakedTexture = getBakedTextureForMagicId(image_id); + changeTEImage(face_index, bakedTexture); + } + } } void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) { - if (mTEImages[te] != imagep) - { - LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null; - - LLPrimitive::setTETexture(te, imagep->getID()); + if (mTEImages[te] != imagep) + { + LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null; - LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID()); - mTEImages[te] = baked_texture ? baked_texture : imagep; - updateAvatarMeshVisibility(imagep->getID(), old_image_id); - setChanged(TEXTURE); - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } + LLPrimitive::setTETexture(te, imagep->getID()); + + LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID()); + mTEImages[te] = baked_texture ? baked_texture : imagep; + updateAvatarMeshVisibility(imagep->getID(), old_image_id); + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } } S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { - LLUUID old_image_id = getTE(te)->getID(); - const LLUUID& uuid = image ? image->getID() : LLUUID::null; - S32 retval = 0; - if (uuid != getTE(te)->getID() || - uuid == LLUUID::null) - { - retval = LLPrimitive::setTETexture(te, uuid); - LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid); - mTEImages[te] = baked_texture ? baked_texture : image; - updateAvatarMeshVisibility(uuid,old_image_id); - setChanged(TEXTURE); - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; + LLUUID old_image_id = getTE(te)->getID(); + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + S32 retval = 0; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + retval = LLPrimitive::setTETexture(te, uuid); + LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid); + mTEImages[te] = baked_texture ? baked_texture : image; + updateAvatarMeshVisibility(uuid,old_image_id); + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; } S32 LLViewerObject::setTENormalMapCore(const U8 te, LLViewerTexture *image) { - S32 retval = TEM_CHANGE_TEXTURE; - const LLUUID& uuid = image ? image->getID() : LLUUID::null; - if (uuid != getTE(te)->getID() || - uuid == LLUUID::null) - { - LLTextureEntry* tep = getTE(te); - LLMaterial* mat = NULL; - if (tep) - { - mat = tep->getMaterialParams(); - } - - if (mat) - { - mat->setNormalID(uuid); - } - } - changeTENormalMap(te,image); - return retval; + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setNormalID(uuid); + } + } + changeTENormalMap(te,image); + return retval; } S32 LLViewerObject::setTESpecularMapCore(const U8 te, LLViewerTexture *image) { - S32 retval = TEM_CHANGE_TEXTURE; - const LLUUID& uuid = image ? image->getID() : LLUUID::null; - if (uuid != getTE(te)->getID() || - uuid == LLUUID::null) - { - LLTextureEntry* tep = getTE(te); - LLMaterial* mat = NULL; - if (tep) - { - mat = tep->getMaterialParams(); - } - - if (mat) - { - mat->setSpecularID(uuid); - } - } - changeTESpecularMap(te, image); - return retval; + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setSpecularID(uuid); + } + } + changeTESpecularMap(te, image); + return retval; } //virtual -void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) +void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { - if(index < 0 || index >= getNumTEs()) - { - return ; - } - mTEImages[index] = new_image ; + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTEImages[index] = new_image ; } void LLViewerObject::changeTENormalMap(S32 index, LLViewerTexture* new_image) { - if(index < 0 || index >= getNumTEs()) - { - return ; - } - mTENormalMaps[index] = new_image ; - refreshMaterials(); + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTENormalMaps[index] = new_image ; + refreshMaterials(); } void LLViewerObject::changeTESpecularMap(S32 index, LLViewerTexture* new_image) { - if(index < 0 || index >= getNumTEs()) - { - return ; - } - mTESpecularMaps[index] = new_image ; - refreshMaterials(); + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTESpecularMaps[index] = new_image ; + refreshMaterials(); } S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { - // Invalid host == get from the agent's sim - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); - return setTETextureCore(te, image); + // Invalid host == get from the agent's sim + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); + return setTETextureCore(te, image); } S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) { - LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); - return setTENormalMapCore(te, image); + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); + return setTENormalMapCore(te, image); } S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) { - LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); - return setTESpecularMapCore(te, image); + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost()); + return setTESpecularMapCore(te, image); } S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color) { - return setTEColor(te, LLColor4(color)); + return setTEColor(te, LLColor4(color)); } S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (color != tep->getColor()) - { - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - dirtyMesh(); - } - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (color != tep->getColor()) + { + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. + dirtyMesh(); + } + } + return retval; } S32 LLViewerObject::setTEBumpmap(const U8 te, const U8 bump) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (bump != tep->getBumpmap()) - { - retval = LLPrimitive::setTEBumpmap(te, bump); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); - } - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (bump != tep->getBumpmap()) + { + retval = LLPrimitive::setTEBumpmap(te, bump); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + } + } + return retval; } S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (texgen != tep->getTexGen()) - { - retval = LLPrimitive::setTETexGen(te, texgen); - setChanged(TEXTURE); - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (texgen != tep->getTexGen()) + { + retval = LLPrimitive::setTETexGen(te, texgen); + setChanged(TEXTURE); + } + return retval; } S32 LLViewerObject::setTEMediaTexGen(const U8 te, const U8 media) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (media != tep->getMediaTexGen()) - { - retval = LLPrimitive::setTEMediaTexGen(te, media); - setChanged(TEXTURE); - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (media != tep->getMediaTexGen()) + { + retval = LLPrimitive::setTEMediaTexGen(te, media); + setChanged(TEXTURE); + } + return retval; } S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (shiny != tep->getShiny()) - { - retval = LLPrimitive::setTEShiny(te, shiny); - setChanged(TEXTURE); - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (shiny != tep->getShiny()) + { + retval = LLPrimitive::setTEShiny(te, shiny); + setChanged(TEXTURE); + } + return retval; } S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (fullbright != tep->getFullbright()) - { - retval = LLPrimitive::setTEFullbright(te, fullbright); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (fullbright != tep->getFullbright()) + { + retval = LLPrimitive::setTEFullbright(te, fullbright); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; } S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { - // this might need work for media type - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (media_flags != tep->getMediaFlags()) - { - retval = LLPrimitive::setTEMediaFlags(te, media_flags); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - gPipeline.markTextured(mDrawable); - } - } - return retval; + // this might need work for media type + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (media_flags != tep->getMediaFlags()) + { + retval = LLPrimitive::setTEMediaFlags(te, media_flags); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + gPipeline.markTextured(mDrawable); + } + } + return retval; } S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (glow != tep->getGlow()) - { - retval = LLPrimitive::setTEGlow(te, glow); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (glow != tep->getGlow()) + { + retval = LLPrimitive::setTEGlow(te, glow); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markTextured(mDrawable); + } + } + return retval; } S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS("Material") << "No texture entry for te " << (S32)te - << ", object " << mID - << ", material " << pMaterialID - << LL_ENDL; - } - //else if (pMaterialID != tep->getMaterialID()) - { - LL_DEBUGS("Material") << "Changing texture entry for te " << (S32)te - << ", object " << mID - << ", material " << pMaterialID - << LL_ENDL; - retval = LLPrimitive::setTEMaterialID(te, pMaterialID); - refreshMaterials(); - } - return retval; + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("Material") << "No texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + } + //else if (pMaterialID != tep->getMaterialID()) + { + LL_DEBUGS("Material") << "Changing texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + retval = LLPrimitive::setTEMaterialID(te, pMaterialID); + refreshMaterials(); + } + return retval; } S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - return 0; - } + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + return 0; + } - retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); - LL_DEBUGS("Material") << "Changing material params for te " << (S32)te - << ", object " << mID - << " (" << retval << ")" - << LL_ENDL; - setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); - setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); + retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); + LL_DEBUGS("Material") << "Changing material params for te " << (S32)te + << ", object " << mID + << " (" << retval << ")" + << LL_ENDL; + setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); + setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); - return retval; + return retval; } S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_mat) @@ -5666,287 +5666,287 @@ S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_ma void LLViewerObject::refreshMaterials() { - setChanged(TEXTURE); - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } } S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t) { - S32 retval = 0; - retval = LLPrimitive::setTEScale(te, s, t); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - return retval; + S32 retval = 0; + retval = LLPrimitive::setTEScale(te, s, t); + setChanged(TEXTURE); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } + return retval; } S32 LLViewerObject::setTEScaleS(const U8 te, const F32 s) { - S32 retval = LLPrimitive::setTEScaleS(te, s); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } + S32 retval = LLPrimitive::setTEScaleS(te, s); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } - return retval; + return retval; } S32 LLViewerObject::setTEScaleT(const U8 te, const F32 t) { - S32 retval = LLPrimitive::setTEScaleT(te, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } + S32 retval = LLPrimitive::setTEScaleT(te, t); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } - return retval; + return retval; } S32 LLViewerObject::setTEOffset(const U8 te, const F32 s, const F32 t) { - S32 retval = LLPrimitive::setTEOffset(te, s, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - return retval; + S32 retval = LLPrimitive::setTEOffset(te, s, t); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } + return retval; } S32 LLViewerObject::setTEOffsetS(const U8 te, const F32 s) { - S32 retval = LLPrimitive::setTEOffsetS(te, s); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } + S32 retval = LLPrimitive::setTEOffsetS(te, s); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } - return retval; + return retval; } S32 LLViewerObject::setTEOffsetT(const U8 te, const F32 t) { - S32 retval = LLPrimitive::setTEOffsetT(te, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } + S32 retval = LLPrimitive::setTEOffsetT(te, t); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } - return retval; + return retval; } S32 LLViewerObject::setTERotation(const U8 te, const F32 r) { - S32 retval = LLPrimitive::setTERotation(te, r); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + S32 retval = LLPrimitive::setTERotation(te, r); + if (mDrawable.notNull() && retval) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); shrinkWrap(); - } - return retval; + } + return retval; } LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const { -// llassert(mTEImages); +// llassert(mTEImages); - if (face < getNumTEs()) - { - LLViewerTexture* image = mTEImages[face]; - if (image) - { - return image; - } - else - { - return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); - } - } + if (face < getNumTEs()) + { + LLViewerTexture* image = mTEImages[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } - LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; - return NULL; + return NULL; } bool LLViewerObject::isImageAlphaBlended(const U8 te) const { - LLViewerTexture* image = getTEImage(te); - LLGLenum format = image ? image->getPrimaryFormat() : GL_RGB; - switch (format) - { - case GL_RGBA: - case GL_ALPHA: - { - return true; - } - break; + LLViewerTexture* image = getTEImage(te); + LLGLenum format = image ? image->getPrimaryFormat() : GL_RGB; + switch (format) + { + case GL_RGBA: + case GL_ALPHA: + { + return true; + } + break; - case GL_RGB: break; - default: - { - LL_WARNS() << "Unexpected tex format in LLViewerObject::isImageAlphaBlended...returning no alpha." << LL_ENDL; - } - break; - } + case GL_RGB: break; + default: + { + LL_WARNS() << "Unexpected tex format in LLViewerObject::isImageAlphaBlended...returning no alpha." << LL_ENDL; + } + break; + } - return false; + return false; } LLViewerTexture *LLViewerObject::getTENormalMap(const U8 face) const { - // llassert(mTEImages); - - if (face < getNumTEs()) - { - LLViewerTexture* image = mTENormalMaps[face]; - if (image) - { - return image; - } - else - { - return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); - } - } - - LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; - - return NULL; + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTENormalMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + + return NULL; } LLViewerTexture *LLViewerObject::getTESpecularMap(const U8 face) const { - // llassert(mTEImages); - - if (face < getNumTEs()) - { - LLViewerTexture* image = mTESpecularMaps[face]; - if (image) - { - return image; - } - else - { - return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); - } - } - - LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; - - return NULL; + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTESpecularMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + + return NULL; } void LLViewerObject::fitFaceTexture(const U8 face) { - LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL; + LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL; } LLBBox LLViewerObject::getBoundingBoxAgent() const { - LLVector3 position_agent; - LLQuaternion rot; - LLViewerObject* avatar_parent = NULL; - LLViewerObject* root_edit = (LLViewerObject*)getRootEdit(); - if (root_edit) - { - avatar_parent = (LLViewerObject*)root_edit->getParent(); - } - - if (avatar_parent && avatar_parent->isAvatar() && - root_edit && root_edit->mDrawable.notNull() && root_edit->mDrawable->getXform()->getParent()) - { - LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent(); - position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); - rot = getRotationEdit() * parent_xform->getWorldRotation(); - } - else - { - position_agent = getPositionAgent(); - rot = getRotationRegion(); - } - - return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f ); + LLVector3 position_agent; + LLQuaternion rot; + LLViewerObject* avatar_parent = NULL; + LLViewerObject* root_edit = (LLViewerObject*)getRootEdit(); + if (root_edit) + { + avatar_parent = (LLViewerObject*)root_edit->getParent(); + } + + if (avatar_parent && avatar_parent->isAvatar() && + root_edit && root_edit->mDrawable.notNull() && root_edit->mDrawable->getXform()->getParent()) + { + LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent(); + position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); + rot = getRotationEdit() * parent_xform->getWorldRotation(); + } + else + { + position_agent = getPositionAgent(); + rot = getRotationRegion(); + } + + return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f ); } U32 LLViewerObject::getNumVertices() const { - U32 num_vertices = 0; - if (mDrawable.notNull()) - { - S32 i, num_faces; - num_faces = mDrawable->getNumFaces(); - for (i = 0; i < num_faces; i++) - { - LLFace * facep = mDrawable->getFace(i); - if (facep) - { - num_vertices += facep->getGeomCount(); - } - } - } - return num_vertices; + U32 num_vertices = 0; + if (mDrawable.notNull()) + { + S32 i, num_faces; + num_faces = mDrawable->getNumFaces(); + for (i = 0; i < num_faces; i++) + { + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_vertices += facep->getGeomCount(); + } + } + } + return num_vertices; } U32 LLViewerObject::getNumIndices() const { - U32 num_indices = 0; - if (mDrawable.notNull()) - { - S32 i, num_faces; - num_faces = mDrawable->getNumFaces(); - for (i = 0; i < num_faces; i++) - { - LLFace * facep = mDrawable->getFace(i); - if (facep) - { - num_indices += facep->getIndicesCount(); - } - } - } - return num_indices; + U32 num_indices = 0; + if (mDrawable.notNull()) + { + S32 i, num_faces; + num_faces = mDrawable->getNumFaces(); + for (i = 0; i < num_faces; i++) + { + LLFace * facep = mDrawable->getFace(i); + if (facep) + { + num_indices += facep->getIndicesCount(); + } + } + } + return num_indices; } // Find the number of instances of this object's inventory that are of the given type S32 LLViewerObject::countInventoryContents(LLAssetType::EType type) { - S32 count = 0; - if( mInventory ) - { - LLInventoryObject::object_list_t::const_iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::const_iterator end = mInventory->end(); - for( ; it != end ; ++it ) - { - if( (*it)->getType() == type ) - { - ++count; - } - } - } - return count; + S32 count = 0; + if( mInventory ) + { + LLInventoryObject::object_list_t::const_iterator it = mInventory->begin(); + LLInventoryObject::object_list_t::const_iterator end = mInventory->end(); + for( ; it != end ; ++it ) + { + if( (*it)->getType() == type ) + { + ++count; + } + } + } + return count; } void LLViewerObject::setDebugText(const std::string &utf8text, const LLColor4& color) { - if (utf8text.empty() && !mText) - { - return; - } + if (utf8text.empty() && !mText) + { + return; + } - if (!mText) - { - initHudText(); - } - mText->setColor(color); - mText->setString(utf8text); - mText->setZCompare(FALSE); - mText->setDoFade(FALSE); - updateText(); + if (!mText) + { + initHudText(); + } + mText->setColor(color); + mText->setString(utf8text); + mText->setZCompare(FALSE); + mText->setDoFade(FALSE); + updateText(); } void LLViewerObject::appendDebugText(const std::string &utf8text) @@ -6005,98 +6005,98 @@ void LLViewerObject::restoreHudText() void LLViewerObject::setIcon(LLViewerTexture* icon_image) { - if (!mIcon) - { - mIcon = (LLHUDIcon *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_ICON); - mIcon->setSourceObject(this); - mIcon->setImage(icon_image); - // *TODO: make this user configurable - mIcon->setScale(0.03f); - } - else - { - mIcon->restartLifeTimer(); - } + if (!mIcon) + { + mIcon = (LLHUDIcon *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_ICON); + mIcon->setSourceObject(this); + mIcon->setImage(icon_image); + // *TODO: make this user configurable + mIcon->setScale(0.03f); + } + else + { + mIcon->restartLifeTimer(); + } } void LLViewerObject::clearIcon() { - if (mIcon) - { - mIcon = NULL; - } + if (mIcon) + { + mIcon = NULL; + } } -LLViewerObject* LLViewerObject::getSubParent() -{ - return (LLViewerObject*) getParent(); +LLViewerObject* LLViewerObject::getSubParent() +{ + return (LLViewerObject*) getParent(); } const LLViewerObject* LLViewerObject::getSubParent() const { - return (const LLViewerObject*) getParent(); + return (const LLViewerObject*) getParent(); } BOOL LLViewerObject::isOnMap() { - return mOnMap; + return mOnMap; } void LLViewerObject::updateText() { - if (!isDead()) - { - if (mText.notNull()) - { - LLVOAvatar* avatar = getAvatar(); - if (avatar) - { - mText->setHidden(avatar->isInMuteList()); - } - - LLVector3 up_offset(0,0,0); - up_offset.mV[2] = getScale().mV[VZ]*0.6f; - - if (mDrawable.notNull()) - { - mText->setPositionAgent(getRenderPosition() + up_offset); - } - else - { - mText->setPositionAgent(getPositionAgent() + up_offset); - } - } - } + if (!isDead()) + { + if (mText.notNull()) + { + LLVOAvatar* avatar = getAvatar(); + if (avatar) + { + mText->setHidden(avatar->isInMuteList()); + } + + LLVector3 up_offset(0,0,0); + up_offset.mV[2] = getScale().mV[VZ]*0.6f; + + if (mDrawable.notNull()) + { + mText->setPositionAgent(getRenderPosition() + up_offset); + } + else + { + mText->setPositionAgent(getPositionAgent() + up_offset); + } + } + } } bool LLViewerObject::isOwnerInMuteList(LLUUID id) { - LLUUID owner_id = id.isNull() ? mOwnerID : id; - if (isAvatar() || owner_id.isNull()) - { - return false; - } - bool muted = false; - F64 now = LLFrameTimer::getTotalSeconds(); - if (now < mCachedMuteListUpdateTime) - { - muted = mCachedOwnerInMuteList; - } - else - { - muted = LLMuteList::getInstance()->isMuted(owner_id); - - const F64 SECONDS_BETWEEN_MUTE_UPDATES = 1; - mCachedMuteListUpdateTime = now + SECONDS_BETWEEN_MUTE_UPDATES; - mCachedOwnerInMuteList = muted; - } - return muted; + LLUUID owner_id = id.isNull() ? mOwnerID : id; + if (isAvatar() || owner_id.isNull()) + { + return false; + } + bool muted = false; + F64 now = LLFrameTimer::getTotalSeconds(); + if (now < mCachedMuteListUpdateTime) + { + muted = mCachedOwnerInMuteList; + } + else + { + muted = LLMuteList::getInstance()->isMuted(owner_id); + + const F64 SECONDS_BETWEEN_MUTE_UPDATES = 1; + mCachedMuteListUpdateTime = now + SECONDS_BETWEEN_MUTE_UPDATES; + mCachedOwnerInMuteList = muted; + } + return muted; } LLVOAvatar* LLViewerObject::asAvatar() { - return NULL; + return NULL; } // If this object is directly or indirectly parented by an avatar, @@ -6108,348 +6108,348 @@ LLVOAvatar* LLViewerObject::asAvatar() // attached. LLVOAvatar* LLViewerObject::getAvatarAncestor() { - LLViewerObject *pobj = (LLViewerObject*) getParent(); - while (pobj) - { - LLVOAvatar *av = pobj->asAvatar(); - if (av) - { - return av; - } - pobj = (LLViewerObject*) pobj->getParent(); - } - return NULL; + LLViewerObject *pobj = (LLViewerObject*) getParent(); + while (pobj) + { + LLVOAvatar *av = pobj->asAvatar(); + if (av) + { + return av; + } + pobj = (LLViewerObject*) pobj->getParent(); + } + return NULL; } BOOL LLViewerObject::isParticleSource() const { - return !mPartSourcep.isNull() && !mPartSourcep->isDead(); + return !mPartSourcep.isNull() && !mPartSourcep->isDead(); } void LLViewerObject::setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id) { - if (mPartSourcep) - { - deleteParticleSource(); - } - - LLPointer pss = LLViewerPartSourceScript::createPSS(this, particle_parameters); - mPartSourcep = pss; - - if (mPartSourcep) - { - mPartSourcep->setOwnerUUID(owner_id); - - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.tga"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } - LLViewerPartSim::getInstance()->addPartSource(pss); + if (mPartSourcep) + { + deleteParticleSource(); + } + + LLPointer pss = LLViewerPartSourceScript::createPSS(this, particle_parameters); + mPartSourcep = pss; + + if (mPartSourcep) + { + mPartSourcep->setOwnerUUID(owner_id); + + if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) + { + LLViewerTexture* image; + if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) + { + image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.tga"); + } + else + { + image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); + } + mPartSourcep->setImage(image); + } + } + LLViewerPartSim::getInstance()->addPartSource(pss); } void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& owner_id) { - if (!mPartSourcep.isNull() && mPartSourcep->isDead()) - { - mPartSourcep = NULL; - } - if (mPartSourcep) - { - // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, block_num)) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - } - else - { - LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num); - //If the owner is muted, don't create the system - if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; - - // We need to be able to deal with a particle source that hasn't changed, but still got an update! - if (pss) - { -// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; - pss->setOwnerUUID(owner_id); - mPartSourcep = pss; - LLViewerPartSim::getInstance()->addPartSource(pss); - } - } - if (mPartSourcep) - { - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } + if (!mPartSourcep.isNull() && mPartSourcep->isDead()) + { + mPartSourcep = NULL; + } + if (mPartSourcep) + { + // If we've got one already, just update the existing source (or remove it) + if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, block_num)) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } + } + else + { + LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num); + //If the owner is muted, don't create the system + if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; + + // We need to be able to deal with a particle source that hasn't changed, but still got an update! + if (pss) + { +// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; + pss->setOwnerUUID(owner_id); + mPartSourcep = pss; + LLViewerPartSim::getInstance()->addPartSource(pss); + } + } + if (mPartSourcep) + { + if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) + { + LLViewerTexture* image; + if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) + { + image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); + } + else + { + image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); + } + mPartSourcep->setImage(image); + } + } } void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy) { - if (!mPartSourcep.isNull() && mPartSourcep->isDead()) - { - mPartSourcep = NULL; - } - if (mPartSourcep) - { - // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy)) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - } - else - { - LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy); - //If the owner is muted, don't create the system - if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; - // We need to be able to deal with a particle source that hasn't changed, but still got an update! - if (pss) - { -// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; - pss->setOwnerUUID(owner_id); - mPartSourcep = pss; - LLViewerPartSim::getInstance()->addPartSource(pss); - } - } - if (mPartSourcep) - { - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } + if (!mPartSourcep.isNull() && mPartSourcep->isDead()) + { + mPartSourcep = NULL; + } + if (mPartSourcep) + { + // If we've got one already, just update the existing source (or remove it) + if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy)) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } + } + else + { + LLPointer pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy); + //If the owner is muted, don't create the system + if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; + // We need to be able to deal with a particle source that hasn't changed, but still got an update! + if (pss) + { +// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; + pss->setOwnerUUID(owner_id); + mPartSourcep = pss; + LLViewerPartSim::getInstance()->addPartSource(pss); + } + } + if (mPartSourcep) + { + if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) + { + LLViewerTexture* image; + if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) + { + image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); + } + else + { + image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); + } + mPartSourcep->setImage(image); + } + } } void LLViewerObject::deleteParticleSource() { - if (mPartSourcep.notNull()) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } + if (mPartSourcep.notNull()) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } } // virtual void LLViewerObject::updateDrawable(BOOL force_damped) { - if (!isChanged(MOVED)) - { //most common case, having an empty if case here makes for better branch prediction - } - else if (mDrawable.notNull() && - !mDrawable->isState(LLDrawable::ON_MOVE_LIST)) - { - BOOL damped_motion = - !isChanged(SHIFTED) && // not shifted between regions this frame and... - ( force_damped || // ...forced into damped motion by application logic or... - ( !isSelected() && // ...not selected and... - ( mDrawable->isRoot() || // ... is root or ... - (getParent() && !((LLViewerObject*)getParent())->isSelected())// ... parent is not selected and ... - ) && - getPCode() == LL_PCODE_VOLUME && // ...is a volume object and... - getVelocity().isExactlyZero() && // ...is not moving physically and... - mDrawable->getGeneration() != -1 // ...was not created this frame. - ) - ); - gPipeline.markMoved(mDrawable, damped_motion); - } - clearChanged(SHIFTED); + if (!isChanged(MOVED)) + { //most common case, having an empty if case here makes for better branch prediction + } + else if (mDrawable.notNull() && + !mDrawable->isState(LLDrawable::ON_MOVE_LIST)) + { + BOOL damped_motion = + !isChanged(SHIFTED) && // not shifted between regions this frame and... + ( force_damped || // ...forced into damped motion by application logic or... + ( !isSelected() && // ...not selected and... + ( mDrawable->isRoot() || // ... is root or ... + (getParent() && !((LLViewerObject*)getParent())->isSelected())// ... parent is not selected and ... + ) && + getPCode() == LL_PCODE_VOLUME && // ...is a volume object and... + getVelocity().isExactlyZero() && // ...is not moving physically and... + mDrawable->getGeneration() != -1 // ...was not created this frame. + ) + ); + gPipeline.markMoved(mDrawable, damped_motion); + } + clearChanged(SHIFTED); } // virtual, overridden by LLVOVolume F32 LLViewerObject::getVObjRadius() const { - return mDrawable.notNull() ? mDrawable->getRadius() : 0.f; + return mDrawable.notNull() ? mDrawable->getRadius() : 0.f; } void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags) { - if (!gAudiop) - { - return; - } - - if (audio_uuid.isNull()) - { - if (!mAudioSourcep) - { - return; - } - if (mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads()) - { - // We don't clear the sound if it's a loop, it'll go away on its own. - // At least, this appears to be how the scripts work. - // The attached sound ID is set to NULL to avoid it playing back when the - // object rezzes in on non-looping sounds. - //LL_INFOS() << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << LL_ENDL; - gAudiop->cleanupAudioSource(mAudioSourcep); - mAudioSourcep = NULL; - } - else if (flags & LL_SOUND_FLAG_STOP) - { - // Just shut off the sound - mAudioSourcep->stop(); - } - return; - } - if (flags & LL_SOUND_FLAG_LOOP - && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData() - && mAudioSourcep->getCurrentData()->getID() == audio_uuid) - { - //LL_INFOS() << "Already playing this sound on a loop, ignoring" << LL_ENDL; - return; - } - - // don't clean up before previous sound is done. Solves: SL-33486 - if ( mAudioSourcep && mAudioSourcep->isDone() ) - { - gAudiop->cleanupAudioSource(mAudioSourcep); - mAudioSourcep = NULL; - } - - if (mAudioSourcep && mAudioSourcep->isMuted() && - mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) - { - //LL_INFOS() << "Already having this sound as muted sound, ignoring" << LL_ENDL; - return; - } - - getAudioSource(owner_id); - - if (mAudioSourcep) - { - BOOL queue = flags & LL_SOUND_FLAG_QUEUE; - mAudioGain = gain; - mAudioSourcep->setGain(gain); - mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP); - mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER); - mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE); - mAudioSourcep->setQueueSounds(queue); - if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG - { - mAudioSourcep->stop(); - } - - // Play this sound if region maturity permits - if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) ) - { - //LL_INFOS() << "Playing attached sound " << audio_uuid << LL_ENDL; - // recheck cutoff radius in case this update was an object-update with new value - mAudioSourcep->checkCutOffRadius(); - mAudioSourcep->play(audio_uuid); - } - } + if (!gAudiop) + { + return; + } + + if (audio_uuid.isNull()) + { + if (!mAudioSourcep) + { + return; + } + if (mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads()) + { + // We don't clear the sound if it's a loop, it'll go away on its own. + // At least, this appears to be how the scripts work. + // The attached sound ID is set to NULL to avoid it playing back when the + // object rezzes in on non-looping sounds. + //LL_INFOS() << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << LL_ENDL; + gAudiop->cleanupAudioSource(mAudioSourcep); + mAudioSourcep = NULL; + } + else if (flags & LL_SOUND_FLAG_STOP) + { + // Just shut off the sound + mAudioSourcep->stop(); + } + return; + } + if (flags & LL_SOUND_FLAG_LOOP + && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData() + && mAudioSourcep->getCurrentData()->getID() == audio_uuid) + { + //LL_INFOS() << "Already playing this sound on a loop, ignoring" << LL_ENDL; + return; + } + + // don't clean up before previous sound is done. Solves: SL-33486 + if ( mAudioSourcep && mAudioSourcep->isDone() ) + { + gAudiop->cleanupAudioSource(mAudioSourcep); + mAudioSourcep = NULL; + } + + if (mAudioSourcep && mAudioSourcep->isMuted() && + mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) + { + //LL_INFOS() << "Already having this sound as muted sound, ignoring" << LL_ENDL; + return; + } + + getAudioSource(owner_id); + + if (mAudioSourcep) + { + BOOL queue = flags & LL_SOUND_FLAG_QUEUE; + mAudioGain = gain; + mAudioSourcep->setGain(gain); + mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP); + mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER); + mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE); + mAudioSourcep->setQueueSounds(queue); + if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG + { + mAudioSourcep->stop(); + } + + // Play this sound if region maturity permits + if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) ) + { + //LL_INFOS() << "Playing attached sound " << audio_uuid << LL_ENDL; + // recheck cutoff radius in case this update was an object-update with new value + mAudioSourcep->checkCutOffRadius(); + mAudioSourcep->play(audio_uuid); + } + } } LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id) { - if (!mAudioSourcep) - { - // Arbitrary low gain for a sound that's not playing. - // This is used for sound preloads, for example. - LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this); + if (!mAudioSourcep) + { + // Arbitrary low gain for a sound that's not playing. + // This is used for sound preloads, for example. + LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this); - mAudioSourcep = asvop; - if(gAudiop) - { - gAudiop->addAudioSource(asvop); - } - } + mAudioSourcep = asvop; + if(gAudiop) + { + gAudiop->addAudioSource(asvop); + } + } - return mAudioSourcep; + return mAudioSourcep; } void LLViewerObject::adjustAudioGain(const F32 gain) { - if (mAudioSourcep) - { - mAudioGain = gain; - mAudioSourcep->setGain(mAudioGain); - } + if (mAudioSourcep) + { + mAudioGain = gain; + mAudioSourcep->setGain(mAudioGain); + } } //---------------------------------------------------------------------------- bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) { - if (LLNetworkData::PARAMS_MESH == param_type) - { - param_type = LLNetworkData::PARAMS_SCULPT; - } - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param) - { - param->data->unpack(*dp); - param->in_use = TRUE; - parameterChanged(param_type, param->data, TRUE, false); - return true; - } - else - { - return false; - } + if (LLNetworkData::PARAMS_MESH == param_type) + { + param_type = LLNetworkData::PARAMS_SCULPT; + } + ExtraParameter* param = getExtraParameterEntryCreate(param_type); + if (param) + { + param->data->unpack(*dp); + param->in_use = TRUE; + parameterChanged(param_type, param->data, TRUE, false); + return true; + } + else + { + return false; + } } LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type) { - LLNetworkData* new_block = NULL; - switch (param_type) - { - case LLNetworkData::PARAMS_FLEXIBLE: - { - new_block = new LLFlexibleObjectData(); - break; - } - case LLNetworkData::PARAMS_LIGHT: - { - new_block = new LLLightParams(); - break; - } - case LLNetworkData::PARAMS_SCULPT: - { - new_block = new LLSculptParams(); - break; - } - case LLNetworkData::PARAMS_LIGHT_IMAGE: - { - new_block = new LLLightImageParams(); - break; - } + LLNetworkData* new_block = NULL; + switch (param_type) + { + case LLNetworkData::PARAMS_FLEXIBLE: + { + new_block = new LLFlexibleObjectData(); + break; + } + case LLNetworkData::PARAMS_LIGHT: + { + new_block = new LLLightParams(); + break; + } + case LLNetworkData::PARAMS_SCULPT: + { + new_block = new LLSculptParams(); + break; + } + case LLNetworkData::PARAMS_LIGHT_IMAGE: + { + new_block = new LLLightImageParams(); + break; + } case LLNetworkData::PARAMS_EXTENDED_MESH: { - new_block = new LLExtendedMeshParams(); - break; + new_block = new LLExtendedMeshParams(); + break; } case LLNetworkData::PARAMS_RENDER_MATERIAL: { @@ -6461,90 +6461,90 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para new_block = new LLReflectionProbeParams(); break; } - default: - { - LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL; - break; - } - }; - - if (new_block) - { - ExtraParameter* new_entry = new ExtraParameter; - new_entry->data = new_block; - new_entry->in_use = false; // not in use yet + default: + { + LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL; + break; + } + }; + + if (new_block) + { + ExtraParameter* new_entry = new ExtraParameter; + new_entry->data = new_block; + new_entry->in_use = false; // not in use yet llassert(mExtraParameterList[param_type] == nullptr); // leak -- redundantly allocated parameter entry - mExtraParameterList[param_type] = new_entry; - return new_entry; - } - return NULL; + mExtraParameterList[param_type] = new_entry; + return new_entry; + } + return NULL; } LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_VIEWER; - std::unordered_map::const_iterator itor = mExtraParameterList.find(param_type); - if (itor != mExtraParameterList.end()) - { - return itor->second; - } - return NULL; + std::unordered_map::const_iterator itor = mExtraParameterList.find(param_type); + if (itor != mExtraParameterList.end()) + { + return itor->second; + } + return NULL; } LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type) { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (!param) - { - param = createNewParameterEntry(param_type); - } - return param; + ExtraParameter* param = getExtraParameterEntry(param_type); + if (!param) + { + param = createNewParameterEntry(param_type); + } + return param; } LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->data; - } - else - { - return NULL; - } + ExtraParameter* param = getExtraParameterEntry(param_type); + if (param) + { + return param->data; + } + else + { + return NULL; + } } BOOL LLViewerObject::getParameterEntryInUse(U16 param_type) const { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->in_use; - } - else - { - return FALSE; - } + ExtraParameter* param = getExtraParameterEntry(param_type); + if (param) + { + return param->in_use; + } + else + { + return FALSE; + } } bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin) { - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param) - { - if (param->in_use && new_value == *(param->data)) - { - return false; - } - param->in_use = true; - param->data->copy(new_value); - parameterChanged(param_type, param->data, TRUE, local_origin); - return true; - } - else - { - return false; - } + ExtraParameter* param = getExtraParameterEntryCreate(param_type); + if (param) + { + if (param->in_use && new_value == *(param->data)) + { + return false; + } + param->in_use = true; + param->data->copy(new_value); + parameterChanged(param_type, param->data, TRUE, local_origin); + return true; + } + else + { + return false; + } } // Assumed to be called locally @@ -6552,65 +6552,65 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ // Should always return true. bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin) { - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param && param->in_use != in_use) - { - param->in_use = in_use; - parameterChanged(param_type, param->data, in_use, local_origin); - return true; - } - return false; + ExtraParameter* param = getExtraParameterEntryCreate(param_type); + if (param && param->in_use != in_use) + { + param->in_use = in_use; + parameterChanged(param_type, param->data, in_use, local_origin); + return true; + } + return false; } void LLViewerObject::parameterChanged(U16 param_type, bool local_origin) { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - parameterChanged(param_type, param->data, param->in_use, local_origin); - } + ExtraParameter* param = getExtraParameterEntry(param_type); + if (param) + { + parameterChanged(param_type, param->data, param->in_use, local_origin); + } } void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) { - if (local_origin) - { + if (local_origin) + { // *NOTE: Do not send the render material ID in this way as it will get // out-of-sync with other sent client data. // See LLViewerObject::setRenderMaterialID and LLGLTFMaterialList llassert(param_type != LLNetworkData::PARAMS_RENDER_MATERIAL); - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - - // Change happened on the viewer. Send the change up - U8 tmp[MAX_OBJECT_PARAMS_SIZE]; - LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); - if (data->pack(dpb)) - { - U32 datasize = (U32)dpb.getCurrentSize(); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ObjectExtraParams); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - - msg->addU16Fast(_PREHASH_ParamType, param_type); - msg->addBOOLFast(_PREHASH_ParamInUse, in_use); - - msg->addU32Fast(_PREHASH_ParamSize, datasize); - msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); - - msg->sendReliable( regionp->getHost() ); - } - else - { - LL_WARNS() << "Failed to send object extra parameters: " << param_type << LL_ENDL; - } - } + LLViewerRegion* regionp = getRegion(); + if(!regionp) return; + + // Change happened on the viewer. Send the change up + U8 tmp[MAX_OBJECT_PARAMS_SIZE]; + LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); + if (data->pack(dpb)) + { + U32 datasize = (U32)dpb.getCurrentSize(); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ObjectExtraParams); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); + + msg->addU16Fast(_PREHASH_ParamType, param_type); + msg->addBOOLFast(_PREHASH_ParamInUse, in_use); + + msg->addU32Fast(_PREHASH_ParamSize, datasize); + msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); + + msg->sendReliable( regionp->getHost() ); + } + else + { + LL_WARNS() << "Failed to send object extra parameters: " << param_type << LL_ENDL; + } + } else { if (param_type == LLNetworkData::PARAMS_RENDER_MATERIAL) @@ -6623,256 +6623,256 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL void LLViewerObject::setDrawableState(U32 state, BOOL recursive) { - if (mDrawable) - { - mDrawable->setState(state); - } - if (recursive) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->setDrawableState(state, recursive); - } - } + if (mDrawable) + { + mDrawable->setState(state); + } + if (recursive) + { + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + child->setDrawableState(state, recursive); + } + } } void LLViewerObject::clearDrawableState(U32 state, BOOL recursive) { - if (mDrawable) - { - mDrawable->clearState(state); - } - if (recursive) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->clearDrawableState(state, recursive); - } - } + if (mDrawable) + { + mDrawable->clearState(state); + } + if (recursive) + { + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + child->clearDrawableState(state, recursive); + } + } } BOOL LLViewerObject::isDrawableState(U32 state, BOOL recursive) const { - BOOL matches = FALSE; - if (mDrawable) - { - matches = mDrawable->isState(state); - } - if (recursive) - { - for (child_list_t::const_iterator iter = mChildList.begin(); - (iter != mChildList.end()) && matches; iter++) - { - LLViewerObject* child = *iter; - matches &= child->isDrawableState(state, recursive); - } - } + BOOL matches = FALSE; + if (mDrawable) + { + matches = mDrawable->isState(state); + } + if (recursive) + { + for (child_list_t::const_iterator iter = mChildList.begin(); + (iter != mChildList.end()) && matches; iter++) + { + LLViewerObject* child = *iter; + matches &= child->isDrawableState(state, recursive); + } + } - return matches; + return matches; } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// RN: these functions assume a 2-level hierarchy +// RN: these functions assume a 2-level hierarchy //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Owned by anyone? BOOL LLViewerObject::permAnyOwner() const -{ - if (isRootEdit()) - { - return flagObjectAnyOwner(); - } - else - { - return ((LLViewerObject*)getParent())->permAnyOwner(); - } -} +{ + if (isRootEdit()) + { + return flagObjectAnyOwner(); + } + else + { + return ((LLViewerObject*)getParent())->permAnyOwner(); + } +} // Owned by this viewer? BOOL LLViewerObject::permYouOwner() const -{ - if (isRootEdit()) - { +{ + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectYouOwner(); + return flagObjectYouOwner(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permYouOwner(); - } + } + else + { + return ((LLViewerObject*)getParent())->permYouOwner(); + } } // Owned by a group? -BOOL LLViewerObject::permGroupOwner() const -{ - if (isRootEdit()) - { - return flagObjectGroupOwned(); - } - else - { - return ((LLViewerObject*)getParent())->permGroupOwner(); - } +BOOL LLViewerObject::permGroupOwner() const +{ + if (isRootEdit()) + { + return flagObjectGroupOwned(); + } + else + { + return ((LLViewerObject*)getParent())->permGroupOwner(); + } } // Can the owner edit BOOL LLViewerObject::permOwnerModify() const -{ - if (isRootEdit()) - { +{ + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectOwnerModify(); + return flagObjectOwnerModify(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permOwnerModify(); - } + } + else + { + return ((LLViewerObject*)getParent())->permOwnerModify(); + } } // Can edit BOOL LLViewerObject::permModify() const -{ - if (isRootEdit()) - { +{ + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectModify(); + return flagObjectModify(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permModify(); - } + } + else + { + return ((LLViewerObject*)getParent())->permModify(); + } } // Can copy BOOL LLViewerObject::permCopy() const -{ - if (isRootEdit()) - { +{ + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectCopy(); + return flagObjectCopy(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permCopy(); - } + } + else + { + return ((LLViewerObject*)getParent())->permCopy(); + } } // Can move BOOL LLViewerObject::permMove() const { - if (isRootEdit()) - { + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectMove(); + return flagObjectMove(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permMove(); - } + } + else + { + return ((LLViewerObject*)getParent())->permMove(); + } } // Can be transferred BOOL LLViewerObject::permTransfer() const -{ - if (isRootEdit()) - { +{ + if (isRootEdit()) + { #ifdef HACKED_GODLIKE_VIEWER - return TRUE; + return TRUE; #else # ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() + if (!LLGridManager::getInstance()->isInProductionGrid() && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } + { + return TRUE; + } # endif - return flagObjectTransfer(); + return flagObjectTransfer(); #endif - } - else - { - return ((LLViewerObject*)getParent())->permTransfer(); - } + } + else + { + return ((LLViewerObject*)getParent())->permTransfer(); + } } // Can only open objects that you own, or that someone has // given you modify rights to. JC BOOL LLViewerObject::allowOpen() const { - return !flagInventoryEmpty() && (permYouOwner() || permModify()); + return !flagInventoryEmpty() && (permYouOwner() || permModify()); } LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo() { - if (mListener) - { - mListener->clearVOInventoryListener(); - } + if (mListener) + { + mListener->clearVOInventoryListener(); + } } void LLViewerObject::updateVolume(const LLVolumeParams& volume_params) { - if (setVolume(volume_params, 1)) // *FIX: magic number, ack! - { - // Transmit the update to the simulator - sendShapeUpdate(); - markForUpdate(); - } + if (setVolume(volume_params, 1)) // *FIX: magic number, ack! + { + // Transmit the update to the simulator + sendShapeUpdate(); + markForUpdate(); + } } void LLViewerObject::recursiveMarkForUpdate() @@ -6888,259 +6888,259 @@ void LLViewerObject::recursiveMarkForUpdate() void LLViewerObject::markForUpdate() { - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); - } + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + } } bool LLViewerObject::isPermanentEnforced() const { - return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); + return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); } bool LLViewerObject::getIncludeInSearch() const { - return flagIncludeInSearch(); + return flagIncludeInSearch(); } void LLViewerObject::setIncludeInSearch(bool include_in_search) { - setFlags(FLAGS_INCLUDE_IN_SEARCH, include_in_search); + setFlags(FLAGS_INCLUDE_IN_SEARCH, include_in_search); } void LLViewerObject::setRegion(LLViewerRegion *regionp) { - if (!regionp) - { - LL_WARNS() << "viewer object set region to NULL" << LL_ENDL; - } - if(regionp != mRegionp) - { - if(mRegionp) - { - mRegionp->removeFromCreatedList(getLocalID()); - } - if(regionp) - { - regionp->addToCreatedList(getLocalID()); - } - } - - mLatestRecvPacketID = 0; - mRegionp = regionp; - - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - LLViewerObject* child = *i; - child->setRegion(regionp); - } + if (!regionp) + { + LL_WARNS() << "viewer object set region to NULL" << LL_ENDL; + } + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } + } + + mLatestRecvPacketID = 0; + mRegionp = regionp; + + for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) + { + LLViewerObject* child = *i; + child->setRegion(regionp); + } if (mControlAvatar) { mControlAvatar->setRegion(regionp); } - setChanged(MOVED | SILHOUETTE); - updateDrawable(FALSE); + setChanged(MOVED | SILHOUETTE); + updateDrawable(FALSE); } // virtual -void LLViewerObject::updateRegion(LLViewerRegion *regionp) +void LLViewerObject::updateRegion(LLViewerRegion *regionp) { -// if (regionp) -// { -// F64 now = LLFrameTimer::getElapsedSeconds(); -// LL_INFOS() << "Updating to region " << regionp->getName() -// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) -// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) -// << LL_ENDL; -// } +// if (regionp) +// { +// F64 now = LLFrameTimer::getElapsedSeconds(); +// LL_INFOS() << "Updating to region " << regionp->getName() +// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) +// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) +// << LL_ENDL; +// } } bool LLViewerObject::specialHoverCursor() const { - return flagUsePhysics() - || flagHandleTouch() - || (mClickAction != 0); + return flagUsePhysics() + || flagHandleTouch() + || (mClickAction != 0); } void LLViewerObject::updateFlags(BOOL physics_changed) { - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessage("ObjectFlagUpdate"); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() ); - gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, flagUsePhysics() ); - gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() ); - gMessageSystem->addBOOL("IsPhantom", flagPhantom() ); - - // stinson 02/28/2012 : This CastsShadows BOOL is no longer used in either the viewer or the simulator - // The simulator code does not even unpack this value when the message is received. - // This could be potentially hijacked in the future for another use should the urgent need arise. - gMessageSystem->addBOOL("CastsShadows", FALSE ); - - if (physics_changed) - { - gMessageSystem->nextBlock("ExtraPhysics"); - gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() ); - gMessageSystem->addF32("Density", getPhysicsDensity() ); - gMessageSystem->addF32("Friction", getPhysicsFriction() ); - gMessageSystem->addF32("Restitution", getPhysicsRestitution() ); - gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() ); - } - gMessageSystem->sendReliable( regionp->getHost() ); + LLViewerRegion* regionp = getRegion(); + if(!regionp) return; + gMessageSystem->newMessage("ObjectFlagUpdate"); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() ); + gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, flagUsePhysics() ); + gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() ); + gMessageSystem->addBOOL("IsPhantom", flagPhantom() ); + + // stinson 02/28/2012 : This CastsShadows BOOL is no longer used in either the viewer or the simulator + // The simulator code does not even unpack this value when the message is received. + // This could be potentially hijacked in the future for another use should the urgent need arise. + gMessageSystem->addBOOL("CastsShadows", FALSE ); + + if (physics_changed) + { + gMessageSystem->nextBlock("ExtraPhysics"); + gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() ); + gMessageSystem->addF32("Density", getPhysicsDensity() ); + gMessageSystem->addF32("Friction", getPhysicsFriction() ); + gMessageSystem->addF32("Restitution", getPhysicsRestitution() ); + gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() ); + } + gMessageSystem->sendReliable( regionp->getHost() ); } BOOL LLViewerObject::setFlags(U32 flags, BOOL state) { - BOOL setit = setFlagsWithoutUpdate(flags, state); + BOOL setit = setFlagsWithoutUpdate(flags, state); - // BUG: Sometimes viewer physics and simulator physics get - // out of sync. To fix this, always send update to simulator. -// if (setit) - { - updateFlags(); - } - return setit; + // BUG: Sometimes viewer physics and simulator physics get + // out of sync. To fix this, always send update to simulator. +// if (setit) + { + updateFlags(); + } + return setit; } BOOL LLViewerObject::setFlagsWithoutUpdate(U32 flags, BOOL state) { - BOOL setit = FALSE; - if (state) - { - if ((mFlags & flags) != flags) - { - mFlags |= flags; - setit = TRUE; - } - } - else - { - if ((mFlags & flags) != 0) - { - mFlags &= ~flags; - setit = TRUE; - } - } - return setit; + BOOL setit = FALSE; + if (state) + { + if ((mFlags & flags) != flags) + { + mFlags |= flags; + setit = TRUE; + } + } + else + { + if ((mFlags & flags) != 0) + { + mFlags &= ~flags; + setit = TRUE; + } + } + return setit; } void LLViewerObject::setPhysicsShapeType(U8 type) { - mPhysicsShapeUnknown = false; - if (type != mPhysicsShapeType) - { - mPhysicsShapeType = type; - setObjectCostStale(); + mPhysicsShapeUnknown = false; + if (type != mPhysicsShapeType) + { + mPhysicsShapeType = type; + setObjectCostStale(); } } void LLViewerObject::setPhysicsGravity(F32 gravity) { - mPhysicsGravity = gravity; + mPhysicsGravity = gravity; } void LLViewerObject::setPhysicsFriction(F32 friction) { - mPhysicsFriction = friction; + mPhysicsFriction = friction; } void LLViewerObject::setPhysicsDensity(F32 density) { - mPhysicsDensity = density; + mPhysicsDensity = density; } void LLViewerObject::setPhysicsRestitution(F32 restitution) { - mPhysicsRestitution = restitution; + mPhysicsRestitution = restitution; } U8 LLViewerObject::getPhysicsShapeType() const -{ - if (mPhysicsShapeUnknown) - { - gObjectList.updatePhysicsFlags(this); - } +{ + if (mPhysicsShapeUnknown) + { + gObjectList.updatePhysicsFlags(this); + } - return mPhysicsShapeType; + return mPhysicsShapeType; } void LLViewerObject::applyAngularVelocity(F32 dt) { - //do target omega here - mRotTime += dt; - LLVector3 ang_vel = getAngularVelocity(); - F32 omega = ang_vel.magVecSquared(); - F32 angle = 0.0f; - LLQuaternion dQ; - if (omega > 0.00001f) - { - omega = sqrt(omega); - angle = omega * dt; - - ang_vel *= 1.f/omega; - - // calculate the delta increment based on the object's angular velocity - dQ.setQuat(angle, ang_vel); - - // accumulate the angular velocity rotations to re-apply in the case of an object update - mAngularVelocityRot *= dQ; - - // Just apply the delta increment to the current rotation - setRotation(getRotation()*dQ); - setChanged(MOVED | SILHOUETTE); - } + //do target omega here + mRotTime += dt; + LLVector3 ang_vel = getAngularVelocity(); + F32 omega = ang_vel.magVecSquared(); + F32 angle = 0.0f; + LLQuaternion dQ; + if (omega > 0.00001f) + { + omega = sqrt(omega); + angle = omega * dt; + + ang_vel *= 1.f/omega; + + // calculate the delta increment based on the object's angular velocity + dQ.setQuat(angle, ang_vel); + + // accumulate the angular velocity rotations to re-apply in the case of an object update + mAngularVelocityRot *= dQ; + + // Just apply the delta increment to the current rotation + setRotation(getRotation()*dQ); + setChanged(MOVED | SILHOUETTE); + } } void LLViewerObject::resetRotTime() { - mRotTime = 0.0f; + mRotTime = 0.0f; } void LLViewerObject::resetRot() { - resetRotTime(); + resetRotTime(); - // Reset the accumulated angular velocity rotation - mAngularVelocityRot.loadIdentity(); + // Reset the accumulated angular velocity rotation + mAngularVelocityRot.loadIdentity(); } U32 LLViewerObject::getPartitionType() const -{ - return LLViewerRegion::PARTITION_NONE; +{ + return LLViewerRegion::PARTITION_NONE; } void LLViewerObject::dirtySpatialGroup() const { - if (mDrawable) - { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->dirtyGeom(); - gPipeline.markRebuild(group); - } - } + if (mDrawable) + { + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + gPipeline.markRebuild(group); + } + } } void LLViewerObject::dirtyMesh() { - if (mDrawable) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); - } + if (mDrawable) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + } } F32 LLAlphaObject::getPartSize(S32 idx) { - return 0.f; + return 0.f; } void LLAlphaObject::getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst) @@ -7151,235 +7151,235 @@ void LLAlphaObject::getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender // virtual void LLStaticViewerObject::updateDrawable(BOOL force_damped) { - // Force an immediate rebuild on any update - if (mDrawable.notNull()) - { - mDrawable->updateXform(TRUE); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); - } - clearChanged(SHIFTED); + // Force an immediate rebuild on any update + if (mDrawable.notNull()) + { + mDrawable->updateXform(TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + } + clearChanged(SHIFTED); } void LLViewerObject::saveUnselectedChildrenPosition(std::vector& positions) { - if(mChildList.empty() || !positions.empty()) - { - return ; - } + if(mChildList.empty() || !positions.empty()) + { + return ; + } - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - positions.push_back(childp->getPositionEdit()); - } - } + for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* childp = *iter; + if (!childp->isSelected() && childp->mDrawable.notNull()) + { + positions.push_back(childp->getPositionEdit()); + } + } - return ; + return ; } void LLViewerObject::saveUnselectedChildrenRotation(std::vector& rotations) { - if(mChildList.empty()) - { - return ; - } + if(mChildList.empty()) + { + return ; + } - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - rotations.push_back(childp->getRotationEdit()); - } - } + for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* childp = *iter; + if (!childp->isSelected() && childp->mDrawable.notNull()) + { + rotations.push_back(childp->getRotationEdit()); + } + } - return ; + return ; } //counter-rotation -void LLViewerObject::resetChildrenRotationAndPosition(const std::vector& rotations, - const std::vector& positions) -{ - if(mChildList.empty()) - { - return ; - } - - S32 index = 0 ; - LLQuaternion inv_rotation = ~getRotationEdit() ; - LLVector3 offset = getPositionEdit() ; - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - childp->setRotation(rotations[index] * inv_rotation); - childp->setPosition((positions[index] - offset) * inv_rotation); - LLManip::rebuild(childp); - } - else //avatar - { - LLVector3 reset_pos = (positions[index] - offset) * inv_rotation ; - LLQuaternion reset_rot = rotations[index] * inv_rotation ; - - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); - ((LLVOAvatar*)childp)->mDrawable->mXform.setRotation(reset_rot) ; - - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE); - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setRotation(reset_rot, TRUE) ; - - LLManip::rebuild(childp); - } - index++; - } - } - - return ; +void LLViewerObject::resetChildrenRotationAndPosition(const std::vector& rotations, + const std::vector& positions) +{ + if(mChildList.empty()) + { + return ; + } + + S32 index = 0 ; + LLQuaternion inv_rotation = ~getRotationEdit() ; + LLVector3 offset = getPositionEdit() ; + for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* childp = *iter; + if (!childp->isSelected() && childp->mDrawable.notNull()) + { + if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) + { + childp->setRotation(rotations[index] * inv_rotation); + childp->setPosition((positions[index] - offset) * inv_rotation); + LLManip::rebuild(childp); + } + else //avatar + { + LLVector3 reset_pos = (positions[index] - offset) * inv_rotation ; + LLQuaternion reset_rot = rotations[index] * inv_rotation ; + + ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); + ((LLVOAvatar*)childp)->mDrawable->mXform.setRotation(reset_rot) ; + + ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE); + ((LLVOAvatar*)childp)->mDrawable->getVObj()->setRotation(reset_rot, TRUE) ; + + LLManip::rebuild(childp); + } + index++; + } + } + + return ; } //counter-translation void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplified, BOOL skip_avatar_child) { - if(mChildList.empty()) - { - return ; - } - - LLVector3 child_offset; - if(simplified) //translation only, rotation matrix does not change - { - child_offset = offset * ~getRotation(); - } - else //rotation matrix might change too. - { - if (isAttachment() && mDrawable.notNull()) - { - LLXform* attachment_point_xform = mDrawable->getXform()->getParent(); - LLQuaternion parent_rotation = getRotation() * attachment_point_xform->getWorldRotation(); - child_offset = offset * ~parent_rotation; - } - else - { - child_offset = offset * ~getRenderRotation(); - } - } - - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - childp->setPosition(childp->getPosition() + child_offset); - LLManip::rebuild(childp); - } - else //avatar - { - if(!skip_avatar_child) - { - LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ; - - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos); - LLManip::rebuild(childp); - } - } - } - } - - return ; -} - -// virtual -BOOL LLViewerObject::isTempAttachment() const -{ - return (mID.notNull() && (mID == mAttachmentItemID)); + if(mChildList.empty()) + { + return ; + } + + LLVector3 child_offset; + if(simplified) //translation only, rotation matrix does not change + { + child_offset = offset * ~getRotation(); + } + else //rotation matrix might change too. + { + if (isAttachment() && mDrawable.notNull()) + { + LLXform* attachment_point_xform = mDrawable->getXform()->getParent(); + LLQuaternion parent_rotation = getRotation() * attachment_point_xform->getWorldRotation(); + child_offset = offset * ~parent_rotation; + } + else + { + child_offset = offset * ~getRenderRotation(); + } + } + + for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* childp = *iter; + + if (!childp->isSelected() && childp->mDrawable.notNull()) + { + if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) + { + childp->setPosition(childp->getPosition() + child_offset); + LLManip::rebuild(childp); + } + else //avatar + { + if(!skip_avatar_child) + { + LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ; + + ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); + ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos); + LLManip::rebuild(childp); + } + } + } + } + + return ; } -BOOL LLViewerObject::isHiglightedOrBeacon() const +// virtual +BOOL LLViewerObject::isTempAttachment() const { - if (LLFloaterReg::instanceVisible("beacons") && (gPipeline.getRenderBeacons() || gPipeline.getRenderHighlights())) - { - BOOL has_media = (getMediaType() == LLViewerObject::MEDIA_SET); - BOOL is_scripted = !isAvatar() && !getParent() && flagScripted(); - BOOL is_physical = !isAvatar() && flagUsePhysics(); + return (mID.notNull() && (mID == mAttachmentItemID)); +} - return (isParticleSource() && gPipeline.getRenderParticleBeacons()) - || (isAudioSource() && gPipeline.getRenderSoundBeacons()) - || (has_media && gPipeline.getRenderMOAPBeacons()) - || (is_scripted && gPipeline.getRenderScriptedBeacons()) - || (is_scripted && flagHandleTouch() && gPipeline.getRenderScriptedTouchBeacons()) - || (is_physical && gPipeline.getRenderPhysicalBeacons()); - } - return FALSE; +BOOL LLViewerObject::isHiglightedOrBeacon() const +{ + if (LLFloaterReg::instanceVisible("beacons") && (gPipeline.getRenderBeacons() || gPipeline.getRenderHighlights())) + { + BOOL has_media = (getMediaType() == LLViewerObject::MEDIA_SET); + BOOL is_scripted = !isAvatar() && !getParent() && flagScripted(); + BOOL is_physical = !isAvatar() && flagUsePhysics(); + + return (isParticleSource() && gPipeline.getRenderParticleBeacons()) + || (isAudioSource() && gPipeline.getRenderSoundBeacons()) + || (has_media && gPipeline.getRenderMOAPBeacons()) + || (is_scripted && gPipeline.getRenderScriptedBeacons()) + || (is_scripted && flagHandleTouch() && gPipeline.getRenderScriptedTouchBeacons()) + || (is_physical && gPipeline.getRenderPhysicalBeacons()); + } + return FALSE; } const LLUUID &LLViewerObject::getAttachmentItemID() const { - return mAttachmentItemID; + return mAttachmentItemID; } void LLViewerObject::setAttachmentItemID(const LLUUID &id) { - mAttachmentItemID = id; + mAttachmentItemID = id; } EObjectUpdateType LLViewerObject::getLastUpdateType() const { - return mLastUpdateType; + return mLastUpdateType; } void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) { - mLastUpdateType = last_update_type; + mLastUpdateType = last_update_type; } BOOL LLViewerObject::getLastUpdateCached() const { - return mLastUpdateCached; + return mLastUpdateCached; } void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) { - mLastUpdateCached = last_update_cached; + mLastUpdateCached = last_update_cached; } const LLUUID &LLViewerObject::extractAttachmentItemID() { - LLUUID item_id = LLUUID::null; - LLNameValue* item_id_nv = getNVPair("AttachItemID"); - if( item_id_nv ) - { - const char* s = item_id_nv->getString(); - if( s ) - { - item_id.set(s); - } - } - setAttachmentItemID(item_id); - return getAttachmentItemID(); + LLUUID item_id = LLUUID::null; + LLNameValue* item_id_nv = getNVPair("AttachItemID"); + if( item_id_nv ) + { + const char* s = item_id_nv->getString(); + if( s ) + { + item_id.set(s); + } + } + setAttachmentItemID(item_id); + return getAttachmentItemID(); } const std::string& LLViewerObject::getAttachmentItemName() const { - static std::string empty; - LLInventoryItem *item = gInventory.getItem(getAttachmentItemID()); - if (isAttachment() && item) - { - return item->getName(); - } - return empty; + static std::string empty; + LLInventoryItem *item = gInventory.getItem(getAttachmentItemID()); + if (isAttachment() && item) + { + return item->getName(); + } + return empty; } //virtual @@ -7389,19 +7389,19 @@ LLVOAvatar* LLViewerObject::getAvatar() const { return getControlAvatar(); } - if (isAttachment()) - { - LLViewerObject* vobj = (LLViewerObject*) getParent(); + if (isAttachment()) + { + LLViewerObject* vobj = (LLViewerObject*) getParent(); - while (vobj && !vobj->asAvatar()) - { - vobj = (LLViewerObject*) vobj->getParent(); - } + while (vobj && !vobj->asAvatar()) + { + vobj = (LLViewerObject*) vobj->getParent(); + } - return (LLVOAvatar*) vobj; - } + return (LLVOAvatar*) vobj; + } - return NULL; + return NULL; } bool LLViewerObject::hasRenderMaterialParams() const @@ -7481,12 +7481,12 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat { new_material = gGLTFMaterialList.getMaterial(id); } - + // update local state for (S32 te = start_idx; te < end_idx; ++te) { LLTextureEntry* tep = getTE(te); - + // If local_origin=false (i.e. it's from the server), we know the // material has updated or been created, because extra params are // checked for equality on unpacking. In that case, checking the @@ -7495,7 +7495,7 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat bool material_changed = !local_origin || !param_block || id != param_block->getMaterial(te); if (update_server) - { + { // Clear most overrides so the render material better matches the material // ID (preserve transforms). If overrides become passthrough, set the overrides // to nullptr. @@ -7506,7 +7506,7 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat } if (update_server || material_changed) - { + { tep->setGLTFRenderMaterial(nullptr); } @@ -7623,53 +7623,53 @@ void LLViewerObject::shrinkWrap() class ObjectPhysicsProperties : public LLHTTPNode { public: - virtual void post( - ResponsePtr responder, - const LLSD& context, - const LLSD& input) const - { - LLSD object_data = input["body"]["ObjectData"]; - S32 num_entries = object_data.size(); - - for ( S32 i = 0; i < num_entries; i++ ) - { - LLSD& curr_object_data = object_data[i]; - U32 local_id = curr_object_data["LocalID"].asInteger(); - - // Iterate through nodes at end, since it can be on both the regular AND hover list - struct f : public LLSelectedNodeFunctor - { - U32 mID; - f(const U32& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mLocalID == mID ); - } - } func(local_id); - - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); - - if (node) - { - // The LLSD message builder doesn't know how to handle U8, so we need to send as S8 and cast - U8 type = (U8)curr_object_data["PhysicsShapeType"].asInteger(); - F32 density = (F32)curr_object_data["Density"].asReal(); - F32 friction = (F32)curr_object_data["Friction"].asReal(); - F32 restitution = (F32)curr_object_data["Restitution"].asReal(); - F32 gravity = (F32)curr_object_data["GravityMultiplier"].asReal(); - - node->getObject()->setPhysicsShapeType(type); - node->getObject()->setPhysicsGravity(gravity); - node->getObject()->setPhysicsFriction(friction); - node->getObject()->setPhysicsDensity(density); - node->getObject()->setPhysicsRestitution(restitution); - } - } - - dialog_refresh_all(); - }; + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLSD object_data = input["body"]["ObjectData"]; + S32 num_entries = object_data.size(); + + for ( S32 i = 0; i < num_entries; i++ ) + { + LLSD& curr_object_data = object_data[i]; + U32 local_id = curr_object_data["LocalID"].asInteger(); + + // Iterate through nodes at end, since it can be on both the regular AND hover list + struct f : public LLSelectedNodeFunctor + { + U32 mID; + f(const U32& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mLocalID == mID ); + } + } func(local_id); + + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); + + if (node) + { + // The LLSD message builder doesn't know how to handle U8, so we need to send as S8 and cast + U8 type = (U8)curr_object_data["PhysicsShapeType"].asInteger(); + F32 density = (F32)curr_object_data["Density"].asReal(); + F32 friction = (F32)curr_object_data["Friction"].asReal(); + F32 restitution = (F32)curr_object_data["Restitution"].asReal(); + F32 gravity = (F32)curr_object_data["GravityMultiplier"].asReal(); + + node->getObject()->setPhysicsShapeType(type); + node->getObject()->setPhysicsGravity(gravity); + node->getObject()->setPhysicsFriction(friction); + node->getObject()->setPhysicsDensity(density); + node->getObject()->setPhysicsRestitution(restitution); + } + } + + dialog_refresh_all(); + }; }; LLHTTPRegistration - gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties"); + gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties"); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 64c1ee6633..a01e0b435f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -47,7 +47,7 @@ #include "llreflectionmap.h" #include "gltf/asset.h" -class LLAgent; // TODO: Get rid of this. +class LLAgent; // TODO: Get rid of this. class LLAudioSource; class LLAudioSourceVO; class LLColor4; @@ -76,112 +76,112 @@ class LLMeshCostData; typedef enum e_object_update_type { - OUT_FULL, - OUT_TERSE_IMPROVED, - OUT_FULL_COMPRESSED, - OUT_FULL_CACHED, - OUT_UNKNOWN, + OUT_FULL, + OUT_TERSE_IMPROVED, + OUT_FULL_COMPRESSED, + OUT_FULL_CACHED, + OUT_UNKNOWN, } EObjectUpdateType; // callback typedef for inventory typedef void (*inventory_callback)(LLViewerObject*, - LLInventoryObject::object_list_t*, - S32 serial_num, - void*); + LLInventoryObject::object_list_t*, + S32 serial_num, + void*); // for exporting textured materials from SL struct LLMaterialExportInfo { public: - LLMaterialExportInfo(S32 mat_index, S32 texture_index, LLColor4 color) : - mMaterialIndex(mat_index), mTextureIndex(texture_index), mColor(color) {}; + LLMaterialExportInfo(S32 mat_index, S32 texture_index, LLColor4 color) : + mMaterialIndex(mat_index), mTextureIndex(texture_index), mColor(color) {}; - S32 mMaterialIndex; - S32 mTextureIndex; - LLColor4 mColor; + S32 mMaterialIndex; + S32 mTextureIndex; + LLColor4 mColor; }; struct PotentialReturnableObject { - LLBBox box; - LLViewerRegion* pRegion; + LLBBox box; + LLViewerRegion* pRegion; }; //============================================================================ -class LLViewerObject -: public LLPrimitive, - public LLRefCount, - public LLGLUpdate +class LLViewerObject +: public LLPrimitive, + public LLRefCount, + public LLGLUpdate { protected: - virtual ~LLViewerObject(); // use unref() + virtual ~LLViewerObject(); // use unref() - // TomY: Provide for a list of extra parameter structures, mapped by structure name - struct ExtraParameter - { - BOOL in_use; - LLNetworkData *data; - }; - std::unordered_map mExtraParameterList; + // TomY: Provide for a list of extra parameter structures, mapped by structure name + struct ExtraParameter + { + BOOL in_use; + LLNetworkData *data; + }; + std::unordered_map mExtraParameterList; public: - typedef std::list > child_list_t; - typedef std::list > vobj_list_t; + typedef std::list > child_list_t; + typedef std::list > vobj_list_t; - typedef const child_list_t const_child_list_t; + typedef const child_list_t const_child_list_t; - LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE); + LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE); - virtual void markDead(); // Mark this object as dead, and clean up its references - BOOL isDead() const {return mDead;} - BOOL isOrphaned() const { return mOrphaned; } - BOOL isParticleSource() const; + virtual void markDead(); // Mark this object as dead, and clean up its references + BOOL isDead() const {return mDead;} + BOOL isOrphaned() const { return mOrphaned; } + BOOL isParticleSource() const; - virtual LLVOAvatar* asAvatar(); + virtual LLVOAvatar* asAvatar(); - LLVOAvatar* getAvatarAncestor(); + LLVOAvatar* getAvatarAncestor(); - static void initVOClasses(); - static void cleanupVOClasses(); + static void initVOClasses(); + static void cleanupVOClasses(); - void addNVPair(const std::string& data); - BOOL removeNVPair(const std::string& name); - LLNameValue* getNVPair(const std::string& name) const; // null if no name value pair by that name + void addNVPair(const std::string& data); + BOOL removeNVPair(const std::string& name); + LLNameValue* getNVPair(const std::string& name) const; // null if no name value pair by that name - // Object create and update functions - virtual void idleUpdate(LLAgent &agent, const F64 &time); + // Object create and update functions + virtual void idleUpdate(LLAgent &agent, const F64 &time); - // Types of media we can associate - enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; + // Types of media we can associate + enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; - // Return codes for processUpdateMessage - enum { - MEDIA_URL_REMOVED = 0x1, - MEDIA_URL_ADDED = 0x2, - MEDIA_URL_UPDATED = 0x4, + // Return codes for processUpdateMessage + enum { + MEDIA_URL_REMOVED = 0x1, + MEDIA_URL_ADDED = 0x2, + MEDIA_URL_UPDATED = 0x4, MEDIA_FLAGS_CHANGED = 0x8, INVALID_UPDATE = 0x80000000 }; - static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); + static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); + + virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate. + BOOL onActiveList() const {return mOnActiveList;} + void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } - virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate. - BOOL onActiveList() const {return mOnActiveList;} - void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } + virtual BOOL isAttachment() const { return FALSE; } + const std::string& getAttachmentItemName() const; - virtual BOOL isAttachment() const { return FALSE; } - const std::string& getAttachmentItemName() const; + virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment - virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment - bool hasRenderMaterialParams() const; void setHasRenderMaterialParams(bool has_params); @@ -194,431 +194,431 @@ public: void setRenderMaterialID(S32 te, const LLUUID& id, bool update_server = true, bool local_origin = true); void setRenderMaterialIDs(const LLUUID& id); - virtual BOOL isHUDAttachment() const { return FALSE; } - virtual BOOL isTempAttachment() const; + virtual BOOL isHUDAttachment() const { return FALSE; } + virtual BOOL isTempAttachment() const; + + virtual BOOL isHiglightedOrBeacon() const; - virtual BOOL isHiglightedOrBeacon() const; + virtual void updateRadius() {}; + virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() - virtual void updateRadius() {}; - virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() - - // for jointed and other parent-relative hacks - LLViewerObject* getSubParent(); - const LLViewerObject* getSubParent() const; - - // Object visiblility and GPW functions - virtual void setPixelAreaAndAngle(LLAgent &agent); // Override to generate accurate apparent angle and area + // for jointed and other parent-relative hacks + LLViewerObject* getSubParent(); + const LLViewerObject* getSubParent() const; - virtual U32 getNumVertices() const; - virtual U32 getNumIndices() const; - S32 getNumFaces() const { return mNumFaces; } + // Object visiblility and GPW functions + virtual void setPixelAreaAndAngle(LLAgent &agent); // Override to generate accurate apparent angle and area - // Graphical stuff for objects - maybe broken out into render class later? - virtual void updateTextures(); + virtual U32 getNumVertices() const; + virtual U32 getNumIndices() const; + S32 getNumFaces() const { return mNumFaces; } + + // Graphical stuff for objects - maybe broken out into render class later? + virtual void updateTextures(); virtual void faceMappingChanged() {} - virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object - - virtual LLDrawable* createDrawable(LLPipeline *pipeline); - virtual BOOL updateGeometry(LLDrawable *drawable); - virtual void updateGL(); - virtual void updateFaceSize(S32 idx); - virtual BOOL updateLOD(); - virtual BOOL setDrawableParent(LLDrawable* parentp); - F32 getRotTime() { return mRotTime; } + virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object + + virtual LLDrawable* createDrawable(LLPipeline *pipeline); + virtual BOOL updateGeometry(LLDrawable *drawable); + virtual void updateGL(); + virtual void updateFaceSize(S32 idx); + virtual BOOL updateLOD(); + virtual BOOL setDrawableParent(LLDrawable* parentp); + F32 getRotTime() { return mRotTime; } private: - void resetRotTime(); - void setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin); + void resetRotTime(); + void setRenderMaterialIDs(const LLRenderMaterialParams* material_params, bool local_origin); void rebuildMaterial(); public: - void resetRot(); - void applyAngularVelocity(F32 dt); + void resetRot(); + void applyAngularVelocity(F32 dt); - void setLineWidthForWindowSize(S32 window_width); + void setLineWidthForWindowSize(S32 window_width); - static void increaseArrowLength(); // makes axis arrows for selections longer - static void decreaseArrowLength(); // makes axis arrows for selections shorter + static void increaseArrowLength(); // makes axis arrows for selections longer + static void decreaseArrowLength(); // makes axis arrows for selections shorter - // Accessor functions - LLViewerRegion* getRegion() const { return mRegionp; } + // Accessor functions + LLViewerRegion* getRegion() const { return mRegionp; } - BOOL isSelected() const { return mUserSelected; } + BOOL isSelected() const { return mUserSelected; } // Check whole linkset BOOL isAnySelected() const; - virtual void setSelected(BOOL sel); - - const LLUUID &getID() const { return mID; } - U32 getLocalID() const { return mLocalID; } - U32 getCRC() const { return mTotalCRC; } - S32 getListIndex() const { return mListIndex; } - void setListIndex(S32 idx) { mListIndex = idx; } - - virtual BOOL isFlexible() const { return FALSE; } - virtual BOOL isSculpted() const { return FALSE; } - virtual BOOL isMesh() const { return FALSE; } - virtual BOOL isRiggedMesh() const { return FALSE; } - virtual BOOL hasLightTexture() const { return FALSE; } + virtual void setSelected(BOOL sel); + + const LLUUID &getID() const { return mID; } + U32 getLocalID() const { return mLocalID; } + U32 getCRC() const { return mTotalCRC; } + S32 getListIndex() const { return mListIndex; } + void setListIndex(S32 idx) { mListIndex = idx; } + + virtual BOOL isFlexible() const { return FALSE; } + virtual BOOL isSculpted() const { return FALSE; } + 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 - // anti-encroachment is enabled - bool isReturnable(); + // This method returns true if the object is over land owned by + // the agent, one of its groups, or it encroaches and + // anti-encroachment is enabled + bool isReturnable(); - void buildReturnablesForChildrenVO( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); - void constructAndAddReturnable( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); + void buildReturnablesForChildrenVO( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); + void constructAndAddReturnable( std::vector& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion ); - // This method returns true if the object crosses - // any parcel bounds in the region. - bool crossesParcelBounds(); + // This method returns true if the object crosses + // any parcel bounds in the region. + bool crossesParcelBounds(); - /* - // This method will scan through this object, and then query the - // selection manager to see if the local agent probably has the - // ability to modify the object. Since this calls into the - // selection manager, you should avoid calling this method from - // there. - BOOL isProbablyModifiable() const; - */ + /* + // This method will scan through this object, and then query the + // selection manager to see if the local agent probably has the + // ability to modify the object. Since this calls into the + // selection manager, you should avoid calling this method from + // there. + BOOL isProbablyModifiable() const; + */ - virtual BOOL setParent(LLViewerObject* parent); + virtual BOOL setParent(LLViewerObject* parent); virtual void onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent); virtual void afterReparent(); - virtual void addChild(LLViewerObject *childp); - virtual void removeChild(LLViewerObject *childp); - const_child_list_t& getChildren() const { return mChildList; } - S32 numChildren() const { return mChildList.size(); } - void addThisAndAllChildren(std::vector& objects); - void addThisAndNonJointChildren(std::vector& objects); - BOOL isChild(LLViewerObject *childp) const; - BOOL isSeat() const; - - - //detect if given line segment (in agent space) intersects with this viewer object. - //returns TRUE if intersection detected and returns information about intersection - virtual BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - BOOL pick_rigged = FALSE, + virtual void addChild(LLViewerObject *childp); + virtual void removeChild(LLViewerObject *childp); + const_child_list_t& getChildren() const { return mChildList; } + S32 numChildren() const { return mChildList.size(); } + void addThisAndAllChildren(std::vector& objects); + void addThisAndNonJointChildren(std::vector& objects); + BOOL isChild(LLViewerObject *childp) const; + BOOL isSeat() const; + + + //detect if given line segment (in agent space) intersects with this viewer object. + //returns TRUE if intersection detected and returns information about intersection + virtual BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + 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 - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); - - virtual BOOL lineSegmentBoundingBox(const LLVector4a& start, const LLVector4a& end); - - virtual const LLVector3d getPositionGlobal() const; - virtual const LLVector3 &getPositionRegion() const; - virtual const LLVector3 getPositionEdit() const; - virtual const LLVector3 &getPositionAgent() const; - virtual const LLVector3 getRenderPosition() const; + 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 + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + virtual BOOL lineSegmentBoundingBox(const LLVector4a& start, const LLVector4a& end); + + virtual const LLVector3d getPositionGlobal() const; + virtual const LLVector3 &getPositionRegion() const; + virtual const LLVector3 getPositionEdit() const; + virtual const LLVector3 &getPositionAgent() const; + virtual const LLVector3 getRenderPosition() const; LLMatrix4a getAgentToGLTFAssetTransform() const; LLMatrix4a getGLTFAssetToAgentTransform() const; LLVector3 getGLTFNodePositionAgent(S32 node_index) const; LLMatrix4a getGLTFNodeTransformAgent(S32 node_index) const; void getGLTFNodeTransformAgent(S32 node_index, LLVector3* position, LLQuaternion* rotation, LLVector3* scale) const; - + // move the node at the given index by the given offset in agent space void moveGLTFNode(S32 node_index, const LLVector3& offset); // set the rotation in agent space of the given node void setGLTFNodeRotationAgent(S32 node_index, const LLQuaternion& rotation); - virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not + virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not - LLViewerObject* getRootEdit() const; + LLViewerObject* getRootEdit() const; - const LLQuaternion getRotationRegion() const; - const LLQuaternion getRotationEdit() const; - const LLQuaternion getRenderRotation() const; - virtual const LLMatrix4 getRenderMatrix() const; + const LLQuaternion getRotationRegion() const; + const LLQuaternion getRotationEdit() const; + const LLQuaternion getRenderRotation() const; + virtual const LLMatrix4 getRenderMatrix() const; - void setPosition(const LLVector3 &pos, BOOL damped = FALSE); - void setPositionGlobal(const LLVector3d &position, BOOL damped = FALSE); - void setPositionRegion(const LLVector3 &position, BOOL damped = FALSE); - void setPositionEdit(const LLVector3 &position, BOOL damped = FALSE); - void setPositionAgent(const LLVector3 &pos_agent, BOOL damped = FALSE); - void setPositionParent(const LLVector3 &pos_parent, BOOL damped = FALSE); - void setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped = FALSE ); + void setPosition(const LLVector3 &pos, BOOL damped = FALSE); + void setPositionGlobal(const LLVector3d &position, BOOL damped = FALSE); + void setPositionRegion(const LLVector3 &position, BOOL damped = FALSE); + void setPositionEdit(const LLVector3 &position, BOOL damped = FALSE); + void setPositionAgent(const LLVector3 &pos_agent, BOOL damped = FALSE); + void setPositionParent(const LLVector3 &pos_parent, BOOL damped = FALSE); + void setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped = FALSE ); - virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const { return xform->getWorldMatrix(); } + virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const { return xform->getWorldMatrix(); } - inline void setRotation(const F32 x, const F32 y, const F32 z, BOOL damped = FALSE); - inline void setRotation(const LLQuaternion& quat, BOOL damped = FALSE); + inline void setRotation(const F32 x, const F32 y, const F32 z, BOOL damped = FALSE); + inline void setRotation(const LLQuaternion& quat, BOOL damped = FALSE); - /*virtual*/ void setNumTEs(const U8 num_tes); - /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); + /*virtual*/ void setNumTEs(const U8 num_tes); + /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); void updateTEMaterialTextures(U8 te); - /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); - /*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid); - /*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid); - S32 setTETextureCore(const U8 te, LLViewerTexture *image); - S32 setTENormalMapCore(const U8 te, LLViewerTexture *image); - S32 setTESpecularMapCore(const U8 te, LLViewerTexture *image); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); - /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); - /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); - /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); - /*virtual*/ S32 setTEOffset(const U8 te, const F32 s, const F32 t); - /*virtual*/ S32 setTEOffsetS(const U8 te, const F32 s); - /*virtual*/ S32 setTEOffsetT(const U8 te, const F32 t); - /*virtual*/ S32 setTERotation(const U8 te, const F32 r); - /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump ); - /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen ); - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics - /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); - /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); - /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); - /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); - /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); - /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); + /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); + /*virtual*/ S32 setTENormalMap(const U8 te, const LLUUID &uuid); + /*virtual*/ S32 setTESpecularMap(const U8 te, const LLUUID &uuid); + S32 setTETextureCore(const U8 te, LLViewerTexture *image); + S32 setTENormalMapCore(const U8 te, LLViewerTexture *image); + S32 setTESpecularMapCore(const U8 te, LLViewerTexture *image); + /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); + /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); + /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); + /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); + /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); + /*virtual*/ S32 setTEOffset(const U8 te, const F32 s, const F32 t); + /*virtual*/ S32 setTEOffsetS(const U8 te, const F32 s); + /*virtual*/ S32 setTEOffsetT(const U8 te, const F32 t); + /*virtual*/ S32 setTERotation(const U8 te, const F32 r); + /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump ); + /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen ); + /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics + /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); + /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); + /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); + /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); + /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); virtual S32 setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat); - // Used by Materials update functions to properly kick off rebuilds - // of VBs etc when materials updates require changes. - // - void refreshMaterials(); + // Used by Materials update functions to properly kick off rebuilds + // of VBs etc when materials updates require changes. + // + void refreshMaterials(); + + /*virtual*/ BOOL setMaterial(const U8 material); + virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive + virtual void changeTEImage(S32 index, LLViewerTexture* new_image) ; + virtual void changeTENormalMap(S32 index, LLViewerTexture* new_image) ; + virtual void changeTESpecularMap(S32 index, LLViewerTexture* new_image) ; + LLViewerTexture *getTEImage(const U8 te) const; + LLViewerTexture *getTENormalMap(const U8 te) const; + LLViewerTexture *getTESpecularMap(const U8 te) const; - /*virtual*/ BOOL setMaterial(const U8 material); - virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive - virtual void changeTEImage(S32 index, LLViewerTexture* new_image) ; - virtual void changeTENormalMap(S32 index, LLViewerTexture* new_image) ; - virtual void changeTESpecularMap(S32 index, LLViewerTexture* new_image) ; - LLViewerTexture *getTEImage(const U8 te) const; - LLViewerTexture *getTENormalMap(const U8 te) const; - LLViewerTexture *getTESpecularMap(const U8 te) const; + bool isImageAlphaBlended(const U8 te) const; - bool isImageAlphaBlended(const U8 te) const; + void fitFaceTexture(const U8 face); + void sendTEUpdate() const; // Sends packed representation of all texture entry information - void fitFaceTexture(const U8 face); - void sendTEUpdate() const; // Sends packed representation of all texture entry information - - virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE); + virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE); S32 getAnimatedObjectMaxTris() const; F32 recursiveGetEstTrianglesMax() const; virtual F32 getEstTrianglesMax() const; virtual F32 getEstTrianglesStreamingCost() const; - virtual F32 getStreamingCost() const; + virtual F32 getStreamingCost() const; virtual bool getCostData(LLMeshCostData& costs) const; - virtual U32 getTriangleCount(S32* vcount = NULL) const; - virtual U32 getHighLODTriangleCount(); + virtual U32 getTriangleCount(S32* vcount = NULL) const; + virtual U32 getHighLODTriangleCount(); F32 recursiveGetScaledSurfaceArea() const; U32 recursiveGetTriangleCount(S32* vcount = NULL) const; - void setObjectCost(F32 cost); - F32 getObjectCost(); - - void setLinksetCost(F32 cost); - F32 getLinksetCost(); - - void setPhysicsCost(F32 cost); - F32 getPhysicsCost(); - - void setLinksetPhysicsCost(F32 cost); - F32 getLinksetPhysicsCost(); - - void sendShapeUpdate(); - - U8 getAttachmentState() { return mAttachmentState; } - - F32 getAppAngle() const { return mAppAngle; } - F32 getPixelArea() const { return mPixelArea; } - void setPixelArea(F32 area) { mPixelArea = area; } - F32 getMaxScale() const; - F32 getMidScale() const; - F32 getMinScale() const; - - // Owner id is this object's owner - void setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags); - void adjustAudioGain(const F32 gain); - F32 getSoundCutOffRadius() const { return mSoundCutOffRadius; } - void clearAttachedSound() { mAudioSourcep = NULL; } - - // Create if necessary - LLAudioSource *getAudioSource(const LLUUID& owner_id); - BOOL isAudioSource() const {return mAudioSourcep != NULL;} - - U8 getMediaType() const; - void setMediaType(U8 media_type); - - std::string getMediaURL() const; - void setMediaURL(const std::string& media_url); - - BOOL getMediaPassedWhitelist() const; - void setMediaPassedWhitelist(BOOL passed); - - void sendMaterialUpdate() const; - - void setDebugText(const std::string &utf8text, const LLColor4& color = LLColor4::white); - void appendDebugText(const std::string &utf8text); - void initHudText(); - void restoreHudText(); - void setIcon(LLViewerTexture* icon_image); - void clearIcon(); + void setObjectCost(F32 cost); + F32 getObjectCost(); + + void setLinksetCost(F32 cost); + F32 getLinksetCost(); + + void setPhysicsCost(F32 cost); + F32 getPhysicsCost(); + + void setLinksetPhysicsCost(F32 cost); + F32 getLinksetPhysicsCost(); + + void sendShapeUpdate(); + + U8 getAttachmentState() { return mAttachmentState; } + + F32 getAppAngle() const { return mAppAngle; } + F32 getPixelArea() const { return mPixelArea; } + void setPixelArea(F32 area) { mPixelArea = area; } + F32 getMaxScale() const; + F32 getMidScale() const; + F32 getMinScale() const; + + // Owner id is this object's owner + void setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags); + void adjustAudioGain(const F32 gain); + F32 getSoundCutOffRadius() const { return mSoundCutOffRadius; } + void clearAttachedSound() { mAudioSourcep = NULL; } + + // Create if necessary + LLAudioSource *getAudioSource(const LLUUID& owner_id); + BOOL isAudioSource() const {return mAudioSourcep != NULL;} + + U8 getMediaType() const; + void setMediaType(U8 media_type); + + std::string getMediaURL() const; + void setMediaURL(const std::string& media_url); + + BOOL getMediaPassedWhitelist() const; + void setMediaPassedWhitelist(BOOL passed); + + void sendMaterialUpdate() const; + + void setDebugText(const std::string &utf8text, const LLColor4& color = LLColor4::white); + void appendDebugText(const std::string &utf8text); + void initHudText(); + void restoreHudText(); + void setIcon(LLViewerTexture* icon_image); + void clearIcon(); void recursiveMarkForUpdate(); - virtual void markForUpdate(); - void updateVolume(const LLVolumeParams& volume_params); - virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); - virtual F32 getBinRadius(); - - LLBBox getBoundingBoxAgent() const; - - void updatePositionCaches() const; // Update the global and region position caches from the object (and parent's) xform. - void updateText(); // update text label position - virtual void updateDrawable(BOOL force_damped); // force updates on static objects - - bool isOwnerInMuteList(LLUUID item_id = LLUUID()); - - void setDrawableState(U32 state, BOOL recursive = TRUE); - void clearDrawableState(U32 state, BOOL recursive = TRUE); - BOOL isDrawableState(U32 state, BOOL recursive = TRUE) const; - - // Called when the drawable shifts - virtual void onShift(const LLVector4a &shift_vector) { } - - ////////////////////////////////////// - // - // Inventory methods - // - - // This function is called when someone is interested in a viewer - // object's inventory. The callback is called as soon as the - // viewer object has the inventory stored locally. - void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); - void removeInventoryListener(LLVOInventoryListener* listener); - BOOL isInventoryPending(); - void clearInventoryListeners(); - bool hasInventoryListeners(); - void requestInventory(); - static void processTaskInv(LLMessageSystem* msg, void** user_data); - void removeInventory(const LLUUID& item_id); - - // The updateInventory() call potentially calls into the selection - // manager, so do no call updateInventory() from the selection - // manager until we have better iterators. - void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); - void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. - void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new); - LLInventoryObject* getInventoryObject(const LLUUID& item_id); - LLInventoryItem* getInventoryItem(const LLUUID& item_id); - - // Get content except for root category - void getInventoryContents(LLInventoryObject::object_list_t& objects); - LLInventoryObject* getInventoryRoot(); - LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); + virtual void markForUpdate(); + void updateVolume(const LLVolumeParams& volume_params); + virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); + virtual F32 getBinRadius(); + + LLBBox getBoundingBoxAgent() const; + + void updatePositionCaches() const; // Update the global and region position caches from the object (and parent's) xform. + void updateText(); // update text label position + virtual void updateDrawable(BOOL force_damped); // force updates on static objects + + bool isOwnerInMuteList(LLUUID item_id = LLUUID()); + + void setDrawableState(U32 state, BOOL recursive = TRUE); + void clearDrawableState(U32 state, BOOL recursive = TRUE); + BOOL isDrawableState(U32 state, BOOL recursive = TRUE) const; + + // Called when the drawable shifts + virtual void onShift(const LLVector4a &shift_vector) { } + + ////////////////////////////////////// + // + // Inventory methods + // + + // This function is called when someone is interested in a viewer + // object's inventory. The callback is called as soon as the + // viewer object has the inventory stored locally. + void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); + void removeInventoryListener(LLVOInventoryListener* listener); + BOOL isInventoryPending(); + void clearInventoryListeners(); + bool hasInventoryListeners(); + void requestInventory(); + static void processTaskInv(LLMessageSystem* msg, void** user_data); + void removeInventory(const LLUUID& item_id); + + // The updateInventory() call potentially calls into the selection + // manager, so do no call updateInventory() from the selection + // manager until we have better iterators. + void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); + void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. + void updateMaterialInventory(LLViewerInventoryItem* item, U8 key, bool is_new); + LLInventoryObject* getInventoryObject(const LLUUID& item_id); + LLInventoryItem* getInventoryItem(const LLUUID& item_id); + + // Get content except for root category + void getInventoryContents(LLInventoryObject::object_list_t& objects); + LLInventoryObject* getInventoryRoot(); + LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id, LLAssetType::EType type); - S16 getInventorySerial() const { return mInventorySerialNum; } - - // These functions does viewer-side only object inventory modifications - void updateViewerInventoryAsset( - const LLViewerInventoryItem* item, - const LLUUID& new_asset); - - // This function will make sure that we refresh the inventory. - void dirtyInventory(); - BOOL isInventoryDirty() { return mInventoryDirty; } - - // save a script, which involves removing the old one, and rezzing - // in the new one. This method should be called with the asset id - // of the new and old script AFTER the bytecode has been saved. - void saveScript(const LLViewerInventoryItem* item, BOOL active, bool is_new); - - // move an inventory item out of the task and into agent - // inventory. This operation is based on messaging. No permissions - // checks are made on the viewer - the server will double check. - void moveInventory(const LLUUID& agent_folder, const LLUUID& item_id); - - // Find the number of instances of this object's inventory that are of the given type - S32 countInventoryContents( LLAssetType::EType type ); - - BOOL permAnyOwner() const; - BOOL permYouOwner() const; - BOOL permGroupOwner() const; - BOOL permOwnerModify() const; - BOOL permModify() const; - BOOL permCopy() const; - BOOL permMove() const; - BOOL permTransfer() const; - inline BOOL flagUsePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); } - inline BOOL flagObjectAnyOwner() const { return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); } - inline BOOL flagObjectYouOwner() const { return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); } - inline BOOL flagObjectGroupOwned() const { return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); } - inline BOOL flagObjectOwnerModify() const { return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); } - inline BOOL flagObjectModify() const { return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); } - inline BOOL flagObjectCopy() const { return ((mFlags & FLAGS_OBJECT_COPY) != 0); } - inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } - inline BOOL flagObjectTransfer() const { return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); } - inline BOOL flagObjectPermanent() const { return ((mFlags & FLAGS_AFFECTS_NAVMESH) != 0); } - inline BOOL flagCharacter() const { return ((mFlags & FLAGS_CHARACTER) != 0); } - inline BOOL flagVolumeDetect() const { return ((mFlags & FLAGS_VOLUME_DETECT) != 0); } - inline BOOL flagIncludeInSearch() const { return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); } - inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); } - inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); } - inline BOOL flagTakesMoney() const { return ((mFlags & FLAGS_TAKES_MONEY) != 0); } - inline BOOL flagPhantom() const { return ((mFlags & FLAGS_PHANTOM) != 0); } - inline BOOL flagInventoryEmpty() const { return ((mFlags & FLAGS_INVENTORY_EMPTY) != 0); } - inline BOOL flagAllowInventoryAdd() const { return ((mFlags & FLAGS_ALLOW_INVENTORY_DROP) != 0); } - inline BOOL flagTemporaryOnRez() const { return ((mFlags & FLAGS_TEMPORARY_ON_REZ) != 0); } - inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); } - inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); } - inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } - - U8 getPhysicsShapeType() const; - inline F32 getPhysicsGravity() const { return mPhysicsGravity; } - inline F32 getPhysicsFriction() const { return mPhysicsFriction; } - inline F32 getPhysicsDensity() const { return mPhysicsDensity; } - inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; } - - bool isPermanentEnforced() const; - - bool getIncludeInSearch() const; - void setIncludeInSearch(bool include_in_search); - - // Does "open" object menu item apply? - BOOL allowOpen() const; - - void setClickAction(U8 action) { mClickAction = action; } - U8 getClickAction() const { return mClickAction; } - bool specialHoverCursor() const; // does it have a special hover cursor? - - void setRegion(LLViewerRegion *regionp); - virtual void updateRegion(LLViewerRegion *regionp); - - void updateFlags(BOOL physics_changed = FALSE); - void loadFlags(U32 flags); //load flags from cache or from message - BOOL setFlags(U32 flag, BOOL state); - BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); - void setPhysicsShapeType(U8 type); - void setPhysicsGravity(F32 gravity); - void setPhysicsFriction(F32 friction); - void setPhysicsDensity(F32 density); - void setPhysicsRestitution(F32 restitution); - - virtual void dump() const; - static U32 getNumZombieObjects() { return sNumZombieObjects; } - - void printNameValuePairs() const; - - virtual S32 getLOD() const { return 3; } - virtual U32 getPartitionType() const; - void dirtySpatialGroup() const; - virtual void dirtyMesh(); - - virtual LLNetworkData* getParameterEntry(U16 param_type) const; - virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); - virtual BOOL getParameterEntryInUse(U16 param_type) const; - virtual bool setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin); - // Called when a parameter is changed - virtual void parameterChanged(U16 param_type, bool local_origin); - virtual void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); - + S16 getInventorySerial() const { return mInventorySerialNum; } + + // These functions does viewer-side only object inventory modifications + void updateViewerInventoryAsset( + const LLViewerInventoryItem* item, + const LLUUID& new_asset); + + // This function will make sure that we refresh the inventory. + void dirtyInventory(); + BOOL isInventoryDirty() { return mInventoryDirty; } + + // save a script, which involves removing the old one, and rezzing + // in the new one. This method should be called with the asset id + // of the new and old script AFTER the bytecode has been saved. + void saveScript(const LLViewerInventoryItem* item, BOOL active, bool is_new); + + // move an inventory item out of the task and into agent + // inventory. This operation is based on messaging. No permissions + // checks are made on the viewer - the server will double check. + void moveInventory(const LLUUID& agent_folder, const LLUUID& item_id); + + // Find the number of instances of this object's inventory that are of the given type + S32 countInventoryContents( LLAssetType::EType type ); + + BOOL permAnyOwner() const; + BOOL permYouOwner() const; + BOOL permGroupOwner() const; + BOOL permOwnerModify() const; + BOOL permModify() const; + BOOL permCopy() const; + BOOL permMove() const; + BOOL permTransfer() const; + inline BOOL flagUsePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); } + inline BOOL flagObjectAnyOwner() const { return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); } + inline BOOL flagObjectYouOwner() const { return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); } + inline BOOL flagObjectGroupOwned() const { return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); } + inline BOOL flagObjectOwnerModify() const { return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); } + inline BOOL flagObjectModify() const { return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); } + inline BOOL flagObjectCopy() const { return ((mFlags & FLAGS_OBJECT_COPY) != 0); } + inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } + inline BOOL flagObjectTransfer() const { return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); } + inline BOOL flagObjectPermanent() const { return ((mFlags & FLAGS_AFFECTS_NAVMESH) != 0); } + inline BOOL flagCharacter() const { return ((mFlags & FLAGS_CHARACTER) != 0); } + inline BOOL flagVolumeDetect() const { return ((mFlags & FLAGS_VOLUME_DETECT) != 0); } + inline BOOL flagIncludeInSearch() const { return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); } + inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); } + inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); } + inline BOOL flagTakesMoney() const { return ((mFlags & FLAGS_TAKES_MONEY) != 0); } + inline BOOL flagPhantom() const { return ((mFlags & FLAGS_PHANTOM) != 0); } + inline BOOL flagInventoryEmpty() const { return ((mFlags & FLAGS_INVENTORY_EMPTY) != 0); } + inline BOOL flagAllowInventoryAdd() const { return ((mFlags & FLAGS_ALLOW_INVENTORY_DROP) != 0); } + inline BOOL flagTemporaryOnRez() const { return ((mFlags & FLAGS_TEMPORARY_ON_REZ) != 0); } + inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); } + inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); } + inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } + + U8 getPhysicsShapeType() const; + inline F32 getPhysicsGravity() const { return mPhysicsGravity; } + inline F32 getPhysicsFriction() const { return mPhysicsFriction; } + inline F32 getPhysicsDensity() const { return mPhysicsDensity; } + inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; } + + bool isPermanentEnforced() const; + + bool getIncludeInSearch() const; + void setIncludeInSearch(bool include_in_search); + + // Does "open" object menu item apply? + BOOL allowOpen() const; + + void setClickAction(U8 action) { mClickAction = action; } + U8 getClickAction() const { return mClickAction; } + bool specialHoverCursor() const; // does it have a special hover cursor? + + void setRegion(LLViewerRegion *regionp); + virtual void updateRegion(LLViewerRegion *regionp); + + void updateFlags(BOOL physics_changed = FALSE); + void loadFlags(U32 flags); //load flags from cache or from message + BOOL setFlags(U32 flag, BOOL state); + BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); + void setPhysicsShapeType(U8 type); + void setPhysicsGravity(F32 gravity); + void setPhysicsFriction(F32 friction); + void setPhysicsDensity(F32 density); + void setPhysicsRestitution(F32 restitution); + + virtual void dump() const; + static U32 getNumZombieObjects() { return sNumZombieObjects; } + + void printNameValuePairs() const; + + virtual S32 getLOD() const { return 3; } + virtual U32 getPartitionType() const; + void dirtySpatialGroup() const; + virtual void dirtyMesh(); + + virtual LLNetworkData* getParameterEntry(U16 param_type) const; + virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); + virtual BOOL getParameterEntryInUse(U16 param_type) const; + virtual bool setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin); + // Called when a parameter is changed + virtual void parameterChanged(U16 param_type, bool local_origin); + virtual void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); + bool isShrinkWrapped() const { return mShouldShrinkWrap; } // Used to improve performance. If an object is likely to rebuild its vertex buffer often @@ -627,139 +627,139 @@ public: // so that nearby objects won't attempt to share a vertex buffer with this object. void shrinkWrap(); - friend class LLViewerObjectList; - friend class LLViewerMediaList; + friend class LLViewerObjectList; + friend class LLViewerMediaList; public: - LLViewerTexture* getBakedTextureForMagicId(const LLUUID& id); - void updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& old_id); - void refreshBakeTexture(); + LLViewerTexture* getBakedTextureForMagicId(const LLUUID& id); + void updateAvatarMeshVisibility(const LLUUID& id, const LLUUID& old_id); + void refreshBakeTexture(); public: - static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); - static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); - static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); - static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); - static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); + static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); + static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); + static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); + static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); + static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); public: - //counter-translation - void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE, BOOL skip_avatar_child = FALSE) ; - //counter-rotation - void resetChildrenRotationAndPosition(const std::vector& rotations, - const std::vector& positions) ; - void saveUnselectedChildrenRotation(std::vector& rotations) ; - void saveUnselectedChildrenPosition(std::vector& positions) ; - std::vector mUnselectedChildrenPositions ; + //counter-translation + void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE, BOOL skip_avatar_child = FALSE) ; + //counter-rotation + void resetChildrenRotationAndPosition(const std::vector& rotations, + const std::vector& positions) ; + void saveUnselectedChildrenRotation(std::vector& rotations) ; + void saveUnselectedChildrenPosition(std::vector& positions) ; + std::vector mUnselectedChildrenPositions ; private: void setObjectCostStale(); bool isAssetInInventory(LLViewerInventoryItem* item, LLAssetType::EType type); - ExtraParameter* createNewParameterEntry(U16 param_type); - ExtraParameter* getExtraParameterEntry(U16 param_type) const; - ExtraParameter* getExtraParameterEntryCreate(U16 param_type); - bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); + ExtraParameter* createNewParameterEntry(U16 param_type); + ExtraParameter* getExtraParameterEntry(U16 param_type) const; + ExtraParameter* getExtraParameterEntryCreate(U16 param_type); + bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); // This function checks to see if the given media URL has changed its version // and the update wasn't due to this agent's last action. U32 checkMediaURL(const std::string &media_url); - - // Motion prediction between updates - void interpolateLinearMotion(const F64SecondsImplicit & frame_time, const F32SecondsImplicit & dt); - static void initObjectDataMap(); + // Motion prediction between updates + void interpolateLinearMotion(const F64SecondsImplicit & frame_time, const F32SecondsImplicit & dt); + + static void initObjectDataMap(); - // forms task inventory request if none are pending, marks request as pending - void fetchInventoryFromServer(); + // forms task inventory request if none are pending, marks request as pending + void fetchInventoryFromServer(); - // forms task inventory request after some time passed, marks request as pending - void fetchInventoryDelayed(const F64 &time_seconds); - static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds); + // forms task inventory request after some time passed, marks request as pending + void fetchInventoryDelayed(const F64 &time_seconds); + static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds); public: - // - // Viewer-side only types - use the LL_PCODE_APP mask. - // - typedef enum e_vo_types - { - LL_VO_CLOUDS = LL_PCODE_APP | 0x20, // no longer used - LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30, - LL_VO_WL_SKY = LL_PCODE_APP | 0x40, - LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50, - LL_VO_SKY = LL_PCODE_APP | 0x60, - LL_VO_VOID_WATER = LL_PCODE_APP | 0x70, - LL_VO_WATER = LL_PCODE_APP | 0x80, - LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0, - LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0, - LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0, - } EVOType; - - typedef enum e_physics_shape_types - { - PHYSICS_SHAPE_PRIM = 0, - PHYSICS_SHAPE_NONE, - PHYSICS_SHAPE_CONVEX_HULL, - } EPhysicsShapeType; - - LLUUID mID; - LLUUID mOwnerID; //null if unknown - - // unique within region, not unique across regions - // Local ID = 0 is not used - U32 mLocalID; - - // Last total CRC received from sim, used for caching - U32 mTotalCRC; - - // index into LLViewerObjectList::mActiveObjects or -1 if not in list - S32 mListIndex; - - LLPointer *mTEImages; - LLPointer *mTENormalMaps; - LLPointer *mTESpecularMaps; - + // + // Viewer-side only types - use the LL_PCODE_APP mask. + // + typedef enum e_vo_types + { + LL_VO_CLOUDS = LL_PCODE_APP | 0x20, // no longer used + LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30, + LL_VO_WL_SKY = LL_PCODE_APP | 0x40, + LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50, + LL_VO_SKY = LL_PCODE_APP | 0x60, + LL_VO_VOID_WATER = LL_PCODE_APP | 0x70, + LL_VO_WATER = LL_PCODE_APP | 0x80, + LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0, + LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0, + LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0, + } EVOType; + + typedef enum e_physics_shape_types + { + PHYSICS_SHAPE_PRIM = 0, + PHYSICS_SHAPE_NONE, + PHYSICS_SHAPE_CONVEX_HULL, + } EPhysicsShapeType; + + LLUUID mID; + LLUUID mOwnerID; //null if unknown + + // unique within region, not unique across regions + // Local ID = 0 is not used + U32 mLocalID; + + // Last total CRC received from sim, used for caching + U32 mTotalCRC; + + // index into LLViewerObjectList::mActiveObjects or -1 if not in list + S32 mListIndex; + + LLPointer *mTEImages; + LLPointer *mTENormalMaps; + LLPointer *mTESpecularMaps; + // 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; + BOOL mbCanSelect; private: - // Grabbed from UPDATE_FLAGS - U32 mFlags; + // Grabbed from UPDATE_FLAGS + U32 mFlags; - static std::map sObjectDataMap; + static std::map sObjectDataMap; public: - // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties - U8 mPhysicsShapeType; - F32 mPhysicsGravity; - F32 mPhysicsFriction; - F32 mPhysicsDensity; - F32 mPhysicsRestitution; - + // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties + U8 mPhysicsShapeType; + F32 mPhysicsGravity; + F32 mPhysicsFriction; + F32 mPhysicsDensity; + F32 mPhysicsRestitution; + // Associated GLTF Asset LLPointer mGLTFAsset; - // Pipeline classes - LLPointer mDrawable; + // Pipeline classes + LLPointer mDrawable; - // Band-aid to select object after all creation initialization is done - BOOL mCreateSelected; + // Band-aid to select object after all creation initialization is done + BOOL mCreateSelected; - // Replace textures with web pages on this object while drawing - BOOL mRenderMedia; + // Replace textures with web pages on this object while drawing + BOOL mRenderMedia; bool mRiggedAttachedWarned; - // In bits - S32 mBestUpdatePrecision; + // In bits + S32 mBestUpdatePrecision; - // TODO: Make all this stuff private. JC - LLPointer mText; - LLPointer mIcon; + // TODO: Make all this stuff private. JC + LLPointer mText; + LLPointer mIcon; - std::string mHudText; - LLColor4 mHudTextColor; + std::string mHudText; + LLColor4 mHudTextColor; - static BOOL sUseSharedDrawables; + static BOOL sUseSharedDrawables; public: // Returns mControlAvatar for the edit root prim of this linkset @@ -783,177 +783,177 @@ protected: LLPointer mControlAvatar; protected: - // delete an item in the inventory, but don't tell the - // server. This is used internally by remove, update, and - // savescript. - void deleteInventoryItem(const LLUUID& item_id); - - // do the update/caching logic. called by saveScript and - // updateInventory. - void doUpdateInventory(LLPointer& item, U8 key, bool is_new); - - static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0); - - BOOL setData(const U8 *datap, const U32 data_size); - - // Hide or show HUD, icon and particles - void hideExtraDisplayItems( BOOL hidden ); - - ////////////////////////// - // - // inventory functionality - // - - static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); - BOOL loadTaskInvFile(const std::string& filename); - void doInventoryCallback(); - - BOOL isOnMap(); - - void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); - void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy); - void deleteParticleSource(); - void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); - + // delete an item in the inventory, but don't tell the + // server. This is used internally by remove, update, and + // savescript. + void deleteInventoryItem(const LLUUID& item_id); + + // do the update/caching logic. called by saveScript and + // updateInventory. + void doUpdateInventory(LLPointer& item, U8 key, bool is_new); + + static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0); + + BOOL setData(const U8 *datap, const U32 data_size); + + // Hide or show HUD, icon and particles + void hideExtraDisplayItems( BOOL hidden ); + + ////////////////////////// + // + // inventory functionality + // + + static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); + BOOL loadTaskInvFile(const std::string& filename); + void doInventoryCallback(); + + BOOL isOnMap(); + + void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); + void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy); + void deleteParticleSource(); + void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); + private: - void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string - void deleteTEImages(); // correctly deletes list of images - + void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string + void deleteTEImages(); // correctly deletes list of images + protected: - typedef std::map name_value_map_t; - name_value_map_t mNameValuePairs; // Any name-value pairs stored by script - - child_list_t mChildList; - - F64Seconds mLastInterpUpdateSecs; // Last update for purposes of interpolation - F64Seconds mLastMessageUpdateSecs; // Last update from a message from the simulator - TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator - F64SecondsImplicit mRegionCrossExpire; // frame time we detected region crossing in + wait time - - // extra data sent from the sim...currently only used for tree species info - U8* mData; - - LLPointer mPartSourcep; // Particle source associated with this object. - LLAudioSourceVO* mAudioSourcep; - F32 mAudioGain; - F32 mSoundCutOffRadius; - - F32 mAppAngle; // Apparent visual arc in degrees - F32 mPixelArea; // Apparent area in pixels - - // IDs of of all items in the object's content which are added to the object's content, - // but not updated on the server yet. After item was updated, its ID will be removed from this list. - std::list mPendingInventoryItemsIDs; - - // This is the object's inventory from the viewer's perspective. - LLInventoryObject::object_list_t* mInventory; - class LLInventoryCallbackInfo - { - public: - ~LLInventoryCallbackInfo(); - LLVOInventoryListener* mListener; - void* mInventoryData; - }; - typedef std::list callback_list_t; - callback_list_t mInventoryCallbacks; - S16 mInventorySerialNum; - S16 mExpectedInventorySerialNum; - - enum EInventoryRequestState - { - INVENTORY_REQUEST_STOPPED, - INVENTORY_REQUEST_WAIT, // delay before requesting - INVENTORY_REQUEST_PENDING, // just did fetchInventoryFromServer() - INVENTORY_XFER // processed response from 'fetch', now doing an xfer - }; - EInventoryRequestState mInvRequestState; - U64 mInvRequestXFerId; - BOOL mInventoryDirty; - - LLViewerRegion *mRegionp; // Region that this object belongs to. - BOOL mDead; - BOOL mOrphaned; // This is an orphaned child - BOOL mUserSelected; // Cached user select information - BOOL mOnActiveList; - BOOL mOnMap; // On the map. - BOOL mStatic; // Object doesn't move. - S32 mSeatCount; - S32 mNumFaces; - - F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) - LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations - LLQuaternion mPreviousRotation; - - U8 mAttachmentState; // this encodes the attachment id in a somewhat complex way. 0 if not an attachment. - LLViewerObjectMedia* mMedia; // NULL if no media associated - U8 mClickAction; - F32 mObjectCost; //resource cost of this object or -1 if unknown - F32 mLinksetCost; - F32 mPhysicsCost; - F32 mLinksetPhysicsCost; - + typedef std::map name_value_map_t; + name_value_map_t mNameValuePairs; // Any name-value pairs stored by script + + child_list_t mChildList; + + F64Seconds mLastInterpUpdateSecs; // Last update for purposes of interpolation + F64Seconds mLastMessageUpdateSecs; // Last update from a message from the simulator + TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator + F64SecondsImplicit mRegionCrossExpire; // frame time we detected region crossing in + wait time + + // extra data sent from the sim...currently only used for tree species info + U8* mData; + + LLPointer mPartSourcep; // Particle source associated with this object. + LLAudioSourceVO* mAudioSourcep; + F32 mAudioGain; + F32 mSoundCutOffRadius; + + F32 mAppAngle; // Apparent visual arc in degrees + F32 mPixelArea; // Apparent area in pixels + + // IDs of of all items in the object's content which are added to the object's content, + // but not updated on the server yet. After item was updated, its ID will be removed from this list. + std::list mPendingInventoryItemsIDs; + + // This is the object's inventory from the viewer's perspective. + LLInventoryObject::object_list_t* mInventory; + class LLInventoryCallbackInfo + { + public: + ~LLInventoryCallbackInfo(); + LLVOInventoryListener* mListener; + void* mInventoryData; + }; + typedef std::list callback_list_t; + callback_list_t mInventoryCallbacks; + S16 mInventorySerialNum; + S16 mExpectedInventorySerialNum; + + enum EInventoryRequestState + { + INVENTORY_REQUEST_STOPPED, + INVENTORY_REQUEST_WAIT, // delay before requesting + INVENTORY_REQUEST_PENDING, // just did fetchInventoryFromServer() + INVENTORY_XFER // processed response from 'fetch', now doing an xfer + }; + EInventoryRequestState mInvRequestState; + U64 mInvRequestXFerId; + BOOL mInventoryDirty; + + LLViewerRegion *mRegionp; // Region that this object belongs to. + BOOL mDead; + BOOL mOrphaned; // This is an orphaned child + BOOL mUserSelected; // Cached user select information + BOOL mOnActiveList; + BOOL mOnMap; // On the map. + BOOL mStatic; // Object doesn't move. + S32 mSeatCount; + S32 mNumFaces; + + F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) + LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations + LLQuaternion mPreviousRotation; + + U8 mAttachmentState; // this encodes the attachment id in a somewhat complex way. 0 if not an attachment. + LLViewerObjectMedia* mMedia; // NULL if no media associated + U8 mClickAction; + F32 mObjectCost; //resource cost of this object or -1 if unknown + F32 mLinksetCost; + F32 mPhysicsCost; + F32 mLinksetPhysicsCost; + // If true, "shrink wrap" this volume in its spatial partition. See "shrinkWrap" bool mShouldShrinkWrap = false; - bool mCostStale; - mutable bool mPhysicsShapeUnknown; + bool mCostStale; + mutable bool mPhysicsShapeUnknown; - static U32 sNumZombieObjects; // Objects which are dead, but not deleted + static U32 sNumZombieObjects; // Objects which are dead, but not deleted - static BOOL sMapDebug; // Map render mode - static LLColor4 sEditSelectColor; - static LLColor4 sNoEditSelectColor; - static F32 sCurrentPulse; - static BOOL sPulseEnabled; + static BOOL sMapDebug; // Map render mode + static LLColor4 sEditSelectColor; + static LLColor4 sNoEditSelectColor; + static F32 sCurrentPulse; + static BOOL sPulseEnabled; - static S32 sAxisArrowLength; + static S32 sAxisArrowLength; - // These two caches are only correct for non-parented objects right now! - mutable LLVector3 mPositionRegion; - mutable LLVector3 mPositionAgent; + // These two caches are only correct for non-parented objects right now! + mutable LLVector3 mPositionRegion; + mutable LLVector3 mPositionAgent; - static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64Seconds) value; } - static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64Seconds) value; } - static void setMaxRegionCrossingInterpolationTime(F32 value) { sMaxRegionCrossingInterpolationTime = (F64Seconds) value; } + static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64Seconds) value; } + static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64Seconds) value; } + static void setMaxRegionCrossingInterpolationTime(F32 value) { sMaxRegionCrossingInterpolationTime = (F64Seconds) value; } - static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } - static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } + static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } + static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } -private: - static S32 sNumObjects; +private: + static S32 sNumObjects; - static F64Seconds sPhaseOutUpdateInterpolationTime; // For motion interpolation - static F64Seconds sMaxUpdateInterpolationTime; // For motion interpolation - static F64Seconds sMaxRegionCrossingInterpolationTime; // For motion interpolation + static F64Seconds sPhaseOutUpdateInterpolationTime; // For motion interpolation + static F64Seconds sMaxUpdateInterpolationTime; // For motion interpolation + static F64Seconds sMaxRegionCrossingInterpolationTime; // For motion interpolation - static BOOL sVelocityInterpolate; - static BOOL sPingInterpolate; + static BOOL sVelocityInterpolate; + static BOOL sPingInterpolate; - bool mCachedOwnerInMuteList; - F64 mCachedMuteListUpdateTime; + bool mCachedOwnerInMuteList; + F64 mCachedMuteListUpdateTime; - //-------------------------------------------------------------------- - // For objects that are attachments - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // For objects that are attachments + //-------------------------------------------------------------------- public: - const LLUUID &getAttachmentItemID() const; - void setAttachmentItemID(const LLUUID &id); - const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object - EObjectUpdateType getLastUpdateType() const; - void setLastUpdateType(EObjectUpdateType last_update_type); - BOOL getLastUpdateCached() const; - void setLastUpdateCached(BOOL last_update_cached); + const LLUUID &getAttachmentItemID() const; + void setAttachmentItemID(const LLUUID &id); + const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object + EObjectUpdateType getLastUpdateType() const; + void setLastUpdateType(EObjectUpdateType last_update_type); + BOOL getLastUpdateCached() const; + void setLastUpdateCached(BOOL last_update_cached); virtual void updateRiggingInfo() {} LLJointRiggingInfoTab mJointRiggingInfoTab; private: - LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. - EObjectUpdateType mLastUpdateType; - BOOL mLastUpdateCached; + LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. + EObjectUpdateType mLastUpdateType; + BOOL mLastUpdateCached; public: // reflection probe state @@ -974,58 +974,58 @@ public: inline void LLViewerObject::setRotation(const LLQuaternion& quat, BOOL damped) { - LLPrimitive::setRotation(quat); - setChanged(ROTATED | SILHOUETTE); - updateDrawable(damped); + LLPrimitive::setRotation(quat); + setChanged(ROTATED | SILHOUETTE); + updateDrawable(damped); } inline void LLViewerObject::setRotation(const F32 x, const F32 y, const F32 z, BOOL damped) { - LLPrimitive::setRotation(x, y, z); - setChanged(ROTATED | SILHOUETTE); - updateDrawable(damped); + LLPrimitive::setRotation(x, y, z); + setChanged(ROTATED | SILHOUETTE); + updateDrawable(damped); } class LLViewerObjectMedia { public: - LLViewerObjectMedia() : mMediaURL(), mPassedWhitelist(FALSE), mMediaType(0) { } + LLViewerObjectMedia() : mMediaURL(), mPassedWhitelist(FALSE), mMediaType(0) { } - std::string mMediaURL; // for web pages on surfaces, one per prim - BOOL mPassedWhitelist; // user has OK'd display - U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc. + std::string mMediaURL; // for web pages on surfaces, one per prim + BOOL mPassedWhitelist; // user has OK'd display + U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc. }; // subclass of viewer object that can be added to particle partitions class LLAlphaObject : public LLViewerObject { public: - LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id,pcode,regionp) - { mDepth = 0.f; } - - virtual F32 getPartSize(S32 idx); - virtual void getGeometry(S32 idx, - LLStrider& verticesp, - LLStrider& normalsp, - LLStrider& texcoordsp, - LLStrider& colorsp, - LLStrider& emissivep, - LLStrider& indicesp) = 0; - - virtual void getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst); - - F32 mDepth; + LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) + : LLViewerObject(id,pcode,regionp) + { mDepth = 0.f; } + + virtual F32 getPartSize(S32 idx); + virtual void getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& emissivep, + LLStrider& indicesp) = 0; + + virtual void getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender::eBlendFactor& dst); + + F32 mDepth; }; class LLStaticViewerObject : public LLViewerObject { public: - LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE) - : LLViewerObject(id,pcode,regionp, is_global) - { } + LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE) + : LLViewerObject(id,pcode,regionp, is_global) + { } - virtual void updateDrawable(BOOL force_damped); + virtual void updateDrawable(BOOL force_damped); }; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 61ab2791fb..0231442316 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerregion.cpp * @brief Implementation of the LLViewerRegion class. * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010-2013, 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$ */ @@ -31,7 +31,7 @@ // linden libraries #include "indra_constants.h" #include "llaisapi.h" -#include "llavatarnamecache.h" // name lookup cap url +#include "llavatarnamecache.h" // name lookup cap url #include "llfloaterreg.h" #include "llmath.h" #include "llregionflags.h" @@ -86,11 +86,11 @@ #include #ifdef LL_WINDOWS - #pragma warning(disable:4355) + #pragma warning(disable:4355) #endif -// When we receive a base grant of capabilities that has a different number of -// capabilities than the original base grant received for the region, print +// When we receive a base grant of capabilities that has a different number of +// capabilities than the original base grant received for the region, print // out the two lists of capabilities for analysis. //#define DEBUG_CAPS_GRANTS @@ -144,25 +144,25 @@ public: { return false; } - + // build a secondlife://{PLACE} SLurl from this SLapp std::string url = "secondlife://"; if (!grid.empty()) { url += grid + "/secondlife/"; } - boost::regex name_rx("[A-Za-z0-9()_%]+"); - boost::regex coord_rx("[0-9]+"); + boost::regex name_rx("[A-Za-z0-9()_%]+"); + boost::regex coord_rx("[0-9]+"); for (int i = 0; i < num_params; i++) { if (i > 0) { url += "/"; } - if (!boost::regex_match(params[i].asString(), i > 0 ? coord_rx : name_rx)) - { - return false; - } + if (!boost::regex_match(params[i].asString(), i > 0 ? coord_rx : name_rx)) + { + return false; + } url += params[i].asString(); } @@ -171,15 +171,15 @@ public: LLURLDispatcher::dispatch(url, LLCommandHandler::NAV_TYPE_CLICKED, web, true); return true; } - + }; LLRegionHandler gRegionHandler; -class LLViewerRegionImpl +class LLViewerRegionImpl { public: - LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host): + LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host): mHost(host), mCompositionp(NULL), mEventPoll(NULL), @@ -190,62 +190,62 @@ public: mLastCameraOrigin(), mVOCachePartition(NULL), mLandp(NULL) - {} + {} - static void buildCapabilityNames(LLSD& capabilityNames); + static void buildCapabilityNames(LLSD& capabilityNames); - // The surfaces and other layers - LLSurface* mLandp; + // The surfaces and other layers + LLSurface* mLandp; - // Region geometry data - LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) - LLVector3d mCenterGlobal; // Location of center in world space (meters) - LLHost mHost; + // Region geometry data + LLVector3d mOriginGlobal; // Location of southwest corner of region (meters) + LLVector3d mCenterGlobal; // Location of center in world space (meters) + LLHost mHost; - // The unique ID for this region. - LLUUID mRegionID; + // The unique ID for this region. + LLUUID mRegionID; - // region/estate owner - usually null. - LLUUID mOwnerID; + // region/estate owner - usually null. + LLUUID mOwnerID; - // Network statistics for the region's circuit... - LLTimer mLastNetUpdate; + // Network statistics for the region's circuit... + LLTimer mLastNetUpdate; - // Misc - LLVLComposition *mCompositionp; // Composition layer for the surface + // Misc + LLVLComposition *mCompositionp; // Composition layer for the surface - LLVOCacheEntry::vocache_entry_map_t mCacheMap; //all cached entries - LLVOCacheEntry::vocache_entry_set_t mActiveSet; //all active entries; - LLVOCacheEntry::vocache_entry_set_t mWaitingSet; //entries waiting for LLDrawable to be generated. - std::set< LLPointer > mVisibleGroups; //visible groupa - LLVOCachePartition* mVOCachePartition; - LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation. - LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation. - std::set mNonCacheableCreatedList; //list of local ids of all non-cacheable objects + LLVOCacheEntry::vocache_entry_map_t mCacheMap; //all cached entries + LLVOCacheEntry::vocache_entry_set_t mActiveSet; //all active entries; + LLVOCacheEntry::vocache_entry_set_t mWaitingSet; //entries waiting for LLDrawable to be generated. + std::set< LLPointer > mVisibleGroups; //visible groupa + LLVOCachePartition* mVOCachePartition; + LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation. + LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation. + std::set mNonCacheableCreatedList; //list of local ids of all non-cacheable objects LLVOCacheEntry::vocache_gltf_overrides_map_t mGLTFOverridesLLSD; // for materials - // time? - // LRU info? + // time? + // LRU info? - // Cache ID is unique per-region, across renames, moving locations, - // etc. - LLUUID mCacheID; + // Cache ID is unique per-region, across renames, moving locations, + // etc. + LLUUID mCacheID; - CapabilityMap mCapabilities; - CapabilityMap mSecondCapabilitiesTracker; + CapabilityMap mCapabilities; + CapabilityMap mSecondCapabilitiesTracker; - LLEventPoll* mEventPoll; + LLEventPoll* mEventPoll; - S32 mSeedCapMaxAttempts; - S32 mSeedCapAttempts; + S32 mSeedCapMaxAttempts; + S32 mSeedCapAttempts; - S32 mHttpResponderID; + S32 mHttpResponderID; - //spatial partitions for objects in this region - std::vector mObjectPartition; + //spatial partitions for objects in this region + std::vector mObjectPartition; - LLVector3 mLastCameraOrigin; - U32 mLastCameraUpdate; + LLVector3 mLastCameraOrigin; + U32 mLastCameraUpdate; static void requestBaseCapabilitiesCoro(U64 regionHandle); static void requestBaseCapabilitiesCompleteCoro(U64 regionHandle); @@ -255,7 +255,7 @@ public: void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("BaseCapabilitiesRequest", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); @@ -284,7 +284,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) return; // this error condition is not recoverable. } LLViewerRegionImpl* impl = regionp->getRegionImplNC(); - LL_DEBUGS("AppInit", "Capabilities") << "requesting seed caps for handle " << regionHandle + LL_DEBUGS("AppInit", "Capabilities") << "requesting seed caps for handle " << regionHandle << " name " << regionp->getName() << LL_ENDL; std::string url = regionp->getCapability("Seed"); @@ -310,12 +310,12 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) LLSD capabilityNames = LLSD::emptyArray(); impl->buildCapabilityNames(capabilityNames); - LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url + LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url << " region name " << regionp->getName() << " region id " << regionp->getRegionID() << " handle " << regionp->getHandle() << " (attempt #" << impl->mSeedCapAttempts + 1 << ")" << LL_ENDL; - LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL; + LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL; regionp = NULL; impl = NULL; @@ -389,12 +389,12 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) log_capabilities(mCapabilities); #endif - LL_DEBUGS("AppInit", "Capabilities", "Teleport") << "received caps for handle " << regionHandle - << " region name " << regionp->getName() << LL_ENDL; + LL_DEBUGS("AppInit", "Capabilities", "Teleport") << "received caps for handle " << regionHandle + << " region name " << regionp->getName() << LL_ENDL; regionp->setCapabilitiesReceived(true); break; - } + } while (true); if (regionp && regionp->isCapabilityAvailable("ServerReleaseNotes") && @@ -535,7 +535,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle) LL_DEBUGS("CrossingCaps") << "Sim sent multiple base cap grants with matching sizes." << LL_ENDL; } impl->mSecondCapabilitiesTracker.clear(); - } + } while (false); } @@ -555,7 +555,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region if (attemptNumber > MAX_CAP_REQUEST_ATTEMPTS) { - LL_WARNS("AppInit", "SimulatorFeatures") << "Retries count exceeded attempting to get Simulator feature from " + LL_WARNS("AppInit", "SimulatorFeatures") << "Retries count exceeded attempting to get Simulator feature from " << url << LL_ENDL; break; } @@ -583,7 +583,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region if (!status) { LL_WARNS("AppInit", "SimulatorFeatures") << "HttpStatus error retrying" << LL_ENDL; - continue; + continue; } if (LLApp::isExiting() || gDisconnected) @@ -617,218 +617,218 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region } LLViewerRegion::LLViewerRegion(const U64 &handle, - const LLHost &host, - const U32 grids_per_region_edge, - const U32 grids_per_patch_edge, - const F32 region_width_meters) -: mImpl(new LLViewerRegionImpl(this, host)), - mHandle(handle), - mTimeDilation(1.0f), - mName(""), - mZoning(""), - mIsEstateManager(FALSE), - mRegionFlags( REGION_FLAGS_DEFAULT ), - mRegionProtocols( 0 ), - mSimAccess( SIM_ACCESS_MIN ), - mBillableFactor(1.0), - mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), - mCentralBakeVersion(1), - mClassID(0), - mCPURatio(0), - mColoName("unknown"), - mProductSKU("unknown"), - mProductName("unknown"), - mViewerAssetUrl(""), - mCacheLoaded(FALSE), - mCacheDirty(FALSE), - mReleaseNotesRequested(FALSE), - mCapabilitiesState(CAPABILITIES_STATE_INIT), - mSimulatorFeaturesReceived(false), - mBitsReceived(0.f), - mPacketsReceived(0.f), - mDead(FALSE), - mLastVisitedEntry(NULL), - mInvisibilityCheckHistory(-1), - mPaused(FALSE), - mRegionCacheHitCount(0), - mRegionCacheMissCount(0), + const LLHost &host, + const U32 grids_per_region_edge, + const U32 grids_per_patch_edge, + const F32 region_width_meters) +: mImpl(new LLViewerRegionImpl(this, host)), + mHandle(handle), + mTimeDilation(1.0f), + mName(""), + mZoning(""), + mIsEstateManager(FALSE), + mRegionFlags( REGION_FLAGS_DEFAULT ), + mRegionProtocols( 0 ), + mSimAccess( SIM_ACCESS_MIN ), + mBillableFactor(1.0), + mMaxTasks(DEFAULT_MAX_REGION_WIDE_PRIM_COUNT), + mCentralBakeVersion(1), + mClassID(0), + mCPURatio(0), + mColoName("unknown"), + mProductSKU("unknown"), + mProductName("unknown"), + mViewerAssetUrl(""), + mCacheLoaded(FALSE), + mCacheDirty(FALSE), + mReleaseNotesRequested(FALSE), + mCapabilitiesState(CAPABILITIES_STATE_INIT), + mSimulatorFeaturesReceived(false), + mBitsReceived(0.f), + mPacketsReceived(0.f), + mDead(FALSE), + mLastVisitedEntry(NULL), + mInvisibilityCheckHistory(-1), + mPaused(FALSE), + mRegionCacheHitCount(0), + mRegionCacheMissCount(0), mInterestListMode(IL_MODE_DEFAULT) { - mWidth = region_width_meters; - mImpl->mOriginGlobal = from_region_handle(handle); - updateRenderMatrix(); + mWidth = region_width_meters; + mImpl->mOriginGlobal = from_region_handle(handle); + updateRenderMatrix(); - mImpl->mLandp = new LLSurface('l', NULL); + mImpl->mLandp = new LLSurface('l', NULL); - // Create the composition layer for the surface - mImpl->mCompositionp = - new LLVLComposition(mImpl->mLandp, - grids_per_region_edge, - region_width_meters / grids_per_region_edge); - mImpl->mCompositionp->setSurface(mImpl->mLandp); + // Create the composition layer for the surface + mImpl->mCompositionp = + new LLVLComposition(mImpl->mLandp, + grids_per_region_edge, + region_width_meters / grids_per_region_edge); + mImpl->mCompositionp->setSurface(mImpl->mLandp); - // Create the surfaces - mImpl->mLandp->setRegion(this); - mImpl->mLandp->create(grids_per_region_edge, - grids_per_patch_edge, - mImpl->mOriginGlobal, - mWidth); + // Create the surfaces + mImpl->mLandp->setRegion(this); + mImpl->mLandp->create(grids_per_region_edge, + grids_per_patch_edge, + mImpl->mOriginGlobal, + mWidth); - mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); + mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); - setOriginGlobal(from_region_handle(handle)); - calculateCenterGlobal(); + setOriginGlobal(from_region_handle(handle)); + calculateCenterGlobal(); - // Create the object lists - initStats(); + // Create the object lists + initStats(); - //create object partitions - //MUST MATCH declaration of eObjectPartitions - mImpl->mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD - mImpl->mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN - mImpl->mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER - mImpl->mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER - mImpl->mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE - mImpl->mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE - mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLAvatarPartition(this)); //PARTITION_AVATAR - mImpl->mObjectPartition.push_back(new LLControlAVPartition(this)); //PARTITION_CONTROL_AV - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE - mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE - mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE - mImpl->mVOCachePartition = getVOCachePartition(); + //create object partitions + //MUST MATCH declaration of eObjectPartitions + mImpl->mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD + mImpl->mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN + mImpl->mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER + mImpl->mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER + mImpl->mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE + mImpl->mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE + mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS + mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME + mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE + mImpl->mObjectPartition.push_back(new LLAvatarPartition(this)); //PARTITION_AVATAR + mImpl->mObjectPartition.push_back(new LLControlAVPartition(this)); //PARTITION_CONTROL_AV + mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE + mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE + mImpl->mVOCachePartition = getVOCachePartition(); - setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::scanNewRegion, _1)); + setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::scanNewRegion, _1)); } void LLViewerRegion::initStats() { - mImpl->mLastNetUpdate.reset(); - mPacketsIn = 0; - mBitsIn = (U32Bits)0; - mLastBitsIn = (U32Bits)0; - mLastPacketsIn = 0; - mPacketsOut = 0; - mLastPacketsOut = 0; - mPacketsLost = 0; - mLastPacketsLost = 0; - mPingDelay = (U32Seconds)0; - mAlive = false; // can become false if circuit disconnects + mImpl->mLastNetUpdate.reset(); + mPacketsIn = 0; + mBitsIn = (U32Bits)0; + mLastBitsIn = (U32Bits)0; + mLastPacketsIn = 0; + mPacketsOut = 0; + mLastPacketsOut = 0; + mPacketsLost = 0; + mLastPacketsLost = 0; + mPingDelay = (U32Seconds)0; + mAlive = false; // can become false if circuit disconnects } static LLTrace::BlockTimerStatHandle FTM_CLEANUP_REGION_OBJECTS("Cleanup Region Objects"); static LLTrace::BlockTimerStatHandle FTM_SAVE_REGION_CACHE("Save Region Cache"); -LLViewerRegion::~LLViewerRegion() +LLViewerRegion::~LLViewerRegion() { LL_PROFILE_ZONE_SCOPED; - mDead = TRUE; - mImpl->mActiveSet.clear(); - mImpl->mVisibleEntries.clear(); - mImpl->mVisibleGroups.clear(); - mImpl->mWaitingSet.clear(); - - gVLManager.cleanupData(this); - // Can't do this on destruction, because the neighbor pointers might be invalid. - // This should be reference counted... - disconnectAllNeighbors(); - LLViewerPartSim::getInstance()->cleanupRegion(this); + mDead = TRUE; + mImpl->mActiveSet.clear(); + mImpl->mVisibleEntries.clear(); + mImpl->mVisibleGroups.clear(); + mImpl->mWaitingSet.clear(); + + gVLManager.cleanupData(this); + // Can't do this on destruction, because the neighbor pointers might be invalid. + // This should be reference counted... + disconnectAllNeighbors(); + LLViewerPartSim::getInstance()->cleanupRegion(this); { LL_RECORD_BLOCK_TIME(FTM_CLEANUP_REGION_OBJECTS); gObjectList.killObjects(this); } - delete mImpl->mCompositionp; - delete mParcelOverlay; - delete mImpl->mLandp; - delete mImpl->mEventPoll; + delete mImpl->mCompositionp; + delete mParcelOverlay; + delete mImpl->mLandp; + delete mImpl->mEventPoll; #if 0 - LLHTTPSender::clearSender(mImpl->mHost); -#endif - std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); + LLHTTPSender::clearSender(mImpl->mHost); +#endif + std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); { LL_RECORD_BLOCK_TIME(FTM_SAVE_REGION_CACHE); saveObjectCache(); } - delete mImpl; - mImpl = NULL; + delete mImpl; + mImpl = NULL; } -/*virtual*/ -const LLHost& LLViewerRegion::getHost() const -{ - return mImpl->mHost; +/*virtual*/ +const LLHost& LLViewerRegion::getHost() const +{ + return mImpl->mHost; } LLSurface & LLViewerRegion::getLand() const { - return *mImpl->mLandp; + return *mImpl->mLandp; } const LLUUID& LLViewerRegion::getRegionID() const { - return mImpl->mRegionID; + return mImpl->mRegionID; } void LLViewerRegion::setRegionID(const LLUUID& region_id) { - mImpl->mRegionID = region_id; + mImpl->mRegionID = region_id; } void LLViewerRegion::loadObjectCache() { - if (mCacheLoaded) - { - return; - } + if (mCacheLoaded) + { + return; + } - // Presume success. If it fails, we don't want to try again. - mCacheLoaded = TRUE; + // Presume success. If it fails, we don't want to try again. + mCacheLoaded = TRUE; - if(LLVOCache::instanceExists()) - { + if(LLVOCache::instanceExists()) + { LLVOCache & vocache = LLVOCache::instance(); - // Without this a "corrupted" vocache persists until a cache clear or other rewrite. Mark as dirty hereif read fails to force a rewrite. - mCacheDirty = !vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); - vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mImpl->mCacheMap); + // Without this a "corrupted" vocache persists until a cache clear or other rewrite. Mark as dirty hereif read fails to force a rewrite. + mCacheDirty = !vocache.readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap); + vocache.readGenericExtrasFromCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mImpl->mCacheMap); - if (mImpl->mCacheMap.empty()) - { - mCacheDirty = TRUE; - } - } + if (mImpl->mCacheMap.empty()) + { + mCacheDirty = TRUE; + } + } } void LLViewerRegion::saveObjectCache() { - if (!mCacheLoaded) - { - return; - } + if (!mCacheLoaded) + { + return; + } - if (mImpl->mCacheMap.empty()) - { - return; - } + if (mImpl->mCacheMap.empty()) + { + return; + } - if(LLVOCache::instanceExists()) - { - const F32 start_time_threshold = 600.0f; //seconds - bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file. + if(LLVOCache::instanceExists()) + { + const F32 start_time_threshold = 600.0f; //seconds + bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file. LLVOCache & instance = LLVOCache::instance(); instance.writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled); instance.writeGenericExtrasToCache(mHandle, mImpl->mCacheID, mImpl->mGLTFOverridesLLSD, mCacheDirty, removal_enabled); - mCacheDirty = FALSE; - } + mCacheDirty = FALSE; + } if (LLAppViewer::instance()->isQuitting()) { @@ -845,253 +845,253 @@ void LLViewerRegion::saveObjectCache() void LLViewerRegion::sendMessage() { - gMessageSystem->sendMessage(mImpl->mHost); + gMessageSystem->sendMessage(mImpl->mHost); } void LLViewerRegion::sendReliableMessage() { - gMessageSystem->sendReliable(mImpl->mHost); + gMessageSystem->sendReliable(mImpl->mHost); } void LLViewerRegion::setWaterHeight(F32 water_level) { - mImpl->mLandp->setWaterHeight(water_level); + mImpl->mLandp->setWaterHeight(water_level); } F32 LLViewerRegion::getWaterHeight() const { - return mImpl->mLandp->getWaterHeight(); + return mImpl->mLandp->getWaterHeight(); } BOOL LLViewerRegion::isVoiceEnabled() const { - return getRegionFlag(REGION_FLAGS_ALLOW_VOICE); + return getRegionFlag(REGION_FLAGS_ALLOW_VOICE); } void LLViewerRegion::setRegionFlags(U64 flags) { - mRegionFlags = flags; + mRegionFlags = flags; } -void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) -{ - mImpl->mOriginGlobal = origin_global; - updateRenderMatrix(); - mImpl->mLandp->setOriginGlobal(origin_global); - mWind.setOriginGlobal(origin_global); - calculateCenterGlobal(); +void LLViewerRegion::setOriginGlobal(const LLVector3d &origin_global) +{ + mImpl->mOriginGlobal = origin_global; + updateRenderMatrix(); + mImpl->mLandp->setOriginGlobal(origin_global); + mWind.setOriginGlobal(origin_global); + calculateCenterGlobal(); } void LLViewerRegion::updateRenderMatrix() { - mRenderMatrix.setTranslation(getOriginAgent()); + mRenderMatrix.setTranslation(getOriginAgent()); } void LLViewerRegion::setTimeDilation(F32 time_dilation) { - mTimeDilation = time_dilation; + mTimeDilation = time_dilation; } const LLVector3d & LLViewerRegion::getOriginGlobal() const { - return mImpl->mOriginGlobal; + return mImpl->mOriginGlobal; } LLVector3 LLViewerRegion::getOriginAgent() const { - return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); + return gAgent.getPosAgentFromGlobal(mImpl->mOriginGlobal); } const LLVector3d & LLViewerRegion::getCenterGlobal() const { - return mImpl->mCenterGlobal; + return mImpl->mCenterGlobal; } LLVector3 LLViewerRegion::getCenterAgent() const { - return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); + return gAgent.getPosAgentFromGlobal(mImpl->mCenterGlobal); } void LLViewerRegion::setOwner(const LLUUID& owner_id) { - mImpl->mOwnerID = owner_id; + mImpl->mOwnerID = owner_id; } const LLUUID& LLViewerRegion::getOwner() const { - return mImpl->mOwnerID; + return mImpl->mOwnerID; } -void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) +void LLViewerRegion::setRegionNameAndZone (const std::string& name_zone) { - std::string::size_type pipe_pos = name_zone.find('|'); - S32 length = name_zone.size(); - if (pipe_pos != std::string::npos) - { - mName = name_zone.substr(0, pipe_pos); - mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); - } - else - { - mName = name_zone; - mZoning = ""; - } + std::string::size_type pipe_pos = name_zone.find('|'); + S32 length = name_zone.size(); + if (pipe_pos != std::string::npos) + { + mName = name_zone.substr(0, pipe_pos); + mZoning = name_zone.substr(pipe_pos+1, length-(pipe_pos+1)); + } + else + { + mName = name_zone; + mZoning = ""; + } - LLStringUtil::stripNonprintable(mName); - LLStringUtil::stripNonprintable(mZoning); + LLStringUtil::stripNonprintable(mName); + LLStringUtil::stripNonprintable(mZoning); } BOOL LLViewerRegion::canManageEstate() const { - return gAgent.isGodlike() - || isEstateManager() - || gAgent.getID() == getOwner(); + return gAgent.isGodlike() + || isEstateManager() + || gAgent.getID() == getOwner(); } const std::string LLViewerRegion::getSimAccessString() const { - return accessToString(mSimAccess); + return accessToString(mSimAccess); } std::string LLViewerRegion::getLocalizedSimProductName() const { - std::string localized_spn; - return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; + std::string localized_spn; + return LLTrans::findString(localized_spn, mProductName) ? localized_spn : mProductName; } // static std::string LLViewerRegion::regionFlagsToString(U64 flags) { - std::string result; + std::string result; - if (flags & REGION_FLAGS_SANDBOX) - { - result += "Sandbox"; - } + if (flags & REGION_FLAGS_SANDBOX) + { + result += "Sandbox"; + } - if (flags & REGION_FLAGS_ALLOW_DAMAGE) - { - result += " Not Safe"; - } + if (flags & REGION_FLAGS_ALLOW_DAMAGE) + { + result += " Not Safe"; + } - return result; + return result; } // static std::string LLViewerRegion::accessToString(U8 sim_access) { - switch(sim_access) - { - case SIM_ACCESS_PG: - return LLTrans::getString("SIM_ACCESS_PG"); + switch(sim_access) + { + case SIM_ACCESS_PG: + return LLTrans::getString("SIM_ACCESS_PG"); - case SIM_ACCESS_MATURE: - return LLTrans::getString("SIM_ACCESS_MATURE"); + case SIM_ACCESS_MATURE: + return LLTrans::getString("SIM_ACCESS_MATURE"); - case SIM_ACCESS_ADULT: - return LLTrans::getString("SIM_ACCESS_ADULT"); + case SIM_ACCESS_ADULT: + return LLTrans::getString("SIM_ACCESS_ADULT"); - case SIM_ACCESS_DOWN: - return LLTrans::getString("SIM_ACCESS_DOWN"); + case SIM_ACCESS_DOWN: + return LLTrans::getString("SIM_ACCESS_DOWN"); - case SIM_ACCESS_MIN: - default: - return LLTrans::getString("SIM_ACCESS_MIN"); - } + case SIM_ACCESS_MIN: + default: + return LLTrans::getString("SIM_ACCESS_MIN"); + } } // static std::string LLViewerRegion::getAccessIcon(U8 sim_access) { - switch(sim_access) - { - case SIM_ACCESS_MATURE: - return "Parcel_M_Dark"; + switch(sim_access) + { + case SIM_ACCESS_MATURE: + return "Parcel_M_Dark"; - case SIM_ACCESS_ADULT: - return "Parcel_R_Light"; + case SIM_ACCESS_ADULT: + return "Parcel_R_Light"; - case SIM_ACCESS_PG: - return "Parcel_PG_Light"; + case SIM_ACCESS_PG: + return "Parcel_PG_Light"; - case SIM_ACCESS_MIN: - default: - return ""; - } + case SIM_ACCESS_MIN: + default: + return ""; + } } // static std::string LLViewerRegion::accessToShortString(U8 sim_access) { - switch(sim_access) /* Flawfinder: ignore */ - { - case SIM_ACCESS_PG: - return "PG"; + switch(sim_access) /* Flawfinder: ignore */ + { + case SIM_ACCESS_PG: + return "PG"; - case SIM_ACCESS_MATURE: - return "M"; + case SIM_ACCESS_MATURE: + return "M"; - case SIM_ACCESS_ADULT: - return "A"; + case SIM_ACCESS_ADULT: + return "A"; - case SIM_ACCESS_MIN: - default: - return "U"; - } + case SIM_ACCESS_MIN: + default: + return "U"; + } } // static U8 LLViewerRegion::shortStringToAccess(const std::string &sim_access) { - U8 accessValue; + U8 accessValue; - if (LLStringUtil::compareStrings(sim_access, "PG") == 0) - { - accessValue = SIM_ACCESS_PG; - } - else if (LLStringUtil::compareStrings(sim_access, "M") == 0) - { - accessValue = SIM_ACCESS_MATURE; - } - else if (LLStringUtil::compareStrings(sim_access, "A") == 0) - { - accessValue = SIM_ACCESS_ADULT; - } - else - { - accessValue = SIM_ACCESS_MIN; - } + if (LLStringUtil::compareStrings(sim_access, "PG") == 0) + { + accessValue = SIM_ACCESS_PG; + } + else if (LLStringUtil::compareStrings(sim_access, "M") == 0) + { + accessValue = SIM_ACCESS_MATURE; + } + else if (LLStringUtil::compareStrings(sim_access, "A") == 0) + { + accessValue = SIM_ACCESS_ADULT; + } + else + { + accessValue = SIM_ACCESS_MIN; + } - return accessValue; + return accessValue; } // static void LLViewerRegion::processRegionInfo(LLMessageSystem* msg, void**) { - // send it to 'observers' - // *TODO: switch the floaters to using LLRegionInfoModel - LL_INFOS() << "Processing region info" << LL_ENDL; - LLRegionInfoModel::instance().update(msg); - LLFloaterGodTools::processRegionInfo(msg); - LLFloaterRegionInfo::processRegionInfo(msg); + // send it to 'observers' + // *TODO: switch the floaters to using LLRegionInfoModel + LL_INFOS() << "Processing region info" << LL_ENDL; + LLRegionInfoModel::instance().update(msg); + LLFloaterGodTools::processRegionInfo(msg); + LLFloaterRegionInfo::processRegionInfo(msg); } void LLViewerRegion::setCacheID(const LLUUID& id) { - mImpl->mCacheID = id; + mImpl->mCacheID = id; } S32 LLViewerRegion::renderPropertyLines() { - if (mParcelOverlay) - { - return mParcelOverlay->renderPropertyLines(); - } - else - { - return 0; - } + if (mParcelOverlay) + { + return mParcelOverlay->renderPropertyLines(); + } + else + { + return 0; + } } void LLViewerRegion::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color) @@ -1106,11 +1106,11 @@ void LLViewerRegion::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, co // This gets called when the height field changes. void LLViewerRegion::dirtyHeights() { - // Property lines need to be reconstructed when the land changes. - if (mParcelOverlay) - { - mParcelOverlay->setDirty(); - } + // Property lines need to be reconstructed when the land changes. + if (mParcelOverlay) + { + mParcelOverlay->setDirty(); + } } void LLViewerRegion::dirtyAllPatches() @@ -1120,159 +1120,159 @@ void LLViewerRegion::dirtyAllPatches() //physically delete the cache entry void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry, bool for_rendering) -{ - if(!entry || !entry->isValid()) - { - return; - } - - if(for_rendering && !entry->isState(LLVOCacheEntry::ACTIVE)) - { - addNewObject(entry); //force to add to rendering pipeline - } - - //remove from active list and waiting list - if(entry->isState(LLVOCacheEntry::ACTIVE)) - { - mImpl->mActiveSet.erase(entry); - } - else - { - if(entry->isState(LLVOCacheEntry::WAITING)) - { - mImpl->mWaitingSet.erase(entry); - } - - //remove from mVOCachePartition - removeFromVOCacheTree(entry); - } - - //remove from the forced visible list - mImpl->mVisibleEntries.erase(entry); - - //disconnect from parent if it is a child - if(entry->getParentID() > 0) - { - LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); - if(parent) - { - parent->removeChild(entry); - } - } - else if(entry->getNumOfChildren() > 0)//remove children from cache if has any - { - LLVOCacheEntry* child = entry->getChild(); - while(child != NULL) - { - killCacheEntry(child, for_rendering); - child = entry->getChild(); - } - } - // Kill the assocaited overrides - mImpl->mGLTFOverridesLLSD.erase(entry->getLocalID()); - //will remove it from the object cache, real deletion - entry->setState(LLVOCacheEntry::INACTIVE); - entry->removeOctreeEntry(); - entry->setValid(FALSE); - -} - -//physically delete the cache entry -void LLViewerRegion::killCacheEntry(U32 local_id) -{ - killCacheEntry(getCacheEntry(local_id)); +{ + if(!entry || !entry->isValid()) + { + return; + } + + if(for_rendering && !entry->isState(LLVOCacheEntry::ACTIVE)) + { + addNewObject(entry); //force to add to rendering pipeline + } + + //remove from active list and waiting list + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + mImpl->mActiveSet.erase(entry); + } + else + { + if(entry->isState(LLVOCacheEntry::WAITING)) + { + mImpl->mWaitingSet.erase(entry); + } + + //remove from mVOCachePartition + removeFromVOCacheTree(entry); + } + + //remove from the forced visible list + mImpl->mVisibleEntries.erase(entry); + + //disconnect from parent if it is a child + if(entry->getParentID() > 0) + { + LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); + if(parent) + { + parent->removeChild(entry); + } + } + else if(entry->getNumOfChildren() > 0)//remove children from cache if has any + { + LLVOCacheEntry* child = entry->getChild(); + while(child != NULL) + { + killCacheEntry(child, for_rendering); + child = entry->getChild(); + } + } + // Kill the assocaited overrides + mImpl->mGLTFOverridesLLSD.erase(entry->getLocalID()); + //will remove it from the object cache, real deletion + entry->setState(LLVOCacheEntry::INACTIVE); + entry->removeOctreeEntry(); + entry->setValid(FALSE); + +} + +//physically delete the cache entry +void LLViewerRegion::killCacheEntry(U32 local_id) +{ + killCacheEntry(getCacheEntry(local_id)); } U32 LLViewerRegion::getNumOfActiveCachedObjects() const { - return mImpl->mActiveSet.size(); + return mImpl->mActiveSet.size(); } void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry) { - if(!entry || mDead) - { - return; - } - if(entry->isState(LLVOCacheEntry::ACTIVE)) - { - return; //already inserted. - } + if(!entry || mDead) + { + return; + } + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + return; //already inserted. + } - if(entry->isState(LLVOCacheEntry::WAITING)) - { - mImpl->mWaitingSet.erase(entry); - } + if(entry->isState(LLVOCacheEntry::WAITING)) + { + mImpl->mWaitingSet.erase(entry); + } - entry->setState(LLVOCacheEntry::ACTIVE); - entry->setVisible(); + entry->setState(LLVOCacheEntry::ACTIVE); + entry->setVisible(); - llassert(entry->getEntry()->hasDrawable()); - mImpl->mActiveSet.insert(entry); + llassert(entry->getEntry()->hasDrawable()); + mImpl->mActiveSet.insert(entry); } void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep) { - if(mDead || !entry || !entry->isValid()) - { - return; - } - if(!entry->isState(LLVOCacheEntry::ACTIVE)) - { - return; //not an active entry. - } - - //shift to the local regional space from agent space - if(drawablep != NULL && drawablep->getVObj().notNull()) - { - const LLVector3& pos = drawablep->getVObj()->getPositionRegion(); - LLVector4a shift; - shift.load3(pos.mV); - shift.sub(entry->getPositionGroup()); - entry->shift(shift); - } - - if(entry->getParentID() > 0) //is a child - { - LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); - if(parent) - { - parent->addChild(entry); - } - else //parent not in cache. - { - //this happens only when parent is not cacheable. - mOrphanMap[entry->getParentID()].push_back(entry->getLocalID()); - } - } - else //insert to vo cache tree. - { - entry->updateParentBoundingInfo(); - entry->saveBoundingSphere(); - addToVOCacheTree(entry); - } - - mImpl->mVisibleEntries.erase(entry); - mImpl->mActiveSet.erase(entry); - mImpl->mWaitingSet.erase(entry); - entry->setState(LLVOCacheEntry::INACTIVE); + if(mDead || !entry || !entry->isValid()) + { + return; + } + if(!entry->isState(LLVOCacheEntry::ACTIVE)) + { + return; //not an active entry. + } + + //shift to the local regional space from agent space + if(drawablep != NULL && drawablep->getVObj().notNull()) + { + const LLVector3& pos = drawablep->getVObj()->getPositionRegion(); + LLVector4a shift; + shift.load3(pos.mV); + shift.sub(entry->getPositionGroup()); + entry->shift(shift); + } + + if(entry->getParentID() > 0) //is a child + { + LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); + if(parent) + { + parent->addChild(entry); + } + else //parent not in cache. + { + //this happens only when parent is not cacheable. + mOrphanMap[entry->getParentID()].push_back(entry->getLocalID()); + } + } + else //insert to vo cache tree. + { + entry->updateParentBoundingInfo(); + entry->saveBoundingSphere(); + addToVOCacheTree(entry); + } + + mImpl->mVisibleEntries.erase(entry); + mImpl->mActiveSet.erase(entry); + mImpl->mWaitingSet.erase(entry); + entry->setState(LLVOCacheEntry::INACTIVE); } bool LLViewerRegion::addVisibleGroup(LLViewerOctreeGroup* group) { - if(mDead || group->isEmpty()) - { - return false; - } - - mImpl->mVisibleGroups.insert(group); + if(mDead || group->isEmpty()) + { + return false; + } - return true; + mImpl->mVisibleGroups.insert(group); + + return true; } U32 LLViewerRegion::getNumOfVisibleGroups() const { - return mImpl ? mImpl->mVisibleGroups.size() : 0; + return mImpl ? mImpl->mVisibleGroups.size() : 0; } void LLViewerRegion::updateReflectionProbes() @@ -1317,306 +1317,306 @@ void LLViewerRegion::updateReflectionProbes() void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry) { - if(!sVOCacheCullingEnabled) - { - return; - } + if(!sVOCacheCullingEnabled) + { + return; + } - if(mDead || !entry || !entry->getEntry() || !entry->isValid()) - { - return; - } - if(entry->getParentID() > 0) - { - return; //no child prim in cache octree. - } + if(mDead || !entry || !entry->getEntry() || !entry->isValid()) + { + return; + } + if(entry->getParentID() > 0) + { + return; //no child prim in cache octree. + } - if(entry->hasState(LLVOCacheEntry::IN_VO_TREE)) - { - return; //already in the tree. - } + if(entry->hasState(LLVOCacheEntry::IN_VO_TREE)) + { + return; //already in the tree. + } - llassert_always(!entry->getGroup()); //not in octree. - llassert(!entry->getEntry()->hasDrawable()); //not have drawables + llassert_always(!entry->getGroup()); //not in octree. + llassert(!entry->getEntry()->hasDrawable()); //not have drawables - if(mImpl->mVOCachePartition->addEntry(entry->getEntry())) - { - entry->setState(LLVOCacheEntry::IN_VO_TREE); - } + if(mImpl->mVOCachePartition->addEntry(entry->getEntry())) + { + entry->setState(LLVOCacheEntry::IN_VO_TREE); + } } void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry) { - if(mDead || !entry || !entry->getEntry()) - { - return; - } - - if(!entry->hasState(LLVOCacheEntry::IN_VO_TREE)) - { - return; //not in the tree. - } - entry->clearState(LLVOCacheEntry::IN_VO_TREE); + if(mDead || !entry || !entry->getEntry()) + { + return; + } - mImpl->mVOCachePartition->removeEntry(entry->getEntry()); + if(!entry->hasState(LLVOCacheEntry::IN_VO_TREE)) + { + return; //not in the tree. + } + entry->clearState(LLVOCacheEntry::IN_VO_TREE); + + mImpl->mVOCachePartition->removeEntry(entry->getEntry()); } //add child objects as visible entries void LLViewerRegion::addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child) { - if(mDead) - { - return; - } - - if(parent && (!parent->isValid() || !parent->isState(LLVOCacheEntry::ACTIVE))) - { - return; //parent must be valid and in rendering pipeline - } - - if(child && (!child->getEntry() || !child->isValid() || !child->isState(LLVOCacheEntry::INACTIVE))) - { - return; //child must be valid and not in the rendering pipeline - } - - if(child) - { - child->setState(LLVOCacheEntry::IN_QUEUE); - mImpl->mVisibleEntries.insert(child); - } - else if(parent && parent->getNumOfChildren() > 0) //add all children - { - child = parent->getChild(); - while(child != NULL) - { - addVisibleChildCacheEntry(NULL, child); - child = parent->getChild(); - } - } + if(mDead) + { + return; + } + + if(parent && (!parent->isValid() || !parent->isState(LLVOCacheEntry::ACTIVE))) + { + return; //parent must be valid and in rendering pipeline + } + + if(child && (!child->getEntry() || !child->isValid() || !child->isState(LLVOCacheEntry::INACTIVE))) + { + return; //child must be valid and not in the rendering pipeline + } + + if(child) + { + child->setState(LLVOCacheEntry::IN_QUEUE); + mImpl->mVisibleEntries.insert(child); + } + else if(parent && parent->getNumOfChildren() > 0) //add all children + { + child = parent->getChild(); + while(child != NULL) + { + addVisibleChildCacheEntry(NULL, child); + child = parent->getChild(); + } + } } void LLViewerRegion::updateVisibleEntries(F32 max_time) { - if(mDead) - { - return; - } - - if(mImpl->mVisibleGroups.empty() && mImpl->mVisibleEntries.empty()) - { - return; - } - - if(!sNewObjectCreationThrottle) - { - return; - } - - const F32 LARGE_SCENE_CONTRIBUTION = 1000.f; //a large number to force to load the object. - const LLVector3 camera_origin = LLViewerCamera::getInstance()->getOrigin(); - const U32 cur_frame = LLViewerOctreeEntryData::getCurrentFrame(); - bool needs_update = ((cur_frame - mImpl->mLastCameraUpdate) > 5) && ((camera_origin - mImpl->mLastCameraOrigin).lengthSquared() > 10.f); - U32 last_update = mImpl->mLastCameraUpdate; - LLVector4a local_origin; - local_origin.load3((camera_origin - getOriginAgent()).mV); - - //process visible entries - for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) - { - LLVOCacheEntry* vo_entry = *iter; - - if(vo_entry->isValid() && vo_entry->getState() < LLVOCacheEntry::WAITING) - { - //set a large number to force to load this object. - vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION); - - mImpl->mWaitingList.insert(vo_entry); - ++iter; - } - else - { - LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter; - ++next_iter; - mImpl->mVisibleEntries.erase(iter); - iter = next_iter; - } - } - - // - //process visible groups - // - //object projected area threshold - F32 projection_threshold = LLVOCacheEntry::getSquaredPixelThreshold(mImpl->mVOCachePartition->isFrontCull()); - F32 dist_threshold = mImpl->mVOCachePartition->isFrontCull() ? gAgentCamera.mDrawDistance : LLVOCacheEntry::sRearFarRadius; - - std::set< LLPointer >::iterator group_iter = mImpl->mVisibleGroups.begin(); - for(; group_iter != mImpl->mVisibleGroups.end(); ++group_iter) - { - LLPointer group = *group_iter; - if(group->getNumRefs() < 3 || //group to be deleted - !group->getOctreeNode() || group->isEmpty()) //group empty - { - continue; - } - - for (LLViewerOctreeGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - if((*i)->hasVOCacheEntry()) - { - LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry(); - - if(vo_entry->getParentID() > 0) //is a child - { - //child visibility depends on its parent. - continue; - } - if(!vo_entry->isValid()) - { - continue; //skip invalid entry. - } - - vo_entry->calcSceneContribution(local_origin, needs_update, last_update, dist_threshold); - if(vo_entry->getSceneContribution() > projection_threshold) - { - mImpl->mWaitingList.insert(vo_entry); - } - } - } - } - - if(needs_update) - { - mImpl->mLastCameraOrigin = camera_origin; - mImpl->mLastCameraUpdate = cur_frame; - } - - return; + if(mDead) + { + return; + } + + if(mImpl->mVisibleGroups.empty() && mImpl->mVisibleEntries.empty()) + { + return; + } + + if(!sNewObjectCreationThrottle) + { + return; + } + + const F32 LARGE_SCENE_CONTRIBUTION = 1000.f; //a large number to force to load the object. + const LLVector3 camera_origin = LLViewerCamera::getInstance()->getOrigin(); + const U32 cur_frame = LLViewerOctreeEntryData::getCurrentFrame(); + bool needs_update = ((cur_frame - mImpl->mLastCameraUpdate) > 5) && ((camera_origin - mImpl->mLastCameraOrigin).lengthSquared() > 10.f); + U32 last_update = mImpl->mLastCameraUpdate; + LLVector4a local_origin; + local_origin.load3((camera_origin - getOriginAgent()).mV); + + //process visible entries + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) + { + LLVOCacheEntry* vo_entry = *iter; + + if(vo_entry->isValid() && vo_entry->getState() < LLVOCacheEntry::WAITING) + { + //set a large number to force to load this object. + vo_entry->setSceneContribution(LARGE_SCENE_CONTRIBUTION); + + mImpl->mWaitingList.insert(vo_entry); + ++iter; + } + else + { + LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter; + ++next_iter; + mImpl->mVisibleEntries.erase(iter); + iter = next_iter; + } + } + + // + //process visible groups + // + //object projected area threshold + F32 projection_threshold = LLVOCacheEntry::getSquaredPixelThreshold(mImpl->mVOCachePartition->isFrontCull()); + F32 dist_threshold = mImpl->mVOCachePartition->isFrontCull() ? gAgentCamera.mDrawDistance : LLVOCacheEntry::sRearFarRadius; + + std::set< LLPointer >::iterator group_iter = mImpl->mVisibleGroups.begin(); + for(; group_iter != mImpl->mVisibleGroups.end(); ++group_iter) + { + LLPointer group = *group_iter; + if(group->getNumRefs() < 3 || //group to be deleted + !group->getOctreeNode() || group->isEmpty()) //group empty + { + continue; + } + + for (LLViewerOctreeGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + if((*i)->hasVOCacheEntry()) + { + LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry(); + + if(vo_entry->getParentID() > 0) //is a child + { + //child visibility depends on its parent. + continue; + } + if(!vo_entry->isValid()) + { + continue; //skip invalid entry. + } + + vo_entry->calcSceneContribution(local_origin, needs_update, last_update, dist_threshold); + if(vo_entry->getSceneContribution() > projection_threshold) + { + mImpl->mWaitingList.insert(vo_entry); + } + } + } + } + + if(needs_update) + { + mImpl->mLastCameraOrigin = camera_origin; + mImpl->mLastCameraUpdate = cur_frame; + } + + return; } void LLViewerRegion::createVisibleObjects(F32 max_time) { - if(mDead) - { - return; - } - if(mImpl->mWaitingList.empty()) - { - mImpl->mVOCachePartition->setCullHistory(FALSE); - return; - } - - S32 throttle = sNewObjectCreationThrottle; - BOOL has_new_obj = FALSE; - LLTimer update_timer; - for(LLVOCacheEntry::vocache_entry_priority_list_t::iterator iter = mImpl->mWaitingList.begin(); - iter != mImpl->mWaitingList.end(); ++iter) - { - LLVOCacheEntry* vo_entry = *iter; - - if(vo_entry->getState() < LLVOCacheEntry::WAITING) - { - addNewObject(vo_entry); - has_new_obj = TRUE; - if(throttle > 0 && !(--throttle) && update_timer.getElapsedTimeF32() > max_time) - { - break; - } - } - } - - mImpl->mVOCachePartition->setCullHistory(has_new_obj); - - return; + if(mDead) + { + return; + } + if(mImpl->mWaitingList.empty()) + { + mImpl->mVOCachePartition->setCullHistory(FALSE); + return; + } + + S32 throttle = sNewObjectCreationThrottle; + BOOL has_new_obj = FALSE; + LLTimer update_timer; + for(LLVOCacheEntry::vocache_entry_priority_list_t::iterator iter = mImpl->mWaitingList.begin(); + iter != mImpl->mWaitingList.end(); ++iter) + { + LLVOCacheEntry* vo_entry = *iter; + + if(vo_entry->getState() < LLVOCacheEntry::WAITING) + { + addNewObject(vo_entry); + has_new_obj = TRUE; + if(throttle > 0 && !(--throttle) && update_timer.getElapsedTimeF32() > max_time) + { + break; + } + } + } + + mImpl->mVOCachePartition->setCullHistory(has_new_obj); + + return; } void LLViewerRegion::clearCachedVisibleObjects() { - mImpl->mWaitingList.clear(); - mImpl->mVisibleGroups.clear(); - - //reset all occluders - mImpl->mVOCachePartition->resetOccluders(); - mPaused = TRUE; - - //clean visible entries - for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) - { - LLVOCacheEntry* entry = *iter; - LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); - - if(!entry->getParentID() || parent) //no child or parent is cache-able - { - if(parent) //has a cache-able parent - { - parent->addChild(entry); - } - - LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter; - ++next_iter; - mImpl->mVisibleEntries.erase(iter); - iter = next_iter; - } - else //parent is not cache-able, leave it. - { - ++iter; - } - } - - //remove all visible entries. - mLastVisitedEntry = NULL; - std::vector delete_list; - for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin(); - iter != mImpl->mActiveSet.end(); ++iter) - { + mImpl->mWaitingList.clear(); + mImpl->mVisibleGroups.clear(); + + //reset all occluders + mImpl->mVOCachePartition->resetOccluders(); + mPaused = TRUE; + + //clean visible entries + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) + { + LLVOCacheEntry* entry = *iter; + LLVOCacheEntry* parent = getCacheEntry(entry->getParentID()); + + if(!entry->getParentID() || parent) //no child or parent is cache-able + { + if(parent) //has a cache-able parent + { + parent->addChild(entry); + } + + LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter; + ++next_iter; + mImpl->mVisibleEntries.erase(iter); + iter = next_iter; + } + else //parent is not cache-able, leave it. + { + ++iter; + } + } + + //remove all visible entries. + mLastVisitedEntry = NULL; + std::vector delete_list; + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin(); + iter != mImpl->mActiveSet.end(); ++iter) + { LLVOCacheEntry* vo_entry = *iter; if (!vo_entry || !vo_entry->getEntry()) { continue; } LLDrawable* drawablep = (LLDrawable*)vo_entry->getEntry()->getDrawable(); - - if(drawablep && !drawablep->getParent()) - { - delete_list.push_back(drawablep); - } - } - if(!delete_list.empty()) - { - for(S32 i = 0; i < delete_list.size(); i++) - { - gObjectList.killObject(delete_list[i]->getVObj()); - } - delete_list.clear(); - } + if(drawablep && !drawablep->getParent()) + { + delete_list.push_back(drawablep); + } + } + + if(!delete_list.empty()) + { + for(S32 i = 0; i < delete_list.size(); i++) + { + gObjectList.killObject(delete_list[i]->getVObj()); + } + delete_list.clear(); + } - return; + return; } //perform some necessary but very light updates. //to replace the function idleUpdate(...) in case there is no enough time. void LLViewerRegion::lightIdleUpdate() { - if(!sVOCacheCullingEnabled) - { - return; - } - if(mImpl->mCacheMap.empty()) - { - return; - } + if(!sVOCacheCullingEnabled) + { + return; + } + if(mImpl->mCacheMap.empty()) + { + return; + } - //reset all occluders - mImpl->mVOCachePartition->resetOccluders(); + //reset all occluders + mImpl->mVOCachePartition->resetOccluders(); } void LLViewerRegion::idleUpdate(F32 max_update_time) -{ +{ LL_PROFILE_ZONE_SCOPED; - LLTimer update_timer; - F32 max_time; + LLTimer update_timer; + F32 max_time; - mLastUpdate = LLViewerOctreeEntryData::getCurrentFrame(); + mLastUpdate = LLViewerOctreeEntryData::getCurrentFrame(); static LLCachedControl pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", false); @@ -1631,48 +1631,48 @@ void LLViewerRegion::idleUpdate(F32 max_update_time) { mImpl->mLandp->idleUpdate(max_update_time); } - - if (mParcelOverlay) - { - // Hopefully not a significant time sink... - mParcelOverlay->idleUpdate(); - } - if(!sVOCacheCullingEnabled) - { - return; - } - if(mImpl->mCacheMap.empty()) - { - return; - } - if(mPaused) - { - mPaused = FALSE; //unpause. - } + if (mParcelOverlay) + { + // Hopefully not a significant time sink... + mParcelOverlay->idleUpdate(); + } + + if(!sVOCacheCullingEnabled) + { + return; + } + if(mImpl->mCacheMap.empty()) + { + return; + } + if(mPaused) + { + mPaused = FALSE; //unpause. + } - LLViewerCamera::eCameraID old_camera_id = LLViewerCamera::sCurCameraID; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLViewerCamera::eCameraID old_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - //reset all occluders - mImpl->mVOCachePartition->resetOccluders(); + //reset all occluders + mImpl->mVOCachePartition->resetOccluders(); - max_time = max_update_time - update_timer.getElapsedTimeF32(); + max_time = max_update_time - update_timer.getElapsedTimeF32(); - //kill invisible objects - killInvisibleObjects(max_time * 0.4f); - max_time = max_update_time - update_timer.getElapsedTimeF32(); + //kill invisible objects + killInvisibleObjects(max_time * 0.4f); + max_time = max_update_time - update_timer.getElapsedTimeF32(); - updateVisibleEntries(max_time); - max_time = max_update_time - update_timer.getElapsedTimeF32(); + updateVisibleEntries(max_time); + max_time = max_update_time - update_timer.getElapsedTimeF32(); - createVisibleObjects(max_time); + createVisibleObjects(max_time); - mImpl->mWaitingList.clear(); - mImpl->mVisibleGroups.clear(); + mImpl->mWaitingList.clear(); + mImpl->mVisibleGroups.clear(); - LLViewerCamera::sCurCameraID = old_camera_id; - return; + LLViewerCamera::sCurCameraID = old_camera_id; + return; } // static @@ -1688,395 +1688,395 @@ void LLViewerRegion::idleCleanup(F32 max_update_time) //update the throttling number for new object creation void LLViewerRegion::calcNewObjectCreationThrottle() { - static LLCachedControl new_object_creation_throttle(gSavedSettings,"NewObjectCreationThrottle"); - static LLCachedControl throttle_delay_time(gSavedSettings,"NewObjectCreationThrottleDelayTime"); - static LLFrameTimer timer; - - // - //sNewObjectCreationThrottle = - //-2: throttle is disabled because either the screen is showing progress view, or immediate after the screen is not black - //-1: throttle is disabled by the debug setting - //0: no new object creation is allowed - //>0: valid throttling number - // - - if(gViewerWindow->getProgressView()->getVisible() && throttle_delay_time > 0.f) - { - sNewObjectCreationThrottle = -2; //cancel the throttling - timer.reset(); - } - else if(sNewObjectCreationThrottle < -1) //just recoved from the login/teleport screen - { - if(timer.getElapsedTimeF32() > throttle_delay_time) //wait for throttle_delay_time to reset the throttle - { - sNewObjectCreationThrottle = new_object_creation_throttle; //reset - if(sNewObjectCreationThrottle < -1) - { - sNewObjectCreationThrottle = -1; - } - } - } - - //update some LLVOCacheEntry debug setting factors. - LLVOCacheEntry::updateDebugSettings(); + static LLCachedControl new_object_creation_throttle(gSavedSettings,"NewObjectCreationThrottle"); + static LLCachedControl throttle_delay_time(gSavedSettings,"NewObjectCreationThrottleDelayTime"); + static LLFrameTimer timer; + + // + //sNewObjectCreationThrottle = + //-2: throttle is disabled because either the screen is showing progress view, or immediate after the screen is not black + //-1: throttle is disabled by the debug setting + //0: no new object creation is allowed + //>0: valid throttling number + // + + if(gViewerWindow->getProgressView()->getVisible() && throttle_delay_time > 0.f) + { + sNewObjectCreationThrottle = -2; //cancel the throttling + timer.reset(); + } + else if(sNewObjectCreationThrottle < -1) //just recoved from the login/teleport screen + { + if(timer.getElapsedTimeF32() > throttle_delay_time) //wait for throttle_delay_time to reset the throttle + { + sNewObjectCreationThrottle = new_object_creation_throttle; //reset + if(sNewObjectCreationThrottle < -1) + { + sNewObjectCreationThrottle = -1; + } + } + } + + //update some LLVOCacheEntry debug setting factors. + LLVOCacheEntry::updateDebugSettings(); } BOOL LLViewerRegion::isViewerCameraStatic() { - return sLastCameraUpdated < LLViewerOctreeEntryData::getCurrentFrame(); + return sLastCameraUpdated < LLViewerOctreeEntryData::getCurrentFrame(); } void LLViewerRegion::killInvisibleObjects(F32 max_time) { #if 1 // TODO: kill this. This is ill-conceived, objects that aren't in the camera frustum should not be deleted from memory. // because of this, every time you turn around the simulator sends a swarm of full object update messages from cache - // probe misses and objects have to be reloaded from scratch. From some reason, disabling this causes holes to + // probe misses and objects have to be reloaded from scratch. From some reason, disabling this causes holes to // appear in the scene when flying back and forth between regions - if(!sVOCacheCullingEnabled) - { - return; - } - if(mImpl->mActiveSet.empty()) - { - return; - } - if(sNewObjectCreationThrottle < 0) - { - return; - } - - LLTimer update_timer; - LLVector4a camera_origin; - camera_origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); - LLVector4a local_origin; - local_origin.load3((LLViewerCamera::getInstance()->getOrigin() - getOriginAgent()).mV); - F32 back_threshold = LLVOCacheEntry::sRearFarRadius; - - size_t max_update = 64; - if(!mInvisibilityCheckHistory && isViewerCameraStatic()) - { - //history is clean, reduce number of checking - max_update /= 2; - } - - std::vector delete_list; - S32 update_counter = llmin(max_update, mImpl->mActiveSet.size()); - LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(mLastVisitedEntry); - - for(; update_counter > 0; --update_counter, ++iter) - { - if(iter == mImpl->mActiveSet.end()) - { - iter = mImpl->mActiveSet.begin(); - } - if((*iter)->getParentID() > 0) - { - continue; //skip child objects, they are removed with their parent. - } - - LLVOCacheEntry* vo_entry = *iter; - if(!vo_entry->isAnyVisible(camera_origin, local_origin, back_threshold) && vo_entry->mLastCameraUpdated < sLastCameraUpdated) - { - killObject(vo_entry, delete_list); - } - - if(max_time < update_timer.getElapsedTimeF32()) //time out - { - break; - } - } - - if(iter == mImpl->mActiveSet.end()) - { - mLastVisitedEntry = NULL; - } - else - { - mLastVisitedEntry = *iter; - } - - mInvisibilityCheckHistory <<= 1; - if(!delete_list.empty()) - { - mInvisibilityCheckHistory |= 1; - S32 count = delete_list.size(); - for(S32 i = 0; i < count; i++) - { - gObjectList.killObject(delete_list[i]->getVObj()); - } - delete_list.clear(); - } - - return; -#endif -} - -void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector& delete_list) -{ - //kill the object. - LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable(); - llassert(drawablep); - llassert(drawablep->getRegion() == this); - - if(drawablep && !drawablep->getParent()) - { - LLViewerObject* v_obj = drawablep->getVObj(); - if (v_obj->isSelected() - || (v_obj->flagAnimSource() && isAgentAvatarValid() && gAgentAvatarp->hasMotionFromSource(v_obj->getID()))) - { - // do not remove objects user is interacting with - ((LLViewerOctreeEntryData*)drawablep)->setVisible(); - return; - } - LLViewerObject::const_child_list_t& child_list = v_obj->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - if(child->mDrawable) - { - if( !child->mDrawable->getEntry() - || !child->mDrawable->getEntry()->hasVOCacheEntry() - || child->isSelected() - || (child->flagAnimSource() && isAgentAvatarValid() && gAgentAvatarp->hasMotionFromSource(child->getID()))) - { - //do not remove parent if any of its children non-cacheable, animating or selected - //especially for the case that an avatar sits on a cache-able object - ((LLViewerOctreeEntryData*)drawablep)->setVisible(); - return; - } - - LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)child->mDrawable->getGroup(); - if(group && group->isAnyRecentlyVisible()) - { - //set the parent visible if any of its children visible. - ((LLViewerOctreeEntryData*)drawablep)->setVisible(); - return; - } - } - } - delete_list.push_back(drawablep); - } + if(!sVOCacheCullingEnabled) + { + return; + } + if(mImpl->mActiveSet.empty()) + { + return; + } + if(sNewObjectCreationThrottle < 0) + { + return; + } + + LLTimer update_timer; + LLVector4a camera_origin; + camera_origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); + LLVector4a local_origin; + local_origin.load3((LLViewerCamera::getInstance()->getOrigin() - getOriginAgent()).mV); + F32 back_threshold = LLVOCacheEntry::sRearFarRadius; + + size_t max_update = 64; + if(!mInvisibilityCheckHistory && isViewerCameraStatic()) + { + //history is clean, reduce number of checking + max_update /= 2; + } + + std::vector delete_list; + S32 update_counter = llmin(max_update, mImpl->mActiveSet.size()); + LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(mLastVisitedEntry); + + for(; update_counter > 0; --update_counter, ++iter) + { + if(iter == mImpl->mActiveSet.end()) + { + iter = mImpl->mActiveSet.begin(); + } + if((*iter)->getParentID() > 0) + { + continue; //skip child objects, they are removed with their parent. + } + + LLVOCacheEntry* vo_entry = *iter; + if(!vo_entry->isAnyVisible(camera_origin, local_origin, back_threshold) && vo_entry->mLastCameraUpdated < sLastCameraUpdated) + { + killObject(vo_entry, delete_list); + } + + if(max_time < update_timer.getElapsedTimeF32()) //time out + { + break; + } + } + + if(iter == mImpl->mActiveSet.end()) + { + mLastVisitedEntry = NULL; + } + else + { + mLastVisitedEntry = *iter; + } + + mInvisibilityCheckHistory <<= 1; + if(!delete_list.empty()) + { + mInvisibilityCheckHistory |= 1; + S32 count = delete_list.size(); + for(S32 i = 0; i < count; i++) + { + gObjectList.killObject(delete_list[i]->getVObj()); + } + delete_list.clear(); + } + + return; +#endif +} + +void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector& delete_list) +{ + //kill the object. + LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable(); + llassert(drawablep); + llassert(drawablep->getRegion() == this); + + if(drawablep && !drawablep->getParent()) + { + LLViewerObject* v_obj = drawablep->getVObj(); + if (v_obj->isSelected() + || (v_obj->flagAnimSource() && isAgentAvatarValid() && gAgentAvatarp->hasMotionFromSource(v_obj->getID()))) + { + // do not remove objects user is interacting with + ((LLViewerOctreeEntryData*)drawablep)->setVisible(); + return; + } + LLViewerObject::const_child_list_t& child_list = v_obj->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + if(child->mDrawable) + { + if( !child->mDrawable->getEntry() + || !child->mDrawable->getEntry()->hasVOCacheEntry() + || child->isSelected() + || (child->flagAnimSource() && isAgentAvatarValid() && gAgentAvatarp->hasMotionFromSource(child->getID()))) + { + //do not remove parent if any of its children non-cacheable, animating or selected + //especially for the case that an avatar sits on a cache-able object + ((LLViewerOctreeEntryData*)drawablep)->setVisible(); + return; + } + + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)child->mDrawable->getGroup(); + if(group && group->isAnyRecentlyVisible()) + { + //set the parent visible if any of its children visible. + ((LLViewerOctreeEntryData*)drawablep)->setVisible(); + return; + } + } + } + delete_list.push_back(drawablep); + } } LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry) { - if(!entry || !entry->getEntry()) - { - if(entry) - { - mImpl->mVisibleEntries.erase(entry); - entry->setState(LLVOCacheEntry::INACTIVE); - } - return NULL; - } - - LLViewerObject* obj = NULL; - if(!entry->getEntry()->hasDrawable()) //not added to the rendering pipeline yet - { - //add the object - obj = gObjectList.processObjectUpdateFromCache(entry, this); - if(obj) - { - if(!entry->isState(LLVOCacheEntry::ACTIVE)) - { - mImpl->mWaitingSet.insert(entry); - entry->setState(LLVOCacheEntry::WAITING); - } - } - } - else - { - LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion(); - if(old_regionp != this) - { - //this object exists in two regions at the same time; - //this case can be safely ignored here because - //server should soon send update message to remove one region for this object. - - LL_WARNS() << "Entry: " << entry->getLocalID() << " exists in two regions at the same time." << LL_ENDL; - return NULL; - } - - LL_WARNS() << "Entry: " << entry->getLocalID() << " in rendering pipeline but not set to be active." << LL_ENDL; - - //should not hit here any more, but does not hurt either, just put it back to active list - addActiveCacheEntry(entry); - } - - return obj; + if(!entry || !entry->getEntry()) + { + if(entry) + { + mImpl->mVisibleEntries.erase(entry); + entry->setState(LLVOCacheEntry::INACTIVE); + } + return NULL; + } + + LLViewerObject* obj = NULL; + if(!entry->getEntry()->hasDrawable()) //not added to the rendering pipeline yet + { + //add the object + obj = gObjectList.processObjectUpdateFromCache(entry, this); + if(obj) + { + if(!entry->isState(LLVOCacheEntry::ACTIVE)) + { + mImpl->mWaitingSet.insert(entry); + entry->setState(LLVOCacheEntry::WAITING); + } + } + } + else + { + LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion(); + if(old_regionp != this) + { + //this object exists in two regions at the same time; + //this case can be safely ignored here because + //server should soon send update message to remove one region for this object. + + LL_WARNS() << "Entry: " << entry->getLocalID() << " exists in two regions at the same time." << LL_ENDL; + return NULL; + } + + LL_WARNS() << "Entry: " << entry->getLocalID() << " in rendering pipeline but not set to be active." << LL_ENDL; + + //should not hit here any more, but does not hurt either, just put it back to active list + addActiveCacheEntry(entry); + } + + return obj; } //update object cache if the object receives a full-update or terse update //update_type == EObjectUpdateType::OUT_TERSE_IMPROVED or EObjectUpdateType::OUT_FULL LLViewerObject* LLViewerRegion::updateCacheEntry(U32 local_id, LLViewerObject* objectp) { - LLVOCacheEntry* entry = getCacheEntry(local_id); - if (!entry) - { - return objectp; //not in the cache, do nothing. - } - if(!objectp) //object not created - { - //create a new object from cache. - objectp = addNewObject(entry); - } + LLVOCacheEntry* entry = getCacheEntry(local_id); + if (!entry) + { + return objectp; //not in the cache, do nothing. + } + if(!objectp) //object not created + { + //create a new object from cache. + objectp = addNewObject(entry); + } //remove from cache. killCacheEntry(entry, true); - return objectp; + return objectp; } // As above, but forcibly do the update. void LLViewerRegion::forceUpdate() { - constexpr F32 max_update_time = 0.f; + constexpr F32 max_update_time = 0.f; static LLCachedControl pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); static LLCachedControl pbr_terrain_experimental_normals(gSavedSettings, "RenderTerrainPBRNormalsEnabled", false); - bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); - bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; + bool pbr_material = mImpl->mCompositionp && (mImpl->mCompositionp->getMaterialType() == LLTerrainMaterials::Type::PBR); + bool pbr_land = pbr_material && pbr_terrain_enabled && pbr_terrain_experimental_normals; - if (!pbr_land) - { - mImpl->mLandp->idleUpdate(max_update_time); - } - else - { - mImpl->mLandp->idleUpdate(max_update_time); - } + if (!pbr_land) + { + mImpl->mLandp->idleUpdate(max_update_time); + } + else + { + mImpl->mLandp->idleUpdate(max_update_time); + } - if (mParcelOverlay) - { - mParcelOverlay->idleUpdate(true); - } + if (mParcelOverlay) + { + mParcelOverlay->idleUpdate(true); + } } void LLViewerRegion::connectNeighbor(LLViewerRegion *neighborp, U32 direction) { - mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); + mImpl->mLandp->connectNeighbor(neighborp->mImpl->mLandp, direction); } void LLViewerRegion::disconnectAllNeighbors() { - mImpl->mLandp->disconnectAllNeighbors(); + mImpl->mLandp->disconnectAllNeighbors(); } LLVLComposition * LLViewerRegion::getComposition() const { - return mImpl->mCompositionp; + return mImpl->mCompositionp; } F32 LLViewerRegion::getCompositionXY(const S32 x, const S32 y) const { - if (x >= 256) - { - if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255, 255); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - else - { - LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); - F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - } - else if (y >= 256) - { - LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); - LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); - if (regionp) - { - // OK, we need to do some hackery here - different simulators no longer use - // the same composition values, necessarily. - // If we're attempting to blend, then we want to make the fractional part of - // this region match the fractional of the adjacent. For now, just minimize - // the delta. - F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); - F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); - while (llabs(our_comp - adj_comp) >= 1.f) - { - if (our_comp > adj_comp) - { - adj_comp += 1.f; - } - else - { - adj_comp -= 1.f; - } - } - return adj_comp; - } - } - - return getComposition()->getValueScaled((F32)x, (F32)y); -} - -void LLViewerRegion::calculateCenterGlobal() -{ - mImpl->mCenterGlobal = mImpl->mOriginGlobal; - mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; - mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); + if (x >= 256) + { + if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255, 255); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + else + { + LLVector3d center = getCenterGlobal() + LLVector3d(256.f, 0, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled(255.f, (F32)y); + F32 adj_comp = regionp->getComposition()->getValueScaled(x - 256.f, (F32)y); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + } + else if (y >= 256) + { + LLVector3d center = getCenterGlobal() + LLVector3d(0.f, 256.f, 0.f); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(center); + if (regionp) + { + // OK, we need to do some hackery here - different simulators no longer use + // the same composition values, necessarily. + // If we're attempting to blend, then we want to make the fractional part of + // this region match the fractional of the adjacent. For now, just minimize + // the delta. + F32 our_comp = getComposition()->getValueScaled((F32)x, 255.f); + F32 adj_comp = regionp->getComposition()->getValueScaled((F32)x, y - 256.f); + while (llabs(our_comp - adj_comp) >= 1.f) + { + if (our_comp > adj_comp) + { + adj_comp += 1.f; + } + else + { + adj_comp -= 1.f; + } + } + return adj_comp; + } + } + + return getComposition()->getValueScaled((F32)x, (F32)y); +} + +void LLViewerRegion::calculateCenterGlobal() +{ + mImpl->mCenterGlobal = mImpl->mOriginGlobal; + mImpl->mCenterGlobal.mdV[VX] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VY] += 0.5 * mWidth; + mImpl->mCenterGlobal.mdV[VZ] = 0.5 * mImpl->mLandp->getMinZ() + mImpl->mLandp->getMaxZ(); } void LLViewerRegion::calculateCameraDistance() { - mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); + mCameraDistanceSquared = (F32)(gAgentCamera.getCameraPositionGlobal() - getCenterGlobal()).magVecSquared(); } std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) { - s << "{ "; - s << region.mImpl->mHost; - s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; + s << "{ "; + s << region.mImpl->mHost; + s << " mOriginGlobal = " << region.getOriginGlobal()<< "\n"; std::string name(region.getName()), zone(region.getZoning()); if (! name.empty()) { @@ -2086,8 +2086,8 @@ std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) { s << " mZoning = " << zone << '\n'; } - s << "}"; - return s; + s << "}"; + return s; } @@ -2095,143 +2095,143 @@ std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion) void LLViewerRegion::updateNetStats() { - F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); + F32 dt = mImpl->mLastNetUpdate.getElapsedTimeAndResetF32(); - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - mAlive = false; - return; - } + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + mAlive = false; + return; + } - mAlive = true; - mDeltaTime = dt; + mAlive = true; + mDeltaTime = dt; - mLastPacketsIn = mPacketsIn; - mLastBitsIn = mBitsIn; - mLastPacketsOut = mPacketsOut; - mLastPacketsLost = mPacketsLost; + mLastPacketsIn = mPacketsIn; + mLastBitsIn = mBitsIn; + mLastPacketsOut = mPacketsOut; + mLastPacketsLost = mPacketsLost; - mPacketsIn = cdp->getPacketsIn(); - mBitsIn = 8 * cdp->getBytesIn(); - mPacketsOut = cdp->getPacketsOut(); - mPacketsLost = cdp->getPacketsLost(); - mPingDelay = cdp->getPingDelay(); + mPacketsIn = cdp->getPacketsIn(); + mBitsIn = 8 * cdp->getBytesIn(); + mPacketsOut = cdp->getPacketsOut(); + mPacketsLost = cdp->getPacketsLost(); + mPingDelay = cdp->getPingDelay(); - mBitsReceived += mBitsIn - mLastBitsIn; - mPacketsReceived += mPacketsIn - mLastPacketsIn; + mBitsReceived += mBitsIn - mLastBitsIn; + mPacketsReceived += mPacketsIn - mLastPacketsIn; } U32 LLViewerRegion::getPacketsLost() const { - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); - if (!cdp) - { - LL_INFOS() << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << LL_ENDL; - return 0; - } - else - { - return cdp->getPacketsLost(); - } + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mImpl->mHost); + if (!cdp) + { + LL_INFOS() << "LLViewerRegion::getPacketsLost couldn't find circuit for " << mImpl->mHost << LL_ENDL; + return 0; + } + else + { + return cdp->getPacketsLost(); + } } S32 LLViewerRegion::getHttpResponderID() const { - return mImpl->mHttpResponderID; + return mImpl->mHttpResponderID; } BOOL LLViewerRegion::pointInRegionGlobal(const LLVector3d &point_global) const { - LLVector3 pos_region = getPosRegionFromGlobal(point_global); - - if (pos_region.mV[VX] < 0) - { - return FALSE; - } - if (pos_region.mV[VX] >= mWidth) - { - return FALSE; - } - if (pos_region.mV[VY] < 0) - { - return FALSE; - } - if (pos_region.mV[VY] >= mWidth) - { - return FALSE; - } - return TRUE; + LLVector3 pos_region = getPosRegionFromGlobal(point_global); + + if (pos_region.mV[VX] < 0) + { + return FALSE; + } + if (pos_region.mV[VX] >= mWidth) + { + return FALSE; + } + if (pos_region.mV[VY] < 0) + { + return FALSE; + } + if (pos_region.mV[VY] >= mWidth) + { + return FALSE; + } + return TRUE; } LLVector3 LLViewerRegion::getPosRegionFromGlobal(const LLVector3d &point_global) const { - LLVector3 pos_region; - pos_region.setVec(point_global - mImpl->mOriginGlobal); - return pos_region; + LLVector3 pos_region; + pos_region.setVec(point_global - mImpl->mOriginGlobal); + return pos_region; } LLVector3d LLViewerRegion::getPosGlobalFromRegion(const LLVector3 &pos_region) const { - LLVector3d pos_region_d; - pos_region_d.setVec(pos_region); - return pos_region_d + mImpl->mOriginGlobal; + LLVector3d pos_region_d; + pos_region_d.setVec(pos_region); + return pos_region_d + mImpl->mOriginGlobal; } LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) const { - LLVector3d pos_global = getPosGlobalFromRegion(pos_region); + LLVector3d pos_global = getPosGlobalFromRegion(pos_region); - return gAgent.getPosAgentFromGlobal(pos_global); + return gAgent.getPosAgentFromGlobal(pos_global); } LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const { - return pos_agent - getOriginAgent(); + return pos_agent - getOriginAgent(); } F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) { - return mImpl->mLandp->resolveHeightRegion( region_pos ); + return mImpl->mLandp->resolveHeightRegion( region_pos ); } bool LLViewerRegion::isAlive() { - return mAlive; + return mAlive; } BOOL LLViewerRegion::isOwnedSelf(const LLVector3& pos) { - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedSelf(pos); - } else { - return FALSE; - } + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedSelf(pos); + } else { + return FALSE; + } } // Owned by a group you belong to? (officer or member) BOOL LLViewerRegion::isOwnedGroup(const LLVector3& pos) { - if (mParcelOverlay) - { - return mParcelOverlay->isOwnedGroup(pos); - } else { - return FALSE; - } + if (mParcelOverlay) + { + return mParcelOverlay->isOwnedGroup(pos); + } else { + return FALSE; + } } // the new TCP coarse location handler node class CoarseLocationUpdate : public LLHTTPNode { public: - virtual void post( - ResponsePtr responder, - const LLSD& context, - const LLSD& input) const - { - LLHost host(input["sender"].asString()); + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLHost host(input["sender"].asString()); LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton! if (!world_inst) @@ -2239,151 +2239,151 @@ public: return; } - LLViewerRegion* region = world_inst->getRegion(host); - if( !region ) - { - return; - } - - S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); - S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); - - std::vector* avatar_locs = ®ion->mMapAvatars; - std::vector* avatar_ids = ®ion->mMapAvatarIDs; - avatar_locs->clear(); - avatar_ids->clear(); - - //LL_INFOS() << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << LL_ENDL; - //LL_INFOS() << "my agent id = " << gAgent.getID() << LL_ENDL; - //LL_INFOS() << ll_pretty_print_sd(input) << LL_ENDL; - - LLSD - locs = input["body"]["Location"], - agents = input["body"]["AgentData"]; - LLSD::array_iterator - locs_it = locs.beginArray(), - agents_it = agents.beginArray(); - BOOL has_agent_data = input["body"].has("AgentData"); - - for(int i=0; - locs_it != locs.endArray(); - i++, locs_it++) - { - U8 - x = locs_it->get("X").asInteger(), - y = locs_it->get("Y").asInteger(), - z = locs_it->get("Z").asInteger(); - // treat the target specially for the map, and don't add you or the target - if(i == target_index) - { - LLVector3d global_pos(region->getOriginGlobal()); - global_pos.mdV[VX] += (F64)x; - global_pos.mdV[VY] += (F64)y; - global_pos.mdV[VZ] += (F64)z * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - else if( i != you_index) - { - U32 pos = 0x0; - pos |= x; - pos <<= 8; - pos |= y; - pos <<= 8; - pos |= z; - avatar_locs->push_back(pos); - //LL_INFOS() << "next pos: " << x << "," << y << "," << z << ": " << pos << LL_ENDL; - if(has_agent_data) // for backwards compatibility with old message format - { - LLUUID agent_id(agents_it->get("AgentID").asUUID()); - //LL_INFOS() << "next agent: " << agent_id.asString() << LL_ENDL; - avatar_ids->push_back(agent_id); - } - } - if (has_agent_data) - { - agents_it++; - } - } - } + LLViewerRegion* region = world_inst->getRegion(host); + if( !region ) + { + return; + } + + S32 target_index = input["body"]["Index"][0]["Prey"].asInteger(); + S32 you_index = input["body"]["Index"][0]["You" ].asInteger(); + + std::vector* avatar_locs = ®ion->mMapAvatars; + std::vector* avatar_ids = ®ion->mMapAvatarIDs; + avatar_locs->clear(); + avatar_ids->clear(); + + //LL_INFOS() << "coarse locations agent[0] " << input["body"]["AgentData"][0]["AgentID"].asUUID() << LL_ENDL; + //LL_INFOS() << "my agent id = " << gAgent.getID() << LL_ENDL; + //LL_INFOS() << ll_pretty_print_sd(input) << LL_ENDL; + + LLSD + locs = input["body"]["Location"], + agents = input["body"]["AgentData"]; + LLSD::array_iterator + locs_it = locs.beginArray(), + agents_it = agents.beginArray(); + BOOL has_agent_data = input["body"].has("AgentData"); + + for(int i=0; + locs_it != locs.endArray(); + i++, locs_it++) + { + U8 + x = locs_it->get("X").asInteger(), + y = locs_it->get("Y").asInteger(), + z = locs_it->get("Z").asInteger(); + // treat the target specially for the map, and don't add you or the target + if(i == target_index) + { + LLVector3d global_pos(region->getOriginGlobal()); + global_pos.mdV[VX] += (F64)x; + global_pos.mdV[VY] += (F64)y; + global_pos.mdV[VZ] += (F64)z * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + else if( i != you_index) + { + U32 pos = 0x0; + pos |= x; + pos <<= 8; + pos |= y; + pos <<= 8; + pos |= z; + avatar_locs->push_back(pos); + //LL_INFOS() << "next pos: " << x << "," << y << "," << z << ": " << pos << LL_ENDL; + if(has_agent_data) // for backwards compatibility with old message format + { + LLUUID agent_id(agents_it->get("AgentID").asUUID()); + //LL_INFOS() << "next agent: " << agent_id.asString() << LL_ENDL; + avatar_ids->push_back(agent_id); + } + } + if (has_agent_data) + { + agents_it++; + } + } + } }; // build the coarse location HTTP node under the "/message" URL LLHTTPRegistration gHTTPRegistrationCoarseLocationUpdate( - "/message/CoarseLocationUpdate"); + "/message/CoarseLocationUpdate"); // the deprecated coarse location handler void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) { - //LL_INFOS() << "CoarseLocationUpdate" << LL_ENDL; - mMapAvatars.clear(); - mMapAvatarIDs.clear(); // only matters in a rare case but it's good to be safe. - - U8 x_pos = 0; - U8 y_pos = 0; - U8 z_pos = 0; - - U32 pos = 0x0; - - S16 agent_index; - S16 target_index; - msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); - msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); - - BOOL has_agent_data = msg->has(_PREHASH_AgentData); - S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); - for(S32 i = 0; i < count; i++) - { - msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); - msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); - LLUUID agent_id = LLUUID::null; - if(has_agent_data) - { - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); - } - - //LL_INFOS() << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos - // << " Z: " << (S32)(z_pos * 4) - // << LL_ENDL; - - // treat the target specially for the map - if(i == target_index) - { - LLVector3d global_pos(mImpl->mOriginGlobal); - global_pos.mdV[VX] += (F64)(x_pos); - global_pos.mdV[VY] += (F64)(y_pos); - global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; - LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); - } - - //don't add you - if( i != agent_index) - { - pos = 0x0; - pos |= x_pos; - pos <<= 8; - pos |= y_pos; - pos <<= 8; - pos |= z_pos; - mMapAvatars.push_back(pos); - if(has_agent_data) - { - mMapAvatarIDs.push_back(agent_id); - } - } - } + //LL_INFOS() << "CoarseLocationUpdate" << LL_ENDL; + mMapAvatars.clear(); + mMapAvatarIDs.clear(); // only matters in a rare case but it's good to be safe. + + U8 x_pos = 0; + U8 y_pos = 0; + U8 z_pos = 0; + + U32 pos = 0x0; + + S16 agent_index; + S16 target_index; + msg->getS16Fast(_PREHASH_Index, _PREHASH_You, agent_index); + msg->getS16Fast(_PREHASH_Index, _PREHASH_Prey, target_index); + + BOOL has_agent_data = msg->has(_PREHASH_AgentData); + S32 count = msg->getNumberOfBlocksFast(_PREHASH_Location); + for(S32 i = 0; i < count; i++) + { + msg->getU8Fast(_PREHASH_Location, _PREHASH_X, x_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Y, y_pos, i); + msg->getU8Fast(_PREHASH_Location, _PREHASH_Z, z_pos, i); + LLUUID agent_id = LLUUID::null; + if(has_agent_data) + { + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id, i); + } + + //LL_INFOS() << " object X: " << (S32)x_pos << " Y: " << (S32)y_pos + // << " Z: " << (S32)(z_pos * 4) + // << LL_ENDL; + + // treat the target specially for the map + if(i == target_index) + { + LLVector3d global_pos(mImpl->mOriginGlobal); + global_pos.mdV[VX] += (F64)(x_pos); + global_pos.mdV[VY] += (F64)(y_pos); + global_pos.mdV[VZ] += (F64)(z_pos) * 4.0; + LLAvatarTracker::instance().setTrackedCoarseLocation(global_pos); + } + + //don't add you + if( i != agent_index) + { + pos = 0x0; + pos |= x_pos; + pos <<= 8; + pos |= y_pos; + pos <<= 8; + pos |= z_pos; + mMapAvatars.push_back(pos); + if(has_agent_data) + { + mMapAvatarIDs.push_back(agent_id); + } + } + } } void LLViewerRegion::getInfo(LLSD& info) { - info["Region"]["Host"] = getHost().getIPandPort(); - info["Region"]["Name"] = getName(); - U32 x, y; - from_region_handle(getHandle(), &x, &y); - info["Region"]["Handle"]["x"] = (LLSD::Integer)x; - info["Region"]["Handle"]["y"] = (LLSD::Integer)y; + info["Region"]["Host"] = getHost().getIPandPort(); + info["Region"]["Name"] = getName(); + U32 x, y; + from_region_handle(getHandle(), &x, &y); + info["Region"]["Handle"]["x"] = (LLSD::Integer)x; + info["Region"]["Handle"]["y"] = (LLSD::Integer)y; } void LLViewerRegion::requestSimulatorFeatures() @@ -2402,7 +2402,7 @@ void LLViewerRegion::requestSimulatorFeatures() // launch() acts like a suspend() // Make sure we are still good to do LLCoros::checkStop(); - + LL_INFOS("AppInit", "SimulatorFeatures") << "Launching " << coroname << " requesting simulator features from " << url << " for region " << getRegionID() << LL_ENDL; } else @@ -2413,44 +2413,44 @@ void LLViewerRegion::requestSimulatorFeatures() boost::signals2::connection LLViewerRegion::setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb) { - return mSimulatorFeaturesReceivedSignal.connect(cb); + return mSimulatorFeaturesReceivedSignal.connect(cb); } void LLViewerRegion::setSimulatorFeaturesReceived(bool received) { - mSimulatorFeaturesReceived = received; - if (received) - { - mSimulatorFeaturesReceivedSignal(getRegionID(), this); - mSimulatorFeaturesReceivedSignal.disconnect_all_slots(); - } + mSimulatorFeaturesReceived = received; + if (received) + { + mSimulatorFeaturesReceivedSignal(getRegionID(), this); + mSimulatorFeaturesReceivedSignal.disconnect_all_slots(); + } } bool LLViewerRegion::simulatorFeaturesReceived() const { - return mSimulatorFeaturesReceived; + return mSimulatorFeaturesReceived; } void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) const { - sim_features = mSimulatorFeatures; + sim_features = mSimulatorFeatures; } void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) { - std::stringstream str; - - LLSDSerialize::toPrettyXML(sim_features, str); - LL_INFOS() << "region " << getName() << " " << str.str() << LL_ENDL; - mSimulatorFeatures = sim_features; + std::stringstream str; - setSimulatorFeaturesReceived(true); + LLSDSerialize::toPrettyXML(sim_features, str); + LL_INFOS() << "region " << getName() << " " << str.str() << LL_ENDL; + mSimulatorFeatures = sim_features; - // WARNING: this is called from a coroutine, and flipping saved settings has a LOT of side effects, shuttle + setSimulatorFeaturesReceived(true); + + // WARNING: this is called from a coroutine, and flipping saved settings has a LOT of side effects, shuttle // the work below back to the main loop - // - + // + // copy features to lambda in case the region is deleted before the lambda is executed LLSD features = mSimulatorFeatures; @@ -2501,252 +2501,252 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) //move all orphan children out of cache and insert to rendering octree. void LLViewerRegion::findOrphans(U32 parent_id) { - orphan_list_t::iterator iter = mOrphanMap.find(parent_id); - if(iter != mOrphanMap.end()) - { - std::vector* children = &mOrphanMap[parent_id]; - for(S32 i = 0; i < children->size(); i++) - { - //parent is visible, so is the child. - addVisibleChildCacheEntry(NULL, getCacheEntry((*children)[i])); - } - children->clear(); - mOrphanMap.erase(parent_id); - } + orphan_list_t::iterator iter = mOrphanMap.find(parent_id); + if(iter != mOrphanMap.end()) + { + std::vector* children = &mOrphanMap[parent_id]; + for(S32 i = 0; i < children->size(); i++) + { + //parent is visible, so is the child. + addVisibleChildCacheEntry(NULL, getCacheEntry((*children)[i])); + } + children->clear(); + mOrphanMap.erase(parent_id); + } } void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry) { - if(!sVOCacheCullingEnabled) - { - gObjectList.processObjectUpdateFromCache(entry, this); - return; - } - if(!entry || !entry->isValid()) - { - return; - } - - if(!entry->getEntry()) - { - entry->setOctreeEntry(NULL); - } - - if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline - { - LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion(); - if(old_regionp != this && old_regionp) - { - LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj(); - if(obj) - { - //remove from old region - old_regionp->killCacheEntry(obj->getLocalID()); - - //change region - obj->setRegion(this); - } - } - - addActiveCacheEntry(entry); - - //set parent id - U32 parent_id = 0; + if(!sVOCacheCullingEnabled) + { + gObjectList.processObjectUpdateFromCache(entry, this); + return; + } + if(!entry || !entry->isValid()) + { + return; + } + + if(!entry->getEntry()) + { + entry->setOctreeEntry(NULL); + } + + if(entry->getEntry()->hasDrawable()) //already in the rendering pipeline + { + LLViewerRegion* old_regionp = ((LLDrawable*)entry->getEntry()->getDrawable())->getRegion(); + if(old_regionp != this && old_regionp) + { + LLViewerObject* obj = ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj(); + if(obj) + { + //remove from old region + old_regionp->killCacheEntry(obj->getLocalID()); + + //change region + obj->setRegion(this); + } + } + + addActiveCacheEntry(entry); + + //set parent id + U32 parent_id = 0; if (entry->getDP()) // NULL if nothing cached { LLViewerObject::unpackParentID(entry->getDP(), parent_id); } - if(parent_id != entry->getParentID()) - { - entry->setParentID(parent_id); - } - - //update the object - gObjectList.processObjectUpdateFromCache(entry, this); - return; //done - } - - //must not be active. - llassert_always(!entry->isState(LLVOCacheEntry::ACTIVE)); - removeFromVOCacheTree(entry); //remove from cache octree if it is in. - - LLVector3 pos; - LLVector3 scale; - LLQuaternion rot; - - //decode spatial info and parent info - U32 parent_id = entry->getDP() ? LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot) : entry->getParentID(); - - U32 old_parent_id = entry->getParentID(); - bool same_old_parent = false; - if(parent_id != old_parent_id) //parent changed. - { - if(old_parent_id > 0) //has an old parent, disconnect it - { - LLVOCacheEntry* old_parent = getCacheEntry(old_parent_id); - if(old_parent) - { - old_parent->removeChild(entry); - if(!old_parent->isState(LLVOCacheEntry::INACTIVE)) - { - mImpl->mVisibleEntries.erase(entry); - entry->setState(LLVOCacheEntry::INACTIVE); - } - } - } - entry->setParentID(parent_id); - } - else - { - same_old_parent = true; - } - - if(parent_id > 0) //has a new parent - { - //1, find the parent in cache - LLVOCacheEntry* parent = getCacheEntry(parent_id); - - //2, parent is not in the cache, put into the orphan list. - if(!parent) - { - if(!same_old_parent) - { - //check if parent is non-cacheable and already created - if(isNonCacheableObjectCreated(parent_id)) - { - //parent is visible, so is the child. - addVisibleChildCacheEntry(NULL, entry); - } - else - { - entry->setBoundingInfo(pos, scale); - mOrphanMap[parent_id].push_back(entry->getLocalID()); - } - } - else - { - entry->setBoundingInfo(pos, scale); - } - } - else //parent in cache. - { - if(!parent->isState(LLVOCacheEntry::INACTIVE)) - { - //parent is visible, so is the child. - addVisibleChildCacheEntry(parent, entry); - } - else - { - entry->setBoundingInfo(pos, scale); - parent->addChild(entry); - - if(parent->getGroup()) //re-insert parent to vo-cache tree because its bounding info changed. - { - removeFromVOCacheTree(parent); - addToVOCacheTree(parent); - } - } - } - - return; - } - - // - //no parent - // - entry->setBoundingInfo(pos, scale); - - if(!parent_id) //a potential parent - { - //find all children and update their bounding info - orphan_list_t::iterator iter = mOrphanMap.find(entry->getLocalID()); - if(iter != mOrphanMap.end()) - { - std::vector* orphans = &mOrphanMap[entry->getLocalID()]; - S32 size = orphans->size(); - for(S32 i = 0; i < size; i++) - { - LLVOCacheEntry* child = getCacheEntry((*orphans)[i]); - if(child) - { - entry->addChild(child); - } - } - orphans->clear(); - mOrphanMap.erase(entry->getLocalID()); - } - } - - if(!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE)) - { - addToVOCacheTree(entry); - } - return ; + if(parent_id != entry->getParentID()) + { + entry->setParentID(parent_id); + } + + //update the object + gObjectList.processObjectUpdateFromCache(entry, this); + return; //done + } + + //must not be active. + llassert_always(!entry->isState(LLVOCacheEntry::ACTIVE)); + removeFromVOCacheTree(entry); //remove from cache octree if it is in. + + LLVector3 pos; + LLVector3 scale; + LLQuaternion rot; + + //decode spatial info and parent info + U32 parent_id = entry->getDP() ? LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot) : entry->getParentID(); + + U32 old_parent_id = entry->getParentID(); + bool same_old_parent = false; + if(parent_id != old_parent_id) //parent changed. + { + if(old_parent_id > 0) //has an old parent, disconnect it + { + LLVOCacheEntry* old_parent = getCacheEntry(old_parent_id); + if(old_parent) + { + old_parent->removeChild(entry); + if(!old_parent->isState(LLVOCacheEntry::INACTIVE)) + { + mImpl->mVisibleEntries.erase(entry); + entry->setState(LLVOCacheEntry::INACTIVE); + } + } + } + entry->setParentID(parent_id); + } + else + { + same_old_parent = true; + } + + if(parent_id > 0) //has a new parent + { + //1, find the parent in cache + LLVOCacheEntry* parent = getCacheEntry(parent_id); + + //2, parent is not in the cache, put into the orphan list. + if(!parent) + { + if(!same_old_parent) + { + //check if parent is non-cacheable and already created + if(isNonCacheableObjectCreated(parent_id)) + { + //parent is visible, so is the child. + addVisibleChildCacheEntry(NULL, entry); + } + else + { + entry->setBoundingInfo(pos, scale); + mOrphanMap[parent_id].push_back(entry->getLocalID()); + } + } + else + { + entry->setBoundingInfo(pos, scale); + } + } + else //parent in cache. + { + if(!parent->isState(LLVOCacheEntry::INACTIVE)) + { + //parent is visible, so is the child. + addVisibleChildCacheEntry(parent, entry); + } + else + { + entry->setBoundingInfo(pos, scale); + parent->addChild(entry); + + if(parent->getGroup()) //re-insert parent to vo-cache tree because its bounding info changed. + { + removeFromVOCacheTree(parent); + addToVOCacheTree(parent); + } + } + } + + return; + } + + // + //no parent + // + entry->setBoundingInfo(pos, scale); + + if(!parent_id) //a potential parent + { + //find all children and update their bounding info + orphan_list_t::iterator iter = mOrphanMap.find(entry->getLocalID()); + if(iter != mOrphanMap.end()) + { + std::vector* orphans = &mOrphanMap[entry->getLocalID()]; + S32 size = orphans->size(); + for(S32 i = 0; i < size; i++) + { + LLVOCacheEntry* child = getCacheEntry((*orphans)[i]); + if(child) + { + entry->addChild(child); + } + } + orphans->clear(); + mOrphanMap.erase(entry->getLocalID()); + } + } + + if(!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE)) + { + addToVOCacheTree(entry); + } + return ; } LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags) { - eCacheUpdateResult result; - U32 crc; - U32 local_id; + eCacheUpdateResult result; + U32 crc; + U32 local_id; - LLViewerObject::unpackU32(&dp, local_id, "LocalID"); - LLViewerObject::unpackU32(&dp, crc, "CRC"); + LLViewerObject::unpackU32(&dp, local_id, "LocalID"); + LLViewerObject::unpackU32(&dp, crc, "CRC"); - LLVOCacheEntry* entry = getCacheEntry(local_id, false); + LLVOCacheEntry* entry = getCacheEntry(local_id, false); - if (entry) - { - entry->setValid(); + if (entry) + { + entry->setValid(); - // we've seen this object before - if (entry->getCRC() == crc) - { + // we've seen this object before + if (entry->getCRC() == crc) + { LL_DEBUGS("AnimatedObjects") << " got dupe for local_id " << local_id << LL_ENDL; dumpStack("AnimatedObjectsStack"); - // Record a hit - entry->recordDupe(); - result = CACHE_UPDATE_DUPE; - } - else //CRC changed - { + // Record a hit + entry->recordDupe(); + result = CACHE_UPDATE_DUPE; + } + else //CRC changed + { LL_DEBUGS("AnimatedObjects") << " got update for local_id " << local_id << LL_ENDL; dumpStack("AnimatedObjectsStack"); - // Update the cache entry - entry->updateEntry(crc, dp); + // Update the cache entry + entry->updateEntry(crc, dp); - decodeBoundingInfo(entry); + decodeBoundingInfo(entry); - result = CACHE_UPDATE_CHANGED; - } - } - else - { + result = CACHE_UPDATE_CHANGED; + } + } + else + { LL_DEBUGS("AnimatedObjects") << " got first notification for local_id " << local_id << LL_ENDL; dumpStack("AnimatedObjectsStack"); - // we haven't seen this object before - // Create new entry and add to map - result = CACHE_UPDATE_ADDED; - entry = new LLVOCacheEntry(local_id, crc, dp); - record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(0)); - - mImpl->mCacheMap[local_id] = entry; - - decodeBoundingInfo(entry); - } - entry->setUpdateFlags(flags); - - return result; - } + // we haven't seen this object before + // Create new entry and add to map + result = CACHE_UPDATE_ADDED; + entry = new LLVOCacheEntry(local_id, crc, dp); + record(LLStatViewer::OBJECT_CACHE_HIT_RATE, LLUnits::Ratio::fromValue(0)); + + mImpl->mCacheMap[local_id] = entry; + + decodeBoundingInfo(entry); + } + entry->setUpdateFlags(flags); + + return result; + } LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags) { - eCacheUpdateResult result = cacheFullUpdate(dp, flags); + eCacheUpdateResult result = cacheFullUpdate(dp, flags); - return result; + return result; } void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data) @@ -2764,216 +2764,216 @@ void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id) { - if(!sVOCacheCullingEnabled) - { - return NULL; - } + if(!sVOCacheCullingEnabled) + { + return NULL; + } - LLVOCacheEntry* entry = getCacheEntry(local_id); - removeFromVOCacheTree(entry); - - return entry; + LLVOCacheEntry* entry = getCacheEntry(local_id); + removeFromVOCacheTree(entry); + + return entry; } LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id, bool valid) { - LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id); - if(iter != mImpl->mCacheMap.end()) - { - if(!valid || iter->second->isValid()) - { - return iter->second; - } - } - return NULL; + LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id); + if(iter != mImpl->mCacheMap.end()) + { + if(!valid || iter->second->isValid()) + { + return iter->second; + } + } + return NULL; } void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType cache_miss_type) { - mRegionCacheMissCount++; + mRegionCacheMissCount++; mCacheMissList.push_back(CacheMissItem(id, cache_miss_type)); } //check if a non-cacheable object is already created. bool LLViewerRegion::isNonCacheableObjectCreated(U32 local_id) { - if(mImpl && local_id > 0 && mImpl->mNonCacheableCreatedList.find(local_id) != mImpl->mNonCacheableCreatedList.end()) - { - return true; - } - return false; + if(mImpl && local_id > 0 && mImpl->mNonCacheableCreatedList.find(local_id) != mImpl->mNonCacheableCreatedList.end()) + { + return true; + } + return false; } - + void LLViewerRegion::removeFromCreatedList(U32 local_id) -{ - if(mImpl && local_id > 0) - { - std::set::iterator iter = mImpl->mNonCacheableCreatedList.find(local_id); - if(iter != mImpl->mNonCacheableCreatedList.end()) - { - mImpl->mNonCacheableCreatedList.erase(iter); - } - } - } +{ + if(mImpl && local_id > 0) + { + std::set::iterator iter = mImpl->mNonCacheableCreatedList.find(local_id); + if(iter != mImpl->mNonCacheableCreatedList.end()) + { + mImpl->mNonCacheableCreatedList.erase(iter); + } + } + } void LLViewerRegion::addToCreatedList(U32 local_id) { - if(mImpl && local_id > 0) - { - mImpl->mNonCacheableCreatedList.insert(local_id); - } + if(mImpl && local_id > 0) + { + mImpl->mNonCacheableCreatedList.insert(local_id); + } } // Get data packer for this object, if we have cached data // AND the CRC matches. JC bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type) { - //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 + //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 - LLVOCacheEntry* entry = getCacheEntry(local_id, false); + LLVOCacheEntry* entry = getCacheEntry(local_id, false); - if (entry) - { - // we've seen this object before - if (entry->getCRC() == crc) - { - // Record a hit - mRegionCacheHitCount++; - entry->recordHit(); + if (entry) + { + // we've seen this object before + if (entry->getCRC() == crc) + { + // Record a hit + mRegionCacheHitCount++; + entry->recordHit(); cache_miss_type = CACHE_MISS_TYPE_NONE; - entry->setUpdateFlags(flags); - - if(entry->isState(LLVOCacheEntry::ACTIVE)) - { - ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj()->loadFlags(flags); - return true; - } - - if(entry->isValid()) - { - return true; //already probed - } - - entry->setValid(); - decodeBoundingInfo(entry); + entry->setUpdateFlags(flags); + + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj()->loadFlags(flags); + return true; + } + + if(entry->isValid()) + { + return true; //already probed + } + + entry->setValid(); + decodeBoundingInfo(entry); //loadCacheMiscExtras(local_id, entry, crc); - return true; - } - else - { - // LL_INFOS() << "CRC miss for " << local_id << LL_ENDL; + return true; + } + else + { + // LL_INFOS() << "CRC miss for " << local_id << LL_ENDL; - addCacheMiss(local_id, CACHE_MISS_TYPE_CRC); + addCacheMiss(local_id, CACHE_MISS_TYPE_CRC); cache_miss_type = CACHE_MISS_TYPE_CRC; - } - } - else - { // Total miss, don't have the object in cache - // LL_INFOS() << "Cache miss for " << local_id << LL_ENDL; + } + } + else + { // Total miss, don't have the object in cache + // LL_INFOS() << "Cache miss for " << local_id << LL_ENDL; addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL); cache_miss_type = CACHE_MISS_TYPE_TOTAL; - } + } - return false; + return false; } void LLViewerRegion::addCacheMissFull(const U32 local_id) { - addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL); + addCacheMiss(local_id, CACHE_MISS_TYPE_TOTAL); } void LLViewerRegion::requestCacheMisses() { - if (!mCacheMissList.size()) - { - return; - } - - LLMessageSystem* msg = gMessageSystem; - BOOL start_new_message = TRUE; - S32 blocks = 0; - - //send requests for all cache-missed objects - for (CacheMissItem::cache_miss_list_t::iterator iter = mCacheMissList.begin(); iter != mCacheMissList.end(); ++iter) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, (*iter).mType); - msg->addU32Fast(_PREHASH_ID, (*iter).mID); + if (!mCacheMissList.size()) + { + return; + } + + LLMessageSystem* msg = gMessageSystem; + BOOL start_new_message = TRUE; + S32 blocks = 0; + + //send requests for all cache-missed objects + for (CacheMissItem::cache_miss_list_t::iterator iter = mCacheMissList.begin(); iter != mCacheMissList.end(); ++iter) + { + if (start_new_message) + { + msg->newMessageFast(_PREHASH_RequestMultipleObjects); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + start_new_message = FALSE; + } + + msg->nextBlockFast(_PREHASH_ObjectData); + msg->addU8Fast(_PREHASH_CacheMissType, (*iter).mType); + msg->addU32Fast(_PREHASH_ID, (*iter).mID); LL_DEBUGS("AnimatedObjects") << "Requesting cache missed object " << (*iter).mID << LL_ENDL; - - blocks++; - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } + blocks++; - // finish any pending message - if (!start_new_message) - { - sendReliableMessage(); - } + if (blocks >= 255) + { + sendReliableMessage(); + start_new_message = TRUE; + blocks = 0; + } + } - mCacheDirty = TRUE ; - // LL_INFOS() << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << LL_ENDL; - LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size()); + // finish any pending message + if (!start_new_message) + { + sendReliableMessage(); + } + + mCacheDirty = TRUE ; + // LL_INFOS() << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << LL_ENDL; + LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size()); - mCacheMissList.clear(); + mCacheMissList.clear(); } void LLViewerRegion::dumpCache() { - const S32 BINS = 4; - S32 hit_bin[BINS]; - S32 change_bin[BINS]; + const S32 BINS = 4; + S32 hit_bin[BINS]; + S32 change_bin[BINS]; - S32 i; - for (i = 0; i < BINS; ++i) - { - hit_bin[i] = 0; - change_bin[i] = 0; - } + S32 i; + for (i = 0; i < BINS; ++i) + { + hit_bin[i] = 0; + change_bin[i] = 0; + } - LLVOCacheEntry *entry; - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - entry = iter->second ; + LLVOCacheEntry *entry; + for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) + { + entry = iter->second ; - S32 hits = entry->getHitCount(); - S32 changes = entry->getCRCChangeCount(); + S32 hits = entry->getHitCount(); + S32 changes = entry->getCRCChangeCount(); - hits = llclamp(hits, 0, BINS-1); - changes = llclamp(changes, 0, BINS-1); + hits = llclamp(hits, 0, BINS-1); + changes = llclamp(changes, 0, BINS-1); - hit_bin[hits]++; - change_bin[changes]++; - } + hit_bin[hits]++; + change_bin[changes]++; + } - LL_INFOS() << "Count " << mImpl->mCacheMap.size() << LL_ENDL; - for (i = 0; i < BINS; i++) - { - LL_INFOS() << "Hits " << i << " " << hit_bin[i] << LL_ENDL; - } - for (i = 0; i < BINS; i++) - { - LL_INFOS() << "Changes " << i << " " << change_bin[i] << LL_ENDL; - } - // TODO - add overrides cache too + LL_INFOS() << "Count " << mImpl->mCacheMap.size() << LL_ENDL; + for (i = 0; i < BINS; i++) + { + LL_INFOS() << "Hits " << i << " " << hit_bin[i] << LL_ENDL; + } + for (i = 0; i < BINS; i++) + { + LL_INFOS() << "Changes " << i << " " << change_bin[i] << LL_ENDL; + } + // TODO - add overrides cache too } void LLViewerRegion::clearVOCacheFromMemory() @@ -2983,315 +2983,315 @@ void LLViewerRegion::clearVOCacheFromMemory() void LLViewerRegion::unpackRegionHandshake() { - LLMessageSystem *msg = gMessageSystem; - - U64 region_flags = 0; - U64 region_protocols = 0; - U8 sim_access; - std::string sim_name; - LLUUID sim_owner; - BOOL is_estate_manager; - F32 water_height; - F32 billable_factor; - LLUUID cache_id; - - msg->getU8 ("RegionInfo", "SimAccess", sim_access); - msg->getString ("RegionInfo", "SimName", sim_name); - msg->getUUID ("RegionInfo", "SimOwner", sim_owner); - msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); - msg->getF32 ("RegionInfo", "WaterHeight", water_height); - msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); - msg->getUUID ("RegionInfo", "CacheID", cache_id ); - - if (msg->has(_PREHASH_RegionInfo4)) - { - msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionFlagsExtended, region_flags); - msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionProtocols, region_protocols); - } - else - { - U32 flags = 0; - msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); - region_flags = flags; - } - - setRegionFlags(region_flags); - setRegionProtocols(region_protocols); - setSimAccess(sim_access); - setRegionNameAndZone(sim_name); - setOwner(sim_owner); - setIsEstateManager(is_estate_manager); - setWaterHeight(water_height); - setBillableFactor(billable_factor); - setCacheID(cache_id); - - LLUUID region_id; - msg->getUUID("RegionInfo2", "RegionID", region_id); - setRegionID(region_id); - - // Retrieve the CR-53 (Homestead/Land SKU) information - S32 classID = 0; - S32 cpuRatio = 0; - std::string coloName; - std::string productSKU; - std::string productName; - - // the only reasonable way to decide if we actually have any data is to - // check to see if any of these fields have positive sizes - if (msg->getSize("RegionInfo3", "ColoName") > 0 || - msg->getSize("RegionInfo3", "ProductSKU") > 0 || - msg->getSize("RegionInfo3", "ProductName") > 0) - { - msg->getS32 ("RegionInfo3", "CPUClassID", classID); - msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); - msg->getString ("RegionInfo3", "ColoName", coloName); - msg->getString ("RegionInfo3", "ProductSKU", productSKU); - msg->getString ("RegionInfo3", "ProductName", productName); - - mClassID = classID; - mCPURatio = cpuRatio; - mColoName = coloName; - mProductSKU = productSKU; - mProductName = productName; - } - - mCentralBakeVersion = region_protocols & 1; // was (S32)gSavedSettings.getBOOL("UseServerTextureBaking"); - LLVLComposition *compp = getComposition(); - if (compp) - { - LLUUID tmp_id; - - bool changed = false; - - // Get the 4 textures for land - msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); - changed |= (tmp_id != compp->getDetailAssetID(0)); - compp->setDetailAssetID(0, tmp_id); - - msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); - changed |= (tmp_id != compp->getDetailAssetID(1)); - compp->setDetailAssetID(1, tmp_id); - - msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); - changed |= (tmp_id != compp->getDetailAssetID(2)); - compp->setDetailAssetID(2, tmp_id); - - msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); - changed |= (tmp_id != compp->getDetailAssetID(3)); - compp->setDetailAssetID(3, tmp_id); - - // Get the start altitude and range values for land textures - F32 tmp_f32; - msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); - changed |= (tmp_f32 != compp->getStartHeight(0)); - compp->setStartHeight(0, tmp_f32); - - msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); - changed |= (tmp_f32 != compp->getStartHeight(1)); - compp->setStartHeight(1, tmp_f32); - - msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); - changed |= (tmp_f32 != compp->getStartHeight(2)); - compp->setStartHeight(2, tmp_f32); - - msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); - changed |= (tmp_f32 != compp->getStartHeight(3)); - compp->setStartHeight(3, tmp_f32); - - - msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); - changed |= (tmp_f32 != compp->getHeightRange(0)); - compp->setHeightRange(0, tmp_f32); - - msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); - changed |= (tmp_f32 != compp->getHeightRange(1)); - compp->setHeightRange(1, tmp_f32); - - msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); - changed |= (tmp_f32 != compp->getHeightRange(2)); - compp->setHeightRange(2, tmp_f32); - - msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); - changed |= (tmp_f32 != compp->getHeightRange(3)); - compp->setHeightRange(3, tmp_f32); - - // If this is an UPDATE (params already ready, we need to regenerate - // all of our terrain stuff, by - if (compp->getParamsReady()) - { - // Update if the land changed - if (changed) - { - getLand().dirtyAllPatches(); - } - } - else - { - compp->setParamsReady(); - } - } - - - // Now that we have the name, we can load the cache file - // off disk. - loadObjectCache(); - - // After loading cache, signal that simulator can start - // sending data. - // TODO: Send all upstream viewer->sim handshake info here. - LLHost host = msg->getSender(); - msg->newMessage("RegionHandshakeReply"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("RegionInfo"); - - U32 flags = 0; - flags |= REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE; - - if(sVOCacheCullingEnabled) - { - flags |= 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects. - } - if(mImpl->mCacheMap.empty()) - { - flags |= 0x00000002; //set the bit 1 to be 1 to tell sim the cache file is empty, no need to send cache probes. - } - msg->addU32("Flags", flags ); - msg->sendReliable(host); - - mRegionTimer.reset(); //reset region timer. + LLMessageSystem *msg = gMessageSystem; + + U64 region_flags = 0; + U64 region_protocols = 0; + U8 sim_access; + std::string sim_name; + LLUUID sim_owner; + BOOL is_estate_manager; + F32 water_height; + F32 billable_factor; + LLUUID cache_id; + + msg->getU8 ("RegionInfo", "SimAccess", sim_access); + msg->getString ("RegionInfo", "SimName", sim_name); + msg->getUUID ("RegionInfo", "SimOwner", sim_owner); + msg->getBOOL ("RegionInfo", "IsEstateManager", is_estate_manager); + msg->getF32 ("RegionInfo", "WaterHeight", water_height); + msg->getF32 ("RegionInfo", "BillableFactor", billable_factor); + msg->getUUID ("RegionInfo", "CacheID", cache_id ); + + if (msg->has(_PREHASH_RegionInfo4)) + { + msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionFlagsExtended, region_flags); + msg->getU64Fast(_PREHASH_RegionInfo4, _PREHASH_RegionProtocols, region_protocols); + } + else + { + U32 flags = 0; + msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); + region_flags = flags; + } + + setRegionFlags(region_flags); + setRegionProtocols(region_protocols); + setSimAccess(sim_access); + setRegionNameAndZone(sim_name); + setOwner(sim_owner); + setIsEstateManager(is_estate_manager); + setWaterHeight(water_height); + setBillableFactor(billable_factor); + setCacheID(cache_id); + + LLUUID region_id; + msg->getUUID("RegionInfo2", "RegionID", region_id); + setRegionID(region_id); + + // Retrieve the CR-53 (Homestead/Land SKU) information + S32 classID = 0; + S32 cpuRatio = 0; + std::string coloName; + std::string productSKU; + std::string productName; + + // the only reasonable way to decide if we actually have any data is to + // check to see if any of these fields have positive sizes + if (msg->getSize("RegionInfo3", "ColoName") > 0 || + msg->getSize("RegionInfo3", "ProductSKU") > 0 || + msg->getSize("RegionInfo3", "ProductName") > 0) + { + msg->getS32 ("RegionInfo3", "CPUClassID", classID); + msg->getS32 ("RegionInfo3", "CPURatio", cpuRatio); + msg->getString ("RegionInfo3", "ColoName", coloName); + msg->getString ("RegionInfo3", "ProductSKU", productSKU); + msg->getString ("RegionInfo3", "ProductName", productName); + + mClassID = classID; + mCPURatio = cpuRatio; + mColoName = coloName; + mProductSKU = productSKU; + mProductName = productName; + } + + mCentralBakeVersion = region_protocols & 1; // was (S32)gSavedSettings.getBOOL("UseServerTextureBaking"); + LLVLComposition *compp = getComposition(); + if (compp) + { + LLUUID tmp_id; + + bool changed = false; + + // Get the 4 textures for land + msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(0)); + compp->setDetailAssetID(0, tmp_id); + + msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(1)); + compp->setDetailAssetID(1, tmp_id); + + msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(2)); + compp->setDetailAssetID(2, tmp_id); + + msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); + changed |= (tmp_id != compp->getDetailAssetID(3)); + compp->setDetailAssetID(3, tmp_id); + + // Get the start altitude and range values for land textures + F32 tmp_f32; + msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(0)); + compp->setStartHeight(0, tmp_f32); + + msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(1)); + compp->setStartHeight(1, tmp_f32); + + msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(2)); + compp->setStartHeight(2, tmp_f32); + + msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(3)); + compp->setStartHeight(3, tmp_f32); + + + msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(0)); + compp->setHeightRange(0, tmp_f32); + + msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(1)); + compp->setHeightRange(1, tmp_f32); + + msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(2)); + compp->setHeightRange(2, tmp_f32); + + msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(3)); + compp->setHeightRange(3, tmp_f32); + + // If this is an UPDATE (params already ready, we need to regenerate + // all of our terrain stuff, by + if (compp->getParamsReady()) + { + // Update if the land changed + if (changed) + { + getLand().dirtyAllPatches(); + } + } + else + { + compp->setParamsReady(); + } + } + + + // Now that we have the name, we can load the cache file + // off disk. + loadObjectCache(); + + // After loading cache, signal that simulator can start + // sending data. + // TODO: Send all upstream viewer->sim handshake info here. + LLHost host = msg->getSender(); + msg->newMessage("RegionHandshakeReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("RegionInfo"); + + U32 flags = 0; + flags |= REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE; + + if(sVOCacheCullingEnabled) + { + flags |= 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects. + } + if(mImpl->mCacheMap.empty()) + { + flags |= 0x00000002; //set the bit 1 to be 1 to tell sim the cache file is empty, no need to send cache probes. + } + msg->addU32("Flags", flags ); + msg->sendReliable(host); + + mRegionTimer.reset(); //reset region timer. } // static void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { - capabilityNames.append("AbuseCategories"); - capabilityNames.append("AcceptFriendship"); - capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! - capabilityNames.append("AgentPreferences"); + capabilityNames.append("AbuseCategories"); + capabilityNames.append("AcceptFriendship"); + capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! + capabilityNames.append("AgentPreferences"); capabilityNames.append("AgentProfile"); - capabilityNames.append("AgentState"); - capabilityNames.append("AttachmentResources"); - capabilityNames.append("AvatarPickerSearch"); - capabilityNames.append("AvatarRenderInfo"); - capabilityNames.append("CharacterProperties"); - capabilityNames.append("ChatSessionRequest"); - capabilityNames.append("CopyInventoryFromNotecard"); - capabilityNames.append("CreateInventoryCategory"); - capabilityNames.append("DeclineFriendship"); - capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!! - capabilityNames.append("DispatchRegionInfo"); - capabilityNames.append("DirectDelivery"); - capabilityNames.append("EnvironmentSettings"); - capabilityNames.append("EstateAccess"); - capabilityNames.append("EstateChangeInfo"); - capabilityNames.append("EventQueueGet"); + capabilityNames.append("AgentState"); + capabilityNames.append("AttachmentResources"); + capabilityNames.append("AvatarPickerSearch"); + capabilityNames.append("AvatarRenderInfo"); + capabilityNames.append("CharacterProperties"); + capabilityNames.append("ChatSessionRequest"); + capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("CreateInventoryCategory"); + capabilityNames.append("DeclineFriendship"); + capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!! + capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("DirectDelivery"); + capabilityNames.append("EnvironmentSettings"); + capabilityNames.append("EstateAccess"); + capabilityNames.append("EstateChangeInfo"); + capabilityNames.append("EventQueueGet"); capabilityNames.append("ExtEnvironment"); - capabilityNames.append("FetchLib2"); - capabilityNames.append("FetchLibDescendents2"); - capabilityNames.append("FetchInventory2"); - capabilityNames.append("FetchInventoryDescendents2"); - capabilityNames.append("IncrementCOFVersion"); - AISAPI::getCapNames(capabilityNames); + capabilityNames.append("FetchLib2"); + capabilityNames.append("FetchLibDescendents2"); + capabilityNames.append("FetchInventory2"); + capabilityNames.append("FetchInventoryDescendents2"); + capabilityNames.append("IncrementCOFVersion"); + AISAPI::getCapNames(capabilityNames); - capabilityNames.append("InterestList"); + capabilityNames.append("InterestList"); capabilityNames.append("InventoryThumbnailUpload"); - capabilityNames.append("GetDisplayNames"); - capabilityNames.append("GetExperiences"); - capabilityNames.append("AgentExperiences"); - capabilityNames.append("FindExperienceByName"); - capabilityNames.append("GetExperienceInfo"); - capabilityNames.append("GetAdminExperiences"); - capabilityNames.append("GetCreatorExperiences"); - capabilityNames.append("ExperiencePreferences"); - capabilityNames.append("GroupExperiences"); - capabilityNames.append("UpdateExperience"); - capabilityNames.append("IsExperienceAdmin"); - capabilityNames.append("IsExperienceContributor"); - capabilityNames.append("RegionExperiences"); + capabilityNames.append("GetDisplayNames"); + capabilityNames.append("GetExperiences"); + capabilityNames.append("AgentExperiences"); + capabilityNames.append("FindExperienceByName"); + capabilityNames.append("GetExperienceInfo"); + capabilityNames.append("GetAdminExperiences"); + capabilityNames.append("GetCreatorExperiences"); + capabilityNames.append("ExperiencePreferences"); + capabilityNames.append("GroupExperiences"); + capabilityNames.append("UpdateExperience"); + capabilityNames.append("IsExperienceAdmin"); + capabilityNames.append("IsExperienceContributor"); + capabilityNames.append("RegionExperiences"); capabilityNames.append("ExperienceQuery"); - capabilityNames.append("GetMetadata"); - capabilityNames.append("GetObjectCost"); - capabilityNames.append("GetObjectPhysicsData"); - capabilityNames.append("GroupAPIv1"); - capabilityNames.append("GroupMemberData"); - capabilityNames.append("GroupProposalBallot"); - capabilityNames.append("HomeLocation"); - capabilityNames.append("LandResources"); - capabilityNames.append("LSLSyntax"); - capabilityNames.append("MapLayer"); - capabilityNames.append("MapLayerGod"); - capabilityNames.append("MeshUploadFlag"); - capabilityNames.append("ModifyMaterialParams"); - capabilityNames.append("NavMeshGenerationStatus"); - capabilityNames.append("NewFileAgentInventory"); - capabilityNames.append("ObjectAnimation"); - capabilityNames.append("ObjectMedia"); - capabilityNames.append("ObjectMediaNavigate"); - capabilityNames.append("ObjectNavMeshProperties"); - capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelVoiceInfoRequest"); - capabilityNames.append("ProductInfoRequest"); - capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite - capabilityNames.append("RegionObjects"); - capabilityNames.append("RemoteParcelRequest"); - capabilityNames.append("RenderMaterials"); - capabilityNames.append("RequestTextureDownload"); - capabilityNames.append("ResourceCostSelected"); - capabilityNames.append("RetrieveNavMeshSrc"); - capabilityNames.append("SearchStatRequest"); - capabilityNames.append("SearchStatTracking"); - capabilityNames.append("SendPostcard"); - capabilityNames.append("SendUserReport"); - capabilityNames.append("SendUserReportWithScreenshot"); - capabilityNames.append("ServerReleaseNotes"); - capabilityNames.append("SetDisplayName"); - capabilityNames.append("SimConsoleAsync"); - capabilityNames.append("SimulatorFeatures"); - capabilityNames.append("StartGroupProposal"); - capabilityNames.append("TerrainNavMeshProperties"); - capabilityNames.append("TextureStats"); - capabilityNames.append("UntrustedSimulatorMessage"); - capabilityNames.append("UpdateAgentInformation"); - capabilityNames.append("UpdateAgentLanguage"); - capabilityNames.append("UpdateAvatarAppearance"); - capabilityNames.append("UpdateGestureAgentInventory"); - capabilityNames.append("UpdateGestureTaskInventory"); - capabilityNames.append("UpdateNotecardAgentInventory"); - capabilityNames.append("UpdateNotecardTaskInventory"); - capabilityNames.append("UpdateScriptAgent"); - capabilityNames.append("UpdateScriptTask"); + capabilityNames.append("GetMetadata"); + capabilityNames.append("GetObjectCost"); + capabilityNames.append("GetObjectPhysicsData"); + capabilityNames.append("GroupAPIv1"); + capabilityNames.append("GroupMemberData"); + capabilityNames.append("GroupProposalBallot"); + capabilityNames.append("HomeLocation"); + capabilityNames.append("LandResources"); + capabilityNames.append("LSLSyntax"); + capabilityNames.append("MapLayer"); + capabilityNames.append("MapLayerGod"); + capabilityNames.append("MeshUploadFlag"); + capabilityNames.append("ModifyMaterialParams"); + capabilityNames.append("NavMeshGenerationStatus"); + capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ObjectAnimation"); + capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate"); + capabilityNames.append("ObjectNavMeshProperties"); + capabilityNames.append("ParcelPropertiesUpdate"); + capabilityNames.append("ParcelVoiceInfoRequest"); + capabilityNames.append("ProductInfoRequest"); + capabilityNames.append("ProvisionVoiceAccountRequest"); + capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite + capabilityNames.append("RegionObjects"); + capabilityNames.append("RemoteParcelRequest"); + capabilityNames.append("RenderMaterials"); + capabilityNames.append("RequestTextureDownload"); + capabilityNames.append("ResourceCostSelected"); + capabilityNames.append("RetrieveNavMeshSrc"); + capabilityNames.append("SearchStatRequest"); + capabilityNames.append("SearchStatTracking"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); + capabilityNames.append("ServerReleaseNotes"); + capabilityNames.append("SetDisplayName"); + capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TerrainNavMeshProperties"); + capabilityNames.append("TextureStats"); + capabilityNames.append("UntrustedSimulatorMessage"); + capabilityNames.append("UpdateAgentInformation"); + capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateAvatarAppearance"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptAgent"); + capabilityNames.append("UpdateScriptTask"); capabilityNames.append("UpdateSettingsAgentInventory"); capabilityNames.append("UpdateSettingsTaskInventory"); capabilityNames.append("UploadAgentProfileImage"); capabilityNames.append("UpdateMaterialAgentInventory"); capabilityNames.append("UpdateMaterialTaskInventory"); - capabilityNames.append("UploadBakedTexture"); + capabilityNames.append("UploadBakedTexture"); capabilityNames.append("UserInfo"); - capabilityNames.append("ViewerAsset"); - capabilityNames.append("ViewerBenefits"); - capabilityNames.append("ViewerMetrics"); - capabilityNames.append("ViewerStartAuction"); - capabilityNames.append("ViewerStats"); + capabilityNames.append("ViewerAsset"); + capabilityNames.append("ViewerBenefits"); + capabilityNames.append("ViewerMetrics"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ViewerStats"); - // Please add new capabilities alphabetically to reduce - // merge conflicts. + // Please add new capabilities alphabetically to reduce + // merge conflicts. } void LLViewerRegion::setSeedCapability(const std::string& url) { - if (getCapability("Seed") == url) - { - setCapabilityDebug("Seed", url); - LL_WARNS("CrossingCaps") << "Received duplicate seed capability for " << getRegionID() << ", posting to seed " << - url << LL_ENDL; + if (getCapability("Seed") == url) + { + setCapabilityDebug("Seed", url); + LL_WARNS("CrossingCaps") << "Received duplicate seed capability for " << getRegionID() << ", posting to seed " << + url << LL_ENDL; - //Instead of just returning we build up a second set of seed caps and compare them - //to the "original" seed cap received and determine why there is problem! + //Instead of just returning we build up a second set of seed caps and compare them + //to the "original" seed cap received and determine why there is problem! std::string coroname = LLCoros::instance().launch("LLEnvironmentRequest::requestBaseCapabilitiesCompleteCoro", boost::bind(&LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro, getHandle())); @@ -3301,14 +3301,14 @@ void LLViewerRegion::setSeedCapability(const std::string& url) // Make sure we are still good to do LLCoros::checkStop(); - return; + return; } - - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - - mImpl->mCapabilities.clear(); - setCapability("Seed", url); + + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + + mImpl->mCapabilities.clear(); + setCapability("Seed", url); std::string coroname = LLCoros::instance().launch("LLViewerRegionImpl::requestBaseCapabilitiesCoro", @@ -3324,69 +3324,69 @@ void LLViewerRegion::setSeedCapability(const std::string& url) S32 LLViewerRegion::getNumSeedCapRetries() { - return mImpl->mSeedCapAttempts; + return mImpl->mSeedCapAttempts; } void LLViewerRegion::setCapability(const std::string& name, const std::string& url) { - if(name == "EventQueueGet") - { - delete mImpl->mEventPoll; - mImpl->mEventPoll = NULL; - mImpl->mEventPoll = new LLEventPoll(url, getHost()); - } - else if(name == "UntrustedSimulatorMessage") - { + if(name == "EventQueueGet") + { + delete mImpl->mEventPoll; + mImpl->mEventPoll = NULL; + mImpl->mEventPoll = new LLEventPoll(url, getHost()); + } + else if(name == "UntrustedSimulatorMessage") + { mImpl->mHost.setUntrustedSimulatorCap(url); - } - else if (name == "SimulatorFeatures") - { + } + else if (name == "SimulatorFeatures") + { mImpl->mCapabilities["SimulatorFeatures"] = url; requestSimulatorFeatures(); - } - else - { - mImpl->mCapabilities[name] = url; - if(name == "ViewerAsset") - { - /*==============================================================*/ - // The following inserted lines are a hack for testing MAINT-7081, - // which is why the indentation and formatting are left ugly. - const char* VIEWERASSET = getenv("VIEWERASSET"); - if (VIEWERASSET) - { - mImpl->mCapabilities[name] = VIEWERASSET; - mViewerAssetUrl = VIEWERASSET; - } - else - /*==============================================================*/ - mViewerAssetUrl = url; - } - } + } + else + { + mImpl->mCapabilities[name] = url; + if(name == "ViewerAsset") + { + /*==============================================================*/ + // The following inserted lines are a hack for testing MAINT-7081, + // which is why the indentation and formatting are left ugly. + const char* VIEWERASSET = getenv("VIEWERASSET"); + if (VIEWERASSET) + { + mImpl->mCapabilities[name] = VIEWERASSET; + mViewerAssetUrl = VIEWERASSET; + } + else + /*==============================================================*/ + mViewerAssetUrl = url; + } + } } void LLViewerRegion::setCapabilityDebug(const std::string& name, const std::string& url) { - // Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later. - if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) ) - { - mImpl->mSecondCapabilitiesTracker[name] = url; - if(name == "ViewerAsset") - { - /*==============================================================*/ - // The following inserted lines are a hack for testing MAINT-7081, - // which is why the indentation and formatting are left ugly. - const char* VIEWERASSET = getenv("VIEWERASSET"); - if (VIEWERASSET) - { - mImpl->mSecondCapabilitiesTracker[name] = VIEWERASSET; - mViewerAssetUrl = VIEWERASSET; - } - else - /*==============================================================*/ - mViewerAssetUrl = url; - } - } + // Continue to not add certain caps, as we do in setCapability. This is so they match up when we check them later. + if ( ! ( name == "EventQueueGet" || name == "UntrustedSimulatorMessage" || name == "SimulatorFeatures" ) ) + { + mImpl->mSecondCapabilitiesTracker[name] = url; + if(name == "ViewerAsset") + { + /*==============================================================*/ + // The following inserted lines are a hack for testing MAINT-7081, + // which is why the indentation and formatting are left ugly. + const char* VIEWERASSET = getenv("VIEWERASSET"); + if (VIEWERASSET) + { + mImpl->mSecondCapabilitiesTracker[name] = VIEWERASSET; + mViewerAssetUrl = VIEWERASSET; + } + else + /*==============================================================*/ + mViewerAssetUrl = url; + } + } } std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const @@ -3403,44 +3403,44 @@ std::string LLViewerRegion::getCapabilityDebug(const std::string& name) const bool LLViewerRegion::isSpecialCapabilityName(const std::string &name) { - return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; + return name == "EventQueueGet" || name == "UntrustedSimulatorMessage"; } std::string LLViewerRegion::getCapability(const std::string& name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) - { - LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL; - } - - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) - { - return ""; - } + if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + { + LL_WARNS() << "getCapability called before caps received for " << name << LL_ENDL; + } + + CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); + if(iter == mImpl->mCapabilities.end()) + { + return ""; + } - return iter->second; + return iter->second; } bool LLViewerRegion::isCapabilityAvailable(const std::string& name) const { - if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) - { - LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL; - } - - CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); - if(iter == mImpl->mCapabilities.end()) - { - return false; - } + if (!capabilitiesReceived() && (name!=std::string("Seed")) && (name!=std::string("ObjectMedia"))) + { + LL_WARNS() << "isCapabilityAvailable called before caps received for " << name << LL_ENDL; + } + + CapabilityMap::const_iterator iter = mImpl->mCapabilities.find(name); + if(iter == mImpl->mCapabilities.end()) + { + return false; + } - return true; + return true; } bool LLViewerRegion::capabilitiesReceived() const { - return mCapabilitiesState == CAPABILITIES_STATE_RECEIVED; + return mCapabilitiesState == CAPABILITIES_STATE_RECEIVED; } bool LLViewerRegion::capabilitiesError() const @@ -3450,22 +3450,22 @@ bool LLViewerRegion::capabilitiesError() const void LLViewerRegion::setCapabilitiesReceived(bool received) { - mCapabilitiesState = received ? CAPABILITIES_STATE_RECEIVED : CAPABILITIES_STATE_INIT; + mCapabilitiesState = received ? CAPABILITIES_STATE_RECEIVED : CAPABILITIES_STATE_INIT; - // Tell interested parties that we've received capabilities, - // so that they can safely use getCapability(). - if (received) - { - mCapabilitiesReceivedSignal(getRegionID(), this); + // Tell interested parties that we've received capabilities, + // so that they can safely use getCapability(). + if (received) + { + mCapabilitiesReceivedSignal(getRegionID(), this); - LLFloaterPermsDefault::sendInitialPerms(); + LLFloaterPermsDefault::sendInitialPerms(); - // This is a single-shot signal. Forget callbacks to save resources. - mCapabilitiesReceivedSignal.disconnect_all_slots(); + // This is a single-shot signal. Forget callbacks to save resources. + mCapabilitiesReceivedSignal.disconnect_all_slots(); - // Set the region to the desired interest list mode + // Set the region to the desired interest list mode setInterestListMode(gAgent.getInterestListMode()); - } + } } void LLViewerRegion::setCapabilitiesError() @@ -3475,12 +3475,12 @@ void LLViewerRegion::setCapabilitiesError() boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) { - return mCapabilitiesReceivedSignal.connect(cb); + return mCapabilitiesReceivedSignal.connect(cb); } void LLViewerRegion::logActiveCapabilities() const { - log_capabilities(mImpl->mCapabilities); + log_capabilities(mImpl->mCapabilities); } @@ -3491,7 +3491,7 @@ bool LLViewerRegion::requestPostCapability(const std::string &capName, LLSD &pos if (url.empty()) { LL_WARNS("Region") << "Could not retrieve region " << getRegionID() - << " POST capability \"" << capName << "\"" << LL_ENDL; + << " POST capability \"" << capName << "\"" << LL_ENDL; return false; } @@ -3538,14 +3538,14 @@ void LLViewerRegion::setInterestListMode(const std::string &new_mode) { mInterestListMode = new_mode; - if (mInterestListMode != std::string(IL_MODE_DEFAULT) && mInterestListMode != std::string(IL_MODE_360)) - { - LL_WARNS("360Capture") << "Region " << getRegionID() << " setInterestListMode() invalid interest list mode: " - << mInterestListMode << ", setting to default" << LL_ENDL; + if (mInterestListMode != std::string(IL_MODE_DEFAULT) && mInterestListMode != std::string(IL_MODE_360)) + { + LL_WARNS("360Capture") << "Region " << getRegionID() << " setInterestListMode() invalid interest list mode: " + << mInterestListMode << ", setting to default" << LL_ENDL; mInterestListMode = IL_MODE_DEFAULT; - } + } - LLSD body; + LLSD body; body["mode"] = mInterestListMode; if (requestPostCapability("InterestList", body, [](const LLSD &response) { @@ -3559,99 +3559,99 @@ void LLViewerRegion::setInterestListMode(const std::string &new_mode) } else { - LL_WARNS("360Capture") << "Region " << getRegionID() - << " Unable to post an InterestList capability request with payload: \n" + LL_WARNS("360Capture") << "Region " << getRegionID() + << " Unable to post an InterestList capability request with payload: \n" << ll_pretty_print_sd(body) << LL_ENDL; } } else { LL_DEBUGS("360Capture") << "Region " << getRegionID() << "No change, skipping Interest List mode POST to " - << new_mode << " mode" << LL_ENDL; + << new_mode << " mode" << LL_ENDL; } } void LLViewerRegion::resetInterestList() { - if (requestDelCapability("InterestList", [](const LLSD &response) { - LL_DEBUGS("360Capture") << "InterestList capability DEL responded: \n" << ll_pretty_print_sd(response) << LL_ENDL; - })) - { - LL_DEBUGS("360Capture") << "Region " << getRegionID() << " Successfully reset InterestList capability" << LL_ENDL; - } - else - { - LL_WARNS("360Capture") << "Region " << getRegionID() << " Unable to DEL InterestList capability request" << LL_ENDL; - } + if (requestDelCapability("InterestList", [](const LLSD &response) { + LL_DEBUGS("360Capture") << "InterestList capability DEL responded: \n" << ll_pretty_print_sd(response) << LL_ENDL; + })) + { + LL_DEBUGS("360Capture") << "Region " << getRegionID() << " Successfully reset InterestList capability" << LL_ENDL; + } + else + { + LL_WARNS("360Capture") << "Region " << getRegionID() << " Unable to DEL InterestList capability request" << LL_ENDL; + } } LLSpatialPartition *LLViewerRegion::getSpatialPartition(U32 type) { - if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE) - { - return (LLSpatialPartition*)mImpl->mObjectPartition[type]; - } - return NULL; + if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE) + { + return (LLSpatialPartition*)mImpl->mObjectPartition[type]; + } + return NULL; } LLVOCachePartition* LLViewerRegion::getVOCachePartition() { - if(PARTITION_VO_CACHE < mImpl->mObjectPartition.size()) - { - return (LLVOCachePartition*)mImpl->mObjectPartition[PARTITION_VO_CACHE]; - } - return NULL; + if(PARTITION_VO_CACHE < mImpl->mObjectPartition.size()) + { + return (LLVOCachePartition*)mImpl->mObjectPartition[PARTITION_VO_CACHE]; + } + return NULL; } // the viewer can not yet distinquish between normal- and estate-owned objects // so we collapse these two bits and enable the UI if either are set const U64 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT - | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const { - return (mParcelOverlay != NULL) - && (mParcelOverlay->isOwnedSelf(pos) - || mParcelOverlay->isOwnedGroup(pos) - || (getRegionFlag(ALLOW_RETURN_ENCROACHING_OBJECT) - && mParcelOverlay->encroachesOwned(boxes)) ); + return (mParcelOverlay != NULL) + && (mParcelOverlay->isOwnedSelf(pos) + || mParcelOverlay->isOwnedGroup(pos) + || (getRegionFlag(ALLOW_RETURN_ENCROACHING_OBJECT) + && mParcelOverlay->encroachesOwned(boxes)) ); } bool LLViewerRegion::childrenObjectReturnable( const std::vector& boxes ) const { - bool result = false; - result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; - return result; + bool result = false; + result = ( mParcelOverlay && mParcelOverlay->encroachesOnUnowned( boxes ) ) ? 1 : 0; + return result; } bool LLViewerRegion::objectsCrossParcel(const std::vector& boxes) const { - return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); + return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes); } void LLViewerRegion::getNeighboringRegions( std::vector& uniqueRegions ) { - mImpl->mLandp->getNeighboringRegions( uniqueRegions ); + mImpl->mLandp->getNeighboringRegions( uniqueRegions ); } void LLViewerRegion::getNeighboringRegionsStatus( std::vector& regions ) { - mImpl->mLandp->getNeighboringRegionsStatus( regions ); + mImpl->mLandp->getNeighboringRegionsStatus( regions ); } void LLViewerRegion::showReleaseNotes() { - std::string url = this->getCapability("ServerReleaseNotes"); + std::string url = this->getCapability("ServerReleaseNotes"); - if (url.empty()) { - // HACK haven't received the capability yet, we'll wait until - // it arives. - mReleaseNotesRequested = TRUE; - return; - } + if (url.empty()) { + // HACK haven't received the capability yet, we'll wait until + // it arives. + mReleaseNotesRequested = TRUE; + return; + } - LLWeb::loadURL(url); - mReleaseNotesRequested = FALSE; + LLWeb::loadURL(url); + mReleaseNotesRequested = FALSE; } std::string LLViewerRegion::getDescription() const @@ -3661,98 +3661,98 @@ std::string LLViewerRegion::getDescription() const bool LLViewerRegion::meshUploadEnabled() const { - return (mSimulatorFeatures.has("MeshUploadEnabled") && - mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); + return (mSimulatorFeatures.has("MeshUploadEnabled") && + mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); } bool LLViewerRegion::bakesOnMeshEnabled() const { - return (mSimulatorFeatures.has("BakesOnMeshEnabled") && - mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean()); + return (mSimulatorFeatures.has("BakesOnMeshEnabled") && + mSimulatorFeatures["BakesOnMeshEnabled"].asBoolean()); } bool LLViewerRegion::meshRezEnabled() const { - return (mSimulatorFeatures.has("MeshRezEnabled") && - mSimulatorFeatures["MeshRezEnabled"].asBoolean()); + return (mSimulatorFeatures.has("MeshRezEnabled") && + mSimulatorFeatures["MeshRezEnabled"].asBoolean()); } bool LLViewerRegion::dynamicPathfindingEnabled() const { - return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && - mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); + return ( mSimulatorFeatures.has("DynamicPathfindingEnabled") && + mSimulatorFeatures["DynamicPathfindingEnabled"].asBoolean()); } bool LLViewerRegion::avatarHoverHeightEnabled() const { - return ( mSimulatorFeatures.has("AvatarHoverHeightEnabled") && - mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean()); + return ( mSimulatorFeatures.has("AvatarHoverHeightEnabled") && + mSimulatorFeatures["AvatarHoverHeightEnabled"].asBoolean()); } /* Static Functions */ void log_capabilities(const CapabilityMap &capmap) { - S32 count = 0; - CapabilityMap::const_iterator iter; - for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count) - { - if (!iter->second.empty()) - { - LL_INFOS() << "log_capabilities: " << iter->first << " URL is " << iter->second << LL_ENDL; - } - } - LL_INFOS() << "log_capabilities: Dumped " << count << " entries." << LL_ENDL; + S32 count = 0; + CapabilityMap::const_iterator iter; + for (iter = capmap.begin(); iter != capmap.end(); ++iter, ++count) + { + if (!iter->second.empty()) + { + LL_INFOS() << "log_capabilities: " << iter->first << " URL is " << iter->second << LL_ENDL; + } + } + LL_INFOS() << "log_capabilities: Dumped " << count << " entries." << LL_ENDL; } void LLViewerRegion::resetMaterialsCapThrottle() { - F32 requests_per_sec = 1.0f; // original default; - if ( mSimulatorFeatures.has("RenderMaterialsCapability") - && mSimulatorFeatures["RenderMaterialsCapability"].isReal() ) - { - requests_per_sec = mSimulatorFeatures["RenderMaterialsCapability"].asReal(); - if ( requests_per_sec == 0.0f ) - { - requests_per_sec = 1.0f; - LL_WARNS("Materials") - << "region '" << getName() - << "' returned zero for RenderMaterialsCapability; using default " - << requests_per_sec << " per second" - << LL_ENDL; - } - LL_DEBUGS("Materials") << "region '" << getName() - << "' RenderMaterialsCapability " << requests_per_sec - << LL_ENDL; - } - else - { - LL_DEBUGS("Materials") - << "region '" << getName() - << "' did not return RenderMaterialsCapability, using default " - << requests_per_sec << " per second" - << LL_ENDL; - } - - mMaterialsCapThrottleTimer.resetWithExpiry( 1.0f / requests_per_sec ); + F32 requests_per_sec = 1.0f; // original default; + if ( mSimulatorFeatures.has("RenderMaterialsCapability") + && mSimulatorFeatures["RenderMaterialsCapability"].isReal() ) + { + requests_per_sec = mSimulatorFeatures["RenderMaterialsCapability"].asReal(); + if ( requests_per_sec == 0.0f ) + { + requests_per_sec = 1.0f; + LL_WARNS("Materials") + << "region '" << getName() + << "' returned zero for RenderMaterialsCapability; using default " + << requests_per_sec << " per second" + << LL_ENDL; + } + LL_DEBUGS("Materials") << "region '" << getName() + << "' RenderMaterialsCapability " << requests_per_sec + << LL_ENDL; + } + else + { + LL_DEBUGS("Materials") + << "region '" << getName() + << "' did not return RenderMaterialsCapability, using default " + << requests_per_sec << " per second" + << LL_ENDL; + } + + mMaterialsCapThrottleTimer.resetWithExpiry( 1.0f / requests_per_sec ); } U32 LLViewerRegion::getMaxMaterialsPerTransaction() const { - U32 max_entries = 50; // original hard coded default - if ( mSimulatorFeatures.has( "MaxMaterialsPerTransaction" ) - && mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].isInteger()) - { - max_entries = mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].asInteger(); - } - return max_entries; + U32 max_entries = 50; // original hard coded default + if ( mSimulatorFeatures.has( "MaxMaterialsPerTransaction" ) + && mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].isInteger()) + { + max_entries = mSimulatorFeatures[ "MaxMaterialsPerTransaction" ].asInteger(); + } + return max_entries; } std::string LLViewerRegion::getSimHostName() { - if (mSimulatorFeaturesReceived) - { - return mSimulatorFeatures.has("HostName") ? mSimulatorFeatures["HostName"].asString() : getHost().getHostName(); - } - return std::string("..."); + if (mSimulatorFeaturesReceived) + { + return mSimulatorFeatures.has("HostName") ? mSimulatorFeatures["HostName"].asString() : getHost().getHostName(); + } + return std::string("..."); } void LLViewerRegion::applyCacheMiscExtras(LLViewerObject* obj) diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 1c89cc4e6d..f1c40dbe9d 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -1,25 +1,25 @@ -/** +/** * @file llviewerregion.h * @brief Description of the LLViewerRegion class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -40,14 +40,14 @@ #include "lluuid.h" #include "llweb.h" #include "llcapabilityprovider.h" -#include "m4math.h" // LLMatrix4 +#include "m4math.h" // LLMatrix4 #include "llframetimer.h" #include "llreflectionmap.h" // Surface id's #define LAND 1 #define WATER 2 -const U32 MAX_OBJECT_CACHE_ENTRIES = 50000; +const U32 MAX_OBJECT_CACHE_ENTRIES = 50000; // Region handshake flags const U32 REGION_HANDSHAKE_SUPPORTS_SELF_APPEARANCE = 1U << 2; @@ -77,214 +77,214 @@ class LLVOCachePartition; class LLViewerRegion: public LLCapabilityProvider // implements this interface { public: - //MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR - typedef enum - { - PARTITION_HUD=0, - PARTITION_TERRAIN, - PARTITION_VOIDWATER, - PARTITION_WATER, - PARTITION_TREE, - PARTITION_PARTICLE, - PARTITION_GRASS, - PARTITION_VOLUME, - PARTITION_BRIDGE, - PARTITION_AVATAR, - PARTITION_CONTROL_AV, // Animesh - PARTITION_HUD_PARTICLE, - PARTITION_VO_CACHE, - PARTITION_NONE, - NUM_PARTITIONS - } eObjectPartitions; - - typedef boost::signals2::signal caps_received_signal_t; - - LLViewerRegion(const U64 &handle, - const LLHost &host, - const U32 surface_grid_width, - const U32 patch_grid_width, - const F32 region_width_meters); - ~LLViewerRegion(); - - // Call this after you have the region name and handle. - void loadObjectCache(); - void saveObjectCache(); - - void sendMessage(); // Send the current message to this region's simulator - void sendReliableMessage(); // Send the current message to this region's simulator - - void setOriginGlobal(const LLVector3d &origin); - //void setAgentOffset(const LLVector3d &offset); - void updateRenderMatrix(); - - void setAllowDamage(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DAMAGE, b); } - void setAllowLandmark(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_LANDMARK, b); } - void setAllowSetHome(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_SET_HOME, b); } - void setResetHomeOnTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_RESET_HOME_ON_TELEPORT, b); } - void setSunFixed(BOOL b) { setRegionFlag(REGION_FLAGS_SUN_FIXED, b); } - //void setBlockFly(BOOL b) { setRegionFlag(REGION_FLAGS_BLOCK_FLY, b); } Never used - void setAllowDirectTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, b); } - - - inline BOOL getAllowDamage() const; - inline BOOL getAllowLandmark() const; - inline BOOL getAllowSetHome() const; - inline BOOL getResetHomeOnTeleport() const; - inline BOOL getSunFixed() const; - inline BOOL getBlockFly() const; - inline BOOL getAllowDirectTeleport() const; - inline BOOL isPrelude() const; - inline BOOL getAllowTerraform() const; - inline BOOL getRestrictPushObject() const; + //MUST MATCH THE ORDER OF DECLARATION IN CONSTRUCTOR + typedef enum + { + PARTITION_HUD=0, + PARTITION_TERRAIN, + PARTITION_VOIDWATER, + PARTITION_WATER, + PARTITION_TREE, + PARTITION_PARTICLE, + PARTITION_GRASS, + PARTITION_VOLUME, + PARTITION_BRIDGE, + PARTITION_AVATAR, + PARTITION_CONTROL_AV, // Animesh + PARTITION_HUD_PARTICLE, + PARTITION_VO_CACHE, + PARTITION_NONE, + NUM_PARTITIONS + } eObjectPartitions; + + typedef boost::signals2::signal caps_received_signal_t; + + LLViewerRegion(const U64 &handle, + const LLHost &host, + const U32 surface_grid_width, + const U32 patch_grid_width, + const F32 region_width_meters); + ~LLViewerRegion(); + + // Call this after you have the region name and handle. + void loadObjectCache(); + void saveObjectCache(); + + void sendMessage(); // Send the current message to this region's simulator + void sendReliableMessage(); // Send the current message to this region's simulator + + void setOriginGlobal(const LLVector3d &origin); + //void setAgentOffset(const LLVector3d &offset); + void updateRenderMatrix(); + + void setAllowDamage(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DAMAGE, b); } + void setAllowLandmark(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_LANDMARK, b); } + void setAllowSetHome(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_SET_HOME, b); } + void setResetHomeOnTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_RESET_HOME_ON_TELEPORT, b); } + void setSunFixed(BOOL b) { setRegionFlag(REGION_FLAGS_SUN_FIXED, b); } + //void setBlockFly(BOOL b) { setRegionFlag(REGION_FLAGS_BLOCK_FLY, b); } Never used + void setAllowDirectTeleport(BOOL b) { setRegionFlag(REGION_FLAGS_ALLOW_DIRECT_TELEPORT, b); } + + + inline BOOL getAllowDamage() const; + inline BOOL getAllowLandmark() const; + inline BOOL getAllowSetHome() const; + inline BOOL getResetHomeOnTeleport() const; + inline BOOL getSunFixed() const; + inline BOOL getBlockFly() const; + inline BOOL getAllowDirectTeleport() const; + inline BOOL isPrelude() const; + inline BOOL getAllowTerraform() const; + inline BOOL getRestrictPushObject() const; inline BOOL getAllowEnvironmentOverride() const; - inline BOOL getReleaseNotesRequested() const; + inline BOOL getReleaseNotesRequested() const; - bool isAlive(); // can become false if circuit disconnects + bool isAlive(); // can become false if circuit disconnects - void setWaterHeight(F32 water_level); - F32 getWaterHeight() const; + void setWaterHeight(F32 water_level); + F32 getWaterHeight() const; - BOOL isVoiceEnabled() const; + BOOL isVoiceEnabled() const; - void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; } - F32 getBillableFactor() const { return mBillableFactor; } + void setBillableFactor(F32 billable_factor) { mBillableFactor = billable_factor; } + F32 getBillableFactor() const { return mBillableFactor; } - // Maximum number of primitives allowed, regardless of object - // bonus factor. - U32 getMaxTasks() const { return mMaxTasks; } - void setMaxTasks(U32 max_tasks) { mMaxTasks = max_tasks; } + // Maximum number of primitives allowed, regardless of object + // bonus factor. + U32 getMaxTasks() const { return mMaxTasks; } + void setMaxTasks(U32 max_tasks) { mMaxTasks = max_tasks; } - // Draw lines in the dirt showing ownership. Return number of - // vertices drawn. - S32 renderPropertyLines(); + // Draw lines in the dirt showing ownership. Return number of + // vertices drawn. + S32 renderPropertyLines(); void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color); - // Call this whenever you change the height data in the region. - // (Automatically called by LLSurfacePatch's update routine) - void dirtyHeights(); + // Call this whenever you change the height data in the region. + // (Automatically called by LLSurfacePatch's update routine) + void dirtyHeights(); // Call this whenever you want to force all terrain to rebuild. // (For example, if a global terrain config option has changed) void dirtyAllPatches(); - LLViewerParcelOverlay *getParcelOverlay() const - { return mParcelOverlay; } - - inline void setRegionFlag(U64 flag, BOOL on); - inline BOOL getRegionFlag(U64 flag) const; - void setRegionFlags(U64 flags); - U64 getRegionFlags() const { return mRegionFlags; } - - inline void setRegionProtocol(U64 protocol, BOOL on); - BOOL getRegionProtocol(U64 protocol) const; - void setRegionProtocols(U64 protocols) { mRegionProtocols = protocols; } - U64 getRegionProtocols() const { return mRegionProtocols; } - - void setTimeDilation(F32 time_dilation); - F32 getTimeDilation() const { return mTimeDilation; } - - // Origin height is at zero. - const LLVector3d &getOriginGlobal() const; - LLVector3 getOriginAgent() const; - - // Center is at the height of the water table. - const LLVector3d &getCenterGlobal() const; - LLVector3 getCenterAgent() const; - - void setRegionNameAndZone(const std::string& name_and_zone); - const std::string& getName() const { return mName; } - const std::string& getZoning() const { return mZoning; } - - void setOwner(const LLUUID& owner_id); - const LLUUID& getOwner() const; - - // Is the current agent on the estate manager list for this region? - void setIsEstateManager(BOOL b) { mIsEstateManager = b; } - BOOL isEstateManager() const { return mIsEstateManager; } - BOOL canManageEstate() const; - - void setSimAccess(U8 sim_access) { mSimAccess = sim_access; } - U8 getSimAccess() const { return mSimAccess; } - const std::string getSimAccessString() const; - - // Homestead-related getters; there are no setters as nobody should be - // setting them other than the individual message handler which is a member - S32 getSimClassID() const { return mClassID; } - S32 getSimCPURatio() const { return mCPURatio; } - const std::string& getSimColoName() const { return mColoName; } - const std::string& getSimProductSKU() const { return mProductSKU; } - std::string getLocalizedSimProductName() const; - - // Returns "Sandbox", "Expensive", etc. - static std::string regionFlagsToString(U64 flags); - - // Returns translated version of "Mature", "PG", "Adult", etc. - static std::string accessToString(U8 sim_access); - - // Returns "M", "PG", "A" etc. - static std::string accessToShortString(U8 sim_access); - static U8 shortStringToAccess(const std::string &sim_access); - - // Return access icon name - static std::string getAccessIcon(U8 sim_access); - - // helper function which just makes sure all interested parties - // can process the message. - static void processRegionInfo(LLMessageSystem* msg, void**); - - //check if the viewer camera is static - static BOOL isViewerCameraStatic(); - static void calcNewObjectCreationThrottle(); - - void setCacheID(const LLUUID& id); - - F32 getWidth() const { return mWidth; } - - // regions are expensive to release, this function gradually releases cache from memory - static void idleCleanup(F32 max_update_time); - - void idleUpdate(F32 max_update_time); - void lightIdleUpdate(); - bool addVisibleGroup(LLViewerOctreeGroup* group); - void addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child); - void addActiveCacheEntry(LLVOCacheEntry* entry); - void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep); - void killCacheEntry(U32 local_id); //physically delete the cache entry - - // Like idleUpdate, but forces everything to complete regardless of - // how long it takes. - void forceUpdate(); - - void connectNeighbor(LLViewerRegion *neighborp, U32 direction); - - void updateNetStats(); - - U32 getPacketsLost() const; - - S32 getHttpResponderID() const; - - // Get/set named capability URLs for this region. - void setSeedCapability(const std::string& url); - S32 getNumSeedCapRetries(); - void setCapability(const std::string& name, const std::string& url); - void setCapabilityDebug(const std::string& name, const std::string& url); - bool isCapabilityAvailable(const std::string& name) const; - // implements LLCapabilityProvider + LLViewerParcelOverlay *getParcelOverlay() const + { return mParcelOverlay; } + + inline void setRegionFlag(U64 flag, BOOL on); + inline BOOL getRegionFlag(U64 flag) const; + void setRegionFlags(U64 flags); + U64 getRegionFlags() const { return mRegionFlags; } + + inline void setRegionProtocol(U64 protocol, BOOL on); + BOOL getRegionProtocol(U64 protocol) const; + void setRegionProtocols(U64 protocols) { mRegionProtocols = protocols; } + U64 getRegionProtocols() const { return mRegionProtocols; } + + void setTimeDilation(F32 time_dilation); + F32 getTimeDilation() const { return mTimeDilation; } + + // Origin height is at zero. + const LLVector3d &getOriginGlobal() const; + LLVector3 getOriginAgent() const; + + // Center is at the height of the water table. + const LLVector3d &getCenterGlobal() const; + LLVector3 getCenterAgent() const; + + void setRegionNameAndZone(const std::string& name_and_zone); + const std::string& getName() const { return mName; } + const std::string& getZoning() const { return mZoning; } + + void setOwner(const LLUUID& owner_id); + const LLUUID& getOwner() const; + + // Is the current agent on the estate manager list for this region? + void setIsEstateManager(BOOL b) { mIsEstateManager = b; } + BOOL isEstateManager() const { return mIsEstateManager; } + BOOL canManageEstate() const; + + void setSimAccess(U8 sim_access) { mSimAccess = sim_access; } + U8 getSimAccess() const { return mSimAccess; } + const std::string getSimAccessString() const; + + // Homestead-related getters; there are no setters as nobody should be + // setting them other than the individual message handler which is a member + S32 getSimClassID() const { return mClassID; } + S32 getSimCPURatio() const { return mCPURatio; } + const std::string& getSimColoName() const { return mColoName; } + const std::string& getSimProductSKU() const { return mProductSKU; } + std::string getLocalizedSimProductName() const; + + // Returns "Sandbox", "Expensive", etc. + static std::string regionFlagsToString(U64 flags); + + // Returns translated version of "Mature", "PG", "Adult", etc. + static std::string accessToString(U8 sim_access); + + // Returns "M", "PG", "A" etc. + static std::string accessToShortString(U8 sim_access); + static U8 shortStringToAccess(const std::string &sim_access); + + // Return access icon name + static std::string getAccessIcon(U8 sim_access); + + // helper function which just makes sure all interested parties + // can process the message. + static void processRegionInfo(LLMessageSystem* msg, void**); + + //check if the viewer camera is static + static BOOL isViewerCameraStatic(); + static void calcNewObjectCreationThrottle(); + + void setCacheID(const LLUUID& id); + + F32 getWidth() const { return mWidth; } + + // regions are expensive to release, this function gradually releases cache from memory + static void idleCleanup(F32 max_update_time); + + void idleUpdate(F32 max_update_time); + void lightIdleUpdate(); + bool addVisibleGroup(LLViewerOctreeGroup* group); + void addVisibleChildCacheEntry(LLVOCacheEntry* parent, LLVOCacheEntry* child); + void addActiveCacheEntry(LLVOCacheEntry* entry); + void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep); + void killCacheEntry(U32 local_id); //physically delete the cache entry + + // Like idleUpdate, but forces everything to complete regardless of + // how long it takes. + void forceUpdate(); + + void connectNeighbor(LLViewerRegion *neighborp, U32 direction); + + void updateNetStats(); + + U32 getPacketsLost() const; + + S32 getHttpResponderID() const; + + // Get/set named capability URLs for this region. + void setSeedCapability(const std::string& url); + S32 getNumSeedCapRetries(); + void setCapability(const std::string& name, const std::string& url); + void setCapabilityDebug(const std::string& name, const std::string& url); + bool isCapabilityAvailable(const std::string& name) const; + // implements LLCapabilityProvider virtual std::string getCapability(const std::string& name) const; std::string getCapabilityDebug(const std::string& name) const; - // has region received its final (not seed) capability list? - bool capabilitiesReceived() const; + // has region received its final (not seed) capability list? + bool capabilitiesReceived() const; bool capabilitiesError() const; - void setCapabilitiesReceived(bool received); - void setCapabilitiesError(); - boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); + void setCapabilitiesReceived(bool received); + void setCapabilitiesError(); + boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); - static bool isSpecialCapabilityName(const std::string &name); - void logActiveCapabilities() const; + static bool isSpecialCapabilityName(const std::string &name); + void logActiveCapabilities() const; - // Utilities to post and get via + // Utilities to post and get via // HTTP using the agent's policy settings and headers. typedef LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t httpCallback_t; bool requestPostCapability(const std::string &capName, @@ -295,279 +295,279 @@ public: bool requestDelCapability(const std::string &capName, httpCallback_t cbSuccess = NULL, httpCallback_t cbFailure = NULL); /// implements LLCapabilityProvider - /*virtual*/ const LLHost& getHost() const; - const U64 &getHandle() const { return mHandle; } + /*virtual*/ const LLHost& getHost() const; + const U64 &getHandle() const { return mHandle; } + + LLSurface &getLand() const; - LLSurface &getLand() const; + // set and get the region id + const LLUUID& getRegionID() const; + void setRegionID(const LLUUID& region_id); - // set and get the region id - const LLUUID& getRegionID() const; - void setRegionID(const LLUUID& region_id); + BOOL pointInRegionGlobal(const LLVector3d &point_global) const; + LLVector3 getPosRegionFromGlobal(const LLVector3d &point_global) const; + LLVector3 getPosRegionFromAgent(const LLVector3 &agent_pos) const; + LLVector3 getPosAgentFromRegion(const LLVector3 ®ion_pos) const; + LLVector3d getPosGlobalFromRegion(const LLVector3 &offset) const; - BOOL pointInRegionGlobal(const LLVector3d &point_global) const; - LLVector3 getPosRegionFromGlobal(const LLVector3d &point_global) const; - LLVector3 getPosRegionFromAgent(const LLVector3 &agent_pos) const; - LLVector3 getPosAgentFromRegion(const LLVector3 ®ion_pos) const; - LLVector3d getPosGlobalFromRegion(const LLVector3 &offset) const; + LLVLComposition *getComposition() const; + F32 getCompositionXY(const S32 x, const S32 y) const; - LLVLComposition *getComposition() const; - F32 getCompositionXY(const S32 x, const S32 y) const; + BOOL isOwnedSelf(const LLVector3& pos); - BOOL isOwnedSelf(const LLVector3& pos); + // Owned by a group you belong to? (officer OR member) + BOOL isOwnedGroup(const LLVector3& pos); - // Owned by a group you belong to? (officer OR member) - BOOL isOwnedGroup(const LLVector3& pos); + // deal with map object updates in the world. + void updateCoarseLocations(LLMessageSystem* msg); - // deal with map object updates in the world. - void updateCoarseLocations(LLMessageSystem* msg); + F32 getLandHeightRegion(const LLVector3& region_pos); - F32 getLandHeightRegion(const LLVector3& region_pos); + U8 getCentralBakeVersion() { return mCentralBakeVersion; } - U8 getCentralBakeVersion() { return mCentralBakeVersion; } + void getInfo(LLSD& info); - void getInfo(LLSD& info); - - bool meshRezEnabled() const; - bool meshUploadEnabled() const; + bool meshRezEnabled() const; + bool meshUploadEnabled() const; - bool bakesOnMeshEnabled() const; + bool bakesOnMeshEnabled() const; - // has region received its simulator features list? Requires an additional query after caps received. + // has region received its simulator features list? Requires an additional query after caps received. void requestSimulatorFeatures(); - void setSimulatorFeaturesReceived(bool); - bool simulatorFeaturesReceived() const; - boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb); - - void getSimulatorFeatures(LLSD& info) const; - void setSimulatorFeatures(const LLSD& info); - - - bool dynamicPathfindingEnabled() const; - - bool avatarHoverHeightEnabled() const; - - typedef enum - { - CACHE_MISS_TYPE_TOTAL = 0, // total cache miss - object not in cache - CACHE_MISS_TYPE_CRC, // object in cache, but CRC doesn't match - CACHE_MISS_TYPE_NONE // not a miss: cache hit - } eCacheMissType; - - typedef enum - { - CACHE_UPDATE_DUPE = 0, - CACHE_UPDATE_CHANGED, - CACHE_UPDATE_ADDED, - CACHE_UPDATE_REPLACED - } eCacheUpdateResult; - - // handle a full update message - eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); - eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags); + void setSimulatorFeaturesReceived(bool); + bool simulatorFeaturesReceived() const; + boost::signals2::connection setSimulatorFeaturesReceivedCallback(const caps_received_signal_t::slot_type& cb); + + void getSimulatorFeatures(LLSD& info) const; + void setSimulatorFeatures(const LLSD& info); + + + bool dynamicPathfindingEnabled() const; + + bool avatarHoverHeightEnabled() const; + + typedef enum + { + CACHE_MISS_TYPE_TOTAL = 0, // total cache miss - object not in cache + CACHE_MISS_TYPE_CRC, // object in cache, but CRC doesn't match + CACHE_MISS_TYPE_NONE // not a miss: cache hit + } eCacheMissType; + + typedef enum + { + CACHE_UPDATE_DUPE = 0, + CACHE_UPDATE_CHANGED, + CACHE_UPDATE_ADDED, + CACHE_UPDATE_REPLACED + } eCacheUpdateResult; + + // handle a full update message + eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); + eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags); void cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data); - LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); - LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true); - bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); - U64 getRegionCacheHitCount() { return mRegionCacheHitCount; } - U64 getRegionCacheMissCount() { return mRegionCacheMissCount; } - void requestCacheMisses(); - void addCacheMissFull(const U32 local_id); - //update object cache if the object receives a full-update or terse update - LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp); - void findOrphans(U32 parent_id); - void clearCachedVisibleObjects(); - void dumpCache (); + LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); + LLVOCacheEntry* getCacheEntry(U32 local_id, bool valid = true); + bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); + U64 getRegionCacheHitCount() { return mRegionCacheHitCount; } + U64 getRegionCacheMissCount() { return mRegionCacheMissCount; } + void requestCacheMisses(); + void addCacheMissFull(const U32 local_id); + //update object cache if the object receives a full-update or terse update + LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp); + void findOrphans(U32 parent_id); + void clearCachedVisibleObjects(); + void dumpCache (); void clearVOCacheFromMemory(); - void unpackRegionHandshake(); + void unpackRegionHandshake(); - void calculateCenterGlobal(); - void calculateCameraDistance(); + void calculateCenterGlobal(); + void calculateCameraDistance(); - friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion); + friend std::ostream& operator<<(std::ostream &s, const LLViewerRegion ®ion); /// implements LLCapabilityProvider virtual std::string getDescription() const; std::string getViewerAssetUrl() const { return mViewerAssetUrl; } - U32 getNumOfVisibleGroups() const; - U32 getNumOfActiveCachedObjects() const; - LLSpatialPartition* getSpatialPartition(U32 type); - LLVOCachePartition* getVOCachePartition(); + U32 getNumOfVisibleGroups() const; + U32 getNumOfActiveCachedObjects() const; + LLSpatialPartition* getSpatialPartition(U32 type); + LLVOCachePartition* getVOCachePartition(); - bool objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const; - bool childrenObjectReturnable( const std::vector& boxes ) const; - bool objectsCrossParcel(const std::vector& boxes) const; + bool objectIsReturnable(const LLVector3& pos, const std::vector& boxes) const; + bool childrenObjectReturnable( const std::vector& boxes ) const; + bool objectsCrossParcel(const std::vector& boxes) const; - void getNeighboringRegions( std::vector& uniqueRegions ); - void getNeighboringRegionsStatus( std::vector& regions ); - const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } - LLViewerRegionImpl * getRegionImplNC() { return mImpl; } + void getNeighboringRegions( std::vector& uniqueRegions ); + void getNeighboringRegionsStatus( std::vector& regions ); + const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } + LLViewerRegionImpl * getRegionImplNC() { return mImpl; } - // implements the materials capability throttle - bool materialsCapThrottled() const { return !mMaterialsCapThrottleTimer.hasExpired(); } - void resetMaterialsCapThrottle(); - - U32 getMaxMaterialsPerTransaction() const; + // implements the materials capability throttle + bool materialsCapThrottled() const { return !mMaterialsCapThrottleTimer.hasExpired(); } + void resetMaterialsCapThrottle(); - void removeFromCreatedList(U32 local_id); - void addToCreatedList(U32 local_id); + U32 getMaxMaterialsPerTransaction() const; - BOOL isPaused() const {return mPaused;} - S32 getLastUpdate() const {return mLastUpdate;} + void removeFromCreatedList(U32 local_id); + void addToCreatedList(U32 local_id); - std::string getSimHostName(); + BOOL isPaused() const {return mPaused;} + S32 getLastUpdate() const {return mLastUpdate;} - static BOOL isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;} + std::string getSimHostName(); + + static BOOL isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;} // rebuild reflection probe list void updateReflectionProbes(); private: - void addToVOCacheTree(LLVOCacheEntry* entry); - LLViewerObject* addNewObject(LLVOCacheEntry* entry); - void killObject(LLVOCacheEntry* entry, std::vector& delete_list); //adds entry into list if it is safe to move into cache - void removeFromVOCacheTree(LLVOCacheEntry* entry); - void killCacheEntry(LLVOCacheEntry* entry, bool for_rendering = false); //physically delete the cache entry - void killInvisibleObjects(F32 max_time); - void createVisibleObjects(F32 max_time); - void updateVisibleEntries(F32 max_time); //update visible entries - - void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); - void decodeBoundingInfo(LLVOCacheEntry* entry); - bool isNonCacheableObjectCreated(U32 local_id); + void addToVOCacheTree(LLVOCacheEntry* entry); + LLViewerObject* addNewObject(LLVOCacheEntry* entry); + void killObject(LLVOCacheEntry* entry, std::vector& delete_list); //adds entry into list if it is safe to move into cache + void removeFromVOCacheTree(LLVOCacheEntry* entry); + void killCacheEntry(LLVOCacheEntry* entry, bool for_rendering = false); //physically delete the cache entry + void killInvisibleObjects(F32 max_time); + void createVisibleObjects(F32 max_time); + void updateVisibleEntries(F32 max_time); //update visible entries + + void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); + void decodeBoundingInfo(LLVOCacheEntry* entry); + bool isNonCacheableObjectCreated(U32 local_id); public: void applyCacheMiscExtras(LLViewerObject* obj); - struct CompareDistance - { - bool operator()(const LLViewerRegion* const& lhs, const LLViewerRegion* const& rhs) - { - return lhs->mCameraDistanceSquared < rhs->mCameraDistanceSquared; - } - }; + struct CompareDistance + { + bool operator()(const LLViewerRegion* const& lhs, const LLViewerRegion* const& rhs) + { + return lhs->mCameraDistanceSquared < rhs->mCameraDistanceSquared; + } + }; - void showReleaseNotes(); + void showReleaseNotes(); protected: - void disconnectAllNeighbors(); - void initStats(); + void disconnectAllNeighbors(); + void initStats(); public: - LLWind mWind; - LLViewerParcelOverlay *mParcelOverlay; - - F32Bits mBitsReceived; - F32 mPacketsReceived; - - LLMatrix4 mRenderMatrix; - - // These arrays are maintained in parallel. Ideally they'd be combined into a - // single array of an aggrigate data type but for compatibility with the old - // messaging system in which the previous message only sends and parses the - // positions stored in the first array so they're maintained separately until - // we stop supporting the old CoarseLocationUpdate message. - std::vector mMapAvatars; - std::vector mMapAvatarIDs; - - static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not. - static S32 sLastCameraUpdated; - - LLFrameTimer & getRenderInfoRequestTimer() { return mRenderInfoRequestTimer; }; - LLFrameTimer & getRenderInfoReportTimer() { return mRenderInfoReportTimer; }; - - struct CompareRegionByLastUpdate - { - bool operator()(const LLViewerRegion* const& lhs, const LLViewerRegion* const& rhs) const - { - S32 lpa = lhs->getLastUpdate(); - S32 rpa = rhs->getLastUpdate(); - - //small mLastUpdate first - if(lpa < rpa) - { - return true; - } - else if(lpa > rpa) - { - return false; - } - else - { - return lhs < rhs; - } - } - }; - typedef std::set region_priority_list_t; - - void setInterestListMode(const std::string & new_mode); + LLWind mWind; + LLViewerParcelOverlay *mParcelOverlay; + + F32Bits mBitsReceived; + F32 mPacketsReceived; + + LLMatrix4 mRenderMatrix; + + // These arrays are maintained in parallel. Ideally they'd be combined into a + // single array of an aggrigate data type but for compatibility with the old + // messaging system in which the previous message only sends and parses the + // positions stored in the first array so they're maintained separately until + // we stop supporting the old CoarseLocationUpdate message. + std::vector mMapAvatars; + std::vector mMapAvatarIDs; + + static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not. + static S32 sLastCameraUpdated; + + LLFrameTimer & getRenderInfoRequestTimer() { return mRenderInfoRequestTimer; }; + LLFrameTimer & getRenderInfoReportTimer() { return mRenderInfoReportTimer; }; + + struct CompareRegionByLastUpdate + { + bool operator()(const LLViewerRegion* const& lhs, const LLViewerRegion* const& rhs) const + { + S32 lpa = lhs->getLastUpdate(); + S32 rpa = rhs->getLastUpdate(); + + //small mLastUpdate first + if(lpa < rpa) + { + return true; + } + else if(lpa > rpa) + { + return false; + } + else + { + return lhs < rhs; + } + } + }; + typedef std::set region_priority_list_t; + + void setInterestListMode(const std::string & new_mode); const std::string & getInterestListMode() const { return mInterestListMode; } - void resetInterestList(); + void resetInterestList(); - static const std::string IL_MODE_DEFAULT; + static const std::string IL_MODE_DEFAULT; static const std::string IL_MODE_360; private: - static S32 sNewObjectCreationThrottle; - LLViewerRegionImpl * mImpl; - LLFrameTimer mRegionTimer; - - F32 mWidth; // Width of region on a side (meters) - U64 mHandle; - F32 mTimeDilation; // time dilation of physics simulation on simulator - S32 mLastUpdate; //last time called idleUpdate() - - // simulator name - std::string mName; - std::string mZoning; - - // Is this agent on the estate managers list for this region? - BOOL mIsEstateManager; - - U32 mPacketsIn; - U32Bits mBitsIn, - mLastBitsIn; - U32 mLastPacketsIn; - U32 mPacketsOut; - U32 mLastPacketsOut; - S32 mPacketsLost; - S32 mLastPacketsLost; - U32Milliseconds mPingDelay; - F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc - - U64 mRegionFlags; // includes damage flags - U64 mRegionProtocols; // protocols supported by this region - U8 mSimAccess; - F32 mBillableFactor; - U32 mMaxTasks; // max prim count - F32 mCameraDistanceSquared; // updated once per frame - U8 mCentralBakeVersion; - - LLVOCacheEntry* mLastVisitedEntry; - U32 mInvisibilityCheckHistory; - - // Information for Homestead / CR-53 - S32 mClassID; - S32 mCPURatio; - - std::string mColoName; - std::string mProductSKU; - std::string mProductName; - std::string mViewerAssetUrl ; - - // Maps local ids to cache entries. - // Regions can have order 10,000 objects, so assume - // a structure of size 2^14 = 16,000 - BOOL mCacheLoaded; - BOOL mCacheDirty; - BOOL mAlive; // can become false if circuit disconnects - BOOL mSimulatorFeaturesReceived; - BOOL mReleaseNotesRequested; - BOOL mDead; //if true, this region is in the process of deleting. - BOOL mPaused; //pause processing the objects in the region + static S32 sNewObjectCreationThrottle; + LLViewerRegionImpl * mImpl; + LLFrameTimer mRegionTimer; + + F32 mWidth; // Width of region on a side (meters) + U64 mHandle; + F32 mTimeDilation; // time dilation of physics simulation on simulator + S32 mLastUpdate; //last time called idleUpdate() + + // simulator name + std::string mName; + std::string mZoning; + + // Is this agent on the estate managers list for this region? + BOOL mIsEstateManager; + + U32 mPacketsIn; + U32Bits mBitsIn, + mLastBitsIn; + U32 mLastPacketsIn; + U32 mPacketsOut; + U32 mLastPacketsOut; + S32 mPacketsLost; + S32 mLastPacketsLost; + U32Milliseconds mPingDelay; + F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc + + U64 mRegionFlags; // includes damage flags + U64 mRegionProtocols; // protocols supported by this region + U8 mSimAccess; + F32 mBillableFactor; + U32 mMaxTasks; // max prim count + F32 mCameraDistanceSquared; // updated once per frame + U8 mCentralBakeVersion; + + LLVOCacheEntry* mLastVisitedEntry; + U32 mInvisibilityCheckHistory; + + // Information for Homestead / CR-53 + S32 mClassID; + S32 mCPURatio; + + std::string mColoName; + std::string mProductSKU; + std::string mProductName; + std::string mViewerAssetUrl ; + + // Maps local ids to cache entries. + // Regions can have order 10,000 objects, so assume + // a structure of size 2^14 = 16,000 + BOOL mCacheLoaded; + BOOL mCacheDirty; + BOOL mAlive; // can become false if circuit disconnects + BOOL mSimulatorFeaturesReceived; + BOOL mReleaseNotesRequested; + BOOL mDead; //if true, this region is in the process of deleting. + BOOL mPaused; //pause processing the objects in the region typedef enum { @@ -576,39 +576,39 @@ public: CAPABILITIES_STATE_RECEIVED } eCababilitiesState; - eCababilitiesState mCapabilitiesState; + eCababilitiesState mCapabilitiesState; - typedef std::map > orphan_list_t; - orphan_list_t mOrphanMap; + typedef std::map > orphan_list_t; + orphan_list_t mOrphanMap; - class CacheMissItem - { - public: + class CacheMissItem + { + public: CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type) {} - U32 mID; //local object id - LLViewerRegion::eCacheMissType mType; // cache miss type + U32 mID; //local object id + LLViewerRegion::eCacheMissType mType; // cache miss type - typedef std::list cache_miss_list_t; - }; - CacheMissItem::cache_miss_list_t mCacheMissList; - U64 mRegionCacheHitCount; - U64 mRegionCacheMissCount; + typedef std::list cache_miss_list_t; + }; + CacheMissItem::cache_miss_list_t mCacheMissList; + U64 mRegionCacheHitCount; + U64 mRegionCacheMissCount; - caps_received_signal_t mCapabilitiesReceivedSignal; - caps_received_signal_t mSimulatorFeaturesReceivedSignal; + caps_received_signal_t mCapabilitiesReceivedSignal; + caps_received_signal_t mSimulatorFeaturesReceivedSignal; - LLSD mSimulatorFeatures; + LLSD mSimulatorFeatures; - typedef std::map > vocache_entry_map_t; + typedef std::map > vocache_entry_map_t; static vocache_entry_map_t sRegionCacheCleanup; - // the materials capability throttle - LLFrameTimer mMaterialsCapThrottleTimer; - LLFrameTimer mRenderInfoRequestTimer; - LLFrameTimer mRenderInfoReportTimer; + // the materials capability throttle + LLFrameTimer mMaterialsCapThrottleTimer; + LLFrameTimer mRenderInfoRequestTimer; + LLFrameTimer mRenderInfoReportTimer; - // how the server interest list works + // how the server interest list works std::string mInterestListMode; // list of reflection maps being managed by this llviewer region @@ -618,86 +618,86 @@ public: inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const { - return ((mRegionProtocols & protocol) != 0); + return ((mRegionProtocols & protocol) != 0); } inline void LLViewerRegion::setRegionProtocol(U64 protocol, BOOL on) { - if (on) - { - mRegionProtocols |= protocol; - } - else - { - mRegionProtocols &= ~protocol; - } + if (on) + { + mRegionProtocols |= protocol; + } + else + { + mRegionProtocols &= ~protocol; + } } inline BOOL LLViewerRegion::getRegionFlag(U64 flag) const { - return ((mRegionFlags & flag) != 0); + return ((mRegionFlags & flag) != 0); } inline void LLViewerRegion::setRegionFlag(U64 flag, BOOL on) { - if (on) - { - mRegionFlags |= flag; - } - else - { - mRegionFlags &= ~flag; - } + if (on) + { + mRegionFlags |= flag; + } + else + { + mRegionFlags &= ~flag; + } } inline BOOL LLViewerRegion::getAllowDamage() const { - return ((mRegionFlags & REGION_FLAGS_ALLOW_DAMAGE) !=0); + return ((mRegionFlags & REGION_FLAGS_ALLOW_DAMAGE) !=0); } inline BOOL LLViewerRegion::getAllowLandmark() const { - return ((mRegionFlags & REGION_FLAGS_ALLOW_LANDMARK) !=0); + return ((mRegionFlags & REGION_FLAGS_ALLOW_LANDMARK) !=0); } inline BOOL LLViewerRegion::getAllowSetHome() const { - return ((mRegionFlags & REGION_FLAGS_ALLOW_SET_HOME) != 0); + return ((mRegionFlags & REGION_FLAGS_ALLOW_SET_HOME) != 0); } inline BOOL LLViewerRegion::getResetHomeOnTeleport() const { - return ((mRegionFlags & REGION_FLAGS_RESET_HOME_ON_TELEPORT) !=0); + return ((mRegionFlags & REGION_FLAGS_RESET_HOME_ON_TELEPORT) !=0); } inline BOOL LLViewerRegion::getSunFixed() const { - return ((mRegionFlags & REGION_FLAGS_SUN_FIXED) !=0); + return ((mRegionFlags & REGION_FLAGS_SUN_FIXED) !=0); } inline BOOL LLViewerRegion::getBlockFly() const { - return ((mRegionFlags & REGION_FLAGS_BLOCK_FLY) !=0); + return ((mRegionFlags & REGION_FLAGS_BLOCK_FLY) !=0); } inline BOOL LLViewerRegion::getAllowDirectTeleport() const { - return ((mRegionFlags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT) !=0); + return ((mRegionFlags & REGION_FLAGS_ALLOW_DIRECT_TELEPORT) !=0); } inline BOOL LLViewerRegion::isPrelude() const { - return is_prelude( mRegionFlags ); + return is_prelude( mRegionFlags ); } inline BOOL LLViewerRegion::getAllowTerraform() const { - return ((mRegionFlags & REGION_FLAGS_BLOCK_TERRAFORM) == 0); + return ((mRegionFlags & REGION_FLAGS_BLOCK_TERRAFORM) == 0); } inline BOOL LLViewerRegion::getRestrictPushObject() const { - return ((mRegionFlags & REGION_FLAGS_RESTRICT_PUSHOBJECT) != 0); + return ((mRegionFlags & REGION_FLAGS_RESTRICT_PUSHOBJECT) != 0); } inline BOOL LLViewerRegion::getAllowEnvironmentOverride() const @@ -707,7 +707,7 @@ inline BOOL LLViewerRegion::getAllowEnvironmentOverride() const inline BOOL LLViewerRegion::getReleaseNotesRequested() const { - return mReleaseNotesRequested; + return mReleaseNotesRequested; } #endif diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5144b28ce9..d0846e3017 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewershadermgr.cpp * @brief Viewer shader manager implementation. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -64,10 +64,10 @@ using std::pair; using std::make_pair; using std::string; -BOOL LLViewerShaderMgr::sInitialized = FALSE; -bool LLViewerShaderMgr::sSkipReload = false; +BOOL LLViewerShaderMgr::sInitialized = FALSE; +bool LLViewerShaderMgr::sSkipReload = false; -LLVector4 gShinyOrigin; +LLVector4 gShinyOrigin; S32 clamp_terrain_mapping(S32 mapping) { @@ -78,155 +78,155 @@ S32 clamp_terrain_mapping(S32 mapping) } //utility shaders -LLGLSLShader gOcclusionProgram; +LLGLSLShader gOcclusionProgram; LLGLSLShader gSkinnedOcclusionProgram; -LLGLSLShader gOcclusionCubeProgram; -LLGLSLShader gGlowCombineProgram; -LLGLSLShader gReflectionMipProgram; +LLGLSLShader gOcclusionCubeProgram; +LLGLSLShader gGlowCombineProgram; +LLGLSLShader gReflectionMipProgram; LLGLSLShader gGaussianProgram; LLGLSLShader gRadianceGenProgram; LLGLSLShader gHeroRadianceGenProgram; -LLGLSLShader gIrradianceGenProgram; -LLGLSLShader gGlowCombineFXAAProgram; -LLGLSLShader gTwoTextureCompareProgram; -LLGLSLShader gOneTextureFilterProgram; -LLGLSLShader gDebugProgram; +LLGLSLShader gIrradianceGenProgram; +LLGLSLShader gGlowCombineFXAAProgram; +LLGLSLShader gTwoTextureCompareProgram; +LLGLSLShader gOneTextureFilterProgram; +LLGLSLShader gDebugProgram; LLGLSLShader gSkinnedDebugProgram; -LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; -LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; -LLGLSLShader gClipProgram; -LLGLSLShader gAlphaMaskProgram; -LLGLSLShader gBenchmarkProgram; +LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +LLGLSLShader gClipProgram; +LLGLSLShader gAlphaMaskProgram; +LLGLSLShader gBenchmarkProgram; LLGLSLShader gReflectionProbeDisplayProgram; LLGLSLShader gCopyProgram; LLGLSLShader gCopyDepthProgram; //object shaders -LLGLSLShader gObjectPreviewProgram; +LLGLSLShader gObjectPreviewProgram; LLGLSLShader gSkinnedObjectPreviewProgram; LLGLSLShader gPhysicsPreviewProgram; -LLGLSLShader gObjectFullbrightAlphaMaskProgram; -LLGLSLShader gObjectBumpProgram; +LLGLSLShader gObjectFullbrightAlphaMaskProgram; +LLGLSLShader gObjectBumpProgram; LLGLSLShader gSkinnedObjectBumpProgram; -LLGLSLShader gObjectAlphaMaskNoColorProgram; +LLGLSLShader gObjectAlphaMaskNoColorProgram; //environment shaders -LLGLSLShader gWaterProgram; +LLGLSLShader gWaterProgram; LLGLSLShader gWaterEdgeProgram; -LLGLSLShader gUnderWaterProgram; +LLGLSLShader gUnderWaterProgram; //interface shaders -LLGLSLShader gHighlightProgram; +LLGLSLShader gHighlightProgram; LLGLSLShader gSkinnedHighlightProgram; -LLGLSLShader gHighlightNormalProgram; -LLGLSLShader gHighlightSpecularProgram; +LLGLSLShader gHighlightNormalProgram; +LLGLSLShader gHighlightSpecularProgram; -LLGLSLShader gDeferredHighlightProgram; +LLGLSLShader gDeferredHighlightProgram; -LLGLSLShader gPathfindingProgram; -LLGLSLShader gPathfindingNoNormalsProgram; +LLGLSLShader gPathfindingProgram; +LLGLSLShader gPathfindingNoNormalsProgram; //avatar shader handles -LLGLSLShader gAvatarProgram; -LLGLSLShader gAvatarEyeballProgram; -LLGLSLShader gImpostorProgram; +LLGLSLShader gAvatarProgram; +LLGLSLShader gAvatarEyeballProgram; +LLGLSLShader gImpostorProgram; // Effects Shaders -LLGLSLShader gGlowProgram; -LLGLSLShader gGlowExtractProgram; -LLGLSLShader gPostScreenSpaceReflectionProgram; +LLGLSLShader gGlowProgram; +LLGLSLShader gGlowExtractProgram; +LLGLSLShader gPostScreenSpaceReflectionProgram; // Deferred rendering shaders -LLGLSLShader gDeferredImpostorProgram; -LLGLSLShader gDeferredDiffuseProgram; -LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +LLGLSLShader gDeferredImpostorProgram; +LLGLSLShader gDeferredDiffuseProgram; +LLGLSLShader gDeferredDiffuseAlphaMaskProgram; LLGLSLShader gDeferredSkinnedDiffuseAlphaMaskProgram; -LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; -LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; -LLGLSLShader gDeferredSkinnedDiffuseProgram; -LLGLSLShader gDeferredSkinnedBumpProgram; -LLGLSLShader gDeferredBumpProgram; -LLGLSLShader gDeferredTerrainProgram; -LLGLSLShader gDeferredTreeProgram; -LLGLSLShader gDeferredTreeShadowProgram; +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; +LLGLSLShader gDeferredSkinnedDiffuseProgram; +LLGLSLShader gDeferredSkinnedBumpProgram; +LLGLSLShader gDeferredBumpProgram; +LLGLSLShader gDeferredTerrainProgram; +LLGLSLShader gDeferredTreeProgram; +LLGLSLShader gDeferredTreeShadowProgram; LLGLSLShader gDeferredSkinnedTreeShadowProgram; -LLGLSLShader gDeferredAvatarProgram; -LLGLSLShader gDeferredAvatarAlphaProgram; -LLGLSLShader gDeferredLightProgram; -LLGLSLShader gDeferredMultiLightProgram[16]; -LLGLSLShader gDeferredSpotLightProgram; -LLGLSLShader gDeferredMultiSpotLightProgram; -LLGLSLShader gDeferredSunProgram; +LLGLSLShader gDeferredAvatarProgram; +LLGLSLShader gDeferredAvatarAlphaProgram; +LLGLSLShader gDeferredLightProgram; +LLGLSLShader gDeferredMultiLightProgram[16]; +LLGLSLShader gDeferredSpotLightProgram; +LLGLSLShader gDeferredMultiSpotLightProgram; +LLGLSLShader gDeferredSunProgram; LLGLSLShader gHazeProgram; LLGLSLShader gHazeWaterProgram; -LLGLSLShader gDeferredBlurLightProgram; -LLGLSLShader gDeferredSoftenProgram; -LLGLSLShader gDeferredShadowProgram; +LLGLSLShader gDeferredBlurLightProgram; +LLGLSLShader gDeferredSoftenProgram; +LLGLSLShader gDeferredShadowProgram; LLGLSLShader gDeferredSkinnedShadowProgram; -LLGLSLShader gDeferredShadowCubeProgram; -LLGLSLShader gDeferredShadowAlphaMaskProgram; +LLGLSLShader gDeferredShadowCubeProgram; +LLGLSLShader gDeferredShadowAlphaMaskProgram; LLGLSLShader gDeferredSkinnedShadowAlphaMaskProgram; -LLGLSLShader gDeferredShadowGLTFAlphaMaskProgram; -LLGLSLShader gDeferredSkinnedShadowGLTFAlphaMaskProgram; +LLGLSLShader gDeferredShadowGLTFAlphaMaskProgram; +LLGLSLShader gDeferredSkinnedShadowGLTFAlphaMaskProgram; LLGLSLShader gDeferredShadowGLTFAlphaBlendProgram; LLGLSLShader gDeferredSkinnedShadowGLTFAlphaBlendProgram; -LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; +LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; LLGLSLShader gDeferredSkinnedShadowFullbrightAlphaMaskProgram; -LLGLSLShader gDeferredAvatarShadowProgram; -LLGLSLShader gDeferredAvatarAlphaShadowProgram; -LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; -LLGLSLShader gDeferredAlphaProgram; -LLGLSLShader gHUDAlphaProgram; +LLGLSLShader gDeferredAvatarShadowProgram; +LLGLSLShader gDeferredAvatarAlphaShadowProgram; +LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; +LLGLSLShader gDeferredAlphaProgram; +LLGLSLShader gHUDAlphaProgram; LLGLSLShader gDeferredSkinnedAlphaProgram; -LLGLSLShader gDeferredAlphaImpostorProgram; +LLGLSLShader gDeferredAlphaImpostorProgram; LLGLSLShader gDeferredSkinnedAlphaImpostorProgram; -LLGLSLShader gDeferredAvatarEyesProgram; -LLGLSLShader gDeferredFullbrightProgram; +LLGLSLShader gDeferredAvatarEyesProgram; +LLGLSLShader gDeferredFullbrightProgram; LLGLSLShader gHUDFullbrightProgram; -LLGLSLShader gDeferredFullbrightAlphaMaskProgram; -LLGLSLShader gHUDFullbrightAlphaMaskProgram; -LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram; -LLGLSLShader gHUDFullbrightAlphaMaskAlphaProgram; -LLGLSLShader gDeferredEmissiveProgram; +LLGLSLShader gDeferredFullbrightAlphaMaskProgram; +LLGLSLShader gHUDFullbrightAlphaMaskProgram; +LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram; +LLGLSLShader gHUDFullbrightAlphaMaskAlphaProgram; +LLGLSLShader gDeferredEmissiveProgram; LLGLSLShader gDeferredSkinnedEmissiveProgram; -LLGLSLShader gDeferredPostProgram; -LLGLSLShader gDeferredCoFProgram; -LLGLSLShader gDeferredDoFCombineProgram; -LLGLSLShader gDeferredPostGammaCorrectProgram; +LLGLSLShader gDeferredPostProgram; +LLGLSLShader gDeferredCoFProgram; +LLGLSLShader gDeferredDoFCombineProgram; +LLGLSLShader gDeferredPostGammaCorrectProgram; LLGLSLShader gNoPostGammaCorrectProgram; LLGLSLShader gLegacyPostGammaCorrectProgram; -LLGLSLShader gExposureProgram; -LLGLSLShader gExposureProgramNoFade; -LLGLSLShader gLuminanceProgram; -LLGLSLShader gFXAAProgram; -LLGLSLShader gDeferredPostNoDoFProgram; -LLGLSLShader gDeferredWLSkyProgram; +LLGLSLShader gExposureProgram; +LLGLSLShader gExposureProgramNoFade; +LLGLSLShader gLuminanceProgram; +LLGLSLShader gFXAAProgram; +LLGLSLShader gDeferredPostNoDoFProgram; +LLGLSLShader gDeferredWLSkyProgram; LLGLSLShader gEnvironmentMapProgram; -LLGLSLShader gDeferredWLCloudProgram; -LLGLSLShader gDeferredWLSunProgram; -LLGLSLShader gDeferredWLMoonProgram; -LLGLSLShader gDeferredStarProgram; -LLGLSLShader gDeferredFullbrightShinyProgram; +LLGLSLShader gDeferredWLCloudProgram; +LLGLSLShader gDeferredWLSunProgram; +LLGLSLShader gDeferredWLMoonProgram; +LLGLSLShader gDeferredStarProgram; +LLGLSLShader gDeferredFullbrightShinyProgram; LLGLSLShader gHUDFullbrightShinyProgram; LLGLSLShader gDeferredSkinnedFullbrightShinyProgram; -LLGLSLShader gDeferredSkinnedFullbrightProgram; +LLGLSLShader gDeferredSkinnedFullbrightProgram; LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskProgram; LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskAlphaProgram; -LLGLSLShader gNormalMapGenProgram; +LLGLSLShader gNormalMapGenProgram; LLGLSLShader gDeferredGenBrdfLutProgram; LLGLSLShader gDeferredBufferVisualProgram; // Deferred materials shaders -LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; -LLGLSLShader gHUDPBROpaqueProgram; +LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; +LLGLSLShader gHUDPBROpaqueProgram; LLGLSLShader gPBRGlowProgram; LLGLSLShader gPBRGlowSkinnedProgram; -LLGLSLShader gDeferredPBROpaqueProgram; +LLGLSLShader gDeferredPBROpaqueProgram; LLGLSLShader gDeferredSkinnedPBROpaqueProgram; LLGLSLShader gHUDPBRAlphaProgram; LLGLSLShader gDeferredPBRAlphaProgram; LLGLSLShader gDeferredSkinnedPBRAlphaProgram; -LLGLSLShader gDeferredPBRTerrainProgram; +LLGLSLShader gDeferredPBRTerrainProgram; //helper for making a rigged variant of a given shader static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader) @@ -275,15 +275,15 @@ static bool no_redundant_shaders(const std::vector& shaders) LLViewerShaderMgr::LLViewerShaderMgr() : - mShaderLevel(SHADER_COUNT, 0), - mMaxAvatarShaderLevel(0) -{ + mShaderLevel(SHADER_COUNT, 0), + mMaxAvatarShaderLevel(0) +{ } LLViewerShaderMgr::~LLViewerShaderMgr() { - mShaderLevel.clear(); - mShaderList.clear(); + mShaderLevel.clear(); + mShaderList.clear(); } void LLViewerShaderMgr::finalizeShaderList() @@ -336,46 +336,46 @@ void LLViewerShaderMgr::finalizeShaderList() mShaderList.push_back(&gDeferredNonIndexedDiffuseAlphaMaskProgram); mShaderList.push_back(&gDeferredTreeProgram); - // make sure there are no redundancies + // make sure there are no redundancies llassert(no_redundant_shaders(mShaderList)); } // static LLViewerShaderMgr * LLViewerShaderMgr::instance() { - if(NULL == sInstance) - { - sInstance = new LLViewerShaderMgr(); - } + if(NULL == sInstance) + { + sInstance = new LLViewerShaderMgr(); + } - return static_cast(sInstance); + return static_cast(sInstance); } // static void LLViewerShaderMgr::releaseInstance() { - if (sInstance != NULL) - { - delete sInstance; - sInstance = NULL; - } + if (sInstance != NULL) + { + delete sInstance; + sInstance = NULL; + } } void LLViewerShaderMgr::initAttribsAndUniforms(void) { - if (mReservedAttribs.empty()) - { - LLShaderMgr::initAttribsAndUniforms(); - } + if (mReservedAttribs.empty()) + { + LLShaderMgr::initAttribsAndUniforms(); + } } - + //============================================================================ // Set Levels S32 LLViewerShaderMgr::getShaderLevel(S32 type) { - return mShaderLevel[type]; + return mShaderLevel[type]; } //============================================================================ @@ -386,7 +386,7 @@ void LLViewerShaderMgr::setShaders() LL_PROFILE_ZONE_SCOPED; //setShaders might be called redundantly by gSavedSettings, so return on reentrance static bool reentrance = false; - + if (!gPipeline.mInitialized || !sInitialized || reentrance || sSkipReload) { return; @@ -403,25 +403,25 @@ void LLViewerShaderMgr::setShaders() return; } - { - static LLCachedControl shader_cache_enabled(gSavedSettings, "RenderShaderCacheEnabled", true); - static LLUUID old_cache_version; - static LLUUID current_cache_version; - if (current_cache_version.isNull()) - { - HBXXH128 hash_obj; - hash_obj.update(LLVersionInfo::instance().getVersion()); - current_cache_version = hash_obj.digest(); + { + static LLCachedControl shader_cache_enabled(gSavedSettings, "RenderShaderCacheEnabled", true); + static LLUUID old_cache_version; + static LLUUID current_cache_version; + if (current_cache_version.isNull()) + { + HBXXH128 hash_obj; + hash_obj.update(LLVersionInfo::instance().getVersion()); + current_cache_version = hash_obj.digest(); - old_cache_version = LLUUID(gSavedSettings.getString("RenderShaderCacheVersion")); - gSavedSettings.setString("RenderShaderCacheVersion", current_cache_version.asString()); - } + old_cache_version = LLUUID(gSavedSettings.getString("RenderShaderCacheVersion")); + gSavedSettings.setString("RenderShaderCacheVersion", current_cache_version.asString()); + } - initShaderCache(shader_cache_enabled, old_cache_version, current_cache_version); - } + initShaderCache(shader_cache_enabled, old_cache_version, current_cache_version); + } static LLCachedControl max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16); - + // when using indexed texture rendering, leave some texture units available for shadow and reflection maps static LLCachedControl reserved_texture_units(gSavedSettings, "RenderReservedTextureIndices", 14); @@ -433,14 +433,14 @@ void LLViewerShaderMgr::setShaders() // Make sure the compiled shader map is cleared before we recompile shaders. mVertexShaderObjects.clear(); mFragmentShaderObjects.clear(); - + initAttribsAndUniforms(); gPipeline.releaseGLBuffers(); - unloadShaders(); + unloadShaders(); + + LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); - LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); - if (gViewerWindow) { gViewerWindow->setCursor(UI_CURSOR_WAIT); @@ -460,7 +460,7 @@ void LLViewerShaderMgr::setShaders() llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10)); - + S32 light_class = 3; S32 interface_class = 2; S32 env_class = 2; @@ -499,7 +499,7 @@ void LLViewerShaderMgr::setShaders() loadBasicShaders(); LLError::setDefaultLevel(lvl); LL_ERRS() << "Unable to load basic shader " << shader_name << ", verify graphics driver installed and current." << LL_ENDL; - reentrance = false; // For hygiene only, re-try probably helps nothing + reentrance = false; // For hygiene only, re-try probably helps nothing return; } @@ -555,7 +555,7 @@ void LLViewerShaderMgr::setShaders() { //hardware skinning is enabled and rigged attachment shaders loaded correctly // cloth is a class3 shader S32 avatar_class = 1; - + // Set the actual level mShaderLevel[SHADER_AVATAR] = avatar_class; @@ -572,7 +572,7 @@ void LLViewerShaderMgr::setShaders() loaded = loaded && loadShadersDeferred(); llassert(loaded); - persistShaderCacheMetadata(); + persistShaderCacheMetadata(); if (gViewerWindow) { @@ -587,76 +587,76 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { - while (!LLGLSLShader::sInstances.empty()) - { - LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); - shader->unload(); - } - - mShaderLevel[SHADER_LIGHTING] = 0; - mShaderLevel[SHADER_OBJECT] = 0; - mShaderLevel[SHADER_AVATAR] = 0; - mShaderLevel[SHADER_ENVIRONMENT] = 0; - mShaderLevel[SHADER_WATER] = 0; - mShaderLevel[SHADER_INTERFACE] = 0; - mShaderLevel[SHADER_EFFECT] = 0; - mShaderLevel[SHADER_WINDLIGHT] = 0; - - gPipeline.mShadersLoaded = false; + while (!LLGLSLShader::sInstances.empty()) + { + LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); + shader->unload(); + } + + mShaderLevel[SHADER_LIGHTING] = 0; + mShaderLevel[SHADER_OBJECT] = 0; + mShaderLevel[SHADER_AVATAR] = 0; + mShaderLevel[SHADER_ENVIRONMENT] = 0; + mShaderLevel[SHADER_WATER] = 0; + mShaderLevel[SHADER_INTERFACE] = 0; + mShaderLevel[SHADER_EFFECT] = 0; + mShaderLevel[SHADER_WINDLIGHT] = 0; + + gPipeline.mShadersLoaded = false; } std::string LLViewerShaderMgr::loadBasicShaders() { - // Load basic dependency shaders first - // All of these have to load for any shaders to function - - S32 sum_lights_class = 3; + // Load basic dependency shaders first + // All of these have to load for any shaders to function + + S32 sum_lights_class = 3; #if LL_DARWIN - // Work around driver crashes on older Macs when using deferred rendering - // NORSPEC-59 - // - if (gGLManager.mIsMobileGF) - sum_lights_class = 3; + // Work around driver crashes on older Macs when using deferred rendering + // NORSPEC-59 + // + if (gGLManager.mIsMobileGF) + sum_lights_class = 3; #endif - // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. - S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); - sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); - - // Load the Basic Vertex Shaders at the appropriate level. - // (in order of shader function call depth for reference purposes, deepest level first) - - vector< pair > shaders; - shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) ); - shaders.push_back( make_pair( "lighting/lightV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl", sum_lights_class ) ); - shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + // Use the feature table to mask out the max light level to use. Also make sure it's at least 1. + S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel"); + sum_lights_class = llclamp(sum_lights_class, 1, max_light_class); + + // Load the Basic Vertex Shaders at the appropriate level. + // (in order of shader function call depth for reference purposes, deepest level first) + + vector< pair > shaders; + shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) ); + shaders.push_back( make_pair( "lighting/lightV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl", sum_lights_class ) ); + shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "environment/srgbF.glsl", 1 ) ); - shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); - shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); + shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); + shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); shaders.push_back( make_pair( "deferred/textureUtilV.glsl", 1 ) ); - if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30) - { - shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) ); - } - shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); + if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30) + { + shaders.push_back( make_pair( "objects/indexedTextureV.glsl", 1 ) ); + } + shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) ); - std::map attribs; - attribs["MAX_JOINTS_PER_MESH_OBJECT"] = - std::to_string(LLSkinningUtil::getMaxJointCount()); + std::map attribs; + attribs["MAX_JOINTS_PER_MESH_OBJECT"] = + std::to_string(LLSkinningUtil::getMaxJointCount()); BOOL ssr = gSavedSettings.getBOOL("RenderScreenSpaceReflections"); - bool has_reflection_probes = gSavedSettings.getBOOL("RenderReflectionsEnabled") && gGLManager.mGLVersion > 3.99f; + bool has_reflection_probes = gSavedSettings.getBOOL("RenderReflectionsEnabled") && gGLManager.mGLVersion > 3.99f; - S32 probe_level = llclamp(gSavedSettings.getS32("RenderReflectionProbeLevel"), 0, 3); + S32 probe_level = llclamp(gSavedSettings.getS32("RenderReflectionProbeLevel"), 0, 3); S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); @@ -675,11 +675,11 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["SSR"] = "1"; } - if (has_reflection_probes) - { + if (has_reflection_probes) + { attribs["REFMAP_LEVEL"] = std::to_string(probe_level); - attribs["REF_SAMPLE_COUNT"] = "32"; - } + attribs["REF_SAMPLE_COUNT"] = "32"; + } { // PBR terrain const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); @@ -691,94 +691,94 @@ std::string LLViewerShaderMgr::loadBasicShaders() attribs["TERRAIN_PBR_DETAIL"] = llformat("%d", detail); } - LLGLSLShader::sGlobalDefines = attribs; + LLGLSLShader::sGlobalDefines = attribs; - // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. - for (U32 i = 0; i < shaders.size(); i++) - { - // Note usage of GL_VERTEX_SHADER - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER, &attribs) == 0) - { - LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; - return shaders[i].first; - } - } + // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. + for (U32 i = 0; i < shaders.size(); i++) + { + // Note usage of GL_VERTEX_SHADER + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER, &attribs) == 0) + { + LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; + return shaders[i].first; + } + } - // Load the Basic Fragment Shaders at the appropriate level. - // (in order of shader function call depth for reference purposes, deepest level first) + // Load the Basic Fragment Shaders at the appropriate level. + // (in order of shader function call depth for reference purposes, deepest level first) - shaders.clear(); - S32 ch = 1; + shaders.clear(); + S32 ch = 1; - if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) - { //use indexed texture rendering for GLSL >= 1.30 - ch = llmax(LLGLSLShader::sIndexedTextureChannels, 1); - } + if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) + { //use indexed texture rendering for GLSL >= 1.30 + ch = llmax(LLGLSLShader::sIndexedTextureChannels, 1); + } - std::vector index_channels; - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mShaderLevel[SHADER_WINDLIGHT]) ); + std::vector index_channels; + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mShaderLevel[SHADER_WINDLIGHT]) ); index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mShaderLevel[SHADER_WATER] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mShaderLevel[SHADER_WATER] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/srgbF.glsl", mShaderLevel[SHADER_ENVIRONMENT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/deferredUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/globalF.glsl", 1)); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); - - for (U32 i = 0; i < shaders.size(); i++) - { - // Note usage of GL_FRAGMENT_SHADER - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER, &attribs, index_channels[i]) == 0) - { - LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; - return shaders[i].first; - } - } - - return std::string(); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); + + for (U32 i = 0; i < shaders.size(); i++) + { + // Note usage of GL_FRAGMENT_SHADER + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER, &attribs, index_channels[i]) == 0) + { + LL_WARNS("Shader") << "Failed to load fragment shader " << shaders[i].first << LL_ENDL; + return shaders[i].first; + } + } + + return std::string(); } BOOL LLViewerShaderMgr::loadShadersWater() { LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; - BOOL terrainWaterSuccess = TRUE; - + BOOL success = TRUE; + BOOL terrainWaterSuccess = TRUE; + bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1 && gSavedSettings.getS32("RenderShadowDetail") > 0; - if (mShaderLevel[SHADER_WATER] == 0) - { - gWaterProgram.unload(); - gWaterEdgeProgram.unload(); - gUnderWaterProgram.unload(); - return TRUE; - } - - if (success) - { - // load water shader - gWaterProgram.mName = "Water Shader"; - gWaterProgram.mFeatures.calculatesAtmospherics = true; + if (mShaderLevel[SHADER_WATER] == 0) + { + gWaterProgram.unload(); + gWaterEdgeProgram.unload(); + gUnderWaterProgram.unload(); + return TRUE; + } + + if (success) + { + // load water shader + gWaterProgram.mName = "Water Shader"; + gWaterProgram.mFeatures.calculatesAtmospherics = true; gWaterProgram.mFeatures.hasAtmospherics = true; - gWaterProgram.mFeatures.hasGamma = true; - gWaterProgram.mFeatures.hasSrgb = true; + gWaterProgram.mFeatures.hasGamma = true; + gWaterProgram.mFeatures.hasSrgb = true; gWaterProgram.mFeatures.hasReflectionProbes = true; gWaterProgram.mFeatures.hasShadows = use_sun_shadow; - gWaterProgram.mShaderFiles.clear(); - gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); - gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER)); + gWaterProgram.mShaderFiles.clear(); + gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); + gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER)); gWaterProgram.clearPermutations(); if (LLPipeline::sRenderTransparentWater) { @@ -790,27 +790,27 @@ BOOL LLViewerShaderMgr::loadShadersWater() gWaterProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; - success = gWaterProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - // load water shader - gWaterEdgeProgram.mName = "Water Edge Shader"; - gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true; + gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; + success = gWaterProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + // load water shader + gWaterEdgeProgram.mName = "Water Edge Shader"; + gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true; gWaterEdgeProgram.mFeatures.hasAtmospherics = true; - gWaterEdgeProgram.mFeatures.hasGamma = true; - gWaterEdgeProgram.mFeatures.hasSrgb = true; + gWaterEdgeProgram.mFeatures.hasGamma = true; + gWaterEdgeProgram.mFeatures.hasSrgb = true; gWaterEdgeProgram.mFeatures.hasReflectionProbes = true; gWaterEdgeProgram.mFeatures.hasShadows = use_sun_shadow; - gWaterEdgeProgram.mShaderFiles.clear(); - gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); - gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER)); + gWaterEdgeProgram.mShaderFiles.clear(); + gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); + gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER)); gWaterEdgeProgram.clearPermutations(); - gWaterEdgeProgram.addPermutation("WATER_EDGE", "1"); + gWaterEdgeProgram.addPermutation("WATER_EDGE", "1"); if (LLPipeline::sRenderTransparentWater) { gWaterEdgeProgram.addPermutation("TRANSPARENT_WATER", "1"); @@ -820,54 +820,54 @@ BOOL LLViewerShaderMgr::loadShadersWater() { gWaterEdgeProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; - success = gWaterEdgeProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - //load under water vertex shader - gUnderWaterProgram.mName = "Underwater Shader"; - gUnderWaterProgram.mFeatures.calculatesAtmospherics = true; - gUnderWaterProgram.mFeatures.hasAtmospherics = true; - gUnderWaterProgram.mShaderFiles.clear(); - gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); - gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER)); - gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; - gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; + success = gWaterEdgeProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + //load under water vertex shader + gUnderWaterProgram.mName = "Underwater Shader"; + gUnderWaterProgram.mFeatures.calculatesAtmospherics = true; + gUnderWaterProgram.mFeatures.hasAtmospherics = true; + gUnderWaterProgram.mShaderFiles.clear(); + gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); + gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER)); + gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; + gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; gUnderWaterProgram.clearPermutations(); if (LLPipeline::sRenderTransparentWater) { gUnderWaterProgram.addPermutation("TRANSPARENT_WATER", "1"); } - success = gUnderWaterProgram.createShader(NULL, NULL); - llassert(success); - } - - /// Keep track of water shader levels - if (gWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER] - || gUnderWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER]) - { - mShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel); - } - - if (!success) - { - mShaderLevel[SHADER_WATER] = 0; - return FALSE; - } - - // if we failed to load the terrain water shaders and we need them (using class2 water), - // then drop down to class1 water. - if (mShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess) - { - mShaderLevel[SHADER_WATER]--; - return loadShadersWater(); - } - - LLWorld::getInstance()->updateWaterObjects(); + success = gUnderWaterProgram.createShader(NULL, NULL); + llassert(success); + } + + /// Keep track of water shader levels + if (gWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER] + || gUnderWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER]) + { + mShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel); + } + + if (!success) + { + mShaderLevel[SHADER_WATER] = 0; + return FALSE; + } + + // if we failed to load the terrain water shaders and we need them (using class2 water), + // then drop down to class1 water. + if (mShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess) + { + mShaderLevel[SHADER_WATER]--; + return loadShadersWater(); + } + + LLWorld::getInstance()->updateWaterObjects(); return TRUE; } @@ -875,146 +875,146 @@ BOOL LLViewerShaderMgr::loadShadersWater() BOOL LLViewerShaderMgr::loadShadersEffects() { LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; - - if (mShaderLevel[SHADER_EFFECT] == 0) - { - gGlowProgram.unload(); - gGlowExtractProgram.unload(); - return TRUE; - } - - if (success) - { - gGlowProgram.mName = "Glow Shader (Post)"; - gGlowProgram.mShaderFiles.clear(); - gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER)); - gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER)); - gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; - success = gGlowProgram.createShader(NULL, NULL); - if (!success) - { - LLPipeline::sRenderGlow = FALSE; - } - } - - if (success) - { + BOOL success = TRUE; + + if (mShaderLevel[SHADER_EFFECT] == 0) + { + gGlowProgram.unload(); + gGlowExtractProgram.unload(); + return TRUE; + } + + if (success) + { + gGlowProgram.mName = "Glow Shader (Post)"; + gGlowProgram.mShaderFiles.clear(); + gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER)); + gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER)); + gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + success = gGlowProgram.createShader(NULL, NULL); + if (!success) + { + LLPipeline::sRenderGlow = FALSE; + } + } + + if (success) + { const bool use_glow_noise = gSavedSettings.getBOOL("RenderGlowNoise"); const std::string glow_noise_label = use_glow_noise ? " (+Noise)" : ""; - gGlowExtractProgram.mName = llformat("Glow Extract Shader (Post)%s", glow_noise_label.c_str()); - gGlowExtractProgram.mShaderFiles.clear(); - gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER)); - gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER)); - gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; + gGlowExtractProgram.mName = llformat("Glow Extract Shader (Post)%s", glow_noise_label.c_str()); + gGlowExtractProgram.mShaderFiles.clear(); + gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER)); + gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER)); + gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT]; if (use_glow_noise) { gGlowExtractProgram.addPermutation("HAS_NOISE", "1"); } - success = gGlowExtractProgram.createShader(NULL, NULL); - if (!success) - { - LLPipeline::sRenderGlow = FALSE; - } - } - - return success; + success = gGlowExtractProgram.createShader(NULL, NULL); + if (!success) + { + LLPipeline::sRenderGlow = FALSE; + } + } + + return success; } BOOL LLViewerShaderMgr::loadShadersDeferred() { LL_PROFILE_ZONE_SCOPED; - bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1 && + bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1 && gSavedSettings.getS32("RenderShadowDetail") > 0; - if (mShaderLevel[SHADER_DEFERRED] == 0) - { - gDeferredTreeProgram.unload(); - gDeferredTreeShadowProgram.unload(); + if (mShaderLevel[SHADER_DEFERRED] == 0) + { + gDeferredTreeProgram.unload(); + gDeferredTreeShadowProgram.unload(); gDeferredSkinnedTreeShadowProgram.unload(); - gDeferredDiffuseProgram.unload(); + gDeferredDiffuseProgram.unload(); gDeferredSkinnedDiffuseProgram.unload(); - gDeferredDiffuseAlphaMaskProgram.unload(); + gDeferredDiffuseAlphaMaskProgram.unload(); gDeferredSkinnedDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); - gDeferredBumpProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.unload(); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload(); + gDeferredBumpProgram.unload(); gDeferredSkinnedBumpProgram.unload(); - gDeferredImpostorProgram.unload(); - gDeferredTerrainProgram.unload(); - gDeferredLightProgram.unload(); - for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i) - { - gDeferredMultiLightProgram[i].unload(); - } - gDeferredSpotLightProgram.unload(); - gDeferredMultiSpotLightProgram.unload(); - gDeferredSunProgram.unload(); - gDeferredBlurLightProgram.unload(); - gDeferredSoftenProgram.unload(); - gDeferredShadowProgram.unload(); + gDeferredImpostorProgram.unload(); + gDeferredTerrainProgram.unload(); + gDeferredLightProgram.unload(); + for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i) + { + gDeferredMultiLightProgram[i].unload(); + } + gDeferredSpotLightProgram.unload(); + gDeferredMultiSpotLightProgram.unload(); + gDeferredSunProgram.unload(); + gDeferredBlurLightProgram.unload(); + gDeferredSoftenProgram.unload(); + gDeferredShadowProgram.unload(); gDeferredSkinnedShadowProgram.unload(); - gDeferredShadowCubeProgram.unload(); + gDeferredShadowCubeProgram.unload(); gDeferredShadowAlphaMaskProgram.unload(); gDeferredSkinnedShadowAlphaMaskProgram.unload(); gDeferredShadowGLTFAlphaMaskProgram.unload(); gDeferredSkinnedShadowGLTFAlphaMaskProgram.unload(); gDeferredShadowFullbrightAlphaMaskProgram.unload(); gDeferredSkinnedShadowFullbrightAlphaMaskProgram.unload(); - gDeferredAvatarShadowProgram.unload(); + gDeferredAvatarShadowProgram.unload(); gDeferredAvatarAlphaShadowProgram.unload(); gDeferredAvatarAlphaMaskShadowProgram.unload(); - gDeferredAvatarProgram.unload(); - gDeferredAvatarAlphaProgram.unload(); - gDeferredAlphaProgram.unload(); + gDeferredAvatarProgram.unload(); + gDeferredAvatarAlphaProgram.unload(); + gDeferredAlphaProgram.unload(); gHUDAlphaProgram.unload(); gDeferredSkinnedAlphaProgram.unload(); - gDeferredFullbrightProgram.unload(); + gDeferredFullbrightProgram.unload(); gHUDFullbrightProgram.unload(); - gDeferredFullbrightAlphaMaskProgram.unload(); + gDeferredFullbrightAlphaMaskProgram.unload(); gHUDFullbrightAlphaMaskProgram.unload(); gDeferredFullbrightAlphaMaskAlphaProgram.unload(); gHUDFullbrightAlphaMaskAlphaProgram.unload(); - gDeferredEmissiveProgram.unload(); + gDeferredEmissiveProgram.unload(); gDeferredSkinnedEmissiveProgram.unload(); - gDeferredAvatarEyesProgram.unload(); - gDeferredPostProgram.unload(); - gDeferredCoFProgram.unload(); - gDeferredDoFCombineProgram.unload(); + gDeferredAvatarEyesProgram.unload(); + gDeferredPostProgram.unload(); + gDeferredCoFProgram.unload(); + gDeferredDoFCombineProgram.unload(); gExposureProgram.unload(); gExposureProgramNoFade.unload(); gLuminanceProgram.unload(); - gDeferredPostGammaCorrectProgram.unload(); + gDeferredPostGammaCorrectProgram.unload(); gNoPostGammaCorrectProgram.unload(); gLegacyPostGammaCorrectProgram.unload(); - gFXAAProgram.unload(); + gFXAAProgram.unload(); gEnvironmentMapProgram.unload(); - gDeferredWLSkyProgram.unload(); - gDeferredWLCloudProgram.unload(); + gDeferredWLSkyProgram.unload(); + gDeferredWLCloudProgram.unload(); gDeferredWLSunProgram.unload(); gDeferredWLMoonProgram.unload(); - gDeferredStarProgram.unload(); - gDeferredFullbrightShinyProgram.unload(); + gDeferredStarProgram.unload(); + gDeferredFullbrightShinyProgram.unload(); gHUDFullbrightShinyProgram.unload(); gDeferredSkinnedFullbrightShinyProgram.unload(); - gDeferredSkinnedFullbrightProgram.unload(); + gDeferredSkinnedFullbrightProgram.unload(); gDeferredSkinnedFullbrightAlphaMaskProgram.unload(); gDeferredSkinnedFullbrightAlphaMaskAlphaProgram.unload(); gDeferredHighlightProgram.unload(); - - gNormalMapGenProgram.unload(); + + gNormalMapGenProgram.unload(); gDeferredGenBrdfLutProgram.unload(); - gDeferredBufferVisualProgram.unload(); + gDeferredBufferVisualProgram.unload(); - for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) - { - gDeferredMaterialProgram[i].unload(); - } + for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) + { + gDeferredMaterialProgram[i].unload(); + } gHUDPBROpaqueProgram.unload(); gPBRGlowProgram.unload(); @@ -1022,95 +1022,95 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSkinnedPBROpaqueProgram.unload(); gDeferredPBRAlphaProgram.unload(); gDeferredSkinnedPBRAlphaProgram.unload(); - gDeferredPBRTerrainProgram.unload(); + gDeferredPBRTerrainProgram.unload(); - return TRUE; - } + return TRUE; + } - BOOL success = TRUE; + BOOL success = TRUE; if (success) - { - gDeferredHighlightProgram.mName = "Deferred Highlight Shader"; - gDeferredHighlightProgram.mShaderFiles.clear(); - gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER)); - gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gDeferredHighlightProgram.createShader(NULL, NULL); - } + { + gDeferredHighlightProgram.mName = "Deferred Highlight Shader"; + gDeferredHighlightProgram.mShaderFiles.clear(); + gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER)); + gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gDeferredHighlightProgram.createShader(NULL, NULL); + } - if (success) - { - gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; + if (success) + { + gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mFeatures.hasSrgb = true; - gDeferredDiffuseProgram.mShaderFiles.clear(); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER)); - gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredDiffuseProgram.mShaderFiles.clear(); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER)); + gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredDiffuseProgram, gDeferredSkinnedDiffuseProgram); - success = success && gDeferredDiffuseProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); - gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER)); - gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = success && gDeferredDiffuseProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER)); + gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredDiffuseAlphaMaskProgram, gDeferredSkinnedDiffuseAlphaMaskProgram); - success = success && gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); - gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); + success = success && gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask No Color Shader"; - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear(); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER)); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER)); - gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredBumpProgram.mName = "Deferred Bump Shader"; - gDeferredBumpProgram.mShaderFiles.clear(); - gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER)); - gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER)); - gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + } + + if (success) + { + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask No Color Shader"; + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER)); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER)); + gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredBumpProgram.mName = "Deferred Bump Shader"; + gDeferredBumpProgram.mShaderFiles.clear(); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER)); + gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER)); + gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredBumpProgram, gDeferredSkinnedBumpProgram); - success = success && gDeferredBumpProgram.createShader(NULL, NULL); - llassert(success); - } - - gDeferredMaterialProgram[1].mFeatures.hasLighting = false; - gDeferredMaterialProgram[5].mFeatures.hasLighting = false; - gDeferredMaterialProgram[9].mFeatures.hasLighting = false; - gDeferredMaterialProgram[13].mFeatures.hasLighting = false; - gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; - - for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) - { - if (success) - { + success = success && gDeferredBumpProgram.createShader(NULL, NULL); + llassert(success); + } + + gDeferredMaterialProgram[1].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13].mFeatures.hasLighting = false; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = false; + + for (U32 i = 0; i < LLMaterial::SHADER_COUNT*2; ++i) + { + if (success) + { bool has_skin = i & 0x10; if (!has_skin) @@ -1122,28 +1122,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMaterialProgram[i].mName = llformat("Skinned Material Shader %d", i); } - - U32 alpha_mode = i & 0x3; - gDeferredMaterialProgram[i].mShaderFiles.clear(); - gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER)); - gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER)); - gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + U32 alpha_mode = i & 0x3; - gDeferredMaterialProgram[i].clearPermutations(); + gDeferredMaterialProgram[i].mShaderFiles.clear(); + gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER)); + gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER)); + gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - bool has_normal_map = (i & 0x8) > 0; - bool has_specular_map = (i & 0x4) > 0; + gDeferredMaterialProgram[i].clearPermutations(); - if (has_normal_map) - { - gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", "1"); - } + bool has_normal_map = (i & 0x8) > 0; + bool has_specular_map = (i & 0x4) > 0; - if (has_specular_map) - { - gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", "1"); - } + if (has_normal_map) + { + gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", "1"); + } + + if (has_specular_map) + { + gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", "1"); + } gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode)); @@ -1158,7 +1158,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1"); } - + gDeferredMaterialProgram[i].mFeatures.hasSrgb = true; gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true; gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true; @@ -1178,17 +1178,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredMaterialProgram[i].createShader(NULL, NULL); llassert(success); - } - } + } + } - gDeferredMaterialProgram[1].mFeatures.hasLighting = true; - gDeferredMaterialProgram[5].mFeatures.hasLighting = true; - gDeferredMaterialProgram[9].mFeatures.hasLighting = true; - gDeferredMaterialProgram[13].mFeatures.hasLighting = true; - gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; - gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[1].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13].mFeatures.hasLighting = true; + gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; + gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT].mFeatures.hasLighting = true; if (success) { @@ -1200,7 +1200,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBROpaqueProgram.mShaderFiles.push_back(make_pair("deferred/pbropaqueF.glsl", GL_FRAGMENT_SHADER)); gDeferredPBROpaqueProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredPBROpaqueProgram.clearPermutations(); - + success = make_rigged_variant(gDeferredPBROpaqueProgram, gDeferredSkinnedPBROpaqueProgram); if (success) { @@ -1238,17 +1238,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gHUDPBROpaqueProgram.addPermutation("IS_HUD", "1"); success = gHUDPBROpaqueProgram.createShader(NULL, NULL); - + llassert(success); } - - if (success) - { + + if (success) + { LLGLSLShader* shader = &gDeferredPBRAlphaProgram; shader->mName = "Deferred PBR Alpha Shader"; - + shader->mFeatures.calculatesLighting = false; shader->mFeatures.hasLighting = false; shader->mFeatures.isAlphaLighting = true; @@ -1301,7 +1301,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() shader->mName = "HUD PBR Alpha Shader"; shader->mFeatures.hasSrgb = true; - + shader->mShaderFiles.clear(); shader->mShaderFiles.push_back(make_pair("deferred/pbralphaV.glsl", GL_VERTEX_SHADER)); shader->mShaderFiles.push_back(make_pair("deferred/pbralphaF.glsl", GL_FRAGMENT_SHADER)); @@ -1315,8 +1315,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { + if (success) + { S32 detail = gSavedSettings.getS32("RenderTerrainPBRDetail"); detail = llclamp(detail, TERRAIN_PBR_DETAIL_MIN, TERRAIN_PBR_DETAIL_MAX); const S32 mapping = clamp_terrain_mapping(gSavedSettings.getS32("RenderTerrainPBRPlanarSampleCount")); @@ -1340,29 +1340,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredPBRTerrainProgram.addPermutation("TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT", llformat("%d", mapping)); success = gDeferredPBRTerrainProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredTreeProgram.mName = "Deferred Tree Shader"; - gDeferredTreeProgram.mShaderFiles.clear(); - gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER)); - gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER)); - gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredTreeProgram.createShader(NULL, NULL); - } - - if (success) - { - gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; - gDeferredTreeShadowProgram.mShaderFiles.clear(); - gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + } + + if (success) + { + gDeferredTreeProgram.mName = "Deferred Tree Shader"; + gDeferredTreeProgram.mShaderFiles.clear(); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER)); + gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER)); + gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredTreeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader"; + gDeferredTreeShadowProgram.mShaderFiles.clear(); + gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER)); + gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER)); + gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredTreeShadowProgram.mRiggedVariant = &gDeferredSkinnedTreeShadowProgram; - success = gDeferredTreeShadowProgram.createShader(NULL, NULL); + success = gDeferredTreeShadowProgram.createShader(NULL, NULL); llassert(success); - } + } if (success) { @@ -1376,96 +1376,96 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; - gDeferredImpostorProgram.mFeatures.hasSrgb = true; - gDeferredImpostorProgram.mShaderFiles.clear(); - gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER)); + if (success) + { + gDeferredImpostorProgram.mName = "Deferred Impostor Shader"; + gDeferredImpostorProgram.mFeatures.hasSrgb = true; + gDeferredImpostorProgram.mShaderFiles.clear(); + gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER)); gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER)); gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredImpostorProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredLightProgram.mName = "Deferred Light Shader"; - gDeferredLightProgram.mFeatures.isDeferred = true; - gDeferredLightProgram.mFeatures.hasShadows = true; + if (success) + { + gDeferredLightProgram.mName = "Deferred Light Shader"; + gDeferredLightProgram.mFeatures.isDeferred = true; + gDeferredLightProgram.mFeatures.hasShadows = true; gDeferredLightProgram.mFeatures.hasSrgb = true; - gDeferredLightProgram.mShaderFiles.clear(); - gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER)); - gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredLightProgram.mShaderFiles.clear(); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER)); + gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredLightProgram.clearPermutations(); - success = gDeferredLightProgram.createShader(NULL, NULL); + success = gDeferredLightProgram.createShader(NULL, NULL); llassert(success); - } - - for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++) - { - if (success) - { - gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); - gDeferredMultiLightProgram[i].mFeatures.isDeferred = true; - gDeferredMultiLightProgram[i].mFeatures.hasShadows = true; + } + + for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++) + { + if (success) + { + gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i); + gDeferredMultiLightProgram[i].mFeatures.isDeferred = true; + gDeferredMultiLightProgram[i].mFeatures.hasShadows = true; gDeferredMultiLightProgram[i].mFeatures.hasSrgb = true; gDeferredMultiLightProgram[i].clearPermutations(); - gDeferredMultiLightProgram[i].mShaderFiles.clear(); - gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER)); - gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); + gDeferredMultiLightProgram[i].mShaderFiles.clear(); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER)); + gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1)); - success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); + success = gDeferredMultiLightProgram[i].createShader(NULL, NULL); llassert(success); - } - } + } + } - if (success) - { - gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; - gDeferredSpotLightProgram.mShaderFiles.clear(); - gDeferredSpotLightProgram.mFeatures.hasSrgb = true; - gDeferredSpotLightProgram.mFeatures.isDeferred = true; - gDeferredSpotLightProgram.mFeatures.hasShadows = true; + if (success) + { + gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; + gDeferredSpotLightProgram.mShaderFiles.clear(); + gDeferredSpotLightProgram.mFeatures.hasSrgb = true; + gDeferredSpotLightProgram.mFeatures.isDeferred = true; + gDeferredSpotLightProgram.mFeatures.hasShadows = true; gDeferredSpotLightProgram.clearPermutations(); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER)); - gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredSpotLightProgram.createShader(NULL, NULL); + success = gDeferredSpotLightProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; - gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true; - gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true; - gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true; + if (success) + { + gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; + gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true; + gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true; + gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true; gDeferredMultiSpotLightProgram.clearPermutations(); gDeferredMultiSpotLightProgram.addPermutation("MULTI_SPOTLIGHT", "1"); - gDeferredMultiSpotLightProgram.mShaderFiles.clear(); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER)); - gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredMultiSpotLightProgram.mShaderFiles.clear(); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); + success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - std::string fragment; - std::string vertex = "deferred/sunLightV.glsl"; + if (success) + { + std::string fragment; + std::string vertex = "deferred/sunLightV.glsl"; bool use_ao = gSavedSettings.getBOOL("RenderDeferredSSAO"); @@ -1488,30 +1488,30 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSunProgram.mFeatures.hasAmbientOcclusion = use_ao; gDeferredSunProgram.mShaderFiles.clear(); - gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER)); - gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER)); - gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER)); + gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; - gDeferredBlurLightProgram.mFeatures.isDeferred = true; + if (success) + { + gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader"; + gDeferredBlurLightProgram.mFeatures.isDeferred = true; - gDeferredBlurLightProgram.mShaderFiles.clear(); - gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER)); - gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredBlurLightProgram.mShaderFiles.clear(); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER)); + gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredBlurLightProgram.createShader(NULL, NULL); + success = gDeferredBlurLightProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { + if (success) + { for (int i = 0; i < 3 && success; ++i) { LLGLSLShader* shader = nullptr; @@ -1584,9 +1584,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { - LLGLSLShader* shaders[] = { - &gDeferredAlphaImpostorProgram, - &gDeferredSkinnedAlphaImpostorProgram + LLGLSLShader* shaders[] = { + &gDeferredAlphaImpostorProgram, + &gDeferredSkinnedAlphaImpostorProgram }; for (int i = 0; i < 2 && success; ++i) @@ -1641,40 +1641,40 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } } - if (success) - { - gDeferredAvatarEyesProgram.mName = "Deferred Avatar Eyes Shader"; - gDeferredAvatarEyesProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAvatarEyesProgram.mFeatures.hasGamma = true; - gDeferredAvatarEyesProgram.mFeatures.hasAtmospherics = true; - gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true; - gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true; - gDeferredAvatarEyesProgram.mFeatures.hasShadows = true; - - gDeferredAvatarEyesProgram.mShaderFiles.clear(); - gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER)); - gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarEyesProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader"; - gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true; - gDeferredFullbrightProgram.mFeatures.hasGamma = true; - gDeferredFullbrightProgram.mFeatures.hasAtmospherics = true; - gDeferredFullbrightProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredFullbrightProgram.mShaderFiles.clear(); - gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER)); - gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (success) + { + gDeferredAvatarEyesProgram.mName = "Deferred Avatar Eyes Shader"; + gDeferredAvatarEyesProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAvatarEyesProgram.mFeatures.hasGamma = true; + gDeferredAvatarEyesProgram.mFeatures.hasAtmospherics = true; + gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true; + gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true; + gDeferredAvatarEyesProgram.mFeatures.hasShadows = true; + + gDeferredAvatarEyesProgram.mShaderFiles.clear(); + gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER)); + gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER)); + gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarEyesProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredFullbrightProgram.mName = "Deferred Fullbright Shader"; + gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightProgram.mFeatures.hasGamma = true; + gDeferredFullbrightProgram.mFeatures.hasAtmospherics = true; + gDeferredFullbrightProgram.mFeatures.hasSrgb = true; + gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightProgram.mShaderFiles.clear(); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER)); + gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredFullbrightProgram, gDeferredSkinnedFullbrightProgram); - success = gDeferredFullbrightProgram.createShader(NULL, NULL); - llassert(success); - } + success = gDeferredFullbrightProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -1694,24 +1694,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredFullbrightAlphaMaskProgram.mName = "Deferred Fullbright Alpha Masking Shader"; - gDeferredFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; - gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; - gDeferredFullbrightAlphaMaskProgram.mFeatures.hasAtmospherics = true; - gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear(); - gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER)); - gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER)); + if (success) + { + gDeferredFullbrightAlphaMaskProgram.mName = "Deferred Fullbright Alpha Masking Shader"; + gDeferredFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true; + gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER)); + gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER)); gDeferredFullbrightAlphaMaskProgram.clearPermutations(); - gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1"); - gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1"); + gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredFullbrightAlphaMaskProgram, gDeferredSkinnedFullbrightAlphaMaskProgram); - success = success && gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); - llassert(success); - } + success = success && gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -1774,23 +1774,23 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredFullbrightShinyProgram.mName = "Deferred FullbrightShiny Shader"; - gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; - gDeferredFullbrightShinyProgram.mFeatures.hasAtmospherics = true; - gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true; - gDeferredFullbrightShinyProgram.mFeatures.hasSrgb = true; - gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredFullbrightShinyProgram.mShaderFiles.clear(); - gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER)); - gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER)); - gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (success) + { + gDeferredFullbrightShinyProgram.mName = "Deferred FullbrightShiny Shader"; + gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gDeferredFullbrightShinyProgram.mFeatures.hasAtmospherics = true; + gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true; + gDeferredFullbrightShinyProgram.mFeatures.hasSrgb = true; + gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredFullbrightShinyProgram.mShaderFiles.clear(); + gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER)); + gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER)); + gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredFullbrightShinyProgram.mFeatures.hasReflectionProbes = true; success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram); - success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL); - llassert(success); - } + success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -1811,54 +1811,54 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredEmissiveProgram.mName = "Deferred Emissive Shader"; - gDeferredEmissiveProgram.mFeatures.calculatesAtmospherics = true; - gDeferredEmissiveProgram.mFeatures.hasGamma = true; - gDeferredEmissiveProgram.mFeatures.hasAtmospherics = true; - gDeferredEmissiveProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - gDeferredEmissiveProgram.mShaderFiles.clear(); - gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER)); - gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER)); - gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + if (success) + { + gDeferredEmissiveProgram.mName = "Deferred Emissive Shader"; + gDeferredEmissiveProgram.mFeatures.calculatesAtmospherics = true; + gDeferredEmissiveProgram.mFeatures.hasGamma = true; + gDeferredEmissiveProgram.mFeatures.hasAtmospherics = true; + gDeferredEmissiveProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + gDeferredEmissiveProgram.mShaderFiles.clear(); + gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER)); + gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER)); + gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredEmissiveProgram, gDeferredSkinnedEmissiveProgram); - success = success && gDeferredEmissiveProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredSoftenProgram.mName = "Deferred Soften Shader"; - gDeferredSoftenProgram.mShaderFiles.clear(); - gDeferredSoftenProgram.mFeatures.hasSrgb = true; - gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true; - gDeferredSoftenProgram.mFeatures.hasAtmospherics = true; - gDeferredSoftenProgram.mFeatures.hasGamma = true; - gDeferredSoftenProgram.mFeatures.isDeferred = true; - gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow; + success = success && gDeferredEmissiveProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredSoftenProgram.mName = "Deferred Soften Shader"; + gDeferredSoftenProgram.mShaderFiles.clear(); + gDeferredSoftenProgram.mFeatures.hasSrgb = true; + gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSoftenProgram.mFeatures.hasAtmospherics = true; + gDeferredSoftenProgram.mFeatures.hasGamma = true; + gDeferredSoftenProgram.mFeatures.isDeferred = true; + gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow; gDeferredSoftenProgram.mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED] > 2; gDeferredSoftenProgram.clearPermutations(); - gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER)); - gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER)); - gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; if (use_sun_shadow) { gDeferredSoftenProgram.addPermutation("HAS_SUN_SHADOW", "1"); } - if (gSavedSettings.getBOOL("RenderDeferredSSAO")) - { //if using SSAO, take screen space light map into account as if shadows are enabled - gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2); + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { //if using SSAO, take screen space light map into account as if shadows are enabled + gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2); gDeferredSoftenProgram.addPermutation("HAS_SSAO", "1"); - } - - success = gDeferredSoftenProgram.createShader(NULL, NULL); - llassert(success); - } + } + + success = gDeferredSoftenProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -1907,17 +1907,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } - if (success) - { - gDeferredShadowProgram.mName = "Deferred Shadow Shader"; - gDeferredShadowProgram.mShaderFiles.clear(); - gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER)); - gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram; - success = gDeferredShadowProgram.createShader(NULL, NULL); - llassert(success); - } + if (success) + { + gDeferredShadowProgram.mName = "Deferred Shadow Shader"; + gDeferredShadowProgram.mShaderFiles.clear(); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER)); + gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER)); + gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram; + success = gDeferredShadowProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -1934,52 +1934,52 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; - gDeferredShadowCubeProgram.mFeatures.isDeferred = true; - gDeferredShadowCubeProgram.mFeatures.hasShadows = true; - gDeferredShadowCubeProgram.mShaderFiles.clear(); - gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER)); - gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER)); - // gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1"); - gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredShadowCubeProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredShadowFullbrightAlphaMaskProgram.mName = "Deferred Shadow Fullbright Alpha Mask Shader"; - gDeferredShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - - gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.clear(); - gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER)); - gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); + if (success) + { + gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader"; + gDeferredShadowCubeProgram.mFeatures.isDeferred = true; + gDeferredShadowCubeProgram.mFeatures.hasShadows = true; + gDeferredShadowCubeProgram.mShaderFiles.clear(); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER)); + gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER)); + // gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1"); + gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowCubeProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredShadowFullbrightAlphaMaskProgram.mName = "Deferred Shadow Fullbright Alpha Mask Shader"; + gDeferredShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER)); + gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); gDeferredShadowFullbrightAlphaMaskProgram.clearPermutations(); - gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); + gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1"); gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1"); - gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredShadowFullbrightAlphaMaskProgram, gDeferredSkinnedShadowFullbrightAlphaMaskProgram); success = success && gDeferredShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; - gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; - - gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); - gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER)); - gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); - gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + llassert(success); + } + + if (success) + { + gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; + gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels; + + gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER)); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER)); + gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = make_rigged_variant(gDeferredShadowAlphaMaskProgram, gDeferredSkinnedShadowAlphaMaskProgram); success = success && gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL); - llassert(success); - } - + llassert(success); + } + if (success) { @@ -2007,108 +2007,108 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; - gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; - - gDeferredAvatarShadowProgram.mShaderFiles.clear(); - gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarShadowProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader"; - gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true; - gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear(); - gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL); + if (success) + { + gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; + gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true; + + gDeferredAvatarShadowProgram.mShaderFiles.clear(); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER)); + gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER)); + gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarShadowProgram.createShader(NULL, NULL); llassert(success); - } - if (success) - { - gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader"; - gDeferredAvatarAlphaMaskShadowProgram.mFeatures.hasSkinning = true; - gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear(); - gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER)); - gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader"; + gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true; + gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear(); + gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER)); + gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER)); + gDeferredAvatarAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) + { + gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader"; + gDeferredAvatarAlphaMaskShadowProgram.mFeatures.hasSkinning = true; + gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear(); + gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER)); + gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER)); + gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredTerrainProgram.mName = "Deferred Terrain Shader"; - gDeferredTerrainProgram.mFeatures.hasSrgb = true; - gDeferredTerrainProgram.mFeatures.isAlphaLighting = true; - gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels - gDeferredTerrainProgram.mFeatures.calculatesAtmospherics = true; - gDeferredTerrainProgram.mFeatures.hasAtmospherics = true; - gDeferredTerrainProgram.mFeatures.hasGamma = true; - - gDeferredTerrainProgram.mShaderFiles.clear(); - gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER)); - gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER)); - gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + } + + if (success) + { + gDeferredTerrainProgram.mName = "Deferred Terrain Shader"; + gDeferredTerrainProgram.mFeatures.hasSrgb = true; + gDeferredTerrainProgram.mFeatures.isAlphaLighting = true; + gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + gDeferredTerrainProgram.mFeatures.calculatesAtmospherics = true; + gDeferredTerrainProgram.mFeatures.hasAtmospherics = true; + gDeferredTerrainProgram.mFeatures.hasGamma = true; + + gDeferredTerrainProgram.mShaderFiles.clear(); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER)); + gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER)); + gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; success = gDeferredTerrainProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredAvatarProgram.mName = "Deferred Avatar Shader"; - gDeferredAvatarProgram.mFeatures.hasSkinning = true; - gDeferredAvatarProgram.mShaderFiles.clear(); - gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER)); - gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredAvatarAlphaProgram.mName = "Deferred Avatar Alpha Shader"; - gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; - gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false; - gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false; - gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true; - gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; - gDeferredAvatarAlphaProgram.mFeatures.hasSrgb = true; - gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; - gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; + llassert(success); + } + + if (success) + { + gDeferredAvatarProgram.mName = "Deferred Avatar Shader"; + gDeferredAvatarProgram.mFeatures.hasSkinning = true; + gDeferredAvatarProgram.mShaderFiles.clear(); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER)); + gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER)); + gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredAvatarProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredAvatarAlphaProgram.mName = "Deferred Avatar Alpha Shader"; + gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false; + gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; + gDeferredAvatarAlphaProgram.mFeatures.hasSrgb = true; + gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; gDeferredAvatarAlphaProgram.mFeatures.isDeferred = true; - gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true; + gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true; gDeferredAvatarAlphaProgram.mFeatures.hasReflectionProbes = true; - gDeferredAvatarAlphaProgram.mShaderFiles.clear(); + gDeferredAvatarAlphaProgram.mShaderFiles.clear(); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER)); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER)); - gDeferredAvatarAlphaProgram.clearPermutations(); - gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); - gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1"); - if (use_sun_shadow) - { - gDeferredAvatarAlphaProgram.addPermutation("HAS_SUN_SHADOW", "1"); - } + gDeferredAvatarAlphaProgram.clearPermutations(); + gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1"); + gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1"); + if (use_sun_shadow) + { + gDeferredAvatarAlphaProgram.addPermutation("HAS_SUN_SHADOW", "1"); + } - gDeferredAvatarAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredAvatarAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL); - llassert(success); + success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL); + llassert(success); - gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; - gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; - } + gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; + } if (success) { @@ -2151,20 +2151,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process"; - gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true; - gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true; - gDeferredPostGammaCorrectProgram.mShaderFiles.clear(); + if (success) + { + gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process"; + gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true; + gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true; + gDeferredPostGammaCorrectProgram.mShaderFiles.clear(); gDeferredPostGammaCorrectProgram.clearPermutations(); gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER)); + gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER)); gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL); - llassert(success); - } - + success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL); + llassert(success); + } + if (success) { gNoPostGammaCorrectProgram.mName = "No Post Gamma Correction Post Process"; @@ -2196,65 +2196,65 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() } - if (success && gGLManager.mGLVersion > 3.9f) - { - gFXAAProgram.mName = "FXAA Shader"; - gFXAAProgram.mFeatures.isDeferred = true; - gFXAAProgram.mShaderFiles.clear(); - gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER)); - gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER)); - gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gFXAAProgram.createShader(NULL, NULL); - llassert(success); - } + if (success && gGLManager.mGLVersion > 3.9f) + { + gFXAAProgram.mName = "FXAA Shader"; + gFXAAProgram.mFeatures.isDeferred = true; + gFXAAProgram.mShaderFiles.clear(); + gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER)); + gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER)); + gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gFXAAProgram.createShader(NULL, NULL); + llassert(success); + } - if (success) - { - gDeferredPostProgram.mName = "Deferred Post Shader"; + if (success) + { + gDeferredPostProgram.mName = "Deferred Post Shader"; gDeferredPostProgram.mFeatures.isDeferred = true; - gDeferredPostProgram.mShaderFiles.clear(); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER)); - gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredCoFProgram.mName = "Deferred CoF Shader"; - gDeferredCoFProgram.mShaderFiles.clear(); - gDeferredCoFProgram.mFeatures.isDeferred = true; - gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER)); - gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredCoFProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader"; - gDeferredDoFCombineProgram.mFeatures.isDeferred = true; - gDeferredDoFCombineProgram.mShaderFiles.clear(); - gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER)); - gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredDoFCombineProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredPostNoDoFProgram.mName = "Deferred Post NoDoF Shader"; - gDeferredPostNoDoFProgram.mFeatures.isDeferred = true; - gDeferredPostNoDoFProgram.mShaderFiles.clear(); - gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER)); - gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); - llassert(success); - } + gDeferredPostProgram.mShaderFiles.clear(); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER)); + gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredCoFProgram.mName = "Deferred CoF Shader"; + gDeferredCoFProgram.mShaderFiles.clear(); + gDeferredCoFProgram.mFeatures.isDeferred = true; + gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER)); + gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredCoFProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader"; + gDeferredDoFCombineProgram.mFeatures.isDeferred = true; + gDeferredDoFCombineProgram.mShaderFiles.clear(); + gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER)); + gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredDoFCombineProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredPostNoDoFProgram.mName = "Deferred Post NoDoF Shader"; + gDeferredPostNoDoFProgram.mFeatures.isDeferred = true; + gDeferredPostNoDoFProgram.mShaderFiles.clear(); + gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER)); + gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); + llassert(success); + } if (success) { @@ -2276,45 +2276,45 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() llassert(success); } - if (success) - { - gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader"; - gDeferredWLSkyProgram.mShaderFiles.clear(); - gDeferredWLSkyProgram.mFeatures.calculatesAtmospherics = true; - gDeferredWLSkyProgram.mFeatures.hasAtmospherics = true; - gDeferredWLSkyProgram.mFeatures.hasGamma = true; - gDeferredWLSkyProgram.mFeatures.hasSrgb = true; - - gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER)); - gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER)); - gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; - - success = gDeferredWLSkyProgram.createShader(NULL, NULL); - llassert(success); - } - - if (success) - { - gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program"; - gDeferredWLCloudProgram.mShaderFiles.clear(); - gDeferredWLCloudProgram.mFeatures.calculatesAtmospherics = true; - gDeferredWLCloudProgram.mFeatures.hasAtmospherics = true; + if (success) + { + gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader"; + gDeferredWLSkyProgram.mShaderFiles.clear(); + gDeferredWLSkyProgram.mFeatures.calculatesAtmospherics = true; + gDeferredWLSkyProgram.mFeatures.hasAtmospherics = true; + gDeferredWLSkyProgram.mFeatures.hasGamma = true; + gDeferredWLSkyProgram.mFeatures.hasSrgb = true; + + gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER)); + gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER)); + gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; + + success = gDeferredWLSkyProgram.createShader(NULL, NULL); + llassert(success); + } + + if (success) + { + gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program"; + gDeferredWLCloudProgram.mShaderFiles.clear(); + gDeferredWLCloudProgram.mFeatures.calculatesAtmospherics = true; + gDeferredWLCloudProgram.mFeatures.hasAtmospherics = true; gDeferredWLCloudProgram.mFeatures.hasGamma = true; gDeferredWLCloudProgram.mFeatures.hasSrgb = true; - - gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER)); - gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER)); - gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; + + gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER)); + gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER)); + gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; gDeferredWLCloudProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113 - success = gDeferredWLCloudProgram.createShader(NULL, NULL); - llassert(success); - } + success = gDeferredWLCloudProgram.createShader(NULL, NULL); + llassert(success); + } - if (success) - { - gDeferredWLSunProgram.mName = "Deferred Windlight Sun Program"; + if (success) + { + gDeferredWLSunProgram.mName = "Deferred Windlight Sun Program"; gDeferredWLSunProgram.mFeatures.calculatesAtmospherics = true; gDeferredWLSunProgram.mFeatures.hasAtmospherics = true; gDeferredWLSunProgram.mFeatures.hasGamma = true; @@ -2339,40 +2339,40 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredWLMoonProgram.mFeatures.hasAtmospherics = true; gDeferredWLMoonProgram.mFeatures.hasSrgb = true; gDeferredWLMoonProgram.mFeatures.disableTextureIndex = true; - + gDeferredWLMoonProgram.mShaderFiles.clear(); gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER)); gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER)); gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY; gDeferredWLMoonProgram.addConstant( LLGLSLShader::SHADER_CONST_CLOUD_MOON_DEPTH ); // SL-14113 - success = gDeferredWLMoonProgram.createShader(NULL, NULL); + success = gDeferredWLMoonProgram.createShader(NULL, NULL); llassert(success); - } - - if (success) - { - gDeferredStarProgram.mName = "Deferred Star Program"; - gDeferredStarProgram.mShaderFiles.clear(); - gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER)); - gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER)); - gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; + } + + if (success) + { + gDeferredStarProgram.mName = "Deferred Star Program"; + gDeferredStarProgram.mShaderFiles.clear(); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER)); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER)); + gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; gDeferredStarProgram.addConstant( LLGLSLShader::SHADER_CONST_STAR_DEPTH ); // SL-14113 - success = gDeferredStarProgram.createShader(NULL, NULL); + success = gDeferredStarProgram.createShader(NULL, NULL); llassert(success); - } + } - if (success) - { - gNormalMapGenProgram.mName = "Normal Map Generation Program"; - gNormalMapGenProgram.mShaderFiles.clear(); - gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER)); - gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER)); - gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY; - success = gNormalMapGenProgram.createShader(NULL, NULL); - } + if (success) + { + gNormalMapGenProgram.mName = "Normal Map Generation Program"; + gNormalMapGenProgram.mShaderFiles.clear(); + gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER)); + gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER)); + gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gNormalMapGenProgram.createShader(NULL, NULL); + } if (success) { @@ -2384,7 +2384,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredGenBrdfLutProgram.createShader(NULL, NULL); } - if (success) { + if (success) { gPostScreenSpaceReflectionProgram.mName = "Screen Space Reflection Post"; gPostScreenSpaceReflectionProgram.mShaderFiles.clear(); gPostScreenSpaceReflectionProgram.mShaderFiles.push_back(make_pair("deferred/screenSpaceReflPostV.glsl", GL_VERTEX_SHADER)); @@ -2393,24 +2393,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gPostScreenSpaceReflectionProgram.mFeatures.isDeferred = true; gPostScreenSpaceReflectionProgram.mShaderLevel = 3; success = gPostScreenSpaceReflectionProgram.createShader(NULL, NULL); - } - - if (success) { - gDeferredBufferVisualProgram.mName = "Deferred Buffer Visualization Shader"; - gDeferredBufferVisualProgram.mShaderFiles.clear(); - gDeferredBufferVisualProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); - gDeferredBufferVisualProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredVisualizeBuffers.glsl", GL_FRAGMENT_SHADER)); - gDeferredBufferVisualProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; - success = gDeferredBufferVisualProgram.createShader(NULL, NULL); - } - - return success; + } + + if (success) { + gDeferredBufferVisualProgram.mName = "Deferred Buffer Visualization Shader"; + gDeferredBufferVisualProgram.mShaderFiles.clear(); + gDeferredBufferVisualProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); + gDeferredBufferVisualProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredVisualizeBuffers.glsl", GL_FRAGMENT_SHADER)); + gDeferredBufferVisualProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED]; + success = gDeferredBufferVisualProgram.createShader(NULL, NULL); + } + + return success; } BOOL LLViewerShaderMgr::loadShadersObject() { LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; + BOOL success = TRUE; if (success) { @@ -2434,66 +2434,66 @@ BOOL LLViewerShaderMgr::loadShadersObject() } } - if (success) - { - gObjectAlphaMaskNoColorProgram.mName = "No color alpha mask Shader"; - gObjectAlphaMaskNoColorProgram.mFeatures.calculatesLighting = true; - gObjectAlphaMaskNoColorProgram.mFeatures.calculatesAtmospherics = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasGamma = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasAtmospherics = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasLighting = true; - gObjectAlphaMaskNoColorProgram.mFeatures.disableTextureIndex = true; - gObjectAlphaMaskNoColorProgram.mFeatures.hasAlphaMask = true; - gObjectAlphaMaskNoColorProgram.mShaderFiles.clear(); - gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER)); - gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER)); - gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL); - } - - if (success) - { - gImpostorProgram.mName = "Impostor Shader"; - gImpostorProgram.mFeatures.disableTextureIndex = true; - gImpostorProgram.mFeatures.hasSrgb = true; - gImpostorProgram.mShaderFiles.clear(); - gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER)); - gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER)); - gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gImpostorProgram.createShader(NULL, NULL); - } - - if (success) - { - gObjectPreviewProgram.mName = "Object Preview Shader"; - gObjectPreviewProgram.mFeatures.disableTextureIndex = true; - gObjectPreviewProgram.mShaderFiles.clear(); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER)); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER)); - gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + if (success) + { + gObjectAlphaMaskNoColorProgram.mName = "No color alpha mask Shader"; + gObjectAlphaMaskNoColorProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNoColorProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasGamma = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNoColorProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNoColorProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNoColorProgram.mShaderFiles.clear(); + gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER)); + gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER)); + gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL); + } + + if (success) + { + gImpostorProgram.mName = "Impostor Shader"; + gImpostorProgram.mFeatures.disableTextureIndex = true; + gImpostorProgram.mFeatures.hasSrgb = true; + gImpostorProgram.mShaderFiles.clear(); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER)); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER)); + gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gImpostorProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectPreviewProgram.mName = "Object Preview Shader"; + gObjectPreviewProgram.mFeatures.disableTextureIndex = true; + gObjectPreviewProgram.mShaderFiles.clear(); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER)); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER)); + gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; success = make_rigged_variant(gObjectPreviewProgram, gSkinnedObjectPreviewProgram); - success = gObjectPreviewProgram.createShader(NULL, NULL); - gObjectPreviewProgram.mFeatures.hasLighting = true; + success = gObjectPreviewProgram.createShader(NULL, NULL); + gObjectPreviewProgram.mFeatures.hasLighting = true; gSkinnedObjectPreviewProgram.mFeatures.hasLighting = true; - } - - if (success) - { - gPhysicsPreviewProgram.mName = "Preview Physics Shader"; - gPhysicsPreviewProgram.mFeatures.calculatesLighting = false; - gPhysicsPreviewProgram.mFeatures.calculatesAtmospherics = false; - gPhysicsPreviewProgram.mFeatures.hasGamma = false; - gPhysicsPreviewProgram.mFeatures.hasAtmospherics = false; - gPhysicsPreviewProgram.mFeatures.hasLighting = false; - gPhysicsPreviewProgram.mFeatures.mIndexedTextureChannels = 0; - gPhysicsPreviewProgram.mFeatures.disableTextureIndex = true; - gPhysicsPreviewProgram.mShaderFiles.clear(); - gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER)); - gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER)); - gPhysicsPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; - success = gPhysicsPreviewProgram.createShader(NULL, NULL); - gPhysicsPreviewProgram.mFeatures.hasLighting = false; - } + } + + if (success) + { + gPhysicsPreviewProgram.mName = "Preview Physics Shader"; + gPhysicsPreviewProgram.mFeatures.calculatesLighting = false; + gPhysicsPreviewProgram.mFeatures.calculatesAtmospherics = false; + gPhysicsPreviewProgram.mFeatures.hasGamma = false; + gPhysicsPreviewProgram.mFeatures.hasAtmospherics = false; + gPhysicsPreviewProgram.mFeatures.hasLighting = false; + gPhysicsPreviewProgram.mFeatures.mIndexedTextureChannels = 0; + gPhysicsPreviewProgram.mFeatures.disableTextureIndex = true; + gPhysicsPreviewProgram.mShaderFiles.clear(); + gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER)); + gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER)); + gPhysicsPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gPhysicsPreviewProgram.createShader(NULL, NULL); + gPhysicsPreviewProgram.mFeatures.hasLighting = false; + } if (!success) { @@ -2501,234 +2501,234 @@ BOOL LLViewerShaderMgr::loadShadersObject() return FALSE; } - return TRUE; + return TRUE; } BOOL LLViewerShaderMgr::loadShadersAvatar() { LL_PROFILE_ZONE_SCOPED; #if 1 // DEPRECATED -- forward rendering is deprecated - BOOL success = TRUE; - - if (mShaderLevel[SHADER_AVATAR] == 0) - { - gAvatarProgram.unload(); - gAvatarEyeballProgram.unload(); - return TRUE; - } - - if (success) - { - gAvatarProgram.mName = "Avatar Shader"; - gAvatarProgram.mFeatures.hasSkinning = true; - gAvatarProgram.mFeatures.calculatesAtmospherics = true; - gAvatarProgram.mFeatures.calculatesLighting = true; - gAvatarProgram.mFeatures.hasGamma = true; - gAvatarProgram.mFeatures.hasAtmospherics = true; - gAvatarProgram.mFeatures.hasLighting = true; - gAvatarProgram.mFeatures.hasAlphaMask = true; - gAvatarProgram.mFeatures.disableTextureIndex = true; - gAvatarProgram.mShaderFiles.clear(); - gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER)); - gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER)); - gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; - success = gAvatarProgram.createShader(NULL, NULL); - - /// Keep track of avatar levels - if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR]) - { - mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; - } - } - - if (success) - { - gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; - gAvatarEyeballProgram.mFeatures.calculatesLighting = true; - gAvatarEyeballProgram.mFeatures.isSpecular = true; - gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true; - gAvatarEyeballProgram.mFeatures.hasGamma = true; - gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; - gAvatarEyeballProgram.mFeatures.hasLighting = true; - gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; - gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; - gAvatarEyeballProgram.mShaderFiles.clear(); - gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER)); - gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER)); - gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; - success = gAvatarEyeballProgram.createShader(NULL, NULL); - } - - if( !success ) - { - mShaderLevel[SHADER_AVATAR] = 0; - mMaxAvatarShaderLevel = 0; - return FALSE; - } + BOOL success = TRUE; + + if (mShaderLevel[SHADER_AVATAR] == 0) + { + gAvatarProgram.unload(); + gAvatarEyeballProgram.unload(); + return TRUE; + } + + if (success) + { + gAvatarProgram.mName = "Avatar Shader"; + gAvatarProgram.mFeatures.hasSkinning = true; + gAvatarProgram.mFeatures.calculatesAtmospherics = true; + gAvatarProgram.mFeatures.calculatesLighting = true; + gAvatarProgram.mFeatures.hasGamma = true; + gAvatarProgram.mFeatures.hasAtmospherics = true; + gAvatarProgram.mFeatures.hasLighting = true; + gAvatarProgram.mFeatures.hasAlphaMask = true; + gAvatarProgram.mFeatures.disableTextureIndex = true; + gAvatarProgram.mShaderFiles.clear(); + gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER)); + gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER)); + gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; + success = gAvatarProgram.createShader(NULL, NULL); + + /// Keep track of avatar levels + if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR]) + { + mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel; + } + } + + if (success) + { + gAvatarEyeballProgram.mName = "Avatar Eyeball Program"; + gAvatarEyeballProgram.mFeatures.calculatesLighting = true; + gAvatarEyeballProgram.mFeatures.isSpecular = true; + gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true; + gAvatarEyeballProgram.mFeatures.hasGamma = true; + gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; + gAvatarEyeballProgram.mFeatures.hasLighting = true; + gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; + gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; + gAvatarEyeballProgram.mShaderFiles.clear(); + gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER)); + gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER)); + gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR]; + success = gAvatarEyeballProgram.createShader(NULL, NULL); + } + + if( !success ) + { + mShaderLevel[SHADER_AVATAR] = 0; + mMaxAvatarShaderLevel = 0; + return FALSE; + } #endif - return TRUE; + return TRUE; } BOOL LLViewerShaderMgr::loadShadersInterface() { LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; - - if (success) - { - gHighlightProgram.mName = "Highlight Shader"; - gHighlightProgram.mShaderFiles.clear(); - gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER)); - gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); - gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + BOOL success = TRUE; + + if (success) + { + gHighlightProgram.mName = "Highlight Shader"; + gHighlightProgram.mShaderFiles.clear(); + gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER)); + gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); + gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = make_rigged_variant(gHighlightProgram, gSkinnedHighlightProgram); - success = success && gHighlightProgram.createShader(NULL, NULL); - } - - if (success) - { - gHighlightNormalProgram.mName = "Highlight Normals Shader"; - gHighlightNormalProgram.mShaderFiles.clear(); - gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER)); - gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); - gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightNormalProgram.createShader(NULL, NULL); - } - - if (success) - { - gHighlightSpecularProgram.mName = "Highlight Spec Shader"; - gHighlightSpecularProgram.mShaderFiles.clear(); - gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER)); - gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); - gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gHighlightSpecularProgram.createShader(NULL, NULL); - } - - if (success) - { - gUIProgram.mName = "UI Shader"; - gUIProgram.mShaderFiles.clear(); - gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER)); - gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER)); - gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gUIProgram.createShader(NULL, NULL); - } - - if (success) - { - gPathfindingProgram.mName = "Pathfinding Shader"; - gPathfindingProgram.mShaderFiles.clear(); - gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER)); - gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER)); - gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gPathfindingProgram.createShader(NULL, NULL); - } - - if (success) - { - gPathfindingNoNormalsProgram.mName = "PathfindingNoNormals Shader"; - gPathfindingNoNormalsProgram.mShaderFiles.clear(); - gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER)); - gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER)); - gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gPathfindingNoNormalsProgram.createShader(NULL, NULL); - } - - if (success) - { - gGlowCombineProgram.mName = "Glow Combine Shader"; - gGlowCombineProgram.mShaderFiles.clear(); - gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER)); - gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER)); - gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gGlowCombineProgram.createShader(NULL, NULL); - if (success) - { - gGlowCombineProgram.bind(); - gGlowCombineProgram.uniform1i(sGlowMap, 0); - gGlowCombineProgram.uniform1i(sScreenMap, 1); - gGlowCombineProgram.unbind(); - } - } - - if (success) - { - gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader"; - gGlowCombineFXAAProgram.mShaderFiles.clear(); - gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER)); - gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER)); - gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gGlowCombineFXAAProgram.createShader(NULL, NULL); - if (success) - { - gGlowCombineFXAAProgram.bind(); - gGlowCombineFXAAProgram.uniform1i(sGlowMap, 0); - gGlowCombineFXAAProgram.uniform1i(sScreenMap, 1); - gGlowCombineFXAAProgram.unbind(); - } - } + success = success && gHighlightProgram.createShader(NULL, NULL); + } + + if (success) + { + gHighlightNormalProgram.mName = "Highlight Normals Shader"; + gHighlightNormalProgram.mShaderFiles.clear(); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER)); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); + gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gHighlightNormalProgram.createShader(NULL, NULL); + } + + if (success) + { + gHighlightSpecularProgram.mName = "Highlight Spec Shader"; + gHighlightSpecularProgram.mShaderFiles.clear(); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER)); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER)); + gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gHighlightSpecularProgram.createShader(NULL, NULL); + } + + if (success) + { + gUIProgram.mName = "UI Shader"; + gUIProgram.mShaderFiles.clear(); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER)); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER)); + gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gUIProgram.createShader(NULL, NULL); + } + + if (success) + { + gPathfindingProgram.mName = "Pathfinding Shader"; + gPathfindingProgram.mShaderFiles.clear(); + gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER)); + gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER)); + gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gPathfindingProgram.createShader(NULL, NULL); + } + + if (success) + { + gPathfindingNoNormalsProgram.mName = "PathfindingNoNormals Shader"; + gPathfindingNoNormalsProgram.mShaderFiles.clear(); + gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER)); + gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER)); + gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gPathfindingNoNormalsProgram.createShader(NULL, NULL); + } + + if (success) + { + gGlowCombineProgram.mName = "Glow Combine Shader"; + gGlowCombineProgram.mShaderFiles.clear(); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER)); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER)); + gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineProgram.bind(); + gGlowCombineProgram.uniform1i(sGlowMap, 0); + gGlowCombineProgram.uniform1i(sScreenMap, 1); + gGlowCombineProgram.unbind(); + } + } + + if (success) + { + gGlowCombineFXAAProgram.mName = "Glow CombineFXAA Shader"; + gGlowCombineFXAAProgram.mShaderFiles.clear(); + gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER)); + gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER)); + gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineFXAAProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineFXAAProgram.bind(); + gGlowCombineFXAAProgram.uniform1i(sGlowMap, 0); + gGlowCombineFXAAProgram.uniform1i(sScreenMap, 1); + gGlowCombineFXAAProgram.unbind(); + } + } #ifdef LL_WINDOWS - if (success) - { - gTwoTextureCompareProgram.mName = "Two Texture Compare Shader"; - gTwoTextureCompareProgram.mShaderFiles.clear(); - gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER)); - gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER)); - gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gTwoTextureCompareProgram.createShader(NULL, NULL); - if (success) - { - gTwoTextureCompareProgram.bind(); - gTwoTextureCompareProgram.uniform1i(sTex0, 0); - gTwoTextureCompareProgram.uniform1i(sTex1, 1); - gTwoTextureCompareProgram.uniform1i(sDitherTex, 2); - } - } - - if (success) - { - gOneTextureFilterProgram.mName = "One Texture Filter Shader"; - gOneTextureFilterProgram.mShaderFiles.clear(); - gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER)); - gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER)); - gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOneTextureFilterProgram.createShader(NULL, NULL); - if (success) - { - gOneTextureFilterProgram.bind(); - gOneTextureFilterProgram.uniform1i(sTex0, 0); - } - } + if (success) + { + gTwoTextureCompareProgram.mName = "Two Texture Compare Shader"; + gTwoTextureCompareProgram.mShaderFiles.clear(); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER)); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER)); + gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureCompareProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureCompareProgram.bind(); + gTwoTextureCompareProgram.uniform1i(sTex0, 0); + gTwoTextureCompareProgram.uniform1i(sTex1, 1); + gTwoTextureCompareProgram.uniform1i(sDitherTex, 2); + } + } + + if (success) + { + gOneTextureFilterProgram.mName = "One Texture Filter Shader"; + gOneTextureFilterProgram.mShaderFiles.clear(); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER)); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER)); + gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOneTextureFilterProgram.createShader(NULL, NULL); + if (success) + { + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1i(sTex0, 0); + } + } #endif - if (success) - { - gSolidColorProgram.mName = "Solid Color Shader"; - gSolidColorProgram.mShaderFiles.clear(); - gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER)); - gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER)); - gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gSolidColorProgram.createShader(NULL, NULL); - if (success) - { - gSolidColorProgram.bind(); - gSolidColorProgram.uniform1i(sTex0, 0); - gSolidColorProgram.unbind(); - } - } - - if (success) - { - gOcclusionProgram.mName = "Occlusion Shader"; - gOcclusionProgram.mShaderFiles.clear(); - gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER)); - gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER)); - gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + if (success) + { + gSolidColorProgram.mName = "Solid Color Shader"; + gSolidColorProgram.mShaderFiles.clear(); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER)); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER)); + gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gSolidColorProgram.createShader(NULL, NULL); + if (success) + { + gSolidColorProgram.bind(); + gSolidColorProgram.uniform1i(sTex0, 0); + gSolidColorProgram.unbind(); + } + } + + if (success) + { + gOcclusionProgram.mName = "Occlusion Shader"; + gOcclusionProgram.mShaderFiles.clear(); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER)); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER)); + gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; gOcclusionProgram.mRiggedVariant = &gSkinnedOcclusionProgram; - success = gOcclusionProgram.createShader(NULL, NULL); - } + success = gOcclusionProgram.createShader(NULL, NULL); + } if (success) { @@ -2741,30 +2741,30 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gSkinnedOcclusionProgram.createShader(NULL, NULL); } - if (success) - { - gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; - gOcclusionCubeProgram.mShaderFiles.clear(); - gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER)); - gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER)); - gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gOcclusionCubeProgram.createShader(NULL, NULL); - } - - if (success) - { - gDebugProgram.mName = "Debug Shader"; - gDebugProgram.mShaderFiles.clear(); - gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER)); - gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER)); + if (success) + { + gOcclusionCubeProgram.mName = "Occlusion Cube Shader"; + gOcclusionCubeProgram.mShaderFiles.clear(); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER)); + gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER)); + gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gOcclusionCubeProgram.createShader(NULL, NULL); + } + + if (success) + { + gDebugProgram.mName = "Debug Shader"; + gDebugProgram.mShaderFiles.clear(); + gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER)); + gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER)); gDebugProgram.mRiggedVariant = &gSkinnedDebugProgram; - gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = make_rigged_variant(gDebugProgram, gSkinnedDebugProgram); - success = success && gDebugProgram.createShader(NULL, NULL); - } + success = success && gDebugProgram.createShader(NULL, NULL); + } - if (success) - { + if (success) + { for (S32 variant = 0; variant < NORMAL_DEBUG_SHADER_COUNT; ++variant) { LLGLSLShader& shader = gNormalDebugProgram[variant]; @@ -2788,27 +2788,27 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = make_rigged_variant(shader, skinned_shader); success = success && shader.createShader(NULL, NULL); } - } - - if (success) - { - gClipProgram.mName = "Clip Shader"; - gClipProgram.mShaderFiles.clear(); - gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER)); - gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER)); - gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gClipProgram.createShader(NULL, NULL); - } - - if (success) - { - gBenchmarkProgram.mName = "Benchmark Shader"; - gBenchmarkProgram.mShaderFiles.clear(); - gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER)); - gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER)); - gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gBenchmarkProgram.createShader(NULL, NULL); - } + } + + if (success) + { + gClipProgram.mName = "Clip Shader"; + gClipProgram.mShaderFiles.clear(); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER)); + gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER)); + gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gClipProgram.createShader(NULL, NULL); + } + + if (success) + { + gBenchmarkProgram.mName = "Benchmark Shader"; + gBenchmarkProgram.mShaderFiles.clear(); + gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER)); + gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER)); + gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gBenchmarkProgram.createShader(NULL, NULL); + } if (success) { @@ -2847,16 +2847,16 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gCopyDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; success = gCopyDepthProgram.createShader(NULL, NULL); } - - if (success) - { - gAlphaMaskProgram.mName = "Alpha Mask Shader"; - gAlphaMaskProgram.mShaderFiles.clear(); - gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER)); - gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER)); - gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; - success = gAlphaMaskProgram.createShader(NULL, NULL); - } + + if (success) + { + gAlphaMaskProgram.mName = "Alpha Mask Shader"; + gAlphaMaskProgram.mShaderFiles.clear(); + gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER)); + gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER)); + gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE]; + success = gAlphaMaskProgram.createShader(NULL, NULL); + } if (success) { @@ -2896,7 +2896,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface() gRadianceGenProgram.addPermutation("PROBE_FILTER_SAMPLES", "32"); success = gRadianceGenProgram.createShader(NULL, NULL); } - + if (success && gGLManager.mHasCubeMapArray) { gHeroRadianceGenProgram.mName = "Hero Radiance Gen Shader"; @@ -2919,19 +2919,19 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gIrradianceGenProgram.createShader(NULL, NULL); } - if( !success ) - { - mShaderLevel[SHADER_INTERFACE] = 0; - return FALSE; - } - - return TRUE; + if( !success ) + { + mShaderLevel[SHADER_INTERFACE] = 0; + return FALSE; + } + + return TRUE; } std::string LLViewerShaderMgr::getShaderDirPrefix(void) { - return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); + return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); } void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) @@ -2941,11 +2941,11 @@ void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) LLViewerShaderMgr::shader_iter LLViewerShaderMgr::beginShaders() const { - return mShaderList.begin(); + return mShaderList.begin(); } LLViewerShaderMgr::shader_iter LLViewerShaderMgr::endShaders() const { - return mShaderList.end(); + return mShaderList.end(); } diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index c51f583ebc..dbac352b92 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -1,25 +1,25 @@ -/** +/** * @file llviewershadermgr.h * @brief Viewer Shader Manager * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -35,251 +35,251 @@ class LLViewerShaderMgr: public LLShaderMgr { public: - static BOOL sInitialized; - static bool sSkipReload; + static BOOL sInitialized; + static bool sSkipReload; - LLViewerShaderMgr(); - /* virtual */ ~LLViewerShaderMgr(); + LLViewerShaderMgr(); + /* virtual */ ~LLViewerShaderMgr(); // Add shaders to mShaderList for later uniform propagation // Will assert on redundant shader entries in debug builds void finalizeShaderList(); - // singleton pattern implementation - static LLViewerShaderMgr * instance(); - static void releaseInstance(); + // singleton pattern implementation + static LLViewerShaderMgr * instance(); + static void releaseInstance(); - void initAttribsAndUniforms(void); - void setShaders(); - void unloadShaders(); + void initAttribsAndUniforms(void); + void setShaders(); + void unloadShaders(); S32 getShaderLevel(S32 type); // loadBasicShaders in case of a failure returns // name of a file error happened at, otherwise // returns an empty string std::string loadBasicShaders(); - BOOL loadShadersEffects(); - BOOL loadShadersDeferred(); - BOOL loadShadersObject(); - BOOL loadShadersAvatar(); - BOOL loadShadersWater(); - BOOL loadShadersInterface(); - - std::vector mShaderLevel; - S32 mMaxAvatarShaderLevel; - - enum EShaderClass - { - SHADER_LIGHTING, - SHADER_OBJECT, - SHADER_AVATAR, - SHADER_ENVIRONMENT, - SHADER_INTERFACE, - SHADER_EFFECT, - SHADER_WINDLIGHT, - SHADER_WATER, - SHADER_DEFERRED, - SHADER_COUNT - }; - - // simple model of forward iterator - // http://www.sgi.com/tech/stl/ForwardIterator.html - class shader_iter - { - private: - friend bool operator == (shader_iter const & a, shader_iter const & b); - friend bool operator != (shader_iter const & a, shader_iter const & b); - - typedef std::vector::const_iterator base_iter_t; - public: - shader_iter() - { - } - - shader_iter(base_iter_t iter) : mIter(iter) - { - } - - LLGLSLShader & operator * () const - { - return **mIter; - } - - LLGLSLShader * operator -> () const - { - return *mIter; - } - - shader_iter & operator++ () - { - ++mIter; - return *this; - } - - shader_iter operator++ (int) - { - return mIter++; - } - - private: - base_iter_t mIter; - }; - - shader_iter beginShaders() const; - shader_iter endShaders() const; - - /* virtual */ std::string getShaderDirPrefix(void); - - /* virtual */ void updateShaderUniforms(LLGLSLShader * shader); + BOOL loadShadersEffects(); + BOOL loadShadersDeferred(); + BOOL loadShadersObject(); + BOOL loadShadersAvatar(); + BOOL loadShadersWater(); + BOOL loadShadersInterface(); + + std::vector mShaderLevel; + S32 mMaxAvatarShaderLevel; + + enum EShaderClass + { + SHADER_LIGHTING, + SHADER_OBJECT, + SHADER_AVATAR, + SHADER_ENVIRONMENT, + SHADER_INTERFACE, + SHADER_EFFECT, + SHADER_WINDLIGHT, + SHADER_WATER, + SHADER_DEFERRED, + SHADER_COUNT + }; + + // simple model of forward iterator + // http://www.sgi.com/tech/stl/ForwardIterator.html + class shader_iter + { + private: + friend bool operator == (shader_iter const & a, shader_iter const & b); + friend bool operator != (shader_iter const & a, shader_iter const & b); + + typedef std::vector::const_iterator base_iter_t; + public: + shader_iter() + { + } + + shader_iter(base_iter_t iter) : mIter(iter) + { + } + + LLGLSLShader & operator * () const + { + return **mIter; + } + + LLGLSLShader * operator -> () const + { + return *mIter; + } + + shader_iter & operator++ () + { + ++mIter; + return *this; + } + + shader_iter operator++ (int) + { + return mIter++; + } + + private: + base_iter_t mIter; + }; + + shader_iter beginShaders() const; + shader_iter endShaders() const; + + /* virtual */ std::string getShaderDirPrefix(void); + + /* virtual */ void updateShaderUniforms(LLGLSLShader * shader); private: - // the list of shaders we need to propagate parameters to. - std::vector mShaderList; + // the list of shaders we need to propagate parameters to. + std::vector mShaderList; }; //LLViewerShaderMgr inline bool operator == (LLViewerShaderMgr::shader_iter const & a, LLViewerShaderMgr::shader_iter const & b) { - return a.mIter == b.mIter; + return a.mIter == b.mIter; } inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShaderMgr::shader_iter const & b) { - return a.mIter != b.mIter; + return a.mIter != b.mIter; } -extern LLVector4 gShinyOrigin; +extern LLVector4 gShinyOrigin; //utility shaders -extern LLGLSLShader gOcclusionProgram; -extern LLGLSLShader gOcclusionCubeProgram; -extern LLGLSLShader gGlowCombineProgram; -extern LLGLSLShader gReflectionMipProgram; +extern LLGLSLShader gOcclusionProgram; +extern LLGLSLShader gOcclusionCubeProgram; +extern LLGLSLShader gGlowCombineProgram; +extern LLGLSLShader gReflectionMipProgram; extern LLGLSLShader gGaussianProgram; extern LLGLSLShader gRadianceGenProgram; extern LLGLSLShader gHeroRadianceGenProgram; extern LLGLSLShader gIrradianceGenProgram; -extern LLGLSLShader gGlowCombineFXAAProgram; -extern LLGLSLShader gDebugProgram; +extern LLGLSLShader gGlowCombineFXAAProgram; +extern LLGLSLShader gDebugProgram; enum NormalDebugShaderVariant : S32 { NORMAL_DEBUG_SHADER_DEFAULT, NORMAL_DEBUG_SHADER_WITH_TANGENTS, NORMAL_DEBUG_SHADER_COUNT }; -extern LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; -extern LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; -extern LLGLSLShader gClipProgram; -extern LLGLSLShader gBenchmarkProgram; +extern LLGLSLShader gNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +extern LLGLSLShader gSkinnedNormalDebugProgram[NORMAL_DEBUG_SHADER_COUNT]; +extern LLGLSLShader gClipProgram; +extern LLGLSLShader gBenchmarkProgram; extern LLGLSLShader gReflectionProbeDisplayProgram; extern LLGLSLShader gCopyProgram; extern LLGLSLShader gCopyDepthProgram; //output tex0[tc0] - tex1[tc1] -extern LLGLSLShader gTwoTextureCompareProgram; +extern LLGLSLShader gTwoTextureCompareProgram; //discard some fragments based on user-set color tolerance -extern LLGLSLShader gOneTextureFilterProgram; - +extern LLGLSLShader gOneTextureFilterProgram; + //object shaders -extern LLGLSLShader gObjectPreviewProgram; +extern LLGLSLShader gObjectPreviewProgram; extern LLGLSLShader gPhysicsPreviewProgram; -extern LLGLSLShader gObjectBumpProgram; +extern LLGLSLShader gObjectBumpProgram; extern LLGLSLShader gSkinnedObjectBumpProgram; -extern LLGLSLShader gObjectAlphaMaskNoColorProgram; +extern LLGLSLShader gObjectAlphaMaskNoColorProgram; //environment shaders -extern LLGLSLShader gWaterProgram; -extern LLGLSLShader gWaterEdgeProgram; -extern LLGLSLShader gUnderWaterProgram; -extern LLGLSLShader gGlowProgram; -extern LLGLSLShader gGlowExtractProgram; +extern LLGLSLShader gWaterProgram; +extern LLGLSLShader gWaterEdgeProgram; +extern LLGLSLShader gUnderWaterProgram; +extern LLGLSLShader gGlowProgram; +extern LLGLSLShader gGlowExtractProgram; //interface shaders -extern LLGLSLShader gHighlightProgram; -extern LLGLSLShader gHighlightNormalProgram; -extern LLGLSLShader gHighlightSpecularProgram; +extern LLGLSLShader gHighlightProgram; +extern LLGLSLShader gHighlightNormalProgram; +extern LLGLSLShader gHighlightSpecularProgram; -extern LLGLSLShader gDeferredHighlightProgram; +extern LLGLSLShader gDeferredHighlightProgram; -extern LLGLSLShader gPathfindingProgram; -extern LLGLSLShader gPathfindingNoNormalsProgram; +extern LLGLSLShader gPathfindingProgram; +extern LLGLSLShader gPathfindingNoNormalsProgram; // avatar shader handles -extern LLGLSLShader gAvatarProgram; -extern LLGLSLShader gAvatarEyeballProgram; -extern LLGLSLShader gImpostorProgram; +extern LLGLSLShader gAvatarProgram; +extern LLGLSLShader gAvatarEyeballProgram; +extern LLGLSLShader gImpostorProgram; // Post Process Shaders extern LLGLSLShader gPostScreenSpaceReflectionProgram; // Deferred rendering shaders -extern LLGLSLShader gDeferredImpostorProgram; -extern LLGLSLShader gDeferredDiffuseProgram; -extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; -extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; -extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; -extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; -extern LLGLSLShader gDeferredBumpProgram; -extern LLGLSLShader gDeferredTerrainProgram; -extern LLGLSLShader gDeferredTreeProgram; -extern LLGLSLShader gDeferredTreeShadowProgram; -extern LLGLSLShader gDeferredLightProgram; -extern LLGLSLShader gDeferredMultiLightProgram[LL_DEFERRED_MULTI_LIGHT_COUNT]; -extern LLGLSLShader gDeferredSpotLightProgram; -extern LLGLSLShader gDeferredMultiSpotLightProgram; -extern LLGLSLShader gDeferredSunProgram; +extern LLGLSLShader gDeferredImpostorProgram; +extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; +extern LLGLSLShader gDeferredBumpProgram; +extern LLGLSLShader gDeferredTerrainProgram; +extern LLGLSLShader gDeferredTreeProgram; +extern LLGLSLShader gDeferredTreeShadowProgram; +extern LLGLSLShader gDeferredLightProgram; +extern LLGLSLShader gDeferredMultiLightProgram[LL_DEFERRED_MULTI_LIGHT_COUNT]; +extern LLGLSLShader gDeferredSpotLightProgram; +extern LLGLSLShader gDeferredMultiSpotLightProgram; +extern LLGLSLShader gDeferredSunProgram; extern LLGLSLShader gHazeProgram; extern LLGLSLShader gHazeWaterProgram; -extern LLGLSLShader gDeferredBlurLightProgram; -extern LLGLSLShader gDeferredAvatarProgram; -extern LLGLSLShader gDeferredSoftenProgram; -extern LLGLSLShader gDeferredShadowProgram; -extern LLGLSLShader gDeferredShadowCubeProgram; -extern LLGLSLShader gDeferredShadowAlphaMaskProgram; +extern LLGLSLShader gDeferredBlurLightProgram; +extern LLGLSLShader gDeferredAvatarProgram; +extern LLGLSLShader gDeferredSoftenProgram; +extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredShadowCubeProgram; +extern LLGLSLShader gDeferredShadowAlphaMaskProgram; extern LLGLSLShader gDeferredShadowGLTFAlphaMaskProgram; extern LLGLSLShader gDeferredShadowGLTFAlphaBlendProgram; -extern LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; -extern LLGLSLShader gDeferredPostProgram; -extern LLGLSLShader gDeferredCoFProgram; -extern LLGLSLShader gDeferredDoFCombineProgram; -extern LLGLSLShader gFXAAProgram; -extern LLGLSLShader gDeferredPostNoDoFProgram; -extern LLGLSLShader gDeferredPostGammaCorrectProgram; +extern LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram; +extern LLGLSLShader gDeferredPostProgram; +extern LLGLSLShader gDeferredCoFProgram; +extern LLGLSLShader gDeferredDoFCombineProgram; +extern LLGLSLShader gFXAAProgram; +extern LLGLSLShader gDeferredPostNoDoFProgram; +extern LLGLSLShader gDeferredPostGammaCorrectProgram; extern LLGLSLShader gNoPostGammaCorrectProgram; extern LLGLSLShader gLegacyPostGammaCorrectProgram; -extern LLGLSLShader gExposureProgram; -extern LLGLSLShader gExposureProgramNoFade; -extern LLGLSLShader gLuminanceProgram; -extern LLGLSLShader gDeferredAvatarShadowProgram; -extern LLGLSLShader gDeferredAvatarAlphaShadowProgram; -extern LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; -extern LLGLSLShader gDeferredAlphaProgram; -extern LLGLSLShader gHUDAlphaProgram; -extern LLGLSLShader gDeferredAlphaImpostorProgram; -extern LLGLSLShader gDeferredFullbrightProgram; -extern LLGLSLShader gHUDFullbrightProgram; -extern LLGLSLShader gDeferredFullbrightAlphaMaskProgram; -extern LLGLSLShader gHUDFullbrightAlphaMaskProgram; -extern LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram; -extern LLGLSLShader gHUDFullbrightAlphaMaskAlphaProgram; -extern LLGLSLShader gDeferredEmissiveProgram; -extern LLGLSLShader gDeferredAvatarEyesProgram; -extern LLGLSLShader gDeferredAvatarAlphaProgram; +extern LLGLSLShader gExposureProgram; +extern LLGLSLShader gExposureProgramNoFade; +extern LLGLSLShader gLuminanceProgram; +extern LLGLSLShader gDeferredAvatarShadowProgram; +extern LLGLSLShader gDeferredAvatarAlphaShadowProgram; +extern LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram; +extern LLGLSLShader gDeferredAlphaProgram; +extern LLGLSLShader gHUDAlphaProgram; +extern LLGLSLShader gDeferredAlphaImpostorProgram; +extern LLGLSLShader gDeferredFullbrightProgram; +extern LLGLSLShader gHUDFullbrightProgram; +extern LLGLSLShader gDeferredFullbrightAlphaMaskProgram; +extern LLGLSLShader gHUDFullbrightAlphaMaskProgram; +extern LLGLSLShader gDeferredFullbrightAlphaMaskAlphaProgram; +extern LLGLSLShader gHUDFullbrightAlphaMaskAlphaProgram; +extern LLGLSLShader gDeferredEmissiveProgram; +extern LLGLSLShader gDeferredAvatarEyesProgram; +extern LLGLSLShader gDeferredAvatarAlphaProgram; extern LLGLSLShader gEnvironmentMapProgram; -extern LLGLSLShader gDeferredWLSkyProgram; -extern LLGLSLShader gDeferredWLCloudProgram; -extern LLGLSLShader gDeferredWLSunProgram; -extern LLGLSLShader gDeferredWLMoonProgram; -extern LLGLSLShader gDeferredStarProgram; -extern LLGLSLShader gDeferredFullbrightShinyProgram; +extern LLGLSLShader gDeferredWLSkyProgram; +extern LLGLSLShader gDeferredWLCloudProgram; +extern LLGLSLShader gDeferredWLSunProgram; +extern LLGLSLShader gDeferredWLMoonProgram; +extern LLGLSLShader gDeferredStarProgram; +extern LLGLSLShader gDeferredFullbrightShinyProgram; extern LLGLSLShader gHUDFullbrightShinyProgram; -extern LLGLSLShader gNormalMapGenProgram; +extern LLGLSLShader gNormalMapGenProgram; extern LLGLSLShader gDeferredGenBrdfLutProgram; -extern LLGLSLShader gDeferredBufferVisualProgram; +extern LLGLSLShader gDeferredBufferVisualProgram; // Deferred materials shaders -extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; +extern LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2]; extern LLGLSLShader gHUDPBROpaqueProgram; extern LLGLSLShader gPBRGlowProgram; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 6b496cf658..9aee1c0caf 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewertexture.cpp * @brief Object which handles a received image (and associated texture(s)) * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -115,24 +115,24 @@ const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_S //---------------------------------------------------------------------------------------------- LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb, - S32 discard_level, - BOOL need_imageraw, // Needs image raw for the callback - void* userdata, - LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, - LLViewerFetchedTexture* target, - BOOL pause) - : mCallback(cb), - mLastUsedDiscard(MAX_DISCARD_LEVEL+1), - mDesiredDiscard(discard_level), - mNeedsImageRaw(need_imageraw), - mUserData(userdata), - mSourceCallbackList(src_callback_list), - mPaused(pause) -{ - if(mSourceCallbackList) - { + S32 discard_level, + BOOL need_imageraw, // Needs image raw for the callback + void* userdata, + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, + LLViewerFetchedTexture* target, + BOOL pause) + : mCallback(cb), + mLastUsedDiscard(MAX_DISCARD_LEVEL+1), + mDesiredDiscard(discard_level), + mNeedsImageRaw(need_imageraw), + mUserData(userdata), + mSourceCallbackList(src_callback_list), + mPaused(pause) +{ + if(mSourceCallbackList) + { mSourceCallbackList->insert(LLTextureKey(target->getID(), (ETexListType)target->getTextureListType())); - } + } } LLLoadedCallbackEntry::~LLLoadedCallbackEntry() @@ -141,34 +141,34 @@ LLLoadedCallbackEntry::~LLLoadedCallbackEntry() void LLLoadedCallbackEntry::removeTexture(LLViewerFetchedTexture* tex) { - if(mSourceCallbackList) - { - mSourceCallbackList->erase(LLTextureKey(tex->getID(), (ETexListType)tex->getTextureListType())); - } + if(mSourceCallbackList) + { + mSourceCallbackList->erase(LLTextureKey(tex->getID(), (ETexListType)tex->getTextureListType())); + } } -//static +//static void LLLoadedCallbackEntry::cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) { - //clear texture callbacks. - if(callback_list && !callback_list->empty()) - { - for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = callback_list->begin(); - iter != callback_list->end(); ++iter) - { - LLViewerFetchedTexture* tex = gTextureList.findImage(*iter); - if(tex) - { - tex->deleteCallbackEntry(callback_list); - } - } - callback_list->clear(); - } + //clear texture callbacks. + if(callback_list && !callback_list->empty()) + { + for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = callback_list->begin(); + iter != callback_list->end(); ++iter) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter); + if(tex) + { + tex->deleteCallbackEntry(callback_list); + } + } + callback_list->clear(); + } } LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image) { - return new LLViewerMediaTexture(media_id, usemipmaps, gl_image); + return new LLViewerMediaTexture(media_id, usemipmaps, gl_image); } void LLViewerTextureManager::findFetchedTextures(const LLUUID& id, std::vector &output) @@ -209,78 +209,78 @@ LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id) { - return LLViewerMediaTexture::findMediaTexture(media_id); + return LLViewerMediaTexture::findMediaTexture(media_id); } -LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) +LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) { - LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id); - if(!tex) - { - tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image); - } + LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id); + if(!tex) + { + tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image); + } - tex->initVirtualSize(); + tex->initVirtualSize(); - return tex; + return tex; } LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error) { - if(!tex) - { - return NULL; - } + if(!tex) + { + return NULL; + } - S8 type = tex->getType(); - if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE) - { - return static_cast(tex); - } + S8 type = tex->getType(); + if(type == LLViewerTexture::FETCHED_TEXTURE || type == LLViewerTexture::LOD_TEXTURE) + { + return static_cast(tex); + } - if(report_error) - { - LL_ERRS() << "not a fetched texture type: " << type << LL_ENDL; - } + if(report_error) + { + LL_ERRS() << "not a fetched texture type: " << type << LL_ENDL; + } - return NULL; + return NULL; } LLPointer LLViewerTextureManager::getLocalTexture(BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(usemipmaps); - if(generate_gl_tex) - { - tex->generateGLTexture(); - tex->setCategory(LLGLTexture::LOCAL); - } - return tex; + LLPointer tex = new LLViewerTexture(usemipmaps); + if(generate_gl_tex) + { + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); + } + return tex; } -LLPointer LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex) +LLPointer LLViewerTextureManager::getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(id, usemipmaps); - if(generate_gl_tex) - { - tex->generateGLTexture(); - tex->setCategory(LLGLTexture::LOCAL); - } - return tex; + LLPointer tex = new LLViewerTexture(id, usemipmaps); + if(generate_gl_tex) + { + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); + } + return tex; } -LLPointer LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLPointer LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { - LLPointer tex = new LLViewerTexture(raw, usemipmaps); - tex->setCategory(LLGLTexture::LOCAL); - return tex; + LLPointer tex = new LLViewerTexture(raw, usemipmaps); + tex->setCategory(LLGLTexture::LOCAL); + return tex; } -LLPointer LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) +LLPointer LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) { - LLPointer tex = new LLViewerTexture(width, height, components, usemipmaps); - if(generate_gl_tex) - { - tex->generateGLTexture(); - tex->setCategory(LLGLTexture::LOCAL); - } - return tex; + LLPointer tex = new LLViewerTexture(width, height, components, usemipmaps); + if(generate_gl_tex) + { + tex->generateGLTexture(); + tex->setCategory(LLGLTexture::LOCAL); + } + return tex; } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps) @@ -291,170 +291,170 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(const LLImageR } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( - const LLUUID &image_id, - FTType f_type, - BOOL usemipmaps, - LLViewerTexture::EBoostLevel boost_priority, - S8 texture_type, - LLGLint internal_format, - LLGLenum primary_format, - LLHost request_from_host) -{ - return gTextureList.getImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host); -} - + const LLUUID &image_id, + FTType f_type, + BOOL usemipmaps, + LLViewerTexture::EBoostLevel boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + LLHost request_from_host) +{ + return gTextureList.getImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host); +} + LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( - const std::string& filename, - FTType f_type, - BOOL usemipmaps, - LLViewerTexture::EBoostLevel boost_priority, - S8 texture_type, - LLGLint internal_format, - LLGLenum primary_format, - const LLUUID& force_id) + const std::string& filename, + FTType f_type, + BOOL usemipmaps, + LLViewerTexture::EBoostLevel boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id) { - return gTextureList.getImageFromFile(filename, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + return gTextureList.getImageFromFile(filename, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } -//static +//static LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, - FTType f_type, - BOOL usemipmaps, - LLViewerTexture::EBoostLevel boost_priority, - S8 texture_type, - LLGLint internal_format, - LLGLenum primary_format, - const LLUUID& force_id - ) + FTType f_type, + BOOL usemipmaps, + LLViewerTexture::EBoostLevel boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id + ) { - return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) { - return gTextureList.getImageFromHost(image_id, f_type, host); + return gTextureList.getImageFromHost(image_id, f_type, host); } // Create a bridge to the viewer texture manager. class LLViewerTextureManagerBridge : public LLTextureManagerBridge { - /*virtual*/ LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) - { - return LLViewerTextureManager::getLocalTexture(usemipmaps, generate_gl_tex); - } + /*virtual*/ LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(usemipmaps, generate_gl_tex); + } - /*virtual*/ LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) - { - return LLViewerTextureManager::getLocalTexture(width, height, components, usemipmaps, generate_gl_tex); - } + /*virtual*/ LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) + { + return LLViewerTextureManager::getLocalTexture(width, height, components, usemipmaps, generate_gl_tex); + } - /*virtual*/ LLGLTexture* getFetchedTexture(const LLUUID &image_id) - { - return LLViewerTextureManager::getFetchedTexture(image_id); - } + /*virtual*/ LLGLTexture* getFetchedTexture(const LLUUID &image_id) + { + return LLViewerTextureManager::getFetchedTexture(image_id); + } }; void LLViewerTextureManager::init() { - { - LLPointer raw = new LLImageRaw(1,1,3); - raw->clear(0x77, 0x77, 0x77, 0xFF); - LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE); - } + { + LLPointer raw = new LLImageRaw(1,1,3); + raw->clear(0x77, 0x77, 0x77, 0xFF); + LLViewerTexture::sNullImagep = LLViewerTextureManager::getLocalTexture(raw.get(), TRUE); + } + + const S32 dim = 128; + LLPointer image_raw = new LLImageRaw(dim,dim,3); + U8* data = image_raw->getData(); - const S32 dim = 128; - LLPointer image_raw = new LLImageRaw(dim,dim,3); - U8* data = image_raw->getData(); - - memset(data, 0, dim * dim * 3); - LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); + memset(data, 0, dim * dim * 3); + LLViewerTexture::sBlackImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); #if 1 - LLPointer imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); - LLViewerFetchedTexture::sDefaultImagep = imagep; - - for (S32 i = 0; i imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT); + LLViewerFetchedTexture::sDefaultImagep = imagep; + + for (S32 i = 0; i=(dim-border) || j>=(dim-border)) - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0xff; - } - else + const S32 border = 2; + if (i=(dim-border) || j>=(dim-border)) + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0xff; + } + else #endif - { - *data++ = 0x7f; - *data++ = 0x7f; - *data++ = 0x7f; - } - } - } - imagep->createGLTexture(0, image_raw); - //cache the raw image - imagep->setCachedRawImage(0, image_raw); - image_raw = NULL; + { + *data++ = 0x7f; + *data++ = 0x7f; + *data++ = 0x7f; + } + } + } + imagep->createGLTexture(0, image_raw); + //cache the raw image + imagep->setCachedRawImage(0, image_raw); + image_raw = NULL; #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); #endif - LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); - LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER); - - image_raw = new LLImageRaw(32,32,3); - data = image_raw->getData(); - - for (S32 i = 0; i < (32*32*3); i+=3) - { - S32 x = (i % (32*3)) / (3*16); - S32 y = i / (32*3*16); - U8 color = ((x + y) % 2) * 255; - data[i] = color; - data[i+1] = color; - data[i+2] = color; - } - - LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); - - LLViewerTexture::initClass(); - - // Create a texture manager bridge. - gTextureManagerBridgep = new LLViewerTextureManagerBridge; - - if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) - { - sTesterp = new LLTexturePipelineTester(); - if (!sTesterp->isValid()) - { - delete sTesterp; - sTesterp = NULL; - } - } + LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER); + + image_raw = new LLImageRaw(32,32,3); + data = image_raw->getData(); + + for (S32 i = 0; i < (32*32*3); i+=3) + { + S32 x = (i % (32*3)) / (3*16); + S32 y = i / (32*3*16); + U8 color = ((x + y) % 2) * 255; + data[i] = color; + data[i+1] = color; + data[i+2] = color; + } + + LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); + + LLViewerTexture::initClass(); + + // Create a texture manager bridge. + gTextureManagerBridgep = new LLViewerTextureManagerBridge; + + if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) + { + sTesterp = new LLTexturePipelineTester(); + if (!sTesterp->isValid()) + { + delete sTesterp; + sTesterp = NULL; + } + } } void LLViewerTextureManager::cleanup() { - stop_glerror(); + stop_glerror(); - delete gTextureManagerBridgep; - LLImageGL::sDefaultGLTexture = NULL; - LLViewerTexture::sNullImagep = NULL; - LLViewerTexture::sBlackImagep = NULL; - LLViewerTexture::sCheckerBoardImagep = NULL; - LLViewerFetchedTexture::sDefaultImagep = NULL; - LLViewerFetchedTexture::sSmokeImagep = NULL; - LLViewerFetchedTexture::sMissingAssetImagep = NULL; - LLTexUnit::sWhiteTexture = 0; - LLViewerFetchedTexture::sWhiteImagep = NULL; - - LLViewerFetchedTexture::sFlatNormalImagep = NULL; - LLViewerFetchedTexture::sDefaultIrradiancePBRp = NULL; + delete gTextureManagerBridgep; + LLImageGL::sDefaultGLTexture = NULL; + LLViewerTexture::sNullImagep = NULL; + LLViewerTexture::sBlackImagep = NULL; + LLViewerTexture::sCheckerBoardImagep = NULL; + LLViewerFetchedTexture::sDefaultImagep = NULL; + LLViewerFetchedTexture::sSmokeImagep = NULL; + LLViewerFetchedTexture::sMissingAssetImagep = NULL; + LLTexUnit::sWhiteTexture = 0; + LLViewerFetchedTexture::sWhiteImagep = NULL; - LLViewerMediaTexture::cleanUpClass(); + LLViewerFetchedTexture::sFlatNormalImagep = NULL; + LLViewerFetchedTexture::sDefaultIrradiancePBRp = NULL; + + LLViewerMediaTexture::cleanUpClass(); } //---------------------------------------------------------------------------------------------- @@ -464,7 +464,7 @@ void LLViewerTextureManager::cleanup() // static void LLViewerTexture::initClass() { - LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); + LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture(); } // tuning params @@ -473,7 +473,7 @@ const F32 GPU_MEMORY_CHECK_WAIT_TIME = 1.0f; F32 texmem_lower_bound_scale = 0.85f; F32 texmem_middle_bound_scale = 0.925f; -//static +//static bool LLViewerTexture::isMemoryForTextureLow() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -498,7 +498,7 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p static S32Megabytes gpu_res = S32Megabytes(S32_MAX); static S32Megabytes physical_res = S32Megabytes(S32_MAX); - + if (timer.getElapsedTimeF32() < GPU_MEMORY_CHECK_WAIT_TIME) //call this once per second. { gpu = gpu_res; @@ -509,7 +509,7 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p { gpu_res = (S32Megabytes)gViewerWindow->getWindow()->getAvailableVRAMMegabytes(); - + //check main memory, only works for windows and macos. LLMemory::updateMemoryInfo(); physical_res = LLMemory::getAvailableMemKB(); @@ -523,25 +523,25 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p void LLViewerTexture::updateClass() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - sCurrentTime = gFrameTimeSeconds; + sCurrentTime = gFrameTimeSeconds; - LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); - if (tester) - { - tester->update(); - } + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); + if (tester) + { + tester->update(); + } - LLViewerMediaTexture::updateClass(); + LLViewerMediaTexture::updateClass(); static LLCachedControl max_vram_budget(gSavedSettings, "RenderMaxVRAMBudget", 0); - F64 texture_bytes_alloc = LLImageGL::getTextureBytesAllocated() / 1024.0 / 512.0; - F64 vertex_bytes_alloc = LLVertexBuffer::getBytesAllocated() / 1024.0 / 512.0; + F64 texture_bytes_alloc = LLImageGL::getTextureBytesAllocated() / 1024.0 / 512.0; + F64 vertex_bytes_alloc = LLVertexBuffer::getBytesAllocated() / 1024.0 / 512.0; - // get an estimate of how much video memory we're using + // get an estimate of how much video memory we're using // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number - F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); - + F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); + F32 budget = max_vram_budget == 0 ? gGLManager.mVRAM : max_vram_budget; // try to leave half a GB for everyone else, but keep at least 768MB for ourselves @@ -563,75 +563,75 @@ void LLViewerTexture::updateClass() const U32 LLViewerTexture::sCurrentFileVersion = 1; LLViewerTexture::LLViewerTexture(BOOL usemipmaps) : - LLGLTexture(usemipmaps) + LLGLTexture(usemipmaps) { - init(true); + init(true); - mID.generate(); - sImageCount++; + mID.generate(); + sImageCount++; } LLViewerTexture::LLViewerTexture(const LLUUID& id, BOOL usemipmaps) : - LLGLTexture(usemipmaps), - mID(id) + LLGLTexture(usemipmaps), + mID(id) { - init(true); - - sImageCount++; + init(true); + + sImageCount++; } LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) : - LLGLTexture(width, height, components, usemipmaps) + LLGLTexture(width, height, components, usemipmaps) { - init(true); + init(true); - mID.generate(); - sImageCount++; + mID.generate(); + sImageCount++; } LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) : - LLGLTexture(raw, usemipmaps) + LLGLTexture(raw, usemipmaps) { - init(true); - - mID.generate(); - sImageCount++; + init(true); + + mID.generate(); + sImageCount++; } LLViewerTexture::~LLViewerTexture() { - // LL_DEBUGS("Avatar") << mID << LL_ENDL; - cleanup(); - sImageCount--; + // LL_DEBUGS("Avatar") << mID << LL_ENDL; + cleanup(); + sImageCount--; } // virtual void LLViewerTexture::init(bool firstinit) { - mMaxVirtualSize = 0.f; - mMaxVirtualSizeResetInterval = 1; - mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; - mParcelMedia = NULL; - - memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); - mFaceList[LLRender::DIFFUSE_MAP].clear(); - mFaceList[LLRender::NORMAL_MAP].clear(); - mFaceList[LLRender::SPECULAR_MAP].clear(); - mNumFaces[LLRender::DIFFUSE_MAP] = - mNumFaces[LLRender::NORMAL_MAP] = - mNumFaces[LLRender::SPECULAR_MAP] = 0; - - mVolumeList[LLRender::LIGHT_TEX].clear(); - mVolumeList[LLRender::SCULPT_TEX].clear(); - - mMainQueue = LL::WorkQueue::getInstance("mainloop"); - mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); -} - -//virtual + mMaxVirtualSize = 0.f; + mMaxVirtualSizeResetInterval = 1; + mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval; + mParcelMedia = NULL; + + memset(&mNumVolumes, 0, sizeof(U32)* LLRender::NUM_VOLUME_TEXTURE_CHANNELS); + mFaceList[LLRender::DIFFUSE_MAP].clear(); + mFaceList[LLRender::NORMAL_MAP].clear(); + mFaceList[LLRender::SPECULAR_MAP].clear(); + mNumFaces[LLRender::DIFFUSE_MAP] = + mNumFaces[LLRender::NORMAL_MAP] = + mNumFaces[LLRender::SPECULAR_MAP] = 0; + + mVolumeList[LLRender::LIGHT_TEX].clear(); + mVolumeList[LLRender::SCULPT_TEX].clear(); + + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); +} + +//virtual S8 LLViewerTexture::getType() const { - return LLViewerTexture::LOCAL_TEXTURE; + return LLViewerTexture::LOCAL_TEXTURE; } void LLViewerTexture::cleanup() @@ -641,37 +641,37 @@ void LLViewerTexture::cleanup() LLAppViewer::getTextureFetch()->updateRequestPriority(mID, 0.f); } - mFaceList[LLRender::DIFFUSE_MAP].clear(); - mFaceList[LLRender::NORMAL_MAP].clear(); - mFaceList[LLRender::SPECULAR_MAP].clear(); - mVolumeList[LLRender::LIGHT_TEX].clear(); - mVolumeList[LLRender::SCULPT_TEX].clear(); + mFaceList[LLRender::DIFFUSE_MAP].clear(); + mFaceList[LLRender::NORMAL_MAP].clear(); + mFaceList[LLRender::SPECULAR_MAP].clear(); + mVolumeList[LLRender::LIGHT_TEX].clear(); + mVolumeList[LLRender::SCULPT_TEX].clear(); } // virtual void LLViewerTexture::dump() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - LLGLTexture::dump(); + LLGLTexture::dump(); - LL_INFOS() << "LLViewerTexture" - << " mID " << mID - << LL_ENDL; + LL_INFOS() << "LLViewerTexture" + << " mID " << mID + << LL_ENDL; } void LLViewerTexture::setBoostLevel(S32 level) { - if(mBoostLevel != level) - { - mBoostLevel = level; - if(mBoostLevel != LLViewerTexture::BOOST_NONE && - mBoostLevel != LLViewerTexture::BOOST_SELECTED && - mBoostLevel != LLViewerTexture::BOOST_ICON && + if(mBoostLevel != level) + { + mBoostLevel = level; + if(mBoostLevel != LLViewerTexture::BOOST_NONE && + mBoostLevel != LLViewerTexture::BOOST_SELECTED && + mBoostLevel != LLViewerTexture::BOOST_ICON && mBoostLevel != LLViewerTexture::BOOST_THUMBNAIL) - { - setNoDelete(); - } - } + { + setNoDelete(); + } + } // strongly encourage anything boosted to load at full res if (mBoostLevel >= LLViewerTexture::BOOST_HIGH) @@ -682,159 +682,159 @@ void LLViewerTexture::setBoostLevel(S32 level) bool LLViewerTexture::isActiveFetching() { - return false; + return false; } bool LLViewerTexture::bindDebugImage(const S32 stage) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (stage < 0) return false; + if (stage < 0) return false; - bool res = true; - if (LLViewerTexture::sCheckerBoardImagep.notNull() && (this != LLViewerTexture::sCheckerBoardImagep.get())) - { - res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sCheckerBoardImagep); - } + bool res = true; + if (LLViewerTexture::sCheckerBoardImagep.notNull() && (this != LLViewerTexture::sCheckerBoardImagep.get())) + { + res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sCheckerBoardImagep); + } - if(!res) - { - return bindDefaultImage(stage); - } + if(!res) + { + return bindDefaultImage(stage); + } - return res; + return res; } -bool LLViewerTexture::bindDefaultImage(S32 stage) +bool LLViewerTexture::bindDefaultImage(S32 stage) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (stage < 0) return false; + if (stage < 0) return false; - bool res = true; - if (LLViewerFetchedTexture::sDefaultImagep.notNull() && (this != LLViewerFetchedTexture::sDefaultImagep.get())) - { - // use default if we've got it - res = gGL.getTexUnit(stage)->bind(LLViewerFetchedTexture::sDefaultImagep); - } - if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep)) - { - res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep); - } - if (!res) - { - LL_WARNS() << "LLViewerTexture::bindDefaultImage failed." << LL_ENDL; - } - stop_glerror(); + bool res = true; + if (LLViewerFetchedTexture::sDefaultImagep.notNull() && (this != LLViewerFetchedTexture::sDefaultImagep.get())) + { + // use default if we've got it + res = gGL.getTexUnit(stage)->bind(LLViewerFetchedTexture::sDefaultImagep); + } + if (!res && LLViewerTexture::sNullImagep.notNull() && (this != LLViewerTexture::sNullImagep)) + { + res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sNullImagep); + } + if (!res) + { + LL_WARNS() << "LLViewerTexture::bindDefaultImage failed." << LL_ENDL; + } + stop_glerror(); - //check if there is cached raw image and switch to it if possible - switchToCachedImage(); + //check if there is cached raw image and switch to it if possible + switchToCachedImage(); - LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); - if (tester) - { - tester->updateGrayTextureBinding(); - } - return res; + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); + if (tester) + { + tester->updateGrayTextureBinding(); + } + return res; } -//virtual -BOOL LLViewerTexture::isMissingAsset()const -{ - return FALSE; +//virtual +BOOL LLViewerTexture::isMissingAsset()const +{ + return FALSE; } -//virtual -void LLViewerTexture::forceImmediateUpdate() +//virtual +void LLViewerTexture::forceImmediateUpdate() { } -void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const +void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(needs_gltexture) - { - mNeedsGLTexture = TRUE; - } + if(needs_gltexture) + { + mNeedsGLTexture = TRUE; + } virtual_size = llmin(virtual_size, LLViewerFetchedTexture::sMaxVirtualSize); - if (virtual_size > mMaxVirtualSize) - { - mMaxVirtualSize = virtual_size; - } + if (virtual_size > mMaxVirtualSize) + { + mMaxVirtualSize = virtual_size; + } } void LLViewerTexture::resetTextureStats() { - mMaxVirtualSize = 0.0f; - mMaxVirtualSizeResetCounter = 0; + mMaxVirtualSize = 0.0f; + mMaxVirtualSizeResetCounter = 0; } -//virtual +//virtual F32 LLViewerTexture::getMaxVirtualSize() { - return mMaxVirtualSize; + return mMaxVirtualSize; } -//virtual +//virtual void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) { - //nothing here. + //nothing here. } //virtual -void LLViewerTexture::addFace(U32 ch, LLFace* facep) +void LLViewerTexture::addFace(U32 ch, LLFace* facep) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - if(mNumFaces[ch] >= mFaceList[ch].size()) - { - mFaceList[ch].resize(2 * mNumFaces[ch] + 1); - } - mFaceList[ch][mNumFaces[ch]] = facep; - facep->setIndexInTex(ch, mNumFaces[ch]); - mNumFaces[ch]++; - mLastFaceListUpdateTimer.reset(); + if(mNumFaces[ch] >= mFaceList[ch].size()) + { + mFaceList[ch].resize(2 * mNumFaces[ch] + 1); + } + mFaceList[ch][mNumFaces[ch]] = facep; + facep->setIndexInTex(ch, mNumFaces[ch]); + mNumFaces[ch]++; + mLastFaceListUpdateTimer.reset(); } //virtual -void LLViewerTexture::removeFace(U32 ch, LLFace* facep) +void LLViewerTexture::removeFace(U32 ch, LLFace* facep) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - - if(mNumFaces[ch] > 1) - { - S32 index = facep->getIndexInTex(ch); - llassert(index < mFaceList[ch].size()); - llassert(index < mNumFaces[ch]); - mFaceList[ch][index] = mFaceList[ch][--mNumFaces[ch]]; - mFaceList[ch][index]->setIndexInTex(ch, index); - } - else - { - mFaceList[ch].clear(); - mNumFaces[ch] = 0; - } - mLastFaceListUpdateTimer.reset(); + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + + if(mNumFaces[ch] > 1) + { + S32 index = facep->getIndexInTex(ch); + llassert(index < mFaceList[ch].size()); + llassert(index < mNumFaces[ch]); + mFaceList[ch][index] = mFaceList[ch][--mNumFaces[ch]]; + mFaceList[ch][index]->setIndexInTex(ch, index); + } + else + { + mFaceList[ch].clear(); + mNumFaces[ch] = 0; + } + mLastFaceListUpdateTimer.reset(); } S32 LLViewerTexture::getTotalNumFaces() const { - S32 ret = 0; + S32 ret = 0; - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - ret += mNumFaces[i]; - } + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + ret += mNumFaces[i]; + } - return ret; + return ret; } S32 LLViewerTexture::getNumFaces(U32 ch) const { - llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); - return mNumFaces[ch]; + llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); + return mNumFaces[ch]; } @@ -842,117 +842,117 @@ S32 LLViewerTexture::getNumFaces(U32 ch) const void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (mNumVolumes[ch] >= mVolumeList[ch].size()) - { - mVolumeList[ch].resize(2 * mNumVolumes[ch] + 1); - } - mVolumeList[ch][mNumVolumes[ch]] = volumep; - volumep->setIndexInTex(ch, mNumVolumes[ch]); - mNumVolumes[ch]++; - mLastVolumeListUpdateTimer.reset(); + if (mNumVolumes[ch] >= mVolumeList[ch].size()) + { + mVolumeList[ch].resize(2 * mNumVolumes[ch] + 1); + } + mVolumeList[ch][mNumVolumes[ch]] = volumep; + volumep->setIndexInTex(ch, mNumVolumes[ch]); + mNumVolumes[ch]++; + mLastVolumeListUpdateTimer.reset(); } //virtual void LLViewerTexture::removeVolume(U32 ch, LLVOVolume* volumep) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (mNumVolumes[ch] > 1) - { - S32 index = volumep->getIndexInTex(ch); - llassert(index < mVolumeList[ch].size()); - llassert(index < mNumVolumes[ch]); - mVolumeList[ch][index] = mVolumeList[ch][--mNumVolumes[ch]]; - mVolumeList[ch][index]->setIndexInTex(ch, index); - } - else - { - mVolumeList[ch].clear(); - mNumVolumes[ch] = 0; - } - mLastVolumeListUpdateTimer.reset(); + if (mNumVolumes[ch] > 1) + { + S32 index = volumep->getIndexInTex(ch); + llassert(index < mVolumeList[ch].size()); + llassert(index < mNumVolumes[ch]); + mVolumeList[ch][index] = mVolumeList[ch][--mNumVolumes[ch]]; + mVolumeList[ch][index]->setIndexInTex(ch, index); + } + else + { + mVolumeList[ch].clear(); + mNumVolumes[ch] = 0; + } + mLastVolumeListUpdateTimer.reset(); } S32 LLViewerTexture::getNumVolumes(U32 ch) const { - return mNumVolumes[ch]; + return mNumVolumes[ch]; } void LLViewerTexture::reorganizeFaceList() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static const F32 MAX_WAIT_TIME = 20.f; // seconds - static const U32 MAX_EXTRA_BUFFER_SIZE = 4; + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4; + + if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return; + } - if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) - { - return; - } + for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) + { + if(mNumFaces[i] + MAX_EXTRA_BUFFER_SIZE > mFaceList[i].size()) + { + return; + } - for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) - { - if(mNumFaces[i] + MAX_EXTRA_BUFFER_SIZE > mFaceList[i].size()) - { - return; - } + mFaceList[i].erase(mFaceList[i].begin() + mNumFaces[i], mFaceList[i].end()); + } - mFaceList[i].erase(mFaceList[i].begin() + mNumFaces[i], mFaceList[i].end()); - } - - mLastFaceListUpdateTimer.reset(); + mLastFaceListUpdateTimer.reset(); } void LLViewerTexture::reorganizeVolumeList() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static const F32 MAX_WAIT_TIME = 20.f; // seconds - static const U32 MAX_EXTRA_BUFFER_SIZE = 4; + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4; - for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) - { - if (mNumVolumes[i] + MAX_EXTRA_BUFFER_SIZE > mVolumeList[i].size()) - { - return; - } - } + for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) + { + if (mNumVolumes[i] + MAX_EXTRA_BUFFER_SIZE > mVolumeList[i].size()) + { + return; + } + } - if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) - { - return; - } + if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return; + } - mLastVolumeListUpdateTimer.reset(); - for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) - { - mVolumeList[i].erase(mVolumeList[i].begin() + mNumVolumes[i], mVolumeList[i].end()); - } + mLastVolumeListUpdateTimer.reset(); + for (U32 i = 0; i < LLRender::NUM_VOLUME_TEXTURE_CHANNELS; ++i) + { + mVolumeList[i].erase(mVolumeList[i].begin() + mNumVolumes[i], mVolumeList[i].end()); + } } //virtual void LLViewerTexture::switchToCachedImage() { - //nothing here. + //nothing here. } //virtual void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { - //nothing here. + //nothing here. } BOOL LLViewerTexture::isLargeImage() { - return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize; + return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize; } -//virtual +//virtual void LLViewerTexture::updateBindStatsForTester() { - LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); - if (tester) - { - tester->updateTextureBindingStats(this); - } + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); + if (tester) + { + tester->updateTextureBindingStats(this); + } } //---------------------------------------------------------------------------------------------- @@ -961,30 +961,30 @@ void LLViewerTexture::updateBindStatsForTester() const std::string& fttype_to_string(const FTType& fttype) { - static const std::string ftt_unknown("FTT_UNKNOWN"); - static const std::string ftt_default("FTT_DEFAULT"); - static const std::string ftt_server_bake("FTT_SERVER_BAKE"); - static const std::string ftt_host_bake("FTT_HOST_BAKE"); - static const std::string ftt_map_tile("FTT_MAP_TILE"); - static const std::string ftt_local_file("FTT_LOCAL_FILE"); - static const std::string ftt_error("FTT_ERROR"); - switch(fttype) - { - case FTT_UNKNOWN: return ftt_unknown; break; - case FTT_DEFAULT: return ftt_default; break; - case FTT_SERVER_BAKE: return ftt_server_bake; break; - case FTT_HOST_BAKE: return ftt_host_bake; break; - case FTT_MAP_TILE: return ftt_map_tile; break; - case FTT_LOCAL_FILE: return ftt_local_file; break; - } - return ftt_error; + static const std::string ftt_unknown("FTT_UNKNOWN"); + static const std::string ftt_default("FTT_DEFAULT"); + static const std::string ftt_server_bake("FTT_SERVER_BAKE"); + static const std::string ftt_host_bake("FTT_HOST_BAKE"); + static const std::string ftt_map_tile("FTT_MAP_TILE"); + static const std::string ftt_local_file("FTT_LOCAL_FILE"); + static const std::string ftt_error("FTT_ERROR"); + switch(fttype) + { + case FTT_UNKNOWN: return ftt_unknown; break; + case FTT_DEFAULT: return ftt_default; break; + case FTT_SERVER_BAKE: return ftt_server_bake; break; + case FTT_HOST_BAKE: return ftt_host_bake; break; + case FTT_MAP_TILE: return ftt_map_tile; break; + case FTT_LOCAL_FILE: return ftt_local_file; break; + } + return ftt_error; } //---------------------------------------------------------------------------------------------- //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -//static +//static LLViewerFetchedTexture* LLViewerFetchedTexture::getSmokeImage() { if (sSmokeImagep.isNull()) @@ -998,186 +998,186 @@ LLViewerFetchedTexture* LLViewerFetchedTexture::getSmokeImage() } LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps), - mTargetHost(host) -{ - init(TRUE); - mFTType = f_type; - if (mFTType == FTT_HOST_BAKE) - { - LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL; - } - generateGLTexture(); -} - + : LLViewerTexture(id, usemipmaps), + mTargetHost(host) +{ + init(TRUE); + mFTType = f_type; + if (mFTType == FTT_HOST_BAKE) + { + LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL; + } + generateGLTexture(); +} + LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps) - : LLViewerTexture(raw, usemipmaps) + : LLViewerTexture(raw, usemipmaps) { - init(TRUE); - mFTType = f_type; + init(TRUE); + mFTType = f_type; } - + LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps), - mUrl(url) + : LLViewerTexture(id, usemipmaps), + mUrl(url) { - init(TRUE); - mFTType = f_type; - generateGLTexture(); + init(TRUE); + mFTType = f_type; + generateGLTexture(); } void LLViewerFetchedTexture::init(bool firstinit) { - mOrigWidth = 0; - mOrigHeight = 0; - mHasAux = FALSE; - mNeedsAux = FALSE; - mRequestedDiscardLevel = -1; - mRequestedDownloadPriority = 0.f; - mFullyLoaded = FALSE; - mCanUseHTTP = true; - mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - - mDecodingAux = FALSE; - - mKnownDrawWidth = 0; - mKnownDrawHeight = 0; - mKnownDrawSizeChanged = FALSE; - - if (firstinit) - { - mInImageList = 0; - } - - // Only set mIsMissingAsset true when we know for certain that the database - // does not contain this image. - mIsMissingAsset = FALSE; - - mLoadedCallbackDesiredDiscardLevel = S8_MAX; - mPauseLoadedCallBacks = FALSE; - - mNeedsCreateTexture = false; - - mIsRawImageValid = FALSE; - mRawDiscardLevel = INVALID_DISCARD_LEVEL; - mMinDiscardLevel = 0; - - mHasFetcher = FALSE; - mIsFetching = FALSE; - mFetchState = 0; - mFetchPriority = 0; - mDownloadProgress = 0.f; - mFetchDeltaTime = 999999.f; - mRequestDeltaTime = 0.f; - mForSculpt = FALSE; - mIsFetched = FALSE; - mInFastCacheList = FALSE; - - mCachedRawImage = NULL; - mCachedRawDiscardLevel = -1; - mCachedRawImageReady = FALSE; - - mSavedRawImage = NULL; - mForceToSaveRawImage = FALSE; - mSaveRawImage = FALSE; - mSavedRawDiscardLevel = -1; - mDesiredSavedRawDiscardLevel = -1; - mLastReferencedSavedRawImageTime = 0.0f; - mKeptSavedRawImageTime = 0.f; - mLastCallBackActiveTime = 0.f; - mForceCallbackFetch = FALSE; - mInDebug = FALSE; - mUnremovable = FALSE; - - mFTType = FTT_UNKNOWN; + mOrigWidth = 0; + mOrigHeight = 0; + mHasAux = FALSE; + mNeedsAux = FALSE; + mRequestedDiscardLevel = -1; + mRequestedDownloadPriority = 0.f; + mFullyLoaded = FALSE; + mCanUseHTTP = true; + mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + + mDecodingAux = FALSE; + + mKnownDrawWidth = 0; + mKnownDrawHeight = 0; + mKnownDrawSizeChanged = FALSE; + + if (firstinit) + { + mInImageList = 0; + } + + // Only set mIsMissingAsset true when we know for certain that the database + // does not contain this image. + mIsMissingAsset = FALSE; + + mLoadedCallbackDesiredDiscardLevel = S8_MAX; + mPauseLoadedCallBacks = FALSE; + + mNeedsCreateTexture = false; + + mIsRawImageValid = FALSE; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + mMinDiscardLevel = 0; + + mHasFetcher = FALSE; + mIsFetching = FALSE; + mFetchState = 0; + mFetchPriority = 0; + mDownloadProgress = 0.f; + mFetchDeltaTime = 999999.f; + mRequestDeltaTime = 0.f; + mForSculpt = FALSE; + mIsFetched = FALSE; + mInFastCacheList = FALSE; + + mCachedRawImage = NULL; + mCachedRawDiscardLevel = -1; + mCachedRawImageReady = FALSE; + + mSavedRawImage = NULL; + mForceToSaveRawImage = FALSE; + mSaveRawImage = FALSE; + mSavedRawDiscardLevel = -1; + mDesiredSavedRawDiscardLevel = -1; + mLastReferencedSavedRawImageTime = 0.0f; + mKeptSavedRawImageTime = 0.f; + mLastCallBackActiveTime = 0.f; + mForceCallbackFetch = FALSE; + mInDebug = FALSE; + mUnremovable = FALSE; + + mFTType = FTT_UNKNOWN; } LLViewerFetchedTexture::~LLViewerFetchedTexture() { assert_main_thread(); - //*NOTE getTextureFetch can return NULL when Viewer is shutting down. - // This is due to LLWearableList is singleton and is destroyed after - // LLAppViewer::cleanup() was called. (see ticket EXT-177) - if (mHasFetcher && LLAppViewer::getTextureFetch()) - { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - } - cleanup(); + //*NOTE getTextureFetch can return NULL when Viewer is shutting down. + // This is due to LLWearableList is singleton and is destroyed after + // LLAppViewer::cleanup() was called. (see ticket EXT-177) + if (mHasFetcher && LLAppViewer::getTextureFetch()) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + } + cleanup(); } -//virtual +//virtual S8 LLViewerFetchedTexture::getType() const { - return LLViewerTexture::FETCHED_TEXTURE; + return LLViewerTexture::FETCHED_TEXTURE; } FTType LLViewerFetchedTexture::getFTType() const { - return mFTType; + return mFTType; } void LLViewerFetchedTexture::cleanup() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - // We never finished loading the image. Indicate failure. - // Note: this allows mLoadedCallbackUserData to be cleaned up. - entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData ); - entryp->removeTexture(this); - delete entryp; - } - mLoadedCallbackList.clear(); - mNeedsAux = FALSE; - - // Clean up image data - destroyRawImage(); - mCachedRawImage = NULL; - mCachedRawDiscardLevel = -1; - mCachedRawImageReady = FALSE; - mSavedRawImage = NULL; - mSavedRawDiscardLevel = -1; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData ); + entryp->removeTexture(this); + delete entryp; + } + mLoadedCallbackList.clear(); + mNeedsAux = FALSE; + + // Clean up image data + destroyRawImage(); + mCachedRawImage = NULL; + mCachedRawDiscardLevel = -1; + mCachedRawImageReady = FALSE; + mSavedRawImage = NULL; + mSavedRawDiscardLevel = -1; } //access the fast cache void LLViewerFetchedTexture::loadFromFastCache() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(!mInFastCacheList) - { - return; //no need to access the fast cache. - } - mInFastCacheList = FALSE; + if(!mInFastCacheList) + { + return; //no need to access the fast cache. + } + mInFastCacheList = FALSE; add(LLTextureFetch::sCacheAttempt, 1.0); LLTimer fastCacheTimer; - mRawImage = LLAppViewer::getTextureCache()->readFromFastCache(getID(), mRawDiscardLevel); - if(mRawImage.notNull()) - { + mRawImage = LLAppViewer::getTextureCache()->readFromFastCache(getID(), mRawDiscardLevel); + if(mRawImage.notNull()) + { F32 cachReadTime = fastCacheTimer.getElapsedTimeF32(); add(LLTextureFetch::sCacheHit, 1.0); record(LLTextureFetch::sCacheHitRate, LLUnits::Ratio::fromValue(1)); sample(LLTextureFetch::sCacheReadLatency, cachReadTime); - mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; - mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; - setTexelsPerImage(); - - if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) - { - //discard all oversized textures. - destroyRawImage(); - LL_WARNS() << "oversized, setting as missing" << LL_ENDL; - setIsMissingAsset(); - mRawDiscardLevel = INVALID_DISCARD_LEVEL; - } - else - { + mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; + mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; + setTexelsPerImage(); + + if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) + { + //discard all oversized textures. + destroyRawImage(); + LL_WARNS() << "oversized, setting as missing" << LL_ENDL; + setIsMissingAsset(); + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + } + else + { if (mBoostLevel == LLGLTexture::BOOST_ICON) { // Shouldn't do anything usefull since texures in fast cache are 16x16, @@ -1202,11 +1202,11 @@ void LLViewerFetchedTexture::loadFromFastCache() } } - mRequestedDiscardLevel = mDesiredDiscardLevel + 1; - mIsRawImageValid = TRUE; - addToCreateTexture(); - } - } + mRequestedDiscardLevel = mDesiredDiscardLevel + 1; + mIsRawImageValid = TRUE; + addToCreateTexture(); + } + } else { record(LLTextureFetch::sCacheHitRate, LLUnits::Ratio::fromValue(0)); @@ -1215,197 +1215,197 @@ void LLViewerFetchedTexture::loadFromFastCache() void LLViewerFetchedTexture::setForSculpt() { - static const S32 MAX_INTERVAL = 8; //frames + static const S32 MAX_INTERVAL = 8; //frames - mForSculpt = TRUE; - if(isForSculptOnly() && hasGLTexture() && !getBoundRecently()) - { - destroyGLTexture(); //sculpt image does not need gl texture. - mTextureState = ACTIVE; - } - checkCachedRawSculptImage(); - setMaxVirtualSizeResetInterval(MAX_INTERVAL); + mForSculpt = TRUE; + if(isForSculptOnly() && hasGLTexture() && !getBoundRecently()) + { + destroyGLTexture(); //sculpt image does not need gl texture. + mTextureState = ACTIVE; + } + checkCachedRawSculptImage(); + setMaxVirtualSizeResetInterval(MAX_INTERVAL); } BOOL LLViewerFetchedTexture::isForSculptOnly() const { - return mForSculpt && !mNeedsGLTexture; + return mForSculpt && !mNeedsGLTexture; } -BOOL LLViewerFetchedTexture::isDeleted() -{ - return mTextureState == DELETED; +BOOL LLViewerFetchedTexture::isDeleted() +{ + return mTextureState == DELETED; } -BOOL LLViewerFetchedTexture::isInactive() -{ - return mTextureState == INACTIVE; +BOOL LLViewerFetchedTexture::isInactive() +{ + return mTextureState == INACTIVE; } -BOOL LLViewerFetchedTexture::isDeletionCandidate() -{ - return mTextureState == DELETION_CANDIDATE; +BOOL LLViewerFetchedTexture::isDeletionCandidate() +{ + return mTextureState == DELETION_CANDIDATE; } -void LLViewerFetchedTexture::setDeletionCandidate() -{ - if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE)) - { - mTextureState = DELETION_CANDIDATE; - } +void LLViewerFetchedTexture::setDeletionCandidate() +{ + if(mGLTexturep.notNull() && mGLTexturep->getTexName() && (mTextureState == INACTIVE)) + { + mTextureState = DELETION_CANDIDATE; + } } //set the texture inactive void LLViewerFetchedTexture::setInactive() { - if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently()) - { - mTextureState = INACTIVE; - } + if(mTextureState == ACTIVE && mGLTexturep.notNull() && mGLTexturep->getTexName() && !mGLTexturep->getBoundRecently()) + { + mTextureState = INACTIVE; + } } BOOL LLViewerFetchedTexture::isFullyLoaded() const { - // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic - // to check if the texture is there and completely downloaded - return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher; + // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic + // to check if the texture is there and completely downloaded + return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher; } // virtual void LLViewerFetchedTexture::dump() { - LLViewerTexture::dump(); - - LL_INFOS() << "Dump : " << mID - << ", mIsMissingAsset = " << (S32)mIsMissingAsset - << ", mFullWidth = " << (S32)mFullWidth - << ", mFullHeight = " << (S32)mFullHeight - << ", mOrigWidth = " << (S32)mOrigWidth - << ", mOrigHeight = " << (S32)mOrigHeight - << LL_ENDL; - LL_INFOS() << " : " - << " mFullyLoaded = " << (S32)mFullyLoaded - << ", mFetchState = " << (S32)mFetchState - << ", mFetchPriority = " << (S32)mFetchPriority - << ", mDownloadProgress = " << (F32)mDownloadProgress - << LL_ENDL; - LL_INFOS() << " : " - << " mHasFetcher = " << (S32)mHasFetcher - << ", mIsFetching = " << (S32)mIsFetching - << ", mIsFetched = " << (S32)mIsFetched - << ", mBoostLevel = " << (S32)mBoostLevel - << LL_ENDL; + LLViewerTexture::dump(); + + LL_INFOS() << "Dump : " << mID + << ", mIsMissingAsset = " << (S32)mIsMissingAsset + << ", mFullWidth = " << (S32)mFullWidth + << ", mFullHeight = " << (S32)mFullHeight + << ", mOrigWidth = " << (S32)mOrigWidth + << ", mOrigHeight = " << (S32)mOrigHeight + << LL_ENDL; + LL_INFOS() << " : " + << " mFullyLoaded = " << (S32)mFullyLoaded + << ", mFetchState = " << (S32)mFetchState + << ", mFetchPriority = " << (S32)mFetchPriority + << ", mDownloadProgress = " << (F32)mDownloadProgress + << LL_ENDL; + LL_INFOS() << " : " + << " mHasFetcher = " << (S32)mHasFetcher + << ", mIsFetching = " << (S32)mIsFetching + << ", mIsFetched = " << (S32)mIsFetched + << ", mBoostLevel = " << (S32)mBoostLevel + << LL_ENDL; } /////////////////////////////////////////////////////////////////////////////// // ONLY called from LLViewerFetchedTextureList -void LLViewerFetchedTexture::destroyTexture() +void LLViewerFetchedTexture::destroyTexture() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (mNeedsCreateTexture)//return if in the process of generating a new texture. - { - return; - } + if (mNeedsCreateTexture)//return if in the process of generating a new texture. + { + return; + } - //LL_DEBUGS("Avatar") << mID << LL_ENDL; - destroyGLTexture(); - mFullyLoaded = FALSE; + //LL_DEBUGS("Avatar") << mID << LL_ENDL; + destroyGLTexture(); + mFullyLoaded = FALSE; } void LLViewerFetchedTexture::addToCreateTexture() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - bool force_update = false; - if (getComponents() != mRawImage->getComponents()) - { - // We've changed the number of components, so we need to move any - // objects using this pool to a different pool. - mComponents = mRawImage->getComponents(); - mGLTexturep->setComponents(mComponents); - force_update = true; - - for (U32 j = 0; j < LLRender::NUM_TEXTURE_CHANNELS; ++j) - { - llassert(mNumFaces[j] <= mFaceList[j].size()); - - for(U32 i = 0; i < mNumFaces[j]; i++) - { - mFaceList[j][i]->dirtyTexture(); - } - } - - //discard the cached raw image and the saved raw image - mCachedRawImageReady = FALSE; - mCachedRawDiscardLevel = -1; - mCachedRawImage = NULL; - mSavedRawDiscardLevel = -1; - mSavedRawImage = NULL; - } - - if(isForSculptOnly()) - { - //just update some variables, not to create a real GL texture. - createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE); - mNeedsCreateTexture = false; - destroyRawImage(); - } - else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel) - { - mNeedsCreateTexture = false; - destroyRawImage(); - } - else - { + bool force_update = false; + if (getComponents() != mRawImage->getComponents()) + { + // We've changed the number of components, so we need to move any + // objects using this pool to a different pool. + mComponents = mRawImage->getComponents(); + mGLTexturep->setComponents(mComponents); + force_update = true; + + for (U32 j = 0; j < LLRender::NUM_TEXTURE_CHANNELS; ++j) + { + llassert(mNumFaces[j] <= mFaceList[j].size()); + + for(U32 i = 0; i < mNumFaces[j]; i++) + { + mFaceList[j][i]->dirtyTexture(); + } + } + + //discard the cached raw image and the saved raw image + mCachedRawImageReady = FALSE; + mCachedRawDiscardLevel = -1; + mCachedRawImage = NULL; + mSavedRawDiscardLevel = -1; + mSavedRawImage = NULL; + } + + if(isForSculptOnly()) + { + //just update some variables, not to create a real GL texture. + createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE); + mNeedsCreateTexture = false; + destroyRawImage(); + } + else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel) + { + mNeedsCreateTexture = false; + destroyRawImage(); + } + else + { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; #if 1 - // - //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, - //so do not scale down the over qualified image. - //Note: scaling down image is expensensive. Do it only when very necessary. - // - if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !mForceToSaveRawImage) - { - S32 w = mFullWidth >> mRawDiscardLevel; - S32 h = mFullHeight >> mRawDiscardLevel; - - //if big image, do not load extra data - //scale it down to size >= LLViewerTexture::sMinLargeImageSize - if(w * h > LLViewerTexture::sMinLargeImageSize) - { - S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel; - - if(d_level > 0) - { - S32 i = 0; - while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize)) - { - i++; - d_level--; - } - if(i > 0) - { - mRawDiscardLevel += i; - if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) - { - mNeedsCreateTexture = false; - destroyRawImage(); - return; - } - - { - //make a duplicate in case somebody else is using this raw image - mRawImage = mRawImage->scaled(w >> i, h >> i); - } - } - } - } - } + // + //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, + //so do not scale down the over qualified image. + //Note: scaling down image is expensensive. Do it only when very necessary. + // + if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !mForceToSaveRawImage) + { + S32 w = mFullWidth >> mRawDiscardLevel; + S32 h = mFullHeight >> mRawDiscardLevel; + + //if big image, do not load extra data + //scale it down to size >= LLViewerTexture::sMinLargeImageSize + if(w * h > LLViewerTexture::sMinLargeImageSize) + { + S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel; + + if(d_level > 0) + { + S32 i = 0; + while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize)) + { + i++; + d_level--; + } + if(i > 0) + { + mRawDiscardLevel += i; + if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) + { + mNeedsCreateTexture = false; + destroyRawImage(); + return; + } + + { + //make a duplicate in case somebody else is using this raw image + mRawImage = mRawImage->scaled(w >> i, h >> i); + } + } + } + } + } #endif scheduleCreateTexture(); - } - return; + } + return; } // ONLY called from LLViewerTextureList @@ -1433,10 +1433,10 @@ BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) destroyRawImage(); return FALSE; } - // LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", - // mRawDiscardLevel, - // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) - // << mID.getString() << LL_ENDL; + // LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", + // mRawDiscardLevel, + // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) + // << mID.getString() << LL_ENDL; BOOL res = TRUE; // store original size only for locally-sourced images @@ -1532,9 +1532,9 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) return FALSE; } - BOOL res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); - - return res; + BOOL res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + + return res; } void LLViewerFetchedTexture::postCreateTexture() @@ -1640,15 +1640,15 @@ void LLViewerFetchedTexture::scheduleCreateTexture() void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(mKnownDrawWidth < width || mKnownDrawHeight < height) - { - mKnownDrawWidth = llmax(mKnownDrawWidth, width); - mKnownDrawHeight = llmax(mKnownDrawHeight, height); + if(mKnownDrawWidth < width || mKnownDrawHeight < height) + { + mKnownDrawWidth = llmax(mKnownDrawWidth, width); + mKnownDrawHeight = llmax(mKnownDrawHeight, height); - mKnownDrawSizeChanged = TRUE; - mFullyLoaded = FALSE; - } - addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight)); + mKnownDrawSizeChanged = TRUE; + mFullyLoaded = FALSE; + } + addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight)); } void LLViewerFetchedTexture::setDebugText(const std::string& text) @@ -1676,25 +1676,25 @@ void LLViewerFetchedTexture::setDebugText(const std::string& text) void LLViewerFetchedTexture::processTextureStats() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(mFullyLoaded) - { - if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more - { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); - mFullyLoaded = FALSE; - } + if(mFullyLoaded) + { + if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); + mFullyLoaded = FALSE; + } //setDebugText("fully loaded"); - } - else - { - updateVirtualSize(); - - static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); - - if (textures_fullres) - { - mDesiredDiscardLevel = 0; - } + } + else + { + updateVirtualSize(); + + static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } else if (mDontDiscard && (mBoostLevel == LLGLTexture::BOOST_ICON || mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)) { if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -1706,96 +1706,96 @@ void LLViewerFetchedTexture::processTextureStats() mDesiredDiscardLevel = 0; } } - else if(!mFullWidth || !mFullHeight) - { - mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel); - } - else - { - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 - if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) - { - if (mFullWidth > desired_size || mFullHeight > desired_size) - { - mDesiredDiscardLevel = 1; - } - else - { - mDesiredDiscardLevel = 0; - } - } - else if(mKnownDrawSizeChanged)//known draw size is set - { - mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, - log((F32)mFullHeight / mKnownDrawHeight) / log_2); - mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()); - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); - } - mKnownDrawSizeChanged = FALSE; - - if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) - { - mFullyLoaded = TRUE; - } - } - } - - if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. - { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); - if(getDiscardLevel() < 0 || getDiscardLevel() > mDesiredDiscardLevel) - { - mFullyLoaded = FALSE; - } - } -} - -//============================================================================ - -void LLViewerFetchedTexture::updateVirtualSize() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - reorganizeFaceList(); - reorganizeVolumeList(); -} - -S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() -{ - S32 current_discard = getDiscardLevel(); - if(mForceToSaveRawImage) - { - if(mSavedRawDiscardLevel < 0 || current_discard < 0) - { - current_discard = -1; - } - else - { - current_discard = llmax(current_discard, mSavedRawDiscardLevel); - } - } - - return current_discard; + else if(!mFullWidth || !mFullHeight) + { + mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel); + } + else + { + U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 + if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) + { + if (mFullWidth > desired_size || mFullHeight > desired_size) + { + mDesiredDiscardLevel = 1; + } + else + { + mDesiredDiscardLevel = 0; + } + } + else if(mKnownDrawSizeChanged)//known draw size is set + { + mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, + log((F32)mFullHeight / mKnownDrawHeight) / log_2); + mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()); + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel); + } + mKnownDrawSizeChanged = FALSE; + + if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) + { + mFullyLoaded = TRUE; + } + } + } + + if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); + if(getDiscardLevel() < 0 || getDiscardLevel() > mDesiredDiscardLevel) + { + mFullyLoaded = FALSE; + } + } +} + +//============================================================================ + +void LLViewerFetchedTexture::updateVirtualSize() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + reorganizeFaceList(); + reorganizeVolumeList(); +} + +S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() +{ + S32 current_discard = getDiscardLevel(); + if(mForceToSaveRawImage) + { + if(mSavedRawDiscardLevel < 0 || current_discard < 0) + { + current_discard = -1; + } + else + { + current_discard = llmax(current_discard, mSavedRawDiscardLevel); + } + } + + return current_discard; } bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level) { - if(debug_level < 0) - { - mInDebug = FALSE; - return false; - } - mInDebug = TRUE; + if(debug_level < 0) + { + mInDebug = FALSE; + return false; + } + mInDebug = TRUE; - mDesiredDiscardLevel = debug_level; + mDesiredDiscardLevel = debug_level; - return true; + return true; } bool LLViewerFetchedTexture::isActiveFetching() { - static LLCachedControl monitor_enabled(gSavedSettings,"DebugShowTextureInfo"); + static LLCachedControl monitor_enabled(gSavedSettings,"DebugShowTextureInfo"); - return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE. + return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE. } void LLViewerFetchedTexture::setBoostLevel(S32 level) @@ -1811,121 +1811,121 @@ void LLViewerFetchedTexture::setBoostLevel(S32 level) bool LLViewerFetchedTexture::updateFetch() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); - - if(textures_decode_disabled) // don't fetch the surface textures in wireframe mode - { - return false; - } - - mFetchState = 0; - mFetchPriority = 0; - mFetchDeltaTime = 999999.f; - mRequestDeltaTime = 999999.f; + static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); + + if(textures_decode_disabled) // don't fetch the surface textures in wireframe mode + { + return false; + } + + mFetchState = 0; + mFetchPriority = 0; + mFetchDeltaTime = 999999.f; + mRequestDeltaTime = 999999.f; #ifndef LL_RELEASE_FOR_DOWNLOAD - if (mID == LLAppViewer::getTextureFetch()->mDebugID) - { - LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints - } + if (mID == LLAppViewer::getTextureFetch()->mDebugID) + { + LLAppViewer::getTextureFetch()->mDebugCount++; // for setting breakpoints + } #endif - if (mNeedsCreateTexture) - { + if (mNeedsCreateTexture) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - needs create"); - // We may be fetching still (e.g. waiting on write) - // but don't check until we've processed the raw data we have - return false; - } - if (mIsMissingAsset) - { + // We may be fetching still (e.g. waiting on write) + // but don't check until we've processed the raw data we have + return false; + } + if (mIsMissingAsset) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - missing asset"); - llassert(!mHasFetcher); - return false; // skip - } - if (!mLoadedCallbackList.empty() && mRawImage.notNull()) - { + llassert(!mHasFetcher); + return false; // skip + } + if (!mLoadedCallbackList.empty() && mRawImage.notNull()) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - callback pending"); - return false; // process any raw image data in callbacks before replacing - } - if(mInFastCacheList) - { + return false; // process any raw image data in callbacks before replacing + } + if(mInFastCacheList) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - in fast cache"); - return false; - } + return false; + } if (mGLTexturep.isNull()) { // fix for crash inside getCurrentDiscardLevelForFetching (shouldn't happen but appears to be happening) llassert(false); return false; } - - S32 current_discard = getCurrentDiscardLevelForFetching(); - S32 desired_discard = getDesiredDiscardLevel(); - F32 decode_priority = mMaxVirtualSize; - if (mIsFetching) - { + S32 current_discard = getCurrentDiscardLevelForFetching(); + S32 desired_discard = getDesiredDiscardLevel(); + F32 decode_priority = mMaxVirtualSize; + + if (mIsFetching) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - is fetching"); - // Sets mRawDiscardLevel, mRawImage, mAuxRawImage - S32 fetch_discard = current_discard; - - if (mRawImage.notNull()) sRawCount--; - if (mAuxRawImage.notNull()) sAuxCount--; - // keep in mind that fetcher still might need raw image, don't modify original - bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage, - mLastHttpGetStatus); - if (mRawImage.notNull()) sRawCount++; - if (mAuxRawImage.notNull()) - { - mHasAux = TRUE; - sAuxCount++; - } - if (finished) - { - mIsFetching = FALSE; + // Sets mRawDiscardLevel, mRawImage, mAuxRawImage + S32 fetch_discard = current_discard; + + if (mRawImage.notNull()) sRawCount--; + if (mAuxRawImage.notNull()) sAuxCount--; + // keep in mind that fetcher still might need raw image, don't modify original + bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage, + mLastHttpGetStatus); + if (mRawImage.notNull()) sRawCount++; + if (mAuxRawImage.notNull()) + { + mHasAux = TRUE; + sAuxCount++; + } + if (finished) + { + mIsFetching = FALSE; mLastFetchState = -1; - mLastPacketTimer.reset(); - } - else - { - mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); - } - - // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) - if (mRawImage.notNull()) - { + mLastPacketTimer.reset(); + } + else + { + mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); + } + + // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) + if (mRawImage.notNull()) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image"); - LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); - if (tester) - { - mIsFetched = TRUE; - tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); - } - mRawDiscardLevel = fetch_discard; - if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && - (current_discard < 0 || mRawDiscardLevel < current_discard)) - { + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); + if (tester) + { + mIsFetched = TRUE; + tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); + } + mRawDiscardLevel = fetch_discard; + if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && + (current_discard < 0 || mRawDiscardLevel < current_discard)) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good"); - mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; - mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; - setTexelsPerImage(); - - if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) - { - //discard all oversized textures. - destroyRawImage(); - LL_WARNS() << "oversize, setting as missing" << LL_ENDL; - setIsMissingAsset(); - mRawDiscardLevel = INVALID_DISCARD_LEVEL; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - } - else - { - mIsRawImageValid = TRUE; - addToCreateTexture(); - } + mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; + mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; + setTexelsPerImage(); + + if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) + { + //discard all oversized textures. + destroyRawImage(); + LL_WARNS() << "oversize, setting as missing" << LL_ENDL; + setIsMissingAsset(); + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + } + else + { + mIsRawImageValid = TRUE; + addToCreateTexture(); + } if (mBoostLevel == LLGLTexture::BOOST_ICON) { @@ -1951,802 +1951,802 @@ bool LLViewerFetchedTexture::updateFetch() } } - return TRUE; - } - else - { + return TRUE; + } + else + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed"); - // Data is ready but we don't need it - // (received it already while fetcher was writing to disk) - destroyRawImage(); - return false; // done - } - } - - if (!mIsFetching) - { - if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) - { - // We finished but received no data - if (getDiscardLevel() < 0) - { - if (getFTType() != FTT_MAP_TILE) - { - LL_WARNS() << mID - << " Fetch failure, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << " stats " << mLastHttpGetStatus.toHex() - << LL_ENDL; - } - setIsMissingAsset(); - desired_discard = -1; - } - else - { - //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; - if(current_discard >= 0) - { - mMinDiscardLevel = current_discard; - //desired_discard = current_discard; - } - else - { - S32 dis_level = getDiscardLevel(); - mMinDiscardLevel = dis_level; - //desired_discard = dis_level; - } - } - destroyRawImage(); - } - else if (mRawImage.notNull()) - { - // We have data, but our fetch failed to return raw data - // *TODO: FIgure out why this is happening and fix it - destroyRawImage(); - } - } - else - { - static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f. - if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME) - { - mStopFetchingTimer.reset(); - LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); - } - } - } + // Data is ready but we don't need it + // (received it already while fetcher was writing to disk) + destroyRawImage(); + return false; // done + } + } + + if (!mIsFetching) + { + if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) + { + // We finished but received no data + if (getDiscardLevel() < 0) + { + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mID + << " Fetch failure, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() + << LL_ENDL; + } + setIsMissingAsset(); + desired_discard = -1; + } + else + { + //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; + if(current_discard >= 0) + { + mMinDiscardLevel = current_discard; + //desired_discard = current_discard; + } + else + { + S32 dis_level = getDiscardLevel(); + mMinDiscardLevel = dis_level; + //desired_discard = dis_level; + } + } + destroyRawImage(); + } + else if (mRawImage.notNull()) + { + // We have data, but our fetch failed to return raw data + // *TODO: FIgure out why this is happening and fix it + destroyRawImage(); + } + } + else + { + static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f. + if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME) + { + mStopFetchingTimer.reset(); + LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); + } + } + } desired_discard = llmin(desired_discard, getMaxDiscardLevel()); - bool make_request = true; - if (decode_priority <= 0) - { + bool make_request = true; + if (decode_priority <= 0) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - priority <= 0"); - make_request = false; - } - else if(mDesiredDiscardLevel > getMaxDiscardLevel()) - { + make_request = false; + } + else if(mDesiredDiscardLevel > getMaxDiscardLevel()) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - desired > max"); - make_request = false; - } - else if (mNeedsCreateTexture || mIsMissingAsset) - { + make_request = false; + } + else if (mNeedsCreateTexture || mIsMissingAsset) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - create or missing"); - make_request = false; - } - else if (current_discard >= 0 && current_discard <= mMinDiscardLevel) - { + make_request = false; + } + else if (current_discard >= 0 && current_discard <= mMinDiscardLevel) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min"); - make_request = false; - } - else if(mCachedRawImage.notNull() // can be empty - && mCachedRawImageReady - && (current_discard < 0 || current_discard > mCachedRawDiscardLevel)) - { - make_request = false; - switchToCachedImage(); //use the cached raw data first - } - - if (make_request) - { - if (mIsFetching) - { + make_request = false; + } + else if(mCachedRawImage.notNull() // can be empty + && mCachedRawImageReady + && (current_discard < 0 || current_discard > mCachedRawDiscardLevel)) + { + make_request = false; + switchToCachedImage(); //use the cached raw data first + } + + if (make_request) + { + if (mIsFetching) + { // already requested a higher resolution mip - if (mRequestedDiscardLevel <= desired_discard) - { + if (mRequestedDiscardLevel <= desired_discard) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - requested < desired"); - make_request = false; - } - } - else - { + make_request = false; + } + } + else + { // already at a higher resolution mip, don't discard - if (current_discard >= 0 && current_discard <= desired_discard) - { + if (current_discard >= 0 && current_discard <= desired_discard) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current <= desired"); - make_request = false; - } - } - } - - if (make_request) - { + make_request = false; + } + } + } + + if (make_request) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - make request"); - S32 w=0, h=0, c=0; - if (getDiscardLevel() >= 0) - { - w = mGLTexturep->getWidth(0); - h = mGLTexturep->getHeight(0); - c = mComponents; - } - - const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); - if (override_tex_discard_level != 0) - { - desired_discard = override_tex_discard_level; - } - - // bypass texturefetch directly by pulling from LLTextureCache - S32 fetch_request_discard = -1; + S32 w=0, h=0, c=0; + if (getDiscardLevel() >= 0) + { + w = mGLTexturep->getWidth(0); + h = mGLTexturep->getHeight(0); + c = mComponents; + } + + const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + if (override_tex_discard_level != 0) + { + desired_discard = override_tex_discard_level; + } + + // bypass texturefetch directly by pulling from LLTextureCache + S32 fetch_request_discard = -1; fetch_request_discard = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux(), mCanUseHTTP); - - if (fetch_request_discard >= 0) - { + w, h, c, desired_discard, needsAux(), mCanUseHTTP); + + if (fetch_request_discard >= 0) + { LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created"); - mHasFetcher = TRUE; - mIsFetching = TRUE; + mHasFetcher = TRUE; + mIsFetching = TRUE; // in some cases createRequest can modify discard, as an example // bake textures are always at discard 0 mRequestedDiscardLevel = llmin(desired_discard, fetch_request_discard); - mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); - } + mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); + } // If createRequest() failed, that means one of two things: // 1. We're finishing up a request for this UUID, so we // should wait for it to complete // 2. We've failed a request for this UUID, so there is // no need to create another request - } - else if (mHasFetcher && !mIsFetching) - { - // Only delete requests that haven't received any network data - // for a while. Note - this is the normal mechanism for - // deleting requests, not just a place to handle timeouts. - const F32 FETCH_IDLE_TIME = 0.1f; - if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) - { - LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL; - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - } - } - - return mIsFetching ? true : false; + } + else if (mHasFetcher && !mIsFetching) + { + // Only delete requests that haven't received any network data + // for a while. Note - this is the normal mechanism for + // deleting requests, not just a place to handle timeouts. + const F32 FETCH_IDLE_TIME = 0.1f; + if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) + { + LL_DEBUGS("Texture") << "exceeded idle time " << FETCH_IDLE_TIME << ", deleting request: " << getID() << LL_ENDL; + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + } + } + + return mIsFetching ? true : false; } void LLViewerFetchedTexture::clearFetchedResults() { - if(mNeedsCreateTexture || mIsFetching) - { - return; - } - - cleanup(); - destroyGLTexture(); + if(mNeedsCreateTexture || mIsFetching) + { + return; + } + + cleanup(); + destroyGLTexture(); - if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate - { - mGLTexturep->forceToInvalidateGLTexture(); - } + if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate + { + mGLTexturep->forceToInvalidateGLTexture(); + } } void LLViewerFetchedTexture::forceToDeleteRequest() { - if (mHasFetcher) - { - mHasFetcher = FALSE; - mIsFetching = FALSE; - } - - resetTextureStats(); + if (mHasFetcher) + { + mHasFetcher = FALSE; + mIsFetching = FALSE; + } - mDesiredDiscardLevel = getMaxDiscardLevel() + 1; + resetTextureStats(); + + mDesiredDiscardLevel = getMaxDiscardLevel() + 1; } void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) { - if (is_missing == mIsMissingAsset) - { - return; - } - if (is_missing) - { - if (mUrl.empty()) - { - LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; - } - else - { - // This may or may not be an error - it is normal to have no - // map tile on an empty region, but bad if we're failing on a - // server bake texture. - if (getFTType() != FTT_MAP_TILE) - { - LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; - } - } - if (mHasFetcher) - { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - mFetchState = 0; - mFetchPriority = 0; - } - } - else - { - LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL; - } - mIsMissingAsset = is_missing; + if (is_missing == mIsMissingAsset) + { + return; + } + if (is_missing) + { + if (mUrl.empty()) + { + LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; + } + else + { + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; + } + } + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + mFetchState = 0; + mFetchPriority = 0; + } + } + else + { + LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL; + } + mIsMissingAsset = is_missing; } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, - S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata, - LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause) -{ - // - // Don't do ANYTHING here, just add it to the global callback list - // - if (mLoadedCallbackList.empty()) - { - // Put in list to call this->doLoadedCallbacks() periodically - gTextureList.mCallbackList.insert(this); - mLoadedCallbackDesiredDiscardLevel = (S8)discard_level; - } - else - { - mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level); - } - - if(mPauseLoadedCallBacks) - { - if(!pause) - { - unpauseLoadedCallbacks(src_callback_list); - } - } - else if(pause) - { - pauseLoadedCallbacks(src_callback_list); - } - - LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause); - mLoadedCallbackList.push_back(entryp); - - mNeedsAux |= needs_aux; - if(keep_imageraw) - { - mSaveRawImage = TRUE; - } - if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) - { - if(mHasAux) - { - //trigger a refetch - forceToRefetchTexture(); - } - else - { - // We need aux data, but we've already loaded the image, and it didn't have any - LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; - } - } - mLastCallBackActiveTime = sCurrentTime ; + S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata, + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause) +{ + // + // Don't do ANYTHING here, just add it to the global callback list + // + if (mLoadedCallbackList.empty()) + { + // Put in list to call this->doLoadedCallbacks() periodically + gTextureList.mCallbackList.insert(this); + mLoadedCallbackDesiredDiscardLevel = (S8)discard_level; + } + else + { + mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level); + } + + if(mPauseLoadedCallBacks) + { + if(!pause) + { + unpauseLoadedCallbacks(src_callback_list); + } + } + else if(pause) + { + pauseLoadedCallbacks(src_callback_list); + } + + LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause); + mLoadedCallbackList.push_back(entryp); + + mNeedsAux |= needs_aux; + if(keep_imageraw) + { + mSaveRawImage = TRUE; + } + if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) + { + if(mHasAux) + { + //trigger a refetch + forceToRefetchTexture(); + } + else + { + // We need aux data, but we've already loaded the image, and it didn't have any + LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; + } + } + mLastCallBackActiveTime = sCurrentTime ; mLastReferencedSavedRawImageTime = sCurrentTime; } void LLViewerFetchedTexture::clearCallbackEntryList() { - if(mLoadedCallbackList.empty()) - { - return; - } - - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter; - - // We never finished loading the image. Indicate failure. - // Note: this allows mLoadedCallbackUserData to be cleaned up. - entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); - iter = mLoadedCallbackList.erase(iter); - delete entryp; - } - gTextureList.mCallbackList.erase(this); - - mLoadedCallbackDesiredDiscardLevel = S8_MAX; - if(needsToSaveRawImage()) - { - destroySavedRawImage(); - } - - return; + if(mLoadedCallbackList.empty()) + { + return; + } + + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter; + + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); + iter = mLoadedCallbackList.erase(iter); + delete entryp; + } + gTextureList.mCallbackList.erase(this); + + mLoadedCallbackDesiredDiscardLevel = S8_MAX; + if(needsToSaveRawImage()) + { + destroySavedRawImage(); + } + + return; } void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) { - if(mLoadedCallbackList.empty() || !callback_list) - { - return; - } - - S32 desired_discard = S8_MAX; - S32 desired_raw_discard = INVALID_DISCARD_LEVEL; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter; - if(entryp->mSourceCallbackList == callback_list) - { - // We never finished loading the image. Indicate failure. - // Note: this allows mLoadedCallbackUserData to be cleaned up. - entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); - iter = mLoadedCallbackList.erase(iter); - delete entryp; - } - else - { - ++iter; - - desired_discard = llmin(desired_discard, entryp->mDesiredDiscard); - if(entryp->mNeedsImageRaw) - { - desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard); - } - } - } - - mLoadedCallbackDesiredDiscardLevel = desired_discard; - if (mLoadedCallbackList.empty()) - { - // If we have no callbacks, take us off of the image callback list. - gTextureList.mCallbackList.erase(this); - - if(needsToSaveRawImage()) - { - destroySavedRawImage(); - } - } - else if(needsToSaveRawImage() && mBoostLevel != LLGLTexture::BOOST_PREVIEW) - { - if(desired_raw_discard != INVALID_DISCARD_LEVEL) - { - mDesiredSavedRawDiscardLevel = desired_raw_discard; - } - else - { - destroySavedRawImage(); - } - } + if(mLoadedCallbackList.empty() || !callback_list) + { + return; + } + + S32 desired_discard = S8_MAX; + S32 desired_raw_discard = INVALID_DISCARD_LEVEL; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter; + if(entryp->mSourceCallbackList == callback_list) + { + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); + iter = mLoadedCallbackList.erase(iter); + delete entryp; + } + else + { + ++iter; + + desired_discard = llmin(desired_discard, entryp->mDesiredDiscard); + if(entryp->mNeedsImageRaw) + { + desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard); + } + } + } + + mLoadedCallbackDesiredDiscardLevel = desired_discard; + if (mLoadedCallbackList.empty()) + { + // If we have no callbacks, take us off of the image callback list. + gTextureList.mCallbackList.erase(this); + + if(needsToSaveRawImage()) + { + destroySavedRawImage(); + } + } + else if(needsToSaveRawImage() && mBoostLevel != LLGLTexture::BOOST_PREVIEW) + { + if(desired_raw_discard != INVALID_DISCARD_LEVEL) + { + mDesiredSavedRawDiscardLevel = desired_raw_discard; + } + else + { + destroySavedRawImage(); + } + } } void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) { - if(!callback_list) -{ - mPauseLoadedCallBacks = FALSE; - return; - } - - BOOL need_raw = FALSE; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - if(entryp->mSourceCallbackList == callback_list) - { - entryp->mPaused = FALSE; - if(entryp->mNeedsImageRaw) - { - need_raw = TRUE; - } - } - } - mPauseLoadedCallBacks = FALSE ; - mLastCallBackActiveTime = sCurrentTime ; - mForceCallbackFetch = TRUE; - if(need_raw) - { - mSaveRawImage = TRUE; - } + if(!callback_list) +{ + mPauseLoadedCallBacks = FALSE; + return; + } + + BOOL need_raw = FALSE; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + if(entryp->mSourceCallbackList == callback_list) + { + entryp->mPaused = FALSE; + if(entryp->mNeedsImageRaw) + { + need_raw = TRUE; + } + } + } + mPauseLoadedCallBacks = FALSE ; + mLastCallBackActiveTime = sCurrentTime ; + mForceCallbackFetch = TRUE; + if(need_raw) + { + mSaveRawImage = TRUE; + } } void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) { - if(!callback_list) + if(!callback_list) { - return; - } + return; + } - bool paused = true; + bool paused = true; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - if(entryp->mSourceCallbackList == callback_list) - { - entryp->mPaused = TRUE; - } - else if(!entryp->mPaused) - { - paused = false; - } - } + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + if(entryp->mSourceCallbackList == callback_list) + { + entryp->mPaused = TRUE; + } + else if(!entryp->mPaused) + { + paused = false; + } + } - if(paused) - { - mPauseLoadedCallBacks = TRUE;//when set, loaded callback is paused. - resetTextureStats(); - mSaveRawImage = FALSE; - } + if(paused) + { + mPauseLoadedCallBacks = TRUE;//when set, loaded callback is paused. + resetTextureStats(); + mSaveRawImage = FALSE; + } } bool LLViewerFetchedTexture::doLoadedCallbacks() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds - static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds - - if (mNeedsCreateTexture) - { - return false; - } - if(mPauseLoadedCallBacks) - { - destroyRawImage(); - return false; //paused - } - if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching) - { - if (mFTType == FTT_SERVER_BAKE) - { - //output some debug info - LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL; - LL_INFOS() << mUrl << LL_ENDL; - LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << - " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << mMaxVirtualSize << LL_ENDL; - } - - clearCallbackEntryList() ; //remove all callbacks. - return false ; - } - - bool res = false; - - if (isMissingAsset()) - { - if (mFTType == FTT_SERVER_BAKE) - { - //output some debug info - LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL; - LL_INFOS() << mUrl << LL_ENDL; - } - - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - // We never finished loading the image. Indicate failure. - // Note: this allows mLoadedCallbackUserData to be cleaned up. - entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); - delete entryp; - } - mLoadedCallbackList.clear(); - - // Remove ourself from the global list of textures with callbacks - gTextureList.mCallbackList.erase(this); - return false; - } - - S32 gl_discard = getDiscardLevel(); - - // If we don't have a legit GL image, set it to be lower than the worst discard level - if (gl_discard == -1) - { - gl_discard = MAX_DISCARD_LEVEL + 1; - } - - // - // Determine the quality levels of textures that we can provide to callbacks - // and whether we need to do decompression/readback to get it - // - S32 current_raw_discard = MAX_DISCARD_LEVEL + 1; // We can always do a readback to get a raw discard - S32 best_raw_discard = gl_discard; // Current GL quality level - S32 current_aux_discard = MAX_DISCARD_LEVEL + 1; - S32 best_aux_discard = MAX_DISCARD_LEVEL + 1; - - if (mIsRawImageValid) - { - // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels. - best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel); - best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw - current_aux_discard = llmin(current_aux_discard, best_aux_discard); - } - else - { - // We have no data at all, we need to get it - // Do this by forcing the best aux discard to be 0. - best_aux_discard = 0; - } - - - // - // See if any of the callbacks would actually run using the data that we can provide, - // and also determine if we need to perform any readbacks or decodes. - // - bool run_gl_callbacks = false; - bool run_raw_callbacks = false; - bool need_readback = false; - - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - - if (entryp->mNeedsImageRaw) - { - if (mNeedsAux) - { - // - // Need raw and auxiliary channels - // - if (entryp->mLastUsedDiscard > current_aux_discard) - { - // We have useful data, run the callbacks - run_raw_callbacks = true; - } - } - else - { - if (entryp->mLastUsedDiscard > current_raw_discard) - { - // We have useful data, just run the callbacks - run_raw_callbacks = true; - } - else if (entryp->mLastUsedDiscard > best_raw_discard) - { - // We can readback data, and then run the callbacks - need_readback = true; - run_raw_callbacks = true; - } - } - } - else - { - // Needs just GL - if (entryp->mLastUsedDiscard > gl_discard) - { - // We have enough data, run this callback requiring GL data - run_gl_callbacks = true; - } - } - } - - // - // Do a readback if required, OR start off a texture decode - // - if (need_readback && (getMaxDiscardLevel() > gl_discard)) - { - // Do a readback to get the GL data into the raw image - // We have GL data. - - destroyRawImage(); - reloadRawImage(mLoadedCallbackDesiredDiscardLevel); - llassert(mRawImage.notNull()); - llassert(!mNeedsAux || mAuxRawImage.notNull()); - } - - // - // Run raw/auxiliary data callbacks - // - if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel())) - { - // Do callbacks which require raw image data. - //LL_INFOS() << "doLoadedCallbacks raw for " << getID() << LL_ENDL; - - // Call each party interested in the raw data. - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLLoadedCallbackEntry *entryp = *curiter; - if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel)) - { - // If we've loaded all the data there is to load or we've loaded enough - // to satisfy the interested party, then this is the last time that - // we're going to call them. - - mLastCallBackActiveTime = sCurrentTime; - if(mNeedsAux && mAuxRawImage.isNull()) - { - LL_WARNS() << "Raw Image with no Aux Data for callback" << LL_ENDL; - } - BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE; - //LL_INFOS() << "Running callback for " << getID() << LL_ENDL; - //LL_INFOS() << mRawImage->getWidth() << "x" << mRawImage->getHeight() << LL_ENDL; - entryp->mLastUsedDiscard = mRawDiscardLevel; - entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); - if (final) - { - iter = mLoadedCallbackList.erase(curiter); - delete entryp; - } - res = true; - } - } - } - - // - // Run GL callbacks - // - if (run_gl_callbacks && (gl_discard <= getMaxDiscardLevel())) - { - //LL_INFOS() << "doLoadedCallbacks GL for " << getID() << LL_ENDL; - - // Call the callbacks interested in GL data. - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLLoadedCallbackEntry *entryp = *curiter; - if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard)) - { - mLastCallBackActiveTime = sCurrentTime; - BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE; - entryp->mLastUsedDiscard = gl_discard; - entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData); - if (final) - { - iter = mLoadedCallbackList.erase(curiter); - delete entryp; - } - res = true; - } - } - } - - // Done with any raw image data at this point (will be re-created if we still have callbacks) - destroyRawImage(); - - // - // If we have no callbacks, take us off of the image callback list. - // - if (mLoadedCallbackList.empty()) - { - gTextureList.mCallbackList.erase(this); - } - else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching) - { - //wait for long enough but no fetching request issued, force one. - forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f); - mForceCallbackFetch = FALSE; //fire once. - } - - return res; + static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds + static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds + + if (mNeedsCreateTexture) + { + return false; + } + if(mPauseLoadedCallBacks) + { + destroyRawImage(); + return false; //paused + } + if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching) + { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << + " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << mMaxVirtualSize << LL_ENDL; + } + + clearCallbackEntryList() ; //remove all callbacks. + return false ; + } + + bool res = false; + + if (isMissingAsset()) + { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + } + + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); + delete entryp; + } + mLoadedCallbackList.clear(); + + // Remove ourself from the global list of textures with callbacks + gTextureList.mCallbackList.erase(this); + return false; + } + + S32 gl_discard = getDiscardLevel(); + + // If we don't have a legit GL image, set it to be lower than the worst discard level + if (gl_discard == -1) + { + gl_discard = MAX_DISCARD_LEVEL + 1; + } + + // + // Determine the quality levels of textures that we can provide to callbacks + // and whether we need to do decompression/readback to get it + // + S32 current_raw_discard = MAX_DISCARD_LEVEL + 1; // We can always do a readback to get a raw discard + S32 best_raw_discard = gl_discard; // Current GL quality level + S32 current_aux_discard = MAX_DISCARD_LEVEL + 1; + S32 best_aux_discard = MAX_DISCARD_LEVEL + 1; + + if (mIsRawImageValid) + { + // If we have an existing raw image, we have a baseline for the raw and auxiliary quality levels. + best_raw_discard = llmin(best_raw_discard, mRawDiscardLevel); + best_aux_discard = llmin(best_aux_discard, mRawDiscardLevel); // We always decode the aux when we decode the base raw + current_aux_discard = llmin(current_aux_discard, best_aux_discard); + } + else + { + // We have no data at all, we need to get it + // Do this by forcing the best aux discard to be 0. + best_aux_discard = 0; + } + + + // + // See if any of the callbacks would actually run using the data that we can provide, + // and also determine if we need to perform any readbacks or decodes. + // + bool run_gl_callbacks = false; + bool run_raw_callbacks = false; + bool need_readback = false; + + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + + if (entryp->mNeedsImageRaw) + { + if (mNeedsAux) + { + // + // Need raw and auxiliary channels + // + if (entryp->mLastUsedDiscard > current_aux_discard) + { + // We have useful data, run the callbacks + run_raw_callbacks = true; + } + } + else + { + if (entryp->mLastUsedDiscard > current_raw_discard) + { + // We have useful data, just run the callbacks + run_raw_callbacks = true; + } + else if (entryp->mLastUsedDiscard > best_raw_discard) + { + // We can readback data, and then run the callbacks + need_readback = true; + run_raw_callbacks = true; + } + } + } + else + { + // Needs just GL + if (entryp->mLastUsedDiscard > gl_discard) + { + // We have enough data, run this callback requiring GL data + run_gl_callbacks = true; + } + } + } + + // + // Do a readback if required, OR start off a texture decode + // + if (need_readback && (getMaxDiscardLevel() > gl_discard)) + { + // Do a readback to get the GL data into the raw image + // We have GL data. + + destroyRawImage(); + reloadRawImage(mLoadedCallbackDesiredDiscardLevel); + llassert(mRawImage.notNull()); + llassert(!mNeedsAux || mAuxRawImage.notNull()); + } + + // + // Run raw/auxiliary data callbacks + // + if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel())) + { + // Do callbacks which require raw image data. + //LL_INFOS() << "doLoadedCallbacks raw for " << getID() << LL_ENDL; + + // Call each party interested in the raw data. + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + callback_list_t::iterator curiter = iter++; + LLLoadedCallbackEntry *entryp = *curiter; + if (entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > mRawDiscardLevel)) + { + // If we've loaded all the data there is to load or we've loaded enough + // to satisfy the interested party, then this is the last time that + // we're going to call them. + + mLastCallBackActiveTime = sCurrentTime; + if(mNeedsAux && mAuxRawImage.isNull()) + { + LL_WARNS() << "Raw Image with no Aux Data for callback" << LL_ENDL; + } + BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE; + //LL_INFOS() << "Running callback for " << getID() << LL_ENDL; + //LL_INFOS() << mRawImage->getWidth() << "x" << mRawImage->getHeight() << LL_ENDL; + entryp->mLastUsedDiscard = mRawDiscardLevel; + entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); + if (final) + { + iter = mLoadedCallbackList.erase(curiter); + delete entryp; + } + res = true; + } + } + } + + // + // Run GL callbacks + // + if (run_gl_callbacks && (gl_discard <= getMaxDiscardLevel())) + { + //LL_INFOS() << "doLoadedCallbacks GL for " << getID() << LL_ENDL; + + // Call the callbacks interested in GL data. + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + callback_list_t::iterator curiter = iter++; + LLLoadedCallbackEntry *entryp = *curiter; + if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard)) + { + mLastCallBackActiveTime = sCurrentTime; + BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE; + entryp->mLastUsedDiscard = gl_discard; + entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData); + if (final) + { + iter = mLoadedCallbackList.erase(curiter); + delete entryp; + } + res = true; + } + } + } + + // Done with any raw image data at this point (will be re-created if we still have callbacks) + destroyRawImage(); + + // + // If we have no callbacks, take us off of the image callback list. + // + if (mLoadedCallbackList.empty()) + { + gTextureList.mCallbackList.erase(this); + } + else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching) + { + //wait for long enough but no fetching request issued, force one. + forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f); + mForceCallbackFetch = FALSE; //fire once. + } + + return res; } //virtual void LLViewerFetchedTexture::forceImmediateUpdate() { - //only immediately update a deleted texture which is now being re-used. - if(!isDeleted()) - { - return; - } - //if already called forceImmediateUpdate() - if(mInImageList && mMaxVirtualSize == LLViewerFetchedTexture::sMaxVirtualSize) - { - return; - } + //only immediately update a deleted texture which is now being re-used. + if(!isDeleted()) + { + return; + } + //if already called forceImmediateUpdate() + if(mInImageList && mMaxVirtualSize == LLViewerFetchedTexture::sMaxVirtualSize) + { + return; + } - gTextureList.forceImmediateUpdate(this); - return; + gTextureList.forceImmediateUpdate(this); + return; } LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) { - llassert(mGLTexturep.notNull()); - llassert(discard_level >= 0); - llassert(mComponents > 0); + llassert(mGLTexturep.notNull()); + llassert(discard_level >= 0); + llassert(mComponents > 0); - if (mRawImage.notNull()) - { - //mRawImage is in use by somebody else, do not delete it. - return NULL; - } + if (mRawImage.notNull()) + { + //mRawImage is in use by somebody else, do not delete it. + return NULL; + } - if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) - { - if (mSavedRawDiscardLevel != discard_level + if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) + { + if (mSavedRawDiscardLevel != discard_level && mBoostLevel != BOOST_ICON && mBoostLevel != BOOST_THUMBNAIL) - { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); - mRawImage->copy(getSavedRawImage()); - } - else - { - mRawImage = getSavedRawImage(); - } - mRawDiscardLevel = discard_level; - } - else - { - //force to fetch raw image again if cached raw image is not good enough. - if(mCachedRawDiscardLevel > discard_level) - { - mRawImage = mCachedRawImage; - mRawDiscardLevel = mCachedRawDiscardLevel; - } - else //cached raw image is good enough, copy it. - { - if(mCachedRawDiscardLevel != discard_level) - { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); - mRawImage->copy(mCachedRawImage); - } - else - { - mRawImage = mCachedRawImage; - } - mRawDiscardLevel = discard_level; - } - } - mIsRawImageValid = TRUE; - sRawCount++; - - return mRawImage; + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); + mRawImage->copy(getSavedRawImage()); + } + else + { + mRawImage = getSavedRawImage(); + } + mRawDiscardLevel = discard_level; + } + else + { + //force to fetch raw image again if cached raw image is not good enough. + if(mCachedRawDiscardLevel > discard_level) + { + mRawImage = mCachedRawImage; + mRawDiscardLevel = mCachedRawDiscardLevel; + } + else //cached raw image is good enough, copy it. + { + if(mCachedRawDiscardLevel != discard_level) + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()); + mRawImage->copy(mCachedRawImage); + } + else + { + mRawImage = mCachedRawImage; + } + mRawDiscardLevel = discard_level; + } + } + mIsRawImageValid = TRUE; + sRawCount++; + + return mRawImage; } bool LLViewerFetchedTexture::needsToSaveRawImage() { - return mForceToSaveRawImage || mSaveRawImage; + return mForceToSaveRawImage || mSaveRawImage; } void LLViewerFetchedTexture::destroyRawImage() -{ +{ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if (mAuxRawImage.notNull() && !needsToSaveRawImage()) - { - sAuxCount--; - mAuxRawImage = NULL; - } - - if (mRawImage.notNull()) - { - sRawCount--; - - if(mIsRawImageValid) - { - if(needsToSaveRawImage()) - { - saveRawImage(); - } - setCachedRawImage(); - } - - mRawImage = NULL; - - mIsRawImageValid = FALSE; - mRawDiscardLevel = INVALID_DISCARD_LEVEL; - } + if (mAuxRawImage.notNull() && !needsToSaveRawImage()) + { + sAuxCount--; + mAuxRawImage = NULL; + } + + if (mRawImage.notNull()) + { + sRawCount--; + + if(mIsRawImageValid) + { + if(needsToSaveRawImage()) + { + saveRawImage(); + } + setCachedRawImage(); + } + + mRawImage = NULL; + + mIsRawImageValid = FALSE; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + } } //use the mCachedRawImage to (re)generate the gl texture. @@ -2754,32 +2754,32 @@ void LLViewerFetchedTexture::destroyRawImage() void LLViewerFetchedTexture::switchToCachedImage() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(mCachedRawImage.notNull() && + if(mCachedRawImage.notNull() && !mNeedsCreateTexture) // <--- texture creation is pending, don't step on it - { - mRawImage = mCachedRawImage; - - if (getComponents() != mRawImage->getComponents()) - { - // We've changed the number of components, so we need to move any - // objects using this pool to a different pool. - mComponents = mRawImage->getComponents(); - mGLTexturep->setComponents(mComponents); - gTextureList.dirtyImage(this); - } - - mIsRawImageValid = TRUE; - mRawDiscardLevel = mCachedRawDiscardLevel; + { + mRawImage = mCachedRawImage; + + if (getComponents() != mRawImage->getComponents()) + { + // We've changed the number of components, so we need to move any + // objects using this pool to a different pool. + mComponents = mRawImage->getComponents(); + mGLTexturep->setComponents(mComponents); + gTextureList.dirtyImage(this); + } + + mIsRawImageValid = TRUE; + mRawDiscardLevel = mCachedRawDiscardLevel; scheduleCreateTexture(); - } + } } //cache the imageraw forcefully. -//virtual -void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) +//virtual +void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) { - if(imageraw != mRawImage.get()) + if(imageraw != mRawImage.get()) { if (mBoostLevel == LLGLTexture::BOOST_ICON) { @@ -2813,96 +2813,96 @@ void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* im { mCachedRawImage = imageraw; } - mCachedRawDiscardLevel = discard_level; - mCachedRawImageReady = TRUE; - } + mCachedRawDiscardLevel = discard_level; + mCachedRawImageReady = TRUE; + } } void LLViewerFetchedTexture::setCachedRawImage() -{ +{ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(mRawImage == mCachedRawImage) - { - return; - } - if(!mIsRawImageValid) - { - return; - } - - if(mCachedRawImageReady) - { - return; - } - - if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) - { - S32 i = 0; - S32 w = mRawImage->getWidth(); - S32 h = mRawImage->getHeight(); - - S32 max_size = MAX_CACHED_RAW_IMAGE_AREA; - if(LLGLTexture::BOOST_TERRAIN == mBoostLevel) - { - max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA; - } - if(mForSculpt) - { - max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA; - mCachedRawImageReady = !mRawDiscardLevel; - } - else - { - mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)); - } - - while(((w >> i) * (h >> i)) > max_size) - { - ++i; - } - - if(i) - { - if(!(w >> i) || !(h >> i)) - { - --i; - } - - { - //make a duplicate in case somebody else is using this raw image - mRawImage = mRawImage->scaled(w >> i, h >> i); - } - } - mCachedRawImage = mRawImage; - mRawDiscardLevel += i; - mCachedRawDiscardLevel = mRawDiscardLevel; - } + if(mRawImage == mCachedRawImage) + { + return; + } + if(!mIsRawImageValid) + { + return; + } + + if(mCachedRawImageReady) + { + return; + } + + if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) + { + S32 i = 0; + S32 w = mRawImage->getWidth(); + S32 h = mRawImage->getHeight(); + + S32 max_size = MAX_CACHED_RAW_IMAGE_AREA; + if(LLGLTexture::BOOST_TERRAIN == mBoostLevel) + { + max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA; + } + if(mForSculpt) + { + max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA; + mCachedRawImageReady = !mRawDiscardLevel; + } + else + { + mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)); + } + + while(((w >> i) * (h >> i)) > max_size) + { + ++i; + } + + if(i) + { + if(!(w >> i) || !(h >> i)) + { + --i; + } + + { + //make a duplicate in case somebody else is using this raw image + mRawImage = mRawImage->scaled(w >> i, h >> i); + } + } + mCachedRawImage = mRawImage; + mRawDiscardLevel += i; + mCachedRawDiscardLevel = mRawDiscardLevel; + } } void LLViewerFetchedTexture::checkCachedRawSculptImage() { - if(mCachedRawImageReady && mCachedRawDiscardLevel > 0) - { - if(getDiscardLevel() != 0) - { - mCachedRawImageReady = FALSE; - } - else if(isForSculptOnly()) - { - resetTextureStats(); //do not update this image any more. - } - } + if(mCachedRawImageReady && mCachedRawDiscardLevel > 0) + { + if(getDiscardLevel() != 0) + { + mCachedRawImageReady = FALSE; + } + else if(isForSculptOnly()) + { + resetTextureStats(); //do not update this image any more. + } + } } -void LLViewerFetchedTexture::saveRawImage() +void LLViewerFetchedTexture::saveRawImage() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel)) - { - return; - } + if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel)) + { + return; + } - mSavedRawDiscardLevel = mRawDiscardLevel; + mSavedRawDiscardLevel = mRawDiscardLevel; if (mBoostLevel == LLGLTexture::BOOST_ICON) { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; @@ -2936,102 +2936,102 @@ void LLViewerFetchedTexture::saveRawImage() mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()); } - if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) - { - mForceToSaveRawImage = FALSE; - } + if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) + { + mForceToSaveRawImage = FALSE; + } - mLastReferencedSavedRawImageTime = sCurrentTime; + mLastReferencedSavedRawImageTime = sCurrentTime; } -//force to refetch the texture to the discard level +//force to refetch the texture to the discard level void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time) { - if(mForceToSaveRawImage) - { - desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel); - kept_time = llmax(kept_time, mKeptSavedRawImageTime); - } - - //trigger a new fetch. - mForceToSaveRawImage = TRUE ; - mDesiredSavedRawDiscardLevel = desired_discard ; - mKeptSavedRawImageTime = kept_time ; - mLastReferencedSavedRawImageTime = sCurrentTime ; - mSavedRawImage = NULL ; - mSavedRawDiscardLevel = -1 ; -} - -void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) -{ - mKeptSavedRawImageTime = kept_time; - mLastReferencedSavedRawImageTime = sCurrentTime; - - if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard) - { - return; //raw imge is ready. - } - - if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard) - { - mForceToSaveRawImage = TRUE; - mDesiredSavedRawDiscardLevel = desired_discard; - - //copy from the cached raw image if exists. - if(mCachedRawImage.notNull() && mRawImage.isNull() ) - { - mRawImage = mCachedRawImage; - mRawDiscardLevel = mCachedRawDiscardLevel; - - saveRawImage(); - - mRawImage = NULL; - mRawDiscardLevel = INVALID_DISCARD_LEVEL; - } - } + if(mForceToSaveRawImage) + { + desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel); + kept_time = llmax(kept_time, mKeptSavedRawImageTime); + } + + //trigger a new fetch. + mForceToSaveRawImage = TRUE ; + mDesiredSavedRawDiscardLevel = desired_discard ; + mKeptSavedRawImageTime = kept_time ; + mLastReferencedSavedRawImageTime = sCurrentTime ; + mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1 ; +} + +void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) +{ + mKeptSavedRawImageTime = kept_time; + mLastReferencedSavedRawImageTime = sCurrentTime; + + if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard) + { + return; //raw imge is ready. + } + + if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard) + { + mForceToSaveRawImage = TRUE; + mDesiredSavedRawDiscardLevel = desired_discard; + + //copy from the cached raw image if exists. + if(mCachedRawImage.notNull() && mRawImage.isNull() ) + { + mRawImage = mCachedRawImage; + mRawDiscardLevel = mCachedRawDiscardLevel; + + saveRawImage(); + + mRawImage = NULL; + mRawDiscardLevel = INVALID_DISCARD_LEVEL; + } + } } void LLViewerFetchedTexture::destroySavedRawImage() { - if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime) - { - return; //keep the saved raw image. - } + if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime) + { + return; //keep the saved raw image. + } + + mForceToSaveRawImage = FALSE; + mSaveRawImage = FALSE; + + clearCallbackEntryList(); - mForceToSaveRawImage = FALSE; - mSaveRawImage = FALSE; + mSavedRawImage = NULL ; + mForceToSaveRawImage = FALSE ; + mSaveRawImage = FALSE ; + mSavedRawDiscardLevel = -1 ; + mDesiredSavedRawDiscardLevel = -1 ; + mLastReferencedSavedRawImageTime = 0.0f ; + mKeptSavedRawImageTime = 0.f ; - clearCallbackEntryList(); - - mSavedRawImage = NULL ; - mForceToSaveRawImage = FALSE ; - mSaveRawImage = FALSE ; - mSavedRawDiscardLevel = -1 ; - mDesiredSavedRawDiscardLevel = -1 ; - mLastReferencedSavedRawImageTime = 0.0f ; - mKeptSavedRawImageTime = 0.f ; - - if(mAuxRawImage.notNull()) - { - sAuxCount--; - mAuxRawImage = NULL; - } + if(mAuxRawImage.notNull()) + { + sAuxCount--; + mAuxRawImage = NULL; + } } -LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() +LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() { - mLastReferencedSavedRawImageTime = sCurrentTime; + mLastReferencedSavedRawImageTime = sCurrentTime; - return mSavedRawImage; + return mSavedRawImage; } - + BOOL LLViewerFetchedTexture::hasSavedRawImage() const { - return mSavedRawImage.notNull(); + return mSavedRawImage.notNull(); } - + F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const -{ - return sCurrentTime - mLastReferencedSavedRawImageTime; +{ + return sCurrentTime - mLastReferencedSavedRawImageTime; } //---------------------------------------------------------------------------------------------- @@ -3042,33 +3042,33 @@ F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) - : LLViewerFetchedTexture(id, f_type, host, usemipmaps) + : LLViewerFetchedTexture(id, f_type, host, usemipmaps) { - init(TRUE); + init(TRUE); } LLViewerLODTexture::LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(url, f_type, id, usemipmaps) + : LLViewerFetchedTexture(url, f_type, id, usemipmaps) { - init(TRUE); + init(TRUE); } void LLViewerLODTexture::init(bool firstinit) { - mTexelsPerImage = 64.f*64.f; - mDiscardVirtualSize = 0.f; - mCalculatedDiscardLevel = -1.f; + mTexelsPerImage = 64.f*64.f; + mDiscardVirtualSize = 0.f; + mCalculatedDiscardLevel = -1.f; } -//virtual +//virtual S8 LLViewerLODTexture::getType() const { - return LLViewerTexture::LOD_TEXTURE; + return LLViewerTexture::LOD_TEXTURE; } bool LLViewerLODTexture::isUpdateFrozen() { - return LLViewerTexture::sFreezeImageUpdates; + return LLViewerTexture::sFreezeImageUpdates; } // This is gauranteed to get called periodically for every texture @@ -3076,9 +3076,9 @@ bool LLViewerLODTexture::isUpdateFrozen() void LLViewerLODTexture::processTextureStats() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - updateVirtualSize(); - - static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); + updateVirtualSize(); + + static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); { // restrict texture resolution to download based on RenderMaxTextureResolution static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); @@ -3088,26 +3088,26 @@ void LLViewerLODTexture::processTextureStats() mMaxVirtualSize = llmin(mMaxVirtualSize, tex_res); } - if (textures_fullres) - { - mDesiredDiscardLevel = 0; - } - // Generate the request priority and render priority - else if (mDontDiscard || !mUseMipMaps) - { - mDesiredDiscardLevel = 0; - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 - } - else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) - { - // If the image has not been significantly visible in a while, we don't want it - mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); - } - else if (!mFullWidth || !mFullHeight) - { - mDesiredDiscardLevel = getMaxDiscardLevel(); - } + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } + // Generate the request priority and render priority + else if (mDontDiscard || !mUseMipMaps) + { + mDesiredDiscardLevel = 0; + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 + } + else if (mBoostLevel < LLGLTexture::BOOST_HIGH && mMaxVirtualSize <= 10.f) + { + // If the image has not been significantly visible in a while, we don't want it + mDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)(MAX_DISCARD_LEVEL + 1)); + } + else if (!mFullWidth || !mFullHeight) + { + mDesiredDiscardLevel = getMaxDiscardLevel(); + } else { //static const F64 log_2 = log(2.0); @@ -3164,7 +3164,7 @@ void LLViewerLODTexture::processTextureStats() // S32 current_discard = getDiscardLevel(); - if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED && + if (mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED && current_discard >= 0) { if (current_discard < (mDesiredDiscardLevel-1) && !mForceToSaveRawImage) @@ -3173,19 +3173,19 @@ void LLViewerLODTexture::processTextureStats() } } - if (isUpdateFrozen() // we are out of memory and nearing max allowed bias - && mBoostLevel < LLGLTexture::BOOST_SCULPTED - && mDesiredDiscardLevel < current_discard) - { - // stop requesting more - mDesiredDiscardLevel = current_discard; - } - } + if (isUpdateFrozen() // we are out of memory and nearing max allowed bias + && mBoostLevel < LLGLTexture::BOOST_SCULPTED + && mDesiredDiscardLevel < current_discard) + { + // stop requesting more + mDesiredDiscardLevel = current_discard; + } + } - if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) - { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); - } + if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel); + } // decay max virtual size over time mMaxVirtualSize *= 0.8f; @@ -3200,19 +3200,19 @@ void LLViewerLODTexture::processTextureStats() bool LLViewerLODTexture::scaleDown() { - if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) - { - switchToCachedImage(); + if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) + { + switchToCachedImage(); - LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); - if (tester) - { - tester->setStablizingTime(); - } + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); + if (tester) + { + tester->setStablizingTime(); + } - return true; - } - return false; + return true; + } + return false; } //---------------------------------------------------------------------------------------------- //end of LLViewerLODTexture @@ -3225,182 +3225,182 @@ bool LLViewerLODTexture::scaleDown() void LLViewerMediaTexture::updateClass() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - static const F32 MAX_INACTIVE_TIME = 30.f; + static const F32 MAX_INACTIVE_TIME = 30.f; #if 0 - //force to play media. - gSavedSettings.setBOOL("AudioStreamingMedia", true); + //force to play media. + gSavedSettings.setBOOL("AudioStreamingMedia", true); #endif - for(media_map_t::iterator iter = sMediaMap.begin(); iter != sMediaMap.end(); ) - { - LLViewerMediaTexture* mediap = iter->second; - - if(mediap->getNumRefs() == 1) //one reference by sMediaMap - { - // - //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. - // - if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) - { - media_map_t::iterator cur = iter++; - sMediaMap.erase(cur); - continue; - } - } - ++iter; - } -} - -//static -void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) -{ - LLViewerMediaTexture* media_tex = findMediaTexture(media_id); - if(media_tex) - { - media_tex->invalidateMediaImpl(); - } + for(media_map_t::iterator iter = sMediaMap.begin(); iter != sMediaMap.end(); ) + { + LLViewerMediaTexture* mediap = iter->second; + + if(mediap->getNumRefs() == 1) //one reference by sMediaMap + { + // + //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. + // + if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + { + media_map_t::iterator cur = iter++; + sMediaMap.erase(cur); + continue; + } + } + ++iter; + } +} + +//static +void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) +{ + LLViewerMediaTexture* media_tex = findMediaTexture(media_id); + if(media_tex) + { + media_tex->invalidateMediaImpl(); + } } //static void LLViewerMediaTexture::cleanUpClass() { - sMediaMap.clear(); + sMediaMap.clear(); } //static LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media_id) { - media_map_t::iterator iter = sMediaMap.find(media_id); - if(iter == sMediaMap.end()) - { - return NULL; - } + media_map_t::iterator iter = sMediaMap.find(media_id); + if(iter == sMediaMap.end()) + { + return NULL; + } - LLViewerMediaTexture* media_tex = iter->second; - media_tex->setMediaImpl(); - media_tex->getLastReferencedTimer()->reset(); + LLViewerMediaTexture* media_tex = iter->second; + media_tex->setMediaImpl(); + media_tex->getLastReferencedTimer()->reset(); - return media_tex; + return media_tex; } -LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) - : LLViewerTexture(id, usemipmaps), - mMediaImplp(NULL), - mUpdateVirtualSizeTime(0) +LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) + : LLViewerTexture(id, usemipmaps), + mMediaImplp(NULL), + mUpdateVirtualSizeTime(0) { - sMediaMap.insert(std::make_pair(id, this)); + sMediaMap.insert(std::make_pair(id, this)); - mGLTexturep = gl_image; + mGLTexturep = gl_image; - if(mGLTexturep.isNull()) - { - generateGLTexture(); - } + if(mGLTexturep.isNull()) + { + generateGLTexture(); + } - mGLTexturep->setAllowCompression(false); + mGLTexturep->setAllowCompression(false); - mGLTexturep->setNeedsAlphaAndPickMask(FALSE); + mGLTexturep->setNeedsAlphaAndPickMask(FALSE); - mIsPlaying = FALSE; + mIsPlaying = FALSE; - setMediaImpl(); + setMediaImpl(); - setCategory(LLGLTexture::MEDIA); - - LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); - if(tex) //this media is a parcel media for tex. - { - tex->setParcelMedia(this); - } -} + setCategory(LLGLTexture::MEDIA); -//virtual -LLViewerMediaTexture::~LLViewerMediaTexture() -{ - LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); - if(tex) //this media is a parcel media for tex. - { - tex->setParcelMedia(NULL); - } + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(this); + } } -void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) +//virtual +LLViewerMediaTexture::~LLViewerMediaTexture() { - llassert(mGLTexturep.notNull()); + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(NULL); + } +} + +void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) +{ + llassert(mGLTexturep.notNull()); - mUseMipMaps = usemipmaps; - getLastReferencedTimer()->reset(); - mGLTexturep->setUseMipMaps(mUseMipMaps); - mGLTexturep->setNeedsAlphaAndPickMask(FALSE); + mUseMipMaps = usemipmaps; + getLastReferencedTimer()->reset(); + mGLTexturep->setUseMipMaps(mUseMipMaps); + mGLTexturep->setNeedsAlphaAndPickMask(FALSE); } -void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) +void LLViewerMediaTexture::setUseMipMaps(BOOL mipmap) { - mUseMipMaps = mipmap; + mUseMipMaps = mipmap; - if(mGLTexturep.notNull()) - { - mGLTexturep->setUseMipMaps(mipmap); - } + if(mGLTexturep.notNull()) + { + mGLTexturep->setUseMipMaps(mipmap); + } } -//virtual +//virtual S8 LLViewerMediaTexture::getType() const { - return LLViewerTexture::MEDIA_TEXTURE; + return LLViewerTexture::MEDIA_TEXTURE; } -void LLViewerMediaTexture::invalidateMediaImpl() +void LLViewerMediaTexture::invalidateMediaImpl() { - mMediaImplp = NULL; + mMediaImplp = NULL; } void LLViewerMediaTexture::setMediaImpl() { - if(!mMediaImplp) - { - mMediaImplp = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mID); - } + if(!mMediaImplp) + { + mMediaImplp = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mID); + } } //return true if all faces to reference to this media texture are found -//Note: mMediaFaceList is valid only for the current instant +//Note: mMediaFaceList is valid only for the current instant // because it does not check the face validity after the current frame. BOOL LLViewerMediaTexture::findFaces() -{ - mMediaFaceList.clear(); - - BOOL ret = TRUE; - - LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); - if(tex) //this media is a parcel media for tex. - { - for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) - { - const ll_face_list_t* face_list = tex->getFaceList(ch); - U32 end = tex->getNumFaces(ch); - for(U32 i = 0; i < end; i++) - { - if ((*face_list)[i]->isMediaAllowed()) - { - mMediaFaceList.push_back((*face_list)[i]); - } - } - } - } - - if(!mMediaImplp) - { - return TRUE; - } - - //for media on a face. - const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList(); - std::list< LLVOVolume* >::const_iterator iter = obj_list->begin(); - for(; iter != obj_list->end(); ++iter) - { - LLVOVolume* obj = *iter; +{ + mMediaFaceList.clear(); + + BOOL ret = TRUE; + + LLViewerTexture* tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); + if(tex) //this media is a parcel media for tex. + { + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + const ll_face_list_t* face_list = tex->getFaceList(ch); + U32 end = tex->getNumFaces(ch); + for(U32 i = 0; i < end; i++) + { + if ((*face_list)[i]->isMediaAllowed()) + { + mMediaFaceList.push_back((*face_list)[i]); + } + } + } + } + + if(!mMediaImplp) + { + return TRUE; + } + + //for media on a face. + const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList(); + std::list< LLVOVolume* >::const_iterator iter = obj_list->begin(); + for(; iter != obj_list->end(); ++iter) + { + LLVOVolume* obj = *iter; if (obj->isDead()) { // Isn't supposed to happen, objects are supposed to detach @@ -3418,343 +3418,343 @@ BOOL LLViewerMediaTexture::findFaces() continue; } - S32 face_id = -1; - S32 num_faces = obj->mDrawable->getNumFaces(); - while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces) - { - LLFace* facep = obj->mDrawable->getFace(face_id); - if(facep) - { - mMediaFaceList.push_back(facep); - } - else - { - ret = FALSE; - } - } - } - - return ret; + S32 face_id = -1; + S32 num_faces = obj->mDrawable->getNumFaces(); + while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces) + { + LLFace* facep = obj->mDrawable->getFace(face_id); + if(facep) + { + mMediaFaceList.push_back(facep); + } + else + { + ret = FALSE; + } + } + } + + return ret; } void LLViewerMediaTexture::initVirtualSize() { - if(mIsPlaying) - { - return; - } - - findFaces(); - for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) - { - addTextureStats((*iter)->getVirtualSize()); - } -} - -void LLViewerMediaTexture::addMediaToFace(LLFace* facep) -{ - if(facep) - { - facep->setHasMedia(true); - } - if(!mIsPlaying) - { - return; //no need to add the face because the media is not in playing. - } - - switchTexture(LLRender::DIFFUSE_MAP, facep); -} - -void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) -{ - if(!facep) - { - return; - } - facep->setHasMedia(false); - - if(!mIsPlaying) - { - return; //no need to remove the face because the media is not in playing. - } - - mIsPlaying = FALSE; //set to remove the media from the face. - switchTexture(LLRender::DIFFUSE_MAP, facep); - mIsPlaying = TRUE; //set the flag back. - - if(getTotalNumFaces() < 1) //no face referencing to this media - { - stopPlaying(); - } -} - -//virtual -void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep) -{ - LLViewerTexture::addFace(ch, facep); - - const LLTextureEntry* te = facep->getTextureEntry(); - if(te && te->getID().notNull()) - { - LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); - if(tex) - { - mTextureList.push_back(tex);//increase the reference number by one for tex to avoid deleting it. - return; - } - } - - //check if it is a parcel media - if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID) - { - mTextureList.push_back(facep->getTexture()); //a parcel media. - return; - } - - if(te && te->getID().notNull()) //should have a texture - { + if(mIsPlaying) + { + return; + } + + findFaces(); + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + addTextureStats((*iter)->getVirtualSize()); + } +} + +void LLViewerMediaTexture::addMediaToFace(LLFace* facep) +{ + if(facep) + { + facep->setHasMedia(true); + } + if(!mIsPlaying) + { + return; //no need to add the face because the media is not in playing. + } + + switchTexture(LLRender::DIFFUSE_MAP, facep); +} + +void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) +{ + if(!facep) + { + return; + } + facep->setHasMedia(false); + + if(!mIsPlaying) + { + return; //no need to remove the face because the media is not in playing. + } + + mIsPlaying = FALSE; //set to remove the media from the face. + switchTexture(LLRender::DIFFUSE_MAP, facep); + mIsPlaying = TRUE; //set the flag back. + + if(getTotalNumFaces() < 1) //no face referencing to this media + { + stopPlaying(); + } +} + +//virtual +void LLViewerMediaTexture::addFace(U32 ch, LLFace* facep) +{ + LLViewerTexture::addFace(ch, facep); + + const LLTextureEntry* te = facep->getTextureEntry(); + if(te && te->getID().notNull()) + { + LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); + if(tex) + { + mTextureList.push_back(tex);//increase the reference number by one for tex to avoid deleting it. + return; + } + } + + //check if it is a parcel media + if(facep->getTexture() && facep->getTexture() != this && facep->getTexture()->getID() == mID) + { + mTextureList.push_back(facep->getTexture()); //a parcel media. + return; + } + + if(te && te->getID().notNull()) //should have a texture + { LL_WARNS_ONCE() << "The face's texture " << te->getID() << " is not valid. Face must have a valid texture before media texture." << LL_ENDL; // This might break the object, but it likely isn't a 'recoverable' situation. LLViewerFetchedTexture* tex = LLViewerTextureManager::getFetchedTexture(te->getID()); mTextureList.push_back(tex); - } -} - -//virtual -void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) -{ - LLViewerTexture::removeFace(ch, facep); - - const LLTextureEntry* te = facep->getTextureEntry(); - if(te && te->getID().notNull()) - { - LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); - if(tex) - { - for(std::list< LLPointer >::iterator iter = mTextureList.begin(); - iter != mTextureList.end(); ++iter) - { - if(*iter == tex) - { - mTextureList.erase(iter); //decrease the reference number for tex by one. - return; - } - } - - std::vector te_list; - - for (U32 ch = 0; ch < 3; ++ch) - { - // - //we have some trouble here: the texture of the face is changed. - //we need to find the former texture, and remove it from the list to avoid memory leaking. - - llassert(mNumFaces[ch] <= mFaceList[ch].size()); - - for(U32 j = 0; j < mNumFaces[ch]; j++) - { - te_list.push_back(mFaceList[ch][j]->getTextureEntry());//all textures are in use. - } - } - - if (te_list.empty()) - { - mTextureList.clear(); - return; - } - - S32 end = te_list.size(); - - for(std::list< LLPointer >::iterator iter = mTextureList.begin(); - iter != mTextureList.end(); ++iter) - { - S32 i = 0; - - for(i = 0; i < end; i++) - { - if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use. - { - te_list[i] = NULL; - break; - } - } - if(i == end) //no hit for this texture, remove it. - { - mTextureList.erase(iter); //decrease the reference number for tex by one. - return; - } - } - } - } - - //check if it is a parcel media - for(std::list< LLPointer >::iterator iter = mTextureList.begin(); - iter != mTextureList.end(); ++iter) - { - if((*iter)->getID() == mID) - { - mTextureList.erase(iter); //decrease the reference number for tex by one. - return; - } - } - - if(te && te->getID().notNull()) //should have a texture but none found - { - LL_ERRS() << "mTextureList texture reference number is corrupted. Texture id: " << te->getID() << " List size: " << (U32)mTextureList.size() << LL_ENDL; - } + } +} + +//virtual +void LLViewerMediaTexture::removeFace(U32 ch, LLFace* facep) +{ + LLViewerTexture::removeFace(ch, facep); + + const LLTextureEntry* te = facep->getTextureEntry(); + if(te && te->getID().notNull()) + { + LLViewerTexture* tex = gTextureList.findImage(te->getID(), TEX_LIST_STANDARD); + if(tex) + { + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + if(*iter == tex) + { + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; + } + } + + std::vector te_list; + + for (U32 ch = 0; ch < 3; ++ch) + { + // + //we have some trouble here: the texture of the face is changed. + //we need to find the former texture, and remove it from the list to avoid memory leaking. + + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + + for(U32 j = 0; j < mNumFaces[ch]; j++) + { + te_list.push_back(mFaceList[ch][j]->getTextureEntry());//all textures are in use. + } + } + + if (te_list.empty()) + { + mTextureList.clear(); + return; + } + + S32 end = te_list.size(); + + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + S32 i = 0; + + for(i = 0; i < end; i++) + { + if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use. + { + te_list[i] = NULL; + break; + } + } + if(i == end) //no hit for this texture, remove it. + { + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; + } + } + } + } + + //check if it is a parcel media + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + if((*iter)->getID() == mID) + { + mTextureList.erase(iter); //decrease the reference number for tex by one. + return; + } + } + + if(te && te->getID().notNull()) //should have a texture but none found + { + LL_ERRS() << "mTextureList texture reference number is corrupted. Texture id: " << te->getID() << " List size: " << (U32)mTextureList.size() << LL_ENDL; + } } void LLViewerMediaTexture::stopPlaying() { - // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser). -// if(mMediaImplp) -// { -// mMediaImplp->stop(); -// } - mIsPlaying = FALSE; + // Don't stop the media impl playing here -- this breaks non-inworld media (login screen, search, and media browser). +// if(mMediaImplp) +// { +// mMediaImplp->stop(); +// } + mIsPlaying = FALSE; } void LLViewerMediaTexture::switchTexture(U32 ch, LLFace* facep) { - if(facep) - { - //check if another media is playing on this face. - if(facep->getTexture() && facep->getTexture() != this - && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE) - { - if(mID == facep->getTexture()->getID()) //this is a parcel media - { - return; //let the prim media win. - } - } - - if(mIsPlaying) //old textures switch to the media texture - { - facep->switchTexture(ch, this); - } - else //switch to old textures. - { - const LLTextureEntry* te = facep->getTextureEntry(); - if(te) - { - LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; - if(!tex && te->getID() != mID)//try parcel media. - { - tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); - } - if(!tex) - { - tex = LLViewerFetchedTexture::sDefaultImagep; - } - facep->switchTexture(ch, tex); - } - } - } -} - -void LLViewerMediaTexture::setPlaying(BOOL playing) -{ - if(!mMediaImplp) - { - return; - } - if(!playing && !mIsPlaying) - { - return; //media is already off - } - - if(playing == mIsPlaying && !mMediaImplp->isUpdated()) - { - return; //nothing has changed since last time. - } - - mIsPlaying = playing; - if(mIsPlaying) //is about to play this media - { - if(findFaces()) - { - //about to update all faces. - mMediaImplp->setUpdated(FALSE); - } - - if(mMediaFaceList.empty())//no face pointing to this media - { - stopPlaying(); - return; - } - - for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) - { - switchTexture(LLRender::DIFFUSE_MAP, *iter); - } - } - else //stop playing this media - { - U32 ch = LLRender::DIFFUSE_MAP; - - llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 i = mNumFaces[ch]; i; i--) - { - switchTexture(ch, mFaceList[ch][i - 1]); //current face could be removed in this function. - } - } - return; -} - -//virtual -F32 LLViewerMediaTexture::getMaxVirtualSize() -{ - if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime) - { - return mMaxVirtualSize; - } - mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount(); - - if(!mMaxVirtualSizeResetCounter) - { - addTextureStats(0.f, FALSE);//reset - } - - if(mIsPlaying) //media is playing - { - for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) - { - llassert(mNumFaces[ch] <= mFaceList[ch].size()); - for(U32 i = 0; i < mNumFaces[ch]; i++) - { - LLFace* facep = mFaceList[ch][i]; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()); - } - } - } - } - else //media is not in playing - { - findFaces(); - - if(!mMediaFaceList.empty()) - { - for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) - { - LLFace* facep = *iter; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()); - } - } - } - } - - if(mMaxVirtualSizeResetCounter > 0) - { - mMaxVirtualSizeResetCounter--; - } - reorganizeFaceList(); - reorganizeVolumeList(); - - return mMaxVirtualSize; + if(facep) + { + //check if another media is playing on this face. + if(facep->getTexture() && facep->getTexture() != this + && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE) + { + if(mID == facep->getTexture()->getID()) //this is a parcel media + { + return; //let the prim media win. + } + } + + if(mIsPlaying) //old textures switch to the media texture + { + facep->switchTexture(ch, this); + } + else //switch to old textures. + { + const LLTextureEntry* te = facep->getTextureEntry(); + if(te) + { + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL; + if(!tex && te->getID() != mID)//try parcel media. + { + tex = gTextureList.findImage(mID, TEX_LIST_STANDARD); + } + if(!tex) + { + tex = LLViewerFetchedTexture::sDefaultImagep; + } + facep->switchTexture(ch, tex); + } + } + } +} + +void LLViewerMediaTexture::setPlaying(BOOL playing) +{ + if(!mMediaImplp) + { + return; + } + if(!playing && !mIsPlaying) + { + return; //media is already off + } + + if(playing == mIsPlaying && !mMediaImplp->isUpdated()) + { + return; //nothing has changed since last time. + } + + mIsPlaying = playing; + if(mIsPlaying) //is about to play this media + { + if(findFaces()) + { + //about to update all faces. + mMediaImplp->setUpdated(FALSE); + } + + if(mMediaFaceList.empty())//no face pointing to this media + { + stopPlaying(); + return; + } + + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + switchTexture(LLRender::DIFFUSE_MAP, *iter); + } + } + else //stop playing this media + { + U32 ch = LLRender::DIFFUSE_MAP; + + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + for(U32 i = mNumFaces[ch]; i; i--) + { + switchTexture(ch, mFaceList[ch][i - 1]); //current face could be removed in this function. + } + } + return; +} + +//virtual +F32 LLViewerMediaTexture::getMaxVirtualSize() +{ + if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime) + { + return mMaxVirtualSize; + } + mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount(); + + if(!mMaxVirtualSizeResetCounter) + { + addTextureStats(0.f, FALSE);//reset + } + + if(mIsPlaying) //media is playing + { + for (U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + llassert(mNumFaces[ch] <= mFaceList[ch].size()); + for(U32 i = 0; i < mNumFaces[ch]; i++) + { + LLFace* facep = mFaceList[ch][i]; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()); + } + } + } + } + else //media is not in playing + { + findFaces(); + + if(!mMediaFaceList.empty()) + { + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + LLFace* facep = *iter; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()); + } + } + } + } + + if(mMaxVirtualSizeResetCounter > 0) + { + mMaxVirtualSizeResetCounter--; + } + reorganizeFaceList(); + reorganizeVolumeList(); + + return mMaxVirtualSize; } //---------------------------------------------------------------------------------------------- //end of LLViewerMediaTexture @@ -3763,391 +3763,391 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() //---------------------------------------------------------------------------------------------- //start of LLTexturePipelineTester //---------------------------------------------------------------------------------------------- -LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName) -{ - addMetric("TotalBytesLoaded"); - addMetric("TotalBytesLoadedFromCache"); - addMetric("TotalBytesLoadedForLargeImage"); - addMetric("TotalBytesLoadedForSculpties"); - addMetric("StartFetchingTime"); - addMetric("TotalGrayTime"); - addMetric("TotalStablizingTime"); - addMetric("StartTimeLoadingSculpties"); - addMetric("EndTimeLoadingSculpties"); - - addMetric("Time"); - addMetric("TotalBytesBound"); - addMetric("TotalBytesBoundForLargeImage"); - addMetric("PercentageBytesBound"); - - mTotalBytesLoaded = (S32Bytes)0; - mTotalBytesLoadedFromCache = (S32Bytes)0; - mTotalBytesLoadedForLargeImage = (S32Bytes)0; - mTotalBytesLoadedForSculpties = (S32Bytes)0; - - reset(); +LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName) +{ + addMetric("TotalBytesLoaded"); + addMetric("TotalBytesLoadedFromCache"); + addMetric("TotalBytesLoadedForLargeImage"); + addMetric("TotalBytesLoadedForSculpties"); + addMetric("StartFetchingTime"); + addMetric("TotalGrayTime"); + addMetric("TotalStablizingTime"); + addMetric("StartTimeLoadingSculpties"); + addMetric("EndTimeLoadingSculpties"); + + addMetric("Time"); + addMetric("TotalBytesBound"); + addMetric("TotalBytesBoundForLargeImage"); + addMetric("PercentageBytesBound"); + + mTotalBytesLoaded = (S32Bytes)0; + mTotalBytesLoadedFromCache = (S32Bytes)0; + mTotalBytesLoadedForLargeImage = (S32Bytes)0; + mTotalBytesLoadedForSculpties = (S32Bytes)0; + + reset(); } LLTexturePipelineTester::~LLTexturePipelineTester() { - LLViewerTextureManager::sTesterp = NULL; + LLViewerTextureManager::sTesterp = NULL; } void LLTexturePipelineTester::update() { - mLastTotalBytesUsed = mTotalBytesUsed; - mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage; - mTotalBytesUsed = (S32Bytes)0; - mTotalBytesUsedForLargeImage = (S32Bytes)0; - - if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty - { - if(mPause) - { - //start a new fetching session - reset(); - mStartFetchingTime = LLImageGL::sLastFrameTime; - mPause = FALSE; - } - - //update total gray time - if(mUsingDefaultTexture) - { - mUsingDefaultTexture = FALSE; - mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime; - } - - //update the stablizing timer. - updateStablizingTime(); - - outputTestResults(); - } - else if(!mPause) - { - //stop the current fetching session - mPause = TRUE; - outputTestResults(); - reset(); - } -} - -void LLTexturePipelineTester::reset() -{ - mPause = TRUE; - - mUsingDefaultTexture = FALSE; - mStartStablizingTime = 0.0f; - mEndStablizingTime = 0.0f; - - mTotalBytesUsed = (S32Bytes)0; - mTotalBytesUsedForLargeImage = (S32Bytes)0; - mLastTotalBytesUsed = (S32Bytes)0; - mLastTotalBytesUsedForLargeImage = (S32Bytes)0; - - mStartFetchingTime = 0.0f; - - mTotalGrayTime = 0.0f; - mTotalStablizingTime = 0.0f; - - mStartTimeLoadingSculpties = 1.0f; - mEndTimeLoadingSculpties = 0.0f; -} - -//virtual -void LLTexturePipelineTester::outputTestRecord(LLSD *sd) -{ - std::string currentLabel = getCurrentLabelName(); - (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value(); - (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value(); - (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value(); - (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value(); - - (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime; - (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime; - (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime; - - (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties; - (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties; - - (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime; - (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value(); - (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value(); - (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded); -} - -void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) -{ - U32Bytes mem_size = imagep->getTextureMemory(); - mTotalBytesUsed += mem_size; - - if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size.value() / (U32)imagep->getComponents())) - { - mTotalBytesUsedForLargeImage += mem_size; - } -} - -void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) -{ - U32Bytes data_size = (U32Bytes)raw_imagep->getDataSize(); - mTotalBytesLoaded += data_size; - - if(from_cache) - { - mTotalBytesLoadedFromCache += data_size; - } - - if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size.value() / (U32)raw_imagep->getComponents())) - { - mTotalBytesLoadedForLargeImage += data_size; - } - - if(imagep->forSculpt()) - { - mTotalBytesLoadedForSculpties += data_size; - - if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties) - { - mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime; - } - mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime; - } + mLastTotalBytesUsed = mTotalBytesUsed; + mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage; + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; + + if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty + { + if(mPause) + { + //start a new fetching session + reset(); + mStartFetchingTime = LLImageGL::sLastFrameTime; + mPause = FALSE; + } + + //update total gray time + if(mUsingDefaultTexture) + { + mUsingDefaultTexture = FALSE; + mTotalGrayTime = LLImageGL::sLastFrameTime - mStartFetchingTime; + } + + //update the stablizing timer. + updateStablizingTime(); + + outputTestResults(); + } + else if(!mPause) + { + //stop the current fetching session + mPause = TRUE; + outputTestResults(); + reset(); + } +} + +void LLTexturePipelineTester::reset() +{ + mPause = TRUE; + + mUsingDefaultTexture = FALSE; + mStartStablizingTime = 0.0f; + mEndStablizingTime = 0.0f; + + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; + mLastTotalBytesUsed = (S32Bytes)0; + mLastTotalBytesUsedForLargeImage = (S32Bytes)0; + + mStartFetchingTime = 0.0f; + + mTotalGrayTime = 0.0f; + mTotalStablizingTime = 0.0f; + + mStartTimeLoadingSculpties = 1.0f; + mEndTimeLoadingSculpties = 0.0f; +} + +//virtual +void LLTexturePipelineTester::outputTestRecord(LLSD *sd) +{ + std::string currentLabel = getCurrentLabelName(); + (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value(); + (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value(); + (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value(); + (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value(); + + (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime; + (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime; + (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime; + + (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties; + (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties; + + (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime; + (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value(); + (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value(); + (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded); +} + +void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) +{ + U32Bytes mem_size = imagep->getTextureMemory(); + mTotalBytesUsed += mem_size; + + if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size.value() / (U32)imagep->getComponents())) + { + mTotalBytesUsedForLargeImage += mem_size; + } +} + +void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) +{ + U32Bytes data_size = (U32Bytes)raw_imagep->getDataSize(); + mTotalBytesLoaded += data_size; + + if(from_cache) + { + mTotalBytesLoadedFromCache += data_size; + } + + if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size.value() / (U32)raw_imagep->getComponents())) + { + mTotalBytesLoadedForLargeImage += data_size; + } + + if(imagep->forSculpt()) + { + mTotalBytesLoadedForSculpties += data_size; + + if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties) + { + mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime; + } + mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime; + } } void LLTexturePipelineTester::updateGrayTextureBinding() { - mUsingDefaultTexture = TRUE; + mUsingDefaultTexture = TRUE; } void LLTexturePipelineTester::setStablizingTime() { - if(mStartStablizingTime <= mStartFetchingTime) - { - mStartStablizingTime = LLImageGL::sLastFrameTime; - } - mEndStablizingTime = LLImageGL::sLastFrameTime; + if(mStartStablizingTime <= mStartFetchingTime) + { + mStartStablizingTime = LLImageGL::sLastFrameTime; + } + mEndStablizingTime = LLImageGL::sLastFrameTime; } void LLTexturePipelineTester::updateStablizingTime() { - if(mStartStablizingTime > mStartFetchingTime) - { - F32 t = mEndStablizingTime - mStartStablizingTime; - - if(t > F_ALMOST_ZERO && (t - mTotalStablizingTime) < F_ALMOST_ZERO) - { - //already stablized - mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime; - - //cancel the timer - mStartStablizingTime = 0.f; - mEndStablizingTime = 0.f; - } - else - { - mTotalStablizingTime = t; - } - } - mTotalStablizingTime = 0.f; -} - -//virtual -void LLTexturePipelineTester::compareTestSessions(llofstream* os) -{ - LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast(mBaseSessionp); - LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast(mCurrentSessionp); - if(!base_sessionp || !current_sessionp) - { - LL_ERRS() << "type of test session does not match!" << LL_ENDL; - } - - //compare and output the comparison - *os << llformat("%s\n", getTesterName().c_str()); - *os << llformat("AggregateResults\n"); - - compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime); - compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime); - compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties); - compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties); - - compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded); - compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache); - compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage); - compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties); - - *os << llformat("InstantResults\n"); - S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter); - for(S32 i = 0; i < size; i++) - { - *os << llformat("Time(B-T)-%.4f-%.4f\n", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime); - - compareTestResults(os, "AverageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond, - current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); - - compareTestResults(os, "AverageBytesUsedForLargeImagePerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond, - current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); - - compareTestResults(os, "AveragePercentageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond, - current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); - } - - if(size < base_sessionp->mInstantPerformanceListCounter) - { - for(S32 i = size; i < base_sessionp->mInstantPerformanceListCounter; i++) - { - *os << llformat("Time(B-T)-%.4f- \n", base_sessionp->mInstantPerformanceList[i].mTime); - - *os << llformat(", AverageBytesUsedPerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); - *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); - *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A \n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); - } - } - else if(size < current_sessionp->mInstantPerformanceListCounter) - { - for(S32 i = size; i < current_sessionp->mInstantPerformanceListCounter; i++) - { - *os << llformat("Time(B-T)- -%.4f\n", current_sessionp->mInstantPerformanceList[i].mTime); - - *os << llformat(", AverageBytesUsedPerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); - *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); - *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4f\n", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); - } - } -} - -//virtual + if(mStartStablizingTime > mStartFetchingTime) + { + F32 t = mEndStablizingTime - mStartStablizingTime; + + if(t > F_ALMOST_ZERO && (t - mTotalStablizingTime) < F_ALMOST_ZERO) + { + //already stablized + mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime; + + //cancel the timer + mStartStablizingTime = 0.f; + mEndStablizingTime = 0.f; + } + else + { + mTotalStablizingTime = t; + } + } + mTotalStablizingTime = 0.f; +} + +//virtual +void LLTexturePipelineTester::compareTestSessions(llofstream* os) +{ + LLTexturePipelineTester::LLTextureTestSession* base_sessionp = dynamic_cast(mBaseSessionp); + LLTexturePipelineTester::LLTextureTestSession* current_sessionp = dynamic_cast(mCurrentSessionp); + if(!base_sessionp || !current_sessionp) + { + LL_ERRS() << "type of test session does not match!" << LL_ENDL; + } + + //compare and output the comparison + *os << llformat("%s\n", getTesterName().c_str()); + *os << llformat("AggregateResults\n"); + + compareTestResults(os, "TotalGrayTime", base_sessionp->mTotalGrayTime, current_sessionp->mTotalGrayTime); + compareTestResults(os, "TotalStablizingTime", base_sessionp->mTotalStablizingTime, current_sessionp->mTotalStablizingTime); + compareTestResults(os, "StartTimeLoadingSculpties", base_sessionp->mStartTimeLoadingSculpties, current_sessionp->mStartTimeLoadingSculpties); + compareTestResults(os, "TotalTimeLoadingSculpties", base_sessionp->mTotalTimeLoadingSculpties, current_sessionp->mTotalTimeLoadingSculpties); + + compareTestResults(os, "TotalBytesLoaded", base_sessionp->mTotalBytesLoaded, current_sessionp->mTotalBytesLoaded); + compareTestResults(os, "TotalBytesLoadedFromCache", base_sessionp->mTotalBytesLoadedFromCache, current_sessionp->mTotalBytesLoadedFromCache); + compareTestResults(os, "TotalBytesLoadedForLargeImage", base_sessionp->mTotalBytesLoadedForLargeImage, current_sessionp->mTotalBytesLoadedForLargeImage); + compareTestResults(os, "TotalBytesLoadedForSculpties", base_sessionp->mTotalBytesLoadedForSculpties, current_sessionp->mTotalBytesLoadedForSculpties); + + *os << llformat("InstantResults\n"); + S32 size = llmin(base_sessionp->mInstantPerformanceListCounter, current_sessionp->mInstantPerformanceListCounter); + for(S32 i = 0; i < size; i++) + { + *os << llformat("Time(B-T)-%.4f-%.4f\n", base_sessionp->mInstantPerformanceList[i].mTime, current_sessionp->mInstantPerformanceList[i].mTime); + + compareTestResults(os, "AverageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond, + current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); + + compareTestResults(os, "AverageBytesUsedForLargeImagePerSecond", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond, + current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); + + compareTestResults(os, "AveragePercentageBytesUsedPerSecond", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond, + current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); + } + + if(size < base_sessionp->mInstantPerformanceListCounter) + { + for(S32 i = size; i < base_sessionp->mInstantPerformanceListCounter; i++) + { + *os << llformat("Time(B-T)-%.4f- \n", base_sessionp->mInstantPerformanceList[i].mTime); + + *os << llformat(", AverageBytesUsedPerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); + *os << llformat(", AverageBytesUsedForLargeImagePerSecond, %d, N/A \n", base_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); + *os << llformat(", AveragePercentageBytesUsedPerSecond, %.4f, N/A \n", base_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); + } + } + else if(size < current_sessionp->mInstantPerformanceListCounter) + { + for(S32 i = size; i < current_sessionp->mInstantPerformanceListCounter; i++) + { + *os << llformat("Time(B-T)- -%.4f\n", current_sessionp->mInstantPerformanceList[i].mTime); + + *os << llformat(", AverageBytesUsedPerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedPerSecond); + *os << llformat(", AverageBytesUsedForLargeImagePerSecond, N/A, %d\n", current_sessionp->mInstantPerformanceList[i].mAverageBytesUsedForLargeImagePerSecond); + *os << llformat(", AveragePercentageBytesUsedPerSecond, N/A, %.4f\n", current_sessionp->mInstantPerformanceList[i].mAveragePercentageBytesUsedPerSecond); + } + } +} + +//virtual LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log) { - LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession(); - if(!sessionp) - { - return NULL; - } - - F32 total_gray_time = 0.f; - F32 total_stablizing_time = 0.f; - F32 total_loading_sculpties_time = 0.f; - - F32 start_fetching_time = -1.f; - F32 start_fetching_sculpties_time = 0.f; - - F32 last_time = 0.0f; - S32 frame_count = 0; - - sessionp->mInstantPerformanceListCounter = 0; - sessionp->mInstantPerformanceList.resize(128); - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; - - //load a session - std::string currentLabel = getCurrentLabelName(); - BOOL in_log = (*log).has(currentLabel); - while (in_log) - { - LLSD::String label = currentLabel; - - if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size()) - { - sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128); - } - - //time - F32 start_time = (*log)[label]["StartFetchingTime"].asReal(); - F32 cur_time = (*log)[label]["Time"].asReal(); - if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while - { - sessionp->mTotalGrayTime += total_gray_time; - sessionp->mTotalStablizingTime += total_stablizing_time; - - sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; - sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; - - start_fetching_time = start_time; - total_gray_time = 0.f; - total_stablizing_time = 0.f; - total_loading_sculpties_time = 0.f; - } - else - { - total_gray_time = (*log)[label]["TotalGrayTime"].asReal(); - total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal(); - - total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal(); - if(start_fetching_sculpties_time < 0.f && total_loading_sculpties_time > 0.f) - { - start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal(); - } - } - - //total loaded bytes - sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger(); - sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger(); - sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger(); - sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger(); - - //instant metrics - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond += - (*log)[label]["TotalBytesBound"].asInteger(); - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond += - (*log)[label]["TotalBytesBoundForLargeImage"].asInteger(); - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond += - (*log)[label]["PercentageBytesBound"].asReal(); - frame_count++; - if(cur_time - last_time >= 1.0f) - { - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time; - - frame_count = 0; - last_time = cur_time; - sessionp->mInstantPerformanceListCounter++; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; - sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; - } - // Next label - incrementCurrentCount(); - currentLabel = getCurrentLabelName(); - in_log = (*log).has(currentLabel); - } - - sessionp->mTotalGrayTime += total_gray_time; - sessionp->mTotalStablizingTime += total_stablizing_time; - - if(sessionp->mStartTimeLoadingSculpties < 0.f) - { - sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; - } - sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; - - return sessionp; -} - -LLTexturePipelineTester::LLTextureTestSession::LLTextureTestSession() -{ - reset(); -} -LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession() -{ -} -void LLTexturePipelineTester::LLTextureTestSession::reset() -{ - mTotalGrayTime = 0.0f; - mTotalStablizingTime = 0.0f; - - mStartTimeLoadingSculpties = 0.0f; - mTotalTimeLoadingSculpties = 0.0f; - - mTotalBytesLoaded = 0; - mTotalBytesLoadedFromCache = 0; - mTotalBytesLoadedForLargeImage = 0; - mTotalBytesLoadedForSculpties = 0; - - mInstantPerformanceListCounter = 0; + LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession(); + if(!sessionp) + { + return NULL; + } + + F32 total_gray_time = 0.f; + F32 total_stablizing_time = 0.f; + F32 total_loading_sculpties_time = 0.f; + + F32 start_fetching_time = -1.f; + F32 start_fetching_sculpties_time = 0.f; + + F32 last_time = 0.0f; + S32 frame_count = 0; + + sessionp->mInstantPerformanceListCounter = 0; + sessionp->mInstantPerformanceList.resize(128); + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; + + //load a session + std::string currentLabel = getCurrentLabelName(); + BOOL in_log = (*log).has(currentLabel); + while (in_log) + { + LLSD::String label = currentLabel; + + if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size()) + { + sessionp->mInstantPerformanceList.resize(sessionp->mInstantPerformanceListCounter + 128); + } + + //time + F32 start_time = (*log)[label]["StartFetchingTime"].asReal(); + F32 cur_time = (*log)[label]["Time"].asReal(); + if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while + { + sessionp->mTotalGrayTime += total_gray_time; + sessionp->mTotalStablizingTime += total_stablizing_time; + + sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; + sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; + + start_fetching_time = start_time; + total_gray_time = 0.f; + total_stablizing_time = 0.f; + total_loading_sculpties_time = 0.f; + } + else + { + total_gray_time = (*log)[label]["TotalGrayTime"].asReal(); + total_stablizing_time = (*log)[label]["TotalStablizingTime"].asReal(); + + total_loading_sculpties_time = (*log)[label]["EndTimeLoadingSculpties"].asReal() - (*log)[label]["StartTimeLoadingSculpties"].asReal(); + if(start_fetching_sculpties_time < 0.f && total_loading_sculpties_time > 0.f) + { + start_fetching_sculpties_time = (*log)[label]["StartTimeLoadingSculpties"].asReal(); + } + } + + //total loaded bytes + sessionp->mTotalBytesLoaded = (*log)[label]["TotalBytesLoaded"].asInteger(); + sessionp->mTotalBytesLoadedFromCache = (*log)[label]["TotalBytesLoadedFromCache"].asInteger(); + sessionp->mTotalBytesLoadedForLargeImage = (*log)[label]["TotalBytesLoadedForLargeImage"].asInteger(); + sessionp->mTotalBytesLoadedForSculpties = (*log)[label]["TotalBytesLoadedForSculpties"].asInteger(); + + //instant metrics + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond += + (*log)[label]["TotalBytesBound"].asInteger(); + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond += + (*log)[label]["TotalBytesBoundForLargeImage"].asInteger(); + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond += + (*log)[label]["PercentageBytesBound"].asReal(); + frame_count++; + if(cur_time - last_time >= 1.0f) + { + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond /= frame_count; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = last_time; + + frame_count = 0; + last_time = cur_time; + sessionp->mInstantPerformanceListCounter++; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedPerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f; + sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f; + } + // Next label + incrementCurrentCount(); + currentLabel = getCurrentLabelName(); + in_log = (*log).has(currentLabel); + } + + sessionp->mTotalGrayTime += total_gray_time; + sessionp->mTotalStablizingTime += total_stablizing_time; + + if(sessionp->mStartTimeLoadingSculpties < 0.f) + { + sessionp->mStartTimeLoadingSculpties = start_fetching_sculpties_time; + } + sessionp->mTotalTimeLoadingSculpties += total_loading_sculpties_time; + + return sessionp; +} + +LLTexturePipelineTester::LLTextureTestSession::LLTextureTestSession() +{ + reset(); +} +LLTexturePipelineTester::LLTextureTestSession::~LLTextureTestSession() +{ +} +void LLTexturePipelineTester::LLTextureTestSession::reset() +{ + mTotalGrayTime = 0.0f; + mTotalStablizingTime = 0.0f; + + mStartTimeLoadingSculpties = 0.0f; + mTotalTimeLoadingSculpties = 0.0f; + + mTotalBytesLoaded = 0; + mTotalBytesLoadedFromCache = 0; + mTotalBytesLoadedForLargeImage = 0; + mTotalBytesLoadedForSculpties = 0; + + mInstantPerformanceListCounter = 0; } //---------------------------------------------------------------------------------------------- //end of LLTexturePipelineTester diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 52b2f19ada..b1983445a6 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -1,30 +1,30 @@ -/** +/** * @file llviewertexture.h * @brief Object for managing images and their textures * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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_LLVIEWERTEXTURE_H +#ifndef LL_LLVIEWERTEXTURE_H #define LL_LLVIEWERTEXTURE_H #include "llatomic.h" @@ -54,7 +54,7 @@ class LLViewerMediaTexture ; class LLTexturePipelineTester ; -typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); +typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); class LLFileSystem; class LLMessageSystem; @@ -68,26 +68,26 @@ public: typedef std::set< LLTextureKey > source_callback_list_t; public: - LLLoadedCallbackEntry(loaded_callback_func cb, - S32 discard_level, - BOOL need_imageraw, // Needs image raw for the callback - void* userdata, - source_callback_list_t* src_callback_list, - LLViewerFetchedTexture* target, - BOOL pause); - ~LLLoadedCallbackEntry(); - void removeTexture(LLViewerFetchedTexture* tex) ; - - loaded_callback_func mCallback; - S32 mLastUsedDiscard; - S32 mDesiredDiscard; - BOOL mNeedsImageRaw; - BOOL mPaused; - void* mUserData; - source_callback_list_t* mSourceCallbackList; - + LLLoadedCallbackEntry(loaded_callback_func cb, + S32 discard_level, + BOOL need_imageraw, // Needs image raw for the callback + void* userdata, + source_callback_list_t* src_callback_list, + LLViewerFetchedTexture* target, + BOOL pause); + ~LLLoadedCallbackEntry(); + void removeTexture(LLViewerFetchedTexture* tex) ; + + loaded_callback_func mCallback; + S32 mLastUsedDiscard; + S32 mDesiredDiscard; + BOOL mNeedsImageRaw; + BOOL mPaused; + void* mUserData; + source_callback_list_t* mSourceCallbackList; + public: - static void cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) ; + static void cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) ; }; class LLTextureBar; @@ -95,163 +95,163 @@ class LLTextureBar; class LLViewerTexture : public LLGLTexture { public: - enum - { - LOCAL_TEXTURE, - MEDIA_TEXTURE, - DYNAMIC_TEXTURE, - FETCHED_TEXTURE, - LOD_TEXTURE, - ATLAS_TEXTURE, - INVALID_TEXTURE_TYPE - }; + enum + { + LOCAL_TEXTURE, + MEDIA_TEXTURE, + DYNAMIC_TEXTURE, + FETCHED_TEXTURE, + LOD_TEXTURE, + ATLAS_TEXTURE, + INVALID_TEXTURE_TYPE + }; - typedef std::vector ll_face_list_t; - typedef std::vector ll_volume_list_t; + typedef std::vector ll_face_list_t; + typedef std::vector ll_volume_list_t; protected: - virtual ~LLViewerTexture(); - LOG_CLASS(LLViewerTexture); - -public: - static void initClass(); - static void updateClass(); - - LLViewerTexture(BOOL usemipmaps = TRUE); - LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ; - LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ; - LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; - - virtual S8 getType() const; - virtual BOOL isMissingAsset() const ; - virtual void dump(); // debug info to LL_INFOS() - + virtual ~LLViewerTexture(); + LOG_CLASS(LLViewerTexture); + +public: + static void initClass(); + static void updateClass(); + + LLViewerTexture(BOOL usemipmaps = TRUE); + LLViewerTexture(const LLUUID& id, BOOL usemipmaps) ; + LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + + virtual S8 getType() const; + virtual BOOL isMissingAsset() const ; + virtual void dump(); // debug info to LL_INFOS() + virtual bool isViewerMediaTexture() const { return false; } - /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; - /*virtual*/ bool bindDebugImage(const S32 stage = 0) ; - /*virtual*/ void forceImmediateUpdate() ; - /*virtual*/ bool isActiveFetching(); - - /*virtual*/ const LLUUID& getID() const { return mID; } - virtual void setBoostLevel(S32 level); - S32 getBoostLevel() { return mBoostLevel; } - void setTextureListType(S32 tex_type) { mTextureListType = tex_type; } - S32 getTextureListType() { return mTextureListType; } - - void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; - void resetTextureStats(); - void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} - void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;} - S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; } - - virtual F32 getMaxVirtualSize() ; - - LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} - - S32 getFullWidth() const { return mFullWidth; } - S32 getFullHeight() const { return mFullHeight; } - /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - - virtual void addFace(U32 channel, LLFace* facep) ; - virtual void removeFace(U32 channel, LLFace* facep) ; - S32 getTotalNumFaces() const; - S32 getNumFaces(U32 ch) const; - const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];} - - virtual void addVolume(U32 channel, LLVOVolume* volumep); - virtual void removeVolume(U32 channel, LLVOVolume* volumep); - S32 getNumVolumes(U32 channel) const; - const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; } - - - virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; - BOOL isLargeImage() ; - - void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} - BOOL hasParcelMedia() const { return mParcelMedia != NULL;} - LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} - - /*virtual*/ void updateBindStatsForTester() ; + /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; + /*virtual*/ bool bindDebugImage(const S32 stage = 0) ; + /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ bool isActiveFetching(); + + /*virtual*/ const LLUUID& getID() const { return mID; } + virtual void setBoostLevel(S32 level); + S32 getBoostLevel() { return mBoostLevel; } + void setTextureListType(S32 tex_type) { mTextureListType = tex_type; } + S32 getTextureListType() { return mTextureListType; } + + void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; + void resetTextureStats(); + void setMaxVirtualSizeResetInterval(S32 interval)const {mMaxVirtualSizeResetInterval = interval;} + void resetMaxVirtualSizeResetCounter()const {mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval;} + S32 getMaxVirtualSizeResetCounter() const { return mMaxVirtualSizeResetCounter; } + + virtual F32 getMaxVirtualSize() ; + + LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} + + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } + /*virtual*/ void setKnownDrawSize(S32 width, S32 height); + + virtual void addFace(U32 channel, LLFace* facep) ; + virtual void removeFace(U32 channel, LLFace* facep) ; + S32 getTotalNumFaces() const; + S32 getNumFaces(U32 ch) const; + const ll_face_list_t* getFaceList(U32 channel) const {llassert(channel < LLRender::NUM_TEXTURE_CHANNELS); return &mFaceList[channel];} + + virtual void addVolume(U32 channel, LLVOVolume* volumep); + virtual void removeVolume(U32 channel, LLVOVolume* volumep); + S32 getNumVolumes(U32 channel) const; + const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; } + + + virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; + BOOL isLargeImage() ; + + void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;} + BOOL hasParcelMedia() const { return mParcelMedia != NULL;} + LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;} + + /*virtual*/ void updateBindStatsForTester() ; protected: - void cleanup() ; - void init(bool firstinit) ; - void reorganizeFaceList() ; - void reorganizeVolumeList(); + void cleanup() ; + void init(bool firstinit) ; + void reorganizeFaceList() ; + void reorganizeVolumeList(); private: - friend class LLBumpImageList; - friend class LLUIImageList; + friend class LLBumpImageList; + friend class LLUIImageList; - virtual void switchToCachedImage(); - - static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical); + virtual void switchToCachedImage(); + + static void getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical); public: static bool isMemoryForTextureLow(); protected: friend class LLViewerTextureList; - LLUUID mID; - S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList + LLUUID mID; + S32 mTextureListType; // along with mID identifies where to search for this texture in TextureList - mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need? - mutable S32 mMaxVirtualSizeResetCounter; - mutable S32 mMaxVirtualSizeResetInterval; - LLFrameTimer mLastReferencedTimer; + mutable F32 mMaxVirtualSize = 0.f; // The largest virtual size of the image, in pixels - how much data to we need? + mutable S32 mMaxVirtualSizeResetCounter; + mutable S32 mMaxVirtualSizeResetInterval; + LLFrameTimer mLastReferencedTimer; - ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture - U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; - LLFrameTimer mLastFaceListUpdateTimer ; + ll_face_list_t mFaceList[LLRender::NUM_TEXTURE_CHANNELS]; //reverse pointer pointing to the faces using this image as texture + U32 mNumFaces[LLRender::NUM_TEXTURE_CHANNELS]; + LLFrameTimer mLastFaceListUpdateTimer ; - ll_volume_list_t mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; - U32 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; - LLFrameTimer mLastVolumeListUpdateTimer; + ll_volume_list_t mVolumeList[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + U32 mNumVolumes[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + LLFrameTimer mLastVolumeListUpdateTimer; - //do not use LLPointer here. - LLViewerMediaTexture* mParcelMedia ; + //do not use LLPointer here. + LLViewerMediaTexture* mParcelMedia ; - LL::WorkQueue::weak_t mMainQueue; - LL::WorkQueue::weak_t mImageQueue; + LL::WorkQueue::weak_t mMainQueue; + LL::WorkQueue::weak_t mImageQueue; public: - static const U32 sCurrentFileVersion; - static S32 sImageCount; - static S32 sRawCount; - static S32 sAuxCount; - static LLFrameTimer sEvaluationTimer; - static F32 sDesiredDiscardBias; - static F32 sDesiredDiscardScale; - static S32 sMaxSculptRez ; - static U32 sMinLargeImageSize ; - static U32 sMaxSmallImageSize ; - static bool sFreezeImageUpdates; - static F32 sCurrentTime ; - - enum EDebugTexels - { - DEBUG_TEXELS_OFF, - DEBUG_TEXELS_CURRENT, - DEBUG_TEXELS_DESIRED, - DEBUG_TEXELS_FULL - }; - - static EDebugTexels sDebugTexelsMode; - - static LLPointer sNullImagep; // Null texture for non-textured objects. - static LLPointer sBlackImagep; // Texture to show NOTHING (pure black) - static LLPointer sCheckerBoardImagep; // Texture to show NOTHING (pure black) + static const U32 sCurrentFileVersion; + static S32 sImageCount; + static S32 sRawCount; + static S32 sAuxCount; + static LLFrameTimer sEvaluationTimer; + static F32 sDesiredDiscardBias; + static F32 sDesiredDiscardScale; + static S32 sMaxSculptRez ; + static U32 sMinLargeImageSize ; + static U32 sMaxSmallImageSize ; + static bool sFreezeImageUpdates; + static F32 sCurrentTime ; + + enum EDebugTexels + { + DEBUG_TEXELS_OFF, + DEBUG_TEXELS_CURRENT, + DEBUG_TEXELS_DESIRED, + DEBUG_TEXELS_FULL + }; + + static EDebugTexels sDebugTexelsMode; + + static LLPointer sNullImagep; // Null texture for non-textured objects. + static LLPointer sBlackImagep; // Texture to show NOTHING (pure black) + static LLPointer sCheckerBoardImagep; // Texture to show NOTHING (pure black) }; enum FTType { - FTT_UNKNOWN = -1, - FTT_DEFAULT = 0, // standard texture fetched by id. - FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. - FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. - FTT_MAP_TILE, // tiles are fetched from map server directly. - FTT_LOCAL_FILE // fetch directly from a local file. + FTT_UNKNOWN = -1, + FTT_DEFAULT = 0, // standard texture fetched by id. + FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. + FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. + FTT_MAP_TILE, // tiles are fetched from map server directly. + FTT_LOCAL_FILE // fetch directly from a local file. }; const std::string& fttype_to_string(const FTType& fttype); @@ -263,269 +263,269 @@ const std::string& fttype_to_string(const FTType& fttype); // class LLViewerFetchedTexture : public LLViewerTexture { - friend class LLTextureBar; // debug info only - friend class LLTextureView; // debug info only + friend class LLTextureBar; // debug info only + friend class LLTextureView; // debug info only protected: - /*virtual*/ ~LLViewerFetchedTexture(); + /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); - LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); - LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); + LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); public: - - struct Compare - { - // lhs < rhs - bool operator()(const LLPointer &lhs, const LLPointer &rhs) const - { - const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs; - const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs; - - // greater priority is "less" - const F32 lpriority = lhsp->mMaxVirtualSize; - const F32 rpriority = rhsp->mMaxVirtualSize; - if (lpriority > rpriority) // higher priority - return true; - if (lpriority < rpriority) - return false; - return lhsp < rhsp; - } - }; + + struct Compare + { + // lhs < rhs + bool operator()(const LLPointer &lhs, const LLPointer &rhs) const + { + const LLViewerFetchedTexture* lhsp = (const LLViewerFetchedTexture*)lhs; + const LLViewerFetchedTexture* rhsp = (const LLViewerFetchedTexture*)rhs; + + // greater priority is "less" + const F32 lpriority = lhsp->mMaxVirtualSize; + const F32 rpriority = rhsp->mMaxVirtualSize; + if (lpriority > rpriority) // higher priority + return true; + if (lpriority < rpriority) + return false; + return lhsp < rhsp; + } + }; public: - /*virtual*/ S8 getType() const override; - FTType getFTType() const; - /*virtual*/ void forceImmediateUpdate() override; - /*virtual*/ void dump() override; - - // Set callbacks to get called when the image gets updated with higher - // resolution versions. - void setLoadedCallback(loaded_callback_func cb, - S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, - void* userdata, LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause = FALSE); - bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; } - void pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); - void unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); - bool doLoadedCallbacks(); - void deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); - void clearCallbackEntryList() ; - - void addToCreateTexture(); + /*virtual*/ S8 getType() const override; + FTType getFTType() const; + /*virtual*/ void forceImmediateUpdate() override; + /*virtual*/ void dump() override; + + // Set callbacks to get called when the image gets updated with higher + // resolution versions. + void setLoadedCallback(loaded_callback_func cb, + S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, + void* userdata, LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause = FALSE); + bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; } + void pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + void unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + bool doLoadedCallbacks(); + void deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list); + void clearCallbackEntryList() ; + + void addToCreateTexture(); //call to determine if createTexture is necessary BOOL preCreateTexture(S32 usename = 0); - // ONLY call from LLViewerTextureList or ImageGL background thread - BOOL createTexture(S32 usename = 0); + // ONLY call from LLViewerTextureList or ImageGL background thread + BOOL createTexture(S32 usename = 0); void postCreateTexture(); void scheduleCreateTexture(); - void destroyTexture() ; + void destroyTexture() ; - virtual void processTextureStats() ; + virtual void processTextureStats() ; - BOOL needsAux() const { return mNeedsAux; } + BOOL needsAux() const { return mNeedsAux; } - // Host we think might have this image, used for baked av textures. - void setTargetHost(LLHost host) { mTargetHost = host; } - LLHost getTargetHost() const { return mTargetHost; } - - void updateVirtualSize() ; + // Host we think might have this image, used for baked av textures. + void setTargetHost(LLHost host) { mTargetHost = host; } + LLHost getTargetHost() const { return mTargetHost; } - S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; } - void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } + void updateVirtualSize() ; + + S32 getDesiredDiscardLevel() { return mDesiredDiscardLevel; } + void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } void setBoostLevel(S32 level) override; - bool updateFetch(); - bool setDebugFetching(S32 debug_level); - bool isInDebug() const { return mInDebug; } + bool updateFetch(); + bool setDebugFetching(S32 debug_level); + bool isInDebug() const { return mInDebug; } + + void setUnremovable(BOOL value) { mUnremovable = value; } + bool isUnremovable() const { return mUnremovable; } - void setUnremovable(BOOL value) { mUnremovable = value; } - bool isUnremovable() const { return mUnremovable; } - - void clearFetchedResults(); //clear all fetched results, for debug use. + void clearFetchedResults(); //clear all fetched results, for debug use. - // Override the computation of discard levels if we know the exact output - // size of the image. Used for UI textures to not decode, even if we have - // more data. - /*virtual*/ void setKnownDrawSize(S32 width, S32 height) override; + // Override the computation of discard levels if we know the exact output + // size of the image. Used for UI textures to not decode, even if we have + // more data. + /*virtual*/ void setKnownDrawSize(S32 width, S32 height) override; // Set the debug text of all Viewer Objects associated with this texture // to the specified text void setDebugText(const std::string& text); - void setIsMissingAsset(BOOL is_missing = true); - /*virtual*/ BOOL isMissingAsset() const override { return mIsMissingAsset; } - - // returns dimensions of original image for local files (before power of two scaling) - // and returns 0 for all asset system images - S32 getOriginalWidth() { return mOrigWidth; } - S32 getOriginalHeight() { return mOrigHeight; } - - BOOL isInImageList() const {return mInImageList ;} - void setInImageList(BOOL flag) {mInImageList = flag ;} - - LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;} - - U32 getFetchPriority() const { return mFetchPriority ;} - F32 getDownloadProgress() const {return mDownloadProgress ;} - - LLImageRaw* reloadRawImage(S8 discard_level) ; - void destroyRawImage(); - bool needsToSaveRawImage(); - - const std::string& getUrl() const {return mUrl;} - //--------------- - BOOL isDeleted() ; - BOOL isInactive() ; - BOOL isDeletionCandidate(); - void setDeletionCandidate() ; - void setInactive() ; - BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } - //--------------- - - void setForSculpt(); - BOOL forSculpt() const {return mForSculpt;} - BOOL isForSculptOnly() const; - - //raw image management - void checkCachedRawSculptImage() ; - LLImageRaw* getRawImage()const { return mRawImage ;} - S32 getRawImageLevel() const {return mRawDiscardLevel;} - LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;} - S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} - BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} - BOOL isRawImageValid()const { return mIsRawImageValid ; } - void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; - /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override; - void destroySavedRawImage() ; - LLImageRaw* getSavedRawImage() ; - BOOL hasSavedRawImage() const ; - F32 getElapsedLastReferencedSavedRawImageTime() const ; - BOOL isFullyLoaded() const; - - BOOL hasFetcher() const { return mHasFetcher;} - bool isFetching() const { return mIsFetching;} - void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} - - void forceToDeleteRequest(); - void loadFromFastCache(); - void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; } - bool isInFastCacheList() { return mInFastCacheList; } - - /*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline. + void setIsMissingAsset(BOOL is_missing = true); + /*virtual*/ BOOL isMissingAsset() const override { return mIsMissingAsset; } + + // returns dimensions of original image for local files (before power of two scaling) + // and returns 0 for all asset system images + S32 getOriginalWidth() { return mOrigWidth; } + S32 getOriginalHeight() { return mOrigHeight; } + + BOOL isInImageList() const {return mInImageList ;} + void setInImageList(BOOL flag) {mInImageList = flag ;} + + LLFrameTimer* getLastPacketTimer() {return &mLastPacketTimer;} + + U32 getFetchPriority() const { return mFetchPriority ;} + F32 getDownloadProgress() const {return mDownloadProgress ;} + + LLImageRaw* reloadRawImage(S8 discard_level) ; + void destroyRawImage(); + bool needsToSaveRawImage(); + + const std::string& getUrl() const {return mUrl;} + //--------------- + BOOL isDeleted() ; + BOOL isInactive() ; + BOOL isDeletionCandidate(); + void setDeletionCandidate() ; + void setInactive() ; + BOOL getUseDiscard() const { return mUseMipMaps && !mDontDiscard; } + //--------------- + + void setForSculpt(); + BOOL forSculpt() const {return mForSculpt;} + BOOL isForSculptOnly() const; + + //raw image management + void checkCachedRawSculptImage() ; + LLImageRaw* getRawImage()const { return mRawImage ;} + S32 getRawImageLevel() const {return mRawDiscardLevel;} + LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;} + S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} + BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} + BOOL isRawImageValid()const { return mIsRawImageValid ; } + void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; + /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override; + void destroySavedRawImage() ; + LLImageRaw* getSavedRawImage() ; + BOOL hasSavedRawImage() const ; + F32 getElapsedLastReferencedSavedRawImageTime() const ; + BOOL isFullyLoaded() const; + + BOOL hasFetcher() const { return mHasFetcher;} + bool isFetching() const { return mIsFetching;} + void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} + + void forceToDeleteRequest(); + void loadFromFastCache(); + void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; } + bool isInFastCacheList() { return mInFastCacheList; } + + /*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline. protected: - /*virtual*/ void switchToCachedImage() override; - S32 getCurrentDiscardLevelForFetching() ; - void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); + /*virtual*/ void switchToCachedImage() override; + S32 getCurrentDiscardLevelForFetching() ; + void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); private: - void init(bool firstinit) ; - void cleanup() ; + void init(bool firstinit) ; + void cleanup() ; - void saveRawImage() ; - void setCachedRawImage() ; + void saveRawImage() ; + void setCachedRawImage() ; - //for atlas - void resetFaceAtlas() ; - void invalidateAtlas(BOOL rebuild_geom) ; - BOOL insertToAtlas() ; + //for atlas + void resetFaceAtlas() ; + void invalidateAtlas(BOOL rebuild_geom) ; + BOOL insertToAtlas() ; private: - BOOL mFullyLoaded; - BOOL mInDebug; - BOOL mUnremovable; - BOOL mInFastCacheList; - BOOL mForceCallbackFetch; - -protected: - std::string mLocalFileName; - - S32 mOrigWidth; - S32 mOrigHeight; - - // Override the computation of discard levels if we know the exact output size of the image. - // Used for UI textures to not decode, even if we have more data. - S32 mKnownDrawWidth; - S32 mKnownDrawHeight; - BOOL mKnownDrawSizeChanged ; - std::string mUrl; - - S32 mRequestedDiscardLevel; - F32 mRequestedDownloadPriority; - S32 mFetchState; + BOOL mFullyLoaded; + BOOL mInDebug; + BOOL mUnremovable; + BOOL mInFastCacheList; + BOOL mForceCallbackFetch; + +protected: + std::string mLocalFileName; + + S32 mOrigWidth; + S32 mOrigHeight; + + // Override the computation of discard levels if we know the exact output size of the image. + // Used for UI textures to not decode, even if we have more data. + S32 mKnownDrawWidth; + S32 mKnownDrawHeight; + BOOL mKnownDrawSizeChanged ; + std::string mUrl; + + S32 mRequestedDiscardLevel; + F32 mRequestedDownloadPriority; + S32 mFetchState; S32 mLastFetchState = -1; // DEBUG - U32 mFetchPriority; - F32 mDownloadProgress; - F32 mFetchDeltaTime; - F32 mRequestDeltaTime; - S32 mMinDiscardLevel; - S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space - S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have - - S8 mNeedsAux; // We need to decode the auxiliary channels - S8 mHasAux; // We have aux channels - S8 mDecodingAux; // Are we decoding high components - S8 mIsRawImageValid; - S8 mHasFetcher; // We've made a fecth request - S8 mIsFetching; // Fetch request is active - bool mCanUseHTTP; //This texture can be fetched through http if true. - LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture. - - FTType mFTType; // What category of image is this - map tile, server bake, etc? - mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - - typedef std::list callback_list_t; - S8 mLoadedCallbackDesiredDiscardLevel; - BOOL mPauseLoadedCallBacks; - callback_list_t mLoadedCallbackList; - F32 mLastCallBackActiveTime; - - LLPointer mRawImage; - S32 mRawDiscardLevel = -1; - - // Used ONLY for cloth meshes right now. Make SURE you know what you're - // doing if you use it for anything else! - djs - LLPointer mAuxRawImage; - - //keep a copy of mRawImage for some special purposes - //when mForceToSaveRawImage is set. - BOOL mForceToSaveRawImage ; - BOOL mSaveRawImage; - LLPointer mSavedRawImage; - S32 mSavedRawDiscardLevel; - S32 mDesiredSavedRawDiscardLevel; - F32 mLastReferencedSavedRawImageTime ; - F32 mKeptSavedRawImageTime ; - - //a small version of the copy of the raw image (<= 64 * 64) - LLPointer mCachedRawImage; - S32 mCachedRawDiscardLevel; - BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. - - LLHost mTargetHost; // if invalid, just request from agent's simulator - - // Timers - LLFrameTimer mLastPacketTimer; // Time since last packet. - LLFrameTimer mStopFetchingTimer; // Time since mDecodePriority == 0.f. - - BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!) - // This needs to be atomic, since it is written both in the main thread - // and in the GL image worker thread... HB - LLAtomicBool mNeedsCreateTexture; - - BOOL mForSculpt ; //a flag if the texture is used as sculpt data. - BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. + U32 mFetchPriority; + F32 mDownloadProgress; + F32 mFetchDeltaTime; + F32 mRequestDeltaTime; + S32 mMinDiscardLevel; + S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space + S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have + + S8 mNeedsAux; // We need to decode the auxiliary channels + S8 mHasAux; // We have aux channels + S8 mDecodingAux; // Are we decoding high components + S8 mIsRawImageValid; + S8 mHasFetcher; // We've made a fecth request + S8 mIsFetching; // Fetch request is active + bool mCanUseHTTP; //This texture can be fetched through http if true. + LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture. + + FTType mFTType; // What category of image is this - map tile, server bake, etc? + mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + + typedef std::list callback_list_t; + S8 mLoadedCallbackDesiredDiscardLevel; + BOOL mPauseLoadedCallBacks; + callback_list_t mLoadedCallbackList; + F32 mLastCallBackActiveTime; + + LLPointer mRawImage; + S32 mRawDiscardLevel = -1; + + // Used ONLY for cloth meshes right now. Make SURE you know what you're + // doing if you use it for anything else! - djs + LLPointer mAuxRawImage; + + //keep a copy of mRawImage for some special purposes + //when mForceToSaveRawImage is set. + BOOL mForceToSaveRawImage ; + BOOL mSaveRawImage; + LLPointer mSavedRawImage; + S32 mSavedRawDiscardLevel; + S32 mDesiredSavedRawDiscardLevel; + F32 mLastReferencedSavedRawImageTime ; + F32 mKeptSavedRawImageTime ; + + //a small version of the copy of the raw image (<= 64 * 64) + LLPointer mCachedRawImage; + S32 mCachedRawDiscardLevel; + BOOL mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit. + + LLHost mTargetHost; // if invalid, just request from agent's simulator + + // Timers + LLFrameTimer mLastPacketTimer; // Time since last packet. + LLFrameTimer mStopFetchingTimer; // Time since mDecodePriority == 0.f. + + BOOL mInImageList; // TRUE if image is in list (in which case don't reset priority!) + // This needs to be atomic, since it is written both in the main thread + // and in the GL image worker thread... HB + LLAtomicBool mNeedsCreateTexture; + + BOOL mForSculpt ; //a flag if the texture is used as sculpt data. + BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally. public: static F32 sMaxVirtualSize; //maximum possible value of mMaxVirtualSize - static LLPointer sMissingAssetImagep; // Texture to show for an image asset that is not in the database - static LLPointer sWhiteImagep; // Texture to show NOTHING (whiteness) - static LLPointer sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local. - static LLPointer sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface - static LLPointer sDefaultIrradiancePBRp; // PBR: irradiance + static LLPointer sMissingAssetImagep; // Texture to show for an image asset that is not in the database + static LLPointer sWhiteImagep; // Texture to show NOTHING (whiteness) + static LLPointer sDefaultImagep; // "Default" texture for error cases, the only case of fetched texture which is generated in local. + static LLPointer sFlatNormalImagep; // Flat normal map denoting no bumpiness on a surface + static LLPointer sDefaultIrradiancePBRp; // PBR: irradiance // not sure why, but something is iffy about the loading of this particular texture, use the accessor instead of accessing directly static LLPointer sSmokeImagep; // Old "Default" translucent texture @@ -539,24 +539,24 @@ public: class LLViewerLODTexture : public LLViewerFetchedTexture { protected: - /*virtual*/ ~LLViewerLODTexture(){} + /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); - LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost(), BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); - /*virtual*/ S8 getType() const; - // Process image stats to determine priority/quality requirements. - /*virtual*/ void processTextureStats(); - bool isUpdateFrozen() ; + /*virtual*/ S8 getType() const; + // Process image stats to determine priority/quality requirements. + /*virtual*/ void processTextureStats(); + bool isUpdateFrozen() ; private: - void init(bool firstinit) ; - bool scaleDown() ; + void init(bool firstinit) ; + bool scaleDown() ; private: - F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard - F32 mCalculatedDiscardLevel; // Last calculated discard level + F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard + F32 mCalculatedDiscardLevel; // Last calculated discard level }; // @@ -566,135 +566,135 @@ private: class LLViewerMediaTexture : public LLViewerTexture { protected: - /*virtual*/ ~LLViewerMediaTexture() ; + /*virtual*/ ~LLViewerMediaTexture() ; public: - LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; - /*virtual*/ S8 getType() const; - void reinit(BOOL usemipmaps = TRUE); + /*virtual*/ S8 getType() const; + void reinit(BOOL usemipmaps = TRUE); - BOOL getUseMipMaps() {return mUseMipMaps ; } - void setUseMipMaps(BOOL mipmap) ; - - void setPlaying(BOOL playing) ; - BOOL isPlaying() const {return mIsPlaying;} - void setMediaImpl() ; + BOOL getUseMipMaps() {return mUseMipMaps ; } + void setUseMipMaps(BOOL mipmap) ; + + void setPlaying(BOOL playing) ; + BOOL isPlaying() const {return mIsPlaying;} + void setMediaImpl() ; virtual bool isViewerMediaTexture() const { return true; } - void initVirtualSize() ; - void invalidateMediaImpl() ; + void initVirtualSize() ; + void invalidateMediaImpl() ; - void addMediaToFace(LLFace* facep) ; - void removeMediaFromFace(LLFace* facep) ; + void addMediaToFace(LLFace* facep) ; + void removeMediaFromFace(LLFace* facep) ; - /*virtual*/ void addFace(U32 ch, LLFace* facep) ; - /*virtual*/ void removeFace(U32 ch, LLFace* facep) ; + /*virtual*/ void addFace(U32 ch, LLFace* facep) ; + /*virtual*/ void removeFace(U32 ch, LLFace* facep) ; - /*virtual*/ F32 getMaxVirtualSize() ; + /*virtual*/ F32 getMaxVirtualSize() ; private: - void switchTexture(U32 ch, LLFace* facep) ; - BOOL findFaces() ; - void stopPlaying() ; + void switchTexture(U32 ch, LLFace* facep) ; + BOOL findFaces() ; + void stopPlaying() ; private: - // - //an instant list, recording all faces referencing or can reference to this media texture. - //NOTE: it is NOT thread safe. - // - std::list< LLFace* > mMediaFaceList ; + // + //an instant list, recording all faces referencing or can reference to this media texture. + //NOTE: it is NOT thread safe. + // + std::list< LLFace* > mMediaFaceList ; - //an instant list keeping all textures which are replaced by the current media texture, - //is only used to avoid the removal of those textures from memory. - std::list< LLPointer > mTextureList ; + //an instant list keeping all textures which are replaced by the current media texture, + //is only used to avoid the removal of those textures from memory. + std::list< LLPointer > mTextureList ; - LLViewerMediaImpl* mMediaImplp ; - BOOL mIsPlaying ; - U32 mUpdateVirtualSizeTime ; + LLViewerMediaImpl* mMediaImplp ; + BOOL mIsPlaying ; + U32 mUpdateVirtualSizeTime ; public: - static void updateClass() ; - static void cleanUpClass() ; + static void updateClass() ; + static void cleanUpClass() ; - static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ; - static void removeMediaImplFromTexture(const LLUUID& media_id) ; + static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ; + static void removeMediaImplFromTexture(const LLUUID& media_id) ; private: - typedef std::map< LLUUID, LLPointer > media_map_t ; - static media_map_t sMediaMap ; + typedef std::map< LLUUID, LLPointer > media_map_t ; + static media_map_t sMediaMap ; }; //just an interface class, do not create instance from this class. class LLViewerTextureManager { private: - //make the constructor private to preclude creating instances from this class. - LLViewerTextureManager(){} + //make the constructor private to preclude creating instances from this class. + LLViewerTextureManager(){} public: //texture pipeline tester - static LLTexturePipelineTester* sTesterp ; - - //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture. - static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ; - - // - //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. - // - static void findFetchedTextures(const LLUUID& id, std::vector &output); - static void findTextures(const LLUUID& id, std::vector &output); - static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id, S32 tex_type); - static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; - - static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; - - // - //"get-texture" will create a new texture if the texture does not exist. - // - static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; - - static LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE); - static LLPointer getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; - static LLPointer getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ; - static LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; + static LLTexturePipelineTester* sTesterp ; + + //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture. + static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ; + + // + //"find-texture" just check if the texture exists, if yes, return it, otherwise return null. + // + static void findFetchedTextures(const LLUUID& id, std::vector &output); + static void findTextures(const LLUUID& id, std::vector &output); + static LLViewerFetchedTexture* findFetchedTexture(const LLUUID& id, S32 tex_type); + static LLViewerMediaTexture* findMediaTexture(const LLUUID& id) ; + + static LLViewerMediaTexture* createMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + + // + //"get-texture" will create a new texture if the texture does not exist. + // + static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; + + static LLPointer getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE); + static LLPointer getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; + static LLPointer getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) ; + static LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; static LLViewerFetchedTexture* getFetchedTexture(const LLImageRaw* raw, FTType type, bool usemipmaps); - static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, - FTType f_type = FTT_DEFAULT, - BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. - S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, - LLGLint internal_format = 0, - LLGLenum primary_format = 0, - LLHost request_from_host = LLHost() - ); - - static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, - FTType f_type = FTT_LOCAL_FILE, - BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, - S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, - LLGLint internal_format = 0, - LLGLenum primary_format = 0, - const LLUUID& force_id = LLUUID::null - ); - - static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, - FTType f_type, - BOOL usemipmap = TRUE, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, - S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, - LLGLint internal_format = 0, - LLGLenum primary_format = 0, - const LLUUID& force_id = LLUUID::null - ); - - static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; - - static void init() ; - static void cleanup() ; + static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + LLHost request_from_host = LLHost() + ); + + static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + FTType f_type, + BOOL usemipmap = TRUE, + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, + S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, + LLGLint internal_format = 0, + LLGLenum primary_format = 0, + const LLUUID& force_id = LLUUID::null + ); + + static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; + + static void init() ; + static void cleanup() ; }; // //this class is used for test/debug only @@ -703,91 +703,91 @@ public: // class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession { - enum - { - MIN_LARGE_IMAGE_AREA = 262144 //512 * 512 - }; + enum + { + MIN_LARGE_IMAGE_AREA = 262144 //512 * 512 + }; public: - LLTexturePipelineTester() ; - ~LLTexturePipelineTester() ; + LLTexturePipelineTester() ; + ~LLTexturePipelineTester() ; - void update(); - void updateTextureBindingStats(const LLViewerTexture* imagep) ; - void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) ; - void updateGrayTextureBinding() ; - void setStablizingTime() ; + void update(); + void updateTextureBindingStats(const LLViewerTexture* imagep) ; + void updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) ; + void updateGrayTextureBinding() ; + void setStablizingTime() ; private: - void reset() ; - void updateStablizingTime() ; + void reset() ; + void updateStablizingTime() ; - /*virtual*/ void outputTestRecord(LLSD* sd) ; + /*virtual*/ void outputTestRecord(LLSD* sd) ; private: - BOOL mPause ; + BOOL mPause ; private: - BOOL mUsingDefaultTexture; //if set, some textures are still gray. - - U32Bytes mTotalBytesUsed ; //total bytes of textures bound/used for the current frame. - U32Bytes mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256. - U32Bytes mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame. - U32Bytes mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256. - - // - //data size - // - U32Bytes mTotalBytesLoaded ; //total bytes fetched by texture pipeline - U32Bytes mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache - U32Bytes mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256. - U32Bytes mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties - - // - //time - //NOTE: the error tolerances of the following timers is one frame time. - // - F32 mStartFetchingTime ; - F32 mTotalGrayTime ; //total loading time when no gray textures. - F32 mTotalStablizingTime ; //total stablizing time when texture memory overflows - F32 mStartTimeLoadingSculpties ; //the start moment of loading sculpty images. - F32 mEndTimeLoadingSculpties ; //the end moment of loading sculpty images. - F32 mStartStablizingTime ; - F32 mEndStablizingTime ; + BOOL mUsingDefaultTexture; //if set, some textures are still gray. + + U32Bytes mTotalBytesUsed ; //total bytes of textures bound/used for the current frame. + U32Bytes mTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the current frame for images larger than 256 * 256. + U32Bytes mLastTotalBytesUsed ; //total bytes of textures bound/used for the previous frame. + U32Bytes mLastTotalBytesUsedForLargeImage ; //total bytes of textures bound/used for the previous frame for images larger than 256 * 256. + + // + //data size + // + U32Bytes mTotalBytesLoaded ; //total bytes fetched by texture pipeline + U32Bytes mTotalBytesLoadedFromCache ; //total bytes fetched by texture pipeline from local cache + U32Bytes mTotalBytesLoadedForLargeImage ; //total bytes fetched by texture pipeline for images larger than 256 * 256. + U32Bytes mTotalBytesLoadedForSculpties ; //total bytes fetched by texture pipeline for sculpties + + // + //time + //NOTE: the error tolerances of the following timers is one frame time. + // + F32 mStartFetchingTime ; + F32 mTotalGrayTime ; //total loading time when no gray textures. + F32 mTotalStablizingTime ; //total stablizing time when texture memory overflows + F32 mStartTimeLoadingSculpties ; //the start moment of loading sculpty images. + F32 mEndTimeLoadingSculpties ; //the end moment of loading sculpty images. + F32 mStartStablizingTime ; + F32 mEndStablizingTime ; private: - // - //The following members are used for performance analyzing - // - class LLTextureTestSession : public LLTestSession - { - public: - LLTextureTestSession() ; - /*virtual*/ ~LLTextureTestSession() ; - - void reset() ; - - F32 mTotalGrayTime ; - F32 mTotalStablizingTime ; - F32 mStartTimeLoadingSculpties ; - F32 mTotalTimeLoadingSculpties ; - - S32 mTotalBytesLoaded ; - S32 mTotalBytesLoadedFromCache ; - S32 mTotalBytesLoadedForLargeImage ; - S32 mTotalBytesLoadedForSculpties ; - - typedef struct _texture_instant_preformance_t - { - S32 mAverageBytesUsedPerSecond ; - S32 mAverageBytesUsedForLargeImagePerSecond ; - F32 mAveragePercentageBytesUsedPerSecond ; - F32 mTime ; - }texture_instant_preformance_t ; - std::vector mInstantPerformanceList ; - S32 mInstantPerformanceListCounter ; - }; - - /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ; - /*virtual*/ void compareTestSessions(llofstream* os) ; + // + //The following members are used for performance analyzing + // + class LLTextureTestSession : public LLTestSession + { + public: + LLTextureTestSession() ; + /*virtual*/ ~LLTextureTestSession() ; + + void reset() ; + + F32 mTotalGrayTime ; + F32 mTotalStablizingTime ; + F32 mStartTimeLoadingSculpties ; + F32 mTotalTimeLoadingSculpties ; + + S32 mTotalBytesLoaded ; + S32 mTotalBytesLoadedFromCache ; + S32 mTotalBytesLoadedForLargeImage ; + S32 mTotalBytesLoadedForSculpties ; + + typedef struct _texture_instant_preformance_t + { + S32 mAverageBytesUsedPerSecond ; + S32 mAverageBytesUsedForLargeImagePerSecond ; + F32 mAveragePercentageBytesUsedPerSecond ; + F32 mTime ; + }texture_instant_preformance_t ; + std::vector mInstantPerformanceList ; + S32 mInstantPerformanceListCounter ; + }; + + /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ; + /*virtual*/ void compareTestSessions(llofstream* os) ; }; #endif diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a0b0fabb66..9f91ecf41c 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerwindow.cpp * @brief Implementation of the LLViewerWindow class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -62,7 +62,7 @@ // // linden library includes -#include "llaudioengine.h" // mute on minimize +#include "llaudioengine.h" // mute on minimize #include "llchatentry.h" #include "indra_constants.h" #include "llassetstorage.h" @@ -166,7 +166,7 @@ #include "lltoolselectland.h" #include "lltrans.h" #include "lluictrlfactory.h" -#include "llurldispatcher.h" // SLURL from other app instance +#include "llurldispatcher.h" // SLURL from other app instance #include "llversioninfo.h" #include "llvieweraudio.h" #include "llviewercamera.h" @@ -231,31 +231,31 @@ extern BOOL gResizeScreenTexture; extern BOOL gCubeSnapshot; extern BOOL gSnapshotNoPost; -LLViewerWindow *gViewerWindow = NULL; +LLViewerWindow *gViewerWindow = NULL; -LLFrameTimer gAwayTimer; -LLFrameTimer gAwayTriggerTimer; +LLFrameTimer gAwayTimer; +LLFrameTimer gAwayTriggerTimer; -BOOL gShowOverlayTitle = FALSE; +BOOL gShowOverlayTitle = FALSE; LLViewerObject* gDebugRaycastObject = NULL; LLVOPartGroup* gDebugRaycastParticle = NULL; LLVector4a gDebugRaycastIntersection; -LLVector4a gDebugRaycastParticleIntersection; +LLVector4a gDebugRaycastParticleIntersection; LLVector2 gDebugRaycastTexCoord; LLVector4a gDebugRaycastNormal; LLVector4a gDebugRaycastTangent; -S32 gDebugRaycastFaceHit; +S32 gDebugRaycastFaceHit; S32 gDebugRaycastGLTFNodeHit; S32 gDebugRaycastGLTFPrimitiveHit; -LLVector4a gDebugRaycastStart; -LLVector4a gDebugRaycastEnd; +LLVector4a gDebugRaycastStart; +LLVector4a gDebugRaycastEnd; // HUD display lines in lower right -BOOL gDisplayWindInfo = FALSE; -BOOL gDisplayCameraPos = FALSE; -BOOL gDisplayFOV = FALSE; -BOOL gDisplayBadge = FALSE; +BOOL gDisplayWindInfo = FALSE; +BOOL gDisplayCameraPos = FALSE; +BOOL gDisplayFOV = FALSE; +BOOL gDisplayBadge = FALSE; static const U8 NO_FACE = 255; BOOL gQuietSnapshot = FALSE; @@ -269,8 +269,8 @@ static const F32 MIN_DISPLAY_SCALE = 0.75f; static const char KEY_MOUSELOOK = 'M'; -static LLCachedControl sSnapshotBaseName(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); -static LLCachedControl sSnapshotDir(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseDir", "")); +static LLCachedControl sSnapshotBaseName(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); +static LLCachedControl sSnapshotDir(LLCachedControl(gSavedPerAccountSettings, "SnapshotBaseDir", "")); LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); @@ -278,40 +278,40 @@ LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity") class RecordToChatConsoleRecorder : public LLError::Recorder { public: - virtual void recordMessage(LLError::ELevel level, - const std::string& message) - { - //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread - - // only log warnings to chat console - //if (level == LLError::LEVEL_WARN) - //{ - //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance("chat"); - //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) - //{ - // LLChat chat; - // chat.mText = message; - // chat.mSourceType = CHAT_SOURCE_SYSTEM; - - // chat_floater->addChat(chat, FALSE, FALSE); - //} - //} - } + virtual void recordMessage(LLError::ELevel level, + const std::string& message) + { + //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread + + // only log warnings to chat console + //if (level == LLError::LEVEL_WARN) + //{ + //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance("chat"); + //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) + //{ + // LLChat chat; + // chat.mText = message; + // chat.mSourceType = CHAT_SOURCE_SYSTEM; + + // chat_floater->addChat(chat, FALSE, FALSE); + //} + //} + } }; class RecordToChatConsole : public LLSingleton { - LLSINGLETON(RecordToChatConsole); + LLSINGLETON(RecordToChatConsole); public: - void startRecorder() { LLError::addRecorder(mRecorder); } - void stopRecorder() { LLError::removeRecorder(mRecorder); } + void startRecorder() { LLError::addRecorder(mRecorder); } + void stopRecorder() { LLError::removeRecorder(mRecorder); } private: - LLError::RecorderPtr mRecorder; + LLError::RecorderPtr mRecorder; }; RecordToChatConsole::RecordToChatConsole(): - mRecorder(new RecordToChatConsoleRecorder()) + mRecorder(new RecordToChatConsoleRecorder()) { mRecorder->showTags(false); mRecorder->showLocation(false); @@ -421,214 +421,214 @@ static LLTrace::BlockTimerStatHandle FTM_DISPLAY_DEBUG_TEXT("Display Debug Text" class LLDebugText { private: - struct Line - { - Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {} - std::string text; - S32 x,y; - }; - - LLViewerWindow *mWindow; - - typedef std::vector line_list_t; - line_list_t mLineList; - LLColor4 mTextColor; - - LLColor4 mBackColor; - LLRect mBackRectCamera1; - LLRect mBackRectCamera2; - - void addText(S32 x, S32 y, const std::string &text) - { - mLineList.push_back(Line(text, x, y)); - } - - void clearText() { mLineList.clear(); } - + struct Line + { + Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {} + std::string text; + S32 x,y; + }; + + LLViewerWindow *mWindow; + + typedef std::vector line_list_t; + line_list_t mLineList; + LLColor4 mTextColor; + + LLColor4 mBackColor; + LLRect mBackRectCamera1; + LLRect mBackRectCamera2; + + void addText(S32 x, S32 y, const std::string &text) + { + mLineList.push_back(Line(text, x, y)); + } + + void clearText() { mLineList.clear(); } + public: - LLDebugText(LLViewerWindow* window) : mWindow(window) {} - - void update() - { - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - clearText(); - return; - } - - static LLCachedControl log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - - std::string wind_vel_text; - std::string wind_vector_text; - std::string rwind_vel_text; - std::string rwind_vector_text; - std::string audio_text; - - static const std::string beacon_particle = LLTrans::getString("BeaconParticle"); - static const std::string beacon_physical = LLTrans::getString("BeaconPhysical"); - static const std::string beacon_scripted = LLTrans::getString("BeaconScripted"); - static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch"); - static const std::string beacon_sound = LLTrans::getString("BeaconSound"); - static const std::string beacon_media = LLTrans::getString("BeaconMedia"); - static const std::string beacon_sun = LLTrans::getString("BeaconSun"); - static const std::string beacon_moon = LLTrans::getString("BeaconMoon"); - static const std::string particle_hiding = LLTrans::getString("ParticleHiding"); - - // Draw the statistics in a light gray - // and in a thin font - mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); - - // Draw stuff growing up from right lower corner of screen - S32 x_right = mWindow->getWorldViewWidthScaled(); - S32 xpos = x_right - 400; - xpos = llmax(xpos, 0); - S32 ypos = 64; - const S32 y_inc = 20; - - // Camera matrix text is hard to see again a white background - // Add a dark background underneath the matrices for readability (contrast) - mBackRectCamera1.mLeft = xpos; - mBackRectCamera1.mRight = x_right; - mBackRectCamera1.mTop = -1; - mBackRectCamera1.mBottom = -1; - mBackRectCamera2 = mBackRectCamera1; - - mBackColor = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" ); - - clearText(); - - if (gSavedSettings.getBOOL("DebugShowTime")) - { - F32 time = gFrameTimeSeconds; - S32 hours = (S32)(time / (60*60)); - S32 mins = (S32)((time - hours*(60*60)) / 60); - S32 secs = (S32)((time - hours*(60*60) - mins*60)); - addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; - } - - if (gSavedSettings.getBOOL("DebugShowMemory")) - { - addText(xpos, ypos, - STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); - ypos += y_inc; - } - - if (gDisplayCameraPos) - { - std::string camera_view_text; - std::string camera_center_text; - std::string agent_view_text; - std::string agent_left_text; - std::string agent_center_text; - std::string agent_root_center_text; - - LLVector3d tvector; // Temporary vector to hold data for printing. - - // Update camera center, camera view, wind info every other frame - tvector = gAgent.getPositionGlobal(); - agent_center_text = llformat("AgentCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - if (isAgentAvatarValid()) - { - tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); - agent_root_center_text = llformat("AgentRootCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - } - else - { - agent_root_center_text = "---"; - } - - - tvector = LLVector4(gAgent.getFrameAgent().getAtAxis()); - agent_view_text = llformat("AgentAtAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis()); - agent_left_text = llformat("AgentLeftAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = gAgentCamera.getCameraPositionGlobal(); - camera_center_text = llformat("CameraCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis()); - camera_view_text = llformat("CameraAtAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - addText(xpos, ypos, agent_center_text); ypos += y_inc; - addText(xpos, ypos, agent_root_center_text); ypos += y_inc; - addText(xpos, ypos, agent_view_text); ypos += y_inc; - addText(xpos, ypos, agent_left_text); ypos += y_inc; - addText(xpos, ypos, camera_center_text); ypos += y_inc; - addText(xpos, ypos, camera_view_text); ypos += y_inc; - } - - if (gDisplayWindInfo) - { - wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec()); - wind_vector_text = llformat("Wind vector %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]); - rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec()); - rwind_vector_text = llformat("RWind vec %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]); - - addText(xpos, ypos, wind_vel_text); ypos += y_inc; - addText(xpos, ypos, wind_vector_text); ypos += y_inc; - addText(xpos, ypos, rwind_vel_text); ypos += y_inc; - addText(xpos, ypos, rwind_vector_text); ypos += y_inc; - } - if (gDisplayWindInfo) - { - audio_text = llformat("Audio for wind: %d", gAudiop ? gAudiop->isWindEnabled() : -1); - addText(xpos, ypos, audio_text); ypos += y_inc; - } - if (gDisplayFOV) - { - addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); - ypos += y_inc; - } - if (gDisplayBadge) - { - addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); - ypos += y_inc * 2; - } - - /*if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - addText(xpos + 200, ypos, llformat("Flycam")); - ypos += y_inc; - }*/ - - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) - { - LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); - - //show streaming cost/triangle count of known prims in current region OR selection - { - F32 cost = 0.f; - S32 count = 0; - S32 vcount = 0; - S32 object_count = 0; - S32 total_bytes = 0; - S32 visible_bytes = 0; - - const char* label = "Region"; - if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0) - { //region - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - for (U32 i = 0; i < gObjectList.getNumObjects(); ++i) - { - LLViewerObject* object = gObjectList.getObject(i); - if (object && - object->getRegion() == region && - object->getVolume()) - { - object_count++; - S32 bytes = 0; - S32 visible = 0; - cost += object->getStreamingCost(); + LLDebugText(LLViewerWindow* window) : mWindow(window) {} + + void update() + { + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + clearText(); + return; + } + + static LLCachedControl log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; + + std::string wind_vel_text; + std::string wind_vector_text; + std::string rwind_vel_text; + std::string rwind_vector_text; + std::string audio_text; + + static const std::string beacon_particle = LLTrans::getString("BeaconParticle"); + static const std::string beacon_physical = LLTrans::getString("BeaconPhysical"); + static const std::string beacon_scripted = LLTrans::getString("BeaconScripted"); + static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch"); + static const std::string beacon_sound = LLTrans::getString("BeaconSound"); + static const std::string beacon_media = LLTrans::getString("BeaconMedia"); + static const std::string beacon_sun = LLTrans::getString("BeaconSun"); + static const std::string beacon_moon = LLTrans::getString("BeaconMoon"); + static const std::string particle_hiding = LLTrans::getString("ParticleHiding"); + + // Draw the statistics in a light gray + // and in a thin font + mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); + + // Draw stuff growing up from right lower corner of screen + S32 x_right = mWindow->getWorldViewWidthScaled(); + S32 xpos = x_right - 400; + xpos = llmax(xpos, 0); + S32 ypos = 64; + const S32 y_inc = 20; + + // Camera matrix text is hard to see again a white background + // Add a dark background underneath the matrices for readability (contrast) + mBackRectCamera1.mLeft = xpos; + mBackRectCamera1.mRight = x_right; + mBackRectCamera1.mTop = -1; + mBackRectCamera1.mBottom = -1; + mBackRectCamera2 = mBackRectCamera1; + + mBackColor = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" ); + + clearText(); + + if (gSavedSettings.getBOOL("DebugShowTime")) + { + F32 time = gFrameTimeSeconds; + S32 hours = (S32)(time / (60*60)); + S32 mins = (S32)((time - hours*(60*60)) / 60); + S32 secs = (S32)((time - hours*(60*60) - mins*60)); + addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; + } + + if (gSavedSettings.getBOOL("DebugShowMemory")) + { + addText(xpos, ypos, + STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); + ypos += y_inc; + } + + if (gDisplayCameraPos) + { + std::string camera_view_text; + std::string camera_center_text; + std::string agent_view_text; + std::string agent_left_text; + std::string agent_center_text; + std::string agent_root_center_text; + + LLVector3d tvector; // Temporary vector to hold data for printing. + + // Update camera center, camera view, wind info every other frame + tvector = gAgent.getPositionGlobal(); + agent_center_text = llformat("AgentCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + if (isAgentAvatarValid()) + { + tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); + agent_root_center_text = llformat("AgentRootCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + } + else + { + agent_root_center_text = "---"; + } + + + tvector = LLVector4(gAgent.getFrameAgent().getAtAxis()); + agent_view_text = llformat("AgentAtAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis()); + agent_left_text = llformat("AgentLeftAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = gAgentCamera.getCameraPositionGlobal(); + camera_center_text = llformat("CameraCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis()); + camera_view_text = llformat("CameraAtAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + addText(xpos, ypos, agent_center_text); ypos += y_inc; + addText(xpos, ypos, agent_root_center_text); ypos += y_inc; + addText(xpos, ypos, agent_view_text); ypos += y_inc; + addText(xpos, ypos, agent_left_text); ypos += y_inc; + addText(xpos, ypos, camera_center_text); ypos += y_inc; + addText(xpos, ypos, camera_view_text); ypos += y_inc; + } + + if (gDisplayWindInfo) + { + wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec()); + wind_vector_text = llformat("Wind vector %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]); + rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec()); + rwind_vector_text = llformat("RWind vec %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]); + + addText(xpos, ypos, wind_vel_text); ypos += y_inc; + addText(xpos, ypos, wind_vector_text); ypos += y_inc; + addText(xpos, ypos, rwind_vel_text); ypos += y_inc; + addText(xpos, ypos, rwind_vector_text); ypos += y_inc; + } + if (gDisplayWindInfo) + { + audio_text = llformat("Audio for wind: %d", gAudiop ? gAudiop->isWindEnabled() : -1); + addText(xpos, ypos, audio_text); ypos += y_inc; + } + if (gDisplayFOV) + { + addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); + ypos += y_inc; + } + if (gDisplayBadge) + { + addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); + ypos += y_inc * 2; + } + + /*if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + addText(xpos + 200, ypos, llformat("Flycam")); + ypos += y_inc; + }*/ + + if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + { + LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); + + //show streaming cost/triangle count of known prims in current region OR selection + { + F32 cost = 0.f; + S32 count = 0; + S32 vcount = 0; + S32 object_count = 0; + S32 total_bytes = 0; + S32 visible_bytes = 0; + + const char* label = "Region"; + if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0) + { //region + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + for (U32 i = 0; i < gObjectList.getNumObjects(); ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && + object->getRegion() == region && + object->getVolume()) + { + object_count++; + S32 bytes = 0; + S32 visible = 0; + cost += object->getStreamingCost(); LLMeshCostData costs; if (object->getCostData(costs)) { @@ -636,96 +636,96 @@ public: visible = costs.getSizeByLOD(object->getLOD()); } - S32 vt = 0; - count += object->getTriangleCount(&vt); - vcount += vt; - total_bytes += bytes; - visible_bytes += visible; - } - } - } - } - else - { - label = "Selection"; - cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes); - count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount); - object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - } - - addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost)); - ypos += y_inc; - - addText(xpos, ypos, llformat(" %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects", - count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); - ypos += y_inc; - - } - - addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount)); - ypos += y_inc; - - addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount)); - ypos += y_inc; - - addText(xpos, ypos, llformat("%d Render Calls", (U32)last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize))); + S32 vt = 0; + count += object->getTriangleCount(&vt); + vcount += vt; + total_bytes += bytes; + visible_bytes += visible; + } + } + } + } + else + { + label = "Selection"; + cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes); + count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount); + object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + } + + addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost)); + ypos += y_inc; + + addText(xpos, ypos, llformat(" %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects", + count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); + ypos += y_inc; + + } + + addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount)); ypos += y_inc; - addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); - ypos += y_inc; + addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount)); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d Render Calls", (U32)last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize))); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); + ypos += y_inc; - addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); + ypos += y_inc; - addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps)); + ypos += y_inc; - gPipeline.mTextureMatrixOps = 0; - gPipeline.mMatrixOpCount = 0; + gPipeline.mTextureMatrixOps = 0; + gPipeline.mMatrixOpCount = 0; - if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) - { + if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) + { addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", (U32)last_frame_recording.getMin(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMax(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMean(LLPipeline::sStatBatchSize))); - } + } + ypos += y_inc; + + addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls)); + LLRender::sUICalls = LLRender::sUIVerts = 0; + ypos += y_inc; + + addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount)); + ypos += y_inc; - addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls)); - LLRender::sUICalls = LLRender::sUIVerts = 0; - ypos += y_inc; + if (!LLOcclusionCullingGroup::sPendingQueries.empty()) + { + addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size())); + ypos += y_inc; + } + - addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount)); - - ypos += y_inc; + addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars)); + + ypos += y_inc; - if (!LLOcclusionCullingGroup::sPendingQueries.empty()) - { - addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size())); - ypos += y_inc; - } + addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); + ypos += y_inc; - addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars)); - - ypos += y_inc; + if (gMeshRepo.meshRezEnabled()) + { + addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); - addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); - - ypos += y_inc; + ypos += y_inc; - if (gMeshRepo.meshRezEnabled()) - { - addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); - - ypos += y_inc; - - addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, - LLMeshRepository::sHTTPRetryCount)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, + LLMeshRepository::sHTTPRetryCount)); + ypos += y_inc; - addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); + ypos += y_inc; - addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); + addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Skins/Decompositions Memory", LLMeshRepository::sCacheBytesSkins / (1024.f*1024.f), LLMeshRepository::sCacheBytesDecomps / (1024.f*1024.f))); @@ -733,72 +733,72 @@ public: addText(xpos, ypos, llformat("%.3f MB Mesh Headers Memory", LLMeshRepository::sCacheBytesHeaders / (1024.f*1024.f))); - ypos += y_inc; - } + ypos += y_inc; + } gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; - } - if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) - { - std::map sorted_avs; - - std::vector::iterator sort_iter = LLCharacter::sInstances.begin(); - while (sort_iter != LLCharacter::sInstances.end()) - { - LLVOAvatar* avatar = dynamic_cast(*sort_iter); - if (avatar && - !avatar->isDead()) // Not dead yet - { - // Stuff into a sorted map so the display is ordered - sorted_avs[avatar->getFullname()] = avatar; - } - sort_iter++; - } - - std::string trunc_name; - std::map::reverse_iterator av_iter = sorted_avs.rbegin(); // Put "A" at the top - while (av_iter != sorted_avs.rend()) - { - LLVOAvatar* avatar = av_iter->second; - - avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date - - trunc_name = utf8str_truncate(avatar->getFullname(), 16); - addText(xpos, ypos, llformat("%s : %s, complexity %d, area %.2f", - trunc_name.c_str(), + } + if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) + { + std::map sorted_avs; + + std::vector::iterator sort_iter = LLCharacter::sInstances.begin(); + while (sort_iter != LLCharacter::sInstances.end()) + { + LLVOAvatar* avatar = dynamic_cast(*sort_iter); + if (avatar && + !avatar->isDead()) // Not dead yet + { + // Stuff into a sorted map so the display is ordered + sorted_avs[avatar->getFullname()] = avatar; + } + sort_iter++; + } + + std::string trunc_name; + std::map::reverse_iterator av_iter = sorted_avs.rbegin(); // Put "A" at the top + while (av_iter != sorted_avs.rend()) + { + LLVOAvatar* avatar = av_iter->second; + + avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date + + trunc_name = utf8str_truncate(avatar->getFullname(), 16); + addText(xpos, ypos, llformat("%s : %s, complexity %d, area %.2f", + trunc_name.c_str(), LLVOAvatar::rezStatusToString(avatar->getRezzedStatus()).c_str(), - avatar->getVisualComplexity(), - avatar->getAttachmentSurfaceArea())); - ypos += y_inc; - av_iter++; - } - } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) - { - char camera_lines[8][32]; - memset(camera_lines, ' ', sizeof(camera_lines)); - - // Projection last column is always <0,0,-1.0001,0> - // Projection last row is always <0,0,-0.2> - mBackRectCamera1.mBottom = ypos - y_inc + 2; - MATRIX_ROW_N32_TO_STR(gGLProjection, 12,camera_lines[7]); addText(xpos, ypos, std::string(camera_lines[7])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLProjection, 8,camera_lines[6]); addText(xpos, ypos, std::string(camera_lines[6])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLProjection, 4,camera_lines[5]); addText(xpos, ypos, std::string(camera_lines[5])); ypos += y_inc; mBackRectCamera1.mTop = ypos + 2; - MATRIX_ROW_N32_TO_STR(gGLProjection, 0,camera_lines[4]); addText(xpos, ypos, std::string(camera_lines[4])); ypos += y_inc; mBackRectCamera2.mBottom = ypos + 2; - - addText(xpos, ypos, "Projection Matrix"); - ypos += y_inc; - - // View last column is always <0,0,0,1> - MATRIX_ROW_F32_TO_STR(gGLModelView, 12,camera_lines[3]); addText(xpos, ypos, std::string(camera_lines[3])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLModelView, 8,camera_lines[2]); addText(xpos, ypos, std::string(camera_lines[2])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLModelView, 4,camera_lines[1]); addText(xpos, ypos, std::string(camera_lines[1])); ypos += y_inc; mBackRectCamera2.mTop = ypos + 2; - MATRIX_ROW_N32_TO_STR(gGLModelView, 0,camera_lines[0]); addText(xpos, ypos, std::string(camera_lines[0])); ypos += y_inc; - - addText(xpos, ypos, "View Matrix"); - ypos += y_inc; - } - // disable use of glReadPixels which messes up nVidia nSight graphics debugging + avatar->getVisualComplexity(), + avatar->getAttachmentSurfaceArea())); + ypos += y_inc; + av_iter++; + } + } + if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + { + char camera_lines[8][32]; + memset(camera_lines, ' ', sizeof(camera_lines)); + + // Projection last column is always <0,0,-1.0001,0> + // Projection last row is always <0,0,-0.2> + mBackRectCamera1.mBottom = ypos - y_inc + 2; + MATRIX_ROW_N32_TO_STR(gGLProjection, 12,camera_lines[7]); addText(xpos, ypos, std::string(camera_lines[7])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLProjection, 8,camera_lines[6]); addText(xpos, ypos, std::string(camera_lines[6])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLProjection, 4,camera_lines[5]); addText(xpos, ypos, std::string(camera_lines[5])); ypos += y_inc; mBackRectCamera1.mTop = ypos + 2; + MATRIX_ROW_N32_TO_STR(gGLProjection, 0,camera_lines[4]); addText(xpos, ypos, std::string(camera_lines[4])); ypos += y_inc; mBackRectCamera2.mBottom = ypos + 2; + + addText(xpos, ypos, "Projection Matrix"); + ypos += y_inc; + + // View last column is always <0,0,0,1> + MATRIX_ROW_F32_TO_STR(gGLModelView, 12,camera_lines[3]); addText(xpos, ypos, std::string(camera_lines[3])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLModelView, 8,camera_lines[2]); addText(xpos, ypos, std::string(camera_lines[2])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLModelView, 4,camera_lines[1]); addText(xpos, ypos, std::string(camera_lines[1])); ypos += y_inc; mBackRectCamera2.mTop = ypos + 2; + MATRIX_ROW_N32_TO_STR(gGLModelView, 0,camera_lines[0]); addText(xpos, ypos, std::string(camera_lines[0])); ypos += y_inc; + + addText(xpos, ypos, "View Matrix"); + ypos += y_inc; + } + // disable use of glReadPixels which messes up nVidia nSight graphics debugging if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) { U8 color[4]; @@ -807,165 +807,165 @@ public: // Convert x,y to raw pixel coords S32 x_raw = llround(coord.mX * gViewerWindow->getWindowWidthRaw() / (F32) gViewerWindow->getWindowWidthScaled()); S32 y_raw = llround(coord.mY * gViewerWindow->getWindowHeightRaw() / (F32) gViewerWindow->getWindowHeightScaled()); - + glReadPixels(x_raw, y_raw, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color); addText(xpos, ypos, llformat("Pixel <%1d, %1d> R:%1d G:%1d B:%1d A:%1d", x_raw, y_raw, color[0], color[1], color[2], color[3])); ypos += y_inc; } // only display these messages if we are actually rendering beacons at this moment - if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons")) - { - if (LLPipeline::getRenderMOAPBeacons()) - { - addText(xpos, ypos, "Viewing media beacons (white)"); - ypos += y_inc; - } - - if (LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES)) - { - addText(xpos, ypos, particle_hiding); - ypos += y_inc; - } - - if (LLPipeline::getRenderParticleBeacons()) - { - addText(xpos, ypos, "Viewing particle beacons (blue)"); - ypos += y_inc; - } - - if (LLPipeline::getRenderSoundBeacons()) - { - addText(xpos, ypos, "Viewing sound beacons (yellow)"); - ypos += y_inc; - } - - if (LLPipeline::getRenderScriptedBeacons()) - { - addText(xpos, ypos, beacon_scripted); - ypos += y_inc; - } - else - if (LLPipeline::getRenderScriptedTouchBeacons()) - { - addText(xpos, ypos, beacon_scripted_touch); - ypos += y_inc; - } - - if (LLPipeline::getRenderPhysicalBeacons()) - { - addText(xpos, ypos, "Viewing physical object beacons (green)"); - ypos += y_inc; - } - } - - static LLUICachedControl show_sun_beacon("sunbeacon", false); - static LLUICachedControl show_moon_beacon("moonbeacon", false); - - if (show_sun_beacon) - { - addText(xpos, ypos, beacon_sun); - ypos += y_inc; - } - if (show_moon_beacon) - { - addText(xpos, ypos, beacon_moon); - ypos += y_inc; - } - - if(log_texture_traffic) - { - U32 old_y = ypos ; - for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++) - { - if(gTotalTextureBytesPerBoostLevel[i] > (S32Bytes)0) - { - addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, F32Megabytes(gTotalTextureBytesPerBoostLevel[i]).value())); - ypos += y_inc; - } - } - if(ypos != old_y) - { - addText(xpos, ypos, "Network traffic for textures:"); - ypos += y_inc; - } - } - - if (gSavedSettings.getBOOL("DebugShowTextureInfo")) - { - LLViewerObject* objectp = NULL ; - - LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); - if (nodep) - { - objectp = nodep->getObject(); - } - - if (objectp && !objectp->isDead()) - { - S32 num_faces = objectp->mDrawable->getNumFaces() ; - std::set tex_list; - - for(S32 i = 0 ; i < num_faces; i++) - { - LLFace* facep = objectp->mDrawable->getFace(i) ; - if(facep) - { - LLViewerFetchedTexture* tex = dynamic_cast(facep->getTexture()) ; - if(tex) - { - if(tex_list.find(tex) != tex_list.end()) - { - continue ; //already displayed. - } - tex_list.insert(tex); - - std::string uuid_str; - tex->getID().toString(uuid_str); - uuid_str = uuid_str.substr(0,7); - - addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); - ypos += y_inc; - - addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), - tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); - ypos += y_inc; - } - } - } - } - } - } - - void draw() - { - LL_RECORD_BLOCK_TIME(FTM_DISPLAY_DEBUG_TEXT); - - // Camera matrix text is hard to see again a white background - // Add a dark background underneath the matrices for readability (contrast) - if (mBackRectCamera1.mTop >= 0) - { - mBackColor.setAlpha( 0.75f ); - gl_rect_2d(mBackRectCamera1, mBackColor, true); - - mBackColor.setAlpha( 0.66f ); - gl_rect_2d(mBackRectCamera2, mBackColor, true); - } - - for (line_list_t::iterator iter = mLineList.begin(); - iter != mLineList.end(); ++iter) - { - const Line& line = *iter; - LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor, - LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - } - } + if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons")) + { + if (LLPipeline::getRenderMOAPBeacons()) + { + addText(xpos, ypos, "Viewing media beacons (white)"); + ypos += y_inc; + } + + if (LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES)) + { + addText(xpos, ypos, particle_hiding); + ypos += y_inc; + } + + if (LLPipeline::getRenderParticleBeacons()) + { + addText(xpos, ypos, "Viewing particle beacons (blue)"); + ypos += y_inc; + } + + if (LLPipeline::getRenderSoundBeacons()) + { + addText(xpos, ypos, "Viewing sound beacons (yellow)"); + ypos += y_inc; + } + + if (LLPipeline::getRenderScriptedBeacons()) + { + addText(xpos, ypos, beacon_scripted); + ypos += y_inc; + } + else + if (LLPipeline::getRenderScriptedTouchBeacons()) + { + addText(xpos, ypos, beacon_scripted_touch); + ypos += y_inc; + } + + if (LLPipeline::getRenderPhysicalBeacons()) + { + addText(xpos, ypos, "Viewing physical object beacons (green)"); + ypos += y_inc; + } + } + + static LLUICachedControl show_sun_beacon("sunbeacon", false); + static LLUICachedControl show_moon_beacon("moonbeacon", false); + + if (show_sun_beacon) + { + addText(xpos, ypos, beacon_sun); + ypos += y_inc; + } + if (show_moon_beacon) + { + addText(xpos, ypos, beacon_moon); + ypos += y_inc; + } + + if(log_texture_traffic) + { + U32 old_y = ypos ; + for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++) + { + if(gTotalTextureBytesPerBoostLevel[i] > (S32Bytes)0) + { + addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, F32Megabytes(gTotalTextureBytesPerBoostLevel[i]).value())); + ypos += y_inc; + } + } + if(ypos != old_y) + { + addText(xpos, ypos, "Network traffic for textures:"); + ypos += y_inc; + } + } + + if (gSavedSettings.getBOOL("DebugShowTextureInfo")) + { + LLViewerObject* objectp = NULL ; + + LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); + if (nodep) + { + objectp = nodep->getObject(); + } + + if (objectp && !objectp->isDead()) + { + S32 num_faces = objectp->mDrawable->getNumFaces() ; + std::set tex_list; + + for(S32 i = 0 ; i < num_faces; i++) + { + LLFace* facep = objectp->mDrawable->getFace(i) ; + if(facep) + { + LLViewerFetchedTexture* tex = dynamic_cast(facep->getTexture()) ; + if(tex) + { + if(tex_list.find(tex) != tex_list.end()) + { + continue ; //already displayed. + } + tex_list.insert(tex); + + std::string uuid_str; + tex->getID().toString(uuid_str); + uuid_str = uuid_str.substr(0,7); + + addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); + ypos += y_inc; + + addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), + tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); + ypos += y_inc; + } + } + } + } + } + } + + void draw() + { + LL_RECORD_BLOCK_TIME(FTM_DISPLAY_DEBUG_TEXT); + + // Camera matrix text is hard to see again a white background + // Add a dark background underneath the matrices for readability (contrast) + if (mBackRectCamera1.mTop >= 0) + { + mBackColor.setAlpha( 0.75f ); + gl_rect_2d(mBackRectCamera1, mBackColor, true); + + mBackColor.setAlpha( 0.66f ); + gl_rect_2d(mBackRectCamera2, mBackColor, true); + } + + for (line_list_t::iterator iter = mLineList.begin(); + iter != mLineList.end(); ++iter) + { + const Line& line = *iter; + LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor, + LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + } + } }; void LLViewerWindow::updateDebugText() { - mDebugText->update(); + mDebugText->update(); } //////////////////////////////////////////////////////////////////////////// @@ -974,16 +974,16 @@ void LLViewerWindow::updateDebugText() // LLViewerWindow::Params::Params() -: title("title"), - name("name"), - x("x"), - y("y"), - width("width"), - height("height"), - min_width("min_width"), - min_height("min_height"), - fullscreen("fullscreen", false), - ignore_pixel_depth("ignore_pixel_depth", false) +: title("title"), + name("name"), + x("x"), + y("y"), + width("width"), + height("height"), + min_width("min_width"), + min_height("min_height"), + fullscreen("fullscreen", false), + ignore_pixel_depth("ignore_pixel_depth", false) {} @@ -1000,167 +1000,167 @@ void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask) BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down, bool& is_toolmgr_action) { - const char* buttonname = ""; - const char* buttonstatestr = ""; - S32 x = pos.mX; - S32 y = pos.mY; - x = ll_round((F32)x / mDisplayScale.mV[VX]); - y = ll_round((F32)y / mDisplayScale.mV[VY]); + const char* buttonname = ""; + const char* buttonstatestr = ""; + S32 x = pos.mX; + S32 y = pos.mY; + x = ll_round((F32)x / mDisplayScale.mV[VX]); + y = ll_round((F32)y / mDisplayScale.mV[VY]); - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice gViewerInput.handleGlobalBindsMouse(clicktype, mask, down); - // only send mouse clicks to UI if UI is visible - if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - - if (down) - { - buttonstatestr = "down" ; - } - else - { - buttonstatestr = "up" ; - } - - switch (clicktype) - { - case CLICK_LEFT: - mLeftMouseDown = down; - buttonname = "Left"; - break; - case CLICK_RIGHT: - mRightMouseDown = down; - buttonname = "Right"; - break; - case CLICK_MIDDLE: - mMiddleMouseDown = down; - buttonname = "Middle"; - break; - case CLICK_DOUBLELEFT: - mLeftMouseDown = down; - buttonname = "Left Double Click"; - break; - case CLICK_BUTTON4: - buttonname = "Button 4"; - break; - case CLICK_BUTTON5: - buttonname = "Button 5"; - break; - default: - break; // COUNT and NONE - } - - LLView::sMouseHandlerMessage.clear(); - - if (gMenuBarView) - { - // stop ALT-key access to menu - gMenuBarView->resetMenuTrigger(); - } - - if (gDebugClicks) - { - LL_INFOS() << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << LL_ENDL; - } - - // Make sure we get a corresponding mouseup event, even if the mouse leaves the window - if (down) - mWindow->captureMouse(); - else - mWindow->releaseMouse(); - - // Indicate mouse was active - LLUI::getInstance()->resetMouseIdleTimer(); - - // Don't let the user move the mouse out of the window until mouse up. - if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() ) - { - mWindow->setMouseClipping(down); - } - - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - if( mouse_captor ) - { - S32 local_x; - S32 local_y; - mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << LL_ENDL; - } - - BOOL r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); - if (r) { - - LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << LL_ENDL; - - LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); - LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); - - } - else if (down && clicktype == CLICK_RIGHT) - { - handlePieMenu(x, y, mask); - r = TRUE; - } - return r; - } - - // Mark the click as handled and return if we aren't within the root view to avoid spurious bugs - if( !mRootView->pointInView(x, y) ) - { - return TRUE; - } - // Give the UI views a chance to process the click - - BOOL r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; - if (r) - { - - LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x "<< " " << x << "global y " << y << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << LL_ENDL; - - LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); - - // Clear local coords - this was a click on root window so these are not needed - // By not including them, this allows the test skeleton generation tool to be smarter when generating code - // the code generator can be smarter because when local coords are present it can try the xui path with local coords - // and fallback to global coordinates only if needed. - // The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element - // (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) - // For this reason it's best to provide hints where possible here by leaving out local coordinates - LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); - LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname); - - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui() << LL_ENDL; - } - return TRUE; - } else if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " not handled by view" << LL_ENDL; - } - } - - // Do not allow tool manager to handle mouseclicks if we have disconnected - if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) - { - LLViewerEventRecorder::instance().clear_xui(); + // only send mouse clicks to UI if UI is visible + if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + + if (down) + { + buttonstatestr = "down" ; + } + else + { + buttonstatestr = "up" ; + } + + switch (clicktype) + { + case CLICK_LEFT: + mLeftMouseDown = down; + buttonname = "Left"; + break; + case CLICK_RIGHT: + mRightMouseDown = down; + buttonname = "Right"; + break; + case CLICK_MIDDLE: + mMiddleMouseDown = down; + buttonname = "Middle"; + break; + case CLICK_DOUBLELEFT: + mLeftMouseDown = down; + buttonname = "Left Double Click"; + break; + case CLICK_BUTTON4: + buttonname = "Button 4"; + break; + case CLICK_BUTTON5: + buttonname = "Button 5"; + break; + default: + break; // COUNT and NONE + } + + LLView::sMouseHandlerMessage.clear(); + + if (gMenuBarView) + { + // stop ALT-key access to menu + gMenuBarView->resetMenuTrigger(); + } + + if (gDebugClicks) + { + LL_INFOS() << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << LL_ENDL; + } + + // Make sure we get a corresponding mouseup event, even if the mouse leaves the window + if (down) + mWindow->captureMouse(); + else + mWindow->releaseMouse(); + + // Indicate mouse was active + LLUI::getInstance()->resetMouseIdleTimer(); + + // Don't let the user move the mouse out of the window until mouse up. + if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() ) + { + mWindow->setMouseClipping(down); + } + + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + if( mouse_captor ) + { + S32 local_x; + S32 local_y; + mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << LL_ENDL; + } + + BOOL r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); + if (r) { + + LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << LL_ENDL; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); + + } + else if (down && clicktype == CLICK_RIGHT) + { + handlePieMenu(x, y, mask); + r = TRUE; + } + return r; + } + + // Mark the click as handled and return if we aren't within the root view to avoid spurious bugs + if( !mRootView->pointInView(x, y) ) + { + return TRUE; + } + // Give the UI views a chance to process the click + + BOOL r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; + if (r) + { + + LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x "<< " " << x << "global y " << y << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << LL_ENDL; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + + // Clear local coords - this was a click on root window so these are not needed + // By not including them, this allows the test skeleton generation tool to be smarter when generating code + // the code generator can be smarter because when local coords are present it can try the xui path with local coords + // and fallback to global coordinates only if needed. + // The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element + // (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) + // For this reason it's best to provide hints where possible here by leaving out local coordinates + LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); + LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname); + + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui() << LL_ENDL; + } + return TRUE; + } else if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " not handled by view" << LL_ENDL; + } + } + + // Do not allow tool manager to handle mouseclicks if we have disconnected + if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) + { + LLViewerEventRecorder::instance().clear_xui(); is_toolmgr_action = true; - return TRUE; - } + return TRUE; + } - if (down && clicktype == CLICK_RIGHT) - { - handlePieMenu(x, y, mask); - return TRUE; - } + if (down && clicktype == CLICK_RIGHT) + { + handlePieMenu(x, y, mask); + return TRUE; + } - // If we got this far on a down-click, it wasn't handled. - // Up-clicks, though, are always handled as far as the OS is concerned. - BOOL default_rtn = !down; - return default_rtn; + // If we got this far on a down-click, it wasn't handled. + // Up-clicks, though, are always handled as far as the OS is concerned. + BOOL default_rtn = !down; + return default_rtn; } BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1173,7 +1173,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask else { mMouseDownTimer.reset(); - } + } BOOL down = TRUE; //handleMouse() loops back to LLViewerWindow::handleAnyMouseClick return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down); @@ -1181,14 +1181,14 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask) { - // try handling as a double-click first, then a single-click if that - // wasn't handled. - BOOL down = TRUE; - if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down)) - { - return TRUE; - } - return handleMouseDown(window, pos, mask); + // try handling as a double-click first, then a single-click if that + // wasn't handled. + BOOL down = TRUE; + if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down)) + { + return TRUE; + } + return handleMouseDown(window, pos, mask); } BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1202,177 +1202,177 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) } BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) { - BOOL down = TRUE; - return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); + BOOL down = TRUE; + return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); } BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { - BOOL down = FALSE; - return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); + BOOL down = FALSE; + return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); } BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) { - BOOL down = TRUE; - gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); - - // Always handled as far as the OS is concerned. - return TRUE; + BOOL down = TRUE; + gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); + + // Always handled as far as the OS is concerned. + return TRUE; } LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data) { - LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE; - - const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop"); - const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop"); - - if ( prim_media_dnd_enabled || slurl_dnd_enabled ) - { - switch(action) - { - // Much of the handling for these two cases is the same. - case LLWindowCallbacks::DNDA_TRACK: - case LLWindowCallbacks::DNDA_DROPPED: - case LLWindowCallbacks::DNDA_START_TRACKING: - { - bool drop = (LLWindowCallbacks::DNDA_DROPPED == action); - - if (slurl_dnd_enabled) - { - LLSLURL dropped_slurl(data); - if(dropped_slurl.isSpatial()) - { - if (drop) - { - LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, NULL, true ); - return LLWindowCallbacks::DND_MOVE; - } - return LLWindowCallbacks::DND_COPY; - } - } - - if (prim_media_dnd_enabled) - { - LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, - TRUE /* pick_transparent */, + LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE; + + const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop"); + const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop"); + + if ( prim_media_dnd_enabled || slurl_dnd_enabled ) + { + switch(action) + { + // Much of the handling for these two cases is the same. + case LLWindowCallbacks::DNDA_TRACK: + case LLWindowCallbacks::DNDA_DROPPED: + case LLWindowCallbacks::DNDA_START_TRACKING: + { + bool drop = (LLWindowCallbacks::DNDA_DROPPED == action); + + if (slurl_dnd_enabled) + { + LLSLURL dropped_slurl(data); + if(dropped_slurl.isSpatial()) + { + if (drop) + { + LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, NULL, true ); + return LLWindowCallbacks::DND_MOVE; + } + return LLWindowCallbacks::DND_COPY; + } + } + + if (prim_media_dnd_enabled) + { + LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, + TRUE /* pick_transparent */, FALSE /* pick_rigged */); - S32 object_face = pick_info.mObjectFace; - std::string url = data; - - LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL; - - LLVOVolume *obj = dynamic_cast(static_cast(pick_info.getObject())); - - if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty()) - { - LLTextureEntry *te = obj->getTE(object_face); - - // can modify URL if we can modify the object or we have navigate permissions - bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT ); - - if (te && allow_modify_url ) - { - if (drop) - { - // object does NOT have media already - if ( ! te->hasMedia() ) - { - // we are allowed to modify the object - if ( obj->permModify() ) - { - // Create new media entry - LLSD media_data; - // XXX Should we really do Home URL too? - media_data[LLMediaEntry::HOME_URL_KEY] = url; - media_data[LLMediaEntry::CURRENT_URL_KEY] = url; - media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; - obj->syncMediaData(object_face, media_data, true, true); - // XXX This shouldn't be necessary, should it ?!? - if (obj->getMediaImpl(object_face)) - obj->getMediaImpl(object_face)->navigateReload(); - obj->sendMediaDataUpdate(); - - result = LLWindowCallbacks::DND_COPY; - } - } - else - // object HAS media already - { - // URL passes the whitelist - if (te->getMediaData()->checkCandidateUrl( url ) ) - { - // just navigate to the URL - if (obj->getMediaImpl(object_face)) - { - obj->getMediaImpl(object_face)->navigateTo(url); - } - else - { - // This is very strange. Navigation should - // happen via the Impl, but we don't have one. - // This sends it to the server, which /should/ - // trigger us getting it. Hopefully. - LLSD media_data; - media_data[LLMediaEntry::CURRENT_URL_KEY] = url; - obj->syncMediaData(object_face, media_data, true, true); - obj->sendMediaDataUpdate(); - } - result = LLWindowCallbacks::DND_LINK; - - } - } - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = NULL; - - } - else - { - // Check the whitelist, if there's media (otherwise just show it) - if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) - { - if ( obj != mDragHoveredObject) - { - // Highlight the dragged object - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = obj; - LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); - } - result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; - - } - } - } - } - } - } - break; - - case LLWindowCallbacks::DNDA_STOP_TRACKING: - // The cleanup case below will make sure things are unhilighted if necessary. - break; - } - - if (prim_media_dnd_enabled && - result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull()) - { - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = NULL; - } - } - - return result; + S32 object_face = pick_info.mObjectFace; + std::string url = data; + + LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL; + + LLVOVolume *obj = dynamic_cast(static_cast(pick_info.getObject())); + + if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty()) + { + LLTextureEntry *te = obj->getTE(object_face); + + // can modify URL if we can modify the object or we have navigate permissions + bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT ); + + if (te && allow_modify_url ) + { + if (drop) + { + // object does NOT have media already + if ( ! te->hasMedia() ) + { + // we are allowed to modify the object + if ( obj->permModify() ) + { + // Create new media entry + LLSD media_data; + // XXX Should we really do Home URL too? + media_data[LLMediaEntry::HOME_URL_KEY] = url; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; + obj->syncMediaData(object_face, media_data, true, true); + // XXX This shouldn't be necessary, should it ?!? + if (obj->getMediaImpl(object_face)) + obj->getMediaImpl(object_face)->navigateReload(); + obj->sendMediaDataUpdate(); + + result = LLWindowCallbacks::DND_COPY; + } + } + else + // object HAS media already + { + // URL passes the whitelist + if (te->getMediaData()->checkCandidateUrl( url ) ) + { + // just navigate to the URL + if (obj->getMediaImpl(object_face)) + { + obj->getMediaImpl(object_face)->navigateTo(url); + } + else + { + // This is very strange. Navigation should + // happen via the Impl, but we don't have one. + // This sends it to the server, which /should/ + // trigger us getting it. Hopefully. + LLSD media_data; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + obj->syncMediaData(object_face, media_data, true, true); + obj->sendMediaDataUpdate(); + } + result = LLWindowCallbacks::DND_LINK; + + } + } + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + + } + else + { + // Check the whitelist, if there's media (otherwise just show it) + if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) + { + if ( obj != mDragHoveredObject) + { + // Highlight the dragged object + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = obj; + LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); + } + result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; + + } + } + } + } + } + } + break; + + case LLWindowCallbacks::DNDA_STOP_TRACKING: + // The cleanup case below will make sure things are unhilighted if necessary. + break; + } + + if (prim_media_dnd_enabled && + result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull()) + { + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + } + } + + return result; } BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { - BOOL down = FALSE; - gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); - - // Always handled as far as the OS is concerned. - return TRUE; + BOOL down = FALSE; + gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); + + // Always handled as far as the OS is concerned. + return TRUE; } BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down) @@ -1406,32 +1406,32 @@ BOOL LLViewerWindow::handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK ma // WARNING: this is potentially called multiple times per frame void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) { - S32 x = pos.mX; - S32 y = pos.mY; + S32 x = pos.mX; + S32 y = pos.mY; - x = ll_round((F32)x / mDisplayScale.mV[VX]); - y = ll_round((F32)y / mDisplayScale.mV[VY]); + x = ll_round((F32)x / mDisplayScale.mV[VX]); + y = ll_round((F32)y / mDisplayScale.mV[VY]); - mMouseInWindow = TRUE; + mMouseInWindow = TRUE; - // Save mouse point for access during idle() and display() + // Save mouse point for access during idle() and display() - LLCoordGL mouse_point(x, y); + LLCoordGL mouse_point(x, y); - if (mouse_point != mCurrentMousePoint) - { - LLUI::getInstance()->resetMouseIdleTimer(); - } + if (mouse_point != mCurrentMousePoint) + { + LLUI::getInstance()->resetMouseIdleTimer(); + } - saveLastMouse(mouse_point); + saveLastMouse(mouse_point); - mWindow->showCursorFromMouseMove(); + mWindow->showCursorFromMouseMove(); - if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME - && !gDisconnected) - { - gAgent.clearAFK(); - } + if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME + && !gDisconnected) + { + gAgent.clearAFK(); + } } void LLViewerWindow::handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1452,114 +1452,114 @@ void LLViewerWindow::handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK m void LLViewerWindow::handleMouseLeave(LLWindow *window) { - // Note: we won't get this if we have captured the mouse. - llassert( gFocusMgr.getMouseCapture() == NULL ); - mMouseInWindow = FALSE; - LLToolTipMgr::instance().blockToolTips(); + // Note: we won't get this if we have captured the mouse. + llassert( gFocusMgr.getMouseCapture() == NULL ); + mMouseInWindow = FALSE; + LLToolTipMgr::instance().blockToolTips(); } BOOL LLViewerWindow::handleCloseRequest(LLWindow *window) { - // User has indicated they want to close, but we may need to ask - // about modified documents. - LLAppViewer::instance()->userQuit(); - // Don't quit immediately - return FALSE; + // User has indicated they want to close, but we may need to ask + // about modified documents. + LLAppViewer::instance()->userQuit(); + // Don't quit immediately + return FALSE; } void LLViewerWindow::handleQuit(LLWindow *window) { - if (gNonInteractive) - { - LLAppViewer::instance()->requestQuit(); - } - else - { - LL_INFOS() << "Window forced quit" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - } + if (gNonInteractive) + { + LLAppViewer::instance()->requestQuit(); + } + else + { + LL_INFOS() << "Window forced quit" << LL_ENDL; + LLAppViewer::instance()->forceQuit(); + } } void LLViewerWindow::handleResize(LLWindow *window, S32 width, S32 height) { - reshape(width, height); - mResDirty = true; + reshape(width, height); + mResDirty = true; } // The top-level window has gained focus (e.g. via ALT-TAB) void LLViewerWindow::handleFocus(LLWindow *window) { - gFocusMgr.setAppHasFocus(TRUE); - LLModalDialog::onAppFocusGained(); + gFocusMgr.setAppHasFocus(TRUE); + LLModalDialog::onAppFocusGained(); - gAgent.onAppFocusGained(); - LLToolMgr::getInstance()->onAppFocusGained(); + gAgent.onAppFocusGained(); + LLToolMgr::getInstance()->onAppFocusGained(); - // See if we're coming in with modifier keys held down - if (gKeyboard) - { - gKeyboard->resetMaskKeys(); - } + // See if we're coming in with modifier keys held down + if (gKeyboard) + { + gKeyboard->resetMaskKeys(); + } - // resume foreground running timer - // since we artifically limit framerate when not frontmost - gForegroundTime.unpause(); + // resume foreground running timer + // since we artifically limit framerate when not frontmost + gForegroundTime.unpause(); } // The top-level window has lost focus (e.g. via ALT-TAB) void LLViewerWindow::handleFocusLost(LLWindow *window) { - gFocusMgr.setAppHasFocus(FALSE); - //LLModalDialog::onAppFocusLost(); - LLToolMgr::getInstance()->onAppFocusLost(); - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setAppHasFocus(FALSE); + //LLModalDialog::onAppFocusLost(); + LLToolMgr::getInstance()->onAppFocusLost(); + gFocusMgr.setMouseCapture( NULL ); - if (gMenuBarView) - { - // stop ALT-key access to menu - gMenuBarView->resetMenuTrigger(); - } + if (gMenuBarView) + { + // stop ALT-key access to menu + gMenuBarView->resetMenuTrigger(); + } - // restore mouse cursor - showCursor(); - getWindow()->setMouseClipping(FALSE); + // restore mouse cursor + showCursor(); + getWindow()->setMouseClipping(FALSE); - // If losing focus while keys are down, handle them as + // If losing focus while keys are down, handle them as // an 'up' to correctly release states, then reset states - if (gKeyboard) - { + if (gKeyboard) + { gKeyboard->resetKeyDownAndHandle(); - gKeyboard->resetKeys(); - } + gKeyboard->resetKeys(); + } - // pause timer that tracks total foreground running time - gForegroundTime.pause(); + // pause timer that tracks total foreground running time + gForegroundTime.pause(); } BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated) { - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice // Never affects event processing. gViewerInput.handleGlobalBindsKeyDown(key, mask); - if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME) - { - gAgent.clearAFK(); - } - - // *NOTE: We want to interpret KEY_RETURN later when it arrives as - // a Unicode char, not as a keydown. Otherwise when client frame - // rate is really low, hitting return sends your chat text before - // it's all entered/processed. - if (key == KEY_RETURN && mask == MASK_NONE) - { + if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME) + { + gAgent.clearAFK(); + } + + // *NOTE: We want to interpret KEY_RETURN later when it arrives as + // a Unicode char, not as a keydown. Otherwise when client frame + // rate is really low, hitting return sends your chat text before + // it's all entered/processed. + if (key == KEY_RETURN && mask == MASK_NONE) + { // RIDER: although, at times some of the controlls (in particular the CEF viewer // would like to know about the KEYDOWN for an enter key... so ask and pass it along. LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if (keyboard_focus && !keyboard_focus->wantsReturnKey()) - return FALSE; - } + return FALSE; + } // remaps, handles ignored cases and returns back to viewer window. return gViewerInput.handleKey(key, mask, repeated); @@ -1567,25 +1567,25 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated) BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask) { - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice // Never affects event processing. gViewerInput.handleGlobalBindsKeyUp(key, mask); - // Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera - LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance(); - if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp) - { - tool_inspectp->keyUp(key, mask); - } + // Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera + LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance(); + if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp) + { + tool_inspectp->keyUp(key, mask); + } - return gViewerInput.handleKeyUp(key, mask); + return gViewerInput.handleKeyUp(key, mask); } void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) { - LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); - gViewerInput.scanKey(key, key_down, key_up, key_level); - return; // Be clear this function returns nothing + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); + gViewerInput.scanKey(key, key_down, key_up, key_level); + return; // Be clear this function returns nothing } @@ -1593,45 +1593,45 @@ void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated) { - if (activated) - { - mActive = true; - send_agent_resume(); - gAgent.clearAFK(); - - // Unmute audio - audio_update_volume(); - } - else - { - mActive = false; - - // if the user has chosen to go Away automatically after some time, then go Away when minimizing - if (gSavedSettings.getS32("AFKTimeout")) - { - gAgent.setAFK(); - } - - // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues - if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - gAgentCamera.changeCameraToDefault(); - } - - send_agent_pause(); - - // Mute audio - audio_update_volume(); - } - return TRUE; + if (activated) + { + mActive = true; + send_agent_resume(); + gAgent.clearAFK(); + + // Unmute audio + audio_update_volume(); + } + else + { + mActive = false; + + // if the user has chosen to go Away automatically after some time, then go Away when minimizing + if (gSavedSettings.getS32("AFKTimeout")) + { + gAgent.setAFK(); + } + + // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues + if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) + { + gAgentCamera.changeCameraToDefault(); + } + + send_agent_pause(); + + // Mute audio + audio_update_volume(); + } + return TRUE; } BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating) { - //if (!activating) gAgentCamera.changeCameraToDefault(); + //if (!activating) gAgentCamera.changeCameraToDefault(); - LLViewerJoystick::getInstance()->setNeedsReset(true); - return FALSE; + LLViewerJoystick::getInstance()->setNeedsReset(true); + return FALSE; } @@ -1642,108 +1642,108 @@ void LLViewerWindow::handleMenuSelect(LLWindow *window, S32 menu_item) BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height) { - // *TODO: Enable similar information output for other platforms? DK 2011-02-18 + // *TODO: Enable similar information output for other platforms? DK 2011-02-18 #if LL_WINDOWS - if (gHeadlessClient) - { - HWND window_handle = (HWND)window->getPlatformWindow(); - PAINTSTRUCT ps; - HDC hdc; - - RECT wnd_rect; - wnd_rect.left = 0; - wnd_rect.top = 0; - wnd_rect.bottom = 200; - wnd_rect.right = 500; - - hdc = BeginPaint(window_handle, &ps); - //SetBKColor(hdc, RGB(255, 255, 255)); - FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); - - std::string temp_str; - LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); - temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ - recording.getPerSec(LLStatViewer::FPS), //mFPSStat.getMeanPerSec(), - recording.getLastValue(LLStatViewer::SIM_PHYSICS_FPS), - recording.getLastValue(LLStatViewer::SIM_TIME_DILATION)); - S32 len = temp_str.length(); - TextOutA(hdc, 0, 0, temp_str.c_str(), len); - - - LLVector3d pos_global = gAgent.getPositionGlobal(); - temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); - len = temp_str.length(); - TextOutA(hdc, 0, 25, temp_str.c_str(), len); - - TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61); - EndPaint(window_handle, &ps); - return TRUE; - } + if (gHeadlessClient) + { + HWND window_handle = (HWND)window->getPlatformWindow(); + PAINTSTRUCT ps; + HDC hdc; + + RECT wnd_rect; + wnd_rect.left = 0; + wnd_rect.top = 0; + wnd_rect.bottom = 200; + wnd_rect.right = 500; + + hdc = BeginPaint(window_handle, &ps); + //SetBKColor(hdc, RGB(255, 255, 255)); + FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); + + std::string temp_str; + LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); + temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ + recording.getPerSec(LLStatViewer::FPS), //mFPSStat.getMeanPerSec(), + recording.getLastValue(LLStatViewer::SIM_PHYSICS_FPS), + recording.getLastValue(LLStatViewer::SIM_TIME_DILATION)); + S32 len = temp_str.length(); + TextOutA(hdc, 0, 0, temp_str.c_str(), len); + + + LLVector3d pos_global = gAgent.getPositionGlobal(); + temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); + len = temp_str.length(); + TextOutA(hdc, 0, 25, temp_str.c_str(), len); + + TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61); + EndPaint(window_handle, &ps); + return TRUE; + } #endif - return FALSE; + return FALSE; } void LLViewerWindow::handleScrollWheel(LLWindow *window, S32 clicks) { - handleScrollWheel( clicks ); + handleScrollWheel( clicks ); } void LLViewerWindow::handleScrollHWheel(LLWindow *window, S32 clicks) { - handleScrollHWheel(clicks); + handleScrollHWheel(clicks); } void LLViewerWindow::handleWindowBlock(LLWindow *window) { - send_agent_pause(); + send_agent_pause(); } void LLViewerWindow::handleWindowUnblock(LLWindow *window) { - send_agent_resume(); + send_agent_resume(); } void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) { - const S32 SLURL_MESSAGE_TYPE = 0; - switch (data_type) - { - case SLURL_MESSAGE_TYPE: - // received URL - std::string url = (const char*)data; - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - // don't treat slapps coming from external browsers as "clicks" as this would bypass throttling - if (LLURLDispatcher::dispatch(url, LLCommandHandler::NAV_TYPE_EXTERNAL, web, trusted_browser)) - { - // bring window to foreground, as it has just been "launched" from a URL - mWindow->bringToFront(); - } - break; - } + const S32 SLURL_MESSAGE_TYPE = 0; + switch (data_type) + { + case SLURL_MESSAGE_TYPE: + // received URL + std::string url = (const char*)data; + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + // don't treat slapps coming from external browsers as "clicks" as this would bypass throttling + if (LLURLDispatcher::dispatch(url, LLCommandHandler::NAV_TYPE_EXTERNAL, web, trusted_browser)) + { + // bring window to foreground, as it has just been "launched" from a URL + mWindow->bringToFront(); + } + break; + } } BOOL LLViewerWindow::handleTimerEvent(LLWindow *window) { //TODO: just call this every frame from gatherInput instead of using a convoluted 30fps timer callback - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - LLViewerJoystick::getInstance()->updateStatus(); - return TRUE; - } - return FALSE; + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + LLViewerJoystick::getInstance()->updateStatus(); + return TRUE; + } + return FALSE; } BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) { - // give a chance to use a joystick after startup (hot-plugging) - if (!LLViewerJoystick::getInstance()->isJoystickInitialized() ) - { - LLViewerJoystick::getInstance()->init(true); - return TRUE; - } - return FALSE; + // give a chance to use a joystick after startup (hot-plugging) + if (!LLViewerJoystick::getInstance()->isJoystickInitialized() ) + { + LLViewerJoystick::getInstance()->init(true); + return TRUE; + } + return FALSE; } BOOL LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) @@ -1763,157 +1763,157 @@ BOOL LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 BOOL LLViewerWindow::handleWindowDidChangeScreen(LLWindow *window) { - LLCoordScreen window_rect; - mWindow->getSize(&window_rect); - reshape(window_rect.mX, window_rect.mY); - return TRUE; + LLCoordScreen window_rect; + mWindow->getSize(&window_rect); + reshape(window_rect.mX, window_rect.mY); + return TRUE; } void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg) { - LLAppViewer::instance()->pingMainloopTimeout(msg); + LLAppViewer::instance()->pingMainloopTimeout(msg); } void LLViewerWindow::handleResumeWatchdog(LLWindow *window) { - LLAppViewer::instance()->resumeMainloopTimeout(); + LLAppViewer::instance()->resumeMainloopTimeout(); } void LLViewerWindow::handlePauseWatchdog(LLWindow *window) { - LLAppViewer::instance()->pauseMainloopTimeout(); + LLAppViewer::instance()->pauseMainloopTimeout(); } //virtual std::string LLViewerWindow::translateString(const char* tag) { - return LLTrans::getString( std::string(tag) ); + return LLTrans::getString( std::string(tag) ); } //virtual std::string LLViewerWindow::translateString(const char* tag, - const std::map& args) -{ - // LLTrans uses a special subclass of std::string for format maps, - // but we must use std::map<> in these callbacks, otherwise we create - // a dependency between LLWindow and LLFormatMapString. So copy the data. - LLStringUtil::format_map_t args_copy; - std::map::const_iterator it = args.begin(); - for ( ; it != args.end(); ++it) - { - args_copy[it->first] = it->second; - } - return LLTrans::getString( std::string(tag), args_copy); + const std::map& args) +{ + // LLTrans uses a special subclass of std::string for format maps, + // but we must use std::map<> in these callbacks, otherwise we create + // a dependency between LLWindow and LLFormatMapString. So copy the data. + LLStringUtil::format_map_t args_copy; + std::map::const_iterator it = args.begin(); + for ( ; it != args.end(); ++it) + { + args_copy[it->first] = it->second; + } + return LLTrans::getString( std::string(tag), args_copy); } // // Classes // LLViewerWindow::LLViewerWindow(const Params& p) -: mWindow(NULL), - mActive(true), - mUIVisible(true), - mWindowRectRaw(0, p.height, p.width, 0), - mWindowRectScaled(0, p.height, p.width, 0), - mWorldViewRectRaw(0, p.height, p.width, 0), - mLeftMouseDown(FALSE), - mMiddleMouseDown(FALSE), - mRightMouseDown(FALSE), - mMouseInWindow( FALSE ), +: mWindow(NULL), + mActive(true), + mUIVisible(true), + mWindowRectRaw(0, p.height, p.width, 0), + mWindowRectScaled(0, p.height, p.width, 0), + mWorldViewRectRaw(0, p.height, p.width, 0), + mLeftMouseDown(FALSE), + mMiddleMouseDown(FALSE), + mRightMouseDown(FALSE), + mMouseInWindow( FALSE ), mAllowMouseDragging(TRUE), mMouseDownTimer(), - mLastMask( MASK_NONE ), - mToolStored( NULL ), - mHideCursorPermanent( FALSE ), - mCursorHidden(FALSE), - mIgnoreActivate( FALSE ), - mResDirty(false), - mStatesDirty(false), - mCurrResolutionIndex(0), - mProgressView(NULL) -{ - // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to - // pass its value right now. Instead, pass it a nullary function that - // will, when we later need it, return the value of gKeyboard. - // boost::lambda::var() constructs such a functor on the fly. - mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); - mViewerWindowListener.reset(new LLViewerWindowListener(this)); - - mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); - mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); - mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); - mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); - - bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); - LLNotifications::instance().setIgnoreAllNotifications(ignore); - if (ignore) - { - LL_INFOS() << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << LL_ENDL; - } - - - /* - LLWindowCallbacks* callbacks, - const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, - BOOL fullscreen, - BOOL clearBg, - BOOL disable_vsync, - BOOL ignore_pixel_depth, - U32 fsaa_samples) - */ - // create window + mLastMask( MASK_NONE ), + mToolStored( NULL ), + mHideCursorPermanent( FALSE ), + mCursorHidden(FALSE), + mIgnoreActivate( FALSE ), + mResDirty(false), + mStatesDirty(false), + mCurrResolutionIndex(0), + mProgressView(NULL) +{ + // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to + // pass its value right now. Instead, pass it a nullary function that + // will, when we later need it, return the value of gKeyboard. + // boost::lambda::var() constructs such a functor on the fly. + mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); + mViewerWindowListener.reset(new LLViewerWindowListener(this)); + + mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); + mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); + mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); + mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); + + bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); + LLNotifications::instance().setIgnoreAllNotifications(ignore); + if (ignore) + { + LL_INFOS() << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << LL_ENDL; + } + + + /* + LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, + BOOL fullscreen, + BOOL clearBg, + BOOL disable_vsync, + BOOL ignore_pixel_depth, + U32 fsaa_samples) + */ + // create window U32 max_core_count = gSavedSettings.getU32("EmulateCoreCount"); U32 max_vram = gSavedSettings.getU32("RenderMaxVRAMBudget"); F32 max_gl_version = gSavedSettings.getF32("RenderMaxOpenGLVersion"); - - mWindow = LLWindowManager::createWindow(this, - p.title, p.name, p.x, p.y, p.width, p.height, 0, - p.fullscreen, - gHeadlessClient, - gSavedSettings.getBOOL("RenderVSyncEnable"), - !gHeadlessClient, - p.ignore_pixel_depth, - 0, + + mWindow = LLWindowManager::createWindow(this, + p.title, p.name, p.x, p.y, p.width, p.height, 0, + p.fullscreen, + gHeadlessClient, + gSavedSettings.getBOOL("RenderVSyncEnable"), + !gHeadlessClient, + p.ignore_pixel_depth, + 0, max_core_count, max_vram, max_gl_version); //don't use window level anti-aliasing - if (NULL == mWindow) - { - LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate")); - - LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << LL_ENDL ; + if (NULL == mWindow) + { + LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate")); + + LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << LL_ENDL ; - ms_sleep(5000) ; //wait for 5 seconds. + ms_sleep(5000) ; //wait for 5 seconds. - LLSplashScreen::update(LLTrans::getString("ShuttingDown")); + LLSplashScreen::update(LLTrans::getString("ShuttingDown")); #if LL_LINUX - LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt for further information." - << LL_ENDL; + LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt for further information." + << LL_ENDL; #else - LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" - << LL_ENDL; + LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" + << LL_ENDL; #endif LLAppViewer::instance()->fastQuit(1); - } + } else if (!LLViewerShaderMgr::sInitialized) { //immediately initialize shaders LLViewerShaderMgr::sInitialized = TRUE; LLViewerShaderMgr::instance()->setShaders(); } - - if (!LLAppViewer::instance()->restoreErrorTrap()) - { + + if (!LLAppViewer::instance()->restoreErrorTrap()) + { // this always happens, so downgrading it to INFO - LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL; - } + LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL; + } - const bool do_not_enforce = false; - mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce); // root view not set - LLCoordScreen scr; + const bool do_not_enforce = false; + mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce); // root view not set + LLCoordScreen scr; mWindow->getSize(&scr); // Reset UI scale factor on first run if OS's display scaling is not 100% @@ -1926,90 +1926,90 @@ LLViewerWindow::LLViewerWindow(const Params& p) gSavedSettings.setBOOL("ResetUIScaleOnFirstRun", FALSE); } - // Get the real window rect the window was created with (since there are various OS-dependent reasons why - // the size of a window or fullscreen context may have been adjusted slightly...) - F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); - - mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - mDisplayScale *= ui_scale_factor; - LLUI::setScaleFactor(mDisplayScale); - - { - LLCoordWindow size; - mWindow->getSize(&size); - mWindowRectRaw.set(0, size.mY, size.mX, 0); - mWindowRectScaled.set(0, ll_round((F32)size.mY / mDisplayScale.mV[VY]), ll_round((F32)size.mX / mDisplayScale.mV[VX]), 0); - } - - LLFontManager::initClass(); - // Init font system, load default fonts and generate basic glyphs - // currently it takes aprox. 0.5 sec and we would load these fonts anyway - // before login screen. - LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), - mDisplayScale.mV[VX], - mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir()); - - // - // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off - // stuff like AGP if we think that it'll crash the viewer. - // - LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; - - // Initialize OpenGL Renderer - LLVertexBuffer::initClass(mWindow); - LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; - if (!gGL.init(true)) + // Get the real window rect the window was created with (since there are various OS-dependent reasons why + // the size of a window or fullscreen context may have been adjusted slightly...) + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); + + mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); + mDisplayScale *= ui_scale_factor; + LLUI::setScaleFactor(mDisplayScale); + + { + LLCoordWindow size; + mWindow->getSize(&size); + mWindowRectRaw.set(0, size.mY, size.mX, 0); + mWindowRectScaled.set(0, ll_round((F32)size.mY / mDisplayScale.mV[VY]), ll_round((F32)size.mX / mDisplayScale.mV[VX]), 0); + } + + LLFontManager::initClass(); + // Init font system, load default fonts and generate basic glyphs + // currently it takes aprox. 0.5 sec and we would load these fonts anyway + // before login screen. + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), + mDisplayScale.mV[VX], + mDisplayScale.mV[VY], + gDirUtilp->getAppRODataDir()); + + // + // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off + // stuff like AGP if we think that it'll crash the viewer. + // + LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; + + // Initialize OpenGL Renderer + LLVertexBuffer::initClass(mWindow); + LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; + if (!gGL.init(true)) { LLError::LLUserWarningMsg::show(LLTrans::getString("MBVideoDrvErr")); LL_ERRS() << "gGL not initialized" << LL_ENDL; } - if (LLFeatureManager::getInstance()->isSafe() - || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) - || (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString()) - || (gSavedSettings.getBOOL("ProbeHardwareOnStartup"))) - { - LLFeatureManager::getInstance()->applyRecommendedSettings(); - gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE); - } - - // If we crashed while initializng GL stuff last time, disable certain features - if (gSavedSettings.getBOOL("RenderInitError")) - { - mInitAlert = "DisplaySettingsNoShaders"; - LLFeatureManager::getInstance()->setGraphicsLevel(0, false); - gSavedSettings.setU32("RenderQualityPerformance", 0); - } - - // Init the image list. Must happen after GL is initialized and before the images that - // LLViewerWindow needs are requested, as well as before LLViewerMedia starts updating images. + if (LLFeatureManager::getInstance()->isSafe() + || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) + || (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString()) + || (gSavedSettings.getBOOL("ProbeHardwareOnStartup"))) + { + LLFeatureManager::getInstance()->applyRecommendedSettings(); + gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE); + } + + // If we crashed while initializng GL stuff last time, disable certain features + if (gSavedSettings.getBOOL("RenderInitError")) + { + mInitAlert = "DisplaySettingsNoShaders"; + LLFeatureManager::getInstance()->setGraphicsLevel(0, false); + gSavedSettings.setU32("RenderQualityPerformance", 0); + } + + // Init the image list. Must happen after GL is initialized and before the images that + // LLViewerWindow needs are requested, as well as before LLViewerMedia starts updating images. LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreadedTextures"), gSavedSettings.getBOOL("RenderGLMultiThreadedMedia")); - gTextureList.init(); - LLViewerTextureManager::init() ; - gBumpImageList.init(); - + gTextureList.init(); + LLViewerTextureManager::init() ; + gBumpImageList.init(); + // Create container for all sub-views - LLView::Params rvp; - rvp.name("root"); - rvp.rect(mWindowRectScaled); - rvp.mouse_opaque(false); - rvp.follows.flags(FOLLOWS_NONE); - mRootView = LLUICtrlFactory::create(rvp); - LLUI::getInstance()->setRootView(mRootView); + LLView::Params rvp; + rvp.name("root"); + rvp.rect(mWindowRectScaled); + rvp.mouse_opaque(false); + rvp.follows.flags(FOLLOWS_NONE); + mRootView = LLUICtrlFactory::create(rvp); + LLUI::getInstance()->setRootView(mRootView); - // Make avatar head look forward at start - mCurrentMousePoint.mX = getWindowWidthScaled() / 2; - mCurrentMousePoint.mY = getWindowHeightScaled() / 2; + // Make avatar head look forward at start + mCurrentMousePoint.mX = getWindowWidthScaled() / 2; + mCurrentMousePoint.mY = getWindowHeightScaled() / 2; - gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); - mOverlayTitle = gSavedSettings.getString("OverlayTitle"); - // Can't have spaces in settings.ini strings, so use underscores instead and convert them. - LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); + gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); + mOverlayTitle = gSavedSettings.getString("OverlayTitle"); + // Can't have spaces in settings.ini strings, so use underscores instead and convert them. + LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); - mDebugText = new LLDebugText(this); + mDebugText = new LLDebugText(this); - mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); + mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); } std::string LLViewerWindow::getLastSnapshotDir() @@ -2019,8 +2019,8 @@ std::string LLViewerWindow::getLastSnapshotDir() void LLViewerWindow::initGLDefaults() { - // RN: Need this for translation and stretch manip. - gBox.prerender(); + // RN: Need this for translation and stretch manip. + gBox.prerender(); } struct MainPanel : public LLPanel @@ -2029,550 +2029,550 @@ struct MainPanel : public LLPanel void LLViewerWindow::initBase() { - S32 height = getWindowHeightScaled(); - S32 width = getWindowWidthScaled(); + S32 height = getWindowHeightScaled(); + S32 width = getWindowWidthScaled(); - LLRect full_window(0, height, width, 0); + LLRect full_window(0, height, width, 0); - //////////////////// - // - // Set the gamma - // + //////////////////// + // + // Set the gamma + // - F32 gamma = gSavedSettings.getF32("RenderGamma"); - if (gamma != 0.0f) - { - getWindow()->setGamma(gamma); - } + F32 gamma = gSavedSettings.getF32("RenderGamma"); + if (gamma != 0.0f) + { + getWindow()->setGamma(gamma); + } - // Create global views + // Create global views - // Login screen and main_view.xml need edit menus for preferences and browser - LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; - initialize_edit_menu(); + // Login screen and main_view.xml need edit menus for preferences and browser + LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; + initialize_edit_menu(); LLFontGL::loadCommonFonts(); - // Create the floater view at the start so that other views can add children to it. - // (But wait to add it as a child of the root view so that it will be in front of the - // other views.) - MainPanel* main_view = new MainPanel(); - if (!main_view->buildFromFile("main_view.xml")) - { - LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file main_view.xml, " - << "if this problem happens again, please validate your installation." << LL_ENDL; - } - main_view->setShape(full_window); - getRootView()->addChild(main_view); - - // placeholder widget that controls where "world" is rendered - mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); - mPopupView = main_view->getChild("popup_holder"); - mHintHolder = main_view->getChild("hint_holder")->getHandle(); - mLoginPanelHolder = main_view->getChild("login_panel_holder")->getHandle(); - - // Create the toolbar view - // Get a pointer to the toolbar view holder - LLPanel* panel_holder = main_view->getChild("toolbar_view_holder"); - // Load the toolbar view from file - gToolBarView = LLUICtrlFactory::getInstance()->createFromFile("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance()); - if (!gToolBarView) - { - LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file panel_toolbar_view.xml, " - << "if this problem happens again, please validate your installation." << LL_ENDL; - } - gToolBarView->setShape(panel_holder->getLocalRect()); - // Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI()) - gToolBarView->setVisible(FALSE); - - // Constrain floaters to inside the menu and status bar regions. - gFloaterView = main_view->getChild("Floater View"); - for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; ++i) - { - LLToolBar * toolbarp = gToolBarView->getToolbar((LLToolBarEnums::EToolBarLocation)i); - if (toolbarp) - { - toolbarp->getCenterLayoutPanel()->setReshapeCallback(boost::bind(&LLFloaterView::setToolbarRect, gFloaterView, _1, _2)); - } - } - gFloaterView->setFloaterSnapView(main_view->getChild("floater_snap_region")->getHandle()); - gSnapshotFloaterView = main_view->getChild("Snapshot Floater View"); - - // Console - llassert( !gConsole ); - LLConsole::Params cp; - cp.name("console"); - cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize")); - cp.rect(getChatConsoleRect()); - cp.persist_time(gSavedSettings.getF32("ChatPersistTime")); - cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); - cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); - gConsole = LLUICtrlFactory::create(cp); - getRootView()->addChild(gConsole); - - // optionally forward warnings to chat console/chat floater - // for qa runs and dev builds + // Create the floater view at the start so that other views can add children to it. + // (But wait to add it as a child of the root view so that it will be in front of the + // other views.) + MainPanel* main_view = new MainPanel(); + if (!main_view->buildFromFile("main_view.xml")) + { + LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file main_view.xml, " + << "if this problem happens again, please validate your installation." << LL_ENDL; + } + main_view->setShape(full_window); + getRootView()->addChild(main_view); + + // placeholder widget that controls where "world" is rendered + mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); + mPopupView = main_view->getChild("popup_holder"); + mHintHolder = main_view->getChild("hint_holder")->getHandle(); + mLoginPanelHolder = main_view->getChild("login_panel_holder")->getHandle(); + + // Create the toolbar view + // Get a pointer to the toolbar view holder + LLPanel* panel_holder = main_view->getChild("toolbar_view_holder"); + // Load the toolbar view from file + gToolBarView = LLUICtrlFactory::getInstance()->createFromFile("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance()); + if (!gToolBarView) + { + LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file panel_toolbar_view.xml, " + << "if this problem happens again, please validate your installation." << LL_ENDL; + } + gToolBarView->setShape(panel_holder->getLocalRect()); + // Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI()) + gToolBarView->setVisible(FALSE); + + // Constrain floaters to inside the menu and status bar regions. + gFloaterView = main_view->getChild("Floater View"); + for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; ++i) + { + LLToolBar * toolbarp = gToolBarView->getToolbar((LLToolBarEnums::EToolBarLocation)i); + if (toolbarp) + { + toolbarp->getCenterLayoutPanel()->setReshapeCallback(boost::bind(&LLFloaterView::setToolbarRect, gFloaterView, _1, _2)); + } + } + gFloaterView->setFloaterSnapView(main_view->getChild("floater_snap_region")->getHandle()); + gSnapshotFloaterView = main_view->getChild("Snapshot Floater View"); + + // Console + llassert( !gConsole ); + LLConsole::Params cp; + cp.name("console"); + cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize")); + cp.rect(getChatConsoleRect()); + cp.persist_time(gSavedSettings.getF32("ChatPersistTime")); + cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); + cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); + gConsole = LLUICtrlFactory::create(cp); + getRootView()->addChild(gConsole); + + // optionally forward warnings to chat console/chat floater + // for qa runs and dev builds #if !LL_RELEASE_FOR_DOWNLOAD - RecordToChatConsole::getInstance()->startRecorder(); + RecordToChatConsole::getInstance()->startRecorder(); #else - if(gSavedSettings.getBOOL("QAMode")) - { - RecordToChatConsole::getInstance()->startRecorder(); - } + if(gSavedSettings.getBOOL("QAMode")) + { + RecordToChatConsole::getInstance()->startRecorder(); + } #endif - gDebugView = getRootView()->getChild("DebugView"); - gDebugView->init(); - gToolTipView = getRootView()->getChild("tooltip view"); + gDebugView = getRootView()->getChild("DebugView"); + gDebugView->init(); + gToolTipView = getRootView()->getChild("tooltip view"); - // Initialize do not disturb response message when logged in - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initDoNotDisturbResponse)); + // Initialize do not disturb response message when logged in + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initDoNotDisturbResponse)); - // Add the progress bar view (startup view), which overrides everything - mProgressView = getRootView()->findChild("progress_view"); - setShowProgress(FALSE); - setProgressCancelButtonVisible(FALSE); + // Add the progress bar view (startup view), which overrides everything + mProgressView = getRootView()->findChild("progress_view"); + setShowProgress(FALSE); + setProgressCancelButtonVisible(FALSE); - gMenuHolder = getRootView()->getChild("Menu Holder"); - LLMenuGL::sMenuContainer = gMenuHolder; + gMenuHolder = getRootView()->getChild("Menu Holder"); + LLMenuGL::sMenuContainer = gMenuHolder; } void LLViewerWindow::initWorldUI() { - if (gNonInteractive) - { - gIMMgr = LLIMMgr::getInstance(); - LLNavigationBar::getInstance(); - gFloaterView->pushVisibleAll(FALSE); - return; - } - - S32 height = mRootView->getRect().getHeight(); - S32 width = mRootView->getRect().getWidth(); - LLRect full_window(0, height, width, 0); - - - gIMMgr = LLIMMgr::getInstance(); - - //getRootView()->sendChildToFront(gFloaterView); - //getRootView()->sendChildToFront(gSnapshotFloaterView); - - if (!gNonInteractive) - { - LLPanel* chiclet_container = getRootView()->getChild("chiclet_container"); - LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); - chiclet_bar->setShape(chiclet_container->getLocalRect()); - chiclet_bar->setFollowsAll(); - chiclet_container->addChild(chiclet_bar); - chiclet_container->setVisible(TRUE); - } - - LLRect morph_view_rect = full_window; - morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); - morph_view_rect.mTop = full_window.mTop - 32; - LLMorphView::Params mvp; - mvp.name("MorphView"); - mvp.rect(morph_view_rect); - mvp.visible(false); - gMorphView = LLUICtrlFactory::create(mvp); - getRootView()->addChild(gMorphView); - - LLWorldMapView::initClass(); - - // Force gFloaterWorldMap to initialize - LLFloaterReg::getInstance("world_map"); - - // Force gFloaterTools to initialize - LLFloaterReg::getInstance("build"); - - // Status bar - LLPanel* status_bar_container = getRootView()->getChild("status_bar_container"); - gStatusBar = new LLStatusBar(status_bar_container->getLocalRect()); - gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT); - gStatusBar->setShape(status_bar_container->getLocalRect()); - // sync bg color with menu bar - gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); + if (gNonInteractive) + { + gIMMgr = LLIMMgr::getInstance(); + LLNavigationBar::getInstance(); + gFloaterView->pushVisibleAll(FALSE); + return; + } + + S32 height = mRootView->getRect().getHeight(); + S32 width = mRootView->getRect().getWidth(); + LLRect full_window(0, height, width, 0); + + + gIMMgr = LLIMMgr::getInstance(); + + //getRootView()->sendChildToFront(gFloaterView); + //getRootView()->sendChildToFront(gSnapshotFloaterView); + + if (!gNonInteractive) + { + LLPanel* chiclet_container = getRootView()->getChild("chiclet_container"); + LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); + chiclet_bar->setShape(chiclet_container->getLocalRect()); + chiclet_bar->setFollowsAll(); + chiclet_container->addChild(chiclet_bar); + chiclet_container->setVisible(TRUE); + } + + LLRect morph_view_rect = full_window; + morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); + morph_view_rect.mTop = full_window.mTop - 32; + LLMorphView::Params mvp; + mvp.name("MorphView"); + mvp.rect(morph_view_rect); + mvp.visible(false); + gMorphView = LLUICtrlFactory::create(mvp); + getRootView()->addChild(gMorphView); + + LLWorldMapView::initClass(); + + // Force gFloaterWorldMap to initialize + LLFloaterReg::getInstance("world_map"); + + // Force gFloaterTools to initialize + LLFloaterReg::getInstance("build"); + + // Status bar + LLPanel* status_bar_container = getRootView()->getChild("status_bar_container"); + gStatusBar = new LLStatusBar(status_bar_container->getLocalRect()); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT); + gStatusBar->setShape(status_bar_container->getLocalRect()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); // add InBack so that gStatusBar won't be drawn over menu status_bar_container->addChildInBack(gStatusBar, 2/*tab order, after menu*/); status_bar_container->setVisible(TRUE); - // Navigation bar - LLView* nav_bar_container = getRootView()->getChild("nav_bar_container"); + // Navigation bar + LLView* nav_bar_container = getRootView()->getChild("nav_bar_container"); - LLNavigationBar* navbar = LLNavigationBar::getInstance(); - navbar->setShape(nav_bar_container->getLocalRect()); - navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); - nav_bar_container->addChild(navbar); - nav_bar_container->setVisible(TRUE); + LLNavigationBar* navbar = LLNavigationBar::getInstance(); + navbar->setShape(nav_bar_container->getLocalRect()); + navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); + nav_bar_container->addChild(navbar); + nav_bar_container->setVisible(TRUE); - if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) - { - navbar->setVisible(FALSE); - } + if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) + { + navbar->setVisible(FALSE); + } else { reshapeStatusBarContainer(); } - // Top Info bar - LLPanel* topinfo_bar_container = getRootView()->getChild("topinfo_bar_container"); - LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance(); - - topinfo_bar->setShape(topinfo_bar_container->getLocalRect()); - - topinfo_bar_container->addChild(topinfo_bar); - topinfo_bar_container->setVisible(TRUE); - - if (!gSavedSettings.getBOOL("ShowMiniLocationPanel")) - { - topinfo_bar->setVisible(FALSE); - } - - if ( gHUDView == NULL ) - { - LLRect hud_rect = full_window; - hud_rect.mBottom += 50; - if (gMenuBarView && gMenuBarView->isInVisibleChain()) - { - hud_rect.mTop -= gMenuBarView->getRect().getHeight(); - } - gHUDView = new LLHUDView(hud_rect); - getRootView()->addChild(gHUDView); - getRootView()->sendChildToBack(gHUDView); - } - - LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); - - LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance(); - panel_ssf_container->addChild(panel_stand_stop_flying); - - LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance(); - panel_ssf_container->addChild(panel_hide_beacon); - - panel_ssf_container->setVisible(TRUE); - - LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); - - // Load and make the toolbars visible - // Note: we need to load the toolbars only *after* the user is logged in and IW - if (gToolBarView) - { - gToolBarView->loadToolbars(); - gToolBarView->setVisible(TRUE); - } - - if (!gNonInteractive) - { - LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild("destination_guide_contents"); - if (destinations) - { - destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("DestinationGuideURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild("avatar_picker_contents"); - if (avatar_picker) - { - avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("AvatarPickerURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - } + // Top Info bar + LLPanel* topinfo_bar_container = getRootView()->getChild("topinfo_bar_container"); + LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance(); + + topinfo_bar->setShape(topinfo_bar_container->getLocalRect()); + + topinfo_bar_container->addChild(topinfo_bar); + topinfo_bar_container->setVisible(TRUE); + + if (!gSavedSettings.getBOOL("ShowMiniLocationPanel")) + { + topinfo_bar->setVisible(FALSE); + } + + if ( gHUDView == NULL ) + { + LLRect hud_rect = full_window; + hud_rect.mBottom += 50; + if (gMenuBarView && gMenuBarView->isInVisibleChain()) + { + hud_rect.mTop -= gMenuBarView->getRect().getHeight(); + } + gHUDView = new LLHUDView(hud_rect); + getRootView()->addChild(gHUDView); + getRootView()->sendChildToBack(gHUDView); + } + + LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); + + LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance(); + panel_ssf_container->addChild(panel_stand_stop_flying); + + LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance(); + panel_ssf_container->addChild(panel_hide_beacon); + + panel_ssf_container->setVisible(TRUE); + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); + + // Load and make the toolbars visible + // Note: we need to load the toolbars only *after* the user is logged in and IW + if (gToolBarView) + { + gToolBarView->loadToolbars(); + gToolBarView->setVisible(TRUE); + } + + if (!gNonInteractive) + { + LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild("destination_guide_contents"); + if (destinations) + { + destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("DestinationGuideURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild("avatar_picker_contents"); + if (avatar_picker) + { + avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("AvatarPickerURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + } } // Destroy the UI void LLViewerWindow::shutdownViews() { - // clean up warning logger - RecordToChatConsole::getInstance()->stopRecorder(); - LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ; - - gFocusMgr.unlockFocus(); - gFocusMgr.setMouseCapture(NULL); - gFocusMgr.setKeyboardFocus(NULL); - gFocusMgr.setTopCtrl(NULL); - if (mWindow) - { - mWindow->allowLanguageTextInput(NULL, FALSE); - } - - delete mDebugText; - mDebugText = NULL; - - LL_INFOS() << "DebugText deleted." << LL_ENDL ; - - // Cleanup global views - if (gMorphView) - { - gMorphView->setVisible(FALSE); - } - LL_INFOS() << "Global views cleaned." << LL_ENDL ; - - LLNotificationsUI::LLToast::cleanupToasts(); - LL_INFOS() << "Leftover toast cleaned up." << LL_ENDL; - - // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open - // will crump with LL_ERRS. - LLModalDialog::shutdownModals(); - LL_INFOS() << "LLModalDialog shut down." << LL_ENDL; - - // destroy the nav bar, not currently part of gViewerWindow - // *TODO: Make LLNavigationBar part of gViewerWindow - LLNavigationBar::deleteSingleton(); - LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ; - - // destroy menus after instantiating navbar above, as it needs - // access to gMenuHolder - cleanup_menus(); - LL_INFOS() << "menus destroyed." << LL_ENDL ; - - view_listener_t::cleanup(); - LL_INFOS() << "view listeners destroyed." << LL_ENDL ; - - // Clean up pointers that are going to be invalid. (todo: check sMenuContainer) - mProgressView = NULL; - mPopupView = NULL; - - // Delete all child views. - delete mRootView; - mRootView = NULL; - LL_INFOS() << "RootView deleted." << LL_ENDL ; - - LLMenuOptionPathfindingRebakeNavmesh::getInstance()->quit(); - - // Automatically deleted as children of mRootView. Fix the globals. - gStatusBar = NULL; - gIMMgr = NULL; - gToolTipView = NULL; - - gToolBarView = NULL; - gFloaterView = NULL; - gMorphView = NULL; - - gHUDView = NULL; + // clean up warning logger + RecordToChatConsole::getInstance()->stopRecorder(); + LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ; + + gFocusMgr.unlockFocus(); + gFocusMgr.setMouseCapture(NULL); + gFocusMgr.setKeyboardFocus(NULL); + gFocusMgr.setTopCtrl(NULL); + if (mWindow) + { + mWindow->allowLanguageTextInput(NULL, FALSE); + } + + delete mDebugText; + mDebugText = NULL; + + LL_INFOS() << "DebugText deleted." << LL_ENDL ; + + // Cleanup global views + if (gMorphView) + { + gMorphView->setVisible(FALSE); + } + LL_INFOS() << "Global views cleaned." << LL_ENDL ; + + LLNotificationsUI::LLToast::cleanupToasts(); + LL_INFOS() << "Leftover toast cleaned up." << LL_ENDL; + + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open + // will crump with LL_ERRS. + LLModalDialog::shutdownModals(); + LL_INFOS() << "LLModalDialog shut down." << LL_ENDL; + + // destroy the nav bar, not currently part of gViewerWindow + // *TODO: Make LLNavigationBar part of gViewerWindow + LLNavigationBar::deleteSingleton(); + LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ; + + // destroy menus after instantiating navbar above, as it needs + // access to gMenuHolder + cleanup_menus(); + LL_INFOS() << "menus destroyed." << LL_ENDL ; + + view_listener_t::cleanup(); + LL_INFOS() << "view listeners destroyed." << LL_ENDL ; + + // Clean up pointers that are going to be invalid. (todo: check sMenuContainer) + mProgressView = NULL; + mPopupView = NULL; + + // Delete all child views. + delete mRootView; + mRootView = NULL; + LL_INFOS() << "RootView deleted." << LL_ENDL ; + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->quit(); + + // Automatically deleted as children of mRootView. Fix the globals. + gStatusBar = NULL; + gIMMgr = NULL; + gToolTipView = NULL; + + gToolBarView = NULL; + gFloaterView = NULL; + gMorphView = NULL; + + gHUDView = NULL; } void LLViewerWindow::shutdownGL() { - //-------------------------------------------------------- - // Shutdown GL cleanly. Order is very important here. - //-------------------------------------------------------- - LLFontGL::destroyDefaultFonts(); - SUBSYSTEM_CLEANUP(LLFontManager); - stop_glerror(); + //-------------------------------------------------------- + // Shutdown GL cleanly. Order is very important here. + //-------------------------------------------------------- + LLFontGL::destroyDefaultFonts(); + SUBSYSTEM_CLEANUP(LLFontManager); + stop_glerror(); + + gSky.cleanup(); + stop_glerror(); - gSky.cleanup(); - stop_glerror(); + LL_INFOS() << "Cleaning up pipeline" << LL_ENDL; + gPipeline.cleanup(); + stop_glerror(); - LL_INFOS() << "Cleaning up pipeline" << LL_ENDL; - gPipeline.cleanup(); - stop_glerror(); + //MUST clean up pipeline before cleaning up wearables + LL_INFOS() << "Cleaning up wearables" << LL_ENDL; + LLWearableList::instance().cleanup() ; - //MUST clean up pipeline before cleaning up wearables - LL_INFOS() << "Cleaning up wearables" << LL_ENDL; - LLWearableList::instance().cleanup() ; + gTextureList.shutdown(); + stop_glerror(); - gTextureList.shutdown(); - stop_glerror(); + gBumpImageList.shutdown(); + stop_glerror(); - gBumpImageList.shutdown(); - stop_glerror(); + LLWorldMapView::cleanupTextures(); - LLWorldMapView::cleanupTextures(); + LLViewerTextureManager::cleanup() ; + SUBSYSTEM_CLEANUP(LLImageGL) ; - LLViewerTextureManager::cleanup() ; - SUBSYSTEM_CLEANUP(LLImageGL) ; - - LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; + LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; - LL_INFOS() << "Cleaning up select manager" << LL_ENDL; - LLSelectMgr::getInstance()->cleanup(); + LL_INFOS() << "Cleaning up select manager" << LL_ENDL; + LLSelectMgr::getInstance()->cleanup(); - LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL; - stopGL(FALSE); - stop_glerror(); + LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL; + stopGL(FALSE); + stop_glerror(); - gGL.shutdown(); + gGL.shutdown(); - SUBSYSTEM_CLEANUP(LLVertexBuffer); + SUBSYSTEM_CLEANUP(LLVertexBuffer); - LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; + LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; } // shutdownViews() and shutdownGL() need to be called first LLViewerWindow::~LLViewerWindow() { - LL_INFOS() << "Destroying Window" << LL_ENDL; - destroyWindow(); + LL_INFOS() << "Destroying Window" << LL_ENDL; + destroyWindow(); - delete mDebugText; - mDebugText = NULL; + delete mDebugText; + mDebugText = NULL; - if (LLViewerShaderMgr::sInitialized) - { - LLViewerShaderMgr::releaseInstance(); - LLViewerShaderMgr::sInitialized = FALSE; - } + if (LLViewerShaderMgr::sInitialized) + { + LLViewerShaderMgr::releaseInstance(); + LLViewerShaderMgr::sInitialized = FALSE; + } } void LLViewerWindow::setCursor( ECursorType c ) { - mWindow->setCursor( c ); + mWindow->setCursor( c ); } void LLViewerWindow::showCursor() { - mWindow->showCursor(); - - mCursorHidden = FALSE; + mWindow->showCursor(); + + mCursorHidden = FALSE; } void LLViewerWindow::hideCursor() { - // And hide the cursor - mWindow->hideCursor(); + // And hide the cursor + mWindow->hideCursor(); - mCursorHidden = TRUE; + mCursorHidden = TRUE; } void LLViewerWindow::sendShapeToSim() { - LLMessageSystem* msg = gMessageSystem; - if(!msg) return; - msg->newMessageFast(_PREHASH_AgentHeightWidth); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); - msg->nextBlockFast(_PREHASH_HeightWidthBlock); - msg->addU32Fast(_PREHASH_GenCounter, 0); - U16 height16 = (U16) mWorldViewRectRaw.getHeight(); - U16 width16 = (U16) mWorldViewRectRaw.getWidth(); - msg->addU16Fast(_PREHASH_Height, height16); - msg->addU16Fast(_PREHASH_Width, width16); - gAgent.sendReliableMessage(); + LLMessageSystem* msg = gMessageSystem; + if(!msg) return; + msg->newMessageFast(_PREHASH_AgentHeightWidth); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); + msg->nextBlockFast(_PREHASH_HeightWidthBlock); + msg->addU32Fast(_PREHASH_GenCounter, 0); + U16 height16 = (U16) mWorldViewRectRaw.getHeight(); + U16 width16 = (U16) mWorldViewRectRaw.getWidth(); + msg->addU16Fast(_PREHASH_Height, height16); + msg->addU16Fast(_PREHASH_Width, width16); + gAgent.sendReliableMessage(); } // Must be called after window is created to set up agent // camera variables and UI variables. void LLViewerWindow::reshape(S32 width, S32 height) { - // Destroying the window at quit time generates spurious - // reshape messages. We don't care about these, and we - // don't want to send messages because the message system - // may have been destructed. - if (!LLApp::isExiting()) - { - gWindowResized = TRUE; + // Destroying the window at quit time generates spurious + // reshape messages. We don't care about these, and we + // don't want to send messages because the message system + // may have been destructed. + if (!LLApp::isExiting()) + { + gWindowResized = TRUE; - // update our window rectangle - mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width; - mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height; + // update our window rectangle + mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width; + mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height; - //glViewport(0, 0, width, height ); + //glViewport(0, 0, width, height ); LLViewerCamera * camera = LLViewerCamera::getInstance(); // simpleton, might not exist - if (height > 0 && camera) - { + if (height > 0 && camera) + { camera->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); camera->setAspect( getWorldViewAspectRatio() ); - } + } - calcDisplayScale(); - - BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); - LLUI::setScaleFactor(mDisplayScale); + calcDisplayScale(); - // update our window rectangle - mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]); - mWindowRectScaled.mTop = mWindowRectScaled.mBottom + ll_round((F32)height / mDisplayScale.mV[VY]); + BOOL display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); + LLUI::setScaleFactor(mDisplayScale); - setup2DViewport(); + // update our window rectangle + mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]); + mWindowRectScaled.mTop = mWindowRectScaled.mBottom + ll_round((F32)height / mDisplayScale.mV[VY]); - // Inform lower views of the change - // round up when converting coordinates to make sure there are no gaps at edge of window - LLView::sForceReshape = display_scale_changed; - mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY])); + setup2DViewport(); + + // Inform lower views of the change + // round up when converting coordinates to make sure there are no gaps at edge of window + LLView::sForceReshape = display_scale_changed; + mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY])); if (display_scale_changed) { // Needs only a 'scale change' update, everything else gets handled by LLLayoutStack::updateClass() LLPanelLogin::reshapePanel(); } - LLView::sForceReshape = FALSE; + LLView::sForceReshape = FALSE; - // clear font width caches - if (display_scale_changed) - { - LLHUDObject::reshapeAll(); - } + // clear font width caches + if (display_scale_changed) + { + LLHUDObject::reshapeAll(); + } - sendShapeToSim(); + sendShapeToSim(); - // store new settings for the mode we are in, regardless - BOOL maximized = mWindow->getMaximized(); - gSavedSettings.setBOOL("WindowMaximized", maximized); + // store new settings for the mode we are in, regardless + BOOL maximized = mWindow->getMaximized(); + gSavedSettings.setBOOL("WindowMaximized", maximized); - if (!maximized) - { - U32 min_window_width=gSavedSettings.getU32("MinWindowWidth"); - U32 min_window_height=gSavedSettings.getU32("MinWindowHeight"); - // tell the OS specific window code about min window size - mWindow->setMinSize(min_window_width, min_window_height); + if (!maximized) + { + U32 min_window_width=gSavedSettings.getU32("MinWindowWidth"); + U32 min_window_height=gSavedSettings.getU32("MinWindowHeight"); + // tell the OS specific window code about min window size + mWindow->setMinSize(min_window_width, min_window_height); - LLCoordScreen window_rect; - if (!gNonInteractive && mWindow->getSize(&window_rect)) - { - // Only save size if not maximized - gSavedSettings.setU32("WindowWidth", window_rect.mX); - gSavedSettings.setU32("WindowHeight", window_rect.mY); - } - } + LLCoordScreen window_rect; + if (!gNonInteractive && mWindow->getSize(&window_rect)) + { + // Only save size if not maximized + gSavedSettings.setU32("WindowWidth", window_rect.mX); + gSavedSettings.setU32("WindowHeight", window_rect.mY); + } + } - sample(LLStatViewer::WINDOW_WIDTH, width); - sample(LLStatViewer::WINDOW_HEIGHT, height); + sample(LLStatViewer::WINDOW_WIDTH, width); + sample(LLStatViewer::WINDOW_HEIGHT, height); - LLLayoutStack::updateClass(); - } + LLLayoutStack::updateClass(); + } } // Hide normal UI when a logon fails void LLViewerWindow::setNormalControlsVisible( BOOL visible ) { - if(LLChicletBar::instanceExists()) - { - LLChicletBar::getInstance()->setVisible(visible); - LLChicletBar::getInstance()->setEnabled(visible); - } - - if ( gMenuBarView ) - { - gMenuBarView->setVisible( visible ); - gMenuBarView->setEnabled( visible ); - - // ...and set the menu color appropriately. - setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, - LLGridManager::getInstance()->isInProductionGrid()); - } - - if ( gStatusBar ) - { - gStatusBar->setVisible( visible ); - gStatusBar->setEnabled( visible ); - } - - LLNavigationBar* navbarp = LLUI::getInstance()->getRootView()->findChild("navigation_bar"); - if (navbarp) - { - // when it's time to show navigation bar we need to ensure that the user wants to see it - // i.e. ShowNavbarNavigationPanel option is true - navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") ); - } + if(LLChicletBar::instanceExists()) + { + LLChicletBar::getInstance()->setVisible(visible); + LLChicletBar::getInstance()->setEnabled(visible); + } + + if ( gMenuBarView ) + { + gMenuBarView->setVisible( visible ); + gMenuBarView->setEnabled( visible ); + + // ...and set the menu color appropriately. + setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, + LLGridManager::getInstance()->isInProductionGrid()); + } + + if ( gStatusBar ) + { + gStatusBar->setVisible( visible ); + gStatusBar->setEnabled( visible ); + } + + LLNavigationBar* navbarp = LLUI::getInstance()->getRootView()->findChild("navigation_bar"); + if (navbarp) + { + // when it's time to show navigation bar we need to ensure that the user wants to see it + // i.e. ShowNavbarNavigationPanel option is true + navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") ); + } } void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) @@ -2580,17 +2580,17 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) LLSD args; LLColor4 new_bg_color; - // god more important than project, proj more important than grid - if ( god_mode ) + // god more important than project, proj more important than grid + if ( god_mode ) { - if ( LLGridManager::getInstance()->isInProductionGrid() ) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); - } - else - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); - } + if ( LLGridManager::getInstance()->isInProductionGrid() ) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); + } + else + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); + } } else { @@ -2603,24 +2603,24 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) case LLVersionInfo::PROJECT_VIEWER: new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" ); break; - + case LLVersionInfo::BETA_VIEWER: new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBetaBgColor" ); break; - + case LLVersionInfo::RELEASE_VIEWER: if(!LLGridManager::getInstance()->isInProductionGrid()) { new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } - else + else { new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); } break; } } - + if(gMenuBarView) { gMenuBarView->setBackgroundColor( new_bg_color ); @@ -2635,149 +2635,149 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) void LLViewerWindow::drawDebugText() { gUIProgram.bind(); - gGL.color4f(1,1,1,1); - gGL.pushMatrix(); - gGL.pushUIMatrix(); - { - // scale view by UI global scale factor and aspect ratio correction factor - gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - mDebugText->draw(); - } - gGL.popUIMatrix(); - gGL.popMatrix(); + gGL.color4f(1,1,1,1); + gGL.pushMatrix(); + gGL.pushUIMatrix(); + { + // scale view by UI global scale factor and aspect ratio correction factor + gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); + mDebugText->draw(); + } + gGL.popUIMatrix(); + gGL.popMatrix(); - gGL.flush(); - gUIProgram.unbind(); + gGL.flush(); + gUIProgram.unbind(); } void LLViewerWindow::draw() { - + //#if LL_DEBUG - LLView::sIsDrawing = TRUE; + LLView::sIsDrawing = TRUE; //#endif - stop_glerror(); - - LLUI::setLineWidth(1.f); - - LLUI::setLineWidth(1.f); - // Reset any left-over transforms - gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.loadIdentity(); - - //S32 screen_x, screen_y; - - if (!gSavedSettings.getBOOL("RenderUIBuffer")) - { - LLView::sDirtyRect = getWindowRectScaled(); - } - - // HACK for timecode debugging - if (gSavedSettings.getBOOL("DisplayTimecode")) - { - // draw timecode block - std::string text; - - gGL.loadIdentity(); - - microsecondsToTimecodeString(gFrameTime,text); - const LLFontGL* font = LLFontGL::getFontSansSerif(); - font->renderUTF8(text, 0, - ll_round((getWindowWidthScaled()/2)-100.f), - ll_round((getWindowHeightScaled()-60.f)), - LLColor4( 1.f, 1.f, 1.f, 1.f ), - LLFontGL::LEFT, LLFontGL::TOP); - } - - // Draw all nested UI views. - // No translation needed, this view is glued to 0,0 - - gUIProgram.bind(); - gGL.color4f(1, 1, 1, 1); + stop_glerror(); - gGL.pushMatrix(); - LLUI::pushMatrix(); - { - - // scale view by UI global scale factor and aspect ratio correction factor - gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - - LLVector2 old_scale_factor = LLUI::getScaleFactor(); - // apply camera zoom transform (for high res screenshots) - F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); - S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - //decompose subregion number to x and y values - int pos_y = sub_region / llceil(zoom_factor); - int pos_x = sub_region - (pos_y*llceil(zoom_factor)); - // offset for this tile - gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, - (F32)getWindowHeightScaled() * -(F32)pos_y, - 0.f); - gGL.scalef(zoom_factor, zoom_factor, 1.f); - LLUI::getScaleFactor() *= zoom_factor; - } - - // Draw tool specific overlay on world - LLToolMgr::getInstance()->getCurrentTool()->draw(); - - if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() ) - { - drawMouselookInstructions(); - stop_glerror(); - } - - // Draw all nested UI views. - // No translation needed, this view is glued to 0,0 - mRootView->draw(); - - if (LLView::sDebugRects) - { - gToolTipView->drawStickyRect(); - } - - // Draw optional on-top-of-everyone view - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - if (top_ctrl && top_ctrl->getVisible()) - { - S32 screen_x, screen_y; - top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - LLUI::pushMatrix(); - LLUI::translate( (F32) screen_x, (F32) screen_y); - top_ctrl->draw(); - LLUI::popMatrix(); - } - - - if( gShowOverlayTitle && !mOverlayTitle.empty() ) - { - // Used for special titles such as "Second Life - Special E3 2003 Beta" - const S32 DIST_FROM_TOP = 20; - LLFontGL::getFontSansSerifBig()->renderUTF8( - mOverlayTitle, 0, - ll_round( getWindowWidthScaled() * 0.5f), - getWindowHeightScaled() - DIST_FROM_TOP, - LLColor4(1, 1, 1, 0.4f), - LLFontGL::HCENTER, LLFontGL::TOP); - } - - LLUI::setScaleFactor(old_scale_factor); - } - LLUI::popMatrix(); - gGL.popMatrix(); - - gUIProgram.unbind(); - - LLView::sIsDrawing = FALSE; -} + LLUI::setLineWidth(1.f); -// Takes a single keyup event, usually when UI is visible -BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) -{ + LLUI::setLineWidth(1.f); + // Reset any left-over transforms + gGL.matrixMode(LLRender::MM_MODELVIEW); + + gGL.loadIdentity(); + + //S32 screen_x, screen_y; + + if (!gSavedSettings.getBOOL("RenderUIBuffer")) + { + LLView::sDirtyRect = getWindowRectScaled(); + } + + // HACK for timecode debugging + if (gSavedSettings.getBOOL("DisplayTimecode")) + { + // draw timecode block + std::string text; + + gGL.loadIdentity(); + + microsecondsToTimecodeString(gFrameTime,text); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + font->renderUTF8(text, 0, + ll_round((getWindowWidthScaled()/2)-100.f), + ll_round((getWindowHeightScaled()-60.f)), + LLColor4( 1.f, 1.f, 1.f, 1.f ), + LLFontGL::LEFT, LLFontGL::TOP); + } + + // Draw all nested UI views. + // No translation needed, this view is glued to 0,0 + + gUIProgram.bind(); + gGL.color4f(1, 1, 1, 1); + + gGL.pushMatrix(); + LLUI::pushMatrix(); + { + + // scale view by UI global scale factor and aspect ratio correction factor + gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); + + LLVector2 old_scale_factor = LLUI::getScaleFactor(); + // apply camera zoom transform (for high res screenshots) + F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); + S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); + if (zoom_factor > 1.f) + { + //decompose subregion number to x and y values + int pos_y = sub_region / llceil(zoom_factor); + int pos_x = sub_region - (pos_y*llceil(zoom_factor)); + // offset for this tile + gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, + (F32)getWindowHeightScaled() * -(F32)pos_y, + 0.f); + gGL.scalef(zoom_factor, zoom_factor, 1.f); + LLUI::getScaleFactor() *= zoom_factor; + } + + // Draw tool specific overlay on world + LLToolMgr::getInstance()->getCurrentTool()->draw(); + + if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() ) + { + drawMouselookInstructions(); + stop_glerror(); + } + + // Draw all nested UI views. + // No translation needed, this view is glued to 0,0 + mRootView->draw(); + + if (LLView::sDebugRects) + { + gToolTipView->drawStickyRect(); + } + + // Draw optional on-top-of-everyone view + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + if (top_ctrl && top_ctrl->getVisible()) + { + S32 screen_x, screen_y; + top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + LLUI::pushMatrix(); + LLUI::translate( (F32) screen_x, (F32) screen_y); + top_ctrl->draw(); + LLUI::popMatrix(); + } + + + if( gShowOverlayTitle && !mOverlayTitle.empty() ) + { + // Used for special titles such as "Second Life - Special E3 2003 Beta" + const S32 DIST_FROM_TOP = 20; + LLFontGL::getFontSansSerifBig()->renderUTF8( + mOverlayTitle, 0, + ll_round( getWindowWidthScaled() * 0.5f), + getWindowHeightScaled() - DIST_FROM_TOP, + LLColor4(1, 1, 1, 0.4f), + LLFontGL::HCENTER, LLFontGL::TOP); + } + + LLUI::setScaleFactor(old_scale_factor); + } + LLUI::popMatrix(); + gGL.popMatrix(); + + gUIProgram.unbind(); + + LLView::sIsDrawing = FALSE; +} + +// Takes a single keyup event, usually when UI is visible +BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) +{ if (LLSetKeyBindDialog::recordKey(key, mask, FALSE)) { LL_DEBUGS() << "KeyUp handled by LLSetKeyBindDialog" << LL_ENDL; @@ -2788,45 +2788,45 @@ BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask) LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if (keyboard_focus - && !(mask & (MASK_CONTROL | MASK_ALT)) - && !gFocusMgr.getKeystrokesOnly()) - { - // We have keyboard focus, and it's not an accelerator + && !(mask & (MASK_CONTROL | MASK_ALT)) + && !gFocusMgr.getKeystrokesOnly()) + { + // We have keyboard focus, and it's not an accelerator if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown()) { return keyboard_focus->handleKeyUp(key, mask, FALSE); } else if (key < 0x80) - { - // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. - return (gFocusMgr.getKeyboardFocus() != NULL); - } - } - - if (keyboard_focus) - { - if (keyboard_focus->handleKeyUp(key, mask, FALSE)) - { - LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return TRUE; - } - else { - LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned FALSE" << LL_ENDL; - } - } - - // don't pass keys on to world when something in ui has focus - return gFocusMgr.childHasKeyboardFocus(mRootView) - || LLMenuGL::getKeyboardMode() - || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); + { + // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. + return (gFocusMgr.getKeyboardFocus() != NULL); + } + } + + if (keyboard_focus) + { + if (keyboard_focus->handleKeyUp(key, mask, FALSE)) + { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return TRUE; + } + else { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned FALSE" << LL_ENDL; + } + } + + // don't pass keys on to world when something in ui has focus + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); } // Takes a single keydown event, usually when UI is visible BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { - // hide tooltips on keypress - LLToolTipMgr::instance().blockToolTips(); + // hide tooltips on keypress + LLToolTipMgr::instance().blockToolTips(); // Menus get handled on key down instead of key up // so keybindings have to be recorded before that @@ -2838,7 +2838,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); - + if (keyboard_focus && !gFocusMgr.getKeystrokesOnly()) { @@ -2911,279 +2911,279 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } } - // let menus handle navigation keys for navigation - if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE)) - ||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE)) - ||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))) - { - LL_DEBUGS() << "LLviewerWindow::handleKey handle nav keys for nav" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - - // give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus - // as long as focus isn't locked - if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked()) - { - // Check the current floater's menu first, if it has one. - if (gFocusMgr.keyboardFocusHasAccelerators() - && keyboard_focus - && keyboard_focus->handleKey(key,mask,FALSE)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - if (gAgent.isInitialized() - && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) - && gMenuBarView - && gMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return TRUE; - } - - if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - } - - // give floaters first chance to handle TAB key - // so frontmost floater gets focus - // if nothing has focus, go to first or last UI element as appropriate + // let menus handle navigation keys for navigation + if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE)) + ||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE)) + ||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))) + { + LL_DEBUGS() << "LLviewerWindow::handleKey handle nav keys for nav" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + + // give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus + // as long as focus isn't locked + if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked()) + { + // Check the current floater's menu first, if it has one. + if (gFocusMgr.keyboardFocusHasAccelerators() + && keyboard_focus + && keyboard_focus->handleKey(key,mask,FALSE)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + if (gAgent.isInitialized() + && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) + && gMenuBarView + && gMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return TRUE; + } + + if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + } + + // give floaters first chance to handle TAB key + // so frontmost floater gets focus + // if nothing has focus, go to first or last UI element as appropriate if (key == KEY_TAB && (mask & MASK_CONTROL || keyboard_focus == NULL)) - { - LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL; - if (gMenuHolder) gMenuHolder->hideMenus(); - - // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode - gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0); - - // do CTRL-TAB and CTRL-SHIFT-TAB logic - if (mask & MASK_SHIFT) - { - mRootView->focusPrevRoot(); - } - else - { - mRootView->focusNextRoot(); - } - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - // hidden edit menu for cut/copy/paste - if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); - std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); - - if( keyboard_focus ) - { - if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) - { - if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) - { - // let Control-Up and Control-Down through for chat line history, - if (!(key == KEY_UP && mask == MASK_CONTROL) - && !(key == KEY_DOWN && mask == MASK_CONTROL) - && !(key == KEY_UP && mask == MASK_ALT) - && !(key == KEY_DOWN && mask == MASK_ALT)) - { - switch(key) - { - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - case KEY_DOWN: - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_HOME: - case KEY_END: - // when chatbar is empty or ArrowKeysAlwaysMove set, - // pass arrow keys on to avatar... - return FALSE; - default: - break; - } - } - } - } - - if (keyboard_focus->handleKey(key, mask, FALSE)) - { - - LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } else { - LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned FALSE" << LL_ENDL; - } - } - - if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) ) - { - LL_DEBUGS() << "LLviewerWindow::handleKey toolbar handling?" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - // Try for a new-format gesture - if (LLGestureMgr::instance().triggerGesture(key, mask)) - { - LL_DEBUGS() << "LLviewerWindow::handleKey new gesture feature" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - // See if this is a gesture trigger. If so, eat the key and - // don't pass it down to the menus. - if (gGestureList.trigger(key, mask)) - { - LL_DEBUGS() << "LLviewerWindow::handleKey check gesture trigger" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return TRUE; - } - - // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, - // no view has keyboard focus, this is a printable character key (and no modifier key is - // pressed except shift), then give focus to nearby chat (STORM-560) - if ( LLStartUp::getStartupState() >= STATE_STARTED && - gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && - !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) - { - // Initialize nearby chat if it's missing - LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); - if (!nearby_chat) - { - LLSD name("im_container"); - LLFloaterReg::toggleInstanceOrBringToFront(name); - } - - LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance("nearby_chat")->getChatBox(); - if (chat_editor) - { - // passing NULL here, character will be added later when it is handled by character handler. - nearby_chat->startChat(NULL); - return TRUE; - } - } - - // give menus a chance to handle unmodified accelerator keys - if (gAgent.isInitialized() - && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) - && gMenuBarView - && gMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return TRUE; - } - - if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - { - return TRUE; - } - - // don't pass keys on to world when something in ui has focus - return gFocusMgr.childHasKeyboardFocus(mRootView) - || LLMenuGL::getKeyboardMode() - || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); + { + LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL; + if (gMenuHolder) gMenuHolder->hideMenus(); + + // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode + gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0); + + // do CTRL-TAB and CTRL-SHIFT-TAB logic + if (mask & MASK_SHIFT) + { + mRootView->focusPrevRoot(); + } + else + { + mRootView->focusNextRoot(); + } + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + // hidden edit menu for cut/copy/paste + if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); + std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); + + if( keyboard_focus ) + { + if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) + { + if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) + { + // let Control-Up and Control-Down through for chat line history, + if (!(key == KEY_UP && mask == MASK_CONTROL) + && !(key == KEY_DOWN && mask == MASK_CONTROL) + && !(key == KEY_UP && mask == MASK_ALT) + && !(key == KEY_DOWN && mask == MASK_ALT)) + { + switch(key) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_HOME: + case KEY_END: + // when chatbar is empty or ArrowKeysAlwaysMove set, + // pass arrow keys on to avatar... + return FALSE; + default: + break; + } + } + } + } + + if (keyboard_focus->handleKey(key, mask, FALSE)) + { + + LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } else { + LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned FALSE" << LL_ENDL; + } + } + + if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) ) + { + LL_DEBUGS() << "LLviewerWindow::handleKey toolbar handling?" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + // Try for a new-format gesture + if (LLGestureMgr::instance().triggerGesture(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey new gesture feature" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + // See if this is a gesture trigger. If so, eat the key and + // don't pass it down to the menus. + if (gGestureList.trigger(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey check gesture trigger" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return TRUE; + } + + // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, + // no view has keyboard focus, this is a printable character key (and no modifier key is + // pressed except shift), then give focus to nearby chat (STORM-560) + if ( LLStartUp::getStartupState() >= STATE_STARTED && + gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && + !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) + { + // Initialize nearby chat if it's missing + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance("nearby_chat"); + if (!nearby_chat) + { + LLSD name("im_container"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance("nearby_chat")->getChatBox(); + if (chat_editor) + { + // passing NULL here, character will be added later when it is handled by character handler. + nearby_chat->startChat(NULL); + return TRUE; + } + } + + // give menus a chance to handle unmodified accelerator keys + if (gAgent.isInitialized() + && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) + && gMenuBarView + && gMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return TRUE; + } + + if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) + { + return TRUE; + } + + // don't pass keys on to world when something in ui has focus + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); } BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) { - // HACK: We delay processing of return keys until they arrive as a Unicode char, - // so that if you're typing chat text at low frame rate, we don't send the chat - // until all keystrokes have been entered. JC - // HACK: Numeric keypad on Mac is Unicode 3 - // HACK: Control-M on Windows is Unicode 13 - if ((uni_char == 13 && mask != MASK_CONTROL) - || (uni_char == 3 && mask == MASK_NONE) ) - { - if (mask != MASK_ALT) - { - // remaps, handles ignored cases and returns back to viewer window. - return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); - } - } - - // let menus handle navigation (jump) keys - if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE)) - { - return TRUE; - } - - // Traverses up the hierarchy - LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); - if( keyboard_focus ) - { - if (keyboard_focus->handleUnicodeChar(uni_char, FALSE)) - { - return TRUE; - } + // HACK: We delay processing of return keys until they arrive as a Unicode char, + // so that if you're typing chat text at low frame rate, we don't send the chat + // until all keystrokes have been entered. JC + // HACK: Numeric keypad on Mac is Unicode 3 + // HACK: Control-M on Windows is Unicode 13 + if ((uni_char == 13 && mask != MASK_CONTROL) + || (uni_char == 3 && mask == MASK_NONE) ) + { + if (mask != MASK_ALT) + { + // remaps, handles ignored cases and returns back to viewer window. + return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); + } + } + + // let menus handle navigation (jump) keys + if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE)) + { + return TRUE; + } + + // Traverses up the hierarchy + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + if( keyboard_focus ) + { + if (keyboard_focus->handleUnicodeChar(uni_char, FALSE)) + { + return TRUE; + } return TRUE; - } + } - return FALSE; + return FALSE; } void LLViewerWindow::handleScrollWheel(S32 clicks) { - LLUI::getInstance()->resetMouseIdleTimer(); - - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - if( mouse_captor ) - { - S32 local_x; - S32 local_y; - mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); - mouse_captor->handleScrollWheel(local_x, local_y, clicks); - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel handled by captor " << mouse_captor->getName() << LL_ENDL; - } - return; - } - - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - if (top_ctrl) - { - S32 local_x; - S32 local_y; - top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); - if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return; - } - - if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) ) - { - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel" << LLView::sMouseHandlerMessage << LL_ENDL; - } - return; - } - else if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel not handled by view" << LL_ENDL; - } - - // Zoom the camera in and out behavior - - if(top_ctrl == 0 - && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) - && gAgentCamera.isInitialized()) - gAgentCamera.handleScrollWheel(clicks); - - return; + LLUI::getInstance()->resetMouseIdleTimer(); + + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + if( mouse_captor ) + { + S32 local_x; + S32 local_y; + mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); + mouse_captor->handleScrollWheel(local_x, local_y, clicks); + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel handled by captor " << mouse_captor->getName() << LL_ENDL; + } + return; + } + + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + if (top_ctrl) + { + S32 local_x; + S32 local_y; + top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); + if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return; + } + + if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) ) + { + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel" << LLView::sMouseHandlerMessage << LL_ENDL; + } + return; + } + else if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel not handled by view" << LL_ENDL; + } + + // Zoom the camera in and out behavior + + if(top_ctrl == 0 + && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) + && gAgentCamera.isInitialized()) + gAgentCamera.handleScrollWheel(clicks); + + return; } void LLViewerWindow::handleScrollHWheel(S32 clicks) @@ -3192,7 +3192,7 @@ void LLViewerWindow::handleScrollHWheel(S32 clicks) { return; } - + LLUI::getInstance()->resetMouseIdleTimer(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); @@ -3236,42 +3236,42 @@ void LLViewerWindow::handleScrollHWheel(S32 clicks) void LLViewerWindow::addPopup(LLView* popup) { - if (mPopupView) - { - mPopupView->addPopup(popup); - } + if (mPopupView) + { + mPopupView->addPopup(popup); + } } void LLViewerWindow::removePopup(LLView* popup) { - if (mPopupView) - { - mPopupView->removePopup(popup); - } + if (mPopupView) + { + mPopupView->removePopup(popup); + } } void LLViewerWindow::clearPopups() { - if (mPopupView) - { - mPopupView->clearPopups(); - } + if (mPopupView) + { + mPopupView->clearPopups(); + } } void LLViewerWindow::moveCursorToCenter() { - if (! gSavedSettings.getBOOL("DisableMouseWarp")) - { - S32 x = getWorldViewWidthScaled() / 2; - S32 y = getWorldViewHeightScaled() / 2; - - LLUI::getInstance()->setMousePositionScreen(x, y); - - //on a forced move, all deltas get zeroed out to prevent jumping - mCurrentMousePoint.set(x,y); - mLastMousePoint.set(x,y); - mCurrentMouseDelta.set(0,0); - } + if (! gSavedSettings.getBOOL("DisableMouseWarp")) + { + S32 x = getWorldViewWidthScaled() / 2; + S32 y = getWorldViewHeightScaled() / 2; + + LLUI::getInstance()->setMousePositionScreen(x, y); + + //on a forced move, all deltas get zeroed out to prevent jumping + mCurrentMousePoint.set(x,y); + mLastMousePoint.set(x,y); + mCurrentMouseDelta.set(0,0); + } } @@ -3282,32 +3282,32 @@ void LLViewerWindow::moveCursorToCenter() void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) { - if (viewp) - { - if (!params.styled_message.empty()) - { - params.styled_message.add().text("\n---------\n"); - } - LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); - // NOTE: we skip "root" since it is assumed - for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView(); - tooltip_it != end_tooltip_it; - ++tooltip_it) - { - LLView* viewp = *tooltip_it; - - params.styled_message.add().text(viewp->getName()); - - LLPanel* panelp = dynamic_cast(viewp); - if (panelp && !panelp->getXMLFilename().empty()) - { - params.styled_message.add() - .text("(" + panelp->getXMLFilename() + ")") - .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f)); - } - params.styled_message.add().text("/"); - } - } + if (viewp) + { + if (!params.styled_message.empty()) + { + params.styled_message.add().text("\n---------\n"); + } + LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); + // NOTE: we skip "root" since it is assumed + for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView(); + tooltip_it != end_tooltip_it; + ++tooltip_it) + { + LLView* viewp = *tooltip_it; + + params.styled_message.add().text(viewp->getName()); + + LLPanel* panelp = dynamic_cast(viewp); + if (panelp && !panelp->getXMLFilename().empty()) + { + params.styled_message.add() + .text("(" + panelp->getXMLFilename() + ")") + .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f)); + } + params.styled_message.add().text("/"); + } + } } static LLTrace::BlockTimerStatHandle ftm("Update UI"); @@ -3316,922 +3316,922 @@ static LLTrace::BlockTimerStatHandle ftm("Update UI"); // event processing. void LLViewerWindow::updateUI() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); - static std::string last_handle_msg; + static std::string last_handle_msg; - if (gLoggedInTime.getStarted()) - { - if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout")) - { - LLFirstUse::notUsingDestinationGuide(); - } - if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout")) - { - LLFirstUse::notUsingSidePanel(); - } - } + if (gLoggedInTime.getStarted()) + { + if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout")) + { + LLFirstUse::notUsingDestinationGuide(); + } + if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout")) + { + LLFirstUse::notUsingSidePanel(); + } + } - LLConsole::updateClass(); + LLConsole::updateClass(); - // animate layout stacks so we have up to date rect for world view - LLLayoutStack::updateClass(); + // animate layout stacks so we have up to date rect for world view + LLLayoutStack::updateClass(); - // use full window for world view when not rendering UI - bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - updateWorldViewRect(world_view_uses_full_window); + // use full window for world view when not rendering UI + bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); + updateWorldViewRect(world_view_uses_full_window); - LLView::sMouseHandlerMessage.clear(); + LLView::sMouseHandlerMessage.clear(); - S32 x = mCurrentMousePoint.mX; - S32 y = mCurrentMousePoint.mY; + S32 x = mCurrentMousePoint.mX; + S32 y = mCurrentMousePoint.mY; - MASK mask = gKeyboard->currentMask(TRUE); + MASK mask = gKeyboard->currentMask(TRUE); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, FALSE, - &gDebugRaycastFaceHit, + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1; + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, FALSE, + &gDebugRaycastFaceHit, &gDebugRaycastGLTFNodeHit, &gDebugRaycastGLTFPrimitiveHit, - &gDebugRaycastIntersection, - &gDebugRaycastTexCoord, - &gDebugRaycastNormal, - &gDebugRaycastTangent, - &gDebugRaycastStart, - &gDebugRaycastEnd); - - gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL); - } - - updateMouseDelta(); - updateKeyboardFocus(); - - BOOL handled = FALSE; - - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - LLView* captor_view = dynamic_cast(mouse_captor); - - //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN - - //build set of views containing mouse cursor by traversing UI hierarchy and testing - //screen rect against mouse cursor - view_handle_set_t mouse_hover_set; - - // constraint mouse enter events to children of mouse captor - LLView* root_view = captor_view; - - // if mouse captor doesn't exist or isn't a LLView - // then allow mouse enter events on entire UI hierarchy - if (!root_view) - { - root_view = mRootView; - } - - static LLCachedControl dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); - if (dump_menu_holder) - { - static bool init = false; - static LLFrameTimer child_count_timer; - static std::vector child_vec; - if (!init) - { - child_count_timer.resetWithExpiry(5.f); - init = true; - } - if (child_count_timer.hasExpired()) - { - LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; - std::vector local_child_vec; - LLView::child_list_t child_list = *gMenuHolder->getChildList(); - for (auto child : child_list) - { - local_child_vec.emplace_back(child->getName()); - } - if (!local_child_vec.empty() && local_child_vec != child_vec) - { - std::vector out_vec; - std::sort(local_child_vec.begin(), local_child_vec.end()); - std::sort(child_vec.begin(), child_vec.end()); - std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); - if (!out_vec.empty()) - { - LL_INFOS() << "gMenuHolder removal diff size: '"<getParent(); - while(captor_parent_view) - { - mouse_hover_set.insert(captor_parent_view->getHandle()); - captor_parent_view = captor_parent_view->getParent(); - } - } - - // aggregate visible views that contain mouse cursor in display order - LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups(); - - for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it) - { - LLView* popup = popup_it->get(); - if (popup && popup->calcScreenBoundingRect().pointInRect(x, y)) - { - // iterator over contents of top_ctrl, and throw into mouse_hover_set - for (LLView::tree_iterator_t it = popup->beginTreeDFS(); - it != popup->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - } - - // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events - if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y)) - { - // iterator over contents of top_ctrl, and throw into mouse_hover_set - for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS(); - it != top_ctrl->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - else - { - // walk UI tree in depth-first order - for (LLView::tree_iterator_t it = root_view->beginTreeDFS(); - it != root_view->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - // calculating the screen rect involves traversing the parent, so this is less than optimal - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - - // if this view is mouse opaque, nothing behind it should be in mouse_hover_set - if (viewp->getMouseOpaque()) - { - // constrain further iteration to children of this widget - it = viewp->beginTreeDFS(); - } - - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - } - - typedef std::vector > view_handle_list_t; - - // call onMouseEnter() on all views which contain the mouse cursor but did not before - view_handle_list_t mouse_enter_views; - std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(), - mMouseHoverViews.begin(), mMouseHoverViews.end(), - std::back_inserter(mouse_enter_views)); - for (view_handle_list_t::iterator it = mouse_enter_views.begin(); - it != mouse_enter_views.end(); - ++it) - { - LLView* viewp = it->get(); - if (viewp) - { - LLRect view_screen_rect = viewp->calcScreenRect(); - viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask); - } - } - - // call onMouseLeave() on all views which no longer contain the mouse cursor - view_handle_list_t mouse_leave_views; - std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(), - mouse_hover_set.begin(), mouse_hover_set.end(), - std::back_inserter(mouse_leave_views)); - for (view_handle_list_t::iterator it = mouse_leave_views.begin(); - it != mouse_leave_views.end(); - ++it) - { - LLView* viewp = it->get(); - if (viewp) - { - LLRect view_screen_rect = viewp->calcScreenRect(); - viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask); - } - } - - // store resulting hover set for next frame - swap(mMouseHoverViews, mouse_hover_set); - - // only handle hover events when UI is enabled - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - - if( mouse_captor ) - { - // Pass hover events to object capturing mouse events. - S32 local_x; - S32 local_y; - mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); - handled = mouse_captor->handleHover(local_x, local_y, mask); - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Hover handled by captor " << mouse_captor->getName() << LL_ENDL; - } - - if( !handled ) - { - LL_DEBUGS("UserInput") << "hover not handled by mouse captor" << LL_ENDL; - } - } - else - { - if (top_ctrl) - { - S32 local_x, local_y; - top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); - handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask); - } - - if ( !handled ) - { - // x and y are from last time mouse was in window - // mMouseInWindow tracks *actual* mouse location - if (mMouseInWindow && mRootView->handleHover(x, y, mask) ) - { - if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg) - { - last_handle_msg = LLView::sMouseHandlerMessage; - LL_INFOS() << "Hover" << LLView::sMouseHandlerMessage << LL_ENDL; - } - handled = TRUE; - } - else if (LLView::sDebugMouseHandling) - { - if (last_handle_msg != LLStringUtil::null) - { - last_handle_msg.clear(); - LL_INFOS() << "Hover not handled by view" << LL_ENDL; - } - } - } - - if (!handled) - { - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - - if(mMouseInWindow && tool) - { - handled = tool->handleHover(x, y, mask); - } - } - } - - // Show a new tool tip (or update one that is already shown) - BOOL tool_tip_handled = FALSE; - std::string tool_tip_msg; - if( handled - && !mWindow->isCursorHidden()) - { - LLRect screen_sticky_rect = mRootView->getLocalRect(); - S32 local_x, local_y; - - static LLCachedControl debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0); - if (debug_show_xui_names) - { - LLToolTip::Params params; - - LLView* tooltip_view = mRootView; - LLView::tree_iterator_t end_it = mRootView->endTreeDFS(); - for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it) - { - LLView* viewp = *it; - LLRect screen_rect; - viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); - if (!(viewp->getVisible() - && screen_rect.pointInRect(x, y))) - { - it.skipDescendants(); - } - // only report xui names for LLUICtrls, - // and blacklist the various containers we don't care about - else if (dynamic_cast(viewp) - && viewp != gMenuHolder - && viewp != gFloaterView - && viewp != gConsole) - { - if (dynamic_cast(viewp)) - { - // constrain search to descendants of this (frontmost) floater - // by resetting iterator - it = viewp->beginTreeDFS(); - } - - // if we are in a new part of the tree (not a descendent of current tooltip_view) - // then push the results for tooltip_view and start with a new potential view - // NOTE: this emulates visiting only the leaf nodes that meet our criteria - if (!viewp->hasAncestor(tooltip_view)) - { - append_xui_tooltip(tooltip_view, params); - screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); - } - tooltip_view = viewp; - } - } - - append_xui_tooltip(tooltip_view, params); - params.styled_message.add().text("\n"); - - screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); - - params.sticky_rect = screen_sticky_rect; - params.max_width = 400; - - LLToolTipMgr::instance().show(params); - } - // if there is a mouse captor, nothing else gets a tooltip - else if (mouse_captor) - { - mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); - tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask); - } - else - { - // next is top_ctrl - if (!tool_tip_handled && top_ctrl) - { - top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); - tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask ); - } - - if (!tool_tip_handled) - { - local_x = x; local_y = y; - tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask ); - } - - LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool(); - if (!tool_tip_handled && current_tool) - { - current_tool->screenPointToLocal(x, y, &local_x, &local_y); - tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask ); - } - } - } - } - else - { // just have tools handle hover when UI is turned off - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - - if(mMouseInWindow && tool) - { - handled = tool->handleHover(x, y, mask); - } - } - - updateLayout(); - - mLastMousePoint = mCurrentMousePoint; - - // cleanup unused selections when no modal dialogs are open - if (LLModalDialog::activeCount() == 0) - { - LLViewerParcelMgr::getInstance()->deselectUnused(); - } - - if (LLModalDialog::activeCount() == 0) - { - LLSelectMgr::getInstance()->deselectUnused(); - } -} - - -void LLViewerWindow::updateLayout() -{ - LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); - if (gFloaterTools != NULL - && tool != NULL - && tool != gToolNull - && tool != LLToolCompInspect::getInstance() - && tool != LLToolDragAndDrop::getInstance() - && !gSavedSettings.getBOOL("FreezeTime")) - { - // Suppress the toolbox view if our source tool was the pie tool, - // and we've overridden to something else. - bool suppress_toolbox = - (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) && - (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()); - - LLMouseHandler *captor = gFocusMgr.getMouseCapture(); - // With the null, inspect, or drag and drop tool, don't muck - // with visibility. - - if (gFloaterTools->isMinimized() - || (tool != LLToolPie::getInstance() // not default tool - && tool != LLToolCompGun::getInstance() // not coming out of mouselook - && !suppress_toolbox // not override in third person - && LLToolMgr::getInstance()->getCurrentToolset()->isShowFloaterTools() - && (!captor || dynamic_cast(captor) != NULL))) // not dragging - { - // Force floater tools to be visible (unless minimized) - if (!gFloaterTools->getVisible()) - { - gFloaterTools->openFloater(); - } - // Update the location of the blue box tool popup - LLCoordGL select_center_screen; - MASK mask = gKeyboard->currentMask(TRUE); - gFloaterTools->updatePopup( select_center_screen, mask ); - } - else - { - gFloaterTools->setVisible(FALSE); - } - //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible()); - } - - // Always update console - if(gConsole) - { - LLRect console_rect = getChatConsoleRect(); - gConsole->reshape(console_rect.getWidth(), console_rect.getHeight()); - gConsole->setRect(console_rect); - } -} + &gDebugRaycastIntersection, + &gDebugRaycastTexCoord, + &gDebugRaycastNormal, + &gDebugRaycastTangent, + &gDebugRaycastStart, + &gDebugRaycastEnd); + + gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL); + } -void LLViewerWindow::updateMouseDelta() -{ -#if LL_WINDOWS - LLCoordCommon delta; - mWindow->getCursorDelta(&delta); - S32 dx = delta.mX; - S32 dy = delta.mY; -#else - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); - S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); -#endif + updateMouseDelta(); + updateKeyboardFocus(); - //RN: fix for asynchronous notification of mouse leaving window not working - LLCoordWindow mouse_pos; - mWindow->getCursorPosition(&mouse_pos); - if (mouse_pos.mX < 0 || - mouse_pos.mY < 0 || - mouse_pos.mX > mWindowRectRaw.getWidth() || - mouse_pos.mY > mWindowRectRaw.getHeight()) - { - mMouseInWindow = FALSE; - } - else - { - mMouseInWindow = TRUE; - } - - LLVector2 mouse_vel; - - if (gSavedSettings.getBOOL("MouseSmooth")) - { - static F32 fdx = 0.f; - static F32 fdy = 0.f; - - F32 amount = 16.f; - fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds.value()*amount,1.f); - fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); - - mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy)); - mouse_vel.setVec(fdx,fdy); - } - else - { - mCurrentMouseDelta.set(dx, dy); - mouse_vel.setVec((F32) dx, (F32) dy); - } - - sample(sMouseVelocityStat, mouse_vel.magVec()); -} + BOOL handled = FALSE; -void LLViewerWindow::updateKeyboardFocus() -{ - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - gFocusMgr.setKeyboardFocus(NULL); - } - - // clean up current focus - LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); - if (cur_focus) - { - if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain()) - { - // don't release focus, just reassign so that if being given - // to a sibling won't call onFocusLost on all the ancestors - // gFocusMgr.releaseFocusIfNeeded(cur_focus); - - LLUICtrl* parent = cur_focus->getParentUICtrl(); - const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot(); - bool new_focus_found = false; - while(parent) - { - if (parent->isCtrl() - && (parent->hasTabStop() || parent == focus_root) - && !parent->getIsChrome() - && parent->isInVisibleChain() - && parent->isInEnabledChain()) - { - if (!parent->focusFirstItem()) - { - parent->setFocus(TRUE); - } - new_focus_found = true; - break; - } - parent = parent->getParentUICtrl(); - } - - // if we didn't find a better place to put focus, just release it - // hasFocus() will return true if and only if we didn't touch focus since we - // are only moving focus higher in the hierarchy - if (!new_focus_found) - { - cur_focus->setFocus(FALSE); - } - } - else if (cur_focus->isFocusRoot()) - { - // focus roots keep trying to delegate focus to their first valid descendant - // this assumes that focus roots are not valid focus holders on their own - cur_focus->focusFirstItem(); - } - } - - // last ditch force of edit menu to selection manager - if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) - { - LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance(); - } - - if (gFloaterView->getCycleMode()) - { - // sync all floaters with their focus state - gFloaterView->highlightFocusedFloater(); - gSnapshotFloaterView->highlightFocusedFloater(); - MASK mask = gKeyboard->currentMask(TRUE); - if ((mask & MASK_CONTROL) == 0) - { - // control key no longer held down, finish cycle mode - gFloaterView->setCycleMode(FALSE); - - gFloaterView->syncFloaterTabOrder(); - } - else - { - // user holding down CTRL, don't update tab order of floaters - } - } - else - { - // update focused floater - gFloaterView->highlightFocusedFloater(); - gSnapshotFloaterView->highlightFocusedFloater(); - // make sure floater visible order is in sync with tab order - gFloaterView->syncFloaterTabOrder(); - } -} + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + LLView* captor_view = dynamic_cast(mouse_captor); -static LLTrace::BlockTimerStatHandle FTM_UPDATE_WORLD_VIEW("Update World View"); -void LLViewerWindow::updateWorldViewRect(bool use_full_window) -{ - LL_RECORD_BLOCK_TIME(FTM_UPDATE_WORLD_VIEW); + //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN - // start off using whole window to render world - LLRect new_world_rect = mWindowRectRaw; + //build set of views containing mouse cursor by traversing UI hierarchy and testing + //screen rect against mouse cursor + view_handle_set_t mouse_hover_set; - if (use_full_window == false && mWorldViewPlaceholder.get()) - { - new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect(); - // clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers - new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1); - new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1); + // constraint mouse enter events to children of mouse captor + LLView* root_view = captor_view; - new_world_rect.mLeft = ll_round((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]); - new_world_rect.mRight = ll_round((F32)new_world_rect.mRight * mDisplayScale.mV[VX]); - new_world_rect.mBottom = ll_round((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]); - new_world_rect.mTop = ll_round((F32)new_world_rect.mTop * mDisplayScale.mV[VY]); - } + // if mouse captor doesn't exist or isn't a LLView + // then allow mouse enter events on entire UI hierarchy + if (!root_view) + { + root_view = mRootView; + } - if (mWorldViewRectRaw != new_world_rect) - { - mWorldViewRectRaw = new_world_rect; - gResizeScreenTexture = TRUE; - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + static LLCachedControl dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); + if (dump_menu_holder) + { + static bool init = false; + static LLFrameTimer child_count_timer; + static std::vector child_vec; + if (!init) + { + child_count_timer.resetWithExpiry(5.f); + init = true; + } + if (child_count_timer.hasExpired()) + { + LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; + std::vector local_child_vec; + LLView::child_list_t child_list = *gMenuHolder->getChildList(); + for (auto child : child_list) + { + local_child_vec.emplace_back(child->getName()); + } + if (!local_child_vec.empty() && local_child_vec != child_vec) + { + std::vector out_vec; + std::sort(local_child_vec.begin(), local_child_vec.end()); + std::sort(child_vec.begin(), child_vec.end()); + std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder removal diff size: '"<getParent(); + while(captor_parent_view) + { + mouse_hover_set.insert(captor_parent_view->getHandle()); + captor_parent_view = captor_parent_view->getParent(); + } + } + + // aggregate visible views that contain mouse cursor in display order + LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups(); + + for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it) + { + LLView* popup = popup_it->get(); + if (popup && popup->calcScreenBoundingRect().pointInRect(x, y)) + { + // iterator over contents of top_ctrl, and throw into mouse_hover_set + for (LLView::tree_iterator_t it = popup->beginTreeDFS(); + it != popup->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + } + + // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events + if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y)) + { + // iterator over contents of top_ctrl, and throw into mouse_hover_set + for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS(); + it != top_ctrl->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + else + { + // walk UI tree in depth-first order + for (LLView::tree_iterator_t it = root_view->beginTreeDFS(); + it != root_view->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + // calculating the screen rect involves traversing the parent, so this is less than optimal + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + + // if this view is mouse opaque, nothing behind it should be in mouse_hover_set + if (viewp->getMouseOpaque()) + { + // constrain further iteration to children of this widget + it = viewp->beginTreeDFS(); + } + + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + } + + typedef std::vector > view_handle_list_t; + + // call onMouseEnter() on all views which contain the mouse cursor but did not before + view_handle_list_t mouse_enter_views; + std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(), + mMouseHoverViews.begin(), mMouseHoverViews.end(), + std::back_inserter(mouse_enter_views)); + for (view_handle_list_t::iterator it = mouse_enter_views.begin(); + it != mouse_enter_views.end(); + ++it) + { + LLView* viewp = it->get(); + if (viewp) + { + LLRect view_screen_rect = viewp->calcScreenRect(); + viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask); + } + } + + // call onMouseLeave() on all views which no longer contain the mouse cursor + view_handle_list_t mouse_leave_views; + std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(), + mouse_hover_set.begin(), mouse_hover_set.end(), + std::back_inserter(mouse_leave_views)); + for (view_handle_list_t::iterator it = mouse_leave_views.begin(); + it != mouse_leave_views.end(); + ++it) + { + LLView* viewp = it->get(); + if (viewp) + { + LLRect view_screen_rect = viewp->calcScreenRect(); + viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask); + } + } + + // store resulting hover set for next frame + swap(mMouseHoverViews, mouse_hover_set); + + // only handle hover events when UI is enabled + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + + if( mouse_captor ) + { + // Pass hover events to object capturing mouse events. + S32 local_x; + S32 local_y; + mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); + handled = mouse_captor->handleHover(local_x, local_y, mask); + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Hover handled by captor " << mouse_captor->getName() << LL_ENDL; + } + + if( !handled ) + { + LL_DEBUGS("UserInput") << "hover not handled by mouse captor" << LL_ENDL; + } + } + else + { + if (top_ctrl) + { + S32 local_x, local_y; + top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); + handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask); + } + + if ( !handled ) + { + // x and y are from last time mouse was in window + // mMouseInWindow tracks *actual* mouse location + if (mMouseInWindow && mRootView->handleHover(x, y, mask) ) + { + if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg) + { + last_handle_msg = LLView::sMouseHandlerMessage; + LL_INFOS() << "Hover" << LLView::sMouseHandlerMessage << LL_ENDL; + } + handled = TRUE; + } + else if (LLView::sDebugMouseHandling) + { + if (last_handle_msg != LLStringUtil::null) + { + last_handle_msg.clear(); + LL_INFOS() << "Hover not handled by view" << LL_ENDL; + } + } + } + + if (!handled) + { + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + + if(mMouseInWindow && tool) + { + handled = tool->handleHover(x, y, mask); + } + } + } + + // Show a new tool tip (or update one that is already shown) + BOOL tool_tip_handled = FALSE; + std::string tool_tip_msg; + if( handled + && !mWindow->isCursorHidden()) + { + LLRect screen_sticky_rect = mRootView->getLocalRect(); + S32 local_x, local_y; + + static LLCachedControl debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0); + if (debug_show_xui_names) + { + LLToolTip::Params params; + + LLView* tooltip_view = mRootView; + LLView::tree_iterator_t end_it = mRootView->endTreeDFS(); + for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it) + { + LLView* viewp = *it; + LLRect screen_rect; + viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect); + if (!(viewp->getVisible() + && screen_rect.pointInRect(x, y))) + { + it.skipDescendants(); + } + // only report xui names for LLUICtrls, + // and blacklist the various containers we don't care about + else if (dynamic_cast(viewp) + && viewp != gMenuHolder + && viewp != gFloaterView + && viewp != gConsole) + { + if (dynamic_cast(viewp)) + { + // constrain search to descendants of this (frontmost) floater + // by resetting iterator + it = viewp->beginTreeDFS(); + } + + // if we are in a new part of the tree (not a descendent of current tooltip_view) + // then push the results for tooltip_view and start with a new potential view + // NOTE: this emulates visiting only the leaf nodes that meet our criteria + if (!viewp->hasAncestor(tooltip_view)) + { + append_xui_tooltip(tooltip_view, params); + screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); + } + tooltip_view = viewp; + } + } + + append_xui_tooltip(tooltip_view, params); + params.styled_message.add().text("\n"); + + screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect()); + + params.sticky_rect = screen_sticky_rect; + params.max_width = 400; + + LLToolTipMgr::instance().show(params); + } + // if there is a mouse captor, nothing else gets a tooltip + else if (mouse_captor) + { + mouse_captor->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask); + } + else + { + // next is top_ctrl + if (!tool_tip_handled && top_ctrl) + { + top_ctrl->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask ); + } + + if (!tool_tip_handled) + { + local_x = x; local_y = y; + tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask ); + } + + LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool(); + if (!tool_tip_handled && current_tool) + { + current_tool->screenPointToLocal(x, y, &local_x, &local_y); + tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask ); + } + } + } + } + else + { // just have tools handle hover when UI is turned off + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + + if(mMouseInWindow && tool) + { + handled = tool->handleHover(x, y, mask); + } + } + + updateLayout(); + + mLastMousePoint = mCurrentMousePoint; + + // cleanup unused selections when no modal dialogs are open + if (LLModalDialog::activeCount() == 0) + { + LLViewerParcelMgr::getInstance()->deselectUnused(); + } + + if (LLModalDialog::activeCount() == 0) + { + LLSelectMgr::getInstance()->deselectUnused(); + } +} + + +void LLViewerWindow::updateLayout() +{ + LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); + if (gFloaterTools != NULL + && tool != NULL + && tool != gToolNull + && tool != LLToolCompInspect::getInstance() + && tool != LLToolDragAndDrop::getInstance() + && !gSavedSettings.getBOOL("FreezeTime")) + { + // Suppress the toolbox view if our source tool was the pie tool, + // and we've overridden to something else. + bool suppress_toolbox = + (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) && + (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance()); + + LLMouseHandler *captor = gFocusMgr.getMouseCapture(); + // With the null, inspect, or drag and drop tool, don't muck + // with visibility. + + if (gFloaterTools->isMinimized() + || (tool != LLToolPie::getInstance() // not default tool + && tool != LLToolCompGun::getInstance() // not coming out of mouselook + && !suppress_toolbox // not override in third person + && LLToolMgr::getInstance()->getCurrentToolset()->isShowFloaterTools() + && (!captor || dynamic_cast(captor) != NULL))) // not dragging + { + // Force floater tools to be visible (unless minimized) + if (!gFloaterTools->getVisible()) + { + gFloaterTools->openFloater(); + } + // Update the location of the blue box tool popup + LLCoordGL select_center_screen; + MASK mask = gKeyboard->currentMask(TRUE); + gFloaterTools->updatePopup( select_center_screen, mask ); + } + else + { + gFloaterTools->setVisible(FALSE); + } + //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible()); + } + + // Always update console + if(gConsole) + { + LLRect console_rect = getChatConsoleRect(); + gConsole->reshape(console_rect.getWidth(), console_rect.getHeight()); + gConsole->setRect(console_rect); + } +} + +void LLViewerWindow::updateMouseDelta() +{ +#if LL_WINDOWS + LLCoordCommon delta; + mWindow->getCursorDelta(&delta); + S32 dx = delta.mX; + S32 dy = delta.mY; +#else + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); +#endif + + //RN: fix for asynchronous notification of mouse leaving window not working + LLCoordWindow mouse_pos; + mWindow->getCursorPosition(&mouse_pos); + if (mouse_pos.mX < 0 || + mouse_pos.mY < 0 || + mouse_pos.mX > mWindowRectRaw.getWidth() || + mouse_pos.mY > mWindowRectRaw.getHeight()) + { + mMouseInWindow = FALSE; + } + else + { + mMouseInWindow = TRUE; + } + + LLVector2 mouse_vel; + + if (gSavedSettings.getBOOL("MouseSmooth")) + { + static F32 fdx = 0.f; + static F32 fdy = 0.f; + + F32 amount = 16.f; + fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds.value()*amount,1.f); + fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); - // sending a signal with a new WorldView rect - mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled); - } + mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy)); + mouse_vel.setVec(fdx,fdy); + } + else + { + mCurrentMouseDelta.set(dx, dy); + mouse_vel.setVec((F32) dx, (F32) dy); + } + + sample(sMouseVelocityStat, mouse_vel.magVec()); +} + +void LLViewerWindow::updateKeyboardFocus() +{ + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + gFocusMgr.setKeyboardFocus(NULL); + } + + // clean up current focus + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus) + { + if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain()) + { + // don't release focus, just reassign so that if being given + // to a sibling won't call onFocusLost on all the ancestors + // gFocusMgr.releaseFocusIfNeeded(cur_focus); + + LLUICtrl* parent = cur_focus->getParentUICtrl(); + const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot(); + bool new_focus_found = false; + while(parent) + { + if (parent->isCtrl() + && (parent->hasTabStop() || parent == focus_root) + && !parent->getIsChrome() + && parent->isInVisibleChain() + && parent->isInEnabledChain()) + { + if (!parent->focusFirstItem()) + { + parent->setFocus(TRUE); + } + new_focus_found = true; + break; + } + parent = parent->getParentUICtrl(); + } + + // if we didn't find a better place to put focus, just release it + // hasFocus() will return true if and only if we didn't touch focus since we + // are only moving focus higher in the hierarchy + if (!new_focus_found) + { + cur_focus->setFocus(FALSE); + } + } + else if (cur_focus->isFocusRoot()) + { + // focus roots keep trying to delegate focus to their first valid descendant + // this assumes that focus roots are not valid focus holders on their own + cur_focus->focusFirstItem(); + } + } + + // last ditch force of edit menu to selection manager + if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) + { + LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance(); + } + + if (gFloaterView->getCycleMode()) + { + // sync all floaters with their focus state + gFloaterView->highlightFocusedFloater(); + gSnapshotFloaterView->highlightFocusedFloater(); + MASK mask = gKeyboard->currentMask(TRUE); + if ((mask & MASK_CONTROL) == 0) + { + // control key no longer held down, finish cycle mode + gFloaterView->setCycleMode(FALSE); + + gFloaterView->syncFloaterTabOrder(); + } + else + { + // user holding down CTRL, don't update tab order of floaters + } + } + else + { + // update focused floater + gFloaterView->highlightFocusedFloater(); + gSnapshotFloaterView->highlightFocusedFloater(); + // make sure floater visible order is in sync with tab order + gFloaterView->syncFloaterTabOrder(); + } +} + +static LLTrace::BlockTimerStatHandle FTM_UPDATE_WORLD_VIEW("Update World View"); +void LLViewerWindow::updateWorldViewRect(bool use_full_window) +{ + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WORLD_VIEW); + + // start off using whole window to render world + LLRect new_world_rect = mWindowRectRaw; + + if (use_full_window == false && mWorldViewPlaceholder.get()) + { + new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect(); + // clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers + new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1); + new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1); + + new_world_rect.mLeft = ll_round((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]); + new_world_rect.mRight = ll_round((F32)new_world_rect.mRight * mDisplayScale.mV[VX]); + new_world_rect.mBottom = ll_round((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]); + new_world_rect.mTop = ll_round((F32)new_world_rect.mTop * mDisplayScale.mV[VY]); + } + + if (mWorldViewRectRaw != new_world_rect) + { + mWorldViewRectRaw = new_world_rect; + gResizeScreenTexture = TRUE; + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + + LLRect old_world_rect_scaled = mWorldViewRectScaled; + mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); + + // sending a signal with a new WorldView rect + mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled); + } } void LLViewerWindow::saveLastMouse(const LLCoordGL &point) { - // Store last mouse location. - // If mouse leaves window, pretend last point was on edge of window - - if (point.mX < 0) - { - mCurrentMousePoint.mX = 0; - } - else if (point.mX > getWindowWidthScaled()) - { - mCurrentMousePoint.mX = getWindowWidthScaled(); - } - else - { - mCurrentMousePoint.mX = point.mX; - } - - if (point.mY < 0) - { - mCurrentMousePoint.mY = 0; - } - else if (point.mY > getWindowHeightScaled() ) - { - mCurrentMousePoint.mY = getWindowHeightScaled(); - } - else - { - mCurrentMousePoint.mY = point.mY; - } + // Store last mouse location. + // If mouse leaves window, pretend last point was on edge of window + + if (point.mX < 0) + { + mCurrentMousePoint.mX = 0; + } + else if (point.mX > getWindowWidthScaled()) + { + mCurrentMousePoint.mX = getWindowWidthScaled(); + } + else + { + mCurrentMousePoint.mX = point.mX; + } + + if (point.mY < 0) + { + mCurrentMousePoint.mY = 0; + } + else if (point.mY > getWindowHeightScaled() ) + { + mCurrentMousePoint.mY = getWindowHeightScaled(); + } + else + { + mCurrentMousePoint.mY = point.mY; + } } // Draws the selection outlines for the currently selected objects // Must be called after displayObjects is called, which sets the mGLName parameter // NOTE: This function gets called 3 times: -// render_ui_3d: FALSE, FALSE, TRUE -// render_hud_elements: FALSE, FALSE, FALSE +// render_ui_3d: FALSE, FALSE, TRUE +// render_hud_elements: FALSE, FALSE, FALSE void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud ) { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (!for_hud && !for_gl_pick) - { - // Call this once and only once - LLSelectMgr::getInstance()->updateSilhouettes(); - } - - // Draw fence around land selections - if (for_gl_pick) - { - if (pick_parcel_walls) - { - LLViewerParcelMgr::getInstance()->renderParcelCollision(); - } - } - else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) || - (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD)) - { - LLSelectMgr::getInstance()->renderSilhouettes(for_hud); - - stop_glerror(); - - // setup HUD render - if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) - { - LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); - - // set up transform to encompass bounding box of HUD - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame - gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); - } - - // Render light for editing - if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit()) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLEnable gls_blend(GL_BLEND); - LLGLEnable gls_cull(GL_CULL_FACE); - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - if (selection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom, zoom, zoom); - } - - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLDrawable* drawable = object->mDrawable; - if (drawable && drawable->isLight()) - { - LLVOVolume* vovolume = drawable->getVOVolume(); - gGL.pushMatrix(); - - LLVector3 center = drawable->getPositionAgent(); - gGL.translatef(center[0], center[1], center[2]); - F32 scale = vovolume->getLightRadius(); - gGL.scalef(scale, scale, scale); - - LLColor4 color(vovolume->getLightSRGBColor(), .5f); - gGL.color4fv(color.mV); - - //F32 pixel_area = 100000.f; - // Render Outside - gSphere.render(); - - // Render Inside - glCullFace(GL_FRONT); - gSphere.render(); - glCullFace(GL_BACK); - - gGL.popMatrix(); - } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); - - gGL.popMatrix(); - } - - // NOTE: The average position for the axis arrows of the selected objects should - // not be recalculated at this time. If they are, then group rotations will break. - - // Draw arrows at average center of all selected objects - LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); - if (tool) - { - if(tool->isAlwaysRendered()) - { - tool->render(); - } - else - { - if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() ) - { - bool all_selected_objects_move; - bool all_selected_objects_modify; - // Note: This might be costly to do on each frame and when a lot of objects are selected - // we might be better off with some kind of memory for selection and/or states, consider - // optimizing, perhaps even some kind of selection generation at level of LLSelectMgr to - // make whole viewer benefit. - LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(all_selected_objects_move, all_selected_objects_modify); - - BOOL draw_handles = TRUE; - - if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) - { - draw_handles = FALSE; - } - - if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) - { - draw_handles = FALSE; - } - - if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() ) - { - draw_handles = FALSE; - } - - if( draw_handles ) - { - tool->render(); - } - } - } - if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount()) - { - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - stop_glerror(); - } - } - } + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (!for_hud && !for_gl_pick) + { + // Call this once and only once + LLSelectMgr::getInstance()->updateSilhouettes(); + } + + // Draw fence around land selections + if (for_gl_pick) + { + if (pick_parcel_walls) + { + LLViewerParcelMgr::getInstance()->renderParcelCollision(); + } + } + else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) || + (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD)) + { + LLSelectMgr::getInstance()->renderSilhouettes(for_hud); + + stop_glerror(); + + // setup HUD render + if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount()) + { + LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); + + // set up transform to encompass bounding box of HUD + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame + gGL.translatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); + } + + // Render light for editing + if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit()) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLEnable gls_blend(GL_BLEND); + LLGLEnable gls_cull(GL_CULL_FACE); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + if (selection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom, zoom, zoom); + } + + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable && drawable->isLight()) + { + LLVOVolume* vovolume = drawable->getVOVolume(); + gGL.pushMatrix(); + + LLVector3 center = drawable->getPositionAgent(); + gGL.translatef(center[0], center[1], center[2]); + F32 scale = vovolume->getLightRadius(); + gGL.scalef(scale, scale, scale); + + LLColor4 color(vovolume->getLightSRGBColor(), .5f); + gGL.color4fv(color.mV); + + //F32 pixel_area = 100000.f; + // Render Outside + gSphere.render(); + + // Render Inside + glCullFace(GL_FRONT); + gSphere.render(); + glCullFace(GL_BACK); + + gGL.popMatrix(); + } + return true; + } + } func; + LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); + + gGL.popMatrix(); + } + + // NOTE: The average position for the axis arrows of the selected objects should + // not be recalculated at this time. If they are, then group rotations will break. + + // Draw arrows at average center of all selected objects + LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); + if (tool) + { + if(tool->isAlwaysRendered()) + { + tool->render(); + } + else + { + if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() ) + { + bool all_selected_objects_move; + bool all_selected_objects_modify; + // Note: This might be costly to do on each frame and when a lot of objects are selected + // we might be better off with some kind of memory for selection and/or states, consider + // optimizing, perhaps even some kind of selection generation at level of LLSelectMgr to + // make whole viewer benefit. + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(all_selected_objects_move, all_selected_objects_modify); + + BOOL draw_handles = TRUE; + + if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) + { + draw_handles = FALSE; + } + + if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) + { + draw_handles = FALSE; + } + + if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() ) + { + draw_handles = FALSE; + } + + if( draw_handles ) + { + tool->render(); + } + } + } + if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount()) + { + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + stop_glerror(); + } + } + } } // Return a point near the clicked object representative of the place the object was clicked. LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const { - // create a normalized vector pointing from the camera center into the - // world at the location of the mouse click - LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot ); + // create a normalized vector pointing from the camera center into the + // world at the location of the mouse click + LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot ); - LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal(); + LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.getCameraPositionGlobal(); - // make mouse vector as long as object vector, so it touchs a point near - // where the user clicked on the object - mouse_direction_global *= (F32) relative_object.magVec(); + // make mouse vector as long as object vector, so it touchs a point near + // where the user clicked on the object + mouse_direction_global *= (F32) relative_object.magVec(); - LLVector3d new_pos; - new_pos.setVec(mouse_direction_global); - // transform mouse vector back to world coords - new_pos += gAgentCamera.getCameraPositionGlobal(); + LLVector3d new_pos; + new_pos.setVec(mouse_direction_global); + // transform mouse vector back to world coords + new_pos += gAgentCamera.getCameraPositionGlobal(); - return new_pos; + return new_pos; } BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const { - BOOL intersect = FALSE; + BOOL intersect = FALSE; -// U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK; - if (!intersect) - { - point_global = clickPointInWorldGlobal(x, y, objectp); - LL_INFOS() << "approx intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; - } - else - { - LL_INFOS() << "good intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; - } +// U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK; + if (!intersect) + { + point_global = clickPointInWorldGlobal(x, y, objectp); + LL_INFOS() << "approx intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; + } + else + { + LL_INFOS() << "good intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; + } - return intersect; + return intersect; } void LLViewerWindow::pickAsync( S32 x, - S32 y_from_bot, - MASK mask, - void (*callback)(const LLPickInfo& info), - BOOL pick_transparent, - BOOL pick_rigged, - BOOL pick_unselectable, + S32 y_from_bot, + MASK mask, + void (*callback)(const LLPickInfo& info), + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_unselectable, BOOL pick_reflection_probes) { - // "Show Debug Alpha" means no object actually transparent + // "Show Debug Alpha" means no object actually transparent BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); if (LLDrawPoolAlpha::sShowDebugAlpha || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects"))) @@ -4239,587 +4239,587 @@ void LLViewerWindow::pickAsync( S32 x, pick_transparent = TRUE; } - LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, pick_reflection_probes, pick_unselectable, TRUE, callback); - schedulePick(pick_info); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, FALSE, pick_reflection_probes, pick_unselectable, TRUE, callback); + schedulePick(pick_info); } void LLViewerWindow::schedulePick(LLPickInfo& pick_info) { - if (mPicks.size() >= 1024 || mWindow->getMinimized()) - { //something went wrong, picks are being scheduled but not processed - - if (pick_info.mPickCallback) - { - pick_info.mPickCallback(pick_info); - } - - return; - } - mPicks.push_back(pick_info); - - // delay further event processing until we receive results of pick - // only do this for async picks so that handleMouseUp won't be called - // until the pick triggered in handleMouseDown has been processed, for example - mWindow->delayInputProcessing(); + if (mPicks.size() >= 1024 || mWindow->getMinimized()) + { //something went wrong, picks are being scheduled but not processed + + if (pick_info.mPickCallback) + { + pick_info.mPickCallback(pick_info); + } + + return; + } + mPicks.push_back(pick_info); + + // delay further event processing until we receive results of pick + // only do this for async picks so that handleMouseUp won't be called + // until the pick triggered in handleMouseDown has been processed, for example + mWindow->delayInputProcessing(); } void LLViewerWindow::performPick() { - if (!mPicks.empty()) - { - std::vector::iterator pick_it; - for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) - { - pick_it->fetchResults(); - } + if (!mPicks.empty()) + { + std::vector::iterator pick_it; + for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) + { + pick_it->fetchResults(); + } - mLastPick = mPicks.back(); - mPicks.clear(); - } + mLastPick = mPicks.back(); + mPicks.clear(); + } } void LLViewerWindow::returnEmptyPicks() { - std::vector::iterator pick_it; - for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) - { - mLastPick = *pick_it; - // just trigger callback with empty results - if (pick_it->mPickCallback) - { - pick_it->mPickCallback(*pick_it); - } - } - mPicks.clear(); + std::vector::iterator pick_it; + for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) + { + mLastPick = *pick_it; + // just trigger callback with empty results + if (pick_it->mPickCallback) + { + pick_it->mPickCallback(*pick_it); + } + } + mPicks.clear(); } // Performs the GL object/land pick. LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent, BOOL pick_rigged, BOOL pick_particle, BOOL pick_unselectable, BOOL pick_reflection_probe) { - BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); - 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 - pick_transparent = TRUE; - } - - // shortcut queueing in mPicks and just update mLastPick in place - MASK key_mask = gKeyboard->currentMask(TRUE); - mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, TRUE, FALSE, NULL); - mLastPick.fetchResults(); + BOOL in_build_mode = LLFloaterReg::instanceVisible("build"); + 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 + pick_transparent = TRUE; + } + + // shortcut queueing in mPicks and just update mLastPick in place + MASK key_mask = gKeyboard->currentMask(TRUE); + mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, TRUE, FALSE, NULL); + mLastPick.fetchResults(); - return mLastPick; + return mLastPick; } LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, - LLVector4a* intersection) + LLVector4a* intersection) { - S32 x = mouse_x; - S32 y = mouse_y; + S32 x = mouse_x; + S32 y = mouse_y; - if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position - { - x = getCurrentMouseX(); - y = getCurrentMouseY(); - } + if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position + { + x = getCurrentMouseX(); + y = getCurrentMouseY(); + } - // world coordinates of mouse - // VECTORIZE THIS - LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); - LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); - LLVector3 mouse_world_start = mouse_point_global; - LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; + // world coordinates of mouse + // VECTORIZE THIS + LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); + LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); + LLVector3 mouse_world_start = mouse_point_global; + LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; - LLVector4a start, end; - start.load3(mouse_world_start.mV); - end.load3(mouse_world_end.mV); - - return LLHUDIcon::lineSegmentIntersectAll(start, end, intersection); + LLVector4a start, end; + start.load3(mouse_world_start.mV); + end.load3(mouse_world_end.mV); + + return LLHUDIcon::lineSegmentIntersectAll(start, end, intersection); } LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth, - LLViewerObject *this_object, - S32 this_face, - BOOL pick_transparent, - BOOL pick_rigged, + LLViewerObject *this_object, + S32 this_face, + BOOL pick_transparent, + BOOL pick_rigged, BOOL pick_unselectable, BOOL pick_reflection_probe, - S32* face_hit, + S32* face_hit, S32* gltf_node_hit, S32* gltf_primitive_hit, - LLVector4a *intersection, - LLVector2 *uv, - LLVector4a *normal, - LLVector4a *tangent, - LLVector4a* start, - LLVector4a* end) -{ - S32 x = mouse_x; - S32 y = mouse_y; - - if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position - { - x = getCurrentMouseX(); - y = getCurrentMouseY(); - } - - // HUD coordinates of mouse - LLVector3 mouse_point_hud = mousePointHUD(x, y); - LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0); - LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0); - - // world coordinates of mouse - LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); - LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); - - //get near clip plane - LLVector3 n = LLViewerCamera::getInstance()->getAtAxis(); - LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear(); - - //project mouse point onto plane - LLVector3 pos; - line_plane(mouse_point_global, mouse_direction_global, p, n, pos); - mouse_point_global = pos; - - LLVector3 mouse_world_start = mouse_point_global; - LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; - - if (!LLViewerJoystick::getInstance()->getOverrideCamera()) - { //always set raycast intersection to mouse_world_end unless - //flycam is on (for DoF effect) - gDebugRaycastIntersection.load3(mouse_world_end.mV); - } - - LLVector4a mw_start; - mw_start.load3(mouse_world_start.mV); - LLVector4a mw_end; - mw_end.load3(mouse_world_end.mV); - - LLVector4a mh_start; - mh_start.load3(mouse_hud_start.mV); - LLVector4a mh_end; - mh_end.load3(mouse_hud_end.mV); - - if (start) - { - *start = mw_start; - } - - if (end) - { - *end = mw_end; - } - - LLViewerObject* found = NULL; - - if (this_object) // check only this object - { - if (this_object->isHUDAttachment()) // is a HUD object? - { - 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; - } - } - else // is a world object - { + LLVector4a *intersection, + LLVector2 *uv, + LLVector4a *normal, + LLVector4a *tangent, + LLVector4a* start, + LLVector4a* end) +{ + S32 x = mouse_x; + S32 y = mouse_y; + + if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position + { + x = getCurrentMouseX(); + y = getCurrentMouseY(); + } + + // HUD coordinates of mouse + LLVector3 mouse_point_hud = mousePointHUD(x, y); + LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0); + LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0); + + // world coordinates of mouse + LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); + LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); + + //get near clip plane + LLVector3 n = LLViewerCamera::getInstance()->getAtAxis(); + LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear(); + + //project mouse point onto plane + LLVector3 pos; + line_plane(mouse_point_global, mouse_direction_global, p, n, pos); + mouse_point_global = pos; + + LLVector3 mouse_world_start = mouse_point_global; + LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; + + if (!LLViewerJoystick::getInstance()->getOverrideCamera()) + { //always set raycast intersection to mouse_world_end unless + //flycam is on (for DoF effect) + gDebugRaycastIntersection.load3(mouse_world_end.mV); + } + + LLVector4a mw_start; + mw_start.load3(mouse_world_start.mV); + LLVector4a mw_end; + mw_end.load3(mouse_world_end.mV); + + LLVector4a mh_start; + mh_start.load3(mouse_hud_start.mV); + LLVector4a mh_end; + mh_end.load3(mouse_hud_end.mV); + + if (start) + { + *start = mw_start; + } + + if (end) + { + *end = mw_end; + } + + LLViewerObject* found = NULL; + + if (this_object) // check only this object + { + if (this_object->isHUDAttachment()) // is a HUD object? + { + 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; + } + } + else // is a world object + { if ((pick_reflection_probe || !this_object->isReflectionProbe()) && this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable, - face_hit, intersection, uv, normal, tangent)) - { - found = this_object; - } - } - } - else // check ALL objects - { - found = gPipeline.lineSegmentIntersectInHUD(mh_start, mh_end, pick_transparent, - face_hit, intersection, uv, normal, tangent); - - if (!found) // if not found in HUD, look in world: - { - found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, - face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent); - if (found && !pick_transparent) - { - gDebugRaycastIntersection = *intersection; - } - } - } - - return found; + face_hit, intersection, uv, normal, tangent)) + { + found = this_object; + } + } + } + else // check ALL objects + { + found = gPipeline.lineSegmentIntersectInHUD(mh_start, mh_end, pick_transparent, + face_hit, intersection, uv, normal, tangent); + + if (!found) // if not found in HUD, look in world: + { + found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, + face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent); + if (found && !pick_transparent) + { + gDebugRaycastIntersection = *intersection; + } + } + } + + return found; } // Returns unit vector relative to camera // indicating direction of point on screen x,y LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const { - // find vertical field of view - F32 fov = LLViewerCamera::getInstance()->getView(); + // find vertical field of view + F32 fov = LLViewerCamera::getInstance()->getView(); - // find world view center in scaled ui coordinates - F32 center_x = getWorldViewRectScaled().getCenterX(); - F32 center_y = getWorldViewRectScaled().getCenterY(); + // find world view center in scaled ui coordinates + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); - // calculate pixel distance to screen - F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f)); + // calculate pixel distance to screen + F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f)); - // calculate click point relative to middle of screen - F32 click_x = x - center_x; - F32 click_y = y - center_y; + // calculate click point relative to middle of screen + F32 click_x = x - center_x; + F32 click_y = y - center_y; - // compute mouse vector - LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis() - - click_x * LLViewerCamera::getInstance()->getLeftAxis() - + click_y * LLViewerCamera::getInstance()->getUpAxis(); + // compute mouse vector + LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis() + - click_x * LLViewerCamera::getInstance()->getLeftAxis() + + click_y * LLViewerCamera::getInstance()->getUpAxis(); - mouse_vector.normVec(); + mouse_vector.normVec(); - return mouse_vector; + return mouse_vector; } LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const { - // find screen resolution - S32 height = getWorldViewHeightScaled(); + // find screen resolution + S32 height = getWorldViewHeightScaled(); - // find world view center - F32 center_x = getWorldViewRectScaled().getCenterX(); - F32 center_y = getWorldViewRectScaled().getCenterY(); + // find world view center + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); - // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5 - F32 hud_x = -((F32)x - center_x) / height; - F32 hud_y = ((F32)y - center_y) / height; + // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5 + F32 hud_x = -((F32)x - center_x) / height; + F32 hud_y = ((F32)y - center_y) / height; - return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom); + return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom); } // Returns unit vector relative to camera in camera space // indicating direction of point on screen x,y LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const { - // find vertical field of view - F32 fov_height = LLViewerCamera::getInstance()->getView(); - F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect(); + // find vertical field of view + F32 fov_height = LLViewerCamera::getInstance()->getView(); + F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect(); - // find screen resolution - S32 height = getWorldViewHeightScaled(); - S32 width = getWorldViewWidthScaled(); + // find screen resolution + S32 height = getWorldViewHeightScaled(); + S32 width = getWorldViewWidthScaled(); - // find world view center - F32 center_x = getWorldViewRectScaled().getCenterX(); - F32 center_y = getWorldViewRectScaled().getCenterY(); + // find world view center + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); - // calculate click point relative to middle of screen - F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f; - F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height; + // calculate click point relative to middle of screen + F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f; + F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height; - // compute mouse vector - LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f); - LLQuaternion mouse_rotate; - mouse_rotate.setQuat(click_y, click_x, 0.f); + // compute mouse vector + LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f); + LLQuaternion mouse_rotate; + mouse_rotate.setQuat(click_y, click_x, 0.f); - mouse_vector = mouse_vector * mouse_rotate; - // project to z = -1 plane; - mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]); + mouse_vector = mouse_vector * mouse_rotate; + // project to z = -1 plane; + mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]); - return mouse_vector; + return mouse_vector; } -BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, - const LLVector3d &plane_point_global, - const LLVector3 &plane_normal_global) +BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, + const LLVector3d &plane_point_global, + const LLVector3 &plane_normal_global) { - LLVector3d mouse_direction_global_d; + LLVector3d mouse_direction_global_d; + + mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y)); + LLVector3d plane_normal_global_d; + plane_normal_global_d.setVec(plane_normal_global); + F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d); + LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal(); + F64 mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel) + / plane_mouse_dot; + if (llabs(plane_mouse_dot) < 0.00001) + { + // if mouse is parallel to plane, return closest point on line through plane origin + // that is parallel to camera plane by scaling mouse direction vector + // by distance to plane origin, modulated by deviation of mouse direction from plane origin + LLVector3d plane_origin_dir = plane_origin_camera_rel; + plane_origin_dir.normVec(); - mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y)); - LLVector3d plane_normal_global_d; - plane_normal_global_d.setVec(plane_normal_global); - F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d); - LLVector3d plane_origin_camera_rel = plane_point_global - gAgentCamera.getCameraPositionGlobal(); - F64 mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel) - / plane_mouse_dot; - if (llabs(plane_mouse_dot) < 0.00001) - { - // if mouse is parallel to plane, return closest point on line through plane origin - // that is parallel to camera plane by scaling mouse direction vector - // by distance to plane origin, modulated by deviation of mouse direction from plane origin - LLVector3d plane_origin_dir = plane_origin_camera_rel; - plane_origin_dir.normVec(); - - mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d); - } + mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d); + } - point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d; + point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d; - return mouse_look_at_scale > 0.0; + return mouse_look_at_scale > 0.0; } // Returns global position BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global, BOOL ignore_distance) { - LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); - F32 mouse_dir_scale; - BOOL hit_land = FALSE; - LLViewerRegion *regionp; - F32 land_z; - const F32 FIRST_PASS_STEP = 1.0f; // meters - const F32 SECOND_PASS_STEP = 0.1f; // meters - const F32 draw_distance = ignore_distance ? MAX_FAR_CLIP : gAgentCamera.mDrawDistance; - LLVector3d camera_pos_global; - - camera_pos_global = gAgentCamera.getCameraPositionGlobal(); - LLVector3d probe_point_global; - LLVector3 probe_point_region; - - // walk forwards to find the point - for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < draw_distance; mouse_dir_scale += FIRST_PASS_STEP) - { - LLVector3d mouse_direction_global_d; - mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale); - probe_point_global = camera_pos_global + mouse_direction_global_d; - - regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global); - - if (!regionp) - { - // ...we're outside the world somehow - continue; - } - - S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid()); - S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid()); - S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge; - if ((i >= grids_per_edge) || (j >= grids_per_edge)) - { - //LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; - continue; - } - - land_z = regionp->getLand().resolveHeightRegion(probe_point_region); - - //LL_INFOS() << "mousePointOnLand initial z " << land_z << LL_ENDL; - - if (probe_point_region.mV[VZ] < land_z) - { - // ...just went under land - - // cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl; - - hit_land = TRUE; - break; - } - } - - - if (hit_land) - { - // Don't go more than one step beyond where we stopped above. - // This can't just be "mouse_vec_scale" because floating point error - // will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X - F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP; - - // take a step backwards, then walk forwards again to refine position - for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP) - { - LLVector3d mouse_direction_global_d; - mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale); - probe_point_global = camera_pos_global + mouse_direction_global_d; - - regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global); - - if (!regionp) - { - // ...we're outside the world somehow - continue; - } - - /* - i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid()); - j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid()); - if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge)) - { - // LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; - continue; - } - land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ]; - */ - - land_z = regionp->getLand().resolveHeightRegion(probe_point_region); - - //LL_INFOS() << "mousePointOnLand refine z " << land_z << LL_ENDL; - - if (probe_point_region.mV[VZ] < land_z) - { - // ...just went under land again - - *land_position_global = probe_point_global; - return TRUE; - } - } - } - - return FALSE; + LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); + F32 mouse_dir_scale; + BOOL hit_land = FALSE; + LLViewerRegion *regionp; + F32 land_z; + const F32 FIRST_PASS_STEP = 1.0f; // meters + const F32 SECOND_PASS_STEP = 0.1f; // meters + const F32 draw_distance = ignore_distance ? MAX_FAR_CLIP : gAgentCamera.mDrawDistance; + LLVector3d camera_pos_global; + + camera_pos_global = gAgentCamera.getCameraPositionGlobal(); + LLVector3d probe_point_global; + LLVector3 probe_point_region; + + // walk forwards to find the point + for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < draw_distance; mouse_dir_scale += FIRST_PASS_STEP) + { + LLVector3d mouse_direction_global_d; + mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale); + probe_point_global = camera_pos_global + mouse_direction_global_d; + + regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global); + + if (!regionp) + { + // ...we're outside the world somehow + continue; + } + + S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid()); + S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid()); + S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge; + if ((i >= grids_per_edge) || (j >= grids_per_edge)) + { + //LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; + continue; + } + + land_z = regionp->getLand().resolveHeightRegion(probe_point_region); + + //LL_INFOS() << "mousePointOnLand initial z " << land_z << LL_ENDL; + + if (probe_point_region.mV[VZ] < land_z) + { + // ...just went under land + + // cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl; + + hit_land = TRUE; + break; + } + } + + + if (hit_land) + { + // Don't go more than one step beyond where we stopped above. + // This can't just be "mouse_vec_scale" because floating point error + // will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X + F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP; + + // take a step backwards, then walk forwards again to refine position + for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP) + { + LLVector3d mouse_direction_global_d; + mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale); + probe_point_global = camera_pos_global + mouse_direction_global_d; + + regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global); + + if (!regionp) + { + // ...we're outside the world somehow + continue; + } + + /* + i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid()); + j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid()); + if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge)) + { + // LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; + continue; + } + land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ]; + */ + + land_z = regionp->getLand().resolveHeightRegion(probe_point_region); + + //LL_INFOS() << "mousePointOnLand refine z " << land_z << LL_ENDL; + + if (probe_point_region.mV[VZ] < land_z) + { + // ...just went under land again + + *land_position_global = probe_point_global; + return TRUE; + } + } + } + + return FALSE; } // Saves an image to the harddrive as "SnapshotX" where X >= 1. void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - if (!image) - { - LL_WARNS() << "No image to save" << LL_ENDL; - return; - } - std::string extension("." + image->getExtension()); - LLImageFormatted* formatted_image = image; - // Get a base file location if needed. - if (force_picker || !isSnapshotLocSet()) - { - std::string proposed_name(sSnapshotBaseName); - - // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. - LLFilePicker::ESaveFilter pick_type; - - if (extension == ".j2c") - pick_type = LLFilePicker::FFSAVE_J2C; - else if (extension == ".bmp") - pick_type = LLFilePicker::FFSAVE_BMP; - else if (extension == ".jpg") - pick_type = LLFilePicker::FFSAVE_JPEG; - else if (extension == ".png") - pick_type = LLFilePicker::FFSAVE_PNG; - else if (extension == ".tga") - pick_type = LLFilePicker::FFSAVE_TGA; - else - pick_type = LLFilePicker::FFSAVE_ALL; - - LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, - boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)); - } - else - { - saveImageLocal(formatted_image, success_cb, failure_cb); - } + if (!image) + { + LL_WARNS() << "No image to save" << LL_ENDL; + return; + } + std::string extension("." + image->getExtension()); + LLImageFormatted* formatted_image = image; + // Get a base file location if needed. + if (force_picker || !isSnapshotLocSet()) + { + std::string proposed_name(sSnapshotBaseName); + + // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. + LLFilePicker::ESaveFilter pick_type; + + if (extension == ".j2c") + pick_type = LLFilePicker::FFSAVE_J2C; + else if (extension == ".bmp") + pick_type = LLFilePicker::FFSAVE_BMP; + else if (extension == ".jpg") + pick_type = LLFilePicker::FFSAVE_JPEG; + else if (extension == ".png") + pick_type = LLFilePicker::FFSAVE_PNG; + else if (extension == ".tga") + pick_type = LLFilePicker::FFSAVE_TGA; + else + pick_type = LLFilePicker::FFSAVE_ALL; + + LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, + boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)); + } + else + { + saveImageLocal(formatted_image, success_cb, failure_cb); + } } void LLViewerWindow::onDirectorySelected(const std::vector& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - // Copy the directory + file name - std::string filepath = filenames[0]; + // Copy the directory + file name + std::string filepath = filenames[0]; - gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); - gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); - saveImageLocal(image, success_cb, failure_cb); + gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); + gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); + saveImageLocal(image, success_cb, failure_cb); } void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb) { - failure_cb(); + failure_cb(); } void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); - if (lastSnapshotDir.empty()) - { - failure_cb(); - return; - } + std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); + if (lastSnapshotDir.empty()) + { + failure_cb(); + return; + } // Check if there is enough free space to save snapshot #ifdef LL_WINDOWS - boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); + boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); #else - boost::filesystem::path b_path(lastSnapshotDir); + boost::filesystem::path b_path(lastSnapshotDir); #endif - if (!boost::filesystem::is_directory(b_path)) - { - LLSD args; - args["PATH"] = lastSnapshotDir; - LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args); - resetSnapshotLoc(); - failure_cb(); - return; - } - boost::filesystem::space_info b_space = boost::filesystem::space(b_path); - if (b_space.free < image->getDataSize()) - { - LLSD args; - args["PATH"] = lastSnapshotDir; - - std::string needM_bytes_string; - LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->getDataSize()) >> 10); - args["NEED_MEMORY"] = needM_bytes_string; - - std::string freeM_bytes_string; - LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); - args["FREE_MEMORY"] = freeM_bytes_string; - - LLNotificationsUtil::add("SnapshotToComputerFailed", args); - - failure_cb(); - } - - // Look for an unused file name - BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); - std::string filepath; - S32 i = 1; - S32 err = 0; - std::string extension("." + image->getExtension()); - do - { - filepath = sSnapshotDir; - filepath += gDirUtilp->getDirDelimiter(); - filepath += sSnapshotBaseName; - - if (is_snapshot_name_loc_set) - { - filepath += llformat("_%.3d",i); - } - - filepath += extension; - - llstat stat_info; - err = LLFile::stat( filepath, &stat_info ); - i++; - } - while( -1 != err // Search until the file is not found (i.e., stat() gives an error). - && is_snapshot_name_loc_set); // Or stop if we are rewriting. - - LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; - if (image->save(filepath)) - { - playSnapshotAnimAndSound(); - success_cb(); - } - else - { - failure_cb(); - } + if (!boost::filesystem::is_directory(b_path)) + { + LLSD args; + args["PATH"] = lastSnapshotDir; + LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args); + resetSnapshotLoc(); + failure_cb(); + return; + } + boost::filesystem::space_info b_space = boost::filesystem::space(b_path); + if (b_space.free < image->getDataSize()) + { + LLSD args; + args["PATH"] = lastSnapshotDir; + + std::string needM_bytes_string; + LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->getDataSize()) >> 10); + args["NEED_MEMORY"] = needM_bytes_string; + + std::string freeM_bytes_string; + LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); + args["FREE_MEMORY"] = freeM_bytes_string; + + LLNotificationsUtil::add("SnapshotToComputerFailed", args); + + failure_cb(); + } + + // Look for an unused file name + BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); + std::string filepath; + S32 i = 1; + S32 err = 0; + std::string extension("." + image->getExtension()); + do + { + filepath = sSnapshotDir; + filepath += gDirUtilp->getDirDelimiter(); + filepath += sSnapshotBaseName; + + if (is_snapshot_name_loc_set) + { + filepath += llformat("_%.3d",i); + } + + filepath += extension; + + llstat stat_info; + err = LLFile::stat( filepath, &stat_info ); + i++; + } + while( -1 != err // Search until the file is not found (i.e., stat() gives an error). + && is_snapshot_name_loc_set); // Or stop if we are rewriting. + + LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; + if (image->save(filepath)) + { + playSnapshotAnimAndSound(); + success_cb(); + } + else + { + failure_cb(); + } } void LLViewerWindow::resetSnapshotLoc() { - gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); } // static void LLViewerWindow::movieSize(S32 new_width, S32 new_height) { - LLCoordWindow size; - LLCoordWindow new_size(new_width, new_height); - gViewerWindow->getWindow()->getSize(&size); - if ( size != new_size ) - { - gViewerWindow->getWindow()->setSize(new_size); - } + LLCoordWindow size; + LLCoordWindow new_size(new_width, new_height); + gViewerWindow->getWindow()->getSize(&size); + if ( size != new_size ) + { + gViewerWindow->getWindow()->setSize(new_size); + } } BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format) @@ -4867,347 +4867,347 @@ BOOL LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, void LLViewerWindow::playSnapshotAnimAndSound() { - if (gSavedSettings.getBOOL("QuietSnapshotsToDisk")) - { - return; - } - gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START); - send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f); + if (gSavedSettings.getBOOL("QuietSnapshotsToDisk")) + { + return; + } + gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START); + send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f); +} + +BOOL LLViewerWindow::isSnapshotLocSet() const +{ + std::string snapshot_dir = sSnapshotDir; + return !snapshot_dir.empty(); +} + +void LLViewerWindow::resetSnapshotLoc() const +{ + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); +} + +BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type) +{ + return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, show_hud, do_rebuild, no_post, type); } -BOOL LLViewerWindow::isSnapshotLocSet() const -{ - std::string snapshot_dir = sSnapshotDir; - return !snapshot_dir.empty(); -} +// Saves the image from the screen to a raw image +// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy +// the results over to the final raw image. +BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, + BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) +{ + if (!raw) + { + return FALSE; + } + //check if there is enough memory for the snapshot image + if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K + { + if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) + { + LL_WARNS() << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << LL_ENDL ; + return FALSE ; //there is no enough memory for taking this snapshot. + } + } + + // PRE SNAPSHOT + gSnapshotNoPost = no_post; + gDisplaySwapBuffers = FALSE; + + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); + setCursor(UI_CURSOR_WAIT); + + // Hide all the UI widgets first and draw a frame + BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE; + + if ( prev_draw_ui != show_ui) + { + LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + BOOL hide_hud = !show_hud && LLPipeline::sShowHUDAttachments; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = FALSE; + } + + // if not showing ui, use full window to render world view + updateWorldViewRect(!show_ui); + + // Copy screen to a buffer + // crop sides or top and bottom, if taking a snapshot of different aspect ratio + // from window + LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); + + S32 snapshot_width = window_rect.getWidth(); + S32 snapshot_height = window_rect.getHeight(); + // SNAPSHOT + S32 window_width = snapshot_width; + S32 window_height = snapshot_height; + + // Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested + if (show_ui) + { + // If the user wants the UI, limit the output size to the available screen size + image_width = llmin(image_width, window_width); + image_height = llmin(image_height, window_height); + } + + S32 original_width = 0; + S32 original_height = 0; + bool reset_deferred = false; + + LLRenderTarget scratch_space; + + F32 scale_factor = 1.0f ; + if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) + { + if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) && + (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) + { + U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA; + if (scratch_space.allocate(image_width, image_height, color_fmt, true)) + { + original_width = gPipeline.mRT->deferredScreen.getWidth(); + original_height = gPipeline.mRT->deferredScreen.getHeight(); + + if (gPipeline.allocateScreenBuffer(image_width, image_height)) + { + window_width = image_width; + window_height = image_height; + snapshot_width = image_width; + snapshot_height = image_height; + reset_deferred = true; + mWorldViewRectRaw.set(0, image_height, image_width, 0); + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + scratch_space.bindTarget(); + } + else + { + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + } + } + } + + if (!reset_deferred) + { + // if image cropping or need to enlarge the scene, compute a scale_factor + F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; + snapshot_width = (S32)(ratio * image_width) ; + snapshot_height = (S32)(ratio * image_height) ; + scale_factor = llmax(1.0f, 1.0f / ratio) ; + } + } + + if (show_ui && scale_factor > 1.f) + { + // Note: we should never get there... + LL_WARNS() << "over scaling UI not supported." << LL_ENDL; + } + + S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); + S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); + + S32 image_buffer_x = llfloor(snapshot_width * scale_factor) ; + S32 image_buffer_y = llfloor(snapshot_height * scale_factor) ; + + if ((image_buffer_x > max_size) || (image_buffer_y > max_size)) // boundary check to avoid memory overflow + { + scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ; + image_buffer_x = llfloor(snapshot_width * scale_factor) ; + image_buffer_y = llfloor(snapshot_height * scale_factor) ; + } + if ((image_buffer_x > 0) && (image_buffer_y > 0)) + { + raw->resize(image_buffer_x, image_buffer_y, 3); + } + else + { + return FALSE ; + } + if (raw->isBufferInvalid()) + { + return FALSE ; + } + + BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher + if (high_res && show_ui) + { + // Note: we should never get there... + LL_WARNS() << "High res UI snapshot not supported. " << LL_ENDL; + /*send_agent_pause(); + //rescale fonts + initFonts(scale_factor); + LLHUDObject::reshapeAll();*/ + } + + S32 output_buffer_offset_y = 0; + + 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()); + + // 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) + { + S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; + // handle fractional columns + U32 read_height = llmax(0, (window_height - subimage_y_offset) - + llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight()))); + + S32 output_buffer_offset_x = 0; + for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x) + { + gDisplaySwapBuffers = FALSE; + gDepthDirty = TRUE; + + S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); + // handle fractional rows + U32 read_width = llmax(0, (window_width - subimage_x_offset) - + llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); + + // Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases) + if (read_width && read_height) + { + const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); + display(do_rebuild, scale_factor, subfield, TRUE); + + if (!LLPipeline::sRenderDeferred) + { + // Required for showing the GUI in snapshots and performing bloom composite overlay + // Call even if show_ui is FALSE + render_ui(scale_factor, subfield); + swap(); + } + + for (U32 out_y = 0; out_y < read_height ; out_y++) + { + S32 output_buffer_offset = ( + (out_y * (raw->getWidth())) // ...plus iterated y... + + (window_width * subimage_x) // ...plus subimage start in x... + + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... + - output_buffer_offset_x // ...minus buffer padding x... + - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... + ) * raw->getComponents(); + + // Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) + if (out_y % 100 == 0) + { + LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); + } + // disable use of glReadPixels when doing nVidia nSight graphics debugging + if (!LLRender::sNsightDebugSupport) + { + if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR) + { + glReadPixels( + subimage_x_offset, out_y + subimage_y_offset, + read_width, 1, + GL_RGB, GL_UNSIGNED_BYTE, + raw->getData() + output_buffer_offset + ); + } + else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH + { + LLPointer depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values + glReadPixels( + subimage_x_offset, out_y + subimage_y_offset, + read_width, 1, + GL_DEPTH_COMPONENT, GL_FLOAT, + depth_line_buffer->getData()// current output pixel is beginning of buffer... + ); + + for (S32 i = 0; i < (S32)read_width; i++) + { + F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); + + F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); + U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); + // write converted scanline out to result image + for (S32 j = 0; j < raw->getComponents(); j++) + { + *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; + } + } + } + } + } + } + output_buffer_offset_x += subimage_x_offset; + stop_glerror(); + } + output_buffer_offset_y += subimage_y_offset; + } + + gDisplaySwapBuffers = FALSE; + gSnapshotNoPost = FALSE; + gDepthDirty = TRUE; + + // POST SNAPSHOT + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } + + /*if (high_res) + { + initFonts(1.f); + LLHUDObject::reshapeAll(); + }*/ + + // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) + // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. + image_width += (image_width * 3) % 4; + + BOOL ret = TRUE ; + // Resize image + if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4) + { + ret = raw->scale( image_width, image_height ); + } + else if(image_width != image_buffer_x || image_height != image_buffer_y) + { + ret = raw->scale( image_width, image_height, FALSE ); + } + -void LLViewerWindow::resetSnapshotLoc() const -{ - gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); -} + setCursor(UI_CURSOR_ARROW); -BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type) -{ - return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, show_hud, do_rebuild, no_post, type); -} + if (do_rebuild) + { + // If we had to do a rebuild, that means that the lists of drawables to be rendered + // was empty before we started. + // Need to reset these, otherwise we call state sort on it again when render gets called the next time + // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of + // objects on them. + gPipeline.resetDrawOrders(); + } -// Saves the image from the screen to a raw image -// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy -// the results over to the final raw image. -BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, - BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) -{ - if (!raw) - { - return FALSE; - } - //check if there is enough memory for the snapshot image - if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K - { - if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) - { - LL_WARNS() << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << LL_ENDL ; - return FALSE ; //there is no enough memory for taking this snapshot. - } - } - - // PRE SNAPSHOT - gSnapshotNoPost = no_post; - gDisplaySwapBuffers = FALSE; - - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); - setCursor(UI_CURSOR_WAIT); + if (reset_deferred) + { + mWorldViewRectRaw = window_rect; + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + scratch_space.flush(); + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); - // Hide all the UI widgets first and draw a frame - BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE; + } - if ( prev_draw_ui != show_ui) - { - LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } + if (high_res) + { + send_agent_resume(); + } - BOOL hide_hud = !show_hud && LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } - - // if not showing ui, use full window to render world view - updateWorldViewRect(!show_ui); - - // Copy screen to a buffer - // crop sides or top and bottom, if taking a snapshot of different aspect ratio - // from window - LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); - - S32 snapshot_width = window_rect.getWidth(); - S32 snapshot_height = window_rect.getHeight(); - // SNAPSHOT - S32 window_width = snapshot_width; - S32 window_height = snapshot_height; - - // Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested - if (show_ui) - { - // If the user wants the UI, limit the output size to the available screen size - image_width = llmin(image_width, window_width); - image_height = llmin(image_height, window_height); - } - - S32 original_width = 0; - S32 original_height = 0; - bool reset_deferred = false; - - LLRenderTarget scratch_space; - - F32 scale_factor = 1.0f ; - if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) - { - if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) && - (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) - { - U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA; - if (scratch_space.allocate(image_width, image_height, color_fmt, true)) - { - original_width = gPipeline.mRT->deferredScreen.getWidth(); - original_height = gPipeline.mRT->deferredScreen.getHeight(); - - if (gPipeline.allocateScreenBuffer(image_width, image_height)) - { - window_width = image_width; - window_height = image_height; - snapshot_width = image_width; - snapshot_height = image_height; - reset_deferred = true; - mWorldViewRectRaw.set(0, image_height, image_width, 0); - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); - scratch_space.bindTarget(); - } - else - { - scratch_space.release(); - gPipeline.allocateScreenBuffer(original_width, original_height); - } - } - } - - if (!reset_deferred) - { - // if image cropping or need to enlarge the scene, compute a scale_factor - F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; - snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; - } - } - - if (show_ui && scale_factor > 1.f) - { - // Note: we should never get there... - LL_WARNS() << "over scaling UI not supported." << LL_ENDL; - } - - S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f); - S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f); - - S32 image_buffer_x = llfloor(snapshot_width * scale_factor) ; - S32 image_buffer_y = llfloor(snapshot_height * scale_factor) ; - - if ((image_buffer_x > max_size) || (image_buffer_y > max_size)) // boundary check to avoid memory overflow - { - scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ; - image_buffer_x = llfloor(snapshot_width * scale_factor) ; - image_buffer_y = llfloor(snapshot_height * scale_factor) ; - } - if ((image_buffer_x > 0) && (image_buffer_y > 0)) - { - raw->resize(image_buffer_x, image_buffer_y, 3); - } - else - { - return FALSE ; - } - if (raw->isBufferInvalid()) - { - return FALSE ; - } - - BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher - if (high_res && show_ui) - { - // Note: we should never get there... - LL_WARNS() << "High res UI snapshot not supported. " << LL_ENDL; - /*send_agent_pause(); - //rescale fonts - initFonts(scale_factor); - LLHUDObject::reshapeAll();*/ - } - - S32 output_buffer_offset_y = 0; - - 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()); - - // 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) - { - S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);; - // handle fractional columns - U32 read_height = llmax(0, (window_height - subimage_y_offset) - - llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight()))); - - S32 output_buffer_offset_x = 0; - for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x) - { - gDisplaySwapBuffers = FALSE; - gDepthDirty = TRUE; - - S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width); - // handle fractional rows - U32 read_width = llmax(0, (window_width - subimage_x_offset) - - llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth()))); - - // Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases) - if (read_width && read_height) - { - const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); - display(do_rebuild, scale_factor, subfield, TRUE); - - if (!LLPipeline::sRenderDeferred) - { - // Required for showing the GUI in snapshots and performing bloom composite overlay - // Call even if show_ui is FALSE - render_ui(scale_factor, subfield); - swap(); - } - - for (U32 out_y = 0; out_y < read_height ; out_y++) - { - S32 output_buffer_offset = ( - (out_y * (raw->getWidth())) // ...plus iterated y... - + (window_width * subimage_x) // ...plus subimage start in x... - + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y... - - output_buffer_offset_x // ...minus buffer padding x... - - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y... - ) * raw->getComponents(); - - // Ping the watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) - if (out_y % 100 == 0) - { - LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); - } - // disable use of glReadPixels when doing nVidia nSight graphics debugging - if (!LLRender::sNsightDebugSupport) - { - if (type == LLSnapshotModel::SNAPSHOT_TYPE_COLOR) - { - glReadPixels( - subimage_x_offset, out_y + subimage_y_offset, - read_width, 1, - GL_RGB, GL_UNSIGNED_BYTE, - raw->getData() + output_buffer_offset - ); - } - else // LLSnapshotModel::SNAPSHOT_TYPE_DEPTH - { - LLPointer depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values - glReadPixels( - subimage_x_offset, out_y + subimage_y_offset, - read_width, 1, - GL_DEPTH_COMPONENT, GL_FLOAT, - depth_line_buffer->getData()// current output pixel is beginning of buffer... - ); - - for (S32 i = 0; i < (S32)read_width; i++) - { - F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32))); - - F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2)); - U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar()); - // write converted scanline out to result image - for (S32 j = 0; j < raw->getComponents(); j++) - { - *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte; - } - } - } - } - } - } - output_buffer_offset_x += subimage_x_offset; - stop_glerror(); - } - output_buffer_offset_y += subimage_y_offset; - } - - gDisplaySwapBuffers = FALSE; - gSnapshotNoPost = FALSE; - gDepthDirty = TRUE; - - // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } - - /*if (high_res) - { - initFonts(1.f); - LLHUDObject::reshapeAll(); - }*/ - - // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding) - // Note: this formula depends on the number of components being 3. Not obvious, but it's correct. - image_width += (image_width * 3) % 4; - - BOOL ret = TRUE ; - // Resize image - if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4) - { - ret = raw->scale( image_width, image_height ); - } - else if(image_width != image_buffer_x || image_height != image_buffer_y) - { - ret = raw->scale( image_width, image_height, FALSE ); - } - - - setCursor(UI_CURSOR_ARROW); - - if (do_rebuild) - { - // If we had to do a rebuild, that means that the lists of drawables to be rendered - // was empty before we started. - // Need to reset these, otherwise we call state sort on it again when render gets called the next time - // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of - // objects on them. - gPipeline.resetDrawOrders(); - } - - if (reset_deferred) - { - mWorldViewRectRaw = window_rect; - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); - scratch_space.flush(); - scratch_space.release(); - gPipeline.allocateScreenBuffer(original_width, original_height); - - } - - if (high_res) - { - send_agent_resume(); - } - - return ret; + return ret; } BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes) @@ -5225,10 +5225,10 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } BOOL hide_hud = LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = FALSE; + } LLRect window_rect = getWorldViewRectRaw(); @@ -5253,8 +5253,8 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } // we render the scene more than once since this helps - // greatly with the objects not being drawn in the - // snapshot when they are drawn in the scene. This is + // greatly with the objects not being drawn in the + // snapshot when they are drawn in the scene. This is // evident when you set this value via the debug setting // called 360CaptureNumRenderPasses to 1. The theory is // that the missing objects are caused by the sUseOcclusion @@ -5299,10 +5299,10 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } } - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } setCursor(UI_CURSOR_ARROW); @@ -5324,7 +5324,7 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea LL_PROFILE_GPU_ZONE("cubeSnapshot"); llassert(LLPipeline::sRenderDeferred); llassert(!gCubeSnapshot); //assert a snapshot isn't already in progress - + U32 res = gPipeline.mRT->deferredScreen.getWidth(); //llassert(res <= gPipeline.mRT->deferredScreen.getWidth()); @@ -5336,7 +5336,7 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea // set new parameters specific to the 360 requirements LLPipeline::sUseOcclusion = 0; LLViewerCamera* camera = LLViewerCamera::getInstance(); - + LLViewerCamera saved_camera = LLViewerCamera::instance(); glh::matrix4f saved_proj = get_current_projection(); glh::matrix4f saved_mod = get_current_modelview(); @@ -5348,16 +5348,16 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea camera->setOrigin(origin); camera->setNear(near_clip); - LLPlane previousClipPlane; + LLPlane previousClipPlane; - if (useCustomClipPlane) - { + if (useCustomClipPlane) + { previousClipPlane = camera->getUserClipPlane(); camera->setUserClipPlane(clipPlane); - } + } glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); - + U32 dynamic_render_types[] = { LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, @@ -5366,7 +5366,7 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea 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) @@ -5384,12 +5384,12 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea { LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); } - + BOOL hide_hud = LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = FALSE; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = FALSE; + } LLRect window_rect = getWorldViewRectRaw(); mWorldViewRectRaw.set(0, res, res, 0); @@ -5455,19 +5455,19 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea } } - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = TRUE; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = TRUE; + } gPipeline.resetDrawOrders(); mWorldViewRectRaw = window_rect; - if (useCustomClipPlane) - { + if (useCustomClipPlane) + { camera->setUserClipPlane(previousClipPlane); - } - + } + // restore original view/camera/avatar settings settings *camera = saved_camera; set_current_modelview(saved_mod); @@ -5481,138 +5481,138 @@ BOOL LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea void LLViewerWindow::destroyWindow() { - if (mWindow) - { - LLWindowManager::destroyWindow(mWindow); - } - mWindow = NULL; + if (mWindow) + { + LLWindowManager::destroyWindow(mWindow); + } + mWindow = NULL; } void LLViewerWindow::drawMouselookInstructions() { - // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.) - const std::string instructions = LLTrans::getString("LeaveMouselook"); - const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD)); - - //to be on top of Bottom bar when it is opened - const S32 INSTRUCTIONS_PAD = 50; + // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.) + const std::string instructions = LLTrans::getString("LeaveMouselook"); + const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD)); - font->renderUTF8( - instructions, 0, - getWorldViewRectScaled().getCenterX(), - getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD, - LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ), - LLFontGL::HCENTER, LLFontGL::TOP, - LLFontGL::NORMAL,LLFontGL::DROP_SHADOW); + //to be on top of Bottom bar when it is opened + const S32 INSTRUCTIONS_PAD = 50; + + font->renderUTF8( + instructions, 0, + getWorldViewRectScaled().getCenterX(), + getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD, + LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ), + LLFontGL::HCENTER, LLFontGL::TOP, + LLFontGL::NORMAL,LLFontGL::DROP_SHADOW); } void* LLViewerWindow::getPlatformWindow() const { - return mWindow->getPlatformWindow(); + return mWindow->getPlatformWindow(); } -void* LLViewerWindow::getMediaWindow() const +void* LLViewerWindow::getMediaWindow() const { - return mWindow->getMediaWindow(); + return mWindow->getMediaWindow(); } -void LLViewerWindow::focusClient() const +void LLViewerWindow::focusClient() const { - return mWindow->focusClient(); + return mWindow->focusClient(); } -LLRootView* LLViewerWindow::getRootView() const +LLRootView* LLViewerWindow::getRootView() const { - return mRootView; + return mRootView; } LLRect LLViewerWindow::getWorldViewRectScaled() const { - return mWorldViewRectScaled; + return mWorldViewRectScaled; } S32 LLViewerWindow::getWorldViewHeightScaled() const { - return mWorldViewRectScaled.getHeight(); + return mWorldViewRectScaled.getHeight(); } S32 LLViewerWindow::getWorldViewWidthScaled() const { - return mWorldViewRectScaled.getWidth(); + return mWorldViewRectScaled.getWidth(); } S32 LLViewerWindow::getWorldViewHeightRaw() const { - return mWorldViewRectRaw.getHeight(); + return mWorldViewRectRaw.getHeight(); } S32 LLViewerWindow::getWorldViewWidthRaw() const { - return mWorldViewRectRaw.getWidth(); + return mWorldViewRectRaw.getWidth(); } -S32 LLViewerWindow::getWindowHeightScaled() const -{ - return mWindowRectScaled.getHeight(); +S32 LLViewerWindow::getWindowHeightScaled() const +{ + return mWindowRectScaled.getHeight(); } -S32 LLViewerWindow::getWindowWidthScaled() const -{ - return mWindowRectScaled.getWidth(); +S32 LLViewerWindow::getWindowWidthScaled() const +{ + return mWindowRectScaled.getWidth(); } -S32 LLViewerWindow::getWindowHeightRaw() const -{ - return mWindowRectRaw.getHeight(); +S32 LLViewerWindow::getWindowHeightRaw() const +{ + return mWindowRectRaw.getHeight(); } -S32 LLViewerWindow::getWindowWidthRaw() const -{ - return mWindowRectRaw.getWidth(); +S32 LLViewerWindow::getWindowWidthRaw() const +{ + return mWindowRectRaw.getWidth(); } void LLViewerWindow::setup2DRender() { - // setup ortho camera - gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight()); - setup2DViewport(); + // setup ortho camera + gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight()); + setup2DViewport(); } void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset) { - gGLViewport[0] = mWindowRectRaw.mLeft + x_offset; - gGLViewport[1] = mWindowRectRaw.mBottom + y_offset; - gGLViewport[2] = mWindowRectRaw.getWidth(); - gGLViewport[3] = mWindowRectRaw.getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + gGLViewport[0] = mWindowRectRaw.mLeft + x_offset; + gGLViewport[1] = mWindowRectRaw.mBottom + y_offset; + gGLViewport[2] = mWindowRectRaw.getWidth(); + gGLViewport[3] = mWindowRectRaw.getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); } void LLViewerWindow::setup3DRender() { - // setup perspective camera - LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom, mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f); - setup3DViewport(); + // setup perspective camera + LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom, mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f); + setup3DViewport(); } void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI - gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset; - gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset; - gGLViewport[2] = mWorldViewRectRaw.getWidth(); - gGLViewport[3] = mWorldViewRectRaw.getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset; + gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset; + gGLViewport[2] = mWorldViewRectRaw.getWidth(); + gGLViewport[3] = mWorldViewRectRaw.getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); } void LLViewerWindow::revealIntroPanel() { - if (mProgressView) - { - mProgressView->revealIntroPanel(); - } + if (mProgressView) + { + mProgressView->revealIntroPanel(); + } } void LLViewerWindow::initTextures(S32 location_id) @@ -5625,417 +5625,417 @@ void LLViewerWindow::initTextures(S32 location_id) void LLViewerWindow::setShowProgress(const BOOL show) { - if (mProgressView) - { - mProgressView->setVisible(show); - } + if (mProgressView) + { + mProgressView->setVisible(show); + } } void LLViewerWindow::setStartupComplete() { - if (mProgressView) - { - mProgressView->setStartupComplete(); - } + if (mProgressView) + { + mProgressView->setStartupComplete(); + } } BOOL LLViewerWindow::getShowProgress() const { - return (mProgressView && mProgressView->getVisible()); + return (mProgressView && mProgressView->getVisible()); } void LLViewerWindow::setProgressString(const std::string& string) { - if (mProgressView) - { - mProgressView->setText(string); - } + if (mProgressView) + { + mProgressView->setText(string); + } } void LLViewerWindow::setProgressMessage(const std::string& msg) { - if(mProgressView) - { - mProgressView->setMessage(msg); - } + if(mProgressView) + { + mProgressView->setMessage(msg); + } } void LLViewerWindow::setProgressPercent(const F32 percent) { - if (mProgressView) - { - mProgressView->setPercent(percent); - } + if (mProgressView) + { + mProgressView->setPercent(percent); + } } void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label ) { - if (mProgressView) - { - mProgressView->setCancelButtonVisible( b, label ); - } + if (mProgressView) + { + mProgressView->setCancelButtonVisible( b, label ); + } } LLProgressView *LLViewerWindow::getProgressView() const { - return mProgressView; + return mProgressView; } void LLViewerWindow::dumpState() { - LL_INFOS() << "LLViewerWindow Active " << S32(mActive) << LL_ENDL; - LL_INFOS() << "mWindow visible " << S32(mWindow->getVisible()) - << " minimized " << S32(mWindow->getMinimized()) - << LL_ENDL; + LL_INFOS() << "LLViewerWindow Active " << S32(mActive) << LL_ENDL; + LL_INFOS() << "mWindow visible " << S32(mWindow->getVisible()) + << " minimized " << S32(mWindow->getMinimized()) + << LL_ENDL; } void LLViewerWindow::stopGL(BOOL save_state) { - //Note: --bao - //if not necessary, do not change the order of the function calls in this function. - //if change something, make sure it will not break anything. - //especially be careful to put anything behind gTextureList.destroyGL(save_state); - if (!gGLManager.mIsDisabled) - { - LL_INFOS() << "Shutting down GL..." << LL_ENDL; - - // Pause texture decode threads (will get unpaused during main loop) - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getTextureFetch()->pause(); - - gSky.destroyGL(); - stop_glerror(); - - LLManipTranslate::destroyGL() ; - stop_glerror(); - - gBumpImageList.destroyGL(); - stop_glerror(); - - LLFontGL::destroyAllGL(); - stop_glerror(); - - LLVOAvatar::destroyGL(); - stop_glerror(); - - LLVOPartGroup::destroyGL(); - - LLViewerDynamicTexture::destroyGL(); - stop_glerror(); - - if (gPipeline.isInit()) - { - gPipeline.destroyGL(); - } - - gBox.cleanupGL(); - - if(gPostProcess) - { - gPostProcess->invalidate(); - } - - gTextureList.destroyGL(save_state); - stop_glerror(); - - gGLManager.mIsDisabled = TRUE; - stop_glerror(); - - //unload shader's - while (LLGLSLShader::sInstances.size()) - { - LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); - shader->unload(); - } - } + //Note: --bao + //if not necessary, do not change the order of the function calls in this function. + //if change something, make sure it will not break anything. + //especially be careful to put anything behind gTextureList.destroyGL(save_state); + if (!gGLManager.mIsDisabled) + { + LL_INFOS() << "Shutting down GL..." << LL_ENDL; + + // Pause texture decode threads (will get unpaused during main loop) + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getTextureFetch()->pause(); + + gSky.destroyGL(); + stop_glerror(); + + LLManipTranslate::destroyGL() ; + stop_glerror(); + + gBumpImageList.destroyGL(); + stop_glerror(); + + LLFontGL::destroyAllGL(); + stop_glerror(); + + LLVOAvatar::destroyGL(); + stop_glerror(); + + LLVOPartGroup::destroyGL(); + + LLViewerDynamicTexture::destroyGL(); + stop_glerror(); + + if (gPipeline.isInit()) + { + gPipeline.destroyGL(); + } + + gBox.cleanupGL(); + + if(gPostProcess) + { + gPostProcess->invalidate(); + } + + gTextureList.destroyGL(save_state); + stop_glerror(); + + gGLManager.mIsDisabled = TRUE; + stop_glerror(); + + //unload shader's + while (LLGLSLShader::sInstances.size()) + { + LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); + shader->unload(); + } + } } void LLViewerWindow::restoreGL(const std::string& progress_message) { - //Note: --bao - //if not necessary, do not change the order of the function calls in this function. - //if change something, make sure it will not break anything. - //especially, be careful to put something before gTextureList.restoreGL(); - if (gGLManager.mIsDisabled) - { - LL_INFOS() << "Restoring GL..." << LL_ENDL; - gGLManager.mIsDisabled = FALSE; - - initGLDefaults(); - LLGLState::restoreGL(); - - gTextureList.restoreGL(); - - // for future support of non-square pixels, and fonts that are properly stretched - //LLFontGL::destroyDefaultFonts(); - initFonts(); - - gSky.restoreGL(); - gPipeline.restoreGL(); - LLManipTranslate::restoreGL(); - - gBumpImageList.restoreGL(); - LLViewerDynamicTexture::restoreGL(); - LLVOAvatar::restoreGL(); - LLVOPartGroup::restoreGL(); - - gResizeScreenTexture = TRUE; - gWindowResized = TRUE; - - if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) - { - LLVisualParamHint::requestHintUpdates(); - } - - if (!progress_message.empty()) - { - gRestoreGLTimer.reset(); - gRestoreGL = TRUE; - setShowProgress(TRUE); - setProgressString(progress_message); - } - LL_INFOS() << "...Restoring GL done" << LL_ENDL; - if(!LLAppViewer::instance()->restoreErrorTrap()) - { - LL_WARNS() << " Someone took over my signal/exception handler (post restoreGL)!" << LL_ENDL; - } - - } + //Note: --bao + //if not necessary, do not change the order of the function calls in this function. + //if change something, make sure it will not break anything. + //especially, be careful to put something before gTextureList.restoreGL(); + if (gGLManager.mIsDisabled) + { + LL_INFOS() << "Restoring GL..." << LL_ENDL; + gGLManager.mIsDisabled = FALSE; + + initGLDefaults(); + LLGLState::restoreGL(); + + gTextureList.restoreGL(); + + // for future support of non-square pixels, and fonts that are properly stretched + //LLFontGL::destroyDefaultFonts(); + initFonts(); + + gSky.restoreGL(); + gPipeline.restoreGL(); + LLManipTranslate::restoreGL(); + + gBumpImageList.restoreGL(); + LLViewerDynamicTexture::restoreGL(); + LLVOAvatar::restoreGL(); + LLVOPartGroup::restoreGL(); + + gResizeScreenTexture = TRUE; + gWindowResized = TRUE; + + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) + { + LLVisualParamHint::requestHintUpdates(); + } + + if (!progress_message.empty()) + { + gRestoreGLTimer.reset(); + gRestoreGL = TRUE; + setShowProgress(TRUE); + setProgressString(progress_message); + } + LL_INFOS() << "...Restoring GL done" << LL_ENDL; + if(!LLAppViewer::instance()->restoreErrorTrap()) + { + LL_WARNS() << " Someone took over my signal/exception handler (post restoreGL)!" << LL_ENDL; + } + + } } void LLViewerWindow::initFonts(F32 zoom_factor) { - LLFontGL::destroyAllGL(); - // Initialize with possibly different zoom factor + LLFontGL::destroyAllGL(); + // Initialize with possibly different zoom factor - LLFontManager::initClass(); + LLFontManager::initClass(); - LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), - mDisplayScale.mV[VX] * zoom_factor, - mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir()); + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), + mDisplayScale.mV[VX] * zoom_factor, + mDisplayScale.mV[VY] * zoom_factor, + gDirUtilp->getAppRODataDir()); } void LLViewerWindow::requestResolutionUpdate() { - mResDirty = true; + mResDirty = true; } static LLTrace::BlockTimerStatHandle FTM_WINDOW_CHECK_SETTINGS("Window Settings"); void LLViewerWindow::checkSettings() { - LL_RECORD_BLOCK_TIME(FTM_WINDOW_CHECK_SETTINGS); - if (mStatesDirty) - { - gGL.refreshState(); - LLViewerShaderMgr::instance()->setShaders(); - mStatesDirty = false; - } - - // We want to update the resolution AFTER the states getting refreshed not before. - if (mResDirty) - { - reshape(getWindowWidthRaw(), getWindowHeightRaw()); - mResDirty = false; - } + LL_RECORD_BLOCK_TIME(FTM_WINDOW_CHECK_SETTINGS); + if (mStatesDirty) + { + gGL.refreshState(); + LLViewerShaderMgr::instance()->setShaders(); + mStatesDirty = false; + } + + // We want to update the resolution AFTER the states getting refreshed not before. + if (mResDirty) + { + reshape(getWindowWidthRaw(), getWindowHeightRaw()); + mResDirty = false; + } } void LLViewerWindow::restartDisplay(BOOL show_progress_bar) { - LL_INFOS() << "Restaring GL" << LL_ENDL; - stopGL(); - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - else - { - restoreGL(); - } + LL_INFOS() << "Restaring GL" << LL_ENDL; + stopGL(); + if (show_progress_bar) + { + restoreGL(LLTrans::getString("ProgressChangingResolution")); + } + else + { + restoreGL(); + } } BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar) { - //BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized"); + //BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized"); - //gResizeScreenTexture = TRUE; + //gResizeScreenTexture = TRUE; - //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); - //U32 old_fsaa = mWindow->getFSAASamples(); + //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); + //U32 old_fsaa = mWindow->getFSAASamples(); - // if not maximized, use the request size - if (!mWindow->getMaximized()) - { - mWindow->setSize(size); - } + // if not maximized, use the request size + if (!mWindow->getMaximized()) + { + mWindow->setSize(size); + } - //if (fsaa == old_fsaa) - { - return TRUE; - } + //if (fsaa == old_fsaa) + { + return TRUE; + } /* - // Close floaters that don't handle settings change - LLFloaterReg::hideInstance("snapshot"); - - BOOL result_first_try = FALSE; - BOOL result_second_try = FALSE; - - LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); - send_agent_pause(); - LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; - stopGL(); - mIgnoreActivate = TRUE; - LLCoordScreen old_size; - LLCoordScreen old_pos; - mWindow->getSize(&old_size); - - //mWindow->setFSAASamples(fsaa); - - result_first_try = mWindow->switchContext(false, size, disable_vsync); - if (!result_first_try) - { - // try to switch back - //mWindow->setFSAASamples(old_fsaa); - result_second_try = mWindow->switchContext(false, old_size, disable_vsync); - - if (!result_second_try) - { - // we are stuck...try once again with a minimal resolution? - send_agent_resume(); - mIgnoreActivate = FALSE; - return FALSE; - } - } - send_agent_resume(); - - LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - else - { - restoreGL(); - } - - if (!result_first_try) - { - LLSD args; - args["RESX"] = llformat("%d",size.mX); - args["RESY"] = llformat("%d",size.mY); - LLNotificationsUtil::add("ResolutionSwitchFail", args); - size = old_size; // for reshape below - } - - BOOL success = result_first_try || result_second_try; - - if (success) - { - // maximize window if was maximized, else reposition - if (was_maximized) - { - mWindow->maximize(); - } - else - { - S32 windowX = gSavedSettings.getS32("WindowX"); - S32 windowY = gSavedSettings.getS32("WindowY"); - - mWindow->setPosition(LLCoordScreen ( windowX, windowY ) ); - } - } - - mIgnoreActivate = FALSE; - gFocusMgr.setKeyboardFocus(keyboard_focus); - - return success; - - */ -} - -F32 LLViewerWindow::getWorldViewAspectRatio() const -{ - F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight(); - return world_aspect; + // Close floaters that don't handle settings change + LLFloaterReg::hideInstance("snapshot"); + + BOOL result_first_try = FALSE; + BOOL result_second_try = FALSE; + + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + send_agent_pause(); + LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; + stopGL(); + mIgnoreActivate = TRUE; + LLCoordScreen old_size; + LLCoordScreen old_pos; + mWindow->getSize(&old_size); + + //mWindow->setFSAASamples(fsaa); + + result_first_try = mWindow->switchContext(false, size, disable_vsync); + if (!result_first_try) + { + // try to switch back + //mWindow->setFSAASamples(old_fsaa); + result_second_try = mWindow->switchContext(false, old_size, disable_vsync); + + if (!result_second_try) + { + // we are stuck...try once again with a minimal resolution? + send_agent_resume(); + mIgnoreActivate = FALSE; + return FALSE; + } + } + send_agent_resume(); + + LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; + if (show_progress_bar) + { + restoreGL(LLTrans::getString("ProgressChangingResolution")); + } + else + { + restoreGL(); + } + + if (!result_first_try) + { + LLSD args; + args["RESX"] = llformat("%d",size.mX); + args["RESY"] = llformat("%d",size.mY); + LLNotificationsUtil::add("ResolutionSwitchFail", args); + size = old_size; // for reshape below + } + + BOOL success = result_first_try || result_second_try; + + if (success) + { + // maximize window if was maximized, else reposition + if (was_maximized) + { + mWindow->maximize(); + } + else + { + S32 windowX = gSavedSettings.getS32("WindowX"); + S32 windowY = gSavedSettings.getS32("WindowY"); + + mWindow->setPosition(LLCoordScreen ( windowX, windowY ) ); + } + } + + mIgnoreActivate = FALSE; + gFocusMgr.setKeyboardFocus(keyboard_focus); + + return success; + + */ +} + +F32 LLViewerWindow::getWorldViewAspectRatio() const +{ + F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight(); + return world_aspect; } void LLViewerWindow::calcDisplayScale() { - F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); - LLVector2 display_scale; - display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - display_scale *= ui_scale_factor; + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); + LLVector2 display_scale; + display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); + display_scale *= ui_scale_factor; - // limit minimum display scale - if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE) - { - display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]); - } - - if (display_scale != mDisplayScale) - { - LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL; + // limit minimum display scale + if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE) + { + display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]); + } + + if (display_scale != mDisplayScale) + { + LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL; - mDisplayScale = display_scale; - // Init default fonts - initFonts(); - } + mDisplayScale = display_scale; + // Init default fonts + initFonts(); + } } //static -LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale) +LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale) { - LLRect res = rect; - res.mLeft = ll_round((F32)res.mLeft / display_scale.mV[VX]); - res.mRight = ll_round((F32)res.mRight / display_scale.mV[VX]); - res.mBottom = ll_round((F32)res.mBottom / display_scale.mV[VY]); - res.mTop = ll_round((F32)res.mTop / display_scale.mV[VY]); + LLRect res = rect; + res.mLeft = ll_round((F32)res.mLeft / display_scale.mV[VX]); + res.mRight = ll_round((F32)res.mRight / display_scale.mV[VX]); + res.mBottom = ll_round((F32)res.mBottom / display_scale.mV[VY]); + res.mTop = ll_round((F32)res.mTop / display_scale.mV[VY]); - return res; + return res; } S32 LLViewerWindow::getChatConsoleBottomPad() { - S32 offset = 0; + S32 offset = 0; - if(gToolBarView) - offset += gToolBarView->getBottomToolbar()->getRect().getHeight(); + if(gToolBarView) + offset += gToolBarView->getBottomToolbar()->getRect().getHeight(); - return offset; + return offset; } LLRect LLViewerWindow::getChatConsoleRect() { - LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0); - LLRect console_rect = full_window; + LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0); + LLRect console_rect = full_window; - const S32 CONSOLE_PADDING_TOP = 24; - const S32 CONSOLE_PADDING_LEFT = 24; - const S32 CONSOLE_PADDING_RIGHT = 10; + const S32 CONSOLE_PADDING_TOP = 24; + const S32 CONSOLE_PADDING_LEFT = 24; + const S32 CONSOLE_PADDING_RIGHT = 10; - console_rect.mTop -= CONSOLE_PADDING_TOP; - console_rect.mBottom += getChatConsoleBottomPad(); + console_rect.mTop -= CONSOLE_PADDING_TOP; + console_rect.mBottom += getChatConsoleBottomPad(); - console_rect.mLeft += CONSOLE_PADDING_LEFT; + console_rect.mLeft += CONSOLE_PADDING_LEFT; - static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth"); + static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth"); - if (CHAT_FULL_WIDTH) - { - console_rect.mRight -= CONSOLE_PADDING_RIGHT; - } - else - { - // Make console rect somewhat narrow so having inventory open is - // less of a problem. - console_rect.mRight = console_rect.mLeft + 2 * getWindowWidthScaled() / 3; - } + if (CHAT_FULL_WIDTH) + { + console_rect.mRight -= CONSOLE_PADDING_RIGHT; + } + else + { + // Make console rect somewhat narrow so having inventory open is + // less of a problem. + console_rect.mRight = console_rect.mLeft + 2 * getWindowWidthScaled() / 3; + } - return console_rect; + return console_rect; } void LLViewerWindow::reshapeStatusBarContainer() @@ -6063,31 +6063,31 @@ void LLViewerWindow::reshapeStatusBarContainer() void LLViewerWindow::setUIVisibility(bool visible) { - mUIVisible = visible; + mUIVisible = visible; - if (!visible) - { - gAgentCamera.changeCameraToThirdPerson(FALSE); - gFloaterView->hideAllFloaters(); - } - else - { - gFloaterView->showHiddenFloaters(); - } + if (!visible) + { + gAgentCamera.changeCameraToThirdPerson(FALSE); + gFloaterView->hideAllFloaters(); + } + else + { + gFloaterView->showHiddenFloaters(); + } - if (gToolBarView) - { - gToolBarView->setToolBarsVisible(visible); - } + if (gToolBarView) + { + gToolBarView->setToolBarsVisible(visible); + } - LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE); - LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE); - mRootView->getChildView("status_bar_container")->setVisible(visible); + LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE); + LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE); + mRootView->getChildView("status_bar_container")->setVisible(visible); } bool LLViewerWindow::getUIVisibility() { - return mUIVisible; + return mUIVisible; } //////////////////////////////////////////////////////////////////////////// @@ -6095,22 +6095,22 @@ bool LLViewerWindow::getUIVisibility() // LLPickInfo // LLPickInfo::LLPickInfo() - : mKeyMask(MASK_NONE), - mPickCallback(NULL), - mPickType(PICK_INVALID), - mWantSurfaceInfo(FALSE), - mObjectFace(-1), - mUVCoords(-1.f, -1.f), - mSTCoords(-1.f, -1.f), - mXYCoords(-1, -1), - mIntersection(), - mNormal(), - mTangent(), - mBinormal(), - mHUDIcon(NULL), - mPickTransparent(FALSE), - mPickRigged(FALSE), - mPickParticle(FALSE) + : mKeyMask(MASK_NONE), + mPickCallback(NULL), + mPickType(PICK_INVALID), + mWantSurfaceInfo(FALSE), + mObjectFace(-1), + mUVCoords(-1.f, -1.f), + mSTCoords(-1.f, -1.f), + mXYCoords(-1, -1), + mIntersection(), + mNormal(), + mTangent(), + mBinormal(), + mHUDIcon(NULL), + mPickTransparent(FALSE), + mPickRigged(FALSE), + mPickParticle(FALSE) { } @@ -6140,236 +6140,236 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, mPickRigged(pick_rigged), mPickParticle(pick_particle), mPickReflectionProbe(pick_reflection_probe), - mPickUnselectable(pick_unselectable) + mPickUnselectable(pick_unselectable) { } void LLPickInfo::fetchResults() { - S32 face_hit = -1; + S32 face_hit = -1; + + LLVector4a intersection, normal; + LLVector4a tangent; - LLVector4a intersection, normal; - LLVector4a tangent; + LLVector2 uv; - LLVector2 uv; + LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection); - LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection); - - LLVector4a origin; - origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); - F32 icon_dist = 0.f; - LLVector4a start; - LLVector4a end; - LLVector4a particle_end; + LLVector4a origin; + origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); + F32 icon_dist = 0.f; + LLVector4a start; + LLVector4a end; + LLVector4a particle_end; - if (hit_icon) - { - LLVector4a delta; - delta.setSub(intersection, origin); - icon_dist = delta.getLength3().getF32(); - } + if (hit_icon) + { + LLVector4a delta; + delta.setSub(intersection, origin); + icon_dist = delta.getLength3().getF32(); + } - LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, - nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, + LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, + nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, &intersection, &uv, &normal, &tangent, &start, &end); - - mPickPt = mMousePt; - - U32 te_offset = face_hit > -1 ? face_hit : 0; - - if (mPickParticle) - { //get the end point of line segement to use for particle raycast - if (hit_object) - { - particle_end = intersection; - } - else - { - particle_end = end; - } - } - - LLViewerObject* objectp = hit_object; - - - LLVector4a delta; - delta.setSub(origin, intersection); - - if (hit_icon && - (!objectp || - icon_dist < delta.getLength3().getF32())) - { - // was this name referring to a hud icon? - mHUDIcon = hit_icon; - mPickType = PICK_ICON; - mPosGlobal = mHUDIcon->getPositionGlobal(); - - } - else if (objectp) - { - if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) - { - // Hit land - mPickType = PICK_LAND; - mObjectID.setNull(); // land has no id - - // put global position into land_pos - LLVector3d land_pos; - if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos, mPickUnselectable)) - { - // The selected point is beyond the draw distance or is otherwise - // not selectable. Return before calling mPickCallback(). - return; - } - - // Fudge the land focus a little bit above ground. - mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; - } - else - { - if(isFlora(objectp)) - { - mPickType = PICK_FLORA; - } - else - { - mPickType = PICK_OBJECT; - } - - LLVector3 v_intersection(intersection.getF32ptr()); - - mObjectOffset = gAgentCamera.calcFocusOffset(objectp, v_intersection, mPickPt.mX, mPickPt.mY); - mObjectID = objectp->mID; - mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; - - - - mPosGlobal = gAgent.getPosGlobalFromAgent(v_intersection); - - if (mWantSurfaceInfo) - { - getSurfaceInfo(); - } - } - } - - if (mPickParticle) - { //search for closest particle to click origin out to intersection point - S32 part_face = -1; - - LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face); - if (group) - { - mParticleOwnerID = group->getPartOwner(part_face); - mParticleSourceID = group->getPartSource(part_face); - } - } - - if (mPickCallback) - { - mPickCallback(*this); - } + + mPickPt = mMousePt; + + U32 te_offset = face_hit > -1 ? face_hit : 0; + + if (mPickParticle) + { //get the end point of line segement to use for particle raycast + if (hit_object) + { + particle_end = intersection; + } + else + { + particle_end = end; + } + } + + LLViewerObject* objectp = hit_object; + + + LLVector4a delta; + delta.setSub(origin, intersection); + + if (hit_icon && + (!objectp || + icon_dist < delta.getLength3().getF32())) + { + // was this name referring to a hud icon? + mHUDIcon = hit_icon; + mPickType = PICK_ICON; + mPosGlobal = mHUDIcon->getPositionGlobal(); + + } + else if (objectp) + { + if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH ) + { + // Hit land + mPickType = PICK_LAND; + mObjectID.setNull(); // land has no id + + // put global position into land_pos + LLVector3d land_pos; + if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos, mPickUnselectable)) + { + // The selected point is beyond the draw distance or is otherwise + // not selectable. Return before calling mPickCallback(). + return; + } + + // Fudge the land focus a little bit above ground. + mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f; + } + else + { + if(isFlora(objectp)) + { + mPickType = PICK_FLORA; + } + else + { + mPickType = PICK_OBJECT; + } + + LLVector3 v_intersection(intersection.getF32ptr()); + + mObjectOffset = gAgentCamera.calcFocusOffset(objectp, v_intersection, mPickPt.mX, mPickPt.mY); + mObjectID = objectp->mID; + mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; + + + + mPosGlobal = gAgent.getPosGlobalFromAgent(v_intersection); + + if (mWantSurfaceInfo) + { + getSurfaceInfo(); + } + } + } + + if (mPickParticle) + { //search for closest particle to click origin out to intersection point + S32 part_face = -1; + + LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face); + if (group) + { + mParticleOwnerID = group->getPartOwner(part_face); + mParticleSourceID = group->getPartSource(part_face); + } + } + + if (mPickCallback) + { + mPickCallback(*this); + } } LLPointer LLPickInfo::getObject() const { - return gObjectList.findObject( mObjectID ); + return gObjectList.findObject( mObjectID ); } void LLPickInfo::updateXYCoords() { - if (mObjectFace > -1) - { - const LLTextureEntry* tep = getObject()->getTE(mObjectFace); - LLPointer imagep = LLViewerTextureManager::getFetchedTexture(tep->getID()); - if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull()) - { - mXYCoords.mX = ll_round(mUVCoords.mV[VX] * (F32)imagep->getWidth()); - mXYCoords.mY = ll_round((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight()); - } - } + if (mObjectFace > -1) + { + const LLTextureEntry* tep = getObject()->getTE(mObjectFace); + LLPointer imagep = LLViewerTextureManager::getFetchedTexture(tep->getID()); + if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull()) + { + mXYCoords.mX = ll_round(mUVCoords.mV[VX] * (F32)imagep->getWidth()); + mXYCoords.mY = ll_round((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight()); + } + } } void LLPickInfo::getSurfaceInfo() { - // set values to uninitialized - this is what we return if no intersection is found - mObjectFace = -1; - mUVCoords = LLVector2(-1, -1); - mSTCoords = LLVector2(-1, -1); - mXYCoords = LLCoordScreen(-1, -1); - mIntersection = LLVector3(0,0,0); - mNormal = LLVector3(0,0,0); - mBinormal = LLVector3(0,0,0); - mTangent = LLVector4(0,0,0,0); - - LLVector4a tangent; - LLVector4a intersection; - LLVector4a normal; - - tangent.clear(); - normal.clear(); - intersection.clear(); - - LLViewerObject* objectp = getObject(); - - if (objectp) - { - if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, - objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, - &mObjectFace, + // set values to uninitialized - this is what we return if no intersection is found + mObjectFace = -1; + mUVCoords = LLVector2(-1, -1); + mSTCoords = LLVector2(-1, -1); + mXYCoords = LLCoordScreen(-1, -1); + mIntersection = LLVector3(0,0,0); + mNormal = LLVector3(0,0,0); + mBinormal = LLVector3(0,0,0); + mTangent = LLVector4(0,0,0,0); + + LLVector4a tangent; + LLVector4a intersection; + LLVector4a normal; + + tangent.clear(); + normal.clear(); + intersection.clear(); + + LLViewerObject* objectp = getObject(); + + if (objectp) + { + if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, + objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, + &mObjectFace, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, - &intersection, - &mSTCoords, - &normal, - &tangent)) - { - // if we succeeded with the intersect above, compute the texture coordinates: - - if (objectp->mDrawable.notNull() && mObjectFace > -1) - { - LLFace* facep = objectp->mDrawable->getFace(mObjectFace); - if (facep) - { - mUVCoords = facep->surfaceToTexture(mSTCoords, intersection, normal); - } - } - - mIntersection.set(intersection.getF32ptr()); - mNormal.set(normal.getF32ptr()); - mTangent.set(tangent.getF32ptr()); - - //extrapoloate binormal from normal and tangent - - LLVector4a binormal; - binormal.setCross3(normal, tangent); - binormal.mul(tangent.getF32ptr()[3]); - - mBinormal.set(binormal.getF32ptr()); - - mBinormal.normalize(); - mNormal.normalize(); - mTangent.normalize(); - - // and XY coords: - updateXYCoords(); - - } - } -} - -//static + &intersection, + &mSTCoords, + &normal, + &tangent)) + { + // if we succeeded with the intersect above, compute the texture coordinates: + + if (objectp->mDrawable.notNull() && mObjectFace > -1) + { + LLFace* facep = objectp->mDrawable->getFace(mObjectFace); + if (facep) + { + mUVCoords = facep->surfaceToTexture(mSTCoords, intersection, normal); + } + } + + mIntersection.set(intersection.getF32ptr()); + mNormal.set(normal.getF32ptr()); + mTangent.set(tangent.getF32ptr()); + + //extrapoloate binormal from normal and tangent + + LLVector4a binormal; + binormal.setCross3(normal, tangent); + binormal.mul(tangent.getF32ptr()[3]); + + mBinormal.set(binormal.getF32ptr()); + + mBinormal.normalize(); + mNormal.normalize(); + mTangent.normalize(); + + // and XY coords: + updateXYCoords(); + + } + } +} + +//static bool LLPickInfo::isFlora(LLViewerObject* object) { - if (!object) return false; + if (!object) return false; - LLPCode pcode = object->getPCode(); + LLPCode pcode = object->getPCode(); - if( (LL_PCODE_LEGACY_GRASS == pcode) - || (LL_PCODE_LEGACY_TREE == pcode) - || (LL_PCODE_TREE_NEW == pcode)) - { - return true; - } - return false; + if( (LL_PCODE_LEGACY_GRASS == pcode) + || (LL_PCODE_LEGACY_TREE == pcode) + || (LL_PCODE_TREE_NEW == pcode)) + { + return true; + } + return false; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 121b5b6fad..fc22b003d5 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -1,25 +1,25 @@ -/** +/** * @file llviewerwindow.h * @brief Description of the LLViewerWindow class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -77,69 +77,69 @@ class LLCubeMapArray; class LLPickInfo { public: - typedef enum - { - PICK_OBJECT, - PICK_FLORA, - PICK_LAND, - PICK_ICON, - PICK_PARCEL_WALL, - PICK_INVALID - } EPickType; + typedef enum + { + PICK_OBJECT, + PICK_FLORA, + PICK_LAND, + PICK_ICON, + PICK_PARCEL_WALL, + PICK_INVALID + } EPickType; public: - LLPickInfo(); - LLPickInfo(const LLCoordGL& mouse_pos, - MASK keyboard_mask, - BOOL pick_transparent, - BOOL pick_rigged, - BOOL pick_particle, + LLPickInfo(); + LLPickInfo(const LLCoordGL& mouse_pos, + MASK keyboard_mask, + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_particle, BOOL pick_reflection_probe, - BOOL pick_surface_info, - BOOL pick_unselectable, - void (*pick_callback)(const LLPickInfo& pick_info)); + BOOL pick_surface_info, + BOOL pick_unselectable, + void (*pick_callback)(const LLPickInfo& pick_info)); - void fetchResults(); - LLPointer getObject() const; - LLUUID getObjectID() const { return mObjectID; } - bool isValid() const { return mPickType != PICK_INVALID; } + void fetchResults(); + LLPointer getObject() const; + LLUUID getObjectID() const { return mObjectID; } + bool isValid() const { return mPickType != PICK_INVALID; } - static bool isFlora(LLViewerObject* object); + static bool isFlora(LLViewerObject* object); public: - LLCoordGL mMousePt; - MASK mKeyMask; - void (*mPickCallback)(const LLPickInfo& pick_info); - - EPickType mPickType; - LLCoordGL mPickPt; - LLVector3d mPosGlobal; - LLVector3 mObjectOffset; - LLUUID mObjectID; - LLUUID mParticleOwnerID; - LLUUID mParticleSourceID; - S32 mObjectFace; + LLCoordGL mMousePt; + MASK mKeyMask; + void (*mPickCallback)(const LLPickInfo& pick_info); + + EPickType mPickType; + LLCoordGL mPickPt; + LLVector3d mPosGlobal; + LLVector3 mObjectOffset; + LLUUID mObjectID; + LLUUID mParticleOwnerID; + LLUUID mParticleSourceID; + S32 mObjectFace; S32 mGLTFNodeIndex = -1; S32 mGLTFPrimitiveIndex = -1; - LLHUDIcon* mHUDIcon; - LLVector3 mIntersection; - LLVector2 mUVCoords; - LLVector2 mSTCoords; - LLCoordScreen mXYCoords; - LLVector3 mNormal; - LLVector4 mTangent; - LLVector3 mBinormal; - BOOL mPickTransparent; - BOOL mPickRigged; - BOOL mPickParticle; - BOOL mPickUnselectable; + LLHUDIcon* mHUDIcon; + LLVector3 mIntersection; + LLVector2 mUVCoords; + LLVector2 mSTCoords; + LLCoordScreen mXYCoords; + LLVector3 mNormal; + LLVector4 mTangent; + LLVector3 mBinormal; + BOOL mPickTransparent; + BOOL mPickRigged; + BOOL mPickParticle; + BOOL mPickUnselectable; BOOL mPickReflectionProbe = FALSE; - void getSurfaceInfo(); + void getSurfaceInfo(); private: - void updateXYCoords(); + void updateXYCoords(); - BOOL mWantSurfaceInfo; // do we populate mUVCoord, mNormal, mBinormal? + BOOL mWantSurfaceInfo; // do we populate mUVCoord, mNormal, mBinormal? }; @@ -148,228 +148,228 @@ static const U32 MAX_SNAPSHOT_IMAGE_SIZE = 7680; // max snapshot image size 7680 class LLViewerWindow : public LLWindowCallbacks { public: - // - // CREATORS - // - struct Params : public LLInitParam::Block - { - Mandatory title, - name; - Mandatory x, - y, - width, - height, - min_width, - min_height; - Optional fullscreen, - ignore_pixel_depth, - first_run; - - Params(); - }; - - LLViewerWindow(const Params& p); - virtual ~LLViewerWindow(); - - void shutdownViews(); - void shutdownGL(); - - void initGLDefaults(); - void initBase(); - void adjustRectanglesForFirstUse(const LLRect& window); - void adjustControlRectanglesForFirstUse(const LLRect& window); - void initWorldUI(); - void setUIVisibility(bool); - bool getUIVisibility(); - void handlePieMenu(S32 x, S32 y, MASK mask); + // + // CREATORS + // + struct Params : public LLInitParam::Block + { + Mandatory title, + name; + Mandatory x, + y, + width, + height, + min_width, + min_height; + Optional fullscreen, + ignore_pixel_depth, + first_run; + + Params(); + }; + + LLViewerWindow(const Params& p); + virtual ~LLViewerWindow(); + + void shutdownViews(); + void shutdownGL(); + + void initGLDefaults(); + void initBase(); + void adjustRectanglesForFirstUse(const LLRect& window); + void adjustControlRectanglesForFirstUse(const LLRect& window); + void initWorldUI(); + void setUIVisibility(bool); + bool getUIVisibility(); + void handlePieMenu(S32 x, S32 y, MASK mask); void reshapeStatusBarContainer(); - BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down, bool &is_toolmgr_action); - - // - // LLWindowCallback interface implementation - // - /*virtual*/ BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated); - /*virtual*/ BOOL handleTranslatedKeyUp(KEY key, MASK mask); - /*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); - /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended - /*virtual*/ BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleCloseRequest(LLWindow *window); - /*virtual*/ void handleQuit(LLWindow *window); - /*virtual*/ BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button); - /*virtual*/ BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button); - BOOL handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down); - /*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data); - void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); + BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down, bool &is_toolmgr_action); + + // + // LLWindowCallback interface implementation + // + /*virtual*/ BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated); + /*virtual*/ BOOL handleTranslatedKeyUp(KEY key, MASK mask); + /*virtual*/ void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); + /*virtual*/ BOOL handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended + /*virtual*/ BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleCloseRequest(LLWindow *window); + /*virtual*/ void handleQuit(LLWindow *window); + /*virtual*/ BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button); + /*virtual*/ BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button); + BOOL handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down); + /*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data); + void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); void handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ void handleMouseLeave(LLWindow *window); - /*virtual*/ void handleResize(LLWindow *window, S32 x, S32 y); - /*virtual*/ void handleFocus(LLWindow *window); - /*virtual*/ void handleFocusLost(LLWindow *window); - /*virtual*/ BOOL handleActivate(LLWindow *window, BOOL activated); - /*virtual*/ BOOL handleActivateApp(LLWindow *window, BOOL activating); - /*virtual*/ void handleMenuSelect(LLWindow *window, S32 menu_item); - /*virtual*/ BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height); - /*virtual*/ void handleScrollWheel(LLWindow *window, S32 clicks); - /*virtual*/ void handleScrollHWheel(LLWindow *window, S32 clicks); - /*virtual*/ BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); - /*virtual*/ void handleWindowBlock(LLWindow *window); - /*virtual*/ void handleWindowUnblock(LLWindow *window); - /*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); - /*virtual*/ BOOL handleTimerEvent(LLWindow *window); - /*virtual*/ BOOL handleDeviceChange(LLWindow *window); - /*virtual*/ BOOL handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); - /*virtual*/ BOOL handleWindowDidChangeScreen(LLWindow *window); - - /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); - /*virtual*/ void handlePauseWatchdog(LLWindow *window); - /*virtual*/ void handleResumeWatchdog(LLWindow *window); - /*virtual*/ std::string translateString(const char* tag); - /*virtual*/ std::string translateString(const char* tag, - const std::map& args); - - // signal on update of WorldView rect - typedef boost::function world_rect_callback_t; - typedef boost::signals2::signal world_rect_signal_t; - world_rect_signal_t mOnWorldViewRectUpdated; - boost::signals2::connection setOnWorldViewRectUpdated(world_rect_callback_t cb) { return mOnWorldViewRectUpdated.connect(cb); } - - // - // ACCESSORS - // - LLRootView* getRootView() const; - - // 3D world area in scaled pixels (via UI scale), use for most UI computations - LLRect getWorldViewRectScaled() const; - S32 getWorldViewHeightScaled() const; - S32 getWorldViewWidthScaled() const; - - // 3D world area, in raw unscaled pixels - LLRect getWorldViewRectRaw() const { return mWorldViewRectRaw; } - S32 getWorldViewHeightRaw() const; - S32 getWorldViewWidthRaw() const; - - // Window in scaled pixels (via UI scale), use for most UI computations - LLRect getWindowRectScaled() const { return mWindowRectScaled; } - S32 getWindowHeightScaled() const; - S32 getWindowWidthScaled() const; - - // Window in raw pixels as seen on screen. - LLRect getWindowRectRaw() const { return mWindowRectRaw; } - S32 getWindowHeightRaw() const; - S32 getWindowWidthRaw() const; - - LLWindow* getWindow() const { return mWindow; } - void* getPlatformWindow() const; - void* getMediaWindow() const; - void focusClient() const; - - LLCoordGL getLastMouse() const { return mLastMousePoint; } - S32 getLastMouseX() const { return mLastMousePoint.mX; } - S32 getLastMouseY() const { return mLastMousePoint.mY; } - LLCoordGL getCurrentMouse() const { return mCurrentMousePoint; } - S32 getCurrentMouseX() const { return mCurrentMousePoint.mX; } - S32 getCurrentMouseY() const { return mCurrentMousePoint.mY; } - S32 getCurrentMouseDX() const { return mCurrentMouseDelta.mX; } - S32 getCurrentMouseDY() const { return mCurrentMouseDelta.mY; } - LLCoordGL getCurrentMouseDelta() const { return mCurrentMouseDelta; } - static LLTrace::SampleStatHandle<>* getMouseVelocityStat() { return &sMouseVelocityStat; } - BOOL getLeftMouseDown() const { return mLeftMouseDown; } - BOOL getMiddleMouseDown() const { return mMiddleMouseDown; } - BOOL getRightMouseDown() const { return mRightMouseDown; } - - const LLPickInfo& getLastPick() const { return mLastPick; } - - void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0); - void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0); - void setup3DRender(); - void setup2DRender(); - - LLVector3 mouseDirectionGlobal(const S32 x, const S32 y) const; - LLVector3 mouseDirectionCamera(const S32 x, const S32 y) const; - LLVector3 mousePointHUD(const S32 x, const S32 y) const; - - - // Is window of our application frontmost? - BOOL getActive() const { return mActive; } - - const std::string& getInitAlert() { return mInitAlert; } - - // - // MANIPULATORS - // - void saveLastMouse(const LLCoordGL &point); - - void setCursor( ECursorType c ); - void showCursor(); - void hideCursor(); - BOOL getCursorHidden() { return mCursorHidden; } - void moveCursorToCenter(); // move to center of window - - void initTextures(S32 location_id); - void setShowProgress(const BOOL show); - BOOL getShowProgress() const; - void setProgressString(const std::string& string); - void setProgressPercent(const F32 percent); - void setProgressMessage(const std::string& msg); - void setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null ); - LLProgressView *getProgressView() const; - void revealIntroPanel(); - void setStartupComplete(); - - void updateObjectUnderCursor(); - - void updateUI(); // Once per frame, update UI based on mouse position, calls following update* functions - void updateLayout(); - void updateMouseDelta(); - void updateKeyboardFocus(); - - void updateWorldViewRect(bool use_full_window=false); - LLView* getToolBarHolder() { return mToolBarHolder.get(); } - LLView* getHintHolder() { return mHintHolder.get(); } - LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); } - BOOL handleKey(KEY key, MASK mask); - BOOL handleKeyUp(KEY key, MASK mask); - void handleScrollWheel (S32 clicks); - void handleScrollHWheel (S32 clicks); - - // add and remove views from "popup" layer - void addPopup(LLView* popup); - void removePopup(LLView* popup); - void clearPopups(); - - // Hide normal UI when a logon fails, re-show everything when logon is attempted again - void setNormalControlsVisible( BOOL visible ); - void setMenuBackgroundColor(bool god_mode = false, bool dev_grid = false); - - void reshape(S32 width, S32 height); - void sendShapeToSim(); - - void draw(); - void updateDebugText(); - void drawDebugText(); - - static void loadUserImage(void **cb_data, const LLUUID &uuid); - - static void movieSize(S32 new_width, S32 new_height); - - // snapshot functionality. - // perhaps some of this should move to llfloatershapshot? -MG - - BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP); - BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, - BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, BOOL no_post = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); - - BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes); - - - + /*virtual*/ void handleMouseLeave(LLWindow *window); + /*virtual*/ void handleResize(LLWindow *window, S32 x, S32 y); + /*virtual*/ void handleFocus(LLWindow *window); + /*virtual*/ void handleFocusLost(LLWindow *window); + /*virtual*/ BOOL handleActivate(LLWindow *window, BOOL activated); + /*virtual*/ BOOL handleActivateApp(LLWindow *window, BOOL activating); + /*virtual*/ void handleMenuSelect(LLWindow *window, S32 menu_item); + /*virtual*/ BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height); + /*virtual*/ void handleScrollWheel(LLWindow *window, S32 clicks); + /*virtual*/ void handleScrollHWheel(LLWindow *window, S32 clicks); + /*virtual*/ BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); + /*virtual*/ void handleWindowBlock(LLWindow *window); + /*virtual*/ void handleWindowUnblock(LLWindow *window); + /*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); + /*virtual*/ BOOL handleTimerEvent(LLWindow *window); + /*virtual*/ BOOL handleDeviceChange(LLWindow *window); + /*virtual*/ BOOL handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); + /*virtual*/ BOOL handleWindowDidChangeScreen(LLWindow *window); + + /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); + /*virtual*/ void handlePauseWatchdog(LLWindow *window); + /*virtual*/ void handleResumeWatchdog(LLWindow *window); + /*virtual*/ std::string translateString(const char* tag); + /*virtual*/ std::string translateString(const char* tag, + const std::map& args); + + // signal on update of WorldView rect + typedef boost::function world_rect_callback_t; + typedef boost::signals2::signal world_rect_signal_t; + world_rect_signal_t mOnWorldViewRectUpdated; + boost::signals2::connection setOnWorldViewRectUpdated(world_rect_callback_t cb) { return mOnWorldViewRectUpdated.connect(cb); } + + // + // ACCESSORS + // + LLRootView* getRootView() const; + + // 3D world area in scaled pixels (via UI scale), use for most UI computations + LLRect getWorldViewRectScaled() const; + S32 getWorldViewHeightScaled() const; + S32 getWorldViewWidthScaled() const; + + // 3D world area, in raw unscaled pixels + LLRect getWorldViewRectRaw() const { return mWorldViewRectRaw; } + S32 getWorldViewHeightRaw() const; + S32 getWorldViewWidthRaw() const; + + // Window in scaled pixels (via UI scale), use for most UI computations + LLRect getWindowRectScaled() const { return mWindowRectScaled; } + S32 getWindowHeightScaled() const; + S32 getWindowWidthScaled() const; + + // Window in raw pixels as seen on screen. + LLRect getWindowRectRaw() const { return mWindowRectRaw; } + S32 getWindowHeightRaw() const; + S32 getWindowWidthRaw() const; + + LLWindow* getWindow() const { return mWindow; } + void* getPlatformWindow() const; + void* getMediaWindow() const; + void focusClient() const; + + LLCoordGL getLastMouse() const { return mLastMousePoint; } + S32 getLastMouseX() const { return mLastMousePoint.mX; } + S32 getLastMouseY() const { return mLastMousePoint.mY; } + LLCoordGL getCurrentMouse() const { return mCurrentMousePoint; } + S32 getCurrentMouseX() const { return mCurrentMousePoint.mX; } + S32 getCurrentMouseY() const { return mCurrentMousePoint.mY; } + S32 getCurrentMouseDX() const { return mCurrentMouseDelta.mX; } + S32 getCurrentMouseDY() const { return mCurrentMouseDelta.mY; } + LLCoordGL getCurrentMouseDelta() const { return mCurrentMouseDelta; } + static LLTrace::SampleStatHandle<>* getMouseVelocityStat() { return &sMouseVelocityStat; } + BOOL getLeftMouseDown() const { return mLeftMouseDown; } + BOOL getMiddleMouseDown() const { return mMiddleMouseDown; } + BOOL getRightMouseDown() const { return mRightMouseDown; } + + const LLPickInfo& getLastPick() const { return mLastPick; } + + void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0); + void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0); + void setup3DRender(); + void setup2DRender(); + + LLVector3 mouseDirectionGlobal(const S32 x, const S32 y) const; + LLVector3 mouseDirectionCamera(const S32 x, const S32 y) const; + LLVector3 mousePointHUD(const S32 x, const S32 y) const; + + + // Is window of our application frontmost? + BOOL getActive() const { return mActive; } + + const std::string& getInitAlert() { return mInitAlert; } + + // + // MANIPULATORS + // + void saveLastMouse(const LLCoordGL &point); + + void setCursor( ECursorType c ); + void showCursor(); + void hideCursor(); + BOOL getCursorHidden() { return mCursorHidden; } + void moveCursorToCenter(); // move to center of window + + void initTextures(S32 location_id); + void setShowProgress(const BOOL show); + BOOL getShowProgress() const; + void setProgressString(const std::string& string); + void setProgressPercent(const F32 percent); + void setProgressMessage(const std::string& msg); + void setProgressCancelButtonVisible( BOOL b, const std::string& label = LLStringUtil::null ); + LLProgressView *getProgressView() const; + void revealIntroPanel(); + void setStartupComplete(); + + void updateObjectUnderCursor(); + + void updateUI(); // Once per frame, update UI based on mouse position, calls following update* functions + void updateLayout(); + void updateMouseDelta(); + void updateKeyboardFocus(); + + void updateWorldViewRect(bool use_full_window=false); + LLView* getToolBarHolder() { return mToolBarHolder.get(); } + LLView* getHintHolder() { return mHintHolder.get(); } + LLView* getLoginPanelHolder() { return mLoginPanelHolder.get(); } + BOOL handleKey(KEY key, MASK mask); + BOOL handleKeyUp(KEY key, MASK mask); + void handleScrollWheel (S32 clicks); + void handleScrollHWheel (S32 clicks); + + // add and remove views from "popup" layer + void addPopup(LLView* popup); + void removePopup(LLView* popup); + void clearPopups(); + + // Hide normal UI when a logon fails, re-show everything when logon is attempted again + void setNormalControlsVisible( BOOL visible ); + void setMenuBackgroundColor(bool god_mode = false, bool dev_grid = false); + + void reshape(S32 width, S32 height); + void sendShapeToSim(); + + void draw(); + void updateDebugText(); + void drawDebugText(); + + static void loadUserImage(void **cb_data, const LLUUID &uuid); + + static void movieSize(S32 new_width, S32 new_height); + + // snapshot functionality. + // perhaps some of this should move to llfloatershapshot? -MG + + BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP); + BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, + BOOL show_ui = TRUE, BOOL show_hud = TRUE, BOOL do_rebuild = FALSE, BOOL no_post = FALSE, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); + + BOOL simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes); + + + // take a cubemap snapshot // origin - vantage point to take the snapshot from // cubearray - cubemap array for storing the results @@ -379,202 +379,202 @@ public: BOOL cubeSnapshot(const LLVector3 &origin, LLCubeMapArray *cubearray, S32 index, S32 face, F32 near_clip, bool render_avatars, bool customCullingPlane = false, LLPlane cullingPlane = LLPlane(LLVector3(0, 0, 0), LLVector3(0, 0, 1))); - + // special implementation of simpleSnapshot for reflection maps - BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes); - - BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type); - BOOL isSnapshotLocSet() const; - void resetSnapshotLoc() const; - - typedef boost::signals2::signal snapshot_saved_signal_t; - - void saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); - void onDirectorySelected(const std::vector& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); - void saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); - void onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb); - - // Reset the directory where snapshots are saved. - // Client will open directory picker on next snapshot save. - void resetSnapshotLoc(); - - void playSnapshotAnimAndSound(); - - // draws selection boxes around selected objects, must call displayObjects first - void renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud ); - void performPick(); - void returnEmptyPicks(); - - void pickAsync( S32 x, - S32 y_from_bot, - MASK mask, - void (*callback)(const LLPickInfo& pick_info), - BOOL pick_transparent = FALSE, - BOOL pick_rigged = FALSE, - BOOL pick_unselectable = FALSE, + BOOL reflectionSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes); + + BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL show_hud, BOOL do_rebuild, BOOL no_post, LLSnapshotModel::ESnapshotLayerType type); + BOOL isSnapshotLocSet() const; + void resetSnapshotLoc() const; + + typedef boost::signals2::signal snapshot_saved_signal_t; + + void saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onDirectorySelected(const std::vector& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb); + + // Reset the directory where snapshots are saved. + // Client will open directory picker on next snapshot save. + void resetSnapshotLoc(); + + void playSnapshotAnimAndSound(); + + // draws selection boxes around selected objects, must call displayObjects first + void renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud ); + void performPick(); + void returnEmptyPicks(); + + void pickAsync( S32 x, + S32 y_from_bot, + MASK mask, + void (*callback)(const LLPickInfo& pick_info), + BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, + BOOL pick_unselectable = FALSE, BOOL pick_reflection_probes = FALSE); - LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE, BOOL pick_reflection_probe = FALSE); - LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, - LLVector4a* intersection); - - LLViewerObject* cursorIntersect(S32 mouse_x = -1, S32 mouse_y = -1, F32 depth = 512.f, - LLViewerObject *this_object = NULL, - S32 this_face = -1, - BOOL pick_transparent = FALSE, - BOOL pick_rigged = FALSE, + LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent, BOOL pick_rigged = FALSE, BOOL pick_particle = FALSE, BOOL pick_unselectable = TRUE, BOOL pick_reflection_probe = FALSE); + LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, + LLVector4a* intersection); + + LLViewerObject* cursorIntersect(S32 mouse_x = -1, S32 mouse_y = -1, F32 depth = 512.f, + LLViewerObject *this_object = NULL, + S32 this_face = -1, + BOOL pick_transparent = FALSE, + BOOL pick_rigged = FALSE, BOOL pick_unselectable = TRUE, BOOL pick_reflection_probe = TRUE, - S32* face_hit = NULL, + S32* face_hit = NULL, S32* gltf_node_hit = nullptr, S32* gltf_primitive_hit = nullptr, - LLVector4a *intersection = NULL, - LLVector2 *uv = NULL, - LLVector4a *normal = NULL, - LLVector4a *tangent = NULL, - LLVector4a* start = NULL, - LLVector4a* end = NULL); - - - // Returns a pointer to the last object hit - //LLViewerObject *getObject(); - //LLViewerObject *lastNonFloraObjectHit(); - - //const LLVector3d& getObjectOffset(); - //const LLVector3d& lastNonFloraObjectHitOffset(); - - // mousePointOnLand() returns true if found point - BOOL mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global, BOOL ignore_distance = FALSE); - BOOL mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, const LLVector3d &plane_point, const LLVector3 &plane_normal); - LLVector3d clickPointInWorldGlobal(const S32 x, const S32 y_from_bot, LLViewerObject* clicked_object) const; - BOOL clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const; - - // Prints window implementation details - void dumpState(); - - // handle shutting down GL and bringing it back up - void requestResolutionUpdate(); - void checkSettings(); - void restartDisplay(BOOL show_progress_bar); - BOOL changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar); - BOOL getIgnoreDestroyWindow() { return mIgnoreActivate; } - F32 getWorldViewAspectRatio() const; - const LLVector2& getDisplayScale() const { return mDisplayScale; } - void calcDisplayScale(); - static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); - - static std::string getLastSnapshotDir(); + LLVector4a *intersection = NULL, + LLVector2 *uv = NULL, + LLVector4a *normal = NULL, + LLVector4a *tangent = NULL, + LLVector4a* start = NULL, + LLVector4a* end = NULL); + + + // Returns a pointer to the last object hit + //LLViewerObject *getObject(); + //LLViewerObject *lastNonFloraObjectHit(); + + //const LLVector3d& getObjectOffset(); + //const LLVector3d& lastNonFloraObjectHitOffset(); + + // mousePointOnLand() returns true if found point + BOOL mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_pos_global, BOOL ignore_distance = FALSE); + BOOL mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, const LLVector3d &plane_point, const LLVector3 &plane_normal); + LLVector3d clickPointInWorldGlobal(const S32 x, const S32 y_from_bot, LLViewerObject* clicked_object) const; + BOOL clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const; + + // Prints window implementation details + void dumpState(); + + // handle shutting down GL and bringing it back up + void requestResolutionUpdate(); + void checkSettings(); + void restartDisplay(BOOL show_progress_bar); + BOOL changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar); + BOOL getIgnoreDestroyWindow() { return mIgnoreActivate; } + F32 getWorldViewAspectRatio() const; + const LLVector2& getDisplayScale() const { return mDisplayScale; } + void calcDisplayScale(); + static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); + + static std::string getLastSnapshotDir(); private: - bool shouldShowToolTipFor(LLMouseHandler *mh); - - void switchToolByMask(MASK mask); - void destroyWindow(); - void drawMouselookInstructions(); - void stopGL(BOOL save_state = TRUE); - void restoreGL(const std::string& progress_message = LLStringUtil::null); - void initFonts(F32 zoom_factor = 1.f); - void schedulePick(LLPickInfo& pick_info); - S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter - LLRect getChatConsoleRect(); // Get optimal cosole rect. + bool shouldShowToolTipFor(LLMouseHandler *mh); + + void switchToolByMask(MASK mask); + void destroyWindow(); + void drawMouselookInstructions(); + void stopGL(BOOL save_state = TRUE); + void restoreGL(const std::string& progress_message = LLStringUtil::null); + void initFonts(F32 zoom_factor = 1.f); + void schedulePick(LLPickInfo& pick_info); + S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter + LLRect getChatConsoleRect(); // Get optimal cosole rect. private: - LLWindow* mWindow; // graphical window object - bool mActive; - bool mUIVisible; - - LLNotificationChannelPtr mSystemChannel; - LLNotificationChannelPtr mCommunicationChannel; - LLNotificationChannelPtr mAlertsChannel; - LLNotificationChannelPtr mModalAlertsChannel; - - LLRect mWindowRectRaw; // whole window, including UI - LLRect mWindowRectScaled; // whole window, scaled by UI size - LLRect mWorldViewRectRaw; // area of screen for 3D world - LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size - LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views - LLVector2 mDisplayScale; - - LLCoordGL mCurrentMousePoint; // last mouse position in GL coords - LLCoordGL mLastMousePoint; // Mouse point at last frame. - LLCoordGL mCurrentMouseDelta; //amount mouse moved this frame - BOOL mLeftMouseDown; - BOOL mMiddleMouseDown; - BOOL mRightMouseDown; - - LLProgressView *mProgressView; - - LLFrameTimer mToolTipFadeTimer; - LLPanel* mToolTip; - std::string mLastToolTipMessage; - LLRect mToolTipStickyRect; // Once a tool tip is shown, it will stay visible until the mouse leaves this rect. - - BOOL mMouseInWindow; // True if the mouse is over our window or if we have captured the mouse. - BOOL mFocusCycleMode; + LLWindow* mWindow; // graphical window object + bool mActive; + bool mUIVisible; + + LLNotificationChannelPtr mSystemChannel; + LLNotificationChannelPtr mCommunicationChannel; + LLNotificationChannelPtr mAlertsChannel; + LLNotificationChannelPtr mModalAlertsChannel; + + LLRect mWindowRectRaw; // whole window, including UI + LLRect mWindowRectScaled; // whole window, scaled by UI size + LLRect mWorldViewRectRaw; // area of screen for 3D world + LLRect mWorldViewRectScaled; // area of screen for 3D world scaled by UI size + LLRootView* mRootView; // a view of size mWindowRectRaw, containing all child views + LLVector2 mDisplayScale; + + LLCoordGL mCurrentMousePoint; // last mouse position in GL coords + LLCoordGL mLastMousePoint; // Mouse point at last frame. + LLCoordGL mCurrentMouseDelta; //amount mouse moved this frame + BOOL mLeftMouseDown; + BOOL mMiddleMouseDown; + BOOL mRightMouseDown; + + LLProgressView *mProgressView; + + LLFrameTimer mToolTipFadeTimer; + LLPanel* mToolTip; + std::string mLastToolTipMessage; + LLRect mToolTipStickyRect; // Once a tool tip is shown, it will stay visible until the mouse leaves this rect. + + BOOL mMouseInWindow; // True if the mouse is over our window or if we have captured the mouse. + BOOL mFocusCycleMode; BOOL mAllowMouseDragging; LLFrameTimer mMouseDownTimer; - typedef std::set > view_handle_set_t; - view_handle_set_t mMouseHoverViews; - - // Variables used for tool override switching based on modifier keys. JC - MASK mLastMask; // used to detect changes in modifier mask - LLTool* mToolStored; // the tool we're overriding - BOOL mHideCursorPermanent; // true during drags, mouselook - BOOL mCursorHidden; - LLPickInfo mLastPick; - std::vector mPicks; - LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen) - LLTimer mPickTimer; // timer for scheduling n picks per second - - std::string mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta" - - BOOL mIgnoreActivate; - - std::string mInitAlert; // Window / GL initialization requires an alert - - LLHandle mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world - LLHandle mToolBarHolder; // container for toolbars - LLHandle mHintHolder; // container for hints - LLHandle mLoginPanelHolder; // container for login panel - LLPopupView* mPopupView; // container for transient popups - - class LLDebugText* mDebugText; // Internal class for debug text - - bool mResDirty; - bool mStatesDirty; - U32 mCurrResolutionIndex; - - std::unique_ptr mWindowListener; - std::unique_ptr mViewerWindowListener; - - // Object temporarily hovered over while dragging - LLPointer mDragHoveredObject; - - static LLTrace::SampleStatHandle<> sMouseVelocityStat; + typedef std::set > view_handle_set_t; + view_handle_set_t mMouseHoverViews; + + // Variables used for tool override switching based on modifier keys. JC + MASK mLastMask; // used to detect changes in modifier mask + LLTool* mToolStored; // the tool we're overriding + BOOL mHideCursorPermanent; // true during drags, mouselook + BOOL mCursorHidden; + LLPickInfo mLastPick; + std::vector mPicks; + LLRect mPickScreenRegion; // area of frame buffer for rendering pick frames (generally follows mouse to avoid going offscreen) + LLTimer mPickTimer; // timer for scheduling n picks per second + + std::string mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta" + + BOOL mIgnoreActivate; + + std::string mInitAlert; // Window / GL initialization requires an alert + + LLHandle mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world + LLHandle mToolBarHolder; // container for toolbars + LLHandle mHintHolder; // container for hints + LLHandle mLoginPanelHolder; // container for login panel + LLPopupView* mPopupView; // container for transient popups + + class LLDebugText* mDebugText; // Internal class for debug text + + bool mResDirty; + bool mStatesDirty; + U32 mCurrResolutionIndex; + + std::unique_ptr mWindowListener; + std::unique_ptr mViewerWindowListener; + + // Object temporarily hovered over while dragging + LLPointer mDragHoveredObject; + + static LLTrace::SampleStatHandle<> sMouseVelocityStat; }; // // Globals // -extern LLViewerWindow* gViewerWindow; +extern LLViewerWindow* gViewerWindow; -extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true -extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away +extern LLFrameTimer gAwayTimer; // tracks time before setting the avatar away state to true +extern LLFrameTimer gAwayTriggerTimer; // how long the avatar has been away extern LLViewerObject* gDebugRaycastObject; extern LLVector4a gDebugRaycastIntersection; -extern LLVOPartGroup* gDebugRaycastParticle; -extern LLVector4a gDebugRaycastParticleIntersection; +extern LLVOPartGroup* gDebugRaycastParticle; +extern LLVector4a gDebugRaycastParticleIntersection; extern LLVector2 gDebugRaycastTexCoord; extern LLVector4a gDebugRaycastNormal; extern LLVector4a gDebugRaycastTangent; -extern S32 gDebugRaycastFaceHit; -extern LLVector4a gDebugRaycastStart; -extern LLVector4a gDebugRaycastEnd; - -extern BOOL gDisplayCameraPos; -extern BOOL gDisplayWindInfo; -extern BOOL gDisplayFOV; -extern BOOL gDisplayBadge; +extern S32 gDebugRaycastFaceHit; +extern LLVector4a gDebugRaycastStart; +extern LLVector4a gDebugRaycastEnd; + +extern BOOL gDisplayCameraPos; +extern BOOL gDisplayWindInfo; +extern BOOL gDisplayFOV; +extern BOOL gDisplayBadge; #endif diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 8d3b5cc8a5..1ffbf20410 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvlcomposition.cpp * @brief Viewer-side representation of a composition layer... * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -161,7 +161,7 @@ LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset) // Assume both the the material and texture were fetched in the same way // using the same UUID. However, we may not know at this point which one // will load. - return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null; + return mDetailTextures[asset] ? mDetailTextures[asset]->getID() : LLUUID::null; } LLPointer fetch_terrain_texture(const LLUUID& id) @@ -183,9 +183,9 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) unboost_minimap_texture(mDetailTextures[asset]); unboost_minimap_material(mDetailMaterials[asset]); - // This is terrain texture, but we are not setting it as BOOST_TERRAIN - // since we will be manipulating it later as needed. - mDetailTextures[asset] = fetch_terrain_texture(id); + // This is terrain texture, but we are not setting it as BOOST_TERRAIN + // since we will be manipulating it later as needed. + mDetailTextures[asset] = fetch_terrain_texture(id); LLPointer& mat = mDetailMaterials[asset]; mat = id.isNull() ? nullptr : gGLTFMaterialList.getMaterial(id); mMaterialTexturesSet[asset] = false; @@ -193,7 +193,7 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) LLTerrainMaterials::Type LLTerrainMaterials::getMaterialType() { - LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_ZONE_SCOPED; const BOOL use_textures = texturesReady(false, false) || !materialsReady(false, false); return use_textures ? Type::TEXTURE : Type::PBR; @@ -372,23 +372,23 @@ const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT] LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : LLTerrainMaterials(), - LLViewerLayer(width, scale) + LLViewerLayer(width, scale) { - // Load Terrain Textures - Original ones + // Load Terrain Textures - Original ones const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures(); for (S32 i = 0; i < ASSET_COUNT; ++i) { setDetailAssetID(i, default_textures[i]); } - mSurfacep = surfacep; + mSurfacep = surfacep; - // Initialize the texture matrix to defaults. - for (S32 i = 0; i < CORNER_COUNT; ++i) - { - mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight"); - mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange"); - } + // Initialize the texture matrix to defaults. + for (S32 i = 0; i < CORNER_COUNT; ++i) + { + mStartHeight[i] = gSavedSettings.getF32("TerrainColorStartHeight"); + mHeightRange[i] = gSavedSettings.getF32("TerrainColorHeightRange"); + } } @@ -400,117 +400,117 @@ LLVLComposition::~LLVLComposition() void LLVLComposition::setSurface(LLSurface *surfacep) { - mSurfacep = surfacep; + mSurfacep = surfacep; } BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, - const F32 width, const F32 height) + const F32 width, const F32 height) { - if (!mParamsReady) - { - // All the parameters haven't been set yet (we haven't gotten the message from the sim) - return FALSE; - } - - llassert(mSurfacep); - - if (!mSurfacep || !mSurfacep->getRegion()) - { - // We don't always have the region yet here.... - return FALSE; - } - - S32 x_begin, y_begin, x_end, y_end; - - x_begin = ll_round( x * mScaleInv ); - y_begin = ll_round( y * mScaleInv ); - x_end = ll_round( (x + width) * mScaleInv ); - y_end = ll_round( (y + width) * mScaleInv ); - - if (x_end > mWidth) - { - x_end = mWidth; - } - if (y_end > mWidth) - { - y_end = mWidth; - } - - LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle()); - - // For perlin noise generation... - const F32 slope_squared = 1.5f*1.5f; - const F32 xyScale = 4.9215f; //0.93284f; - const F32 zScale = 4; //0.92165f; - const F32 z_offset = 0.f; - const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus - // simple height) - - const F32 xyScaleInv = (1.f / xyScale); - const F32 zScaleInv = (1.f / zScale); - - const F32 inv_width = 1.f/mWidth; - - // OK, for now, just have the composition value equal the height at the point. - for (S32 j = y_begin; j < y_end; j++) - { - for (S32 i = x_begin; i < x_end; i++) - { - - F32 vec[3]; - F32 vec1[3]; - F32 twiddle; - - // Bilinearly interpolate the start height and height range of the textures - F32 start_height = bilinear(mStartHeight[SOUTHWEST], - mStartHeight[SOUTHEAST], - mStartHeight[NORTHWEST], - mStartHeight[NORTHEAST], - i*inv_width, j*inv_width); // These will be bilinearly interpolated - F32 height_range = bilinear(mHeightRange[SOUTHWEST], - mHeightRange[SOUTHEAST], - mHeightRange[NORTHWEST], - mHeightRange[NORTHEAST], - i*inv_width, j*inv_width); // These will be bilinearly interpolated - - LLVector3 location(i*mScale, j*mScale, 0.f); - - F32 height = mSurfacep->resolveHeightRegion(location) + z_offset; - - // Step 0: Measure the exact height at this texel - vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice - vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; - vec[2] = height*zScaleInv; - // - // Choose material value by adding to the exact height a random value - // - vec1[0] = vec[0]*(0.2222222222f); - vec1[1] = vec[1]*(0.2222222222f); - vec1[2] = vec[2]*(0.2222222222f); - twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions - - twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component - twiddle *= noise_magnitude; - - F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range; - - scaled_noisy_height = llmax(0.f, scaled_noisy_height); - scaled_noisy_height = llmin(3.f, scaled_noisy_height); - *(mDatap + i + j*mWidth) = scaled_noisy_height; - } - } - return TRUE; + if (!mParamsReady) + { + // All the parameters haven't been set yet (we haven't gotten the message from the sim) + return FALSE; + } + + llassert(mSurfacep); + + if (!mSurfacep || !mSurfacep->getRegion()) + { + // We don't always have the region yet here.... + return FALSE; + } + + S32 x_begin, y_begin, x_end, y_end; + + x_begin = ll_round( x * mScaleInv ); + y_begin = ll_round( y * mScaleInv ); + x_end = ll_round( (x + width) * mScaleInv ); + y_end = ll_round( (y + width) * mScaleInv ); + + if (x_end > mWidth) + { + x_end = mWidth; + } + if (y_end > mWidth) + { + y_end = mWidth; + } + + LLVector3d origin_global = from_region_handle(mSurfacep->getRegion()->getHandle()); + + // For perlin noise generation... + const F32 slope_squared = 1.5f*1.5f; + const F32 xyScale = 4.9215f; //0.93284f; + const F32 zScale = 4; //0.92165f; + const F32 z_offset = 0.f; + const F32 noise_magnitude = 2.f; // Degree to which noise modulates composition layer (versus + // simple height) + + const F32 xyScaleInv = (1.f / xyScale); + const F32 zScaleInv = (1.f / zScale); + + const F32 inv_width = 1.f/mWidth; + + // OK, for now, just have the composition value equal the height at the point. + for (S32 j = y_begin; j < y_end; j++) + { + for (S32 i = x_begin; i < x_end; i++) + { + + F32 vec[3]; + F32 vec1[3]; + F32 twiddle; + + // Bilinearly interpolate the start height and height range of the textures + F32 start_height = bilinear(mStartHeight[SOUTHWEST], + mStartHeight[SOUTHEAST], + mStartHeight[NORTHWEST], + mStartHeight[NORTHEAST], + i*inv_width, j*inv_width); // These will be bilinearly interpolated + F32 height_range = bilinear(mHeightRange[SOUTHWEST], + mHeightRange[SOUTHEAST], + mHeightRange[NORTHWEST], + mHeightRange[NORTHEAST], + i*inv_width, j*inv_width); // These will be bilinearly interpolated + + LLVector3 location(i*mScale, j*mScale, 0.f); + + F32 height = mSurfacep->resolveHeightRegion(location) + z_offset; + + // Step 0: Measure the exact height at this texel + vec[0] = (F32)(origin_global.mdV[VX]+location.mV[VX])*xyScaleInv; // Adjust to non-integer lattice + vec[1] = (F32)(origin_global.mdV[VY]+location.mV[VY])*xyScaleInv; + vec[2] = height*zScaleInv; + // + // Choose material value by adding to the exact height a random value + // + vec1[0] = vec[0]*(0.2222222222f); + vec1[1] = vec[1]*(0.2222222222f); + vec1[2] = vec[2]*(0.2222222222f); + twiddle = noise2(vec1)*6.5f; // Low freq component for large divisions + + twiddle += turbulence2(vec, 2)*slope_squared; // High frequency component + twiddle *= noise_magnitude; + + F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range; + + scaled_noisy_height = llmax(0.f, scaled_noisy_height); + scaled_noisy_height = llmin(3.f, scaled_noisy_height); + *(mDatap + i + j*mWidth) = scaled_noisy_height; + } + } + return TRUE; } LLTerrainMaterials gLocalTerrainMaterials; BOOL LLVLComposition::generateComposition() { - if (!mParamsReady) - { - // All the parameters haven't been set yet (we haven't gotten the message from the sim) - return FALSE; - } + if (!mParamsReady) + { + // All the parameters haven't been set yet (we haven't gotten the message from the sim) + return FALSE; + } return LLTerrainMaterials::generateMaterials(); } @@ -618,22 +618,22 @@ namespace }; BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, - const F32 width, const F32 height) + const F32 width, const F32 height) { - LL_PROFILE_ZONE_SCOPED - llassert(mSurfacep); - llassert(x >= 0.f); - llassert(y >= 0.f); + LL_PROFILE_ZONE_SCOPED + llassert(mSurfacep); + llassert(x >= 0.f); + llassert(y >= 0.f); - /////////////////////////// - // - // Generate raw data arrays for surface textures - // - // + /////////////////////////// + // + // Generate raw data arrays for surface textures + // + // - // These have already been validated by generateComposition. - U8* st_data[ASSET_COUNT]; - S32 st_data_size[ASSET_COUNT]; // for debugging + // These have already been validated by generateComposition. + U8* st_data[ASSET_COUNT]; + S32 st_data_size[ASSET_COUNT]; // for debugging const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR; if (use_textures) @@ -645,11 +645,11 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, if (!materialsReady(true, true)) { return FALSE; } } - for (S32 i = 0; i < ASSET_COUNT; i++) - { - if (mRawImages[i].isNull()) - { - // Read back a raw image for this discard level, if it exists + for (S32 i = 0; i < ASSET_COUNT; i++) + { + if (mRawImages[i].isNull()) + { + // Read back a raw image for this discard level, if it exists LLViewerFetchedTexture* tex; LLViewerFetchedTexture* tex_emissive; // Can be null bool has_base_color_factor; @@ -721,14 +721,14 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, raw_emissive = newraw_emissive; } } - if (has_base_color_factor || + if (has_base_color_factor || raw_emissive || has_alpha || tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE || - tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE || - tex->getComponents() != 3) - { - LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); + tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE || + tex->getComponents() != 3) + { + LLPointer newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); if (has_alpha) { // Approximate the water underneath terrain alpha with solid water color @@ -738,7 +738,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, MAX_WATER_COLOR.mV[VZ], 255); } - newraw->composite(mRawImagesBaseColor[i]); + newraw->composite(mRawImagesBaseColor[i]); if (has_base_color_factor) { newraw->tint(base_color_factor); @@ -749,8 +749,8 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, newraw->addEmissive(raw_emissive); } - mRawImages[i] = newraw; // deletes old - } + mRawImages[i] = newraw; // deletes old + } if (delete_raw_post) { @@ -764,150 +764,150 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, // Remove intermediary image references mRawImagesBaseColor[i] = nullptr; mRawImagesEmissive[i] = nullptr; - } - st_data[i] = mRawImages[i]->getData(); - st_data_size[i] = mRawImages[i]->getDataSize(); - } - - /////////////////////////////////////// - // - // Generate and clamp x/y bounding box. - // - // - - S32 x_begin, y_begin, x_end, y_end; - x_begin = (S32)(x * mScaleInv); - y_begin = (S32)(y * mScaleInv); - x_end = ll_round( (x + width) * mScaleInv ); - y_end = ll_round( (y + width) * mScaleInv ); - - if (x_end > mWidth) - { + } + st_data[i] = mRawImages[i]->getData(); + st_data_size[i] = mRawImages[i]->getDataSize(); + } + + /////////////////////////////////////// + // + // Generate and clamp x/y bounding box. + // + // + + S32 x_begin, y_begin, x_end, y_end; + x_begin = (S32)(x * mScaleInv); + y_begin = (S32)(y * mScaleInv); + x_end = ll_round( (x + width) * mScaleInv ); + y_end = ll_round( (y + width) * mScaleInv ); + + if (x_end > mWidth) + { llassert(false); - x_end = mWidth; - } - if (y_end > mWidth) - { + x_end = mWidth; + } + if (y_end > mWidth) + { llassert(false); - y_end = mWidth; - } - - - /////////////////////////////////////////// - // - // Generate target texture information, stride ratios. - // - // - - LLViewerTexture *texturep; - U32 tex_width, tex_height, tex_comps; - U32 tex_stride; - F32 tex_x_scalef, tex_y_scalef; - S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end; - F32 tex_x_ratiof, tex_y_ratiof; - - texturep = mSurfacep->getSTexture(); - tex_width = texturep->getWidth(); - tex_height = texturep->getHeight(); - tex_comps = texturep->getComponents(); - tex_stride = tex_width * tex_comps; - - U32 st_comps = 3; - U32 st_width = BASE_SIZE; - U32 st_height = BASE_SIZE; - - if (tex_comps != st_comps) - { + y_end = mWidth; + } + + + /////////////////////////////////////////// + // + // Generate target texture information, stride ratios. + // + // + + LLViewerTexture *texturep; + U32 tex_width, tex_height, tex_comps; + U32 tex_stride; + F32 tex_x_scalef, tex_y_scalef; + S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end; + F32 tex_x_ratiof, tex_y_ratiof; + + texturep = mSurfacep->getSTexture(); + tex_width = texturep->getWidth(); + tex_height = texturep->getHeight(); + tex_comps = texturep->getComponents(); + tex_stride = tex_width * tex_comps; + + U32 st_comps = 3; + U32 st_width = BASE_SIZE; + U32 st_height = BASE_SIZE; + + if (tex_comps != st_comps) + { llassert(false); - return FALSE; - } - - tex_x_scalef = (F32)tex_width / (F32)mWidth; - tex_y_scalef = (F32)tex_height / (F32)mWidth; - tex_x_begin = (S32)((F32)x_begin * tex_x_scalef); - tex_y_begin = (S32)((F32)y_begin * tex_y_scalef); - tex_x_end = (S32)((F32)x_end * tex_x_scalef); - tex_y_end = (S32)((F32)y_end * tex_y_scalef); - - tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width; - tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height; - - LLPointer raw = new LLImageRaw(tex_width, tex_height, tex_comps); - U8 *rawp = raw->getData(); - - F32 st_x_stride, st_y_stride; - st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); - st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); - - llassert(st_x_stride > 0.f); - llassert(st_y_stride > 0.f); - //////////////////////////////// - // - // Iterate through the target texture, striding through the - // subtextures and interpolating appropriately. - // - // - - F32 sti, stj; - S32 st_offset; - sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width)); - stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height)); - - st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps; - for (S32 j = tex_y_begin; j < tex_y_end; j++) - { - U32 offset = j * tex_stride + tex_x_begin * tex_comps; - sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width); - for (S32 i = tex_x_begin; i < tex_x_end; i++) - { - S32 tex0, tex1; - F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof); - - tex0 = llfloor( composition ); - tex0 = llclamp(tex0, 0, 3); - composition -= tex0; - tex1 = tex0 + 1; - tex1 = llclamp(tex1, 0, 3); - - st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; - for (U32 k = 0; k < tex_comps; k++) - { - // Linearly interpolate based on composition. - if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1]) - { - // SJB: This shouldn't be happening, but does... Rounding error? - //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL; - //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL; - } - else - { - F32 a = *(st_data[tex0] + st_offset); - F32 b = *(st_data[tex1] + st_offset); - rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) ); - } - offset++; - st_offset++; - } - - sti += st_x_stride; - if (sti >= st_width) - { - sti -= st_width; - } - } - - stj += st_y_stride; - if (stj >= st_height) - { - stj -= st_height; - } - } - - if (!texturep->hasGLTexture()) - { - texturep->createGLTexture(0, raw); - } - texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); + return FALSE; + } + + tex_x_scalef = (F32)tex_width / (F32)mWidth; + tex_y_scalef = (F32)tex_height / (F32)mWidth; + tex_x_begin = (S32)((F32)x_begin * tex_x_scalef); + tex_y_begin = (S32)((F32)y_begin * tex_y_scalef); + tex_x_end = (S32)((F32)x_end * tex_x_scalef); + tex_y_end = (S32)((F32)y_end * tex_y_scalef); + + tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width; + tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height; + + LLPointer raw = new LLImageRaw(tex_width, tex_height, tex_comps); + U8 *rawp = raw->getData(); + + F32 st_x_stride, st_y_stride; + st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); + st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); + + llassert(st_x_stride > 0.f); + llassert(st_y_stride > 0.f); + //////////////////////////////// + // + // Iterate through the target texture, striding through the + // subtextures and interpolating appropriately. + // + // + + F32 sti, stj; + S32 st_offset; + sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width)); + stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height)); + + st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps; + for (S32 j = tex_y_begin; j < tex_y_end; j++) + { + U32 offset = j * tex_stride + tex_x_begin * tex_comps; + sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width); + for (S32 i = tex_x_begin; i < tex_x_end; i++) + { + S32 tex0, tex1; + F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof); + + tex0 = llfloor( composition ); + tex0 = llclamp(tex0, 0, 3); + composition -= tex0; + tex1 = tex0 + 1; + tex1 = llclamp(tex1, 0, 3); + + st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; + for (U32 k = 0; k < tex_comps; k++) + { + // Linearly interpolate based on composition. + if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1]) + { + // SJB: This shouldn't be happening, but does... Rounding error? + //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL; + //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL; + } + else + { + F32 a = *(st_data[tex0] + st_offset); + F32 b = *(st_data[tex1] + st_offset); + rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) ); + } + offset++; + st_offset++; + } + + sti += st_x_stride; + if (sti >= st_width) + { + sti -= st_width; + } + } + + stj += st_y_stride; + if (stj >= st_height) + { + stj -= st_height; + } + } + + if (!texturep->hasGLTexture()) + { + texturep->createGLTexture(0, raw); + } + texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); // Un-boost detail textures (will get re-boosted if rendering in high detail) for (S32 i = 0; i < ASSET_COUNT; i++) @@ -920,38 +920,38 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { unboost_minimap_material(mDetailMaterials[i]); } - - return TRUE; + + return TRUE; } F32 LLVLComposition::getStartHeight(S32 corner) { - return mStartHeight[corner]; + return mStartHeight[corner]; } void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id) { - if (id.isNull()) - { + if (id.isNull()) + { return; } LLTerrainMaterials::setDetailAssetID(asset, id); - mRawImages[asset] = NULL; - mRawImagesBaseColor[asset] = NULL; - mRawImagesEmissive[asset] = NULL; + mRawImages[asset] = NULL; + mRawImagesBaseColor[asset] = NULL; + mRawImagesEmissive[asset] = NULL; } void LLVLComposition::setStartHeight(S32 corner, const F32 start_height) { - mStartHeight[corner] = start_height; + mStartHeight[corner] = start_height; } F32 LLVLComposition::getHeightRange(S32 corner) { - return mHeightRange[corner]; + return mHeightRange[corner]; } void LLVLComposition::setHeightRange(S32 corner, const F32 range) { - mHeightRange[corner] = range; + mHeightRange[corner] = range; } diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index 5db832e034..e0b08a3aca 100644 --- a/indra/newview/llvlcomposition.h +++ b/indra/newview/llvlcomposition.h @@ -1,25 +1,25 @@ -/** +/** * @file llvlcomposition.h * @brief Viewer-side representation of a composition layer... * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -40,13 +40,13 @@ class LLFetchedGLTFMaterial; class LLTerrainMaterials { public: - friend class LLDrawPoolTerrain; + friend class LLDrawPoolTerrain; LLTerrainMaterials(); virtual ~LLTerrainMaterials(); - // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. - // So we need to compress heights into this range. + // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. + // So we need to compress heights into this range. static const S32 ASSET_COUNT = 4; enum class Type @@ -60,8 +60,8 @@ public: void boost(); - virtual LLUUID getDetailAssetID(S32 asset); - virtual void setDetailAssetID(S32 asset, const LLUUID& id); + virtual LLUUID getDetailAssetID(S32 asset); + virtual void setDetailAssetID(S32 asset, const LLUUID& id); Type getMaterialType(); bool texturesReady(bool boost, bool strict); // strict = true -> all materials must be sufficiently loaded @@ -74,8 +74,8 @@ protected: // strict = true -> all materials must be sufficiently loaded // strict = false -> at least one material must be loaded static bool materialReady(LLPointer& mat, bool& textures_set, bool boost, bool strict); - LLPointer mDetailTextures[ASSET_COUNT]; - LLPointer mDetailMaterials[ASSET_COUNT]; + LLPointer mDetailTextures[ASSET_COUNT]; + LLPointer mDetailMaterials[ASSET_COUNT]; bool mMaterialTexturesSet[ASSET_COUNT]; }; @@ -85,63 +85,63 @@ extern LLTerrainMaterials gLocalTerrainMaterials; class LLVLComposition : public LLTerrainMaterials, public LLViewerLayer { public: - // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. - // So we need to compress heights into this range. + // Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc. + // So we need to compress heights into this range. static const S32 ASSET_COUNT = 4; - static const LLUUID (&getDefaultTextures())[ASSET_COUNT]; + static const LLUUID (&getDefaultTextures())[ASSET_COUNT]; - LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); - /*virtual*/ ~LLVLComposition(); + LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); + /*virtual*/ ~LLVLComposition(); - void setSurface(LLSurface *surfacep); + void setSurface(LLSurface *surfacep); - // Viewer side hack to generate composition values - BOOL generateHeights(const F32 x, const F32 y, const F32 width, const F32 height); - BOOL generateComposition(); - // Generate texture from composition values. - BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height); + // Viewer side hack to generate composition values + BOOL generateHeights(const F32 x, const F32 y, const F32 width, const F32 height); + BOOL generateComposition(); + // Generate texture from composition values. + BOOL generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height); - // Use these as indeces ito the get/setters below that use 'corner' - enum ECorner - { - SOUTHWEST = 0, - SOUTHEAST = 1, - NORTHWEST = 2, - NORTHEAST = 3, - CORNER_COUNT = 4 - }; + // Use these as indeces ito the get/setters below that use 'corner' + enum ECorner + { + SOUTHWEST = 0, + SOUTHEAST = 1, + NORTHWEST = 2, + NORTHEAST = 3, + CORNER_COUNT = 4 + }; - void setDetailAssetID(S32 asset, const LLUUID& id) override; - F32 getStartHeight(S32 corner); - F32 getHeightRange(S32 corner); + void setDetailAssetID(S32 asset, const LLUUID& id) override; + F32 getStartHeight(S32 corner); + F32 getHeightRange(S32 corner); - void setStartHeight(S32 corner, F32 start_height); - void setHeightRange(S32 corner, F32 range); + void setStartHeight(S32 corner, F32 start_height); + void setHeightRange(S32 corner, F32 range); - friend class LLVOSurfacePatch; - friend class LLDrawPoolTerrain; - void setParamsReady() { mParamsReady = TRUE; } - BOOL getParamsReady() const { return mParamsReady; } + friend class LLVOSurfacePatch; + friend class LLDrawPoolTerrain; + void setParamsReady() { mParamsReady = TRUE; } + BOOL getParamsReady() const { return mParamsReady; } protected: static bool textureReady(LLPointer& tex, bool boost = false); static bool materialReady(LLPointer& mat, bool& textures_set, bool boost = false); - BOOL mParamsReady = FALSE; - LLSurface *mSurfacep; + BOOL mParamsReady = FALSE; + LLSurface *mSurfacep; // Final minimap raw images - LLPointer mRawImages[LLTerrainMaterials::ASSET_COUNT]; + LLPointer mRawImages[LLTerrainMaterials::ASSET_COUNT]; // Only non-null during minimap tile generation - LLPointer mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT]; - LLPointer mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT]; + LLPointer mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT]; + LLPointer mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT]; - F32 mStartHeight[CORNER_COUNT]; - F32 mHeightRange[CORNER_COUNT]; + F32 mStartHeight[CORNER_COUNT]; + F32 mHeightRange[CORNER_COUNT]; - F32 mTexScaleX = 16.f; - F32 mTexScaleY = 16.f; + F32 mTexScaleX = 16.f; + F32 mTexScaleY = 16.f; }; #endif //LL_LLVLCOMPOSITION_H diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index d8ac3613bc..0366106aad 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -5,21 +5,21 @@ * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -49,7 +49,7 @@ #include "llexperiencecache.h" #include "llphysicsmotion.h" #include "llviewercontrol.h" -#include "llcallingcard.h" // IDEVO for LLAvatarTracker +#include "llcallingcard.h" // IDEVO for LLAvatarTracker #include "lldrawpoolavatar.h" #include "lldriverparam.h" #include "llpolyskeletaldistortion.h" @@ -60,7 +60,7 @@ #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llhudnametag.h" -#include "llhudtext.h" // for mText/mDebugText +#include "llhudtext.h" // for mText/mDebugText #include "llimview.h" #include "llinitparam.h" #include "llkeyframefallmotion.h" @@ -141,30 +141,30 @@ using namespace LLAvatarAppearanceDefines; // Global constants //----------------------------------------------------------------------------- const LLUUID ANIM_AGENT_BODY_NOISE = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise" -const LLUUID ANIM_AGENT_BREATHE_ROT = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot" -const LLUUID ANIM_AGENT_EDITING = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing" -const LLUUID ANIM_AGENT_EYE = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye" +const LLUUID ANIM_AGENT_BREATHE_ROT = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot" +const LLUUID ANIM_AGENT_EDITING = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing" +const LLUUID ANIM_AGENT_EYE = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye" const LLUUID ANIM_AGENT_FLY_ADJUST = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e"); //"fly_adjust" -const LLUUID ANIM_AGENT_HAND_MOTION = LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578"); //"hand_motion" +const LLUUID ANIM_AGENT_HAND_MOTION = LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578"); //"hand_motion" const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"); //"head_rot" const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix" const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target" -const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" +const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion" //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- -const F32 DELTA_TIME_MIN = 0.01f; // we clamp measured delta_time to this -const F32 DELTA_TIME_MAX = 0.2f; // range to insure stability of computations. +const F32 DELTA_TIME_MIN = 0.01f; // we clamp measured delta_time to this +const F32 DELTA_TIME_MAX = 0.2f; // range to insure stability of computations. -const F32 PELVIS_LAG_FLYING = 0.22f;// pelvis follow half life while flying -const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking +const F32 PELVIS_LAG_FLYING = 0.22f;// pelvis follow half life while flying +const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking const F32 PELVIS_LAG_MOUSELOOK = 0.15f; const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f; -const F32 TORSO_NOISE_AMOUNT = 1.0f; // Amount of deviation from up-axis, in degrees -const F32 TORSO_NOISE_SPEED = 0.2f; // Time scale factor on torso noise. +const F32 TORSO_NOISE_AMOUNT = 1.0f; // Amount of deviation from up-axis, in degrees +const F32 TORSO_NOISE_SPEED = 0.2f; // Time scale factor on torso noise. const F32 BREATHE_ROT_MOTION_STRENGTH = 0.05f; @@ -211,9 +211,9 @@ const S32 MIN_NONTUNED_AVS = 5; enum ERenderName { - RENDER_NAME_NEVER, - RENDER_NAME_ALWAYS, - RENDER_NAME_FADE + RENDER_NAME_NEVER, + RENDER_NAME_ALWAYS, + RENDER_NAME_FADE }; #define JELLYDOLLS_SHOULD_IMPOSTOR @@ -224,12 +224,12 @@ enum ERenderName struct LLTextureMaskData { - LLTextureMaskData( const LLUUID& id ) : - mAvatarID(id), - mLastDiscardLevel(S32_MAX) - {} - LLUUID mAvatarID; - S32 mLastDiscardLevel; + LLTextureMaskData( const LLUUID& id ) : + mAvatarID(id), + mLastDiscardLevel(S32_MAX) + {} + LLUUID mAvatarID; + S32 mLastDiscardLevel; }; /********************************************************************************* @@ -241,22 +241,22 @@ struct LLTextureMaskData struct LLAppearanceMessageContents: public LLRefCount { - LLAppearanceMessageContents(): - mAppearanceVersion(-1), - mParamAppearanceVersion(-1), - mCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) - { - } - LLTEContents mTEContents; - S32 mAppearanceVersion; - S32 mParamAppearanceVersion; - S32 mCOFVersion; - // For future use: - //U32 appearance_flags = 0; - std::vector mParamWeights; - std::vector mParams; - LLVector3 mHoverOffset; - bool mHoverOffsetWasSet; + LLAppearanceMessageContents(): + mAppearanceVersion(-1), + mParamAppearanceVersion(-1), + mCOFVersion(LLViewerInventoryCategory::VERSION_UNKNOWN) + { + } + LLTEContents mTEContents; + S32 mAppearanceVersion; + S32 mParamAppearanceVersion; + S32 mCOFVersion; + // For future use: + //U32 appearance_flags = 0; + std::vector mParamWeights; + std::vector mParams; + LLVector3 mHoverOffset; + bool mHoverOffsetWasSet; }; @@ -264,317 +264,317 @@ struct LLAppearanceMessageContents: public LLRefCount // class LLBodyNoiseMotion //----------------------------------------------------------------------------- class LLBodyNoiseMotion : - public LLMotion + public LLMotion { public: - // Constructor - LLBodyNoiseMotion(const LLUUID &id) - : LLMotion(id) - { - mName = "body_noise"; - mTorsoState = new LLJointState; - } + // Constructor + LLBodyNoiseMotion(const LLUUID &id) + : LLMotion(id) + { + mName = "body_noise"; + mTorsoState = new LLJointState; + } - // Destructor - virtual ~LLBodyNoiseMotion() { } + // Destructor + virtual ~LLBodyNoiseMotion() { } public: - //------------------------------------------------------------------------- - // functions to support MotionController and MotionRegistry - //------------------------------------------------------------------------- - // static constructor - // all subclasses must implement such a function and register it - static LLMotion *create(const LLUUID &id) { return new LLBodyNoiseMotion(id); } + //------------------------------------------------------------------------- + // functions to support MotionController and MotionRegistry + //------------------------------------------------------------------------- + // static constructor + // all subclasses must implement such a function and register it + static LLMotion *create(const LLUUID &id) { return new LLBodyNoiseMotion(id); } public: - //------------------------------------------------------------------------- - // animation callbacks to be implemented by subclasses - //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + // animation callbacks to be implemented by subclasses + //------------------------------------------------------------------------- - // motions must specify whether or not they loop - virtual BOOL getLoop() { return TRUE; } + // motions must specify whether or not they loop + virtual BOOL getLoop() { return TRUE; } - // motions must report their total duration - virtual F32 getDuration() { return 0.0; } + // motions must report their total duration + virtual F32 getDuration() { return 0.0; } - // motions must report their "ease in" duration - virtual F32 getEaseInDuration() { return 0.0; } + // motions must report their "ease in" duration + virtual F32 getEaseInDuration() { return 0.0; } - // motions must report their "ease out" duration. - virtual F32 getEaseOutDuration() { return 0.0; } + // motions must report their "ease out" duration. + virtual F32 getEaseOutDuration() { return 0.0; } - // motions must report their priority - virtual LLJoint::JointPriority getPriority() { return LLJoint::HIGH_PRIORITY; } + // motions must report their priority + virtual LLJoint::JointPriority getPriority() { return LLJoint::HIGH_PRIORITY; } - virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; } + virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; } - // called to determine when a motion should be activated/deactivated based on avatar pixel coverage - virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BODY_NOISE; } + // called to determine when a motion should be activated/deactivated based on avatar pixel coverage + virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BODY_NOISE; } - // run-time (post constructor) initialization, - // called after parameters have been set - // must return true to indicate success and be available for activation - virtual LLMotionInitStatus onInitialize(LLCharacter *character) - { - if( !mTorsoState->setJoint( character->getJoint("mTorso") )) - { - return STATUS_FAILURE; - } + // run-time (post constructor) initialization, + // called after parameters have been set + // must return true to indicate success and be available for activation + virtual LLMotionInitStatus onInitialize(LLCharacter *character) + { + if( !mTorsoState->setJoint( character->getJoint("mTorso") )) + { + return STATUS_FAILURE; + } - mTorsoState->setUsage(LLJointState::ROT); + mTorsoState->setUsage(LLJointState::ROT); - addJointState( mTorsoState ); - return STATUS_SUCCESS; - } + addJointState( mTorsoState ); + return STATUS_SUCCESS; + } - // called when a motion is activated - // must return TRUE to indicate success, or else - // it will be deactivated - virtual BOOL onActivate() { return TRUE; } + // called when a motion is activated + // must return TRUE to indicate success, or else + // it will be deactivated + virtual BOOL onActivate() { return TRUE; } - // called per time step - // must return TRUE while it is active, and - // must return FALSE when the motion is completed. - virtual BOOL onUpdate(F32 time, U8* joint_mask) - { + // called per time step + // must return TRUE while it is active, and + // must return FALSE when the motion is completed. + virtual BOOL onUpdate(F32 time, U8* joint_mask) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - F32 nx[2]; - nx[0]=time*TORSO_NOISE_SPEED; - nx[1]=0.0f; - F32 ny[2]; - ny[0]=0.0f; - ny[1]=time*TORSO_NOISE_SPEED; - F32 noiseX = noise2(nx); - F32 noiseY = noise2(ny); - - F32 rx = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseX / 0.42f; - F32 ry = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseY / 0.42f; - LLQuaternion tQn; - tQn.setQuat( rx, ry, 0.0f ); - mTorsoState->setRotation( tQn ); - - return TRUE; - } - - // called when a motion is deactivated - virtual void onDeactivate() {} + F32 nx[2]; + nx[0]=time*TORSO_NOISE_SPEED; + nx[1]=0.0f; + F32 ny[2]; + ny[0]=0.0f; + ny[1]=time*TORSO_NOISE_SPEED; + F32 noiseX = noise2(nx); + F32 noiseY = noise2(ny); + + F32 rx = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseX / 0.42f; + F32 ry = TORSO_NOISE_AMOUNT * DEG_TO_RAD * noiseY / 0.42f; + LLQuaternion tQn; + tQn.setQuat( rx, ry, 0.0f ); + mTorsoState->setRotation( tQn ); + + return TRUE; + } + + // called when a motion is deactivated + virtual void onDeactivate() {} private: - //------------------------------------------------------------------------- - // joint states to be animated - //------------------------------------------------------------------------- - LLPointer mTorsoState; + //------------------------------------------------------------------------- + // joint states to be animated + //------------------------------------------------------------------------- + LLPointer mTorsoState; }; //----------------------------------------------------------------------------- // class LLBreatheMotionRot //----------------------------------------------------------------------------- class LLBreatheMotionRot : - public LLMotion + public LLMotion { public: - // Constructor - LLBreatheMotionRot(const LLUUID &id) : - LLMotion(id), - mBreatheRate(1.f), - mCharacter(NULL) - { - mName = "breathe_rot"; - mChestState = new LLJointState; - } - - // Destructor - virtual ~LLBreatheMotionRot() {} + // Constructor + LLBreatheMotionRot(const LLUUID &id) : + LLMotion(id), + mBreatheRate(1.f), + mCharacter(NULL) + { + mName = "breathe_rot"; + mChestState = new LLJointState; + } + + // Destructor + virtual ~LLBreatheMotionRot() {} public: - //------------------------------------------------------------------------- - // functions to support MotionController and MotionRegistry - //------------------------------------------------------------------------- - // static constructor - // all subclasses must implement such a function and register it - static LLMotion *create(const LLUUID &id) { return new LLBreatheMotionRot(id); } + //------------------------------------------------------------------------- + // functions to support MotionController and MotionRegistry + //------------------------------------------------------------------------- + // static constructor + // all subclasses must implement such a function and register it + static LLMotion *create(const LLUUID &id) { return new LLBreatheMotionRot(id); } public: - //------------------------------------------------------------------------- - // animation callbacks to be implemented by subclasses - //------------------------------------------------------------------------- - - // motions must specify whether or not they loop - virtual BOOL getLoop() { return TRUE; } - - // motions must report their total duration - virtual F32 getDuration() { return 0.0; } - - // motions must report their "ease in" duration - virtual F32 getEaseInDuration() { return 0.0; } - - // motions must report their "ease out" duration. - virtual F32 getEaseOutDuration() { return 0.0; } - - // motions must report their priority - virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; } - - virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } - - // called to determine when a motion should be activated/deactivated based on avatar pixel coverage - virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BREATHE; } - - // run-time (post constructor) initialization, - // called after parameters have been set - // must return true to indicate success and be available for activation - virtual LLMotionInitStatus onInitialize(LLCharacter *character) - { - mCharacter = character; - BOOL success = true; - - if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) - { - success = false; - } - - if ( success ) - { - mChestState->setUsage(LLJointState::ROT); - addJointState( mChestState ); - } - - if ( success ) - { - return STATUS_SUCCESS; - } - else - { - return STATUS_FAILURE; - } - } - - // called when a motion is activated - // must return TRUE to indicate success, or else - // it will be deactivated - virtual BOOL onActivate() { return TRUE; } - - // called per time step - // must return TRUE while it is active, and - // must return FALSE when the motion is completed. - virtual BOOL onUpdate(F32 time, U8* joint_mask) - { + //------------------------------------------------------------------------- + // animation callbacks to be implemented by subclasses + //------------------------------------------------------------------------- + + // motions must specify whether or not they loop + virtual BOOL getLoop() { return TRUE; } + + // motions must report their total duration + virtual F32 getDuration() { return 0.0; } + + // motions must report their "ease in" duration + virtual F32 getEaseInDuration() { return 0.0; } + + // motions must report their "ease out" duration. + virtual F32 getEaseOutDuration() { return 0.0; } + + // motions must report their priority + virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; } + + virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } + + // called to determine when a motion should be activated/deactivated based on avatar pixel coverage + virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_BREATHE; } + + // run-time (post constructor) initialization, + // called after parameters have been set + // must return true to indicate success and be available for activation + virtual LLMotionInitStatus onInitialize(LLCharacter *character) + { + mCharacter = character; + BOOL success = true; + + if ( !mChestState->setJoint( character->getJoint( "mChest" ) ) ) + { + success = false; + } + + if ( success ) + { + mChestState->setUsage(LLJointState::ROT); + addJointState( mChestState ); + } + + if ( success ) + { + return STATUS_SUCCESS; + } + else + { + return STATUS_FAILURE; + } + } + + // called when a motion is activated + // must return TRUE to indicate success, or else + // it will be deactivated + virtual BOOL onActivate() { return TRUE; } + + // called per time step + // must return TRUE while it is active, and + // must return FALSE when the motion is completed. + virtual BOOL onUpdate(F32 time, U8* joint_mask) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - mBreatheRate = 1.f; + mBreatheRate = 1.f; - F32 breathe_amt = (sinf(mBreatheRate * time) * BREATHE_ROT_MOTION_STRENGTH); + F32 breathe_amt = (sinf(mBreatheRate * time) * BREATHE_ROT_MOTION_STRENGTH); - mChestState->setRotation(LLQuaternion(breathe_amt, LLVector3(0.f, 1.f, 0.f))); + mChestState->setRotation(LLQuaternion(breathe_amt, LLVector3(0.f, 1.f, 0.f))); - return TRUE; - } + return TRUE; + } - // called when a motion is deactivated - virtual void onDeactivate() {} + // called when a motion is deactivated + virtual void onDeactivate() {} private: - //------------------------------------------------------------------------- - // joint states to be animated - //------------------------------------------------------------------------- - LLPointer mChestState; - F32 mBreatheRate; - LLCharacter* mCharacter; + //------------------------------------------------------------------------- + // joint states to be animated + //------------------------------------------------------------------------- + LLPointer mChestState; + F32 mBreatheRate; + LLCharacter* mCharacter; }; //----------------------------------------------------------------------------- // class LLPelvisFixMotion //----------------------------------------------------------------------------- class LLPelvisFixMotion : - public LLMotion + public LLMotion { public: - // Constructor - LLPelvisFixMotion(const LLUUID &id) - : LLMotion(id), mCharacter(NULL) - { - mName = "pelvis_fix"; + // Constructor + LLPelvisFixMotion(const LLUUID &id) + : LLMotion(id), mCharacter(NULL) + { + mName = "pelvis_fix"; - mPelvisState = new LLJointState; - } + mPelvisState = new LLJointState; + } - // Destructor - virtual ~LLPelvisFixMotion() { } + // Destructor + virtual ~LLPelvisFixMotion() { } public: - //------------------------------------------------------------------------- - // functions to support MotionController and MotionRegistry - //------------------------------------------------------------------------- - // static constructor - // all subclasses must implement such a function and register it - static LLMotion *create(const LLUUID& id) { return new LLPelvisFixMotion(id); } + //------------------------------------------------------------------------- + // functions to support MotionController and MotionRegistry + //------------------------------------------------------------------------- + // static constructor + // all subclasses must implement such a function and register it + static LLMotion *create(const LLUUID& id) { return new LLPelvisFixMotion(id); } public: - //------------------------------------------------------------------------- - // animation callbacks to be implemented by subclasses - //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + // animation callbacks to be implemented by subclasses + //------------------------------------------------------------------------- - // motions must specify whether or not they loop - virtual BOOL getLoop() { return TRUE; } + // motions must specify whether or not they loop + virtual BOOL getLoop() { return TRUE; } - // motions must report their total duration - virtual F32 getDuration() { return 0.0; } + // motions must report their total duration + virtual F32 getDuration() { return 0.0; } - // motions must report their "ease in" duration - virtual F32 getEaseInDuration() { return 0.5f; } + // motions must report their "ease in" duration + virtual F32 getEaseInDuration() { return 0.5f; } - // motions must report their "ease out" duration. - virtual F32 getEaseOutDuration() { return 0.5f; } + // motions must report their "ease out" duration. + virtual F32 getEaseOutDuration() { return 0.5f; } - // motions must report their priority - virtual LLJoint::JointPriority getPriority() { return LLJoint::LOW_PRIORITY; } + // motions must report their priority + virtual LLJoint::JointPriority getPriority() { return LLJoint::LOW_PRIORITY; } - virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } + virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } - // called to determine when a motion should be activated/deactivated based on avatar pixel coverage - virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX; } + // called to determine when a motion should be activated/deactivated based on avatar pixel coverage + virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX; } - // run-time (post constructor) initialization, - // called after parameters have been set - // must return true to indicate success and be available for activation - virtual LLMotionInitStatus onInitialize(LLCharacter *character) - { - mCharacter = character; + // run-time (post constructor) initialization, + // called after parameters have been set + // must return true to indicate success and be available for activation + virtual LLMotionInitStatus onInitialize(LLCharacter *character) + { + mCharacter = character; - if (!mPelvisState->setJoint( character->getJoint("mPelvis"))) - { - return STATUS_FAILURE; - } + if (!mPelvisState->setJoint( character->getJoint("mPelvis"))) + { + return STATUS_FAILURE; + } - mPelvisState->setUsage(LLJointState::POS); + mPelvisState->setUsage(LLJointState::POS); - addJointState( mPelvisState ); - return STATUS_SUCCESS; - } + addJointState( mPelvisState ); + return STATUS_SUCCESS; + } - // called when a motion is activated - // must return TRUE to indicate success, or else - // it will be deactivated - virtual BOOL onActivate() { return TRUE; } + // called when a motion is activated + // must return TRUE to indicate success, or else + // it will be deactivated + virtual BOOL onActivate() { return TRUE; } - // called per time step - // must return TRUE while it is active, and - // must return FALSE when the motion is completed. - virtual BOOL onUpdate(F32 time, U8* joint_mask) - { + // called per time step + // must return TRUE while it is active, and + // must return FALSE when the motion is completed. + virtual BOOL onUpdate(F32 time, U8* joint_mask) + { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - mPelvisState->setPosition(LLVector3::zero); + mPelvisState->setPosition(LLVector3::zero); - return TRUE; - } + return TRUE; + } - // called when a motion is deactivated - virtual void onDeactivate() {} + // called when a motion is deactivated + virtual void onDeactivate() {} private: - //------------------------------------------------------------------------- - // joint states to be animated - //------------------------------------------------------------------------- - LLPointer mPelvisState; - LLCharacter* mCharacter; + //------------------------------------------------------------------------- + // joint states to be animated + //------------------------------------------------------------------------- + LLPointer mPelvisState; + LLCharacter* mCharacter; }; /** @@ -590,19 +590,19 @@ private: U32 LLVOAvatar::sMaxNonImpostors = 12; // Set from RenderAvatarMaxNonImpostors bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonImpostors is 0 (unlimited) F32 LLVOAvatar::sRenderDistance = 256.f; -S32 LLVOAvatar::sNumVisibleAvatars = 0; -S32 LLVOAvatar::sNumLODChangesThisFrame = 0; +S32 LLVOAvatar::sNumVisibleAvatars = 0; +S32 LLVOAvatar::sNumLODChangesThisFrame = 0; const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = { - SND_STONE_RUBBER, - SND_METAL_RUBBER, - SND_GLASS_RUBBER, - SND_WOOD_RUBBER, - SND_FLESH_RUBBER, - SND_RUBBER_PLASTIC, - SND_RUBBER_RUBBER + SND_STONE_RUBBER, + SND_METAL_RUBBER, + SND_GLASS_RUBBER, + SND_WOOD_RUBBER, + SND_FLESH_RUBBER, + SND_RUBBER_PLASTIC, + SND_RUBBER_RUBBER }; S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; @@ -632,138 +632,138 @@ static F32 calc_bouncy_animation(F32 x); // LLVOAvatar() //----------------------------------------------------------------------------- LLVOAvatar::LLVOAvatar(const LLUUID& id, - const LLPCode pcode, - LLViewerRegion* regionp) : - LLAvatarAppearance(&gAgentWearables), - LLViewerObject(id, pcode, regionp), - mSpecialRenderMode(0), - mAttachmentSurfaceArea(0.f), - mAttachmentVisibleTriangleCount(0), - mAttachmentEstTriangleCount(0.f), - mReportedVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), - mTurning(FALSE), - mLastSkeletonSerialNum( 0 ), - mIsSitting(FALSE), - mTimeVisible(), - mTyping(FALSE), - mMeshValid(FALSE), - mVisible(FALSE), - mLastImpostorUpdateFrameTime(0.f), - mLastImpostorUpdateReason(0), - mWindFreq(0.f), - mRipplePhase( 0.f ), - mBelowWater(FALSE), - mLastAppearanceBlendTime(0.f), - mAppearanceAnimating(FALSE), + const LLPCode pcode, + LLViewerRegion* regionp) : + LLAvatarAppearance(&gAgentWearables), + LLViewerObject(id, pcode, regionp), + mSpecialRenderMode(0), + mAttachmentSurfaceArea(0.f), + mAttachmentVisibleTriangleCount(0), + mAttachmentEstTriangleCount(0.f), + mReportedVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), + mTurning(FALSE), + mLastSkeletonSerialNum( 0 ), + mIsSitting(FALSE), + mTimeVisible(), + mTyping(FALSE), + mMeshValid(FALSE), + mVisible(FALSE), + mLastImpostorUpdateFrameTime(0.f), + mLastImpostorUpdateReason(0), + mWindFreq(0.f), + mRipplePhase( 0.f ), + mBelowWater(FALSE), + mLastAppearanceBlendTime(0.f), + mAppearanceAnimating(FALSE), mNameIsSet(false), - mTitle(), - mNameAway(false), - mNameDoNotDisturb(false), - mNameMute(false), - mNameAppearance(false), - mNameFriend(false), - mNameAlpha(0.f), - mRenderGroupTitles(sRenderGroupTitles), - mNameCloud(false), - mFirstTEMessageReceived( FALSE ), - mFirstAppearanceMessageReceived( FALSE ), - mCulled( FALSE ), - mVisibilityRank(0), - mNeedsSkin(FALSE), - mLastSkinTime(0.f), - mUpdatePeriod(1), - mOverallAppearance(AOA_INVISIBLE), - mVisualComplexityStale(true), - mVisuallyMuteSetting(AV_RENDER_NORMALLY), - mMutedAVColor(LLColor4::white /* used for "uninitialize" */), - mFirstFullyVisible(TRUE), - mFirstUseDelaySeconds(FIRST_APPEARANCE_CLOUD_MIN_DELAY), - mFullyLoaded(FALSE), - mPreviousFullyLoaded(FALSE), - mFullyLoadedInitialized(FALSE), - mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), - mLoadedCallbacksPaused(FALSE), - mLoadedCallbackTextures(0), - mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar", false)), - mLastRezzedStatus(-1), - mIsEditingAppearance(FALSE), - mUseLocalAppearance(FALSE), - mLastUpdateRequestCOFVersion(-1), - mLastUpdateReceivedCOFVersion(-1), - mCachedMuteListUpdateTime(0), - mCachedInMuteList(false), + mTitle(), + mNameAway(false), + mNameDoNotDisturb(false), + mNameMute(false), + mNameAppearance(false), + mNameFriend(false), + mNameAlpha(0.f), + mRenderGroupTitles(sRenderGroupTitles), + mNameCloud(false), + mFirstTEMessageReceived( FALSE ), + mFirstAppearanceMessageReceived( FALSE ), + mCulled( FALSE ), + mVisibilityRank(0), + mNeedsSkin(FALSE), + mLastSkinTime(0.f), + mUpdatePeriod(1), + mOverallAppearance(AOA_INVISIBLE), + mVisualComplexityStale(true), + mVisuallyMuteSetting(AV_RENDER_NORMALLY), + mMutedAVColor(LLColor4::white /* used for "uninitialize" */), + mFirstFullyVisible(TRUE), + mFirstUseDelaySeconds(FIRST_APPEARANCE_CLOUD_MIN_DELAY), + mFullyLoaded(FALSE), + mPreviousFullyLoaded(FALSE), + mFullyLoadedInitialized(FALSE), + mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), + mLoadedCallbacksPaused(FALSE), + mLoadedCallbackTextures(0), + mRenderUnloadedAvatar(LLCachedControl(gSavedSettings, "RenderUnloadedAvatar", false)), + mLastRezzedStatus(-1), + mIsEditingAppearance(FALSE), + mUseLocalAppearance(FALSE), + mLastUpdateRequestCOFVersion(-1), + mLastUpdateReceivedCOFVersion(-1), + mCachedMuteListUpdateTime(0), + mCachedInMuteList(false), mIsControlAvatar(false), mIsUIAvatar(false), mEnableDefaultMotions(true) { - LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; + LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; - //VTResume(); // VTune - setHoverOffset(LLVector3(0.0, 0.0, 0.0)); + //VTResume(); // VTune + setHoverOffset(LLVector3(0.0, 0.0, 0.0)); - // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline - const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job - mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); + // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline + const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job + mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); - LL_DEBUGS("Avatar","Message") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; - mPelvisp = NULL; + LL_DEBUGS("Avatar","Message") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; + mPelvisp = NULL; - mDirtyMesh = 2; // Dirty geometry, need to regenerate. - mMeshTexturesDirty = FALSE; - mHeadp = NULL; + mDirtyMesh = 2; // Dirty geometry, need to regenerate. + mMeshTexturesDirty = FALSE; + mHeadp = NULL; - // set up animation variables - mSpeed = 0.f; - setAnimationData("Speed", &mSpeed); + // set up animation variables + mSpeed = 0.f; + setAnimationData("Speed", &mSpeed); - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 0; - mNeedsAnimUpdate = TRUE; + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 0; + mNeedsAnimUpdate = TRUE; - mNeedsExtentUpdate = true; + mNeedsExtentUpdate = true; - mImpostorDistance = 0; - mImpostorPixelArea = 0; + mImpostorDistance = 0; + mImpostorPixelArea = 0; - setNumTEs(TEX_NUM_INDICES); + setNumTEs(TEX_NUM_INDICES); - mbCanSelect = TRUE; + mbCanSelect = TRUE; - mSignaledAnimations.clear(); - mPlayingAnimations.clear(); + mSignaledAnimations.clear(); + mPlayingAnimations.clear(); - mWasOnGroundLeft = FALSE; - mWasOnGroundRight = FALSE; + mWasOnGroundLeft = FALSE; + mWasOnGroundRight = FALSE; - mTimeLast = 0.0f; - mSpeedAccum = 0.0f; + mTimeLast = 0.0f; + mSpeedAccum = 0.0f; - mRippleTimeLast = 0.f; + mRippleTimeLast = 0.f; - mInAir = FALSE; + mInAir = FALSE; - mStepOnLand = TRUE; - mStepMaterial = 0; + mStepOnLand = TRUE; + mStepMaterial = 0; - mLipSyncActive = false; - mOohMorph = NULL; - mAahMorph = NULL; + mLipSyncActive = false; + mOohMorph = NULL; + mAahMorph = NULL; - mCurrentGesticulationLevel = 0; + mCurrentGesticulationLevel = 0; mFirstAppearanceMessageTimer.reset(); - mRuthTimer.reset(); - mRuthDebugTimer.reset(); - mDebugExistenceTimer.reset(); - mLastAppearanceMessageTimer.reset(); + mRuthTimer.reset(); + mRuthDebugTimer.reset(); + mDebugExistenceTimer.reset(); + mLastAppearanceMessageTimer.reset(); - if(LLSceneMonitor::getInstance()->isEnabled()) - { - LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this); - } + if(LLSceneMonitor::getInstance()->isEnabled()) + { + LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this); + } - mVisuallyMuteSetting = LLVOAvatar::VisualMuteSettings(LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(getID())); + mVisuallyMuteSetting = LLVOAvatar::VisualMuteSettings(LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(getID())); } std::string LLVOAvatar::avString() const @@ -774,8 +774,8 @@ std::string LLVOAvatar::avString() const } else { - std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); - return " Avatar '" + getFullname() + "' " + viz_string + " "; + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + return " Avatar '" + getFullname() + "' " + viz_string + " "; } } @@ -788,22 +788,22 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c return; } - LL_INFOS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() - << "sec ]" - << avString() - << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() - << " Notification " << notification_name - << " : " << comment - << LL_ENDL; + LL_INFOS("Avatar") << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() + << "sec ]" + << avString() + << "RuthTimer " << (U32)mRuthDebugTimer.getElapsedTimeF32() + << " Notification " << notification_name + << " : " << comment + << LL_ENDL; - if (gSavedSettings.getBOOL("DebugAvatarRezTime")) - { - LLSD args; - args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); - args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); - args["NAME"] = getFullname(); - LLNotificationsUtil::add(notification_name,args); - } + if (gSavedSettings.getBOOL("DebugAvatarRezTime")) + { + LLSD args; + args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add(notification_name,args); + } } //------------------------------------------------------------------------ @@ -811,14 +811,14 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { - if (!mFullyLoaded) - { - debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); - } - else - { - debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); - } + if (!mFullyLoaded) + { + debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); + } + else + { + debugAvatarRezTime("AvatarRezLeftNotification","left sometime after declouding"); + } if(mTuned) { @@ -828,306 +828,306 @@ LLVOAvatar::~LLVOAvatar() sAVsIgnoringARTLimit.erase(std::remove(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID), sAVsIgnoringARTLimit.end()); - logPendingPhases(); - - LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL; + logPendingPhases(); + + LL_DEBUGS("Avatar") << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << LL_ENDL; + + std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); + mAttachmentPoints.clear(); - std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); - mAttachmentPoints.clear(); + mDead = TRUE; - mDead = TRUE; - - mAnimationSources.clear(); - LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + mAnimationSources.clear(); + LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; - getPhases().clearPhases(); - - LL_DEBUGS() << "LLVOAvatar Destructor end" << LL_ENDL; + getPhases().clearPhases(); + + LL_DEBUGS() << "LLVOAvatar Destructor end" << LL_ENDL; } void LLVOAvatar::markDead() { - if (mNameText) - { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; - } - mVoiceVisualizer->markDead(); - LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; - LLViewerObject::markDead(); + if (mNameText) + { + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; + } + mVoiceVisualizer->markDead(); + LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + LLViewerObject::markDead(); } BOOL LLVOAvatar::isFullyBaked() { - if (mIsDummy) return TRUE; - if (getNumTEs() == 0) return FALSE; + if (mIsDummy) return TRUE; + if (getNumTEs() == 0) return FALSE; - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex) - && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT)) - && (i != BAKED_LEFT_ARM) && (i != BAKED_LEFT_LEG) && (i != BAKED_AUX1) && (i != BAKED_AUX2) && (i != BAKED_AUX3)) - { - return FALSE; - } - } - return TRUE; + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex) + && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT)) + && (i != BAKED_LEFT_ARM) && (i != BAKED_LEFT_LEG) && (i != BAKED_AUX1) && (i != BAKED_AUX2) && (i != BAKED_AUX3)) + { + return FALSE; + } + } + return TRUE; } BOOL LLVOAvatar::isFullyTextured() const { - for (S32 i = 0; i < mMeshLOD.size(); i++) - { - LLAvatarJoint* joint = mMeshLOD[i]; - if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) - { - continue; // don't care about skirt textures if we're not wearing one. - } - if (!joint) - { - continue; // nonexistent LOD OK. - } - avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); - if (meshIter != joint->mMeshParts.end()) - { - LLAvatarJointMesh *mesh = (*meshIter); - if (!mesh) - { - continue; // nonexistent mesh OK - } - if (mesh->hasGLTexture()) - { - continue; // Mesh exists and has a baked texture. - } - if (mesh->hasComposite()) - { - continue; // Mesh exists and has a composite texture. - } - // Fail - return FALSE; - } - } - return TRUE; + for (S32 i = 0; i < mMeshLOD.size(); i++) + { + LLAvatarJoint* joint = mMeshLOD[i]; + if (i==MESH_ID_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) + { + continue; // don't care about skirt textures if we're not wearing one. + } + if (!joint) + { + continue; // nonexistent LOD OK. + } + avatar_joint_mesh_list_t::iterator meshIter = joint->mMeshParts.begin(); + if (meshIter != joint->mMeshParts.end()) + { + LLAvatarJointMesh *mesh = (*meshIter); + if (!mesh) + { + continue; // nonexistent mesh OK + } + if (mesh->hasGLTexture()) + { + continue; // Mesh exists and has a baked texture. + } + if (mesh->hasComposite()) + { + continue; // Mesh exists and has a composite texture. + } + // Fail + return FALSE; + } + } + return TRUE; } BOOL LLVOAvatar::hasGray() const { - return !getIsCloud() && !isFullyTextured(); + return !getIsCloud() && !isFullyTextured(); } S32 LLVOAvatar::getRezzedStatus() const { - if (getIsCloud()) return 0; - bool textured = isFullyTextured(); - if (textured && allBakedTexturesCompletelyDownloaded()) return 3; - if (textured) return 2; - llassert(hasGray()); - return 1; // gray + if (getIsCloud()) return 0; + bool textured = isFullyTextured(); + if (textured && allBakedTexturesCompletelyDownloaded()) return 3; + if (textured) return 2; + llassert(hasGray()); + return 1; // gray } void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - if (mBakedTextureDatas[i].mTexLayerSet) - { - // ! BACKWARDS COMPATIBILITY ! - // Can be removed after hair baking is mandatory on the grid - if ((i != BAKED_HAIR || isSelf()) && !clearAll) - { - mBakedTextureDatas[i].mTexLayerSet->deleteCaches(); - } - } - if (mBakedTextureDatas[i].mMaskTexName) - { - LLImageGL::deleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); - mBakedTextureDatas[i].mMaskTexName = 0 ; - } - } -} - -// static + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (mBakedTextureDatas[i].mTexLayerSet) + { + // ! BACKWARDS COMPATIBILITY ! + // Can be removed after hair baking is mandatory on the grid + if ((i != BAKED_HAIR || isSelf()) && !clearAll) + { + mBakedTextureDatas[i].mTexLayerSet->deleteCaches(); + } + } + if (mBakedTextureDatas[i].mMaskTexName) + { + LLImageGL::deleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); + mBakedTextureDatas[i].mMaskTexName = 0 ; + } + } +} + +// static BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) { - BOOL res = TRUE; - grey_avatars = 0; - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - if( inst->isDead() ) - { - continue; - } - else if( !inst->isFullyBaked() ) - { - res = FALSE; - if (inst->mHasGrey) - { - ++grey_avatars; - } - } - } - return res; + BOOL res = TRUE; + grey_avatars = 0; + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if( inst->isDead() ) + { + continue; + } + else if( !inst->isFullyBaked() ) + { + res = FALSE; + if (inst->mHasGrey) + { + ++grey_avatars; + } + } + } + return res; } // static void LLVOAvatar::getNearbyRezzedStats(std::vector& counts) { - counts.clear(); - counts.resize(4); - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - if (inst) - { - S32 rez_status = inst->getRezzedStatus(); - counts[rez_status]++; - } - } + counts.clear(); + counts.resize(4); + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if (inst) + { + S32 rez_status = inst->getRezzedStatus(); + counts[rez_status]++; + } + } } // static std::string LLVOAvatar::rezStatusToString(S32 rez_status) { - if (rez_status==0) return "cloud"; - if (rez_status==1) return "gray"; - if (rez_status==2) return "downloading"; - if (rez_status==3) return "full"; - return "unknown"; + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "downloading"; + if (rez_status==3) return "full"; + return "unknown"; } // static void LLVOAvatar::dumpBakedStatus() { - LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal(); - - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - LL_INFOS() << "Avatar "; - - LLNameValue* firstname = inst->getNVPair("FirstName"); - LLNameValue* lastname = inst->getNVPair("LastName"); - - if( firstname ) - { - LL_CONT << firstname->getString(); - } - if( lastname ) - { - LL_CONT << " " << lastname->getString(); - } - - LL_CONT << " " << inst->mID; - - if( inst->isDead() ) - { - LL_CONT << " DEAD ("<< inst->getNumRefs() << " refs)"; - } - - if( inst->isSelf() ) - { - LL_CONT << " (self)"; - } - - - F64 dist_to_camera = (inst->getPositionGlobal() - camera_pos_global).length(); - LL_CONT << " " << dist_to_camera << "m "; - - LL_CONT << " " << inst->mPixelArea << " pixels"; - - if( inst->isVisible() ) - { - LL_CONT << " (visible)"; - } - else - { - LL_CONT << " (not visible)"; - } - - if( inst->isFullyBaked() ) - { - LL_CONT << " Baked"; - } - else - { - LL_CONT << " Unbaked ("; - - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); - iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); - ++iter) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; - const ETextureIndex index = baked_dict->mTextureIndex; - if (!inst->isTextureDefined(index)) - { - LL_CONT << " " << (LLAvatarAppearance::getDictionary()->getTexture(index) ? LLAvatarAppearance::getDictionary()->getTexture(index)->mName : ""); - } - } - LL_CONT << " ) " << inst->getUnbakedPixelAreaRank(); - if( inst->isCulled() ) - { - LL_CONT << " culled"; - } - } - LL_CONT << LL_ENDL; - } + LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal(); + + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + LL_INFOS() << "Avatar "; + + LLNameValue* firstname = inst->getNVPair("FirstName"); + LLNameValue* lastname = inst->getNVPair("LastName"); + + if( firstname ) + { + LL_CONT << firstname->getString(); + } + if( lastname ) + { + LL_CONT << " " << lastname->getString(); + } + + LL_CONT << " " << inst->mID; + + if( inst->isDead() ) + { + LL_CONT << " DEAD ("<< inst->getNumRefs() << " refs)"; + } + + if( inst->isSelf() ) + { + LL_CONT << " (self)"; + } + + + F64 dist_to_camera = (inst->getPositionGlobal() - camera_pos_global).length(); + LL_CONT << " " << dist_to_camera << "m "; + + LL_CONT << " " << inst->mPixelArea << " pixels"; + + if( inst->isVisible() ) + { + LL_CONT << " (visible)"; + } + else + { + LL_CONT << " (not visible)"; + } + + if( inst->isFullyBaked() ) + { + LL_CONT << " Baked"; + } + else + { + LL_CONT << " Unbaked ("; + + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); + ++iter) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; + const ETextureIndex index = baked_dict->mTextureIndex; + if (!inst->isTextureDefined(index)) + { + LL_CONT << " " << (LLAvatarAppearance::getDictionary()->getTexture(index) ? LLAvatarAppearance::getDictionary()->getTexture(index)->mName : ""); + } + } + LL_CONT << " ) " << inst->getUnbakedPixelAreaRank(); + if( inst->isCulled() ) + { + LL_CONT << " culled"; + } + } + LL_CONT << LL_ENDL; + } } //static void LLVOAvatar::restoreGL() { - if (!isAgentAvatarValid()) return; + if (!isAgentAvatarValid()) return; - gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); - for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++) - { - gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i)); - } - gAgentAvatarp->updateMeshTextures(); + gAgentAvatarp->setCompositeUpdatesEnabled(TRUE); + for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++) + { + gAgentAvatarp->invalidateComposite(gAgentAvatarp->getTexLayerSet(i)); + } + gAgentAvatarp->updateMeshTextures(); } //static void LLVOAvatar::destroyGL() { - deleteCachedImages(); + deleteCachedImages(); - resetImpostors(); + resetImpostors(); } //static void LLVOAvatar::resetImpostors() { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* avatar = (LLVOAvatar*) *iter; - avatar->mImpostor.release(); - avatar->mNeedsImpostorUpdate = TRUE; - avatar->mLastImpostorUpdateReason = 1; - } + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* avatar = (LLVOAvatar*) *iter; + avatar->mImpostor.release(); + avatar->mNeedsImpostorUpdate = TRUE; + avatar->mLastImpostorUpdateReason = 1; + } } // static void LLVOAvatar::deleteCachedImages(bool clearAll) -{ - if (LLViewerTexLayerSet::sHasCaches) - { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - inst->deleteLayerSetCaches(clearAll); - } - LLViewerTexLayerSet::sHasCaches = FALSE; - } - LLVOAvatarSelf::deleteScratchTextures(); - LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); +{ + if (LLViewerTexLayerSet::sHasCaches) + { + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + inst->deleteLayerSetCaches(clearAll); + } + LLViewerTexLayerSet::sHasCaches = FALSE; + } + LLVOAvatarSelf::deleteScratchTextures(); + LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); } @@ -1136,23 +1136,23 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) // LLVOAvatar::initClass() //------------------------------------------------------------------------ void LLVOAvatar::initClass() -{ - gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise"); - gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot"); - gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion"); - gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing"); - gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye"); - gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust"); - gAnimLibrary.animStateSetString(ANIM_AGENT_HAND_MOTION,"hand_motion"); - gAnimLibrary.animStateSetString(ANIM_AGENT_HEAD_ROT,"head_rot"); - gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix"); - gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target"); - gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust"); +{ + gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise"); + gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot"); + gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion"); + gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing"); + gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye"); + gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust"); + gAnimLibrary.animStateSetString(ANIM_AGENT_HAND_MOTION,"hand_motion"); + gAnimLibrary.animStateSetString(ANIM_AGENT_HEAD_ROT,"head_rot"); + gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix"); + gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target"); + gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust"); // Where should this be set initially? LLJoint::setDebugJointNames(gSavedSettings.getString("DebugAvatarJoints")); - LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged); + LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged); sCloudTexture = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c"); } @@ -1165,74 +1165,74 @@ void LLVOAvatar::cleanupClass() // virtual void LLVOAvatar::initInstance() { - //------------------------------------------------------------------------- - // register motions - //------------------------------------------------------------------------- - if (LLCharacter::sInstances.size() == 1) - { - registerMotion( ANIM_AGENT_DO_NOT_DISTURB, LLNullMotion::create ); - registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_ANGER, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_BORED, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_CRY, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_DISDAIN, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_EMBARRASSED, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_FROWN, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_KISS, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_LAUGH, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_OPEN_MOUTH, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_REPULSED, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_SAD, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_SHRUG, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_SMILE, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_SURPRISE, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_TONGUE_OUT, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create ); - registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create ); - registerMotion( ANIM_AGENT_FEMALE_RUN_NEW, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_FEMALE_WALK_NEW, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_RUN_NEW, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_STAND_3, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_STAND_4, LLKeyframeStandMotion::create ); - registerMotion( ANIM_AGENT_STANDUP, LLKeyframeFallMotion::create ); - registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_WALK_NEW, LLKeyframeWalkMotion::create ); - - // motions without a start/stop bit - registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create ); - registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create ); - registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create ); - registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create ); - registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create ); - registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); - registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create ); - registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create ); - registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create ); - registerMotion( ANIM_AGENT_PELVIS_FIX, LLPelvisFixMotion::create ); - registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create ); - registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); - registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); - } - - LLAvatarAppearance::initInstance(); - - // preload specific motions here - createMotion( ANIM_AGENT_CUSTOMIZE); - createMotion( ANIM_AGENT_CUSTOMIZE_DONE); - - //VTPause(); // VTune - - mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); + //------------------------------------------------------------------------- + // register motions + //------------------------------------------------------------------------- + if (LLCharacter::sInstances.size() == 1) + { + registerMotion( ANIM_AGENT_DO_NOT_DISTURB, LLNullMotion::create ); + registerMotion( ANIM_AGENT_CROUCH, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_CROUCHWALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_EXPRESS_AFRAID, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_ANGER, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_BORED, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_CRY, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_DISDAIN, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_EMBARRASSED, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_FROWN, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_KISS, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_LAUGH, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_OPEN_MOUTH, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_REPULSED, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_SAD, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_SHRUG, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_SMILE, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_SURPRISE, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_TONGUE_OUT, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create ); + registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create ); + registerMotion( ANIM_AGENT_FEMALE_RUN_NEW, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_FEMALE_WALK_NEW, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_RUN_NEW, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_STAND_3, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_STAND_4, LLKeyframeStandMotion::create ); + registerMotion( ANIM_AGENT_STANDUP, LLKeyframeFallMotion::create ); + registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_WALK_NEW, LLKeyframeWalkMotion::create ); + + // motions without a start/stop bit + registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create ); + registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create ); + registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create ); + registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create ); + registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create ); + registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create ); + registerMotion( ANIM_AGENT_FLY_ADJUST, LLFlyAdjustMotion::create ); + registerMotion( ANIM_AGENT_HAND_MOTION, LLHandMotion::create ); + registerMotion( ANIM_AGENT_HEAD_ROT, LLHeadRotMotion::create ); + registerMotion( ANIM_AGENT_PELVIS_FIX, LLPelvisFixMotion::create ); + registerMotion( ANIM_AGENT_SIT_FEMALE, LLKeyframeMotion::create ); + registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); + registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); + } + + LLAvatarAppearance::initInstance(); + + // preload specific motions here + createMotion( ANIM_AGENT_CUSTOMIZE); + createMotion( ANIM_AGENT_CUSTOMIZE_DONE); + + //VTPause(); // VTune + + mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); mInitFlags |= 1<<1; } @@ -1240,65 +1240,65 @@ void LLVOAvatar::initInstance() // virtual LLAvatarJoint* LLVOAvatar::createAvatarJoint() { - return new LLViewerJoint(); + return new LLViewerJoint(); } // virtual LLAvatarJoint* LLVOAvatar::createAvatarJoint(S32 joint_num) { - return new LLViewerJoint(joint_num); + return new LLViewerJoint(joint_num); } // virtual LLAvatarJointMesh* LLVOAvatar::createAvatarJointMesh() { - return new LLViewerJointMesh(); + return new LLViewerJointMesh(); } // virtual LLTexLayerSet* LLVOAvatar::createTexLayerSet() { - return new LLViewerTexLayerSet(this); + return new LLViewerTexLayerSet(this); } const LLVector3 LLVOAvatar::getRenderPosition() const { - if (mDrawable.isNull() || mDrawable->getGeneration() < 0) - { - return getPositionAgent(); - } - else if (isRoot()) - { - F32 fixup; - if ( hasPelvisFixup( fixup) ) - { - //Apply a pelvis fixup (as defined by the avs skin) - LLVector3 pos = mDrawable->getPositionAgent(); - pos[VZ] += fixup; - return pos; - } - else - { - return mDrawable->getPositionAgent(); - } - } - else - { - return getPosition() * mDrawable->getParent()->getRenderMatrix(); - } + if (mDrawable.isNull() || mDrawable->getGeneration() < 0) + { + return getPositionAgent(); + } + else if (isRoot()) + { + F32 fixup; + if ( hasPelvisFixup( fixup) ) + { + //Apply a pelvis fixup (as defined by the avs skin) + LLVector3 pos = mDrawable->getPositionAgent(); + pos[VZ] += fixup; + return pos; + } + else + { + return mDrawable->getPositionAgent(); + } + } + else + { + return getPosition() * mDrawable->getParent()->getRenderMatrix(); + } } void LLVOAvatar::updateDrawable(BOOL force_damped) { - clearChanged(SHIFTED); + clearChanged(SHIFTED); } void LLVOAvatar::onShift(const LLVector4a& shift_vector) { - const LLVector3& shift = reinterpret_cast(shift_vector); - mLastAnimExtents[0] += shift; - mLastAnimExtents[1] += shift; + const LLVector3& shift = reinterpret_cast(shift_vector); + mLastAnimExtents[0] += shift; + mLastAnimExtents[1] += shift; } void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) @@ -1313,37 +1313,37 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) calculateSpatialExtents(newMin,newMax); mLastAnimExtents[0].set(newMin.getF32ptr()); mLastAnimExtents[1].set(newMax.getF32ptr()); - mLastAnimBasePos = mPelvisp->getWorldPosition(); + mLastAnimBasePos = mPelvisp->getWorldPosition(); mNeedsExtentUpdate = false; } - else - { - LLVector3 new_base_pos = mPelvisp->getWorldPosition(); - LLVector3 shift = new_base_pos-mLastAnimBasePos; - mLastAnimExtents[0] += shift; - mLastAnimExtents[1] += shift; - mLastAnimBasePos = new_base_pos; - - } - - if (isImpostor() && !needsImpostorUpdate()) - { - LLVector3 delta = getRenderPosition() - - ((LLVector3(mDrawable->getPositionGroup().getF32ptr())-mImpostorOffset)); - - newMin.load3( (mLastAnimExtents[0] + delta).mV); - newMax.load3( (mLastAnimExtents[1] + delta).mV); - } - else - { + else + { + LLVector3 new_base_pos = mPelvisp->getWorldPosition(); + LLVector3 shift = new_base_pos-mLastAnimBasePos; + mLastAnimExtents[0] += shift; + mLastAnimExtents[1] += shift; + mLastAnimBasePos = new_base_pos; + + } + + if (isImpostor() && !needsImpostorUpdate()) + { + LLVector3 delta = getRenderPosition() - + ((LLVector3(mDrawable->getPositionGroup().getF32ptr())-mImpostorOffset)); + + newMin.load3( (mLastAnimExtents[0] + delta).mV); + newMax.load3( (mLastAnimExtents[1] + delta).mV); + } + else + { newMin.load3(mLastAnimExtents[0].mV); newMax.load3(mLastAnimExtents[1].mV); - LLVector4a pos_group; - pos_group.setAdd(newMin,newMax); - pos_group.mul(0.5f); - mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition(); - mDrawable->setPositionGroup(pos_group); - } + LLVector4a pos_group; + pos_group.setAdd(newMin,newMax); + pos_group.mul(0.5f); + mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition(); + mDrawable->setPositionGroup(pos_group); + } } @@ -1414,8 +1414,8 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) if (box_detail >= 2) { float max_attachment_span = get_default_max_prim_scale() * 5.0f; - - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) { @@ -1434,7 +1434,7 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) const LLVOVolume *vol = dynamic_cast(attached_object); if (vol && vol->isAnimatedObject()) { - // Animated objects already have a bounding box in their control av, use that. + // Animated objects already have a bounding box in their control av, use that. // Could lag by a frame if there's no guarantee on order of processing for avatars. LLControlAvatar *cav = vol->getControlAvatar(); if (cav) @@ -1464,10 +1464,10 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) LLVector4a max_span(max_attachment_span); S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; - + // Only add the prim to spatial extents calculations if it isn't a megaprim. - // max_attachment_span calculated at the start of the function - // (currently 5 times our max prim size) + // max_attachment_span calculated at the start of the function + // (currently 5 times our max prim size) if (lt == 0x7) { update_min_max(newMin,newMax,ext[0]); @@ -1521,10 +1521,10 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) LLVector4a center, size; center.setAdd(newMin, newMax); center.mul(0.5f); - + size.setSub(newMax,newMin); size.mul(0.5f); - + mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); } @@ -1537,24 +1537,24 @@ void render_sphere_and_line(const LLVector3& begin_pos, const LLVector3& end_pos gGL.diffuseColor3f(visible_color[0], visible_color[1], visible_color[2]); gGL.begin(LLRender::LINES); - gGL.vertex3fv(begin_pos.mV); + gGL.vertex3fv(begin_pos.mV); gGL.vertex3fv(end_pos.mV); gGL.end(); - + // Draw sphere representing joint pos gGL.pushMatrix(); gGL.scalef(sphere_scale, sphere_scale, sphere_scale); gSphere.renderGGL(); gGL.popMatrix(); - + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); // Occluded bone portions gGL.diffuseColor3f(occ_color[0], occ_color[1], occ_color[2]); gGL.begin(LLRender::LINES); - gGL.vertex3fv(begin_pos.mV); + gGL.vertex3fv(begin_pos.mV); gGL.vertex3fv(end_pos.mV); gGL.end(); @@ -1570,18 +1570,18 @@ void render_sphere_and_line(const LLVector3& begin_pos, const LLVector3& end_pos //----------------------------------------------------------------------------- void LLVOAvatar::renderCollisionVolumes() { - std::ostringstream ostr; + std::ostringstream ostr; - for (S32 i = 0; i < mNumCollisionVolumes; i++) - { - ostr << mCollisionVolumes[i].getName() << ", "; + for (S32 i = 0; i < mNumCollisionVolumes; i++) + { + ostr << mCollisionVolumes[i].getName() << ", "; LLAvatarJointCollisionVolume& collision_volume = mCollisionVolumes[i]; - collision_volume.updateWorldMatrix(); + collision_volume.updateWorldMatrix(); - gGL.pushMatrix(); - gGL.multMatrix( &collision_volume.getXform()->getWorldMatrix().mMatrix[0][0] ); + gGL.pushMatrix(); + gGL.multMatrix( &collision_volume.getXform()->getWorldMatrix().mMatrix[0][0] ); LLVector3 begin_pos(0,0,0); LLVector3 end_pos(collision_volume.getEnd()); @@ -1593,7 +1593,7 @@ void LLVOAvatar::renderCollisionVolumes() static LLVector3 RED(1.0f, 0.0f, 0.0f); static LLVector3 PASTEL_RED(1.0f, 0.5f, 0.5f); static LLVector3 WHITE(1.0f, 1.0f, 1.0f); - + LLVector3 cv_color_occluded; LLVector3 cv_color_visible; @@ -1615,20 +1615,20 @@ void LLVOAvatar::renderCollisionVolumes() gGL.popMatrix(); } - - if (mNameText.notNull()) - { - LLVector4a unused; - - mNameText->lineSegmentIntersect(unused, unused, unused, TRUE); - } + + if (mNameText.notNull()) + { + LLVector4a unused; + + mNameText->lineSegmentIntersect(unused, unused, unused, TRUE); + } } void LLVOAvatar::renderBones(const std::string &selected_joint) { LLGLEnable blend(GL_BLEND); - avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator iter = mSkeleton.begin(); avatar_joint_list_t::iterator end = mSkeleton.end(); // For selected joints @@ -1643,18 +1643,18 @@ void LLVOAvatar::renderBones(const std::string &selected_joint) // For bones not otherwise colored static LLVector3 OTHER_COLOR_OCCLUDED(0.0f, 1.0f, 0.0f); static LLVector3 OTHER_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); - + static F32 SPHERE_SCALEF = 0.001f; - for (; iter != end; ++iter) - { - LLJoint* jointp = *iter; - if (!jointp) - { - continue; - } + for (; iter != end; ++iter) + { + LLJoint* jointp = *iter; + if (!jointp) + { + continue; + } - jointp->updateWorldMatrix(); + jointp->updateWorldMatrix(); LLVector3 occ_color, visible_color; @@ -1692,343 +1692,343 @@ void LLVOAvatar::renderBones(const std::string &selected_joint) LLVector3 begin_pos(0,0,0); LLVector3 end_pos(jointp->getEnd()); - - gGL.pushMatrix(); - gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); + + gGL.pushMatrix(); + gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); render_sphere_and_line(begin_pos, end_pos, sphere_scale, occ_color, visible_color); - - gGL.popMatrix(); - } + + gGL.popMatrix(); + } } void LLVOAvatar::renderJoints() { - std::ostringstream ostr; - std::ostringstream nullstr; + std::ostringstream ostr; + std::ostringstream nullstr; + + for (joint_map_t::iterator iter = mJointMap.begin(); iter != mJointMap.end(); ++iter) + { + LLJoint* jointp = iter->second; + if (!jointp) + { + nullstr << iter->first << " is NULL" << std::endl; + continue; + } - for (joint_map_t::iterator iter = mJointMap.begin(); iter != mJointMap.end(); ++iter) - { - LLJoint* jointp = iter->second; - if (!jointp) - { - nullstr << iter->first << " is NULL" << std::endl; - continue; - } + ostr << jointp->getName() << ", "; - ostr << jointp->getName() << ", "; + jointp->updateWorldMatrix(); - jointp->updateWorldMatrix(); - - gGL.pushMatrix(); - gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); + gGL.pushMatrix(); + gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); - gGL.diffuseColor3f( 1.f, 0.f, 1.f ); - - gGL.begin(LLRender::LINES); - - LLVector3 v[] = - { - LLVector3(1,0,0), - LLVector3(-1,0,0), - LLVector3(0,1,0), - LLVector3(0,-1,0), + gGL.diffuseColor3f( 1.f, 0.f, 1.f ); - LLVector3(0,0,-1), - LLVector3(0,0,1), - }; + gGL.begin(LLRender::LINES); - //sides - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); + LLVector3 v[] = + { + LLVector3(1,0,0), + LLVector3(-1,0,0), + LLVector3(0,1,0), + LLVector3(0,-1,0), + + LLVector3(0,0,-1), + LLVector3(0,0,1), + }; - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[3].mV); + //sides + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[3].mV); - //top - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[4].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[4].mV); + //top + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[4].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[4].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[4].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[4].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[4].mV); + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[4].mV); - //bottom - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[5].mV); - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[5].mV); + //bottom + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[5].mV); - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[5].mV); + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[5].mV); - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[5].mV); + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[5].mV); - gGL.end(); + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[5].mV); - gGL.popMatrix(); - } + gGL.end(); + + gGL.popMatrix(); + } - mDebugText.clear(); - addDebugText(ostr.str()); - addDebugText(nullstr.str()); + mDebugText.clear(); + addDebugText(ostr.str()); + addDebugText(nullstr.str()); } BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face, - BOOL pick_transparent, - BOOL pick_rigged, + S32 face, + BOOL pick_transparent, + BOOL pick_rigged, BOOL pick_unselectable, - S32* face_hit, - LLVector4a* intersection, - LLVector2* tex_coord, - LLVector4a* normal, - LLVector4a* tangent) + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent) { - if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar) - { - return FALSE; - } + if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar) + { + return FALSE; + } if (isControlAvatar()) { return FALSE; } - - if (lineSegmentBoundingBox(start, end)) - { - for (S32 i = 0; i < mNumCollisionVolumes; ++i) - { - mCollisionVolumes[i].updateWorldMatrix(); - - glh::matrix4f mat((F32*) mCollisionVolumes[i].getXform()->getWorldMatrix().mMatrix); - glh::matrix4f inverse = mat.inverse(); - glh::matrix4f norm_mat = inverse.transpose(); - - glh::vec3f p1(start.getF32ptr()); - glh::vec3f p2(end.getF32ptr()); - - inverse.mult_matrix_vec(p1); - inverse.mult_matrix_vec(p2); - - LLVector3 position; - LLVector3 norm; - - if (linesegment_sphere(LLVector3(p1.v), LLVector3(p2.v), LLVector3(0,0,0), 1.f, position, norm)) - { - glh::vec3f res_pos(position.mV); - mat.mult_matrix_vec(res_pos); - - norm.normalize(); - glh::vec3f res_norm(norm.mV); - norm_mat.mult_matrix_dir(res_norm); - - if (intersection) - { - intersection->load3(res_pos.v); - } - - if (normal) - { - normal->load3(res_norm.v); - } - - return TRUE; - } - } - - if (isSelf()) - { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject* attached_object = attachment_iter->get(); - - if (attached_object && !attached_object->isDead() && attachment->getValid()) - { - LLDrawable* drawable = attached_object->mDrawable; - if (drawable->isState(LLDrawable::RIGGED)) - { //regenerate octree for rigged attachment - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED); - } - } - } - } - } - } - - - - LLVector4a position; - if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position)) - { - if (intersection) - { - *intersection = position; - } - - return TRUE; - } - - return FALSE; -} -// virtual -LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, - S32 face, - BOOL pick_transparent, - BOOL pick_rigged, - BOOL pick_unselectable, - S32* face_hit, - LLVector4a* intersection, - LLVector2* tex_coord, - LLVector4a* normal, - LLVector4a* tangent) -{ - if (isSelf() && !gAgent.needsRenderAvatar()) - { - return NULL; - } - - LLViewerObject* hit = NULL; - - if (lineSegmentBoundingBox(start, end)) - { - LLVector4a local_end = end; - LLVector4a local_intersection; - - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject* attached_object = attachment_iter->get(); - - 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) - { - *intersection = local_intersection; - } - - hit = attached_object; - } - } - } - } - - return hit; -} + if (lineSegmentBoundingBox(start, end)) + { + for (S32 i = 0; i < mNumCollisionVolumes; ++i) + { + mCollisionVolumes[i].updateWorldMatrix(); + glh::matrix4f mat((F32*) mCollisionVolumes[i].getXform()->getWorldMatrix().mMatrix); + glh::matrix4f inverse = mat.inverse(); + glh::matrix4f norm_mat = inverse.transpose(); -LLVOAvatar* LLVOAvatar::asAvatar() -{ - return this; -} + glh::vec3f p1(start.getF32ptr()); + glh::vec3f p2(end.getF32ptr()); -//----------------------------------------------------------------------------- -// LLVOAvatar::startDefaultMotions() -//----------------------------------------------------------------------------- -void LLVOAvatar::startDefaultMotions() -{ - //------------------------------------------------------------------------- - // start default motions - //------------------------------------------------------------------------- - startMotion( ANIM_AGENT_HEAD_ROT ); - startMotion( ANIM_AGENT_EYE ); - startMotion( ANIM_AGENT_BODY_NOISE ); - startMotion( ANIM_AGENT_BREATHE_ROT ); - startMotion( ANIM_AGENT_PHYSICS_MOTION ); - startMotion( ANIM_AGENT_HAND_MOTION ); - startMotion( ANIM_AGENT_PELVIS_FIX ); + inverse.mult_matrix_vec(p1); + inverse.mult_matrix_vec(p2); - //------------------------------------------------------------------------- - // restart any currently active motions - //------------------------------------------------------------------------- - processAnimationStateChanges(); -} + LLVector3 position; + LLVector3 norm; -//----------------------------------------------------------------------------- -// LLVOAvatar::buildCharacter() -// Deferred initialization and rebuild of the avatar. -//----------------------------------------------------------------------------- -// virtual -void LLVOAvatar::buildCharacter() -{ - LLAvatarAppearance::buildCharacter(); + if (linesegment_sphere(LLVector3(p1.v), LLVector3(p2.v), LLVector3(0,0,0), 1.f, position, norm)) + { + glh::vec3f res_pos(position.mV); + mat.mult_matrix_vec(res_pos); - // Not done building yet; more to do. - mIsBuilt = FALSE; + norm.normalize(); + glh::vec3f res_norm(norm.mV); + norm_mat.mult_matrix_dir(res_norm); - //------------------------------------------------------------------------- - // set head offset from pelvis - //------------------------------------------------------------------------- - updateHeadOffset(); + if (intersection) + { + intersection->load3(res_pos.v); + } - //------------------------------------------------------------------------- - // initialize lip sync morph pointers - //------------------------------------------------------------------------- - mOohMorph = getVisualParam( "Lipsync_Ooh" ); - mAahMorph = getVisualParam( "Lipsync_Aah" ); + if (normal) + { + normal->load3(res_norm.v); + } - // If we don't have the Ooh morph, use the Kiss morph - if (!mOohMorph) - { - LL_WARNS() << "Missing 'Ooh' morph for lipsync, using fallback." << LL_ENDL; - mOohMorph = getVisualParam( "Express_Kiss" ); - } + return TRUE; + } + } - // If we don't have the Aah morph, use the Open Mouth morph - if (!mAahMorph) - { - LL_WARNS() << "Missing 'Aah' morph for lipsync, using fallback." << LL_ENDL; - mAahMorph = getVisualParam( "Express_Open_Mouth" ); - } + if (isSelf()) + { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; - // Currently disabled for control avatars (animated objects), enabled for all others. + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = attachment_iter->get(); + + if (attached_object && !attached_object->isDead() && attachment->getValid()) + { + LLDrawable* drawable = attached_object->mDrawable; + if (drawable->isState(LLDrawable::RIGGED)) + { //regenerate octree for rigged attachment + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED); + } + } + } + } + } + } + + + + LLVector4a position; + if (mNameText.notNull() && mNameText->lineSegmentIntersect(start, end, position)) + { + if (intersection) + { + *intersection = position; + } + + return TRUE; + } + + return FALSE; +} + +// virtual +LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, + S32 face, + BOOL pick_transparent, + BOOL pick_rigged, + BOOL pick_unselectable, + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent) +{ + if (isSelf() && !gAgent.needsRenderAvatar()) + { + return NULL; + } + + LLViewerObject* hit = NULL; + + if (lineSegmentBoundingBox(start, end)) + { + LLVector4a local_end = end; + LLVector4a local_intersection; + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = attachment_iter->get(); + + 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) + { + *intersection = local_intersection; + } + + hit = attached_object; + } + } + } + } + + return hit; +} + + +LLVOAvatar* LLVOAvatar::asAvatar() +{ + return this; +} + +//----------------------------------------------------------------------------- +// LLVOAvatar::startDefaultMotions() +//----------------------------------------------------------------------------- +void LLVOAvatar::startDefaultMotions() +{ + //------------------------------------------------------------------------- + // start default motions + //------------------------------------------------------------------------- + startMotion( ANIM_AGENT_HEAD_ROT ); + startMotion( ANIM_AGENT_EYE ); + startMotion( ANIM_AGENT_BODY_NOISE ); + startMotion( ANIM_AGENT_BREATHE_ROT ); + startMotion( ANIM_AGENT_PHYSICS_MOTION ); + startMotion( ANIM_AGENT_HAND_MOTION ); + startMotion( ANIM_AGENT_PELVIS_FIX ); + + //------------------------------------------------------------------------- + // restart any currently active motions + //------------------------------------------------------------------------- + processAnimationStateChanges(); +} + +//----------------------------------------------------------------------------- +// LLVOAvatar::buildCharacter() +// Deferred initialization and rebuild of the avatar. +//----------------------------------------------------------------------------- +// virtual +void LLVOAvatar::buildCharacter() +{ + LLAvatarAppearance::buildCharacter(); + + // Not done building yet; more to do. + mIsBuilt = FALSE; + + //------------------------------------------------------------------------- + // set head offset from pelvis + //------------------------------------------------------------------------- + updateHeadOffset(); + + //------------------------------------------------------------------------- + // initialize lip sync morph pointers + //------------------------------------------------------------------------- + mOohMorph = getVisualParam( "Lipsync_Ooh" ); + mAahMorph = getVisualParam( "Lipsync_Aah" ); + + // If we don't have the Ooh morph, use the Kiss morph + if (!mOohMorph) + { + LL_WARNS() << "Missing 'Ooh' morph for lipsync, using fallback." << LL_ENDL; + mOohMorph = getVisualParam( "Express_Kiss" ); + } + + // If we don't have the Aah morph, use the Open Mouth morph + if (!mAahMorph) + { + LL_WARNS() << "Missing 'Aah' morph for lipsync, using fallback." << LL_ENDL; + mAahMorph = getVisualParam( "Express_Open_Mouth" ); + } + + // Currently disabled for control avatars (animated objects), enabled for all others. if (mEnableDefaultMotions) { - startDefaultMotions(); + startDefaultMotions(); } - //------------------------------------------------------------------------- - // restart any currently active motions - //------------------------------------------------------------------------- - processAnimationStateChanges(); + //------------------------------------------------------------------------- + // restart any currently active motions + //------------------------------------------------------------------------- + processAnimationStateChanges(); - mIsBuilt = TRUE; - stop_glerror(); + mIsBuilt = TRUE; + stop_glerror(); - mMeshValid = TRUE; + mMeshValid = TRUE; } //----------------------------------------------------------------------------- @@ -2036,30 +2036,30 @@ void LLVOAvatar::buildCharacter() //----------------------------------------------------------------------------- void LLVOAvatar::resetVisualParams() { - // Skeletal params - { - LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; - for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); - ++iter) - { - LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; - LLPolySkeletalDistortion *param = dynamic_cast(getVisualParam(info->getID())); + // Skeletal params + { + LLAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); + ++iter) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)*iter; + LLPolySkeletalDistortion *param = dynamic_cast(getVisualParam(info->getID())); *param = LLPolySkeletalDistortion(this); llassert(param); - if (!param->setInfo(info)) - { - llassert(false); - } - } - } - - // Driver parameters - for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); - iter != sAvatarXmlInfo->mDriverInfoList.end(); - ++iter) - { - LLDriverParamInfo *info = *iter; + if (!param->setInfo(info)) + { + llassert(false); + } + } + } + + // Driver parameters + for (LLAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); + ++iter) + { + LLDriverParamInfo *info = *iter; LLDriverParam *param = dynamic_cast(getVisualParam(info->getID())); LLDriverParam::entry_list_t driven_list = param->getDrivenList(); *param = LLDriverParam(this); @@ -2067,41 +2067,41 @@ void LLVOAvatar::resetVisualParams() if (!param->setInfo(info)) { llassert(false); - } + } param->setDrivenList(driven_list); - } + } } void LLVOAvatar::applyDefaultParams() { - // These are params from avs with newly created copies of shape, - // skin, hair, eyes, plus gender set as noted. Run arche_tool.py - // to get params from some other xml appearance dump. - std::map male_params = { - {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,255}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} - }; - std::map female_params = { - {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,0}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} - }; - std::map *params = NULL; - if (getSex() == SEX_MALE) - params = &male_params; - else - params = &female_params; - - for( auto it = params->begin(); it != params->end(); ++it) - { - LLVisualParam* param = getVisualParam(it->first); - if( !param ) - { - // invalid id - break; - } - - U8 value = it->second; - F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); - param->setWeight(newWeight); - } + // These are params from avs with newly created copies of shape, + // skin, hair, eyes, plus gender set as noted. Run arche_tool.py + // to get params from some other xml appearance dump. + std::map male_params = { + {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,255}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} + }; + std::map female_params = { + {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,0}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} + }; + std::map *params = NULL; + if (getSex() == SEX_MALE) + params = &male_params; + else + params = &female_params; + + for( auto it = params->begin(); it != params->end(); ++it) + { + LLVisualParam* param = getVisualParam(it->first); + if( !param ) + { + // invalid id + break; + } + + U8 value = it->second; + F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + param->setWeight(newWeight); + } } //----------------------------------------------------------------------------- @@ -2127,10 +2127,10 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) // just to get the right scale for the collision volumes, because // this will be used in setting the mJointScales for the // LLPolySkeletalDistortions of which the CVs are children. - if( !buildSkeleton(sAvatarSkeletonInfo) ) + if( !buildSkeleton(sAvatarSkeletonInfo) ) { LL_ERRS() << "Error resetting skeleton" << LL_ENDL; - } + } // Reset some params to default state, without propagating changes downstream. resetVisualParams(); @@ -2138,10 +2138,10 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) // Now we have to reset the skeleton again, because its state // got clobbered by the resetVisualParams() calls // above. - if( !buildSkeleton(sAvatarSkeletonInfo) ) + if( !buildSkeleton(sAvatarSkeletonInfo) ) { LL_ERRS() << "Error resetting skeleton" << LL_ENDL; - } + } // Reset attachment points // BuildSkeleton only does bones and CVs but we still need to reinit huds @@ -2150,7 +2150,7 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) initAttachmentPoints(ignore_hud_joints); // Fix up collision volumes - for (LLVisualParam *param = getFirstVisualParam(); + for (LLVisualParam *param = getFirstVisualParam(); param; param = getNextVisualParam()) { @@ -2166,30 +2166,30 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) } // Reset tweakable params to preserved state - if (getOverallAppearance() == AOA_NORMAL) - { - if (mLastProcessedAppearance) - { - bool slam_params = true; - applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); - } - } - else - { - // Stripped down approximation of - // applyParsedAppearanceMessage, but with alternative default - // (jellydoll) params - setCompositeUpdatesEnabled( FALSE ); - gPipeline.markGLRebuild(this); - applyDefaultParams(); - setCompositeUpdatesEnabled( TRUE ); - updateMeshTextures(); - updateMeshVisibility(); - } + if (getOverallAppearance() == AOA_NORMAL) + { + if (mLastProcessedAppearance) + { + bool slam_params = true; + applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); + } + } + else + { + // Stripped down approximation of + // applyParsedAppearanceMessage, but with alternative default + // (jellydoll) params + setCompositeUpdatesEnabled( FALSE ); + gPipeline.markGLRebuild(this); + applyDefaultParams(); + setCompositeUpdatesEnabled( TRUE ); + updateMeshTextures(); + updateMeshVisibility(); + } updateVisualParams(); // Restore attachment pos overrides - updateAttachmentOverrides(); + updateAttachmentOverrides(); // Animations if (reset_animations) @@ -2207,7 +2207,7 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) resetAnimations(); } } - + LL_DEBUGS("Avatar") << avString() << " reset ends" << LL_ENDL; } @@ -2216,49 +2216,49 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) //----------------------------------------------------------------------------- void LLVOAvatar::releaseMeshData() { - if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || isUIAvatar()) - { - return; - } - - // cleanup mesh data - for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); - ++iter) - { - LLAvatarJoint* joint = (*iter); - joint->setValid(FALSE, TRUE); - } - - //cleanup data - if (mDrawable.notNull()) - { - LLFace* facep = mDrawable->getFace(0); - if (facep) - { - facep->setSize(0, 0); - for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) - { - facep = mDrawable->getFace(i); - if (facep) - { - facep->setSize(0, 0); - } - } - } - } - - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (!attachment->getIsHUDAttachment()) - { - attachment->setAttachmentVisibility(FALSE); - } - } - mMeshValid = FALSE; + if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || isUIAvatar()) + { + return; + } + + // cleanup mesh data + for (avatar_joint_list_t::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); + ++iter) + { + LLAvatarJoint* joint = (*iter); + joint->setValid(FALSE, TRUE); + } + + //cleanup data + if (mDrawable.notNull()) + { + LLFace* facep = mDrawable->getFace(0); + if (facep) + { + facep->setSize(0, 0); + for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) + { + facep = mDrawable->getFace(i); + if (facep) + { + facep->setSize(0, 0); + } + } + } + } + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment->getIsHUDAttachment()) + { + attachment->setAttachmentVisibility(FALSE); + } + } + mMeshValid = FALSE; } //----------------------------------------------------------------------------- @@ -2267,29 +2267,29 @@ void LLVOAvatar::releaseMeshData() // virtual void LLVOAvatar::restoreMeshData() { - llassert(!isSelf()); + llassert(!isSelf()); if (mDrawable.isNull()) { return; } - - //LL_INFOS() << "Restoring" << LL_ENDL; - mMeshValid = TRUE; - updateJointLODs(); - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (!attachment->getIsHUDAttachment()) - { - attachment->setAttachmentVisibility(TRUE); - } - } + //LL_INFOS() << "Restoring" << LL_ENDL; + mMeshValid = TRUE; + updateJointLODs(); + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment->getIsHUDAttachment()) + { + attachment->setAttachmentVisibility(TRUE); + } + } - // force mesh update as LOD might not have changed to trigger this - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + // force mesh update as LOD might not have changed to trigger this + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); } //----------------------------------------------------------------------------- @@ -2297,149 +2297,149 @@ void LLVOAvatar::restoreMeshData() //----------------------------------------------------------------------------- void LLVOAvatar::updateMeshData() { - if (mDrawable.notNull()) - { - stop_glerror(); - - S32 f_num = 0 ; - const U32 VERTEX_NUMBER_THRESHOLD = 128 ;//small number of this means each part of an avatar has its own vertex buffer. - const S32 num_parts = mMeshLOD.size(); - - // this order is determined by number of LODS - // if a mesh earlier in this list changed LODs while a later mesh doesn't, - // the later mesh's index offset will be inaccurate - for(S32 part_index = 0 ; part_index < num_parts ;) - { - S32 j = part_index ; - U32 last_v_num = 0, num_vertices = 0 ; - U32 last_i_num = 0, num_indices = 0 ; - - while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD) - { - last_v_num = num_vertices ; - last_i_num = num_indices ; - - LLViewerJoint* part_mesh = getViewerJoint(part_index++); - if (part_mesh) - { - part_mesh->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); - } - } - if(num_vertices < 1)//skip empty meshes - { - continue ; - } - if(last_v_num > 0)//put the last inserted part into next vertex buffer. - { - num_vertices = last_v_num ; - num_indices = last_i_num ; - part_index-- ; - } - - LLFace* facep = NULL; - if(f_num < mDrawable->getNumFaces()) - { - facep = mDrawable->getFace(f_num); - } - else - { - facep = mDrawable->getFace(0); - if (facep) - { - facep = mDrawable->addFace(facep->getPool(), facep->getTexture()) ; - } - } - if (!facep) continue; - - // resize immediately - facep->setSize(num_vertices, num_indices); - - bool terse_update = false; - - facep->setGeomIndex(0); - facep->setIndicesIndex(0); - - LLVertexBuffer* buff = facep->getVertexBuffer(); - if(!facep->getVertexBuffer()) - { + if (mDrawable.notNull()) + { + stop_glerror(); + + S32 f_num = 0 ; + const U32 VERTEX_NUMBER_THRESHOLD = 128 ;//small number of this means each part of an avatar has its own vertex buffer. + const S32 num_parts = mMeshLOD.size(); + + // this order is determined by number of LODS + // if a mesh earlier in this list changed LODs while a later mesh doesn't, + // the later mesh's index offset will be inaccurate + for(S32 part_index = 0 ; part_index < num_parts ;) + { + S32 j = part_index ; + U32 last_v_num = 0, num_vertices = 0 ; + U32 last_i_num = 0, num_indices = 0 ; + + while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD) + { + last_v_num = num_vertices ; + last_i_num = num_indices ; + + LLViewerJoint* part_mesh = getViewerJoint(part_index++); + if (part_mesh) + { + part_mesh->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + } + } + if(num_vertices < 1)//skip empty meshes + { + continue ; + } + if(last_v_num > 0)//put the last inserted part into next vertex buffer. + { + num_vertices = last_v_num ; + num_indices = last_i_num ; + part_index-- ; + } + + LLFace* facep = NULL; + if(f_num < mDrawable->getNumFaces()) + { + facep = mDrawable->getFace(f_num); + } + else + { + facep = mDrawable->getFace(0); + if (facep) + { + facep = mDrawable->addFace(facep->getPool(), facep->getTexture()) ; + } + } + if (!facep) continue; + + // resize immediately + facep->setSize(num_vertices, num_indices); + + bool terse_update = false; + + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + + LLVertexBuffer* buff = facep->getVertexBuffer(); + if(!facep->getVertexBuffer()) + { buff = new LLVertexBuffer(LLDrawPoolAvatar::VERTEX_DATA_MASK); - if (!buff->allocateBuffer(num_vertices, num_indices)) - { - LL_WARNS() << "Failed to allocate Vertex Buffer for Mesh to " - << num_vertices << " vertices and " - << num_indices << " indices" << LL_ENDL; - // Attempt to create a dummy triangle (one vertex, 3 indices, all 0) - facep->setSize(1, 3); - buff->allocateBuffer(1, 3); - memset((U8*) buff->getMappedData(), 0, buff->getSize()); - memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize()); - } - facep->setVertexBuffer(buff); - } - else - { - if (buff->getNumIndices() == num_indices && - buff->getNumVerts() == num_vertices) - { - terse_update = true; - } - else - { + if (!buff->allocateBuffer(num_vertices, num_indices)) + { + LL_WARNS() << "Failed to allocate Vertex Buffer for Mesh to " + << num_vertices << " vertices and " + << num_indices << " indices" << LL_ENDL; + // Attempt to create a dummy triangle (one vertex, 3 indices, all 0) + facep->setSize(1, 3); + buff->allocateBuffer(1, 3); + memset((U8*) buff->getMappedData(), 0, buff->getSize()); + memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize()); + } + facep->setVertexBuffer(buff); + } + else + { + if (buff->getNumIndices() == num_indices && + buff->getNumVerts() == num_vertices) + { + terse_update = true; + } + else + { buff = new LLVertexBuffer(buff->getTypeMask()); if (!buff->allocateBuffer(num_vertices, num_indices)) { - LL_WARNS() << "Failed to allocate vertex buffer for Mesh, Substituting" << LL_ENDL; - // Attempt to create a dummy triangle (one vertex, 3 indices, all 0) - facep->setSize(1, 3); - buff->allocateBuffer(1, 3); - memset((U8*) buff->getMappedData(), 0, buff->getSize()); - memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize()); - } - } - } - - - // This is a hack! Avatars have their own pool, so we are detecting - // the case of more than one avatar in the pool (thus > 0 instead of >= 0) - if (facep->getGeomIndex() > 0) - { - LL_ERRS() << "non-zero geom index: " << facep->getGeomIndex() << " in LLVOAvatar::restoreMeshData" << LL_ENDL; - } - - if (num_vertices == buff->getNumVerts() && num_indices == buff->getNumIndices()) - { - for(S32 k = j ; k < part_index ; k++) - { - bool rigid = false; - if (k == MESH_ID_EYEBALL_LEFT || - k == MESH_ID_EYEBALL_RIGHT) - { - //eyeballs can't have terse updates since they're never rendered with - //the hardware skinning shader - rigid = true; - } - - LLViewerJoint* mesh = getViewerJoint(k); - if (mesh) - { - mesh->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); - } - } - } - - stop_glerror(); - buff->unmapBuffer(); - - if(!f_num) - { - f_num += mNumInitFaces ; - } - else - { - f_num++ ; - } - } - } + LL_WARNS() << "Failed to allocate vertex buffer for Mesh, Substituting" << LL_ENDL; + // Attempt to create a dummy triangle (one vertex, 3 indices, all 0) + facep->setSize(1, 3); + buff->allocateBuffer(1, 3); + memset((U8*) buff->getMappedData(), 0, buff->getSize()); + memset((U8*) buff->getMappedIndices(), 0, buff->getIndicesSize()); + } + } + } + + + // This is a hack! Avatars have their own pool, so we are detecting + // the case of more than one avatar in the pool (thus > 0 instead of >= 0) + if (facep->getGeomIndex() > 0) + { + LL_ERRS() << "non-zero geom index: " << facep->getGeomIndex() << " in LLVOAvatar::restoreMeshData" << LL_ENDL; + } + + if (num_vertices == buff->getNumVerts() && num_indices == buff->getNumIndices()) + { + for(S32 k = j ; k < part_index ; k++) + { + bool rigid = false; + if (k == MESH_ID_EYEBALL_LEFT || + k == MESH_ID_EYEBALL_RIGHT) + { + //eyeballs can't have terse updates since they're never rendered with + //the hardware skinning shader + rigid = true; + } + + LLViewerJoint* mesh = getViewerJoint(k); + if (mesh) + { + mesh->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update && !rigid); + } + } + } + + stop_glerror(); + buff->unmapBuffer(); + + if(!f_num) + { + f_num += mNumInitFaces ; + } + else + { + f_num++ ; + } + } + } } //------------------------------------------------------------------------ @@ -2448,78 +2448,78 @@ void LLVOAvatar::updateMeshData() // LLVOAvatar::processUpdateMessage() //------------------------------------------------------------------------ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, const EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, const EObjectUpdateType update_type, + LLDataPacker *dp) { - const BOOL has_name = !getNVPair("FirstName"); + const BOOL has_name = !getNVPair("FirstName"); - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + // Do base class updates... + U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - // Print out arrival information once we have name of avatar. + // Print out arrival information once we have name of avatar. if (has_name && getNVPair("FirstName")) { mDebugExistenceTimer.reset(); debugAvatarRezTime("AvatarRezArrivedNotification","avatar arrived"); } - if(retval & LLViewerObject::INVALID_UPDATE) - { - if (isSelf()) - { - //tell sim to cancel this update - gAgent.teleportViaLocation(gAgent.getPositionGlobal()); - } - } + if(retval & LLViewerObject::INVALID_UPDATE) + { + if (isSelf()) + { + //tell sim to cancel this update + gAgent.teleportViaLocation(gAgent.getPositionGlobal()); + } + } - return retval; + return retval; } LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUUID& uuid) { - LLViewerFetchedTexture *result = NULL; - - if (uuid == IMG_DEFAULT_AVATAR || - uuid == IMG_DEFAULT || - uuid == IMG_INVISIBLE) - { - // Should already exist, don't need to find it on sim or baked-texture host. - result = gTextureList.findImage(uuid, TEX_LIST_STANDARD); - } - if (!result) - { - const std::string url = getImageURL(te,uuid); - - if (url.empty()) - { - LL_WARNS() << "unable to determine URL for te " << te << " uuid " << uuid << LL_ENDL; - return NULL; - } - LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL; - result = LLViewerTextureManager::getFetchedTextureFromUrl( - url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); - if (result->isMissingAsset()) - { - result->setIsMissingAsset(false); - } - - } - return result; + LLViewerFetchedTexture *result = NULL; + + if (uuid == IMG_DEFAULT_AVATAR || + uuid == IMG_DEFAULT || + uuid == IMG_INVISIBLE) + { + // Should already exist, don't need to find it on sim or baked-texture host. + result = gTextureList.findImage(uuid, TEX_LIST_STANDARD); + } + if (!result) + { + const std::string url = getImageURL(te,uuid); + + if (url.empty()) + { + LL_WARNS() << "unable to determine URL for te " << te << " uuid " << uuid << LL_ENDL; + return NULL; + } + LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL; + result = LLViewerTextureManager::getFetchedTextureFromUrl( + url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + if (result->isMissingAsset()) + { + result->setIsMissingAsset(false); + } + + } + return result; } // virtual S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) { - if (!isIndexBakedTexture((ETextureIndex)te)) - { - // Sim still sends some uuids for non-baked slots sometimes - ignore. - return LLViewerObject::setTETexture(te, LLUUID::null); - } + if (!isIndexBakedTexture((ETextureIndex)te)) + { + // Sim still sends some uuids for non-baked slots sometimes - ignore. + return LLViewerObject::setTETexture(te, LLUUID::null); + } - LLViewerFetchedTexture *image = getBakedTextureImage(te,uuid); - llassert(image); - return setTETextureCore(te, image); + LLViewerFetchedTexture *image = getBakedTextureImage(te,uuid); + llassert(image); + return setTETextureCore(te, image); } //------------------------------------------------------------------------ @@ -2527,26 +2527,26 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) //------------------------------------------------------------------------ void LLVOAvatar::dumpAnimationState() { - LL_INFOS() << "==============================================" << LL_ENDL; - for (LLVOAvatar::AnimIterator it = mSignaledAnimations.begin(); it != mSignaledAnimations.end(); ++it) - { - LLUUID id = it->first; - std::string playtag = ""; - if (mPlayingAnimations.find(id) != mPlayingAnimations.end()) - { - playtag = "*"; - } - LL_INFOS() << gAnimLibrary.animationName(id) << playtag << LL_ENDL; - } - for (LLVOAvatar::AnimIterator it = mPlayingAnimations.begin(); it != mPlayingAnimations.end(); ++it) - { - LLUUID id = it->first; - bool is_signaled = mSignaledAnimations.find(id) != mSignaledAnimations.end(); - if (!is_signaled) - { - LL_INFOS() << gAnimLibrary.animationName(id) << "!S" << LL_ENDL; - } - } + LL_INFOS() << "==============================================" << LL_ENDL; + for (LLVOAvatar::AnimIterator it = mSignaledAnimations.begin(); it != mSignaledAnimations.end(); ++it) + { + LLUUID id = it->first; + std::string playtag = ""; + if (mPlayingAnimations.find(id) != mPlayingAnimations.end()) + { + playtag = "*"; + } + LL_INFOS() << gAnimLibrary.animationName(id) << playtag << LL_ENDL; + } + for (LLVOAvatar::AnimIterator it = mPlayingAnimations.begin(); it != mPlayingAnimations.end(); ++it) + { + LLUUID id = it->first; + bool is_signaled = mSignaledAnimations.find(id) != mSignaledAnimations.end(); + if (!is_signaled) + { + LL_INFOS() << gAnimLibrary.animationName(id) << "!S" << LL_ENDL; + } + } } //------------------------------------------------------------------------ @@ -2556,127 +2556,127 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (isDead()) - { - LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL; - return; - } + if (isDead()) + { + LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL; + return; + } // record time and refresh "tooSlow" status updateTooSlow(); - static LLCachedControl disable_all_render_types(gSavedSettings, "DisableAllRenderTypes"); - if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)) - && !disable_all_render_types && !isSelf()) - { + static LLCachedControl disable_all_render_types(gSavedSettings, "DisableAllRenderTypes"); + if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)) + && !disable_all_render_types && !isSelf()) + { if (!mIsControlAvatar) { idleUpdateNameTag(idleCalcNameTagPosition(mLastRootPos)); } - return; - } + return; + } // Update should be happening max once per frame. - if ((mLastAnimExtents[0]==LLVector3())|| - (mLastAnimExtents[1])==LLVector3()) - { - mNeedsExtentUpdate = true; - } - else - { - const S32 upd_freq = 4; // force update every upd_freq frames. - mNeedsExtentUpdate = ((LLDrawable::getCurrentFrame()+mID.mData[0])%upd_freq==0); - } - + if ((mLastAnimExtents[0]==LLVector3())|| + (mLastAnimExtents[1])==LLVector3()) + { + mNeedsExtentUpdate = true; + } + else + { + const S32 upd_freq = 4; // force update every upd_freq frames. + mNeedsExtentUpdate = ((LLDrawable::getCurrentFrame()+mID.mData[0])%upd_freq==0); + } + LLScopedContextString str("avatar_idle_update " + getFullname()); - - checkTextureLoading() ; - - // force immediate pixel area update on avatars using last frames data (before drawable or camera updates) - setPixelAreaAndAngle(gAgent); - - // force asynchronous drawable update - if(mDrawable.notNull()) - { - if (isSitting() && getParent()) - { - LLViewerObject *root_object = (LLViewerObject*)getRoot(); - LLDrawable* drawablep = root_object->mDrawable; - // if this object hasn't already been updated by another avatar... - if (drawablep) // && !drawablep->isState(LLDrawable::EARLY_MOVE)) - { - if (root_object->isSelected()) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - gPipeline.updateMoveDampedAsync(drawablep); - } - } - } - else - { - gPipeline.updateMoveDampedAsync(mDrawable); - } - } - - //-------------------------------------------------------------------- - // set alpha flag depending on state - //-------------------------------------------------------------------- - - if (isSelf()) - { - LLViewerObject::idleUpdate(agent, time); - - // trigger fidget anims - if (isAnyAnimationSignaled(AGENT_STAND_ANIMS, NUM_AGENT_STAND_ANIMS)) - { - agent.fidget(); - } - } - else - { - // Should override the idleUpdate stuff and leave out the angular update part. - LLQuaternion rotation = getRotation(); - LLViewerObject::idleUpdate(agent, time); - setRotation(rotation); - } - - // attach objects that were waiting for a drawable - lazyAttach(); - - // animate the character - // store off last frame's root position to be consistent with camera position - mLastRootPos = mRoot->getWorldPosition(); - BOOL detailed_update = updateCharacter(agent); - - static LLUICachedControl visualizers_in_calls("ShowVoiceVisualizersInCalls", false); - bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) && - LLVoiceClient::getInstance()->getVoiceEnabled(mID); - LLVector3 hud_name_pos = idleCalcNameTagPosition(mLastRootPos); + checkTextureLoading() ; - idleUpdateVoiceVisualizer(voice_enabled, hud_name_pos); - idleUpdateMisc( detailed_update ); - idleUpdateAppearanceAnimation(); - if (detailed_update) - { - idleUpdateLipSync( voice_enabled ); - idleUpdateLoadingEffect(); - idleUpdateBelowWater(); // wind effect uses this - idleUpdateWindEffect(); - } - - idleUpdateNameTag(hud_name_pos); + // force immediate pixel area update on avatars using last frames data (before drawable or camera updates) + setPixelAreaAndAngle(gAgent); - // Complexity has stale mechanics, but updates still can be very rapid - // so spread avatar complexity calculations over frames to lesen load from - // rapid updates and to make sure all avatars are not calculated at once. - S32 compl_upd_freq = 20; - if (isControlAvatar()) + // force asynchronous drawable update + if(mDrawable.notNull()) { - // animeshes do not (or won't) have impostors nor change outfis, - // no need for high frequency + if (isSitting() && getParent()) + { + LLViewerObject *root_object = (LLViewerObject*)getRoot(); + LLDrawable* drawablep = root_object->mDrawable; + // if this object hasn't already been updated by another avatar... + if (drawablep) // && !drawablep->isState(LLDrawable::EARLY_MOVE)) + { + if (root_object->isSelected()) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + gPipeline.updateMoveDampedAsync(drawablep); + } + } + } + else + { + gPipeline.updateMoveDampedAsync(mDrawable); + } + } + + //-------------------------------------------------------------------- + // set alpha flag depending on state + //-------------------------------------------------------------------- + + if (isSelf()) + { + LLViewerObject::idleUpdate(agent, time); + + // trigger fidget anims + if (isAnyAnimationSignaled(AGENT_STAND_ANIMS, NUM_AGENT_STAND_ANIMS)) + { + agent.fidget(); + } + } + else + { + // Should override the idleUpdate stuff and leave out the angular update part. + LLQuaternion rotation = getRotation(); + LLViewerObject::idleUpdate(agent, time); + setRotation(rotation); + } + + // attach objects that were waiting for a drawable + lazyAttach(); + + // animate the character + // store off last frame's root position to be consistent with camera position + mLastRootPos = mRoot->getWorldPosition(); + BOOL detailed_update = updateCharacter(agent); + + static LLUICachedControl visualizers_in_calls("ShowVoiceVisualizersInCalls", false); + bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) && + LLVoiceClient::getInstance()->getVoiceEnabled(mID); + + LLVector3 hud_name_pos = idleCalcNameTagPosition(mLastRootPos); + + idleUpdateVoiceVisualizer(voice_enabled, hud_name_pos); + idleUpdateMisc( detailed_update ); + idleUpdateAppearanceAnimation(); + if (detailed_update) + { + idleUpdateLipSync( voice_enabled ); + idleUpdateLoadingEffect(); + idleUpdateBelowWater(); // wind effect uses this + idleUpdateWindEffect(); + } + + idleUpdateNameTag(hud_name_pos); + + // Complexity has stale mechanics, but updates still can be very rapid + // so spread avatar complexity calculations over frames to lesen load from + // rapid updates and to make sure all avatars are not calculated at once. + S32 compl_upd_freq = 20; + if (isControlAvatar()) + { + // animeshes do not (or won't) have impostors nor change outfis, + // no need for high frequency compl_upd_freq = 100; } else if (mLastRezzedStatus <= 0) //cloud or init @@ -2698,7 +2698,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0) { - // DEPRECATED + // DEPRECATED // replace with LLPipeline::profileAvatar? // Avatar profile takes ~ 0.5ms while idleUpdateRenderComplexity takes ~5ms // (both are unacceptably costly) @@ -2709,96 +2709,96 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled, const LLVector3 &position) { - bool render_visualizer = voice_enabled; - - // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. - if(isSelf()) - { + bool render_visualizer = voice_enabled; + + // Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. + if(isSelf()) + { static LLCachedControl voice_disable_mic(gSavedSettings, "VoiceDisableMic"); - if(gAgentCamera.cameraMouselook() || voice_disable_mic) - { - render_visualizer = false; - } - } - - mVoiceVisualizer->setVoiceEnabled(render_visualizer); - - if ( voice_enabled ) - { - //---------------------------------------------------------------- - // Only do gesture triggering for your own avatar, and only when you're in a proximal channel. - //---------------------------------------------------------------- - if( isSelf() ) - { - //---------------------------------------------------------------------------------------- - // The following takes the voice signal and uses that to trigger gesticulations. - //---------------------------------------------------------------------------------------- - int lastGesticulationLevel = mCurrentGesticulationLevel; - mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel(); - - //--------------------------------------------------------------------------------------------------- - // If "current gesticulation level" changes, we catch this, and trigger the new gesture - //--------------------------------------------------------------------------------------------------- - if ( lastGesticulationLevel != mCurrentGesticulationLevel ) - { - if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF ) - { - std::string gestureString = "unInitialized"; - if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; } - else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; } - else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; } - else { LL_INFOS() << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << LL_ENDL; } - - // this is the call that Karl S. created for triggering gestures from within the code. - LLGestureMgr::instance().triggerAndReviseString( gestureString ); - } - } - - } //if( isSelf() ) - - //----------------------------------------------------------------------------------------------------------------- - // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer. - // Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol. - // - // Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been - // "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking. - //----------------------------------------------------------------------------------------------------------------- - if (LLVoiceClient::getInstance()->getIsSpeaking( mID )) - { - if (!mVoiceVisualizer->getCurrentlySpeaking()) - { - mVoiceVisualizer->setStartSpeaking(); - - //printf( "gAwayTimer.reset();\n" ); - } - - mVoiceVisualizer->setSpeakingAmplitude( LLVoiceClient::getInstance()->getCurrentPower( mID ) ); - - if( isSelf() ) - { - gAgent.clearAFK(); - } - } - else - { - if ( mVoiceVisualizer->getCurrentlySpeaking() ) - { - mVoiceVisualizer->setStopSpeaking(); - - if ( mLipSyncActive ) - { - if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight()); - if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight()); - - mLipSyncActive = false; - LLCharacter::updateVisualParams(); - dirtyMesh(); - } - } - } + if(gAgentCamera.cameraMouselook() || voice_disable_mic) + { + render_visualizer = false; + } + } + + mVoiceVisualizer->setVoiceEnabled(render_visualizer); + + if ( voice_enabled ) + { + //---------------------------------------------------------------- + // Only do gesture triggering for your own avatar, and only when you're in a proximal channel. + //---------------------------------------------------------------- + if( isSelf() ) + { + //---------------------------------------------------------------------------------------- + // The following takes the voice signal and uses that to trigger gesticulations. + //---------------------------------------------------------------------------------------- + int lastGesticulationLevel = mCurrentGesticulationLevel; + mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel(); + + //--------------------------------------------------------------------------------------------------- + // If "current gesticulation level" changes, we catch this, and trigger the new gesture + //--------------------------------------------------------------------------------------------------- + if ( lastGesticulationLevel != mCurrentGesticulationLevel ) + { + if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF ) + { + std::string gestureString = "unInitialized"; + if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; } + else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; } + else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; } + else { LL_INFOS() << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << LL_ENDL; } + + // this is the call that Karl S. created for triggering gestures from within the code. + LLGestureMgr::instance().triggerAndReviseString( gestureString ); + } + } + + } //if( isSelf() ) + + //----------------------------------------------------------------------------------------------------------------- + // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer. + // Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol. + // + // Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been + // "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking. + //----------------------------------------------------------------------------------------------------------------- + if (LLVoiceClient::getInstance()->getIsSpeaking( mID )) + { + if (!mVoiceVisualizer->getCurrentlySpeaking()) + { + mVoiceVisualizer->setStartSpeaking(); + + //printf( "gAwayTimer.reset();\n" ); + } + + mVoiceVisualizer->setSpeakingAmplitude( LLVoiceClient::getInstance()->getCurrentPower( mID ) ); + + if( isSelf() ) + { + gAgent.clearAFK(); + } + } + else + { + if ( mVoiceVisualizer->getCurrentlySpeaking() ) + { + mVoiceVisualizer->setStopSpeaking(); + + if ( mLipSyncActive ) + { + if( mOohMorph ) mOohMorph->setWeight(mOohMorph->getMinWeight()); + if( mAahMorph ) mAahMorph->setWeight(mAahMorph->getMinWeight()); + + mLipSyncActive = false; + LLCharacter::updateVisualParams(); + dirtyMesh(); + } + } + } mVoiceVisualizer->setPositionAgent(position); - }//if ( voiceEnabled ) -} + }//if ( voiceEnabled ) +} static void override_bbox(LLDrawable* drawable, LLVector4a* extents) { @@ -2811,31 +2811,31 @@ static void override_bbox(LLDrawable* drawable, LLVector4a* extents) void LLVOAvatar::idleUpdateMisc(bool detailed_update) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (LLVOAvatar::sJointDebug) - { - LL_INFOS() << getFullname() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << LL_ENDL; - } + if (LLVOAvatar::sJointDebug) + { + LL_INFOS() << getFullname() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << LL_ENDL; + } - LLJoint::sNumUpdates = 0; - LLJoint::sNumTouches = 0; + LLJoint::sNumUpdates = 0; + LLJoint::sNumTouches = 0; - BOOL visible = isVisible() || mNeedsAnimUpdate; + BOOL visible = isVisible() || mNeedsAnimUpdate; - // update attachments positions - if (detailed_update) - { + // update attachments positions + if (detailed_update) + { U32 draw_order = 0; S32 attachment_selected = LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment(); - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { LLViewerObject* attached_object = attachment_iter->get(); if (!attached_object || attached_object->isDead() @@ -2846,9 +2846,9 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge(); - - if (visible || !(bridge && bridge->getRadius() < 2.0)) - { + + if (visible || !(bridge && bridge->getRadius() < 2.0)) + { //override rigged attachments' octree spatial extents with this avatar's bounding box bool rigged = false; if (bridge) @@ -2902,839 +2902,839 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - attached_object->updateText(); - } - } - } - } - - mNeedsAnimUpdate = FALSE; - - if (isImpostor() && !mNeedsImpostorUpdate) - { - LL_ALIGN_16(LLVector4a ext[2]); - F32 distance; - LLVector3 angle; - - getImpostorValues(ext, angle, distance); - - for (U32 i = 0; i < 3 && !mNeedsImpostorUpdate; i++) - { - F32 cur_angle = angle.mV[i]; - F32 old_angle = mImpostorAngle.mV[i]; - F32 angle_diff = fabsf(cur_angle-old_angle); - - if (angle_diff > F_PI/512.f*distance*mUpdatePeriod) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 2; - } - } - - if (detailed_update && !mNeedsImpostorUpdate) - { //update impostor if view angle, distance, or bounding box change - //significantly - - F32 dist_diff = fabsf(distance-mImpostorDistance); - if (dist_diff/mImpostorDistance > 0.1f) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 3; - } - else - { - ext[0].load3(mLastAnimExtents[0].mV); + attached_object->updateText(); + } + } + } + } + + mNeedsAnimUpdate = FALSE; + + if (isImpostor() && !mNeedsImpostorUpdate) + { + LL_ALIGN_16(LLVector4a ext[2]); + F32 distance; + LLVector3 angle; + + getImpostorValues(ext, angle, distance); + + for (U32 i = 0; i < 3 && !mNeedsImpostorUpdate; i++) + { + F32 cur_angle = angle.mV[i]; + F32 old_angle = mImpostorAngle.mV[i]; + F32 angle_diff = fabsf(cur_angle-old_angle); + + if (angle_diff > F_PI/512.f*distance*mUpdatePeriod) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 2; + } + } + + if (detailed_update && !mNeedsImpostorUpdate) + { //update impostor if view angle, distance, or bounding box change + //significantly + + F32 dist_diff = fabsf(distance-mImpostorDistance); + if (dist_diff/mImpostorDistance > 0.1f) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 3; + } + else + { + ext[0].load3(mLastAnimExtents[0].mV); ext[1].load3(mLastAnimExtents[1].mV); // Expensive. Just call this once per frame, in updateSpatialExtents(); //calculateSpatialExtents(ext[0], ext[1]); - LLVector4a diff; - diff.setSub(ext[1], mImpostorExtents[1]); - if (diff.getLength3().getF32() > 0.05f) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 4; - } - else - { - diff.setSub(ext[0], mImpostorExtents[0]); - if (diff.getLength3().getF32() > 0.05f) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 5; - } - } - } - } - } + LLVector4a diff; + diff.setSub(ext[1], mImpostorExtents[1]); + if (diff.getLength3().getF32() > 0.05f) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 4; + } + else + { + diff.setSub(ext[0], mImpostorExtents[0]); + if (diff.getLength3().getF32() > 0.05f) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 5; + } + } + } + } + } if (mDrawable.notNull()) { - mDrawable->movePartition(); - - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) - { - gPipeline.markMoved(mDrawable, TRUE); - } + mDrawable->movePartition(); + + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + { + gPipeline.markMoved(mDrawable, TRUE); + } } } void LLVOAvatar::idleUpdateAppearanceAnimation() { - // update morphing params - if (mAppearanceAnimating) - { - ESex avatar_sex = getSex(); - F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); - if (appearance_anim_time >= APPEARANCE_MORPH_TIME) - { - mAppearanceAnimating = FALSE; - for (LLVisualParam *param = getFirstVisualParam(); - param; - param = getNextVisualParam()) - { - if (param->isTweakable()) - { - param->stopAnimating(); - } - } - updateVisualParams(); - } - else - { - F32 morph_amt = calcMorphAmount(); - LLVisualParam *param; - - if (!isSelf()) - { - // animate only top level params for non-self avatars - for (param = getFirstVisualParam(); - param; - param = getNextVisualParam()) - { - if (param->isTweakable()) - { - param->animate(morph_amt); - } - } - } - - // apply all params - for (param = getFirstVisualParam(); - param; - param = getNextVisualParam()) - { - param->apply(avatar_sex); - } - - mLastAppearanceBlendTime = appearance_anim_time; - } - dirtyMesh(); - } + // update morphing params + if (mAppearanceAnimating) + { + ESex avatar_sex = getSex(); + F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); + if (appearance_anim_time >= APPEARANCE_MORPH_TIME) + { + mAppearanceAnimating = FALSE; + for (LLVisualParam *param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + if (param->isTweakable()) + { + param->stopAnimating(); + } + } + updateVisualParams(); + } + else + { + F32 morph_amt = calcMorphAmount(); + LLVisualParam *param; + + if (!isSelf()) + { + // animate only top level params for non-self avatars + for (param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + if (param->isTweakable()) + { + param->animate(morph_amt); + } + } + } + + // apply all params + for (param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + param->apply(avatar_sex); + } + + mLastAppearanceBlendTime = appearance_anim_time; + } + dirtyMesh(); + } } F32 LLVOAvatar::calcMorphAmount() { - F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); - F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); - F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); + F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); + F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); + F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); - F32 morph_amt; - if (last_blend_frac == 1.f) - { - morph_amt = 1.f; - } - else - { - morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac); - } + F32 morph_amt; + if (last_blend_frac == 1.f) + { + morph_amt = 1.f; + } + else + { + morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac); + } - return morph_amt; + return morph_amt; } void LLVOAvatar::idleUpdateLipSync(bool voice_enabled) { - // Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync + // Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync if ( voice_enabled && mLastRezzedStatus > 0 // no point updating lip-sync for clouds && (LLVoiceClient::getInstance()->lipSyncEnabled()) && LLVoiceClient::getInstance()->getIsSpeaking( mID ) ) - { - F32 ooh_morph_amount = 0.0f; - F32 aah_morph_amount = 0.0f; + { + F32 ooh_morph_amount = 0.0f; + F32 aah_morph_amount = 0.0f; - mVoiceVisualizer->lipSyncOohAah( ooh_morph_amount, aah_morph_amount ); + mVoiceVisualizer->lipSyncOohAah( ooh_morph_amount, aah_morph_amount ); - if( mOohMorph ) - { - F32 ooh_weight = mOohMorph->getMinWeight() - + ooh_morph_amount * (mOohMorph->getMaxWeight() - mOohMorph->getMinWeight()); + if( mOohMorph ) + { + F32 ooh_weight = mOohMorph->getMinWeight() + + ooh_morph_amount * (mOohMorph->getMaxWeight() - mOohMorph->getMinWeight()); - mOohMorph->setWeight( ooh_weight); - } + mOohMorph->setWeight( ooh_weight); + } - if( mAahMorph ) - { - F32 aah_weight = mAahMorph->getMinWeight() - + aah_morph_amount * (mAahMorph->getMaxWeight() - mAahMorph->getMinWeight()); + if( mAahMorph ) + { + F32 aah_weight = mAahMorph->getMinWeight() + + aah_morph_amount * (mAahMorph->getMaxWeight() - mAahMorph->getMinWeight()); - mAahMorph->setWeight( aah_weight); - } + mAahMorph->setWeight( aah_weight); + } - mLipSyncActive = true; - LLCharacter::updateVisualParams(); - dirtyMesh(); - } + mLipSyncActive = true; + LLCharacter::updateVisualParams(); + dirtyMesh(); + } } void LLVOAvatar::idleUpdateLoadingEffect() { - // update visibility when avatar is partially loaded - if (updateIsFullyLoaded()) // changed? - { - if (isFullyLoaded()) - { - if (mFirstFullyVisible) - { - mFirstFullyVisible = FALSE; - if (isSelf()) - { - LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; - LLAppearanceMgr::instance().onFirstFullyVisible(); - } - else - { - LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; - } - } - - deleteParticleSource(); - updateLOD(); - } - else - { - LLPartSysData particle_parameters; - - // fancy particle cloud designed by Brent - particle_parameters.mPartData.mMaxAge = 4.f; - particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; - particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; - particle_parameters.mPartData.mStartScale.mV[VY] = 1.0f; - particle_parameters.mPartData.mEndScale.mV[VX] = 0.02f; - particle_parameters.mPartData.mEndScale.mV[VY] = 0.02f; - particle_parameters.mPartData.mStartColor = LLColor4(1, 1, 1, 0.5f); - particle_parameters.mPartData.mEndColor = LLColor4(1, 1, 1, 0.0f); - particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; - particle_parameters.mPartImageID = sCloudTexture->getID(); - particle_parameters.mMaxAge = 0.f; - particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE; - particle_parameters.mInnerAngle = F_PI; - particle_parameters.mOuterAngle = 0.f; - particle_parameters.mBurstRate = 0.02f; - particle_parameters.mBurstRadius = 0.0f; - particle_parameters.mBurstPartCount = 1; - particle_parameters.mBurstSpeedMin = 0.1f; - particle_parameters.mBurstSpeedMax = 1.f; - particle_parameters.mPartData.mFlags = ( LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | - LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK | - LLPartData::LL_PART_TARGET_POS_MASK ); - - // do not generate particles for dummy or overly-complex avatars - if (!mIsDummy && !isTooComplex() && !isTooSlow()) - { - setParticleSource(particle_parameters, getID()); - } - } - } -} + // update visibility when avatar is partially loaded + if (updateIsFullyLoaded()) // changed? + { + if (isFullyLoaded()) + { + if (mFirstFullyVisible) + { + mFirstFullyVisible = FALSE; + if (isSelf()) + { + LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + LLAppearanceMgr::instance().onFirstFullyVisible(); + } + else + { + LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL; + } + } + + deleteParticleSource(); + updateLOD(); + } + else + { + LLPartSysData particle_parameters; + + // fancy particle cloud designed by Brent + particle_parameters.mPartData.mMaxAge = 4.f; + particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; + particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; + particle_parameters.mPartData.mStartScale.mV[VY] = 1.0f; + particle_parameters.mPartData.mEndScale.mV[VX] = 0.02f; + particle_parameters.mPartData.mEndScale.mV[VY] = 0.02f; + particle_parameters.mPartData.mStartColor = LLColor4(1, 1, 1, 0.5f); + particle_parameters.mPartData.mEndColor = LLColor4(1, 1, 1, 0.0f); + particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f; + particle_parameters.mPartImageID = sCloudTexture->getID(); + particle_parameters.mMaxAge = 0.f; + particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE; + particle_parameters.mInnerAngle = F_PI; + particle_parameters.mOuterAngle = 0.f; + particle_parameters.mBurstRate = 0.02f; + particle_parameters.mBurstRadius = 0.0f; + particle_parameters.mBurstPartCount = 1; + particle_parameters.mBurstSpeedMin = 0.1f; + particle_parameters.mBurstSpeedMax = 1.f; + particle_parameters.mPartData.mFlags = ( LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | + LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK | + LLPartData::LL_PART_TARGET_POS_MASK ); + + // do not generate particles for dummy or overly-complex avatars + if (!mIsDummy && !isTooComplex() && !isTooSlow()) + { + setParticleSource(particle_parameters, getID()); + } + } + } +} void LLVOAvatar::idleUpdateWindEffect() { - // update wind effect - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) - { - F32 hover_strength = 0.f; - F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast; - mRippleTimeLast = mRippleTimer.getElapsedTimeF32(); - LLVector3 velocity = getVelocity(); - F32 speed = velocity.length(); - //RN: velocity varies too much frame to frame for this to work - mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLSmoothInterpolation::getInterpolant(0.02f)); - mLastVel = velocity; - LLVector4 wind; - wind.setVec(getRegion()->mWind.getVelocityNoisy(getPositionAgent(), 4.f) - velocity); - - if (mInAir) - { - hover_strength = HOVER_EFFECT_STRENGTH * llmax(0.f, HOVER_EFFECT_MAX_SPEED - speed); - } - - if (mBelowWater) - { - // TODO: make cloth flow more gracefully when underwater - hover_strength += UNDERWATER_EFFECT_STRENGTH; - } - - wind.mV[VZ] += hover_strength; - wind.normalize(); - - wind.mV[VW] = llmin(0.025f + (speed * 0.015f) + hover_strength, 0.5f); - F32 interp; - if (wind.mV[VW] > mWindVec.mV[VW]) - { - interp = LLSmoothInterpolation::getInterpolant(0.2f); - } - else - { - interp = LLSmoothInterpolation::getInterpolant(0.4f); - } - mWindVec = lerp(mWindVec, wind, interp); - - F32 wind_freq = hover_strength + llclamp(8.f + (speed * 0.7f) + (noise1(mRipplePhase) * 4.f), 8.f, 25.f); - mWindFreq = lerp(mWindFreq, wind_freq, interp); - - if (mBelowWater) - { - mWindFreq *= UNDERWATER_FREQUENCY_DAMP; - } - - mRipplePhase += (time_delta * mWindFreq); - if (mRipplePhase > F_TWO_PI) - { - mRipplePhase = fmodf(mRipplePhase, F_TWO_PI); - } - } + // update wind effect + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) + { + F32 hover_strength = 0.f; + F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast; + mRippleTimeLast = mRippleTimer.getElapsedTimeF32(); + LLVector3 velocity = getVelocity(); + F32 speed = velocity.length(); + //RN: velocity varies too much frame to frame for this to work + mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLSmoothInterpolation::getInterpolant(0.02f)); + mLastVel = velocity; + LLVector4 wind; + wind.setVec(getRegion()->mWind.getVelocityNoisy(getPositionAgent(), 4.f) - velocity); + + if (mInAir) + { + hover_strength = HOVER_EFFECT_STRENGTH * llmax(0.f, HOVER_EFFECT_MAX_SPEED - speed); + } + + if (mBelowWater) + { + // TODO: make cloth flow more gracefully when underwater + hover_strength += UNDERWATER_EFFECT_STRENGTH; + } + + wind.mV[VZ] += hover_strength; + wind.normalize(); + + wind.mV[VW] = llmin(0.025f + (speed * 0.015f) + hover_strength, 0.5f); + F32 interp; + if (wind.mV[VW] > mWindVec.mV[VW]) + { + interp = LLSmoothInterpolation::getInterpolant(0.2f); + } + else + { + interp = LLSmoothInterpolation::getInterpolant(0.4f); + } + mWindVec = lerp(mWindVec, wind, interp); + + F32 wind_freq = hover_strength + llclamp(8.f + (speed * 0.7f) + (noise1(mRipplePhase) * 4.f), 8.f, 25.f); + mWindFreq = lerp(mWindFreq, wind_freq, interp); + + if (mBelowWater) + { + mWindFreq *= UNDERWATER_FREQUENCY_DAMP; + } + + mRipplePhase += (time_delta * mWindFreq); + if (mRipplePhase > F_TWO_PI) + { + mRipplePhase = fmodf(mRipplePhase, F_TWO_PI); + } + } } void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - // update chat bubble - //-------------------------------------------------------------------- - // draw text label over character's head - //-------------------------------------------------------------------- - if (mChatTimer.getElapsedTimeF32() > BUBBLE_CHAT_TIME) - { - mChats.clear(); - } - - const F32 time_visible = mTimeVisible.getElapsedTimeF32(); + // update chat bubble + //-------------------------------------------------------------------- + // draw text label over character's head + //-------------------------------------------------------------------- + if (mChatTimer.getElapsedTimeF32() > BUBBLE_CHAT_TIME) + { + mChats.clear(); + } + + const F32 time_visible = mTimeVisible.getElapsedTimeF32(); static LLCachedControl NAME_SHOW_TIME(gSavedSettings, "RenderNameShowTime"); // seconds static LLCachedControl FADE_DURATION(gSavedSettings, "RenderNameFadeDuration"); // seconds static LLCachedControl use_chat_bubbles(gSavedSettings, "UseChatBubbles"); - bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping); - bool render_name = visible_chat || - (((sRenderName == RENDER_NAME_ALWAYS) || - (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); - // If it's your own avatar, don't draw in mouselook, and don't - // draw if we're specifically hiding our own name. - if (isSelf()) - { + bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping); + bool render_name = visible_chat || + (((sRenderName == RENDER_NAME_ALWAYS) || + (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); + // If it's your own avatar, don't draw in mouselook, and don't + // draw if we're specifically hiding our own name. + if (isSelf()) + { static LLCachedControl render_name_show_self(gSavedSettings, "RenderNameShowSelf"); static LLCachedControl name_tag_mode(gSavedSettings, "AvatarNameTagMode"); - render_name = render_name - && !gAgentCamera.cameraMouselook() - && (visible_chat || (render_name_show_self && name_tag_mode)); - } - - if ( !render_name ) - { - if (mNameText) - { - // ...clean up old name tag - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; - } - return; - } - - bool new_name = FALSE; - if (visible_chat != mVisibleChat) - { - mVisibleChat = visible_chat; - new_name = TRUE; - } - - if (sRenderGroupTitles != mRenderGroupTitles) - { - mRenderGroupTitles = sRenderGroupTitles; - new_name = TRUE; - } - - // First Calculate Alpha - // If alpha > 0, create mNameText if necessary, otherwise delete it - F32 alpha = 0.f; - if (mAppAngle > 5.f) - { - const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; - if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) - { - alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; - } - else - { - // ...not fading, full alpha - alpha = 1.f; - } - } - else if (mAppAngle > 2.f) - { - // far away is faded out also - alpha = (mAppAngle-2.f)/3.f; - } - - if (alpha <= 0.f) - { - if (mNameText) - { - mNameText->markDead(); - mNameText = NULL; - sNumVisibleChatBubbles--; - } - return; - } - - if (!mNameText) - { - mNameText = static_cast( LLHUDObject::addHUDObject( - LLHUDObject::LL_HUD_NAME_TAG) ); - //mNameText->setMass(10.f); - mNameText->setSourceObject(this); - mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); - mNameText->setVisibleOffScreen(TRUE); - mNameText->setMaxLines(11); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - sNumVisibleChatBubbles++; - new_name = TRUE; - } - - mNameText->setPositionAgent(root_pos_last); - - idleUpdateNameTagText(new_name); - idleUpdateNameTagAlpha(new_name, alpha); -} + render_name = render_name + && !gAgentCamera.cameraMouselook() + && (visible_chat || (render_name_show_self && name_tag_mode)); + } -void LLVOAvatar::idleUpdateNameTagText(bool new_name) -{ - LLNameValue *title = getNVPair("Title"); - LLNameValue* firstname = getNVPair("FirstName"); - LLNameValue* lastname = getNVPair("LastName"); - - // Avatars must have a first and last name - if (!firstname || !lastname) return; - - bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - bool is_do_not_disturb = mSignaledAnimations.find(ANIM_AGENT_DO_NOT_DISTURB) != mSignaledAnimations.end(); - bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); - bool is_muted; - if (isSelf()) - { - is_muted = false; - } - else - { - is_muted = isInMuteList(); - } - bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); - bool is_cloud = getIsCloud(); - - if (is_appearance != mNameAppearance) - { - if (is_appearance) - { - debugAvatarRezTime("AvatarRezEnteredAppearanceNotification","entered appearance mode"); - } - else - { - debugAvatarRezTime("AvatarRezLeftAppearanceNotification","left appearance mode"); - } - } - - // Rebuild name tag if state change detected - if (!mNameIsSet - || new_name - || (!title && !mTitle.empty()) - || (title && mTitle != title->getString()) - || is_away != mNameAway - || is_do_not_disturb != mNameDoNotDisturb - || is_muted != mNameMute - || is_appearance != mNameAppearance - || is_friend != mNameFriend - || is_cloud != mNameCloud) - { - LLColor4 name_tag_color = getNameTagColor(is_friend); - - clearNameTag(); - - if (is_away || is_muted || is_do_not_disturb || is_appearance) - { - std::string line; - if (is_away) - { - line += LLTrans::getString("AvatarAway"); - line += ", "; - } - if (is_do_not_disturb) - { - line += LLTrans::getString("AvatarDoNotDisturb"); - line += ", "; - } - if (is_muted) - { - line += LLTrans::getString("AvatarMuted"); - line += ", "; - } - if (is_appearance) - { - line += LLTrans::getString("AvatarEditingAppearance"); - line += ", "; - } - if (is_cloud) - { - line += LLTrans::getString("LoadingData"); - line += ", "; - } - // trim last ", " - line.resize( line.length() - 2 ); - addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); - } - - if (sRenderGroupTitles - && title && title->getString() && title->getString()[0] != '\0') - { - std::string title_str = title->getString(); - LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); - addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall(), true); - } - - static LLUICachedControl show_display_names("NameTagShowDisplayNames", true); - static LLUICachedControl show_usernames("NameTagShowUsernames", true); - - if (LLAvatarName::useDisplayNames()) - { - LLAvatarName av_name; - if (!LLAvatarNameCache::get(getID(), &av_name)) - { - // Force a rebuild at next idle - // Note: do not connect a callback on idle(). - clearNameTag(); - } - - // Might be blank if name not available yet, that's OK - if (show_display_names) - { - addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerif(), true); - } - // Suppress SLID display if display name matches exactly (ugh) - if (show_usernames && !av_name.isDisplayNameDefault()) - { - // *HACK: Desaturate the color - LLColor4 username_color = name_tag_color * 0.83f; - addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall(), true); - } - } - else - { - const LLFontGL* font = LLFontGL::getFontSansSerif(); - std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); - addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font, true); - } - - mNameAway = is_away; - mNameDoNotDisturb = is_do_not_disturb; - mNameMute = is_muted; - mNameAppearance = is_appearance; - mNameFriend = is_friend; - mNameCloud = is_cloud; - mTitle = title ? title->getString() : ""; - LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); - new_name = TRUE; - } - - if (mVisibleChat) - { - mNameText->setFont(LLFontGL::getFontSansSerif()); - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - - std::deque::iterator chat_iter = mChats.begin(); - mNameText->clearString(); - - LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); - LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); - LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); - if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) - { - ++chat_iter; - } - - for(; chat_iter != mChats.end(); ++chat_iter) - { - F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); - LLFontGL::StyleFlags style; - switch(chat_iter->mChatType) - { - case CHAT_TYPE_WHISPER: - style = LLFontGL::ITALIC; - break; - case CHAT_TYPE_SHOUT: - style = LLFontGL::BOLD; - break; - default: - style = LLFontGL::NORMAL; - break; - } - if (chat_fade_amt < 1.f) - { - F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); - } - else if (chat_fade_amt < 2.f) - { - F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); - mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); - } - else if (chat_fade_amt < 3.f) - { - // *NOTE: only remove lines down to minimum number - mNameText->addLine(chat_iter->mText, old_chat, style); - } - } - mNameText->setVisibleOffScreen(TRUE); - - if (mTyping) - { - S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; - switch(dot_count) - { - case 1: - mNameText->addLine(".", new_chat); - break; - case 2: - mNameText->addLine("..", new_chat); - break; - case 3: - mNameText->addLine("...", new_chat); - break; - } - - } - } - else - { - // ...not using chat bubbles, just names - mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); - mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); - mNameText->setVisibleOffScreen(FALSE); - } -} + if ( !render_name ) + { + if (mNameText) + { + // ...clean up old name tag + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; + } + return; + } -void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses) -{ - // extra width (NAMETAG_MAX_WIDTH) is for names only, not for chat - llassert(mNameText); - if (mVisibleChat) - { - mNameText->addLabel(line, LLHUDNameTag::NAMETAG_MAX_WIDTH); - } - else - { - mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font, use_ellipses, LLHUDNameTag::NAMETAG_MAX_WIDTH); - } - mNameIsSet |= !line.empty(); -} + bool new_name = FALSE; + if (visible_chat != mVisibleChat) + { + mVisibleChat = visible_chat; + new_name = TRUE; + } -void LLVOAvatar::clearNameTag() -{ - mNameIsSet = false; - if (mNameText) - { - mNameText->setLabel(""); - mNameText->setString(""); - } - mTimeVisible.reset(); -} + if (sRenderGroupTitles != mRenderGroupTitles) + { + mRenderGroupTitles = sRenderGroupTitles; + new_name = TRUE; + } -//static -void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id) -{ - LLViewerObject* obj = gObjectList.findObject(agent_id); - if (!obj) return; + // First Calculate Alpha + // If alpha > 0, create mNameText if necessary, otherwise delete it + F32 alpha = 0.f; + if (mAppAngle > 5.f) + { + const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; + if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) + { + alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; + } + else + { + // ...not fading, full alpha + alpha = 1.f; + } + } + else if (mAppAngle > 2.f) + { + // far away is faded out also + alpha = (mAppAngle-2.f)/3.f; + } - LLVOAvatar* avatar = dynamic_cast(obj); - if (!avatar) return; + if (alpha <= 0.f) + { + if (mNameText) + { + mNameText->markDead(); + mNameText = NULL; + sNumVisibleChatBubbles--; + } + return; + } - avatar->clearNameTag(); -} + if (!mNameText) + { + mNameText = static_cast( LLHUDObject::addHUDObject( + LLHUDObject::LL_HUD_NAME_TAG) ); + //mNameText->setMass(10.f); + mNameText->setSourceObject(this); + mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); + mNameText->setVisibleOffScreen(TRUE); + mNameText->setMaxLines(11); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + sNumVisibleChatBubbles++; + new_name = TRUE; + } -//static -void LLVOAvatar::invalidateNameTags() -{ - std::vector::iterator it = LLCharacter::sInstances.begin(); - for ( ; it != LLCharacter::sInstances.end(); ++it) - { - LLVOAvatar* avatar = dynamic_cast(*it); - if (!avatar) continue; - if (avatar->isDead()) continue; + mNameText->setPositionAgent(root_pos_last); - avatar->clearNameTag(); - } + idleUpdateNameTagText(new_name); + idleUpdateNameTagAlpha(new_name, alpha); } -// Compute name tag position during idle update -LLVector3 LLVOAvatar::idleCalcNameTagPosition(const LLVector3 &root_pos_last) +void LLVOAvatar::idleUpdateNameTagText(bool new_name) { - LLQuaternion root_rot = mRoot->getWorldRotation(); - LLQuaternion inv_root_rot = ~root_rot; - LLVector3 pixel_right_vec; - LLVector3 pixel_up_vec; - LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); - LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); - camera_to_av.normalize(); - LLVector3 local_camera_at = camera_to_av * inv_root_rot; - LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); - local_camera_up.normalize(); - local_camera_up = local_camera_up * inv_root_rot; - - // position is based on head position, does not require mAvatarOffset here. - Nyx - LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, - mBodySize.mV[VY] * 0.4f, - mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); - - local_camera_up.scaleVec(avatar_ellipsoid); - local_camera_at.scaleVec(avatar_ellipsoid); - - LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot->getLastWorldPosition()) * inv_root_rot; - - if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) - { - mTargetRootToHeadOffset = head_offset; - } - - mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLSmoothInterpolation::getInterpolant(0.2f)); - - LLVector3 name_position = mRoot->getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); - name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); - name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; - - const F32 water_height = getRegion()->getWaterHeight(); - static const F32 WATER_HEIGHT_DELTA = 0.25f; - if (name_position[VZ] < water_height + WATER_HEIGHT_DELTA) - { - if (LLViewerCamera::getInstance()->getOrigin()[VZ] >= water_height) - { - name_position[VZ] = water_height; - } - else if (mNameText) // both camera and HUD are below watermark - { - F32 name_world_height = mNameText->getWorldHeight(); - F32 max_z_position = water_height - name_world_height; - if (name_position[VZ] > max_z_position) - { - name_position[VZ] = max_z_position; - } - } - } - - return name_position; -} + LLNameValue *title = getNVPair("Title"); + LLNameValue* firstname = getNVPair("FirstName"); + LLNameValue* lastname = getNVPair("LastName"); -void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha) -{ - llassert(mNameText); + // Avatars must have a first and last name + if (!firstname || !lastname) return; - if (new_name - || alpha != mNameAlpha) - { - mNameText->setAlpha(alpha); - mNameAlpha = alpha; - } + bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); + bool is_do_not_disturb = mSignaledAnimations.find(ANIM_AGENT_DO_NOT_DISTURB) != mSignaledAnimations.end(); + bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); + bool is_muted; + if (isSelf()) + { + is_muted = false; + } + else + { + is_muted = isInMuteList(); + } + bool is_friend = LLAvatarTracker::instance().isBuddy(getID()); + bool is_cloud = getIsCloud(); + + if (is_appearance != mNameAppearance) + { + if (is_appearance) + { + debugAvatarRezTime("AvatarRezEnteredAppearanceNotification","entered appearance mode"); + } + else + { + debugAvatarRezTime("AvatarRezLeftAppearanceNotification","left appearance mode"); + } + } + + // Rebuild name tag if state change detected + if (!mNameIsSet + || new_name + || (!title && !mTitle.empty()) + || (title && mTitle != title->getString()) + || is_away != mNameAway + || is_do_not_disturb != mNameDoNotDisturb + || is_muted != mNameMute + || is_appearance != mNameAppearance + || is_friend != mNameFriend + || is_cloud != mNameCloud) + { + LLColor4 name_tag_color = getNameTagColor(is_friend); + + clearNameTag(); + + if (is_away || is_muted || is_do_not_disturb || is_appearance) + { + std::string line; + if (is_away) + { + line += LLTrans::getString("AvatarAway"); + line += ", "; + } + if (is_do_not_disturb) + { + line += LLTrans::getString("AvatarDoNotDisturb"); + line += ", "; + } + if (is_muted) + { + line += LLTrans::getString("AvatarMuted"); + line += ", "; + } + if (is_appearance) + { + line += LLTrans::getString("AvatarEditingAppearance"); + line += ", "; + } + if (is_cloud) + { + line += LLTrans::getString("LoadingData"); + line += ", "; + } + // trim last ", " + line.resize( line.length() - 2 ); + addNameTagLine(line, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall()); + } + + if (sRenderGroupTitles + && title && title->getString() && title->getString()[0] != '\0') + { + std::string title_str = title->getString(); + LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); + addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall(), true); + } + + static LLUICachedControl show_display_names("NameTagShowDisplayNames", true); + static LLUICachedControl show_usernames("NameTagShowUsernames", true); + + if (LLAvatarName::useDisplayNames()) + { + LLAvatarName av_name; + if (!LLAvatarNameCache::get(getID(), &av_name)) + { + // Force a rebuild at next idle + // Note: do not connect a callback on idle(). + clearNameTag(); + } + + // Might be blank if name not available yet, that's OK + if (show_display_names) + { + addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerif(), true); + } + // Suppress SLID display if display name matches exactly (ugh) + if (show_usernames && !av_name.isDisplayNameDefault()) + { + // *HACK: Desaturate the color + LLColor4 username_color = name_tag_color * 0.83f; + addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL, + LLFontGL::getFontSansSerifSmall(), true); + } + } + else + { + const LLFontGL* font = LLFontGL::getFontSansSerif(); + std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); + addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font, true); + } + + mNameAway = is_away; + mNameDoNotDisturb = is_do_not_disturb; + mNameMute = is_muted; + mNameAppearance = is_appearance; + mNameFriend = is_friend; + mNameCloud = is_cloud; + mTitle = title ? title->getString() : ""; + LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); + new_name = TRUE; + } + + if (mVisibleChat) + { + mNameText->setFont(LLFontGL::getFontSansSerif()); + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); + + std::deque::iterator chat_iter = mChats.begin(); + mNameText->clearString(); + + LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); + LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); + LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); + if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES) + { + ++chat_iter; + } + + for(; chat_iter != mChats.end(); ++chat_iter) + { + F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); + LLFontGL::StyleFlags style; + switch(chat_iter->mChatType) + { + case CHAT_TYPE_WHISPER: + style = LLFontGL::ITALIC; + break; + case CHAT_TYPE_SHOUT: + style = LLFontGL::BOLD; + break; + default: + style = LLFontGL::NORMAL; + break; + } + if (chat_fade_amt < 1.f) + { + F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); + } + else if (chat_fade_amt < 2.f) + { + F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); + mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); + } + else if (chat_fade_amt < 3.f) + { + // *NOTE: only remove lines down to minimum number + mNameText->addLine(chat_iter->mText, old_chat, style); + } + } + mNameText->setVisibleOffScreen(TRUE); + + if (mTyping) + { + S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; + switch(dot_count) + { + case 1: + mNameText->addLine(".", new_chat); + break; + case 2: + mNameText->addLine("..", new_chat); + break; + case 3: + mNameText->addLine("...", new_chat); + break; + } + + } + } + else + { + // ...not using chat bubbles, just names + mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); + mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); + mNameText->setVisibleOffScreen(FALSE); + } +} + +void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses) +{ + // extra width (NAMETAG_MAX_WIDTH) is for names only, not for chat + llassert(mNameText); + if (mVisibleChat) + { + mNameText->addLabel(line, LLHUDNameTag::NAMETAG_MAX_WIDTH); + } + else + { + mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font, use_ellipses, LLHUDNameTag::NAMETAG_MAX_WIDTH); + } + mNameIsSet |= !line.empty(); +} + +void LLVOAvatar::clearNameTag() +{ + mNameIsSet = false; + if (mNameText) + { + mNameText->setLabel(""); + mNameText->setString(""); + } + mTimeVisible.reset(); +} + +//static +void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id) +{ + LLViewerObject* obj = gObjectList.findObject(agent_id); + if (!obj) return; + + LLVOAvatar* avatar = dynamic_cast(obj); + if (!avatar) return; + + avatar->clearNameTag(); +} + +//static +void LLVOAvatar::invalidateNameTags() +{ + std::vector::iterator it = LLCharacter::sInstances.begin(); + for ( ; it != LLCharacter::sInstances.end(); ++it) + { + LLVOAvatar* avatar = dynamic_cast(*it); + if (!avatar) continue; + if (avatar->isDead()) continue; + + avatar->clearNameTag(); + } +} + +// Compute name tag position during idle update +LLVector3 LLVOAvatar::idleCalcNameTagPosition(const LLVector3 &root_pos_last) +{ + LLQuaternion root_rot = mRoot->getWorldRotation(); + LLQuaternion inv_root_rot = ~root_rot; + LLVector3 pixel_right_vec; + LLVector3 pixel_up_vec; + LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec); + LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin(); + camera_to_av.normalize(); + LLVector3 local_camera_at = camera_to_av * inv_root_rot; + LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis(); + local_camera_up.normalize(); + local_camera_up = local_camera_up * inv_root_rot; + + // position is based on head position, does not require mAvatarOffset here. - Nyx + LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, + mBodySize.mV[VY] * 0.4f, + mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); + + local_camera_up.scaleVec(avatar_ellipsoid); + local_camera_at.scaleVec(avatar_ellipsoid); + + LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot->getLastWorldPosition()) * inv_root_rot; + + if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) + { + mTargetRootToHeadOffset = head_offset; + } + + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLSmoothInterpolation::getInterpolant(0.2f)); + + LLVector3 name_position = mRoot->getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); + name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); + name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; + + const F32 water_height = getRegion()->getWaterHeight(); + static const F32 WATER_HEIGHT_DELTA = 0.25f; + if (name_position[VZ] < water_height + WATER_HEIGHT_DELTA) + { + if (LLViewerCamera::getInstance()->getOrigin()[VZ] >= water_height) + { + name_position[VZ] = water_height; + } + else if (mNameText) // both camera and HUD are below watermark + { + F32 name_world_height = mNameText->getWorldHeight(); + F32 max_z_position = water_height - name_world_height; + if (name_position[VZ] > max_z_position) + { + name_position[VZ] = max_z_position; + } + } + } + + return name_position; +} + +void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha) +{ + llassert(mNameText); + + if (new_name + || alpha != mNameAlpha) + { + mNameText->setAlpha(alpha); + mNameAlpha = alpha; + } } LLColor4 LLVOAvatar::getNameTagColor(bool is_friend) { - static LLUICachedControl show_friends("NameTagShowFriends", false); - const char* color_name; - if (show_friends && is_friend) - { - color_name = "NameTagFriend"; - } - else if (LLAvatarName::useDisplayNames()) - { - // ...color based on whether username "matches" a computed display name - LLAvatarName av_name; - if (LLAvatarNameCache::get(getID(), &av_name) && av_name.isDisplayNameDefault()) - { - color_name = "NameTagMatch"; - } - else - { - color_name = "NameTagMismatch"; - } - } - else - { - // ...not using display names - color_name = "NameTagLegacy"; - } - return LLUIColorTable::getInstance()->getColor( color_name ); + static LLUICachedControl show_friends("NameTagShowFriends", false); + const char* color_name; + if (show_friends && is_friend) + { + color_name = "NameTagFriend"; + } + else if (LLAvatarName::useDisplayNames()) + { + // ...color based on whether username "matches" a computed display name + LLAvatarName av_name; + if (LLAvatarNameCache::get(getID(), &av_name) && av_name.isDisplayNameDefault()) + { + color_name = "NameTagMatch"; + } + else + { + color_name = "NameTagMismatch"; + } + } + else + { + // ...not using display names + color_name = "NameTagLegacy"; + } + return LLUIColorTable::getInstance()->getColor( color_name ); } void LLVOAvatar::idleUpdateBelowWater() { - F32 avatar_height = (F32)(getPositionGlobal().mdV[VZ]); + F32 avatar_height = (F32)(getPositionGlobal().mdV[VZ]); - F32 water_height; - water_height = getRegion()->getWaterHeight(); + F32 water_height; + water_height = getRegion()->getWaterHeight(); - mBelowWater = avatar_height < water_height; + mBelowWater = avatar_height < water_height; } void LLVOAvatar::slamPosition() { - gAgent.setPositionAgent(getPositionAgent()); - // SL-315 - mRoot->setWorldPosition(getPositionAgent()); // teleport - setChanged(TRANSLATED); - if (mDrawable.notNull()) - { - gPipeline.updateMoveNormalAsync(mDrawable); - } - mRoot->updateWorldMatrixChildren(); + gAgent.setPositionAgent(getPositionAgent()); + // SL-315 + mRoot->setWorldPosition(getPositionAgent()); // teleport + setChanged(TRANSLATED); + if (mDrawable.notNull()) + { + gPipeline.updateMoveNormalAsync(mDrawable); + } + mRoot->updateWorldMatrixChildren(); } bool LLVOAvatar::isVisuallyMuted() { - bool muted = false; - - // Priority order (highest priority first) - // * own avatar is never visually muted - // * if on the "always draw normally" list, draw them normally - // * if on the "always visually mute" list, mute them - // * check against the render cost and attachment limits - if (!isSelf()) - { - if (mVisuallyMuteSetting == AV_ALWAYS_RENDER) - { - muted = false; - } - else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) - { + bool muted = false; + + // Priority order (highest priority first) + // * own avatar is never visually muted + // * if on the "always draw normally" list, draw them normally + // * if on the "always visually mute" list, mute them + // * check against the render cost and attachment limits + if (!isSelf()) + { + if (mVisuallyMuteSetting == AV_ALWAYS_RENDER) + { + muted = false; + } + else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) + { #ifdef JELLYDOLLS_SHOULD_IMPOSTOR - muted = true; - // Always want to see this AV as an impostor + muted = true; + // Always want to see this AV as an impostor #else - muted = false; + muted = false; #endif - } + } else if (isInMuteList()) { muted = true; @@ -3743,89 +3743,89 @@ bool LLVOAvatar::isVisuallyMuted() { muted = isTooSlow(); } - else - { - muted = isTooComplex() || isTooSlow(); - } - } + else + { + muted = isTooComplex() || isTooSlow(); + } + } - return muted; + return muted; } bool LLVOAvatar::isInMuteList() const { - bool muted = false; - F64 now = LLFrameTimer::getTotalSeconds(); - if (now < mCachedMuteListUpdateTime) - { - muted = mCachedInMuteList; - } - else - { - muted = LLMuteList::getInstance()->isMuted(getID()); + bool muted = false; + F64 now = LLFrameTimer::getTotalSeconds(); + if (now < mCachedMuteListUpdateTime) + { + muted = mCachedInMuteList; + } + else + { + muted = LLMuteList::getInstance()->isMuted(getID()); - const F64 SECONDS_BETWEEN_MUTE_UPDATES = 1; - mCachedMuteListUpdateTime = now + SECONDS_BETWEEN_MUTE_UPDATES; - mCachedInMuteList = muted; - } - return muted; + const F64 SECONDS_BETWEEN_MUTE_UPDATES = 1; + mCachedMuteListUpdateTime = now + SECONDS_BETWEEN_MUTE_UPDATES; + mCachedInMuteList = muted; + } + return muted; } void LLVOAvatar::updateAppearanceMessageDebugText() { - S32 central_bake_version = -1; - if (getRegion()) - { - central_bake_version = getRegion()->getCentralBakeVersion(); - } - bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); - bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); - std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", - isSelf() ? (all_local_downloaded ? "L" : "l") : "-", - all_baked_downloaded ? "B" : "b", - mUseLocalAppearance, mIsEditingAppearance, - 1, central_bake_version); - std::string origin_string = bakedTextureOriginInfo(); - debug_line += " [" + origin_string + "]"; - S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); - S32 last_request_cof_version = mLastUpdateRequestCOFVersion; - S32 last_received_cof_version = mLastUpdateReceivedCOFVersion; - if (isSelf()) - { - debug_line += llformat(" - cof: %d req: %d rcv:%d", - curr_cof_version, last_request_cof_version, last_received_cof_version); - static LLCachedControl debug_force_failure(gSavedSettings, "DebugForceAppearanceRequestFailure"); - if (debug_force_failure) - { - debug_line += " FORCING ERRS"; - } - } - else - { - debug_line += llformat(" - cof rcv:%d", last_received_cof_version); - } - debug_line += llformat(" bsz-z: %.3f", mBodySize[2]); + S32 central_bake_version = -1; + if (getRegion()) + { + central_bake_version = getRegion()->getCentralBakeVersion(); + } + bool all_baked_downloaded = allBakedTexturesCompletelyDownloaded(); + bool all_local_downloaded = allLocalTexturesCompletelyDownloaded(); + std::string debug_line = llformat("%s%s - mLocal: %d, mEdit: %d, mUSB: %d, CBV: %d", + isSelf() ? (all_local_downloaded ? "L" : "l") : "-", + all_baked_downloaded ? "B" : "b", + mUseLocalAppearance, mIsEditingAppearance, + 1, central_bake_version); + std::string origin_string = bakedTextureOriginInfo(); + debug_line += " [" + origin_string + "]"; + S32 curr_cof_version = LLAppearanceMgr::instance().getCOFVersion(); + S32 last_request_cof_version = mLastUpdateRequestCOFVersion; + S32 last_received_cof_version = mLastUpdateReceivedCOFVersion; + if (isSelf()) + { + debug_line += llformat(" - cof: %d req: %d rcv:%d", + curr_cof_version, last_request_cof_version, last_received_cof_version); + static LLCachedControl debug_force_failure(gSavedSettings, "DebugForceAppearanceRequestFailure"); + if (debug_force_failure) + { + debug_line += " FORCING ERRS"; + } + } + else + { + debug_line += llformat(" - cof rcv:%d", last_received_cof_version); + } + debug_line += llformat(" bsz-z: %.3f", mBodySize[2]); if (mAvatarOffset[2] != 0.0f) { debug_line += llformat("avofs-z: %.3f", mAvatarOffset[2]); } - bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled(); - debug_line += hover_enabled ? " H" : " h"; - const LLVector3& hover_offset = getHoverOffset(); - if (hover_offset[2] != 0.0) - { - debug_line += llformat(" hov_z: %.3f", hover_offset[2]); - debug_line += llformat(" %s", (isSitting() ? "S" : "T")); - debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); - } - if (mInAir) - { - debug_line += " A"; - - } + bool hover_enabled = getRegion() && getRegion()->avatarHoverHeightEnabled(); + debug_line += hover_enabled ? " H" : " h"; + const LLVector3& hover_offset = getHoverOffset(); + if (hover_offset[2] != 0.0) + { + debug_line += llformat(" hov_z: %.3f", hover_offset[2]); + debug_line += llformat(" %s", (isSitting() ? "S" : "T")); + debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); + } + if (mInAir) + { + debug_line += " A"; + + } LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); - LLVector3 normal; + LLVector3 normal; LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); @@ -3835,40 +3835,40 @@ void LLVOAvatar::updateAppearanceMessageDebugText() LLVector3 pelvis_pos = mPelvisp->getPosition(); debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]); - const LLVector3& scale = getScale(); - debug_line += llformat(" scale-z %.3f", scale[2]); - S32 is_visible = (S32) isVisible(); - S32 is_m_visible = (S32) mVisible; - debug_line += llformat(" v %d/%d", is_visible, is_m_visible); - - AvatarOverallAppearance aoa = getOverallAppearance(); - if (aoa == AOA_NORMAL) - { - debug_line += " N"; - } - else if (aoa == AOA_JELLYDOLL) - { - debug_line += " J"; - } - else - { - debug_line += " I"; - } - - if (mMeshValid) - { - debug_line += "m"; - } - else - { - debug_line += "-"; - } - if (isImpostor()) - { - debug_line += " Imp" + llformat("%d[%d]:%.1f", mUpdatePeriod, mLastImpostorUpdateReason, ((F32)(gFrameTimeSeconds-mLastImpostorUpdateFrameTime))); - } - - addDebugText(debug_line); + const LLVector3& scale = getScale(); + debug_line += llformat(" scale-z %.3f", scale[2]); + S32 is_visible = (S32) isVisible(); + S32 is_m_visible = (S32) mVisible; + debug_line += llformat(" v %d/%d", is_visible, is_m_visible); + + AvatarOverallAppearance aoa = getOverallAppearance(); + if (aoa == AOA_NORMAL) + { + debug_line += " N"; + } + else if (aoa == AOA_JELLYDOLL) + { + debug_line += " J"; + } + else + { + debug_line += " I"; + } + + if (mMeshValid) + { + debug_line += "m"; + } + else + { + debug_line += "-"; + } + if (isImpostor()) + { + debug_line += " Imp" + llformat("%d[%d]:%.1f", mUpdatePeriod, mLastImpostorUpdateReason, ((F32)(gFrameTimeSeconds-mLastImpostorUpdateFrameTime))); + } + + addDebugText(debug_line); } LLViewerInventoryItem* getObjectInventoryItem(LLViewerObject *vobj, LLUUID asset_id) @@ -3879,8 +3879,8 @@ LLViewerInventoryItem* getObjectInventoryItem(LLViewerObject *vobj, LLUUID asset { if (vobj->getInventorySerial()<=0) { - vobj->requestInventory(); - } + vobj->requestInventory(); + } item = vobj->getInventoryItemByAsset(asset_id); } return item; @@ -3898,23 +3898,23 @@ LLViewerInventoryItem* recursiveGetObjectInventoryItem(LLViewerObject *vobj, LLU LLViewerObject *childp = *it; item = getObjectInventoryItem(childp, asset_id); if (item) - { + { break; } } - } + } return item; } void LLVOAvatar::updateAnimationDebugText() { - for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); - iter != mMotionController.getActiveMotions().end(); ++iter) - { - LLMotion* motionp = *iter; - if (motionp->getMinPixelArea() < getPixelArea()) - { - std::string output; + for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); + iter != mMotionController.getActiveMotions().end(); ++iter) + { + LLMotion* motionp = *iter; + if (motionp->getMinPixelArea() < getPixelArea()) + { + std::string output; std::string motion_name = motionp->getName(); if (motion_name.empty()) { @@ -3931,107 +3931,107 @@ void LLVOAvatar::updateAnimationDebugText() } } if (motion_name.empty()) - { - std::string name; - if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf()) - { - name = motionp->getID().asString(); - LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin(); - for (; anim_it != mAnimationSources.end(); ++anim_it) - { - if (anim_it->second == motionp->getID()) - { - LLViewerObject* object = gObjectList.findObject(anim_it->first); - if (!object) - { - break; - } - if (object->isAvatar()) - { - if (mMotionController.mIsSelf) - { - // Searching inventory by asset id is really long - // so just mark as inventory - // Also item is likely to be named by LLPreviewAnim - name += "(inventory)"; - } - } - else - { - LLViewerInventoryItem* item = NULL; - if (!object->isInventoryDirty()) - { - item = object->getInventoryItemByAsset(motionp->getID()); - } - if (item) - { - name = item->getName(); - } - else if (object->isAttachment()) - { - name += "(att:" + getAttachmentItemName() + ")"; - } - else - { - // in-world object, name or content unknown - name += "(in-world)"; - } - } - break; - } - } - } - else - { - name = LLUUID::null.asString(); - } - motion_name = name; - } - std::string motion_tag = ""; - if (mPlayingAnimations.find(motionp->getID()) != mPlayingAnimations.end()) - { - motion_tag = "*"; - } - output = llformat("%s%s - %d", - motion_name.c_str(), - motion_tag.c_str(), - (U32)motionp->getPriority()); - addDebugText(output); - } - } + { + std::string name; + if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf()) + { + name = motionp->getID().asString(); + LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin(); + for (; anim_it != mAnimationSources.end(); ++anim_it) + { + if (anim_it->second == motionp->getID()) + { + LLViewerObject* object = gObjectList.findObject(anim_it->first); + if (!object) + { + break; + } + if (object->isAvatar()) + { + if (mMotionController.mIsSelf) + { + // Searching inventory by asset id is really long + // so just mark as inventory + // Also item is likely to be named by LLPreviewAnim + name += "(inventory)"; + } + } + else + { + LLViewerInventoryItem* item = NULL; + if (!object->isInventoryDirty()) + { + item = object->getInventoryItemByAsset(motionp->getID()); + } + if (item) + { + name = item->getName(); + } + else if (object->isAttachment()) + { + name += "(att:" + getAttachmentItemName() + ")"; + } + else + { + // in-world object, name or content unknown + name += "(in-world)"; + } + } + break; + } + } + } + else + { + name = LLUUID::null.asString(); + } + motion_name = name; + } + std::string motion_tag = ""; + if (mPlayingAnimations.find(motionp->getID()) != mPlayingAnimations.end()) + { + motion_tag = "*"; + } + output = llformat("%s%s - %d", + motion_name.c_str(), + motion_tag.c_str(), + (U32)motionp->getPriority()); + addDebugText(output); + } + } } void LLVOAvatar::updateDebugText() { // Leave mDebugText uncleared here, in case a derived class has added some state first - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { updateAppearanceMessageDebugText(); - } + } - if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) - { - if (!mBakedTextureDebugText.empty()) - addDebugText(mBakedTextureDebugText); - } + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + if (!mBakedTextureDebugText.empty()) + addDebugText(mBakedTextureDebugText); + } // Develop -> Avatar -> Animation Info - if (LLVOAvatar::sShowAnimationDebug) - { + if (LLVOAvatar::sShowAnimationDebug) + { updateAnimationDebugText(); - } + } - if (!mDebugText.size() && mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - else if (mDebugText.size()) - { - setDebugText(mDebugText); - } - mDebugText.clear(); + if (!mDebugText.size() && mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + else if (mDebugText.size()) + { + setDebugText(mDebugText); + } + mDebugText.clear(); } //------------------------------------------------------------------------ @@ -4045,87 +4045,87 @@ void LLVOAvatar::updateFootstepSounds() { return; } - - //------------------------------------------------------------------------- - // Find the ground under each foot, these are used for a variety - // of things that follow - //------------------------------------------------------------------------- - LLVector3 ankle_left_pos_agent = mFootLeftp->getWorldPosition(); - LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); - LLVector3 ankle_left_ground_agent = ankle_left_pos_agent; - LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; + //------------------------------------------------------------------------- + // Find the ground under each foot, these are used for a variety + // of things that follow + //------------------------------------------------------------------------- + LLVector3 ankle_left_pos_agent = mFootLeftp->getWorldPosition(); + LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); + + LLVector3 ankle_left_ground_agent = ankle_left_pos_agent; + LLVector3 ankle_right_ground_agent = ankle_right_pos_agent; LLVector3 normal; - resolveHeightAgent(ankle_left_pos_agent, ankle_left_ground_agent, normal); - resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); - - F32 leftElev = llmax(-0.2f, ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]); - F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); - - if (!isSitting()) - { - //------------------------------------------------------------------------- - // Figure out which foot is on ground - //------------------------------------------------------------------------- - if (!mInAir) - { - if ((leftElev < 0.0f) || (rightElev < 0.0f)) - { - ankle_left_pos_agent = mFootLeftp->getWorldPosition(); - ankle_right_pos_agent = mFootRightp->getWorldPosition(); - leftElev = ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]; - rightElev = ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]; - } - } - } - - const LLUUID AGENT_FOOTSTEP_ANIMS[] = {ANIM_AGENT_WALK, ANIM_AGENT_RUN, ANIM_AGENT_LAND}; - const S32 NUM_AGENT_FOOTSTEP_ANIMS = LL_ARRAY_SIZE(AGENT_FOOTSTEP_ANIMS); - - if ( gAudiop && isAnyAnimationSignaled(AGENT_FOOTSTEP_ANIMS, NUM_AGENT_FOOTSTEP_ANIMS) ) - { - BOOL playSound = FALSE; - LLVector3 foot_pos_agent; - - BOOL onGroundLeft = (leftElev <= 0.05f); - BOOL onGroundRight = (rightElev <= 0.05f); - - // did left foot hit the ground? - if ( onGroundLeft && !mWasOnGroundLeft ) - { - foot_pos_agent = ankle_left_pos_agent; - playSound = TRUE; - } - - // did right foot hit the ground? - if ( onGroundRight && !mWasOnGroundRight ) - { - foot_pos_agent = ankle_right_pos_agent; - playSound = TRUE; - } - - mWasOnGroundLeft = onGroundLeft; - mWasOnGroundRight = onGroundRight; - - if ( playSound ) - { - const F32 STEP_VOLUME = 0.1f; - const LLUUID& step_sound_id = getStepSound(); - - LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); - - if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) - && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) - { - gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); - } - } - } -} + resolveHeightAgent(ankle_left_pos_agent, ankle_left_ground_agent, normal); + resolveHeightAgent(ankle_right_pos_agent, ankle_right_ground_agent, normal); -//------------------------------------------------------------------------ -// computeUpdatePeriod() -// Factored out from updateCharacter() + F32 leftElev = llmax(-0.2f, ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]); + F32 rightElev = llmax(-0.2f, ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]); + + if (!isSitting()) + { + //------------------------------------------------------------------------- + // Figure out which foot is on ground + //------------------------------------------------------------------------- + if (!mInAir) + { + if ((leftElev < 0.0f) || (rightElev < 0.0f)) + { + ankle_left_pos_agent = mFootLeftp->getWorldPosition(); + ankle_right_pos_agent = mFootRightp->getWorldPosition(); + leftElev = ankle_left_pos_agent.mV[VZ] - ankle_left_ground_agent.mV[VZ]; + rightElev = ankle_right_pos_agent.mV[VZ] - ankle_right_ground_agent.mV[VZ]; + } + } + } + + const LLUUID AGENT_FOOTSTEP_ANIMS[] = {ANIM_AGENT_WALK, ANIM_AGENT_RUN, ANIM_AGENT_LAND}; + const S32 NUM_AGENT_FOOTSTEP_ANIMS = LL_ARRAY_SIZE(AGENT_FOOTSTEP_ANIMS); + + if ( gAudiop && isAnyAnimationSignaled(AGENT_FOOTSTEP_ANIMS, NUM_AGENT_FOOTSTEP_ANIMS) ) + { + BOOL playSound = FALSE; + LLVector3 foot_pos_agent; + + BOOL onGroundLeft = (leftElev <= 0.05f); + BOOL onGroundRight = (rightElev <= 0.05f); + + // did left foot hit the ground? + if ( onGroundLeft && !mWasOnGroundLeft ) + { + foot_pos_agent = ankle_left_pos_agent; + playSound = TRUE; + } + + // did right foot hit the ground? + if ( onGroundRight && !mWasOnGroundRight ) + { + foot_pos_agent = ankle_right_pos_agent; + playSound = TRUE; + } + + mWasOnGroundLeft = onGroundLeft; + mWasOnGroundRight = onGroundRight; + + if ( playSound ) + { + const F32 STEP_VOLUME = 0.1f; + const LLUUID& step_sound_id = getStepSound(); + + LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); + + if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) + && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) + { + gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); + } + } + } +} + +//------------------------------------------------------------------------ +// computeUpdatePeriod() +// Factored out from updateCharacter() // Set new value for mUpdatePeriod based on distance and various other factors. // // Note 10-2020: it turns out that none of these update period @@ -4137,57 +4137,57 @@ void LLVOAvatar::updateFootstepSounds() // ------------------------------------------------------------------------ void LLVOAvatar::computeUpdatePeriod() { - bool visually_muted = isVisuallyMuted(); - if (mDrawable.notNull() - && isVisible() + bool visually_muted = isVisuallyMuted(); + if (mDrawable.notNull() + && isVisible() && (!isSelf() || visually_muted) && !isUIAvatar() && (sLimitNonImpostors || visually_muted) && !mNeedsAnimUpdate) - { - const LLVector4a* ext = mDrawable->getSpatialExtents(); - LLVector4a size; - size.setSub(ext[1],ext[0]); - F32 mag = size.getLength3().getF32()*0.5f; - - const S32 UPDATE_RATE_SLOW = 64; - const S32 UPDATE_RATE_MED = 48; - const S32 UPDATE_RATE_FAST = 32; - - if (visually_muted) - { // visually muted avatars update at lowest rate - mUpdatePeriod = UPDATE_RATE_SLOW; - } - else if (! shouldImpostor() - || mDrawable->mDistanceWRTCamera < 1.f + mag) - { // first 25% of max visible avatars are not impostored - // also, don't impostor avatars whose bounding box may be penetrating the - // impostor camera near clip plane - mUpdatePeriod = 1; - } - else if ( shouldImpostor(4.0) ) - { //background avatars are REALLY slow updating impostors - mUpdatePeriod = UPDATE_RATE_SLOW; - } - else if (mLastRezzedStatus <= 0) - { - // Don't update cloud avatars too often - mUpdatePeriod = UPDATE_RATE_SLOW; - } - else if ( shouldImpostor(3.0) ) - { //back 25% of max visible avatars are slow updating impostors - mUpdatePeriod = UPDATE_RATE_MED; - } - else - { - //nearby avatars, update the impostors more frequently. - mUpdatePeriod = UPDATE_RATE_FAST; - } - } - else - { - mUpdatePeriod = 1; - } + { + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a size; + size.setSub(ext[1],ext[0]); + F32 mag = size.getLength3().getF32()*0.5f; + + const S32 UPDATE_RATE_SLOW = 64; + const S32 UPDATE_RATE_MED = 48; + const S32 UPDATE_RATE_FAST = 32; + + if (visually_muted) + { // visually muted avatars update at lowest rate + mUpdatePeriod = UPDATE_RATE_SLOW; + } + else if (! shouldImpostor() + || mDrawable->mDistanceWRTCamera < 1.f + mag) + { // first 25% of max visible avatars are not impostored + // also, don't impostor avatars whose bounding box may be penetrating the + // impostor camera near clip plane + mUpdatePeriod = 1; + } + else if ( shouldImpostor(4.0) ) + { //background avatars are REALLY slow updating impostors + mUpdatePeriod = UPDATE_RATE_SLOW; + } + else if (mLastRezzedStatus <= 0) + { + // Don't update cloud avatars too often + mUpdatePeriod = UPDATE_RATE_SLOW; + } + else if ( shouldImpostor(3.0) ) + { //back 25% of max visible avatars are slow updating impostors + mUpdatePeriod = UPDATE_RATE_MED; + } + else + { + //nearby avatars, update the impostors more frequently. + mUpdatePeriod = UPDATE_RATE_FAST; + } + } + else + { + mUpdatePeriod = 1; + } } //------------------------------------------------------------------------ @@ -4200,97 +4200,97 @@ void LLVOAvatar::computeUpdatePeriod() //------------------------------------------------------------------------ void LLVOAvatar::updateOrientation(LLAgent& agent, F32 speed, F32 delta_time) { - LLQuaternion iQ; - LLVector3 upDir( 0.0f, 0.0f, 1.0f ); - - // Compute a forward direction vector derived from the primitive rotation - // and the velocity vector. When walking or jumping, don't let body deviate - // more than 90 from the view, if necessary, flip the velocity vector. - - LLVector3 primDir; - if (isSelf()) - { - primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector()); - primDir.normalize(); - } - else - { - primDir = getRotation().getMatrix3().getFwdRow(); - } - LLVector3 velDir = getVelocity(); - velDir.normalize(); - if ( mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end()) - { - F32 vpD = velDir * primDir; - if (vpD < -0.5f) - { - velDir *= -1.0f; - } - } - LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f)); - if (isSelf() && gAgentCamera.cameraMouselook()) - { - // make sure fwdDir stays in same general direction as primdir - if (gAgent.getFlying()) - { - fwdDir = LLViewerCamera::getInstance()->getAtAxis(); - } - else - { - LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); - LLVector3 up_vector = gAgent.getReferenceUpVector(); - at_axis -= up_vector * (at_axis * up_vector); - at_axis.normalize(); - - F32 dot = fwdDir * at_axis; - if (dot < 0.f) - { - fwdDir -= 2.f * at_axis * dot; - fwdDir.normalize(); - } - } - } - - LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion(); - F32 root_roll, root_pitch, root_yaw; - root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); - - // When moving very slow, the pelvis is allowed to deviate from the + LLQuaternion iQ; + LLVector3 upDir( 0.0f, 0.0f, 1.0f ); + + // Compute a forward direction vector derived from the primitive rotation + // and the velocity vector. When walking or jumping, don't let body deviate + // more than 90 from the view, if necessary, flip the velocity vector. + + LLVector3 primDir; + if (isSelf()) + { + primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector()); + primDir.normalize(); + } + else + { + primDir = getRotation().getMatrix3().getFwdRow(); + } + LLVector3 velDir = getVelocity(); + velDir.normalize(); + if ( mSignaledAnimations.find(ANIM_AGENT_WALK) != mSignaledAnimations.end()) + { + F32 vpD = velDir * primDir; + if (vpD < -0.5f) + { + velDir *= -1.0f; + } + } + LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f)); + if (isSelf() && gAgentCamera.cameraMouselook()) + { + // make sure fwdDir stays in same general direction as primdir + if (gAgent.getFlying()) + { + fwdDir = LLViewerCamera::getInstance()->getAtAxis(); + } + else + { + LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis(); + LLVector3 up_vector = gAgent.getReferenceUpVector(); + at_axis -= up_vector * (at_axis * up_vector); + at_axis.normalize(); + + F32 dot = fwdDir * at_axis; + if (dot < 0.f) + { + fwdDir -= 2.f * at_axis * dot; + fwdDir.normalize(); + } + } + } + + LLQuaternion root_rotation = mRoot->getWorldMatrix().quaternion(); + F32 root_roll, root_pitch, root_yaw; + root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); + + // When moving very slow, the pelvis is allowed to deviate from the // forward direction to allow it to hold its position while the torso - // and head turn. Once in motion, it must conform however. - BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); - - LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV ); - - static LLCachedControl s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); - static LLCachedControl s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0); - - F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); - - if (self_in_mouselook) - { - pelvis_rot_threshold *= MOUSELOOK_PELVIS_FOLLOW_FACTOR; - } - pelvis_rot_threshold *= DEG_TO_RAD; - - F32 angle = angle_between( pelvisDir, fwdDir ); - - // The avatar's root is allowed to have a yaw that deviates widely - // from the forward direction, but if roll or pitch are off even - // a little bit we need to correct the rotation. - if(root_roll < 1.f * DEG_TO_RAD - && root_pitch < 5.f * DEG_TO_RAD) - { - // smaller correction vector means pelvis follows prim direction more closely - if (!mTurning && angle > pelvis_rot_threshold*0.75f) - { - mTurning = TRUE; - } - - // use tighter threshold when turning - if (mTurning) - { - pelvis_rot_threshold *= 0.4f; + // and head turn. Once in motion, it must conform however. + BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook(); + + LLVector3 pelvisDir( mRoot->getWorldMatrix().getFwdRow4().mV ); + + static LLCachedControl s_pelvis_rot_threshold_slow(gSavedSettings, "AvatarRotateThresholdSlow", 60.0); + static LLCachedControl s_pelvis_rot_threshold_fast(gSavedSettings, "AvatarRotateThresholdFast", 2.0); + + F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, s_pelvis_rot_threshold_slow, s_pelvis_rot_threshold_fast); + + if (self_in_mouselook) + { + pelvis_rot_threshold *= MOUSELOOK_PELVIS_FOLLOW_FACTOR; + } + pelvis_rot_threshold *= DEG_TO_RAD; + + F32 angle = angle_between( pelvisDir, fwdDir ); + + // The avatar's root is allowed to have a yaw that deviates widely + // from the forward direction, but if roll or pitch are off even + // a little bit we need to correct the rotation. + if(root_roll < 1.f * DEG_TO_RAD + && root_pitch < 5.f * DEG_TO_RAD) + { + // smaller correction vector means pelvis follows prim direction more closely + if (!mTurning && angle > pelvis_rot_threshold*0.75f) + { + mTurning = TRUE; + } + + // use tighter threshold when turning + if (mTurning) + { + pelvis_rot_threshold *= 0.4f; // account for fps, assume that above value is for ~60fps constexpr F32 default_frame_sec = 0.016f; F32 prev_frame_sec = LLFrameTimer::getFrameDeltaTimeF32(); @@ -4300,62 +4300,62 @@ void LLVOAvatar::updateOrientation(LLAgent& agent, F32 speed, F32 delta_time) // shorter frame means shorter turn. pelvis_rot_threshold *= prev_frame_sec/default_frame_sec; } - } - - // am I done turning? - if (angle < pelvis_rot_threshold) - { - mTurning = FALSE; - } - - LLVector3 correction_vector = (pelvisDir - fwdDir) * clamp_rescale(angle, pelvis_rot_threshold*0.75f, pelvis_rot_threshold, 1.0f, 0.0f); - fwdDir += correction_vector; - } - else - { - mTurning = FALSE; - } - - // Now compute the full world space rotation for the whole body (wQv) - LLVector3 leftDir = upDir % fwdDir; - leftDir.normalize(); - fwdDir = leftDir % upDir; - LLQuaternion wQv( fwdDir, leftDir, upDir ); - - if (isSelf() && mTurning) - { - if ((fwdDir % pelvisDir) * upDir > 0.f) - { - gAgent.setControlFlags(AGENT_CONTROL_TURN_RIGHT); - } - else - { - gAgent.setControlFlags(AGENT_CONTROL_TURN_LEFT); - } - } - - // Set the root rotation, but do so incrementally so that it - // lags in time by some fixed amount. - //F32 u = LLSmoothInterpolation::getInterpolant(PELVIS_LAG); - F32 pelvis_lag_time = 0.f; - if (self_in_mouselook) - { - pelvis_lag_time = PELVIS_LAG_MOUSELOOK; - } - else if (mInAir) - { - pelvis_lag_time = PELVIS_LAG_FLYING; - // increase pelvis lag time when moving slowly - pelvis_lag_time *= clamp_rescale(mSpeedAccum, 0.f, 15.f, 3.f, 1.f); - } - else - { - pelvis_lag_time = PELVIS_LAG_WALKING; - } - - F32 u = llclamp((delta_time / pelvis_lag_time), 0.0f, 1.0f); - - mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); + } + + // am I done turning? + if (angle < pelvis_rot_threshold) + { + mTurning = FALSE; + } + + LLVector3 correction_vector = (pelvisDir - fwdDir) * clamp_rescale(angle, pelvis_rot_threshold*0.75f, pelvis_rot_threshold, 1.0f, 0.0f); + fwdDir += correction_vector; + } + else + { + mTurning = FALSE; + } + + // Now compute the full world space rotation for the whole body (wQv) + LLVector3 leftDir = upDir % fwdDir; + leftDir.normalize(); + fwdDir = leftDir % upDir; + LLQuaternion wQv( fwdDir, leftDir, upDir ); + + if (isSelf() && mTurning) + { + if ((fwdDir % pelvisDir) * upDir > 0.f) + { + gAgent.setControlFlags(AGENT_CONTROL_TURN_RIGHT); + } + else + { + gAgent.setControlFlags(AGENT_CONTROL_TURN_LEFT); + } + } + + // Set the root rotation, but do so incrementally so that it + // lags in time by some fixed amount. + //F32 u = LLSmoothInterpolation::getInterpolant(PELVIS_LAG); + F32 pelvis_lag_time = 0.f; + if (self_in_mouselook) + { + pelvis_lag_time = PELVIS_LAG_MOUSELOOK; + } + else if (mInAir) + { + pelvis_lag_time = PELVIS_LAG_FLYING; + // increase pelvis lag time when moving slowly + pelvis_lag_time *= clamp_rescale(mSpeedAccum, 0.f, 15.f, 3.f, 1.f); + } + else + { + pelvis_lag_time = PELVIS_LAG_WALKING; + } + + F32 u = llclamp((delta_time / pelvis_lag_time), 0.0f, 1.0f); + + mRoot->setWorldRotation( slerp(u, mRoot->getWorldRotation(), wQv) ); } //------------------------------------------------------------------------ @@ -4368,91 +4368,91 @@ void LLVOAvatar::updateOrientation(LLAgent& agent, F32 speed, F32 delta_time) // ------------------------------------------------------------------------ void LLVOAvatar::updateTimeStep() { - if (!isSelf() && !isUIAvatar()) // ie, non-self avatars, and animated objects will be affected. - { + if (!isSelf() && !isUIAvatar()) // ie, non-self avatars, and animated objects will be affected. + { // Note that sInstances counts animated objects and // standard avatars in the same bucket. Is this desirable? - F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); - F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); - F32 time_step = time_quantum * pixel_area_scale; + F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); + F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); + F32 time_step = time_quantum * pixel_area_scale; // Extrema: // If number of avs is 10 or less, time_step is unmodified (flagged with 0.0). // If area of av is 5000 or greater, time_step is unmodified (flagged with 0.0). // If number of avs is 35 or greater, and area of av is 100 or less, // time_step takes the maximum possible value of 0.25. // Other situations will give values within the (0, 0.25) range. - if (time_step != 0.f) - { - // disable walk motion servo controller as it doesn't work with motion timesteps - stopMotion(ANIM_AGENT_WALK_ADJUST); - removeAnimationData("Walk Speed"); - } + if (time_step != 0.f) + { + // disable walk motion servo controller as it doesn't work with motion timesteps + stopMotion(ANIM_AGENT_WALK_ADJUST); + removeAnimationData("Walk Speed"); + } // See SL-763 - playback with altered time step does not // appear to work correctly, odd behavior for distant avatars. // As of 11-2017, LLMotionController::updateMotions() will // ignore the value here. Need to re-enable if it's every // fixed. - mMotionController.setTimeStep(time_step); - } -} - -void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool was_sit_ground_constrained) -{ - if (!(isSitting() && getParent())) - { - // This case includes all configurations except sitting on an - // object, so does include ground sit. - - //-------------------------------------------------------------------- - // get timing info - // handle initial condition case - //-------------------------------------------------------------------- - F32 animation_time = mAnimTimer.getElapsedTimeF32(); - if (mTimeLast == 0.0f) - { - mTimeLast = animation_time; - - // Initially put the pelvis at slaved position/mRotation - // SL-315 - mRoot->setWorldPosition( getPositionAgent() ); // first frame - mRoot->setWorldRotation( getRotation() ); - } - - //-------------------------------------------------------------------- - // dont' let dT get larger than 1/5th of a second - //-------------------------------------------------------------------- - F32 delta_time = animation_time - mTimeLast; - - delta_time = llclamp( delta_time, DELTA_TIME_MIN, DELTA_TIME_MAX ); - mTimeLast = animation_time; - - mSpeedAccum = (mSpeedAccum * 0.95f) + (speed * 0.05f); - - //-------------------------------------------------------------------- - // compute the position of the avatar's root - //-------------------------------------------------------------------- - LLVector3d root_pos; - LLVector3d ground_under_pelvis; - - if (isSelf()) - { - gAgent.setPositionAgent(getRenderPosition()); - } - - root_pos = gAgent.getPosGlobalFromAgent(getRenderPosition()); - root_pos.mdV[VZ] += getVisualParamWeight(AVATAR_HOVER); + mMotionController.setTimeStep(time_step); + } +} + +void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool was_sit_ground_constrained) +{ + if (!(isSitting() && getParent())) + { + // This case includes all configurations except sitting on an + // object, so does include ground sit. + + //-------------------------------------------------------------------- + // get timing info + // handle initial condition case + //-------------------------------------------------------------------- + F32 animation_time = mAnimTimer.getElapsedTimeF32(); + if (mTimeLast == 0.0f) + { + mTimeLast = animation_time; + + // Initially put the pelvis at slaved position/mRotation + // SL-315 + mRoot->setWorldPosition( getPositionAgent() ); // first frame + mRoot->setWorldRotation( getRotation() ); + } + + //-------------------------------------------------------------------- + // dont' let dT get larger than 1/5th of a second + //-------------------------------------------------------------------- + F32 delta_time = animation_time - mTimeLast; + + delta_time = llclamp( delta_time, DELTA_TIME_MIN, DELTA_TIME_MAX ); + mTimeLast = animation_time; + + mSpeedAccum = (mSpeedAccum * 0.95f) + (speed * 0.05f); + + //-------------------------------------------------------------------- + // compute the position of the avatar's root + //-------------------------------------------------------------------- + LLVector3d root_pos; + LLVector3d ground_under_pelvis; + + if (isSelf()) + { + gAgent.setPositionAgent(getRenderPosition()); + } + + root_pos = gAgent.getPosGlobalFromAgent(getRenderPosition()); + root_pos.mdV[VZ] += getVisualParamWeight(AVATAR_HOVER); LLVector3 normal; - resolveHeightGlobal(root_pos, ground_under_pelvis, normal); - F32 foot_to_ground = (F32) (root_pos.mdV[VZ] - mPelvisToFoot - ground_under_pelvis.mdV[VZ]); - BOOL in_air = ((!LLWorld::getInstance()->getRegionFromPosGlobal(ground_under_pelvis)) || - foot_to_ground > FOOT_GROUND_COLLISION_TOLERANCE); + resolveHeightGlobal(root_pos, ground_under_pelvis, normal); + F32 foot_to_ground = (F32) (root_pos.mdV[VZ] - mPelvisToFoot - ground_under_pelvis.mdV[VZ]); + BOOL in_air = ((!LLWorld::getInstance()->getRegionFromPosGlobal(ground_under_pelvis)) || + foot_to_ground > FOOT_GROUND_COLLISION_TOLERANCE); - if (in_air && !mInAir) - { - mTimeInAir.reset(); - } - mInAir = in_air; + if (in_air && !mInAir) + { + mTimeInAir.reset(); + } + mInAir = in_air; // SL-402: with the ability to animate the position of joints // that affect the body size calculation, computed body size @@ -4460,40 +4460,40 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w // it frequently. // SL-427: this appears to be too frequent, moving to only do on animation state change. //computeBodySize(); - - // correct for the fact that the pelvis is not necessarily the center - // of the agent's physical representation - root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; - if (!isSitting() && !was_sit_ground_constrained) - { - root_pos += LLVector3d(getHoverOffset()); - if (getOverallAppearance() == AOA_JELLYDOLL) - { - F32 offz = -0.5 * (getScale()[VZ] - mBodySize.mV[VZ]); - root_pos[2] += offz; - // if (!isSelf() && !isControlAvatar()) - // { - // LL_DEBUGS("Avatar") << "av " << getFullname() - // << " frame " << LLFrameTimer::getFrameCount() - // << " root adjust offz " << offz - // << " scalez " << getScale()[VZ] - // << " bsz " << mBodySize.mV[VZ] - // << LL_ENDL; - // } - } - } - // if (!isSelf() && !isControlAvatar()) - // { - // LL_DEBUGS("Avatar") << "av " << getFullname() << " aoa " << (S32) getOverallAppearance() - // << " frame " << LLFrameTimer::getFrameCount() - // << " scalez " << getScale()[VZ] - // << " bsz " << mBodySize.mV[VZ] - // << " root pos " << root_pos[2] - // << " curr rootz " << mRoot->getPosition()[2] - // << " pp-z " << mPelvisp->getPosition()[2] - // << " renderpos " << getRenderPosition() - // << LL_ENDL; - // } + + // correct for the fact that the pelvis is not necessarily the center + // of the agent's physical representation + root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; + if (!isSitting() && !was_sit_ground_constrained) + { + root_pos += LLVector3d(getHoverOffset()); + if (getOverallAppearance() == AOA_JELLYDOLL) + { + F32 offz = -0.5 * (getScale()[VZ] - mBodySize.mV[VZ]); + root_pos[2] += offz; + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() + // << " frame " << LLFrameTimer::getFrameCount() + // << " root adjust offz " << offz + // << " scalez " << getScale()[VZ] + // << " bsz " << mBodySize.mV[VZ] + // << LL_ENDL; + // } + } + } + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() << " aoa " << (S32) getOverallAppearance() + // << " frame " << LLFrameTimer::getFrameCount() + // << " scalez " << getScale()[VZ] + // << " bsz " << mBodySize.mV[VZ] + // << " root pos " << root_pos[2] + // << " curr rootz " << mRoot->getPosition()[2] + // << " pp-z " << mPelvisp->getPosition()[2] + // << " renderpos " << getRenderPosition() + // << LL_ENDL; + // } LLControlAvatar *cav = dynamic_cast(this); if (cav) @@ -4504,73 +4504,73 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w else { LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); - // if (!isSelf() && !isControlAvatar()) - // { - // LL_DEBUGS("Avatar") << "av " << getFullname() - // << " frame " << LLFrameTimer::getFrameCount() - // << " newPosition " << newPosition - // << " renderpos " << getRenderPosition() - // << LL_ENDL; - // } + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() + // << " frame " << LLFrameTimer::getFrameCount() + // << " newPosition " << newPosition + // << " renderpos " << getRenderPosition() + // << LL_ENDL; + // } if (newPosition != mRoot->getXform()->getWorldPosition()) - { + { mRoot->touch(); // SL-315 - mRoot->setWorldPosition( newPosition ); // regular update + mRoot->setWorldPosition( newPosition ); // regular update } } - //-------------------------------------------------------------------- - // Propagate viewer object rotation to root of avatar - //-------------------------------------------------------------------- - if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS)) - { + //-------------------------------------------------------------------- + // Propagate viewer object rotation to root of avatar + //-------------------------------------------------------------------- + if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS)) + { // Rotation fixups for avatars in motion. // Skip for animated objects. updateOrientation(agent, speed, delta_time); - } - } - else if (mDrawable.notNull()) - { + } + } + else if (mDrawable.notNull()) + { // Sitting on an object - mRoot is slaved to mDrawable orientation. - LLVector3 pos = mDrawable->getPosition(); - pos += getHoverOffset() * mDrawable->getRotation(); - // SL-315 - mRoot->setPosition(pos); - mRoot->setRotation(mDrawable->getRotation()); - } + LLVector3 pos = mDrawable->getPosition(); + pos += getHoverOffset() * mDrawable->getRotation(); + // SL-315 + mRoot->setPosition(pos); + mRoot->setRotation(mDrawable->getRotation()); + } } //------------------------------------------------------------------------ // LLVOAvatar::computeNeedsUpdate() -// +// // Most of the logic here is to figure out when to periodically update impostors. // Non-impostors have mUpdatePeriod == 1 and will need update every frame. //------------------------------------------------------------------------ bool LLVOAvatar::computeNeedsUpdate() { - const F32 MAX_IMPOSTOR_INTERVAL = 4.0f; - computeUpdatePeriod(); + const F32 MAX_IMPOSTOR_INTERVAL = 4.0f; + computeUpdatePeriod(); - bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0); + bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0); bool needs_update_by_max_time = ((gFrameTimeSeconds-mLastImpostorUpdateFrameTime)> MAX_IMPOSTOR_INTERVAL); - bool needs_update = needs_update_by_frame_count || needs_update_by_max_time; - - if (needs_update && !isSelf()) - { - if (needs_update_by_max_time) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 11; - } - else - { - //mNeedsImpostorUpdate = TRUE; - //mLastImpostorUpdateReason = 10; - } - } - return needs_update; + bool needs_update = needs_update_by_frame_count || needs_update_by_max_time; + + if (needs_update && !isSelf()) + { + if (needs_update_by_max_time) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 11; + } + else + { + //mNeedsImpostorUpdate = TRUE; + //mLastImpostorUpdateReason = 10; + } + } + return needs_update; } // updateCharacter() @@ -4596,153 +4596,153 @@ bool LLVOAvatar::computeNeedsUpdate() // //------------------------------------------------------------------------ bool LLVOAvatar::updateCharacter(LLAgent &agent) -{ - updateDebugText(); - - if (!mIsBuilt) - { - return FALSE; - } - - BOOL visible = isVisible(); +{ + updateDebugText(); + + if (!mIsBuilt) + { + return FALSE; + } + + BOOL visible = isVisible(); bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing - bool is_attachment = false; + bool is_attachment = false; - if (is_control_avatar) - { + if (is_control_avatar) + { LLControlAvatar *cav = dynamic_cast(this); - is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects - } + is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects + } LLScopedContextString str("updateCharacter " + getFullname() + " is_control_avatar " - + boost::lexical_cast(is_control_avatar) + + boost::lexical_cast(is_control_avatar) + " is_attachment " + boost::lexical_cast(is_attachment)); - // For fading out the names above heads, only let the timer - // run if we're visible. - if (mDrawable.notNull() && !visible) - { - mTimeVisible.reset(); - } + // For fading out the names above heads, only let the timer + // run if we're visible. + if (mDrawable.notNull() && !visible) + { + mTimeVisible.reset(); + } - //-------------------------------------------------------------------- - // The rest should only be done occasionally for far away avatars. + //-------------------------------------------------------------------- + // The rest should only be done occasionally for far away avatars. // Set mUpdatePeriod and visible based on distance and other criteria, - // and flag for impostor update if needed. - //-------------------------------------------------------------------- - bool needs_update = computeNeedsUpdate(); - - //-------------------------------------------------------------------- - // Early out if does not need update and not self - // don't early out for your own avatar, as we rely on your animations playing reliably - // for example, the "turn around" animation when entering customize avatar needs to trigger - // even when your avatar is offscreen - //-------------------------------------------------------------------- - if (!needs_update && !isSelf()) - { - updateMotions(LLCharacter::HIDDEN_UPDATE); - return FALSE; - } - - //-------------------------------------------------------------------- - // Handle transitions between regular rendering, jellydoll, or invisible. - // Can trigger skeleton reset or animation changes - //-------------------------------------------------------------------- - updateOverallAppearance(); - - //-------------------------------------------------------------------- - // change animation time quanta based on avatar render load - //-------------------------------------------------------------------- + // and flag for impostor update if needed. + //-------------------------------------------------------------------- + bool needs_update = computeNeedsUpdate(); + + //-------------------------------------------------------------------- + // Early out if does not need update and not self + // don't early out for your own avatar, as we rely on your animations playing reliably + // for example, the "turn around" animation when entering customize avatar needs to trigger + // even when your avatar is offscreen + //-------------------------------------------------------------------- + if (!needs_update && !isSelf()) + { + updateMotions(LLCharacter::HIDDEN_UPDATE); + return FALSE; + } + + //-------------------------------------------------------------------- + // Handle transitions between regular rendering, jellydoll, or invisible. + // Can trigger skeleton reset or animation changes + //-------------------------------------------------------------------- + updateOverallAppearance(); + + //-------------------------------------------------------------------- + // change animation time quanta based on avatar render load + //-------------------------------------------------------------------- // SL-763 the time step quantization does not currently work. //updateTimeStep(); - - //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- // Update sitting state based on parent and active animation info. - //-------------------------------------------------------------------- - if (getParent() && !isSitting()) - { - sitOnObject((LLViewerObject*)getParent()); - } - else if (!getParent() && isSitting() && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED)) - { + //-------------------------------------------------------------------- + if (getParent() && !isSitting()) + { + sitOnObject((LLViewerObject*)getParent()); + } + else if (!getParent() && isSitting() && !isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED)) + { // If we are starting up, motion might be loading LLMotion *motionp = mMotionController.findMotion(ANIM_AGENT_SIT_GROUND_CONSTRAINED); if (!motionp || !mMotionController.isMotionLoading(motionp)) { getOffObject(); } - } - - //-------------------------------------------------------------------- - // create local variables in world coords for region position values - //-------------------------------------------------------------------- - LLVector3 xyVel = getVelocity(); - xyVel.mV[VZ] = 0.0f; - F32 speed = xyVel.length(); - // remembering the value here prevents a display glitch if the - // animation gets toggled during this update. - bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED); + } - //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // create local variables in world coords for region position values + //-------------------------------------------------------------------- + LLVector3 xyVel = getVelocity(); + xyVel.mV[VZ] = 0.0f; + F32 speed = xyVel.length(); + // remembering the value here prevents a display glitch if the + // animation gets toggled during this update. + bool was_sit_ground_constrained = isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED); + + //-------------------------------------------------------------------- // This does a bunch of state updating, including figuring out // whether av is in the air, setting mRoot position and rotation // In some cases, calls updateOrientation() for a lot of the // work // -------------------------------------------------------------------- updateRootPositionAndRotation(agent, speed, was_sit_ground_constrained); - - //------------------------------------------------------------------------- - // Update character motions - //------------------------------------------------------------------------- - // store data relevant to motions - mSpeed = speed; - - // update animations - if (!visible && !isSelf()) // NOTE: never do a "hidden update" for self avatar as it interrupts controller processing - { - updateMotions(LLCharacter::HIDDEN_UPDATE); - } - else if (mSpecialRenderMode == 1) // Animation Preview - { - updateMotions(LLCharacter::FORCE_UPDATE); - } - else - { - // Might be better to do HIDDEN_UPDATE if cloud - updateMotions(LLCharacter::NORMAL_UPDATE); - } - - // Special handling for sitting on ground. - if (!getParent() && (isSitting() || was_sit_ground_constrained)) - { - - F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ]; - if (off_z != 0.0) - { - LLVector3 pos = mRoot->getWorldPosition(); - pos.mV[VZ] += off_z; - mRoot->touch(); - // SL-315 - mRoot->setWorldPosition(pos); - } - } - - // update head position - updateHeadOffset(); - - // Generate footstep sounds when feet hit the ground + + //------------------------------------------------------------------------- + // Update character motions + //------------------------------------------------------------------------- + // store data relevant to motions + mSpeed = speed; + + // update animations + if (!visible && !isSelf()) // NOTE: never do a "hidden update" for self avatar as it interrupts controller processing + { + updateMotions(LLCharacter::HIDDEN_UPDATE); + } + else if (mSpecialRenderMode == 1) // Animation Preview + { + updateMotions(LLCharacter::FORCE_UPDATE); + } + else + { + // Might be better to do HIDDEN_UPDATE if cloud + updateMotions(LLCharacter::NORMAL_UPDATE); + } + + // Special handling for sitting on ground. + if (!getParent() && (isSitting() || was_sit_ground_constrained)) + { + + F32 off_z = LLVector3d(getHoverOffset()).mdV[VZ]; + if (off_z != 0.0) + { + LLVector3 pos = mRoot->getWorldPosition(); + pos.mV[VZ] += off_z; + mRoot->touch(); + // SL-315 + mRoot->setWorldPosition(pos); + } + } + + // update head position + updateHeadOffset(); + + // Generate footstep sounds when feet hit the ground updateFootstepSounds(); - // Update child joints as needed. - mRoot->updateWorldMatrixChildren(); + // Update child joints as needed. + mRoot->updateWorldMatrixChildren(); if (visible) { - // System avatar mesh vertices need to be reskinned. - mNeedsSkin = TRUE; + // System avatar mesh vertices need to be reskinned. + mNeedsSkin = TRUE; } - return visible; + return visible; } //----------------------------------------------------------------------------- @@ -4750,487 +4750,487 @@ bool LLVOAvatar::updateCharacter(LLAgent &agent) //----------------------------------------------------------------------------- void LLVOAvatar::updateHeadOffset() { - // since we only care about Z, just grab one of the eyes - LLVector3 midEyePt = mEyeLeftp->getWorldPosition(); - midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot->getWorldPosition(); - midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]); - - if (mDrawable.notNull()) - { - midEyePt = midEyePt * ~mDrawable->getWorldRotation(); - } - if (isSitting()) - { - mHeadOffset = midEyePt; - } - else - { - F32 u = llmax(0.f, HEAD_MOVEMENT_AVG_TIME - (1.f / gFPSClamped)); - mHeadOffset = lerp(midEyePt, mHeadOffset, u); - } + // since we only care about Z, just grab one of the eyes + LLVector3 midEyePt = mEyeLeftp->getWorldPosition(); + midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot->getWorldPosition(); + midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]); + + if (mDrawable.notNull()) + { + midEyePt = midEyePt * ~mDrawable->getWorldRotation(); + } + if (isSitting()) + { + mHeadOffset = midEyePt; + } + else + { + F32 u = llmax(0.f, HEAD_MOVEMENT_AVG_TIME - (1.f / gFPSClamped)); + mHeadOffset = lerp(midEyePt, mHeadOffset, u); + } } void LLVOAvatar::debugBodySize() const { - LLVector3 pelvis_scale = mPelvisp->getScale(); + LLVector3 pelvis_scale = mPelvisp->getScale(); - // some of the joints have not been cached - LLVector3 skull = mSkullp->getPosition(); + // some of the joints have not been cached + LLVector3 skull = mSkullp->getPosition(); LL_DEBUGS("Avatar") << "skull pos " << skull << LL_ENDL; - //LLVector3 skull_scale = mSkullp->getScale(); + //LLVector3 skull_scale = mSkullp->getScale(); - LLVector3 neck = mNeckp->getPosition(); - LLVector3 neck_scale = mNeckp->getScale(); + LLVector3 neck = mNeckp->getPosition(); + LLVector3 neck_scale = mNeckp->getScale(); LL_DEBUGS("Avatar") << "neck pos " << neck << " neck_scale " << neck_scale << LL_ENDL; - LLVector3 chest = mChestp->getPosition(); - LLVector3 chest_scale = mChestp->getScale(); + LLVector3 chest = mChestp->getPosition(); + LLVector3 chest_scale = mChestp->getScale(); LL_DEBUGS("Avatar") << "chest pos " << chest << " chest_scale " << chest_scale << LL_ENDL; - // the rest of the joints have been cached - LLVector3 head = mHeadp->getPosition(); - LLVector3 head_scale = mHeadp->getScale(); + // the rest of the joints have been cached + LLVector3 head = mHeadp->getPosition(); + LLVector3 head_scale = mHeadp->getScale(); LL_DEBUGS("Avatar") << "head pos " << head << " head_scale " << head_scale << LL_ENDL; - LLVector3 torso = mTorsop->getPosition(); - LLVector3 torso_scale = mTorsop->getScale(); + LLVector3 torso = mTorsop->getPosition(); + LLVector3 torso_scale = mTorsop->getScale(); LL_DEBUGS("Avatar") << "torso pos " << torso << " torso_scale " << torso_scale << LL_ENDL; - LLVector3 hip = mHipLeftp->getPosition(); - LLVector3 hip_scale = mHipLeftp->getScale(); + LLVector3 hip = mHipLeftp->getPosition(); + LLVector3 hip_scale = mHipLeftp->getScale(); LL_DEBUGS("Avatar") << "hip pos " << hip << " hip_scale " << hip_scale << LL_ENDL; - LLVector3 knee = mKneeLeftp->getPosition(); - LLVector3 knee_scale = mKneeLeftp->getScale(); + LLVector3 knee = mKneeLeftp->getPosition(); + LLVector3 knee_scale = mKneeLeftp->getScale(); LL_DEBUGS("Avatar") << "knee pos " << knee << " knee_scale " << knee_scale << LL_ENDL; - LLVector3 ankle = mAnkleLeftp->getPosition(); - LLVector3 ankle_scale = mAnkleLeftp->getScale(); + LLVector3 ankle = mAnkleLeftp->getPosition(); + LLVector3 ankle_scale = mAnkleLeftp->getScale(); LL_DEBUGS("Avatar") << "ankle pos " << ankle << " ankle_scale " << ankle_scale << LL_ENDL; - LLVector3 foot = mFootLeftp->getPosition(); + LLVector3 foot = mFootLeftp->getPosition(); LL_DEBUGS("Avatar") << "foot pos " << foot << LL_ENDL; - F32 new_offset = (const_cast(this))->getVisualParamWeight(AVATAR_HOVER); + F32 new_offset = (const_cast(this))->getVisualParamWeight(AVATAR_HOVER); LL_DEBUGS("Avatar") << "new_offset " << new_offset << LL_ENDL; - F32 new_pelvis_to_foot = hip.mV[VZ] * pelvis_scale.mV[VZ] - + F32 new_pelvis_to_foot = hip.mV[VZ] * pelvis_scale.mV[VZ] - knee.mV[VZ] * hip_scale.mV[VZ] - ankle.mV[VZ] * knee_scale.mV[VZ] - foot.mV[VZ] * ankle_scale.mV[VZ]; LL_DEBUGS("Avatar") << "new_pelvis_to_foot " << new_pelvis_to_foot << LL_ENDL; - LLVector3 new_body_size; - new_body_size.mV[VZ] = new_pelvis_to_foot + - // the sqrt(2) correction below is an approximate - // correction to get to the top of the head - F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + - head.mV[VZ] * neck_scale.mV[VZ] + - neck.mV[VZ] * chest_scale.mV[VZ] + - chest.mV[VZ] * torso_scale.mV[VZ] + - torso.mV[VZ] * pelvis_scale.mV[VZ]; + LLVector3 new_body_size; + new_body_size.mV[VZ] = new_pelvis_to_foot + + // the sqrt(2) correction below is an approximate + // correction to get to the top of the head + F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + + head.mV[VZ] * neck_scale.mV[VZ] + + neck.mV[VZ] * chest_scale.mV[VZ] + + chest.mV[VZ] * torso_scale.mV[VZ] + + torso.mV[VZ] * pelvis_scale.mV[VZ]; - // TODO -- measure the real depth and width - new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; - new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + // TODO -- measure the real depth and width + new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; + new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; LL_DEBUGS("Avatar") << "new_body_size " << new_body_size << LL_ENDL; } - + //------------------------------------------------------------------------ // postPelvisSetRecalc //------------------------------------------------------------------------ void LLVOAvatar::postPelvisSetRecalc() -{ - mRoot->updateWorldMatrixChildren(); - computeBodySize(); - dirtyMesh(2); +{ + mRoot->updateWorldMatrixChildren(); + computeBodySize(); + dirtyMesh(2); } //------------------------------------------------------------------------ // updateVisibility() //------------------------------------------------------------------------ void LLVOAvatar::updateVisibility() { - BOOL visible = FALSE; - - if (mIsDummy) - { - visible = FALSE; - } - else if (mDrawable.isNull()) - { - visible = FALSE; - } - else - { - if (!mDrawable->getSpatialGroup() || mDrawable->getSpatialGroup()->isVisible()) - { - visible = TRUE; - } - else - { - visible = FALSE; - } - - if(isSelf()) - { - if (!gAgentWearables.areWearablesLoaded()) - { - visible = FALSE; - } - } - else if( !mFirstAppearanceMessageReceived ) - { - visible = FALSE; - } - - if (sDebugInvisible) - { - LLNameValue* firstname = getNVPair("FirstName"); - if (firstname) - { - LL_DEBUGS("Avatar") << avString() << " updating visibility" << LL_ENDL; - } - else - { - LL_INFOS() << "Avatar " << this << " updating visiblity" << LL_ENDL; - } - - if (visible) - { - LL_INFOS() << "Visible" << LL_ENDL; - } - else - { - LL_INFOS() << "Not visible" << LL_ENDL; - } - - /*if (avatar_in_frustum) - { - LL_INFOS() << "Avatar in frustum" << LL_ENDL; - } - else - { - LL_INFOS() << "Avatar not in frustum" << LL_ENDL; - }*/ - - /*if (LLViewerCamera::getInstance()->sphereInFrustum(sel_pos_agent, 2.0f)) - { - LL_INFOS() << "Sel pos visible" << LL_ENDL; - } - if (LLViewerCamera::getInstance()->sphereInFrustum(wrist_right_pos_agent, 0.2f)) - { - LL_INFOS() << "Wrist pos visible" << LL_ENDL; - } - if (LLViewerCamera::getInstance()->sphereInFrustum(getPositionAgent(), getMaxScale()*2.f)) - { - LL_INFOS() << "Agent visible" << LL_ENDL; - }*/ - LL_INFOS() << "PA: " << getPositionAgent() << LL_ENDL; - /*LL_INFOS() << "SPA: " << sel_pos_agent << LL_ENDL; - LL_INFOS() << "WPA: " << wrist_right_pos_agent << LL_ENDL;*/ - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - 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()) - { - if(attached_object->mDrawable->isVisible()) - { - LL_INFOS() << attachment->getName() << " visible" << LL_ENDL; - } - else - { - LL_INFOS() << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << LL_ENDL; - } - } - } - } - } - } - - if (!visible && mVisible) - { - mMeshInvisibleTime.reset(); - } - - if (visible) - { - if (!mMeshValid) - { - restoreMeshData(); - } - } - else - { - if (mMeshValid && - (isControlAvatar() || mMeshInvisibleTime.getElapsedTimeF32() > TIME_BEFORE_MESH_CLEANUP)) - { - releaseMeshData(); - } - } + BOOL visible = FALSE; - if ( visible != mVisible ) + if (mIsDummy) { - LL_DEBUGS("AvatarRender") << "visible was " << mVisible << " now " << visible << LL_ENDL; + visible = FALSE; } - mVisible = visible; -} - -// private -bool LLVOAvatar::shouldAlphaMask() -{ - const bool should_alpha_mask = !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked - && !LLDrawPoolAvatar::sSkipTransparent; + else if (mDrawable.isNull()) + { + visible = FALSE; + } + else + { + if (!mDrawable->getSpatialGroup() || mDrawable->getSpatialGroup()->isVisible()) + { + visible = TRUE; + } + else + { + visible = FALSE; + } - return should_alpha_mask; + if(isSelf()) + { + if (!gAgentWearables.areWearablesLoaded()) + { + visible = FALSE; + } + } + else if( !mFirstAppearanceMessageReceived ) + { + visible = FALSE; + } -} + if (sDebugInvisible) + { + LLNameValue* firstname = getNVPair("FirstName"); + if (firstname) + { + LL_DEBUGS("Avatar") << avString() << " updating visibility" << LL_ENDL; + } + else + { + LL_INFOS() << "Avatar " << this << " updating visiblity" << LL_ENDL; + } -//----------------------------------------------------------------------------- -// renderSkinned() -//----------------------------------------------------------------------------- -U32 LLVOAvatar::renderSkinned() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; + if (visible) + { + LL_INFOS() << "Visible" << LL_ENDL; + } + else + { + LL_INFOS() << "Not visible" << LL_ENDL; + } - U32 num_indices = 0; + /*if (avatar_in_frustum) + { + LL_INFOS() << "Avatar in frustum" << LL_ENDL; + } + else + { + LL_INFOS() << "Avatar not in frustum" << LL_ENDL; + }*/ - if (!mIsBuilt) - { - return num_indices; - } + /*if (LLViewerCamera::getInstance()->sphereInFrustum(sel_pos_agent, 2.0f)) + { + LL_INFOS() << "Sel pos visible" << LL_ENDL; + } + if (LLViewerCamera::getInstance()->sphereInFrustum(wrist_right_pos_agent, 0.2f)) + { + LL_INFOS() << "Wrist pos visible" << LL_ENDL; + } + if (LLViewerCamera::getInstance()->sphereInFrustum(getPositionAgent(), getMaxScale()*2.f)) + { + LL_INFOS() << "Agent visible" << LL_ENDL; + }*/ + LL_INFOS() << "PA: " << getPositionAgent() << LL_ENDL; + /*LL_INFOS() << "SPA: " << sel_pos_agent << LL_ENDL; + LL_INFOS() << "WPA: " << wrist_right_pos_agent << LL_ENDL;*/ + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; - if (mDrawable.isNull()) - { - return num_indices; - } - - LLFace* face = mDrawable->getFace(0); - - bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); - - if (needs_rebuild || mDirtyMesh) - { //LOD changed or new mesh created, allocate new vertex buffer if needed - if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) - { - updateMeshData(); - mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } - } - - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) - { - if (mNeedsSkin) - { - //generate animated mesh - LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); - LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); - LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); - LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); - LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); - LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); - - if(upper_mesh) - { - upper_mesh->updateJointGeometry(); - } - if (lower_mesh) - { - lower_mesh->updateJointGeometry(); - } - - if( isWearingWearableType( LLWearableType::WT_SKIRT ) ) - { - if(skirt_mesh) - { - skirt_mesh->updateJointGeometry(); - } - } - - if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) - { - if(eyelash_mesh) - { - eyelash_mesh->updateJointGeometry(); - } - if(head_mesh) - { - head_mesh->updateJointGeometry(); - } - if(hair_mesh) - { - hair_mesh->updateJointGeometry(); - } - } - mNeedsSkin = FALSE; - mLastSkinTime = gFrameTimeSeconds; - - LLFace * face = mDrawable->getFace(0); - if (face) - { - LLVertexBuffer* vb = face->getVertexBuffer(); - if (vb) - { - vb->unmapBuffer(); - } - } - } - } - else - { - mNeedsSkin = FALSE; - } - - if (sDebugInvisible) - { - LLNameValue* firstname = getNVPair("FirstName"); - if (firstname) - { - LL_DEBUGS("Avatar") << avString() << " in render" << LL_ENDL; - } - else - { - LL_INFOS() << "Avatar " << this << " in render" << LL_ENDL; - } - if (!mIsBuilt) - { - LL_INFOS() << "Not built!" << LL_ENDL; - } - else if (!gAgent.needsRenderAvatar()) - { - LL_INFOS() << "Doesn't need avatar render!" << LL_ENDL; - } - else - { - LL_INFOS() << "Rendering!" << LL_ENDL; - } - } - - if (!mIsBuilt) - { - return num_indices; - } - - if (isSelf() && !gAgent.needsRenderAvatar()) - { - return num_indices; - } - - //-------------------------------------------------------------------- - // render all geometry attached to the skeleton - //-------------------------------------------------------------------- - - BOOL first_pass = TRUE; - if (!LLDrawPoolAvatar::sSkipOpaque) - { - if (isUIAvatar() && mIsDummy) - { - LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); - if (hair_mesh) - { - num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) - { - - if (isTextureVisible(TEX_HEAD_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) - { - LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); - if (head_mesh) - { - num_indices += head_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - } - if (isTextureVisible(TEX_UPPER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) - { - LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); - if (upper_mesh) - { - num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - - if (isTextureVisible(TEX_LOWER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) - { - LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); - if (lower_mesh) - { - num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - } - - if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) - { - LLGLState blend(GL_BLEND, !mIsDummy); - num_indices += renderTransparent(first_pass); - } - - return num_indices; -} + 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()) + { + if(attached_object->mDrawable->isVisible()) + { + LL_INFOS() << attachment->getName() << " visible" << LL_ENDL; + } + else + { + LL_INFOS() << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << LL_ENDL; + } + } + } + } + } + } + + if (!visible && mVisible) + { + mMeshInvisibleTime.reset(); + } + + if (visible) + { + if (!mMeshValid) + { + restoreMeshData(); + } + } + else + { + if (mMeshValid && + (isControlAvatar() || mMeshInvisibleTime.getElapsedTimeF32() > TIME_BEFORE_MESH_CLEANUP)) + { + releaseMeshData(); + } + } + + if ( visible != mVisible ) + { + LL_DEBUGS("AvatarRender") << "visible was " << mVisible << " now " << visible << LL_ENDL; + } + mVisible = visible; +} + +// private +bool LLVOAvatar::shouldAlphaMask() +{ + const bool should_alpha_mask = !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked + && !LLDrawPoolAvatar::sSkipTransparent; + + return should_alpha_mask; + +} + +//----------------------------------------------------------------------------- +// renderSkinned() +//----------------------------------------------------------------------------- +U32 LLVOAvatar::renderSkinned() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; + + U32 num_indices = 0; + + if (!mIsBuilt) + { + return num_indices; + } + + if (mDrawable.isNull()) + { + return num_indices; + } + + LLFace* face = mDrawable->getFace(0); + + bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); + + if (needs_rebuild || mDirtyMesh) + { //LOD changed or new mesh created, allocate new vertex buffer if needed + if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) + { + updateMeshData(); + mDirtyMesh = 0; + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } + } + + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) + { + if (mNeedsSkin) + { + //generate animated mesh + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + + if(upper_mesh) + { + upper_mesh->updateJointGeometry(); + } + if (lower_mesh) + { + lower_mesh->updateJointGeometry(); + } + + if( isWearingWearableType( LLWearableType::WT_SKIRT ) ) + { + if(skirt_mesh) + { + skirt_mesh->updateJointGeometry(); + } + } + + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + { + if(eyelash_mesh) + { + eyelash_mesh->updateJointGeometry(); + } + if(head_mesh) + { + head_mesh->updateJointGeometry(); + } + if(hair_mesh) + { + hair_mesh->updateJointGeometry(); + } + } + mNeedsSkin = FALSE; + mLastSkinTime = gFrameTimeSeconds; + + LLFace * face = mDrawable->getFace(0); + if (face) + { + LLVertexBuffer* vb = face->getVertexBuffer(); + if (vb) + { + vb->unmapBuffer(); + } + } + } + } + else + { + mNeedsSkin = FALSE; + } + + if (sDebugInvisible) + { + LLNameValue* firstname = getNVPair("FirstName"); + if (firstname) + { + LL_DEBUGS("Avatar") << avString() << " in render" << LL_ENDL; + } + else + { + LL_INFOS() << "Avatar " << this << " in render" << LL_ENDL; + } + if (!mIsBuilt) + { + LL_INFOS() << "Not built!" << LL_ENDL; + } + else if (!gAgent.needsRenderAvatar()) + { + LL_INFOS() << "Doesn't need avatar render!" << LL_ENDL; + } + else + { + LL_INFOS() << "Rendering!" << LL_ENDL; + } + } + + if (!mIsBuilt) + { + return num_indices; + } + + if (isSelf() && !gAgent.needsRenderAvatar()) + { + return num_indices; + } + + //-------------------------------------------------------------------- + // render all geometry attached to the skeleton + //-------------------------------------------------------------------- + + BOOL first_pass = TRUE; + if (!LLDrawPoolAvatar::sSkipOpaque) + { + if (isUIAvatar() && mIsDummy) + { + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + { + + if (isTextureVisible(TEX_HEAD_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) + { + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + if (head_mesh) + { + num_indices += head_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + } + if (isTextureVisible(TEX_UPPER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) + { + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + if (upper_mesh) + { + num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + + if (isTextureVisible(TEX_LOWER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) + { + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + if (lower_mesh) + { + num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + } + + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) + { + LLGLState blend(GL_BLEND, !mIsDummy); + num_indices += renderTransparent(first_pass); + } + + return num_indices; +} U32 LLVOAvatar::renderTransparent(BOOL first_pass) { - U32 num_indices = 0; - if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (isUIAvatar() || isTextureVisible(TEX_SKIRT_BAKED)) ) - { + U32 num_indices = 0; + if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (isUIAvatar() || isTextureVisible(TEX_SKIRT_BAKED)) ) + { gGL.flush(); - LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); - if (skirt_mesh) - { - num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE); - } - first_pass = FALSE; + LLViewerJoint* skirt_mesh = getViewerJoint(MESH_ID_SKIRT); + if (skirt_mesh) + { + num_indices += skirt_mesh->render(mAdjustedPixelArea, FALSE); + } + first_pass = FALSE; gGL.flush(); - } + } - if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) - { - if (LLPipeline::sImpostorRender) - { + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + { + if (LLPipeline::sImpostorRender) + { gGL.flush(); - } - - if (isTextureVisible(TEX_HEAD_BAKED)) - { - LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); - if (eyelash_mesh) - { - num_indices += eyelash_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - if (isTextureVisible(TEX_HAIR_BAKED) && (getOverallAppearance() != AOA_JELLYDOLL)) - { - LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); - if (hair_mesh) - { - num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - if (LLPipeline::sImpostorRender) - { + } + + if (isTextureVisible(TEX_HEAD_BAKED)) + { + LLViewerJoint* eyelash_mesh = getViewerJoint(MESH_ID_EYELASH); + if (eyelash_mesh) + { + num_indices += eyelash_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + if (isTextureVisible(TEX_HAIR_BAKED) && (getOverallAppearance() != AOA_JELLYDOLL)) + { + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } + if (LLPipeline::sImpostorRender) + { gGL.flush(); - } - } - - return num_indices; + } + } + + return num_indices; } //----------------------------------------------------------------------------- @@ -5238,399 +5238,399 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) //----------------------------------------------------------------------------- U32 LLVOAvatar::renderRigid() { - U32 num_indices = 0; + U32 num_indices = 0; - if (!mIsBuilt) - { - return 0; - } + if (!mIsBuilt) + { + return 0; + } - if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) - { - return 0; - } + if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) + { + return 0; + } - if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) - { - LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); - LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); - if (eyeball_left) - { - num_indices += eyeball_left->render(mAdjustedPixelArea, TRUE, mIsDummy); - } - if(eyeball_right) - { - num_indices += eyeball_right->render(mAdjustedPixelArea, TRUE, mIsDummy); - } - } + if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) + { + LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); + LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); + if (eyeball_left) + { + num_indices += eyeball_left->render(mAdjustedPixelArea, TRUE, mIsDummy); + } + if(eyeball_right) + { + num_indices += eyeball_right->render(mAdjustedPixelArea, TRUE, mIsDummy); + } + } - return num_indices; + return num_indices; } U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) { - if (!mImpostor.isComplete()) - { - return 0; - } - - LLVector3 pos(getRenderPosition()+mImpostorOffset); - LLVector3 at = (pos - LLViewerCamera::getInstance()->getOrigin()); - at.normalize(); - LLVector3 left = LLViewerCamera::getInstance()->getUpAxis() % at; - LLVector3 up = at%left; - - left *= mImpostorDim.mV[0]; - up *= mImpostorDim.mV[1]; - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_IMPOSTORS)) - { - LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ADD); - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); - - // gGL.begin(LLRender::QUADS); - // gGL.vertex3fv((pos+left-up).mV); - // gGL.vertex3fv((pos-left-up).mV); - // gGL.vertex3fv((pos-left+up).mV); - // gGL.vertex3fv((pos+left+up).mV); - // gGL.end(); - - - gGL.begin(LLRender::LINES); - gGL.color4f(1.f,1.f,1.f,1.f); - F32 thickness = llmax(F32(5.0f-5.0f*(gFrameTimeSeconds-mLastImpostorUpdateFrameTime)),1.0f); - glLineWidth(thickness); - gGL.vertex3fv((pos+left-up).mV); - gGL.vertex3fv((pos-left-up).mV); - gGL.vertex3fv((pos-left-up).mV); - gGL.vertex3fv((pos-left+up).mV); - gGL.vertex3fv((pos-left+up).mV); - gGL.vertex3fv((pos+left+up).mV); - gGL.vertex3fv((pos+left+up).mV); - gGL.vertex3fv((pos+left-up).mV); - gGL.end(); - gGL.flush(); - } - { - gGL.flush(); - - gGL.color4ubv(color.mV); - gGL.getTexUnit(diffuse_channel)->bind(&mImpostor); - gGL.begin(LLRender::QUADS); - gGL.texCoord2f(0,0); - gGL.vertex3fv((pos+left-up).mV); - gGL.texCoord2f(1,0); - gGL.vertex3fv((pos-left-up).mV); - gGL.texCoord2f(1,1); - gGL.vertex3fv((pos-left+up).mV); - gGL.texCoord2f(0,1); - gGL.vertex3fv((pos+left+up).mV); - gGL.end(); - gGL.flush(); - } - - return 6; + if (!mImpostor.isComplete()) + { + return 0; + } + + LLVector3 pos(getRenderPosition()+mImpostorOffset); + LLVector3 at = (pos - LLViewerCamera::getInstance()->getOrigin()); + at.normalize(); + LLVector3 left = LLViewerCamera::getInstance()->getUpAxis() % at; + LLVector3 up = at%left; + + left *= mImpostorDim.mV[0]; + up *= mImpostorDim.mV[1]; + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_IMPOSTORS)) + { + LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ADD); + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + + // gGL.begin(LLRender::QUADS); + // gGL.vertex3fv((pos+left-up).mV); + // gGL.vertex3fv((pos-left-up).mV); + // gGL.vertex3fv((pos-left+up).mV); + // gGL.vertex3fv((pos+left+up).mV); + // gGL.end(); + + + gGL.begin(LLRender::LINES); + gGL.color4f(1.f,1.f,1.f,1.f); + F32 thickness = llmax(F32(5.0f-5.0f*(gFrameTimeSeconds-mLastImpostorUpdateFrameTime)),1.0f); + glLineWidth(thickness); + gGL.vertex3fv((pos+left-up).mV); + gGL.vertex3fv((pos-left-up).mV); + gGL.vertex3fv((pos-left-up).mV); + gGL.vertex3fv((pos-left+up).mV); + gGL.vertex3fv((pos-left+up).mV); + gGL.vertex3fv((pos+left+up).mV); + gGL.vertex3fv((pos+left+up).mV); + gGL.vertex3fv((pos+left-up).mV); + gGL.end(); + gGL.flush(); + } + { + gGL.flush(); + + gGL.color4ubv(color.mV); + gGL.getTexUnit(diffuse_channel)->bind(&mImpostor); + gGL.begin(LLRender::QUADS); + gGL.texCoord2f(0,0); + gGL.vertex3fv((pos+left-up).mV); + gGL.texCoord2f(1,0); + gGL.vertex3fv((pos-left-up).mV); + gGL.texCoord2f(1,1); + gGL.vertex3fv((pos-left+up).mV); + gGL.texCoord2f(0,1); + gGL.vertex3fv((pos+left+up).mV); + gGL.end(); + gGL.flush(); + } + + return 6; } bool LLVOAvatar::allTexturesCompletelyDownloaded(std::set& ids) const { - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) - { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); - if (imagep && imagep->getDiscardLevel()!=0) - { - return false; - } - } - return true; + for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); + if (imagep && imagep->getDiscardLevel()!=0) + { + return false; + } + } + return true; } bool LLVOAvatar::allLocalTexturesCompletelyDownloaded() const { - std::set local_ids; - collectLocalTextureUUIDs(local_ids); - return allTexturesCompletelyDownloaded(local_ids); + std::set local_ids; + collectLocalTextureUUIDs(local_ids); + return allTexturesCompletelyDownloaded(local_ids); } bool LLVOAvatar::allBakedTexturesCompletelyDownloaded() const { - std::set baked_ids; - collectBakedTextureUUIDs(baked_ids); - return allTexturesCompletelyDownloaded(baked_ids); + std::set baked_ids; + collectBakedTextureUUIDs(baked_ids); + return allTexturesCompletelyDownloaded(baked_ids); } std::string LLVOAvatar::bakedTextureOriginInfo() { - std::string result; - - std::set baked_ids; - collectBakedTextureUUIDs(baked_ids); - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - ETextureIndex texture_index = mBakedTextureDatas[i].mTextureIndex; - LLViewerFetchedTexture *imagep = - LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); - if (!imagep || - imagep->getID() == IMG_DEFAULT || - imagep->getID() == IMG_DEFAULT_AVATAR) - - { - result += "-"; - } - else - { - bool has_url = false, has_host = false; - if (!imagep->getUrl().empty()) - { - has_url = true; - } - if (imagep->getTargetHost().isOk()) - { - has_host = true; - } - S32 discard = imagep->getDiscardLevel(); - if (has_url && !has_host) result += discard ? "u" : "U"; // server-bake texture with url - else if (has_host && !has_url) result += discard ? "h" : "H"; // old-style texture on sim - else if (has_host && has_url) result += discard ? "x" : "X"; // both origins? - else if (!has_host && !has_url) result += discard ? "n" : "N"; // no origin? - if (discard != 0) - { - result += llformat("(%d/%d)",discard,imagep->getDesiredDiscardLevel()); - } - } - - } - return result; + std::string result; + + std::set baked_ids; + collectBakedTextureUUIDs(baked_ids); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex texture_index = mBakedTextureDatas[i].mTextureIndex; + LLViewerFetchedTexture *imagep = + LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + if (!imagep || + imagep->getID() == IMG_DEFAULT || + imagep->getID() == IMG_DEFAULT_AVATAR) + + { + result += "-"; + } + else + { + bool has_url = false, has_host = false; + if (!imagep->getUrl().empty()) + { + has_url = true; + } + if (imagep->getTargetHost().isOk()) + { + has_host = true; + } + S32 discard = imagep->getDiscardLevel(); + if (has_url && !has_host) result += discard ? "u" : "U"; // server-bake texture with url + else if (has_host && !has_url) result += discard ? "h" : "H"; // old-style texture on sim + else if (has_host && has_url) result += discard ? "x" : "X"; // both origins? + else if (!has_host && !has_url) result += discard ? "n" : "N"; // no origin? + if (discard != 0) + { + result += llformat("(%d/%d)",discard,imagep->getDesiredDiscardLevel()); + } + } + + } + return result; } S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) { - S32Bytes result(0); - for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) - { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); - if (imagep) - { - result += imagep->getTextureMemory(); - } - } - return result; -} - + S32Bytes result(0); + for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); + if (imagep) + { + result += imagep->getTextureMemory(); + } + } + return result; +} + void LLVOAvatar::collectLocalTextureUUIDs(std::set& ids) const { - for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) - { - LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); - U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); - - LLViewerFetchedTexture *imagep = NULL; - for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) - { - imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); - if (imagep) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); - if (texture_dict && texture_dict->mIsLocalTexture) - { - ids.insert(imagep->getID()); - } - } - } - } - ids.erase(IMG_DEFAULT); - ids.erase(IMG_DEFAULT_AVATAR); - ids.erase(IMG_INVISIBLE); + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + + LLViewerFetchedTexture *imagep = NULL; + for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); + if (imagep) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); + if (texture_dict && texture_dict->mIsLocalTexture) + { + ids.insert(imagep->getID()); + } + } + } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); } void LLVOAvatar::collectBakedTextureUUIDs(std::set& ids) const { - for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) - { - LLViewerFetchedTexture *imagep = NULL; - if (isIndexBakedTexture((ETextureIndex) texture_index)) - { - imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); - if (imagep) - { - ids.insert(imagep->getID()); - } - } - } - ids.erase(IMG_DEFAULT); - ids.erase(IMG_DEFAULT_AVATAR); - ids.erase(IMG_INVISIBLE); + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLViewerFetchedTexture *imagep = NULL; + if (isIndexBakedTexture((ETextureIndex) texture_index)) + { + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + if (imagep) + { + ids.insert(imagep->getID()); + } + } + } + ids.erase(IMG_DEFAULT); + ids.erase(IMG_DEFAULT_AVATAR); + ids.erase(IMG_INVISIBLE); } void LLVOAvatar::collectTextureUUIDs(std::set& ids) { - collectLocalTextureUUIDs(ids); - collectBakedTextureUUIDs(ids); + collectLocalTextureUUIDs(ids); + collectBakedTextureUUIDs(ids); } void LLVOAvatar::releaseOldTextures() { - S32Bytes current_texture_mem; - - // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" - std::set baked_texture_ids; - collectBakedTextureUUIDs(baked_texture_ids); - S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); - - std::set local_texture_ids; - collectLocalTextureUUIDs(local_texture_ids); - //S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); - - std::set new_texture_ids; - new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); - new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); - S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids); - - //S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); - //LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << LL_ENDL; - if (!isSelf() && new_total_mem > new_baked_mem) - { - LL_WARNS() << "extra local textures stored for non-self av" << LL_ENDL; - } - for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) - { - if (new_texture_ids.find(*it) == new_texture_ids.end()) - { - LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); - if (imagep) - { - current_texture_mem += imagep->getTextureMemory(); - if (imagep->getTextureState() == LLGLTexture::NO_DELETE) - { - // This will allow the texture to be deleted if not in use. - imagep->forceActive(); - - // This resets the clock to texture being flagged - // as unused, preventing the texture from being - // deleted immediately. If other avatars or - // objects are using it, it can still be flagged - // no-delete by them. - imagep->forceUpdateBindStats(); - } - } - } - } - mTextureIDs = new_texture_ids; + S32Bytes current_texture_mem; + + // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" + std::set baked_texture_ids; + collectBakedTextureUUIDs(baked_texture_ids); + S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); + + std::set local_texture_ids; + collectLocalTextureUUIDs(local_texture_ids); + //S32 new_local_mem = totalTextureMemForUUIDS(local_texture_ids); + + std::set new_texture_ids; + new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); + new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); + S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids); + + //S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); + //LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << LL_ENDL; + if (!isSelf() && new_total_mem > new_baked_mem) + { + LL_WARNS() << "extra local textures stored for non-self av" << LL_ENDL; + } + for (std::set::iterator it = mTextureIDs.begin(); it != mTextureIDs.end(); ++it) + { + if (new_texture_ids.find(*it) == new_texture_ids.end()) + { + LLViewerFetchedTexture *imagep = gTextureList.findImage(*it, TEX_LIST_STANDARD); + if (imagep) + { + current_texture_mem += imagep->getTextureMemory(); + if (imagep->getTextureState() == LLGLTexture::NO_DELETE) + { + // This will allow the texture to be deleted if not in use. + imagep->forceActive(); + + // This resets the clock to texture being flagged + // as unused, preventing the texture from being + // deleted immediately. If other avatars or + // objects are using it, it can still be flagged + // no-delete by them. + imagep->forceUpdateBindStats(); + } + } + } + } + mTextureIDs = new_texture_ids; } void LLVOAvatar::updateTextures() { - releaseOldTextures(); - - BOOL render_avatar = TRUE; - - if (mIsDummy) - { - return; - } - - if( isSelf() ) - { - render_avatar = TRUE; - } - else - { - if(!isVisible()) - { - return ;//do not update for invisible avatar. - } - - render_avatar = !mCulled; //visible and not culled. - } - - std::vector layer_baked; - // GL NOT ACTIVE HERE - *TODO - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex)); - // bind the texture so that they'll be decoded slightly - // inefficient, we can short-circuit this if we have to - if (render_avatar && !gGLManager.mIsDisabled) - { - if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded) - { - gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 )); - } - } - } - - mMaxPixelArea = 0.f; - mMinPixelArea = 99999999.f; - mHasGrey = FALSE; // debug - for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) - { - LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); - U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); - const LLTextureEntry *te = getTE(texture_index); - - // getTE can return 0. - // Not sure yet why it does, but of course it crashes when te->mScale? gets used. - // Put safeguard in place so this corner case get better handling and does not result in a crash. - F32 texel_area_ratio = 1.0f; - if( te ) - { - texel_area_ratio = fabs(te->mScaleS * te->mScaleT); - } - else - { - LL_WARNS() << "getTE( " << texture_index << " ) returned 0" <getTexture((ETextureIndex)texture_index); - const EBakedTextureIndex baked_index = texture_dict ? texture_dict->mBakedTextureIndex : EBakedTextureIndex::BAKED_NUM_INDICES; - if (texture_dict && texture_dict->mIsLocalTexture) - { - addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, mBakedTextureDatas[baked_index].mIsUsed); - } - } - } - if (isIndexBakedTexture((ETextureIndex) texture_index) && render_avatar) - { - const S32 boost_level = getAvatarBakedBoostLevel(); - imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%4.0f:%4.0f", (F32) sqrt(mMinPixelArea),(F32) sqrt(mMaxPixelArea))); - } + releaseOldTextures(); + + BOOL render_avatar = TRUE; + + if (mIsDummy) + { + return; + } + + if( isSelf() ) + { + render_avatar = TRUE; + } + else + { + if(!isVisible()) + { + return ;//do not update for invisible avatar. + } + + render_avatar = !mCulled; //visible and not culled. + } + + std::vector layer_baked; + // GL NOT ACTIVE HERE - *TODO + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex)); + // bind the texture so that they'll be decoded slightly + // inefficient, we can short-circuit this if we have to + if (render_avatar && !gGLManager.mIsDisabled) + { + if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded) + { + gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 )); + } + } + } + + mMaxPixelArea = 0.f; + mMinPixelArea = 99999999.f; + mHasGrey = FALSE; // debug + for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) + { + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); + U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); + const LLTextureEntry *te = getTE(texture_index); + + // getTE can return 0. + // Not sure yet why it does, but of course it crashes when te->mScale? gets used. + // Put safeguard in place so this corner case get better handling and does not result in a crash. + F32 texel_area_ratio = 1.0f; + if( te ) + { + texel_area_ratio = fabs(te->mScaleS * te->mScaleT); + } + else + { + LL_WARNS() << "getTE( " << texture_index << " ) returned 0" <getTexture((ETextureIndex)texture_index); + const EBakedTextureIndex baked_index = texture_dict ? texture_dict->mBakedTextureIndex : EBakedTextureIndex::BAKED_NUM_INDICES; + if (texture_dict && texture_dict->mIsLocalTexture) + { + addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, mBakedTextureDatas[baked_index].mIsUsed); + } + } + } + if (isIndexBakedTexture((ETextureIndex) texture_index) && render_avatar) + { + const S32 boost_level = getAvatarBakedBoostLevel(); + imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%4.0f:%4.0f", (F32) sqrt(mMinPixelArea),(F32) sqrt(mMaxPixelArea))); + } } void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) { - // No local texture stats for non-self avatars - return; + // No local texture stats for non-self avatars + return; } -const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames. +const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames. const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = S32_MAX ; //frames void LLVOAvatar::checkTextureLoading() { - static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds + static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds - BOOL pause = !isVisible() ; - if(!pause) - { - mInvisibleTimer.reset() ; - } - if(mLoadedCallbacksPaused == pause) - { + BOOL pause = !isVisible() ; + if(!pause) + { + mInvisibleTimer.reset() ; + } + if(mLoadedCallbacksPaused == pause) + { if (!pause && mFirstFullyVisible && mLoadedCallbackTextures < mCallbackTextureList.size()) { // We still need to update 'loaded' textures count to decide on 'cloud' visibility @@ -5646,120 +5646,120 @@ void LLVOAvatar::checkTextureLoading() } } } - return ; - } - - if(mCallbackTextureList.empty()) //when is self or no callbacks. Note: this list for self is always empty. - { - mLoadedCallbacksPaused = pause ; - mLoadedCallbackTextures = 0; - return ; //nothing to check. - } - - if(pause && mInvisibleTimer.getElapsedTimeF32() < MAX_INVISIBLE_WAITING_TIME) - { - return ; //have not been invisible for enough time. - } - - mLoadedCallbackTextures = pause ? mCallbackTextureList.size() : 0; - - for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); - iter != mCallbackTextureList.end(); ++iter) - { - LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ; - if(tex) - { - if(pause)//pause texture fetching. - { - tex->pauseLoadedCallbacks(&mCallbackTextureList) ; - - //set to terminate texture fetching after MAX_TEXTURE_UPDATE_INTERVAL frames. - tex->setMaxVirtualSizeResetInterval(MAX_TEXTURE_UPDATE_INTERVAL); - tex->resetMaxVirtualSizeResetCounter() ; - } - else//unpause - { - static const F32 START_AREA = 100.f ; - - tex->unpauseLoadedCallbacks(&mCallbackTextureList) ; - tex->addTextureStats(START_AREA); //jump start the fetching again - - // technically shouldn't need to account for missing, but callback might not have happened yet - if (tex->getDiscardLevel() >= 0 || tex->isMissingAsset()) - { - mLoadedCallbackTextures++; // consider it loaded (we have at least some data) - } - } - } - } - - if(!pause) - { - updateTextures() ; //refresh texture stats. - } - mLoadedCallbacksPaused = pause ; - return ; + return ; + } + + if(mCallbackTextureList.empty()) //when is self or no callbacks. Note: this list for self is always empty. + { + mLoadedCallbacksPaused = pause ; + mLoadedCallbackTextures = 0; + return ; //nothing to check. + } + + if(pause && mInvisibleTimer.getElapsedTimeF32() < MAX_INVISIBLE_WAITING_TIME) + { + return ; //have not been invisible for enough time. + } + + mLoadedCallbackTextures = pause ? mCallbackTextureList.size() : 0; + + for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); + iter != mCallbackTextureList.end(); ++iter) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ; + if(tex) + { + if(pause)//pause texture fetching. + { + tex->pauseLoadedCallbacks(&mCallbackTextureList) ; + + //set to terminate texture fetching after MAX_TEXTURE_UPDATE_INTERVAL frames. + tex->setMaxVirtualSizeResetInterval(MAX_TEXTURE_UPDATE_INTERVAL); + tex->resetMaxVirtualSizeResetCounter() ; + } + else//unpause + { + static const F32 START_AREA = 100.f ; + + tex->unpauseLoadedCallbacks(&mCallbackTextureList) ; + tex->addTextureStats(START_AREA); //jump start the fetching again + + // technically shouldn't need to account for missing, but callback might not have happened yet + if (tex->getDiscardLevel() >= 0 || tex->isMissingAsset()) + { + mLoadedCallbackTextures++; // consider it loaded (we have at least some data) + } + } + } + } + + if(!pause) + { + updateTextures() ; //refresh texture stats. + } + mLoadedCallbacksPaused = pause ; + return ; } const F32 SELF_ADDITIONAL_PRI = 0.75f ; void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level) { - //Note: - //if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, - //the texture pipeline will stop fetching this texture. + //Note: + //if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, + //the texture pipeline will stop fetching this texture. - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); - imagep->resetMaxVirtualSizeResetCounter() ; + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); + imagep->resetMaxVirtualSizeResetCounter() ; - mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); - mMinPixelArea = llmin(pixel_area, mMinPixelArea); - imagep->addTextureStats(pixel_area / texel_area_ratio); - imagep->setBoostLevel(boost_level); + mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); + mMinPixelArea = llmin(pixel_area, mMinPixelArea); + imagep->addTextureStats(pixel_area / texel_area_ratio); + imagep->setBoostLevel(boost_level); } -//virtual +//virtual void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index) { - setTEImage(te, imagep); + setTEImage(te, imagep); } -//virtual +//virtual LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const { - return getTEImage(te); + return getTEImage(te); } -//virtual +//virtual const LLTextureEntry* LLVOAvatar::getTexEntry(const U8 te_num) const { - return getTE(te_num); + return getTE(te_num); } -//virtual +//virtual void LLVOAvatar::setTexEntry(const U8 index, const LLTextureEntry &te) { - setTE(index, te); + setTE(index, te); } const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) { - llassert(isIndexBakedTexture(ETextureIndex(te))); - std::string url = ""; - const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL(); - if (appearance_service_url.empty()) - { - // Probably a server-side issue if we get here: - LL_WARNS() << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << LL_ENDL; - return url; - } - - const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); - if (texture_entry != NULL) - { - url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); - //LL_INFOS() << "baked texture url: " << url << LL_ENDL; - } - return url; + llassert(isIndexBakedTexture(ETextureIndex(te))); + std::string url = ""; + const std::string& appearance_service_url = LLAppearanceMgr::instance().getAppearanceServiceURL(); + if (appearance_service_url.empty()) + { + // Probably a server-side issue if we get here: + LL_WARNS() << "AgentAppearanceServiceURL not set - Baked texture requests will fail" << LL_ENDL; + return url; + } + + const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); + if (texture_entry != NULL) + { + url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); + //LL_INFOS() << "baked texture url: " << url << LL_ENDL; + } + return url; } //----------------------------------------------------------------------------- @@ -5768,47 +5768,47 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) void LLVOAvatar::resolveHeightAgent(const LLVector3 &in_pos_agent, LLVector3 &out_pos_agent, LLVector3 &out_norm) { - LLVector3d in_pos_global, out_pos_global; + LLVector3d in_pos_global, out_pos_global; - in_pos_global = gAgent.getPosGlobalFromAgent(in_pos_agent); - resolveHeightGlobal(in_pos_global, out_pos_global, out_norm); - out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global); + in_pos_global = gAgent.getPosGlobalFromAgent(in_pos_agent); + resolveHeightGlobal(in_pos_global, out_pos_global, out_norm); + out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global); } void LLVOAvatar::resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm) { - LLViewerObject *obj; - LLWorld::getInstance()->resolveStepHeightGlobal(this, start_pt, end_pt, out_pos, out_norm, &obj); + LLViewerObject *obj; + LLWorld::getInstance()->resolveStepHeightGlobal(this, start_pt, end_pt, out_pos, out_norm, &obj); } void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm) { - LLVector3d zVec(0.0f, 0.0f, 0.5f); - LLVector3d p0 = inPos + zVec; - LLVector3d p1 = inPos - zVec; - LLViewerObject *obj; - LLWorld::getInstance()->resolveStepHeightGlobal(this, p0, p1, outPos, outNorm, &obj); - if (!obj) - { - mStepOnLand = TRUE; - mStepMaterial = 0; - mStepObjectVelocity.setVec(0.0f, 0.0f, 0.0f); - } - else - { - mStepOnLand = FALSE; - mStepMaterial = obj->getMaterial(); + LLVector3d zVec(0.0f, 0.0f, 0.5f); + LLVector3d p0 = inPos + zVec; + LLVector3d p1 = inPos - zVec; + LLViewerObject *obj; + LLWorld::getInstance()->resolveStepHeightGlobal(this, p0, p1, outPos, outNorm, &obj); + if (!obj) + { + mStepOnLand = TRUE; + mStepMaterial = 0; + mStepObjectVelocity.setVec(0.0f, 0.0f, 0.0f); + } + else + { + mStepOnLand = FALSE; + mStepMaterial = obj->getMaterial(); - // We want the primitive velocity, not our velocity... (which actually subtracts the - // step object velocity) - LLVector3 angularVelocity = obj->getAngularVelocity(); - LLVector3 relativePos = gAgent.getPosAgentFromGlobal(outPos) - obj->getPositionAgent(); + // We want the primitive velocity, not our velocity... (which actually subtracts the + // step object velocity) + LLVector3 angularVelocity = obj->getAngularVelocity(); + LLVector3 relativePos = gAgent.getPosAgentFromGlobal(outPos) - obj->getPositionAgent(); - LLVector3 linearComponent = angularVelocity % relativePos; -// LL_INFOS() << "Linear Component of Rotation Velocity " << linearComponent << LL_ENDL; - mStepObjectVelocity = obj->getVelocity() + linearComponent; - } + LLVector3 linearComponent = angularVelocity % relativePos; +// LL_INFOS() << "Linear Component of Rotation Velocity " << linearComponent << LL_ENDL; + mStepObjectVelocity = obj->getVelocity() + linearComponent; + } } @@ -5817,12 +5817,12 @@ void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos //----------------------------------------------------------------------------- const LLUUID& LLVOAvatar::getStepSound() const { - if ( mStepOnLand ) - { - return sStepSoundOnLand; - } + if ( mStepOnLand ) + { + return sStepSoundOnLand; + } - return sStepSounds[mStepMaterial]; + return sStepSounds[mStepMaterial]; } @@ -5831,106 +5831,106 @@ const LLUUID& LLVOAvatar::getStepSound() const //----------------------------------------------------------------------------- void LLVOAvatar::processAnimationStateChanges() { - if ( isAnyAnimationSignaled(AGENT_WALK_ANIMS, NUM_AGENT_WALK_ANIMS) ) - { - startMotion(ANIM_AGENT_WALK_ADJUST); - stopMotion(ANIM_AGENT_FLY_ADJUST); - } - else if (mInAir && !isSitting()) - { - stopMotion(ANIM_AGENT_WALK_ADJUST); + if ( isAnyAnimationSignaled(AGENT_WALK_ANIMS, NUM_AGENT_WALK_ANIMS) ) + { + startMotion(ANIM_AGENT_WALK_ADJUST); + stopMotion(ANIM_AGENT_FLY_ADJUST); + } + else if (mInAir && !isSitting()) + { + stopMotion(ANIM_AGENT_WALK_ADJUST); if (mEnableDefaultMotions) { - startMotion(ANIM_AGENT_FLY_ADJUST); - } - } - else - { - stopMotion(ANIM_AGENT_WALK_ADJUST); - stopMotion(ANIM_AGENT_FLY_ADJUST); - } - - if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) ) - { + startMotion(ANIM_AGENT_FLY_ADJUST); + } + } + else + { + stopMotion(ANIM_AGENT_WALK_ADJUST); + stopMotion(ANIM_AGENT_FLY_ADJUST); + } + + if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) ) + { if (mEnableDefaultMotions) { - startMotion(ANIM_AGENT_TARGET); + startMotion(ANIM_AGENT_TARGET); } - stopMotion(ANIM_AGENT_BODY_NOISE); - } - else - { - stopMotion(ANIM_AGENT_TARGET); + stopMotion(ANIM_AGENT_BODY_NOISE); + } + else + { + stopMotion(ANIM_AGENT_TARGET); if (mEnableDefaultMotions) { - startMotion(ANIM_AGENT_BODY_NOISE); - } - } - - // clear all current animations - AnimIterator anim_it; - for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) - { - AnimIterator found_anim = mSignaledAnimations.find(anim_it->first); - - // playing, but not signaled, so stop - if (found_anim == mSignaledAnimations.end()) - { - processSingleAnimationStateChange(anim_it->first, FALSE); - mPlayingAnimations.erase(anim_it++); - continue; - } - - ++anim_it; - } - - // if jellydolled, shelve all playing animations - if (getOverallAppearance() != AOA_NORMAL) - { - mPlayingAnimations.clear(); - } - - // start up all new anims - if (getOverallAppearance() == AOA_NORMAL) - { - for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();) - { - AnimIterator found_anim = mPlayingAnimations.find(anim_it->first); - - // signaled but not playing, or different sequence id, start motion - if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second) - { - if (processSingleAnimationStateChange(anim_it->first, TRUE)) - { - mPlayingAnimations[anim_it->first] = anim_it->second; - ++anim_it; - continue; - } - } - - ++anim_it; - } - } - - // clear source information for animations which have been stopped - if (isSelf()) - { - AnimSourceIterator source_it = mAnimationSources.begin(); - - for (source_it = mAnimationSources.begin(); source_it != mAnimationSources.end();) - { - if (mSignaledAnimations.find(source_it->second) == mSignaledAnimations.end()) - { - mAnimationSources.erase(source_it++); - } - else - { - ++source_it; - } - } - } - - stop_glerror(); + startMotion(ANIM_AGENT_BODY_NOISE); + } + } + + // clear all current animations + AnimIterator anim_it; + for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) + { + AnimIterator found_anim = mSignaledAnimations.find(anim_it->first); + + // playing, but not signaled, so stop + if (found_anim == mSignaledAnimations.end()) + { + processSingleAnimationStateChange(anim_it->first, FALSE); + mPlayingAnimations.erase(anim_it++); + continue; + } + + ++anim_it; + } + + // if jellydolled, shelve all playing animations + if (getOverallAppearance() != AOA_NORMAL) + { + mPlayingAnimations.clear(); + } + + // start up all new anims + if (getOverallAppearance() == AOA_NORMAL) + { + for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();) + { + AnimIterator found_anim = mPlayingAnimations.find(anim_it->first); + + // signaled but not playing, or different sequence id, start motion + if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second) + { + if (processSingleAnimationStateChange(anim_it->first, TRUE)) + { + mPlayingAnimations[anim_it->first] = anim_it->second; + ++anim_it; + continue; + } + } + + ++anim_it; + } + } + + // clear source information for animations which have been stopped + if (isSelf()) + { + AnimSourceIterator source_it = mAnimationSources.begin(); + + for (source_it = mAnimationSources.begin(); source_it != mAnimationSources.end();) + { + if (mSignaledAnimations.find(source_it->second) == mSignaledAnimations.end()) + { + mAnimationSources.erase(source_it++); + } + else + { + ++source_it; + } + } + } + + stop_glerror(); } @@ -5944,66 +5944,66 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL // cause constant jiggling of the body or camera. Possible // compromise is to do it on animation changes: computeBodySize(); - - BOOL result = FALSE; - - if ( start ) // start animation - { - if (anim_id == ANIM_AGENT_TYPE) - { - if (gAudiop) - { - LLVector3d char_pos_global = gAgent.getPosGlobalFromAgent(getCharacterPosition()); - if (LLViewerParcelMgr::getInstance()->canHearSound(char_pos_global) - && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) - { - // RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed - // to support both spatialized and non-spatialized instances of the same sound - //if (isSelf()) - //{ - // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); - //} - //else - { + + BOOL result = FALSE; + + if ( start ) // start animation + { + if (anim_id == ANIM_AGENT_TYPE) + { + if (gAudiop) + { + LLVector3d char_pos_global = gAgent.getPosGlobalFromAgent(getCharacterPosition()); + if (LLViewerParcelMgr::getInstance()->canHearSound(char_pos_global) + && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) + { + // RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed + // to support both spatialized and non-spatialized instances of the same sound + //if (isSelf()) + //{ + // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); + //} + //else + { static LLCachedControl ui_snd_string(gSavedSettings, "UISndTyping"); - LLUUID sound_id = LLUUID(ui_snd_string); - gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global); - } - } - } - } - else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) - { - sitDown(TRUE); - } - - - if (startMotion(anim_id)) - { - result = TRUE; - } - else - { - LL_WARNS("Motion") << "Failed to start motion!" << LL_ENDL; - } - } - else //stop animation - { - if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) - { - sitDown(FALSE); - } - if ((anim_id == ANIM_AGENT_DO_NOT_DISTURB) && gAgent.isDoNotDisturb()) - { - // re-assert DND tag animation - gAgent.sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, ANIM_REQUEST_START); - return result; - } - stopMotion(anim_id); - result = TRUE; - } - - return result; + LLUUID sound_id = LLUUID(ui_snd_string); + gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global); + } + } + } + } + else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) + { + sitDown(TRUE); + } + + + if (startMotion(anim_id)) + { + result = TRUE; + } + else + { + LL_WARNS("Motion") << "Failed to start motion!" << LL_ENDL; + } + } + else //stop animation + { + if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED) + { + sitDown(FALSE); + } + if ((anim_id == ANIM_AGENT_DO_NOT_DISTURB) && gAgent.isDoNotDisturb()) + { + // re-assert DND tag animation + gAgent.sendAnimationRequest(ANIM_AGENT_DO_NOT_DISTURB, ANIM_REQUEST_START); + return result; + } + stopMotion(anim_id); + result = TRUE; + } + + return result; } //----------------------------------------------------------------------------- @@ -6011,14 +6011,14 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL //----------------------------------------------------------------------------- BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const { - for (S32 i = 0; i < num_anims; i++) - { - if(mSignaledAnimations.find(anim_array[i]) != mSignaledAnimations.end()) - { - return TRUE; - } - } - return FALSE; + for (S32 i = 0; i < num_anims; i++) + { + if(mSignaledAnimations.find(anim_array[i]) != mSignaledAnimations.end()) + { + return TRUE; + } + } + return FALSE; } //----------------------------------------------------------------------------- @@ -6026,8 +6026,8 @@ BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_ //----------------------------------------------------------------------------- void LLVOAvatar::resetAnimations() { - LLKeyframeMotion::flushKeyframeCache(); - flushAllMotions(); + LLKeyframeMotion::flushKeyframeCache(); + flushAllMotions(); } // Override selectively based on avatar sex and whether we're using new @@ -6035,52 +6035,52 @@ void LLVOAvatar::resetAnimations() LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) { static LLCachedControl use_new_walk_run(gSavedSettings, "UseNewWalkRun"); - LLUUID result = id; - - // start special case female walk for female avatars - if (getSex() == SEX_FEMALE) - { - if (id == ANIM_AGENT_WALK) - { - if (use_new_walk_run) - result = ANIM_AGENT_FEMALE_WALK_NEW; - else - result = ANIM_AGENT_FEMALE_WALK; - } - else if (id == ANIM_AGENT_RUN) - { - // There is no old female run animation, so only override - // in one case. - if (use_new_walk_run) - result = ANIM_AGENT_FEMALE_RUN_NEW; - } - else if (id == ANIM_AGENT_SIT) - { - result = ANIM_AGENT_SIT_FEMALE; - } - } - else - { - // Male avatar. - if (id == ANIM_AGENT_WALK) - { - if (use_new_walk_run) - result = ANIM_AGENT_WALK_NEW; - } - else if (id == ANIM_AGENT_RUN) - { - if (use_new_walk_run) - result = ANIM_AGENT_RUN_NEW; - } - // keeps in sync with setSex() related code (viewer controls sit's sex) - else if (id == ANIM_AGENT_SIT_FEMALE) - { - result = ANIM_AGENT_SIT; - } - - } - - return result; + LLUUID result = id; + + // start special case female walk for female avatars + if (getSex() == SEX_FEMALE) + { + if (id == ANIM_AGENT_WALK) + { + if (use_new_walk_run) + result = ANIM_AGENT_FEMALE_WALK_NEW; + else + result = ANIM_AGENT_FEMALE_WALK; + } + else if (id == ANIM_AGENT_RUN) + { + // There is no old female run animation, so only override + // in one case. + if (use_new_walk_run) + result = ANIM_AGENT_FEMALE_RUN_NEW; + } + else if (id == ANIM_AGENT_SIT) + { + result = ANIM_AGENT_SIT_FEMALE; + } + } + else + { + // Male avatar. + if (id == ANIM_AGENT_WALK) + { + if (use_new_walk_run) + result = ANIM_AGENT_WALK_NEW; + } + else if (id == ANIM_AGENT_RUN) + { + if (use_new_walk_run) + result = ANIM_AGENT_RUN_NEW; + } + // keeps in sync with setSex() related code (viewer controls sit's sex) + else if (id == ANIM_AGENT_SIT_FEMALE) + { + result = ANIM_AGENT_SIT; + } + + } + + return result; } @@ -6091,21 +6091,21 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id) //----------------------------------------------------------------------------- BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) { - LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL; + LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL; - LLUUID remap_id = remapMotionID(id); + LLUUID remap_id = remapMotionID(id); - if (remap_id != id) - { - LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL; - } + if (remap_id != id) + { + LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL; + } - if (isSelf() && remap_id == ANIM_AGENT_AWAY) - { - gAgent.setAFK(); - } + if (isSelf() && remap_id == ANIM_AGENT_AWAY) + { + gAgent.setAFK(); + } - return LLCharacter::startMotion(remap_id, time_offset); + return LLCharacter::startMotion(remap_id, time_offset); } //----------------------------------------------------------------------------- @@ -6113,21 +6113,21 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) //----------------------------------------------------------------------------- BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) { - LL_DEBUGS("Motion") << "Motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL; + LL_DEBUGS("Motion") << "Motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL; + + LLUUID remap_id = remapMotionID(id); - LLUUID remap_id = remapMotionID(id); - - if (remap_id != id) - { - LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL; - } + if (remap_id != id) + { + LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL; + } - if (isSelf()) - { - gAgent.onAnimStop(remap_id); - } + if (isSelf()) + { + gAgent.onAnimStop(remap_id); + } - return LLCharacter::stopMotion(remap_id, stop_immediate); + return LLCharacter::stopMotion(remap_id, stop_immediate); } //----------------------------------------------------------------------------- @@ -6136,7 +6136,7 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) // virtual bool LLVOAvatar::hasMotionFromSource(const LLUUID& source_id) { - return false; + return false; } //----------------------------------------------------------------------------- @@ -6152,8 +6152,8 @@ void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id) //----------------------------------------------------------------------------- void LLVOAvatar::addDebugText(const std::string& text) { - mDebugText.append(1, '\n'); - mDebugText.append(text); + mDebugText.append(1, '\n'); + mDebugText.append(text); } //----------------------------------------------------------------------------- @@ -6161,7 +6161,7 @@ void LLVOAvatar::addDebugText(const std::string& text) //----------------------------------------------------------------------------- const LLUUID& LLVOAvatar::getID() const { - return mID; + return mID; } //----------------------------------------------------------------------------- @@ -6170,33 +6170,33 @@ const LLUUID& LLVOAvatar::getID() const // RN: avatar joints are multi-rooted to include screen-based attachments LLJoint *LLVOAvatar::getJoint( const std::string &name ) { - joint_map_t::iterator iter = mJointMap.find(name); - - LLJoint* jointp = NULL; - - if (iter == mJointMap.end() || iter->second == NULL) - { //search for joint and cache found joint in lookup table - if (mJointAliasMap.empty()) - { - getJointAliases(); - } - joint_alias_map_t::const_iterator alias_iter = mJointAliasMap.find(name); - std::string canonical_name; - if (alias_iter != mJointAliasMap.end()) - { - canonical_name = alias_iter->second; - } - else - { - canonical_name = name; - } - jointp = mRoot->findJoint(canonical_name); - mJointMap[name] = jointp; - } - else - { //return cached pointer - jointp = iter->second; - } + joint_map_t::iterator iter = mJointMap.find(name); + + LLJoint* jointp = NULL; + + if (iter == mJointMap.end() || iter->second == NULL) + { //search for joint and cache found joint in lookup table + if (mJointAliasMap.empty()) + { + getJointAliases(); + } + joint_alias_map_t::const_iterator alias_iter = mJointAliasMap.find(name); + std::string canonical_name; + if (alias_iter != mJointAliasMap.end()) + { + canonical_name = alias_iter->second; + } + else + { + canonical_name = name; + } + jointp = mRoot->findJoint(canonical_name); + mJointMap[name] = jointp; + } + else + { //return cached pointer + jointp = iter->second; + } #ifndef LL_RELEASE_FOR_DOWNLOAD if (jointp && jointp->getName()!="mScreen" && jointp->getName()!="mRoot") @@ -6204,7 +6204,7 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) llassert(getJoint(jointp->getJointNum())==jointp); } #endif - return jointp; + return jointp; } LLJoint *LLVOAvatar::getJoint( S32 joint_num ) @@ -6232,8 +6232,8 @@ LLJoint *LLVOAvatar::getJoint( S32 joint_num ) } } } - - llassert(!pJoint || pJoint->getJointNum() == joint_num); + + llassert(!pJoint || pJoint->getJointNum() == joint_num); return pJoint; } @@ -6246,31 +6246,31 @@ LLJoint *LLVOAvatar::getJoint( S32 joint_num ) // static bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id) { - mesh_id.setNull(); - - //If a VO has a skin that we'll reset the joint positions to their default - if ( pVO && pVO->mDrawable ) - { - LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); - if ( pVObj ) - { - const LLMeshSkinInfo* pSkinData = pVObj->getSkinInfo(); - if (pSkinData - && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig - && pSkinData->mAlternateBindMatrix.size() > 0 ) - { - mesh_id = pSkinData->mMeshID; - return true; - } - } - } - return false; + mesh_id.setNull(); + + //If a VO has a skin that we'll reset the joint positions to their default + if ( pVO && pVO->mDrawable ) + { + LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); + if ( pVObj ) + { + const LLMeshSkinInfo* pSkinData = pVObj->getSkinInfo(); + if (pSkinData + && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig + && pSkinData->mAlternateBindMatrix.size() > 0 ) + { + mesh_id = pSkinData->mMeshID; + return true; + } + } + } + return false; } bool LLVOAvatar::jointIsRiggedTo(const LLJoint *joint) const { if (joint) - { + { const LLJointRiggingInfoTab& tab = mJointRiggingInfoTab; S32 joint_num = joint->getJointNum(); if (joint_num < tab.size() && tab[joint_num].isRiggedTo()) @@ -6286,25 +6286,25 @@ void LLVOAvatar::clearAttachmentOverrides() LLScopedContextString str("clearAttachmentOverrides " + getFullname()); for (S32 i=0; iclearAttachmentPosOverrides(); - pJoint->clearAttachmentScaleOverrides(); + pJoint->clearAttachmentPosOverrides(); + pJoint->clearAttachmentScaleOverrides(); } - } + } if (mPelvisFixups.count()>0) { mPelvisFixups.clear(); LLJoint* pJointPelvis = getJoint("mPelvis"); if (pJointPelvis) - { - pJointPelvis->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); + { + pJointPelvis->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); } - postPelvisSetRecalc(); - } + postPelvisSetRecalc(); + } mActiveOverrideMeshes.clear(); onActiveOverrideMeshesChanged(); @@ -6319,32 +6319,32 @@ void LLVOAvatar::rebuildAttachmentOverrides() LL_DEBUGS("AnimatedObjects") << "rebuilding" << LL_ENDL; dumpStack("AnimatedObjectsStack"); - + clearAttachmentOverrides(); // Handle the case that we're resetting the skeleton of an animated object. LLControlAvatar *control_av = dynamic_cast(this); if (control_av) - { + { LLVOVolume *volp = control_av->mRootVolp; if (volp) { - LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " + LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " << (S32) (1+volp->numChildren()) << LL_ENDL; addAttachmentOverridesForObject(volp); } } // Attached objects - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment *attachment_pt = (*iter).second; + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment *attachment_pt = (*iter).second; if (attachment_pt) { for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin(); - at_it != attachment_pt->mAttachedObjects.end(); ++at_it) + at_it != attachment_pt->mAttachedObjects.end(); ++at_it) { LLViewerObject *vo = at_it->get(); // Attached animated objects affect joints in their control @@ -6372,7 +6372,7 @@ void LLVOAvatar::updateAttachmentOverrides() dumpStack("AnimatedObjectsStack"); std::set meshes_seen; - + // Handle the case that we're updating the skeleton of an animated object. LLControlAvatar *control_av = dynamic_cast(this); if (control_av) @@ -6380,22 +6380,22 @@ void LLVOAvatar::updateAttachmentOverrides() LLVOVolume *volp = control_av->mRootVolp; if (volp) { - LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " + LL_DEBUGS("Avatar") << volp->getID() << " adding attachment overrides for root vol, prim count " << (S32) (1+volp->numChildren()) << LL_ENDL; addAttachmentOverridesForObject(volp, &meshes_seen); } } // Attached objects - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment *attachment_pt = (*iter).second; + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment *attachment_pt = (*iter).second; if (attachment_pt) { for (LLViewerJointAttachment::attachedobjs_vec_t::iterator at_it = attachment_pt->mAttachedObjects.begin(); - at_it != attachment_pt->mAttachedObjects.end(); ++at_it) + at_it != attachment_pt->mAttachedObjects.end(); ++at_it) { LLViewerObject *vo = at_it->get(); // Attached animated objects affect joints in their control @@ -6409,8 +6409,8 @@ void LLVOAvatar::updateAttachmentOverrides() } // Remove meshes that are no longer present on the skeleton - // have to work with a copy because removeAttachmentOverrides() will change mActiveOverrideMeshes. - std::set active_override_meshes = mActiveOverrideMeshes; + // have to work with a copy because removeAttachmentOverrides() will change mActiveOverrideMeshes. + std::set active_override_meshes = mActiveOverrideMeshes; for (std::set::iterator it = active_override_meshes.begin(); it != active_override_meshes.end(); ++it) { if (meshes_seen.find(*it) == meshes_seen.end()) @@ -6493,63 +6493,63 @@ void LLVOAvatar::notifyAttachmentMeshLoaded() void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set* meshes_seen, bool recursive) { if (vo->getAvatar() != this && vo->getAvatarAncestor() != this) - { - LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; return; - } + } LLScopedContextString str("addAttachmentOverridesForObject " + getFullname()); - if (getOverallAppearance() != AOA_NORMAL) - { - return; - } - + if (getOverallAppearance() != AOA_NORMAL) + { + return; + } + LL_DEBUGS("AnimatedObjects") << "adding" << LL_ENDL; dumpStack("AnimatedObjectsStack"); - - // Process all children + + // Process all children if (recursive) { - LLViewerObject::const_child_list_t& children = vo->getChildren(); - for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); - it != children.end(); ++it) - { - LLViewerObject *childp = *it; + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; addAttachmentOverridesForObject(childp, meshes_seen, true); } - } + } - LLVOVolume *vobj = dynamic_cast(vo); - bool pelvisGotSet = false; + LLVOVolume *vobj = dynamic_cast(vo); + bool pelvisGotSet = false; - if (!vobj) - { - return; - } + if (!vobj) + { + return; + } - LLViewerObject *root_object = (LLViewerObject*)vobj->getRoot(); + LLViewerObject *root_object = (LLViewerObject*)vobj->getRoot(); LL_DEBUGS("AnimatedObjects") << "trying to add attachment overrides for root object " << root_object->getID() << " prim is " << vobj << LL_ENDL; - if (vobj->isMesh() && - ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) - { + if (vobj->isMesh() && + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { LL_DEBUGS("AnimatedObjects") << "failed to add attachment overrides for root object " << root_object->getID() << " mesh asset not loaded" << LL_ENDL; - return; - } - const LLMeshSkinInfo* pSkinData = vobj->getSkinInfo(); + return; + } + const LLMeshSkinInfo* pSkinData = vobj->getSkinInfo(); - if ( vobj && vobj->isMesh() && pSkinData ) - { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( vobj && vobj->isMesh() && pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); const int jointCnt = pSkinData->mJointNames.size(); if ((bindCnt > 0) && (bindCnt != jointCnt)) { LL_WARNS_ONCE() << "invalid mesh, bindCnt " << bindCnt << "!= jointCnt " << jointCnt << ", joint overrides will be ignored." << LL_ENDL; } - if ((bindCnt > 0) && (bindCnt == jointCnt)) - { - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - const LLUUID& mesh_id = pSkinData->mMeshID; + if ((bindCnt > 0) && (bindCnt == jointCnt)) + { + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + const LLUUID& mesh_id = pSkinData->mMeshID; if (meshes_seen) { @@ -6558,38 +6558,38 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::setgetID() << ", already loaded" << LL_ENDL; } else { - LL_DEBUGS("AnimatedObjects") << "adding attachment overrides for " << mesh_id + LL_DEBUGS("AnimatedObjects") << "adding attachment overrides for " << mesh_id << " to root object " << root_object->getID() << LL_ENDL; } - bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; - if ( fullRig && !mesh_overrides_loaded ) - { - for ( int i=0; imJointNames[i].c_str(); - LLJoint* pJoint = getJoint( lookingForJoint ); - if (pJoint) - { - const LLVector3& jointPos = LLVector3(pSkinData->mAlternateBindMatrix[i].getTranslation()); + bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; + if ( fullRig && !mesh_overrides_loaded ) + { + for ( int i=0; imJointNames[i].c_str(); + LLJoint* pJoint = getJoint( lookingForJoint ); + if (pJoint) + { + const LLVector3& jointPos = LLVector3(pSkinData->mAlternateBindMatrix[i].getTranslation()); if (pJoint->aboveJointPosThreshold(jointPos)) { bool override_changed; pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString(), override_changed ); - + if (override_changed) { //If joint is a pelvis then handle old/new pelvis to foot values if ( lookingForJoint == "mPelvis" ) - { - pelvisGotSet = true; - } + { + pelvisGotSet = true; + } } if (pSkinData->mLockScaleIfJointPosition) { @@ -6598,36 +6598,36 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::setaddAttachmentScaleOverride(pJoint->getDefaultScale(), mesh_id, avString()); } } - } - } - if (pelvisZOffset != 0.0F) - { + } + } + if (pelvisZOffset != 0.0F) + { F32 pelvis_fixup_before; bool has_fixup_before = hasPelvisFixup(pelvis_fixup_before); - addPelvisFixup( pelvisZOffset, mesh_id ); - F32 pelvis_fixup_after; + addPelvisFixup( pelvisZOffset, mesh_id ); + F32 pelvis_fixup_after; hasPelvisFixup(pelvis_fixup_after); // Don't have to check bool here because we just added it... if (!has_fixup_before || (pelvis_fixup_before != pelvis_fixup_after)) { - pelvisGotSet = true; + pelvisGotSet = true; } - - } + + } mActiveOverrideMeshes.insert(mesh_id); onActiveOverrideMeshesChanged(); - } - } - } + } + } + } else { LL_DEBUGS("AnimatedObjects") << "failed to add attachment overrides for root object " << root_object->getID() << " not mesh or no pSkinData" << LL_ENDL; } - - //Rebuild body data if we altered joints/pelvis - if ( pelvisGotSet ) - { - postPelvisSetRecalc(); - } + + //Rebuild body data if we altered joints/pelvis + if ( pelvisGotSet ) + { + postPelvisSetRecalc(); + } } //----------------------------------------------------------------------------- @@ -6640,26 +6640,26 @@ void LLVOAvatar::getAttachmentOverrideNames(std::set& pos_names, st LLUUID mesh_id; // Bones - for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); + for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); iter != mSkeleton.end(); ++iter) - { - const LLJoint* pJoint = (*iter); - if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) - { + { + const LLJoint* pJoint = (*iter); + if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { pos_names.insert(pJoint->getName()); - } - if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) - { + } + if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) + { scale_names.insert(pJoint->getName()); - } - } + } + } // Attachment points - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment *attachment_pt = (*iter).second; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; if (attachment_pt && attachment_pt->hasAttachmentPosOverride(pos,mesh_id)) { pos_names.insert(attachment_pt->getName()); @@ -6707,28 +6707,28 @@ void LLVOAvatar::showAttachmentOverrides(bool verbose) const S32 count = 0; // Bones - for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); + for (avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); iter != mSkeleton.end(); ++iter) - { - const LLJoint* pJoint = (*iter); - if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) - { - pJoint->showAttachmentPosOverrides(getFullname()); + { + const LLJoint* pJoint = (*iter); + if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { + pJoint->showAttachmentPosOverrides(getFullname()); count++; - } - if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) - { - pJoint->showAttachmentScaleOverrides(getFullname()); + } + if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) + { + pJoint->showAttachmentScaleOverrides(getFullname()); count++; } - } + } // Attachment points - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment *attachment_pt = (*iter).second; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; if (attachment_pt && attachment_pt->hasAttachmentPosOverride(pos,mesh_id)) { attachment_pt->showAttachmentPosOverrides(getFullname()); @@ -6749,53 +6749,53 @@ void LLVOAvatar::showAttachmentOverrides(bool verbose) const void LLVOAvatar::removeAttachmentOverridesForObject(LLViewerObject *vo) { if (vo->getAvatar() != this && vo->getAvatarAncestor() != this) - { - LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; return; - } - - // Process all children - LLViewerObject::const_child_list_t& children = vo->getChildren(); - for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); - it != children.end(); ++it) - { - LLViewerObject *childp = *it; - removeAttachmentOverridesForObject(childp); - } - - // Process self. - LLUUID mesh_id; - if (getRiggedMeshID(vo,mesh_id)) - { - removeAttachmentOverridesForObject(mesh_id); - } + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + removeAttachmentOverridesForObject(childp); + } + + // Process self. + LLUUID mesh_id; + if (getRiggedMeshID(vo,mesh_id)) + { + removeAttachmentOverridesForObject(mesh_id); + } } //----------------------------------------------------------------------------- // removeAttachmentOverridesForObject //----------------------------------------------------------------------------- void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id) -{ - LLJoint* pJointPelvis = getJoint("mPelvis"); +{ + LLJoint* pJointPelvis = getJoint("mPelvis"); const std::string av_string = avString(); for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) - { + { LLJoint *pJoint = getJoint(joint_num); - if ( pJoint ) - { + if ( pJoint ) + { bool dummy; // unused - pJoint->removeAttachmentPosOverride(mesh_id, av_string, dummy); - pJoint->removeAttachmentScaleOverride(mesh_id, av_string); - } - if ( pJoint && pJoint == pJointPelvis) - { - removePelvisFixup( mesh_id ); - // SL-315 - pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); - } - } - - postPelvisSetRecalc(); + pJoint->removeAttachmentPosOverride(mesh_id, av_string, dummy); + pJoint->removeAttachmentScaleOverride(mesh_id, av_string); + } + if ( pJoint && pJoint == pJointPelvis) + { + removePelvisFixup( mesh_id ); + // SL-315 + pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); + } + } + + postPelvisSetRecalc(); mActiveOverrideMeshes.erase(mesh_id); onActiveOverrideMeshesChanged(); @@ -6805,14 +6805,14 @@ void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id) //----------------------------------------------------------------------------- LLVector3 LLVOAvatar::getCharacterPosition() { - if (mDrawable.notNull()) - { - return mDrawable->getPositionAgent(); - } - else - { - return getPositionAgent(); - } + if (mDrawable.notNull()) + { + return mDrawable->getPositionAgent(); + } + else + { + return getPositionAgent(); + } } @@ -6821,7 +6821,7 @@ LLVector3 LLVOAvatar::getCharacterPosition() //----------------------------------------------------------------------------- LLQuaternion LLVOAvatar::getCharacterRotation() { - return getRotation(); + return getRotation(); } @@ -6830,7 +6830,7 @@ LLQuaternion LLVOAvatar::getCharacterRotation() //----------------------------------------------------------------------------- LLVector3 LLVOAvatar::getCharacterVelocity() { - return getVelocity() - mStepObjectVelocity; + return getVelocity() - mStepObjectVelocity; } @@ -6839,7 +6839,7 @@ LLVector3 LLVOAvatar::getCharacterVelocity() //----------------------------------------------------------------------------- LLVector3 LLVOAvatar::getCharacterAngularVelocity() { - return getAngularVelocity(); + return getAngularVelocity(); } //----------------------------------------------------------------------------- @@ -6847,22 +6847,22 @@ LLVector3 LLVOAvatar::getCharacterAngularVelocity() //----------------------------------------------------------------------------- void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_agent, LLVector3 &outNorm) { - LLVector3d z_vec(0.0f, 0.0f, 1.0f); - LLVector3d p0_global, p1_global; + LLVector3d z_vec(0.0f, 0.0f, 1.0f); + LLVector3d p0_global, p1_global; + + if (isUIAvatar()) + { + outNorm.setVec(z_vec); + out_pos_agent = in_pos_agent; + return; + } - if (isUIAvatar()) - { - outNorm.setVec(z_vec); - out_pos_agent = in_pos_agent; - return; - } - - p0_global = gAgent.getPosGlobalFromAgent(in_pos_agent) + z_vec; - p1_global = gAgent.getPosGlobalFromAgent(in_pos_agent) - z_vec; - LLViewerObject *obj; - LLVector3d out_pos_global; - LLWorld::getInstance()->resolveStepHeightGlobal(this, p0_global, p1_global, out_pos_global, outNorm, &obj); - out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global); + p0_global = gAgent.getPosGlobalFromAgent(in_pos_agent) + z_vec; + p1_global = gAgent.getPosGlobalFromAgent(in_pos_agent) - z_vec; + LLViewerObject *obj; + LLVector3d out_pos_global; + LLWorld::getInstance()->resolveStepHeightGlobal(this, p0_global, p1_global, out_pos_global, outNorm, &obj); + out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global); } //----------------------------------------------------------------------------- @@ -6870,7 +6870,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age //----------------------------------------------------------------------------- F32 LLVOAvatar::getTimeDilation() { - return mRegionp ? mRegionp->getTimeDilation() : 1.f; + return mRegionp ? mRegionp->getTimeDilation() : 1.f; } @@ -6879,11 +6879,11 @@ F32 LLVOAvatar::getTimeDilation() //----------------------------------------------------------------------------- F32 LLVOAvatar::getPixelArea() const { - if (isUIAvatar()) - { - return 100000.f; - } - return mPixelArea; + if (isUIAvatar()) + { + return 100000.f; + } + return mPixelArea; } @@ -6891,17 +6891,17 @@ F32 LLVOAvatar::getPixelArea() const //----------------------------------------------------------------------------- // LLVOAvatar::getPosGlobalFromAgent() //----------------------------------------------------------------------------- -LLVector3d LLVOAvatar::getPosGlobalFromAgent(const LLVector3 &position) +LLVector3d LLVOAvatar::getPosGlobalFromAgent(const LLVector3 &position) { - return gAgent.getPosGlobalFromAgent(position); + return gAgent.getPosGlobalFromAgent(position); } //----------------------------------------------------------------------------- // getPosAgentFromGlobal() //----------------------------------------------------------------------------- -LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position) +LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position) { - return gAgent.getPosAgentFromGlobal(position); + return gAgent.getPosAgentFromGlobal(position); } @@ -6911,7 +6911,7 @@ LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position) // virtual void LLVOAvatar::requestStopMotion( LLMotion* motion ) { - // Only agent avatars should handle the stop motion notifications. + // Only agent avatars should handle the stop motion notifications. } //----------------------------------------------------------------------------- @@ -6920,31 +6920,31 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion ) //virtual BOOL LLVOAvatar::loadSkeletonNode () { - if (!LLAvatarAppearance::loadSkeletonNode()) - { - return FALSE; - } - + if (!LLAvatarAppearance::loadSkeletonNode()) + { + return FALSE; + } + bool ignore_hud_joints = false; initAttachmentPoints(ignore_hud_joints); - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- -// initAttachmentPoints(): creates attachment points if needed, sets state based on avatar_lad.xml. +// initAttachmentPoints(): creates attachment points if needed, sets state based on avatar_lad.xml. //----------------------------------------------------------------------------- void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) { LLAvatarXmlInfo::attachment_info_list_t::iterator iter; for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); - iter != sAvatarXmlInfo->mAttachmentInfoList.end(); + iter != sAvatarXmlInfo->mAttachmentInfoList.end(); ++iter) { LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; if (info->mIsHUDAttachment && (!isSelf() || ignore_hud_joints)) { - //don't process hud joint for other avatars. + //don't process hud joint for other avatars. continue; } @@ -6981,7 +6981,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) attachment->setOriginalPosition(info->mPosition); attachment->setDefaultPosition(info->mPosition); } - + if (info->mHasRotation) { LLQuaternion rotation; @@ -7013,7 +7013,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) if (newly_created) { mAttachmentPoints[attachmentID] = attachment; - + // now add attachment joint parent_joint->addChild(attachment); } @@ -7025,45 +7025,45 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) //----------------------------------------------------------------------------- void LLVOAvatar::updateVisualParams() { - ESex avatar_sex = (getVisualParamWeight("male") > 0.5f) ? SEX_MALE : SEX_FEMALE; - if (getSex() != avatar_sex) - { - if (mIsSitting && findMotion(avatar_sex == SEX_MALE ? ANIM_AGENT_SIT_FEMALE : ANIM_AGENT_SIT) != NULL) - { - // In some cases of gender change server changes sit motion with motion message, - // but in case of some avatars (legacy?) there is no update from server side, - // likely because server doesn't know about difference between motions - // (female and male sit ids are same server side, so it is likely unaware that it - // need to send update) - // Make sure motion is up to date - stopMotion(ANIM_AGENT_SIT); - setSex(avatar_sex); - startMotion(ANIM_AGENT_SIT); - } - else - { - setSex(avatar_sex); - } - } - - LLCharacter::updateVisualParams(); - - if (mLastSkeletonSerialNum != mSkeletonSerialNum) - { - computeBodySize(); - mLastSkeletonSerialNum = mSkeletonSerialNum; - mRoot->updateWorldMatrixChildren(); - } - - dirtyMesh(); - updateHeadOffset(); + ESex avatar_sex = (getVisualParamWeight("male") > 0.5f) ? SEX_MALE : SEX_FEMALE; + if (getSex() != avatar_sex) + { + if (mIsSitting && findMotion(avatar_sex == SEX_MALE ? ANIM_AGENT_SIT_FEMALE : ANIM_AGENT_SIT) != NULL) + { + // In some cases of gender change server changes sit motion with motion message, + // but in case of some avatars (legacy?) there is no update from server side, + // likely because server doesn't know about difference between motions + // (female and male sit ids are same server side, so it is likely unaware that it + // need to send update) + // Make sure motion is up to date + stopMotion(ANIM_AGENT_SIT); + setSex(avatar_sex); + startMotion(ANIM_AGENT_SIT); + } + else + { + setSex(avatar_sex); + } + } + + LLCharacter::updateVisualParams(); + + if (mLastSkeletonSerialNum != mSkeletonSerialNum) + { + computeBodySize(); + mLastSkeletonSerialNum = mSkeletonSerialNum; + mRoot->updateWorldMatrixChildren(); + } + + dirtyMesh(); + updateHeadOffset(); } //----------------------------------------------------------------------------- // isActive() //----------------------------------------------------------------------------- BOOL LLVOAvatar::isActive() const { - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -7071,39 +7071,39 @@ BOOL LLVOAvatar::isActive() const //----------------------------------------------------------------------------- void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { - if (mDrawable.isNull()) - { - return; - } + if (mDrawable.isNull()) + { + return; + } - const LLVector4a* ext = mDrawable->getSpatialExtents(); - LLVector4a center; - center.setAdd(ext[1], ext[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a center; + center.setAdd(ext[1], ext[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - mImpostorPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); + mImpostorPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); mPixelArea = mImpostorPixelArea; - F32 range = mDrawable->mDistanceWRTCamera; + F32 range = mDrawable->mDistanceWRTCamera; - if (range < 0.001f) // range == zero - { - mAppAngle = 180.f; - } - else - { - F32 radius = size.getLength3().getF32(); - mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG; - } + if (range < 0.001f) // range == zero + { + mAppAngle = 180.f; + } + else + { + F32 radius = size.getLength3().getF32(); + mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG; + } - // We always want to look good to ourselves - if( isSelf() ) - { - mPixelArea = llmax( mPixelArea, F32(getTexImageSize() / 16) ); - } + // We always want to look good to ourselves + if( isSelf() ) + { + mPixelArea = llmax( mPixelArea, F32(getTexImageSize() / 16) ); + } } //----------------------------------------------------------------------------- @@ -7111,48 +7111,48 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) //----------------------------------------------------------------------------- BOOL LLVOAvatar::updateJointLODs() { - const F32 MAX_PIXEL_AREA = 100000000.f; - F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE)); - F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f); - F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); - F32 area_scale = 0.16f; - - if (isSelf()) - { - if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - mAdjustedPixelArea = mPixelArea*area_scale; - } - } - else if (mIsDummy) - { - mAdjustedPixelArea = MAX_PIXEL_AREA; - } - else - { - // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars - mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; - } - - // now select meshes to render based on adjusted pixel area - LLViewerJoint* root = dynamic_cast(mRoot); - BOOL res = FALSE; - if (root) - { - res = root->updateLOD(mAdjustedPixelArea, TRUE); - } - if (res) - { - sNumLODChangesThisFrame++; - dirtyMesh(2); - return TRUE; - } - - return FALSE; + const F32 MAX_PIXEL_AREA = 100000000.f; + F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE)); + F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f); + F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); + F32 area_scale = 0.16f; + + if (isSelf()) + { + if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + mAdjustedPixelArea = mPixelArea*area_scale; + } + } + else if (mIsDummy) + { + mAdjustedPixelArea = MAX_PIXEL_AREA; + } + else + { + // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars + mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; + } + + // now select meshes to render based on adjusted pixel area + LLViewerJoint* root = dynamic_cast(mRoot); + BOOL res = FALSE; + if (root) + { + res = root->updateLOD(mAdjustedPixelArea, TRUE); + } + if (res) + { + sNumLODChangesThisFrame++; + dirtyMesh(2); + return TRUE; + } + + return FALSE; } //----------------------------------------------------------------------------- @@ -7160,32 +7160,32 @@ BOOL LLVOAvatar::updateJointLODs() //----------------------------------------------------------------------------- LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) { - pipeline->allocDrawable(this); - mDrawable->setLit(FALSE); + pipeline->allocDrawable(this); + mDrawable->setLit(FALSE); + + LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*)gPipeline.getPool(mIsControlAvatar ? LLDrawPool::POOL_CONTROL_AV : LLDrawPool::POOL_AVATAR); - LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*)gPipeline.getPool(mIsControlAvatar ? LLDrawPool::POOL_CONTROL_AV : LLDrawPool::POOL_AVATAR); + // Only a single face (one per avatar) + //this face will be splitted into several if its vertex buffer is too long. + mDrawable->setState(LLDrawable::ACTIVE); + mDrawable->addFace(poolp, NULL); + mDrawable->setRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR); - // Only a single face (one per avatar) - //this face will be splitted into several if its vertex buffer is too long. - mDrawable->setState(LLDrawable::ACTIVE); - mDrawable->addFace(poolp, NULL); - mDrawable->setRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR); - - mNumInitFaces = mDrawable->getNumFaces() ; + mNumInitFaces = mDrawable->getNumFaces() ; - dirtyMesh(2); - return mDrawable; + dirtyMesh(2); + return mDrawable; } void LLVOAvatar::updateGL() { - if (mMeshTexturesDirty) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR - updateMeshTextures(); - mMeshTexturesDirty = FALSE; - } + if (mMeshTexturesDirty) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR + updateMeshTextures(); + mMeshTexturesDirty = FALSE; + } } //----------------------------------------------------------------------------- @@ -7194,22 +7194,22 @@ void LLVOAvatar::updateGL() BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))) - { - return TRUE; - } - - if (!mMeshValid) - { - return TRUE; - } + if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))) + { + return TRUE; + } - if (!drawable) - { - LL_ERRS() << "LLVOAvatar::updateGeometry() called with NULL drawable" << LL_ENDL; - } + if (!mMeshValid) + { + return TRUE; + } + + if (!drawable) + { + LL_ERRS() << "LLVOAvatar::updateGeometry() called with NULL drawable" << LL_ENDL; + } - return TRUE; + return TRUE; } //----------------------------------------------------------------------------- @@ -7217,9 +7217,9 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) //----------------------------------------------------------------------------- void LLVOAvatar::updateSexDependentLayerSets() { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); - invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet); - invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet); } //----------------------------------------------------------------------------- @@ -7227,19 +7227,19 @@ void LLVOAvatar::updateSexDependentLayerSets() //----------------------------------------------------------------------------- void LLVOAvatar::dirtyMesh() { - dirtyMesh(1); + dirtyMesh(1); } void LLVOAvatar::dirtyMesh(S32 priority) { - mDirtyMesh = llmax(mDirtyMesh, priority); + mDirtyMesh = llmax(mDirtyMesh, priority); } //----------------------------------------------------------------------------- // getViewerJoint() //----------------------------------------------------------------------------- -LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx) +LLViewerJoint* LLVOAvatar::getViewerJoint(S32 idx) { - return dynamic_cast(mMeshLOD[idx]); + return dynamic_cast(mMeshLOD[idx]); } //----------------------------------------------------------------------------- @@ -7255,111 +7255,111 @@ void LLVOAvatar::hideHair() //----------------------------------------------------------------------------- void LLVOAvatar::hideSkirt() { - mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE); + mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE); } BOOL LLVOAvatar::setParent(LLViewerObject* parent) { - BOOL ret ; - if (parent == NULL) - { - getOffObject(); - ret = LLViewerObject::setParent(parent); - if (isSelf()) - { - gAgentCamera.resetCamera(); - } - } - else - { - ret = LLViewerObject::setParent(parent); - if(ret) - { - sitOnObject(parent); - } - } - return ret ; + BOOL ret ; + if (parent == NULL) + { + getOffObject(); + ret = LLViewerObject::setParent(parent); + if (isSelf()) + { + gAgentCamera.resetCamera(); + } + } + else + { + ret = LLViewerObject::setParent(parent); + if(ret) + { + sitOnObject(parent); + } + } + return ret ; } void LLVOAvatar::addChild(LLViewerObject *childp) { - childp->extractAttachmentItemID(); // find the inventory item this object is associated with. - if (isSelf()) - { - const LLUUID& item_id = childp->getAttachmentItemID(); - LLViewerInventoryItem *item = gInventory.getItem(item_id); - LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; - - } - - LLViewerObject::addChild(childp); - if (childp->mDrawable) - { - if (!attachObject(childp)) - { - LL_WARNS() << "ATT addChild() failed for " - << childp->getID() - << " item " << childp->getAttachmentItemID() - << LL_ENDL; - // MAINT-3312 backout - // mPendingAttachment.push_back(childp); - } - } - else - { - mPendingAttachment.push_back(childp); - } + childp->extractAttachmentItemID(); // find the inventory item this object is associated with. + if (isSelf()) + { + const LLUUID& item_id = childp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + + } + + LLViewerObject::addChild(childp); + if (childp->mDrawable) + { + if (!attachObject(childp)) + { + LL_WARNS() << "ATT addChild() failed for " + << childp->getID() + << " item " << childp->getAttachmentItemID() + << LL_ENDL; + // MAINT-3312 backout + // mPendingAttachment.push_back(childp); + } + } + else + { + mPendingAttachment.push_back(childp); + } } void LLVOAvatar::removeChild(LLViewerObject *childp) { - LLViewerObject::removeChild(childp); - if (!detachObject(childp)) - { - LL_WARNS() << "Calling detach on non-attached object " << LL_ENDL; - } + LLViewerObject::removeChild(childp); + if (!detachObject(childp)) + { + LL_WARNS() << "Calling detach on non-attached object " << LL_ENDL; + } } LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object) { - S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getAttachmentState()); - - // This should never happen unless the server didn't process the attachment point - // correctly, but putting this check in here to be safe. - if (attachmentID & ATTACHMENT_ADD) - { - LL_WARNS() << "Got an attachment with ATTACHMENT_ADD mask, removing ( attach pt:" << attachmentID << " )" << LL_ENDL; - attachmentID &= ~ATTACHMENT_ADD; - } - - LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); - - if (!attachment) - { - LL_WARNS() << "Object attachment point invalid: " << attachmentID - << " trying to use 1 (chest)" - << LL_ENDL; - - attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest) - if (attachment) - { - LL_WARNS() << "Object attachment point invalid: " << attachmentID - << " on object " << viewer_object->getID() - << " attachment item " << viewer_object->getAttachmentItemID() - << " falling back to 1 (chest)" - << LL_ENDL; - } - else - { - LL_WARNS() << "Object attachment point invalid: " << attachmentID - << " on object " << viewer_object->getID() - << " attachment item " << viewer_object->getAttachmentItemID() - << "Unable to use fallback attachment point 1 (chest)" - << LL_ENDL; - } - } - - return attachment; + S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getAttachmentState()); + + // This should never happen unless the server didn't process the attachment point + // correctly, but putting this check in here to be safe. + if (attachmentID & ATTACHMENT_ADD) + { + LL_WARNS() << "Got an attachment with ATTACHMENT_ADD mask, removing ( attach pt:" << attachmentID << " )" << LL_ENDL; + attachmentID &= ~ATTACHMENT_ADD; + } + + LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL); + + if (!attachment) + { + LL_WARNS() << "Object attachment point invalid: " << attachmentID + << " trying to use 1 (chest)" + << LL_ENDL; + + attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest) + if (attachment) + { + LL_WARNS() << "Object attachment point invalid: " << attachmentID + << " on object " << viewer_object->getID() + << " attachment item " << viewer_object->getAttachmentItemID() + << " falling back to 1 (chest)" + << LL_ENDL; + } + else + { + LL_WARNS() << "Object attachment point invalid: " << attachmentID + << " on object " << viewer_object->getID() + << " attachment item " << viewer_object->getAttachmentItemID() + << "Unable to use fallback attachment point 1 (chest)" + << LL_ENDL; + } + } + + return attachment; } //----------------------------------------------------------------------------- @@ -7367,54 +7367,54 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi //----------------------------------------------------------------------------- const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object) { - if (isSelf()) - { - const LLUUID& item_id = viewer_object->getAttachmentItemID(); - LLViewerInventoryItem *item = gInventory.getItem(item_id); - LL_DEBUGS("Avatar") << "ATT attaching object " - << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; - } - LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); - - if (!attachment || !attachment->addObject(viewer_object)) - { - const LLUUID& item_id = viewer_object->getAttachmentItemID(); - LLViewerInventoryItem *item = gInventory.getItem(item_id); - LL_WARNS("Avatar") << "ATT attach failed " - << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; - return 0; - } + if (isSelf()) + { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } + LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); + + if (!attachment || !attachment->addObject(viewer_object)) + { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_WARNS("Avatar") << "ATT attach failed " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + return 0; + } if (!viewer_object->isAnimatedObject()) { updateAttachmentOverrides(); } - updateVisualComplexity(); + updateVisualComplexity(); - if (viewer_object->isSelected()) - { - LLSelectMgr::getInstance()->updateSelectionCenter(); - LLSelectMgr::getInstance()->updatePointAt(); - } + if (viewer_object->isSelected()) + { + LLSelectMgr::getInstance()->updateSelectionCenter(); + LLSelectMgr::getInstance()->updatePointAt(); + } - viewer_object->refreshBakeTexture(); + viewer_object->refreshBakeTexture(); - LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* objectp = *iter; - if (objectp) - { - objectp->refreshBakeTexture(); - } - } + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* objectp = *iter; + if (objectp) + { + objectp->refreshBakeTexture(); + } + } - updateMeshVisibility(); + updateMeshVisibility(); - return attachment; + return attachment; } //----------------------------------------------------------------------------- @@ -7422,15 +7422,15 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o //----------------------------------------------------------------------------- U32 LLVOAvatar::getNumAttachments() const { - U32 num_attachments = 0; - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment *attachment_pt = (*iter).second; - num_attachments += attachment_pt->getNumObjects(); - } - return num_attachments; + U32 num_attachments = 0; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; + num_attachments += attachment_pt->getNumObjects(); + } + return num_attachments; } //----------------------------------------------------------------------------- @@ -7438,7 +7438,7 @@ U32 LLVOAvatar::getNumAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAttachments() const { - return LLAgentBenefitsMgr::current().getAttachmentLimit(); + return LLAgentBenefitsMgr::current().getAttachmentLimit(); } //----------------------------------------------------------------------------- @@ -7447,7 +7447,7 @@ S32 LLVOAvatar::getMaxAttachments() const //----------------------------------------------------------------------------- BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const { - return (getNumAttachments() + n) <= getMaxAttachments(); + return (getNumAttachments() + n) <= getMaxAttachments(); } //----------------------------------------------------------------------------- @@ -7455,15 +7455,15 @@ BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const //----------------------------------------------------------------------------- U32 LLVOAvatar::getNumAnimatedObjectAttachments() const { - U32 num_attachments = 0; - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment *attachment_pt = (*iter).second; - num_attachments += attachment_pt->getNumAnimatedObjects(); - } - return num_attachments; + U32 num_attachments = 0; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment *attachment_pt = (*iter).second; + num_attachments += attachment_pt->getNumAnimatedObjects(); + } + return num_attachments; } //----------------------------------------------------------------------------- @@ -7472,7 +7472,7 @@ U32 LLVOAvatar::getNumAnimatedObjectAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAnimatedObjectAttachments() const { - return LLAgentBenefitsMgr::current().getAnimatedObjectLimit(); + return LLAgentBenefitsMgr::current().getAnimatedObjectLimit(); } //----------------------------------------------------------------------------- @@ -7481,7 +7481,7 @@ S32 LLVOAvatar::getMaxAnimatedObjectAttachments() const //----------------------------------------------------------------------------- BOOL LLVOAvatar::canAttachMoreAnimatedObjects(U32 n) const { - return (getNumAnimatedObjectAttachments() + n) <= getMaxAnimatedObjectAttachments(); + return (getNumAnimatedObjectAttachments() + n) <= getMaxAnimatedObjectAttachments(); } //----------------------------------------------------------------------------- @@ -7489,101 +7489,101 @@ BOOL LLVOAvatar::canAttachMoreAnimatedObjects(U32 n) const //----------------------------------------------------------------------------- void LLVOAvatar::lazyAttach() { - std::vector > still_pending; - - for (U32 i = 0; i < mPendingAttachment.size(); i++) - { - LLPointer cur_attachment = mPendingAttachment[i]; - // Object might have died while we were waiting for drawable - if (!cur_attachment->isDead()) - { - if (cur_attachment->mDrawable) - { - if (isSelf()) - { - const LLUUID& item_id = cur_attachment->getAttachmentItemID(); - LLViewerInventoryItem *item = gInventory.getItem(item_id); - LL_DEBUGS("Avatar") << "ATT attaching object " - << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; - } - if (!attachObject(cur_attachment)) - { // Drop it - LL_WARNS() << "attachObject() failed for " - << cur_attachment->getID() - << " item " << cur_attachment->getAttachmentItemID() - << LL_ENDL; - // MAINT-3312 backout - //still_pending.push_back(cur_attachment); - } - } - else - { - still_pending.push_back(cur_attachment); - } - } - } - - mPendingAttachment = still_pending; + std::vector > still_pending; + + for (U32 i = 0; i < mPendingAttachment.size(); i++) + { + LLPointer cur_attachment = mPendingAttachment[i]; + // Object might have died while we were waiting for drawable + if (!cur_attachment->isDead()) + { + if (cur_attachment->mDrawable) + { + if (isSelf()) + { + const LLUUID& item_id = cur_attachment->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } + if (!attachObject(cur_attachment)) + { // Drop it + LL_WARNS() << "attachObject() failed for " + << cur_attachment->getID() + << " item " << cur_attachment->getAttachmentItemID() + << LL_ENDL; + // MAINT-3312 backout + //still_pending.push_back(cur_attachment); + } + } + else + { + still_pending.push_back(cur_attachment); + } + } + } + + mPendingAttachment = still_pending; } void LLVOAvatar::resetHUDAttachments() { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getIsHUDAttachment()) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object && attached_object->mDrawable.notNull()) - { - gPipeline.markMoved(attached_object->mDrawable); - } - } - } - } + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment()) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + const LLViewerObject* attached_object = attachment_iter->get(); + if (attached_object && attached_object->mDrawable.notNull()) + { + gPipeline.markMoved(attached_object->mDrawable); + } + } + } + } } void LLVOAvatar::rebuildRiggedAttachments( void ) { - for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) - { - LLViewerJointAttachment* pAttachment = iter->second; - LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIterEnd = pAttachment->mAttachedObjects.end(); - - for ( LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIter = pAttachment->mAttachedObjects.begin(); - attachmentIter != attachmentIterEnd; ++attachmentIter) - { - const LLViewerObject* pAttachedObject = *attachmentIter; - if ( pAttachment && pAttachedObject->mDrawable.notNull() ) - { - gPipeline.markRebuild(pAttachedObject->mDrawable); - } - } - } + for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) + { + LLViewerJointAttachment* pAttachment = iter->second; + LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIterEnd = pAttachment->mAttachedObjects.end(); + + for ( LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIter = pAttachment->mAttachedObjects.begin(); + attachmentIter != attachmentIterEnd; ++attachmentIter) + { + const LLViewerObject* pAttachedObject = *attachmentIter; + if ( pAttachment && pAttachedObject->mDrawable.notNull() ) + { + gPipeline.markRebuild(pAttachedObject->mDrawable); + } + } + } } //----------------------------------------------------------------------------- // cleanupAttachedMesh() //----------------------------------------------------------------------------- void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) { - LLUUID mesh_id; - if (getRiggedMeshID(pVO, mesh_id)) - { + LLUUID mesh_id; + if (getRiggedMeshID(pVO, mesh_id)) + { // FIXME this seems like an odd place for this code. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + if ( gAgentCamera.cameraCustomizeAvatar() ) + { + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); + } + } } bool LLVOAvatar::hasPendingAttachedMeshes() @@ -7670,51 +7670,51 @@ bool LLVOAvatar::hasPendingAttachedMeshes() //----------------------------------------------------------------------------- BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - if (attachment->isObjectAttached(viewer_object)) - { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + + if (attachment->isObjectAttached(viewer_object)) + { updateVisualComplexity(); bool is_animated_object = viewer_object->isAnimatedObject(); - cleanupAttachedMesh(viewer_object); + cleanupAttachedMesh(viewer_object); - attachment->removeObject(viewer_object); + attachment->removeObject(viewer_object); if (!is_animated_object) { updateAttachmentOverrides(); } - viewer_object->refreshBakeTexture(); - - LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); - iter1 != child_list.end(); ++iter1) - { - LLViewerObject* objectp = *iter1; - if (objectp) + viewer_object->refreshBakeTexture(); + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); + iter1 != child_list.end(); ++iter1) { - objectp->refreshBakeTexture(); - } + LLViewerObject* objectp = *iter1; + if (objectp) + { + objectp->refreshBakeTexture(); + } } - updateMeshVisibility(); + updateMeshVisibility(); + + LL_DEBUGS() << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << LL_ENDL; + return TRUE; + } + } - LL_DEBUGS() << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << LL_ENDL; - return TRUE; - } - } + std::vector >::iterator iter = std::find(mPendingAttachment.begin(), mPendingAttachment.end(), viewer_object); + if (iter != mPendingAttachment.end()) + { + mPendingAttachment.erase(iter); + return TRUE; + } - std::vector >::iterator iter = std::find(mPendingAttachment.begin(), mPendingAttachment.end(), viewer_object); - if (iter != mPendingAttachment.end()) - { - mPendingAttachment.erase(iter); - return TRUE; - } - - return FALSE; + return FALSE; } //----------------------------------------------------------------------------- @@ -7722,12 +7722,12 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) //----------------------------------------------------------------------------- void LLVOAvatar::sitDown(BOOL bSitting) { - mIsSitting = bSitting; - if (isSelf()) - { - // Update Movement Controls according to own Sitting mode - LLFloaterMove::setSittingMode(bSitting); - } + mIsSitting = bSitting; + if (isSelf()) + { + // Update Movement Controls according to own Sitting mode + LLFloaterMove::setSittingMode(bSitting); + } } //----------------------------------------------------------------------------- @@ -7735,22 +7735,22 @@ void LLVOAvatar::sitDown(BOOL bSitting) //----------------------------------------------------------------------------- void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) { - if (isSelf()) - { - // Might be first sit - //LLFirstUse::useSit(); - - gAgent.setFlying(FALSE); - gAgentCamera.setThirdPersonHeadOffset(LLVector3::zero); - //interpolate to new camera position - gAgentCamera.startCameraAnimation(); - // make sure we are not trying to autopilot - gAgent.stopAutoPilot(); - gAgentCamera.setupSitCamera(); - if (gAgentCamera.getForceMouselook()) - { - gAgentCamera.changeCameraToMouselook(); - } + if (isSelf()) + { + // Might be first sit + //LLFirstUse::useSit(); + + gAgent.setFlying(FALSE); + gAgentCamera.setThirdPersonHeadOffset(LLVector3::zero); + //interpolate to new camera position + gAgentCamera.startCameraAnimation(); + // make sure we are not trying to autopilot + gAgent.stopAutoPilot(); + gAgentCamera.setupSitCamera(); + if (gAgentCamera.getForceMouselook()) + { + gAgentCamera.changeCameraToMouselook(); + } if (gAgentCamera.getFocusOnAvatar() && LLToolMgr::getInstance()->inEdit()) { @@ -7764,33 +7764,33 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) } } } - } + } - if (mDrawable.isNull()) - { - return; - } - LLQuaternion inv_obj_rot = ~sit_object->getRenderRotation(); - LLVector3 obj_pos = sit_object->getRenderPosition(); + if (mDrawable.isNull()) + { + return; + } + LLQuaternion inv_obj_rot = ~sit_object->getRenderRotation(); + LLVector3 obj_pos = sit_object->getRenderPosition(); - LLVector3 rel_pos = getRenderPosition() - obj_pos; - rel_pos.rotVec(inv_obj_rot); + LLVector3 rel_pos = getRenderPosition() - obj_pos; + rel_pos.rotVec(inv_obj_rot); - mDrawable->mXform.setPosition(rel_pos); - mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot); + mDrawable->mXform.setPosition(rel_pos); + mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot); - gPipeline.markMoved(mDrawable, TRUE); - // Notice that removing sitDown() from here causes avatars sitting on - // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655. - sitDown(TRUE); - mRoot->getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject - // SL-315 - mRoot->setPosition(getPosition()); - mRoot->updateWorldMatrixChildren(); + gPipeline.markMoved(mDrawable, TRUE); + // Notice that removing sitDown() from here causes avatars sitting on + // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655. + sitDown(TRUE); + mRoot->getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject + // SL-315 + mRoot->setPosition(getPosition()); + mRoot->updateWorldMatrixChildren(); - stopMotion(ANIM_AGENT_BODY_NOISE); - - gAgentCamera.setInitSitRot(gAgent.getFrameAgent().getQuaternion()); + stopMotion(ANIM_AGENT_BODY_NOISE); + + gAgentCamera.setInitSitRot(gAgent.getFrameAgent().getQuaternion()); } //----------------------------------------------------------------------------- @@ -7798,168 +7798,168 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) //----------------------------------------------------------------------------- void LLVOAvatar::getOffObject() { - if (mDrawable.isNull()) - { - return; - } - - LLViewerObject* sit_object = (LLViewerObject*)getParent(); - - if (sit_object) - { - stopMotionFromSource(sit_object->getID()); - LLFollowCamMgr::getInstance()->setCameraActive(sit_object->getID(), FALSE); - - LLViewerObject::const_child_list_t& child_list = sit_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* child_objectp = *iter; - - stopMotionFromSource(child_objectp->getID()); - LLFollowCamMgr::getInstance()->setCameraActive(child_objectp->getID(), FALSE); - } - } - - // assumes that transform will not be updated with drawable still having a parent - // or that drawable had no parent from the start - LLVector3 cur_position_world = mDrawable->getWorldPosition(); - LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); - - if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN - && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN - || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) - { - // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent - // restore coordinates from cache - cur_position_world = mLastRootPos; - } - - // set *local* position based on last *world* position, since we're unparenting the avatar - mDrawable->mXform.setPosition(cur_position_world); - mDrawable->mXform.setRotation(cur_rotation_world); - - gPipeline.markMoved(mDrawable, TRUE); - - sitDown(FALSE); - - mRoot->getXform()->setParent(NULL); // LLVOAvatar::getOffObject - // SL-315 - mRoot->setPosition(cur_position_world); - mRoot->setRotation(cur_rotation_world); - mRoot->getXform()->update(); + if (mDrawable.isNull()) + { + return; + } + + LLViewerObject* sit_object = (LLViewerObject*)getParent(); + + if (sit_object) + { + stopMotionFromSource(sit_object->getID()); + LLFollowCamMgr::getInstance()->setCameraActive(sit_object->getID(), FALSE); + + LLViewerObject::const_child_list_t& child_list = sit_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* child_objectp = *iter; + + stopMotionFromSource(child_objectp->getID()); + LLFollowCamMgr::getInstance()->setCameraActive(child_objectp->getID(), FALSE); + } + } + + // assumes that transform will not be updated with drawable still having a parent + // or that drawable had no parent from the start + LLVector3 cur_position_world = mDrawable->getWorldPosition(); + LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); + + if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN + && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN + || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) + { + // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent + // restore coordinates from cache + cur_position_world = mLastRootPos; + } + + // set *local* position based on last *world* position, since we're unparenting the avatar + mDrawable->mXform.setPosition(cur_position_world); + mDrawable->mXform.setRotation(cur_rotation_world); + + gPipeline.markMoved(mDrawable, TRUE); + + sitDown(FALSE); + + mRoot->getXform()->setParent(NULL); // LLVOAvatar::getOffObject + // SL-315 + mRoot->setPosition(cur_position_world); + mRoot->setRotation(cur_rotation_world); + mRoot->getXform()->update(); if (mEnableDefaultMotions) { - startMotion(ANIM_AGENT_BODY_NOISE); + startMotion(ANIM_AGENT_BODY_NOISE); } - if (isSelf()) - { - LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); - LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; - av_rot = av_rot * obj_rot; - LLVector3 at_axis = LLVector3::x_axis; - at_axis = at_axis * av_rot; - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - gAgent.resetAxes(at_axis); - gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); - gAgentCamera.setSitCamera(LLUUID::null); - } + if (isSelf()) + { + LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion(); + LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT; + av_rot = av_rot * obj_rot; + LLVector3 at_axis = LLVector3::x_axis; + at_axis = at_axis * av_rot; + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis); + gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); + gAgentCamera.setSitCamera(LLUUID::null); + } } //----------------------------------------------------------------------------- // findAvatarFromAttachment() //----------------------------------------------------------------------------- -// static +// static LLVOAvatar* LLVOAvatar::findAvatarFromAttachment( LLViewerObject* obj ) { - if( obj->isAttachment() ) - { - do - { - obj = (LLViewerObject*) obj->getParent(); - } - while( obj && !obj->isAvatar() ); + if( obj->isAttachment() ) + { + do + { + obj = (LLViewerObject*) obj->getParent(); + } + while( obj && !obj->isAvatar() ); - if( obj && !obj->isDead() ) - { - return (LLVOAvatar*)obj; - } - } - return NULL; + if( obj && !obj->isDead() ) + { + return (LLVOAvatar*)obj; + } + } + return NULL; } S32 LLVOAvatar::getAttachmentCount() { - S32 count = mAttachmentPoints.size(); - return count; + S32 count = mAttachmentPoints.size(); + return count; } BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const { - if (mIsDummy) return TRUE; - - if (isSelf()) - { - return LLAvatarAppearance::isWearingWearableType(type); - } - - switch(type) - { - case LLWearableType::WT_SHAPE: - case LLWearableType::WT_SKIN: - case LLWearableType::WT_HAIR: - case LLWearableType::WT_EYES: - return TRUE; // everyone has all bodyparts - default: - break; // Do nothing - } - - for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); - tex_iter != LLAvatarAppearance::getDictionary()->getTextures().end(); - ++tex_iter) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; - if (texture_dict->mWearableType == type) - { - // Thus, you must check to see if the corresponding baked texture is defined. - // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing - // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that - // gets baked into a texture that always exists (upper or lower). - if (texture_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index)->mTextureIndex); - } - return FALSE; - } - } - return FALSE; -} - -LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const -{ - for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin(); - attachment_points_iter != gAgentAvatarp->mAttachmentPoints.end(); - ++attachment_points_iter) - { - LLViewerJointAttachment* attachment = attachment_points_iter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *attached_object = attachment_iter->get(); - if (attached_object && - attached_object->getID() == target_id) - { - return attached_object; - } - } - } - - return NULL; + if (mIsDummy) return TRUE; + + if (isSelf()) + { + return LLAvatarAppearance::isWearingWearableType(type); + } + + switch(type) + { + case LLWearableType::WT_SHAPE: + case LLWearableType::WT_SKIN: + case LLWearableType::WT_HAIR: + case LLWearableType::WT_EYES: + return TRUE; // everyone has all bodyparts + default: + break; // Do nothing + } + + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + tex_iter != LLAvatarAppearance::getDictionary()->getTextures().end(); + ++tex_iter) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; + if (texture_dict->mWearableType == type) + { + // Thus, you must check to see if the corresponding baked texture is defined. + // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing + // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that + // gets baked into a texture that always exists (upper or lower). + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + return isTextureDefined(LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index)->mTextureIndex); + } + return FALSE; + } + } + return FALSE; +} + +LLViewerObject * LLVOAvatar::findAttachmentByID( const LLUUID & target_id ) const +{ + for(attachment_map_t::const_iterator attachment_points_iter = mAttachmentPoints.begin(); + attachment_points_iter != gAgentAvatarp->mAttachmentPoints.end(); + ++attachment_points_iter) + { + LLViewerJointAttachment* attachment = attachment_points_iter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = attachment_iter->get(); + if (attached_object && + attached_object->getID() == target_id) + { + return attached_object; + } + } + } + + return NULL; } // virtual @@ -7974,40 +7974,40 @@ void LLVOAvatar::invalidateAll() // virtual void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color) { - if (global_color == mTexSkinColor) - { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); - invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet); - invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet); - } - else if (global_color == mTexHairColor) - { - invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); - invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet); - - // ! BACKWARDS COMPATIBILITY ! - // Fix for dealing with avatars from viewers that don't bake hair. - if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) - { - LLColor4 color = mTexHairColor->getColor(); - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setColor( color ); - } - } - } - } - else if (global_color == mTexEyeColor) - { - // LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; - invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet); - } - updateMeshTextures(); + if (global_color == mTexSkinColor) + { + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet); + } + else if (global_color == mTexHairColor) + { + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet); + invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet); + + // ! BACKWARDS COMPATIBILITY ! + // Fix for dealing with avatars from viewers that don't bake hair. + if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) + { + LLColor4 color = mTexHairColor->getColor(); + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor( color ); + } + } + } + } + else if (global_color == mTexEyeColor) + { + // LL_INFOS() << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << LL_ENDL; + invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet); + } + updateMeshTextures(); } // virtual @@ -8016,12 +8016,12 @@ bool LLVOAvatar::shouldRenderRigged() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (getOverallAppearance() == AOA_NORMAL) - { - return true; - } - // TBD - render for AOA_JELLYDOLL? - return false; + if (getOverallAppearance() == AOA_NORMAL) + { + return true; + } + // TBD - render for AOA_JELLYDOLL? + return false; } // FIXME: We have an mVisible member, set in updateVisibility(), but this @@ -8032,207 +8032,207 @@ bool LLVOAvatar::shouldRenderRigged() const // Maybe better naming could make this clearer? BOOL LLVOAvatar::isVisible() const { - return mDrawable.notNull() - && (!mOrphaned || isSelf()) - && (mDrawable->isVisible() || mIsDummy); + return mDrawable.notNull() + && (!mOrphaned || isSelf()) + && (mDrawable->isVisible() || mIsDummy); } // Determine if we have enough avatar data to render bool LLVOAvatar::getIsCloud() const { - if (mIsDummy) - { - return false; - } + if (mIsDummy) + { + return false; + } - return ( ((const_cast(this))->visualParamWeightsAreDefault())// Do we have a shape? - || ( !isTextureDefined(TEX_LOWER_BAKED) - || !isTextureDefined(TEX_UPPER_BAKED) - || !isTextureDefined(TEX_HEAD_BAKED) - ) - ); + return ( ((const_cast(this))->visualParamWeightsAreDefault())// Do we have a shape? + || ( !isTextureDefined(TEX_LOWER_BAKED) + || !isTextureDefined(TEX_UPPER_BAKED) + || !isTextureDefined(TEX_HEAD_BAKED) + ) + ); } void LLVOAvatar::updateRezzedStatusTimers(S32 rez_status) { - // State machine for rezzed status. Statuses are -1 on startup, 0 - // = cloud, 1 = gray, 2 = downloading, 3 = full. - // Purpose is to collect time data for each it takes avatar to reach - // various loading landmarks: gray, textured (partial), textured fully. - - if (rez_status != mLastRezzedStatus) - { - LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; - - if (mLastRezzedStatus == -1 && rez_status != -1) - { - // First time initialization, start all timers. - for (S32 i = 1; i < 4; i++) - { - startPhase("load_" + LLVOAvatar::rezStatusToString(i)); - startPhase("first_load_" + LLVOAvatar::rezStatusToString(i)); - } - } - if (rez_status < mLastRezzedStatus) - { - // load level has decreased. start phase timers for higher load levels. - for (S32 i = rez_status+1; i <= mLastRezzedStatus; i++) - { - startPhase("load_" + LLVOAvatar::rezStatusToString(i)); - } - } - else if (rez_status > mLastRezzedStatus) - { - // load level has increased. stop phase timers for lower and equal load levels. - for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++) - { - stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); - stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); - } - if (rez_status == 3) - { - // "fully loaded", mark any pending appearance change complete. - selfStopPhase("update_appearance_from_cof"); - selfStopPhase("wear_inventory_category", false); - selfStopPhase("process_initial_wearables_update", false); + // State machine for rezzed status. Statuses are -1 on startup, 0 + // = cloud, 1 = gray, 2 = downloading, 3 = full. + // Purpose is to collect time data for each it takes avatar to reach + // various loading landmarks: gray, textured (partial), textured fully. + + if (rez_status != mLastRezzedStatus) + { + LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; + + if (mLastRezzedStatus == -1 && rez_status != -1) + { + // First time initialization, start all timers. + for (S32 i = 1; i < 4; i++) + { + startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + startPhase("first_load_" + LLVOAvatar::rezStatusToString(i)); + } + } + if (rez_status < mLastRezzedStatus) + { + // load level has decreased. start phase timers for higher load levels. + for (S32 i = rez_status+1; i <= mLastRezzedStatus; i++) + { + startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + } + } + else if (rez_status > mLastRezzedStatus) + { + // load level has increased. stop phase timers for lower and equal load levels. + for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++) + { + stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); + stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); + } + if (rez_status == 3) + { + // "fully loaded", mark any pending appearance change complete. + selfStopPhase("update_appearance_from_cof"); + selfStopPhase("wear_inventory_category", false); + selfStopPhase("process_initial_wearables_update", false); updateVisualComplexity(); - } - } - mLastRezzedStatus = rez_status; - } + } + } + mLastRezzedStatus = rez_status; + } } void LLVOAvatar::clearPhases() { - getPhases().clearPhases(); + getPhases().clearPhases(); } void LLVOAvatar::startPhase(const std::string& phase_name) { - F32 elapsed = 0.0; - bool completed = false; - bool found = getPhases().getPhaseValues(phase_name, elapsed, completed); - //LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name - // << " found " << found << " elapsed " << elapsed << " completed " << completed << LL_ENDL; - if (found) - { - if (!completed) - { - LL_DEBUGS("Avatar") << avString() << "no-op, start when started already for " << phase_name << LL_ENDL; - return; - } - } - LL_DEBUGS("Avatar") << "started phase " << phase_name << LL_ENDL; - getPhases().startPhase(phase_name); + F32 elapsed = 0.0; + bool completed = false; + bool found = getPhases().getPhaseValues(phase_name, elapsed, completed); + //LL_DEBUGS("Avatar") << avString() << " phase state " << phase_name + // << " found " << found << " elapsed " << elapsed << " completed " << completed << LL_ENDL; + if (found) + { + if (!completed) + { + LL_DEBUGS("Avatar") << avString() << "no-op, start when started already for " << phase_name << LL_ENDL; + return; + } + } + LL_DEBUGS("Avatar") << "started phase " << phase_name << LL_ENDL; + getPhases().startPhase(phase_name); } void LLVOAvatar::stopPhase(const std::string& phase_name, bool err_check) { - F32 elapsed = 0.0; - bool completed = false; - if (getPhases().getPhaseValues(phase_name, elapsed, completed)) - { - if (!completed) - { - getPhases().stopPhase(phase_name); - completed = true; - logMetricsTimerRecord(phase_name, elapsed, completed); - LL_DEBUGS("Avatar") << avString() << "stopped phase " << phase_name << " elapsed " << elapsed << LL_ENDL; - } - else - { - if (err_check) - { - LL_DEBUGS("Avatar") << "no-op, stop when stopped already for " << phase_name << LL_ENDL; - } - } - } - else - { - if (err_check) - { - LL_DEBUGS("Avatar") << "no-op, stop when not started for " << phase_name << LL_ENDL; - } - } + F32 elapsed = 0.0; + bool completed = false; + if (getPhases().getPhaseValues(phase_name, elapsed, completed)) + { + if (!completed) + { + getPhases().stopPhase(phase_name); + completed = true; + logMetricsTimerRecord(phase_name, elapsed, completed); + LL_DEBUGS("Avatar") << avString() << "stopped phase " << phase_name << " elapsed " << elapsed << LL_ENDL; + } + else + { + if (err_check) + { + LL_DEBUGS("Avatar") << "no-op, stop when stopped already for " << phase_name << LL_ENDL; + } + } + } + else + { + if (err_check) + { + LL_DEBUGS("Avatar") << "no-op, stop when not started for " << phase_name << LL_ENDL; + } + } } void LLVOAvatar::logPendingPhases() { - if (!isAgentAvatarValid()) - { - return; - } - - for (LLViewerStats::phase_map_t::iterator it = getPhases().begin(); - it != getPhases().end(); - ++it) - { - const std::string& phase_name = it->first; - F32 elapsed; - bool completed; - if (getPhases().getPhaseValues(phase_name, elapsed, completed)) - { - if (!completed) - { - logMetricsTimerRecord(phase_name, elapsed, completed); - } - } - } + if (!isAgentAvatarValid()) + { + return; + } + + for (LLViewerStats::phase_map_t::iterator it = getPhases().begin(); + it != getPhases().end(); + ++it) + { + const std::string& phase_name = it->first; + F32 elapsed; + bool completed; + if (getPhases().getPhaseValues(phase_name, elapsed, completed)) + { + if (!completed) + { + logMetricsTimerRecord(phase_name, elapsed, completed); + } + } + } } //static void LLVOAvatar::logPendingPhasesAllAvatars() { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - if( inst->isDead() ) - { - continue; - } - inst->logPendingPhases(); - } + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if( inst->isDead() ) + { + continue; + } + inst->logPendingPhases(); + } } void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed) { - if (!isAgentAvatarValid()) - { - return; - } - - LLSD record; - record["timer_name"] = phase_name; - record["avatar_id"] = getID(); - record["elapsed"] = elapsed; - record["completed"] = completed; - U32 grid_x(0), grid_y(0); - if (getRegion() && LLWorld::instance().isRegionListed(getRegion())) - { - record["central_bake_version"] = LLSD::Integer(getRegion()->getCentralBakeVersion()); - grid_from_region_handle(getRegion()->getHandle(), &grid_x, &grid_y); - } - record["grid_x"] = LLSD::Integer(grid_x); - record["grid_y"] = LLSD::Integer(grid_y); - record["is_using_server_bakes"] = true; - record["is_self"] = isSelf(); - - if (isAgentAvatarValid()) - { - gAgentAvatarp->addMetricsTimerRecord(record); - } + if (!isAgentAvatarValid()) + { + return; + } + + LLSD record; + record["timer_name"] = phase_name; + record["avatar_id"] = getID(); + record["elapsed"] = elapsed; + record["completed"] = completed; + U32 grid_x(0), grid_y(0); + if (getRegion() && LLWorld::instance().isRegionListed(getRegion())) + { + record["central_bake_version"] = LLSD::Integer(getRegion()->getCentralBakeVersion()); + grid_from_region_handle(getRegion()->getHandle(), &grid_x, &grid_y); + } + record["grid_x"] = LLSD::Integer(grid_x); + record["grid_y"] = LLSD::Integer(grid_y); + record["is_using_server_bakes"] = true; + record["is_self"] = isSelf(); + + if (isAgentAvatarValid()) + { + gAgentAvatarp->addMetricsTimerRecord(record); + } } // call periodically to keep isFullyLoaded up to date. // returns true if the value has changed. BOOL LLVOAvatar::updateIsFullyLoaded() { - S32 rez_status = getRezzedStatus(); - bool loading = getIsCloud(); - if (mFirstFullyVisible && !mIsControlAvatar) - { + S32 rez_status = getRezzedStatus(); + bool loading = getIsCloud(); + if (mFirstFullyVisible && !mIsControlAvatar) + { loading = ((rez_status < 2) // Wait at least 60s for unfinished textures to finish on first load, // don't wait forever, it might fail. Even if it will eventually load by @@ -8243,56 +8243,56 @@ BOOL LLVOAvatar::updateIsFullyLoaded() || (rez_status < 3 && !isFullyBaked()) || hasPendingAttachedMeshes() ); - } - updateRezzedStatusTimers(rez_status); - updateRuthTimer(loading); - return processFullyLoadedChange(loading); + } + updateRezzedStatusTimers(rez_status); + updateRuthTimer(loading); + return processFullyLoadedChange(loading); } void LLVOAvatar::updateRuthTimer(bool loading) { - if (isSelf() || !loading) - { - return; - } - - if (mPreviousFullyLoaded) - { - mRuthTimer.reset(); - debugAvatarRezTime("AvatarRezCloudNotification","became cloud"); - } - - const F32 LOADING_TIMEOUT__SECONDS = 120.f; - if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT__SECONDS) - { - LL_DEBUGS("Avatar") << avString() - << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " - << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) " - << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) " - << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) " - << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )." - << LL_ENDL; - - LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); - mRuthTimer.reset(); - } + if (isSelf() || !loading) + { + return; + } + + if (mPreviousFullyLoaded) + { + mRuthTimer.reset(); + debugAvatarRezTime("AvatarRezCloudNotification","became cloud"); + } + + const F32 LOADING_TIMEOUT__SECONDS = 120.f; + if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT__SECONDS) + { + LL_DEBUGS("Avatar") << avString() + << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' " + << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) " + << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) " + << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) " + << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )." + << LL_ENDL; + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); + mRuthTimer.reset(); + } } BOOL LLVOAvatar::processFullyLoadedChange(bool loading) { - // We wait a little bit before giving the 'all clear', to let things to - // settle down (models to snap into place, textures to get first packets). + // We wait a little bit before giving the 'all clear', to let things to + // settle down (models to snap into place, textures to get first packets). // And if viewer isn't aware of some parts yet, this gives them a chance // to arrive. - const F32 LOADED_DELAY = 1.f; + const F32 LOADED_DELAY = 1.f; if (loading) { mFullyLoadedTimer.reset(); } - if (mFirstFullyVisible) - { + if (mFirstFullyVisible) + { if (!isSelf() && loading) { // Note that textures can causes 60s delay on thier own @@ -8309,31 +8309,31 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) mFirstUseDelaySeconds *= 1.25; } } - mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > mFirstUseDelaySeconds); - } - else - { - mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > LOADED_DELAY); - } - - if (!mPreviousFullyLoaded && !loading && mFullyLoaded) - { - debugAvatarRezTime("AvatarRezNotification","fully loaded"); - } - - // did our loading state "change" from last call? - // FIXME runway - why are we updating every 30 calls even if nothing has changed? - // This causes updateLOD() to run every 30 frames, among other things. - const S32 UPDATE_RATE = 30; - BOOL changed = - ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call - (!mFullyLoadedInitialized) || // if we've never been called before - (mFullyLoadedFrameCounter % UPDATE_RATE == 0)); // every now and then issue a change - BOOL fully_loaded_changed = (mFullyLoaded != mPreviousFullyLoaded); - - mPreviousFullyLoaded = mFullyLoaded; - mFullyLoadedInitialized = TRUE; - mFullyLoadedFrameCounter++; + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > mFirstUseDelaySeconds); + } + else + { + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > LOADED_DELAY); + } + + if (!mPreviousFullyLoaded && !loading && mFullyLoaded) + { + debugAvatarRezTime("AvatarRezNotification","fully loaded"); + } + + // did our loading state "change" from last call? + // FIXME runway - why are we updating every 30 calls even if nothing has changed? + // This causes updateLOD() to run every 30 frames, among other things. + const S32 UPDATE_RATE = 30; + BOOL changed = + ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call + (!mFullyLoadedInitialized) || // if we've never been called before + (mFullyLoadedFrameCounter % UPDATE_RATE == 0)); // every now and then issue a change + BOOL fully_loaded_changed = (mFullyLoaded != mPreviousFullyLoaded); + + mPreviousFullyLoaded = mFullyLoaded; + mFullyLoadedInitialized = TRUE; + mFullyLoadedFrameCounter++; if (changed && isSelf()) { @@ -8341,45 +8341,45 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) LLAvatarRenderNotifier::getInstance()->updateNotificationState(); } - if (fully_loaded_changed && !isSelf() && mFullyLoaded && isImpostor()) - { - // Fix for jellydoll initially invisible - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 6; - } - return changed; + if (fully_loaded_changed && !isSelf() && mFullyLoaded && isImpostor()) + { + // Fix for jellydoll initially invisible + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 6; + } + return changed; } BOOL LLVOAvatar::isFullyLoaded() const { - return (mRenderUnloadedAvatar || mFullyLoaded); + return (mRenderUnloadedAvatar || mFullyLoaded); } bool LLVOAvatar::isTooComplex() const { - bool too_complex; + bool too_complex; static LLCachedControl always_render_friends(gSavedSettings, "AlwaysRenderFriends"); - bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends); - - if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) - { - too_complex = false; - } - else - { - // Determine if visually muted or not - static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); - static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); - // If the user has chosen unlimited max complexity, we also disregard max attachment area + bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends); + + if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) + { + too_complex = false; + } + else + { + // Determine if visually muted or not + static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0U); + static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); + // If the user has chosen unlimited max complexity, we also disregard max attachment area // so that unlimited will completely disable the overly complex impostor rendering // yes, this leaves them vulnerable to griefing objects... their choice too_complex = ( max_render_cost > 0 && (mVisualComplexity > max_render_cost || (max_attachment_area > 0.0f && mAttachmentSurfaceArea > max_attachment_area) )); - } + } - return too_complex; + return too_complex; } bool LLVOAvatar::isTooSlow() const @@ -8387,477 +8387,477 @@ bool LLVOAvatar::isTooSlow() const static LLCachedControl always_render_friends(gSavedSettings, "AlwaysRenderFriends"); bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends); - if (render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) + if (render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER) + { + return false; + } + return mTooSlow; +} + +// Udpate Avatar state based on render time +void LLVOAvatar::updateTooSlow() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; + static LLCachedControl alwaysRenderFriends(gSavedSettings, "AlwaysRenderFriends"); + static LLCachedControl allowSelfImpostor(gSavedSettings, "AllowSelfImpostor"); + const auto id = getID(); + + // mTooSlow - Is the avatar flagged as being slow (includes shadow time) + // mTooSlowWithoutShadows - Is the avatar flagged as being slow even with shadows removed. + + // get max render time in ms + F32 max_art_ms = (F32) (LLPerfStats::renderAvatarMaxART_ns / 1000000.0); + + bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf(); + + bool ignore_tune = false; + if (autotune && sAVsIgnoringARTLimit.size() > 0) + { + auto it = std::find(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID); + if (it != sAVsIgnoringARTLimit.end()) + { + S32 index = it - sAVsIgnoringARTLimit.begin(); + ignore_tune = (index < (MIN_NONTUNED_AVS - sAvatarsNearby + 1 + LLPerfStats::tunedAvatars)); + } + } + + bool exceeds_max_ART = + ((LLPerfStats::renderAvatarMaxART_ns > 0) && + (mGPURenderTime >= max_art_ms)); // NOTE: don't use getGPURenderTime accessor here to avoid "isTooSlow" feedback loop + + if (exceeds_max_ART && !ignore_tune) + { + mTooSlow = true; + + if(!mTooSlowWithoutShadows) // if we were not previously above the full impostor cap + { + bool render_friend_or_exception = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( id ) ) || + ( getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER ); + if( (!isSelf() || allowSelfImpostor) && !render_friend_or_exception ) + { + // Note: slow rendering Friends still get their shadows zapped. + mTooSlowWithoutShadows = getGPURenderTime()*2.f >= max_art_ms; // NOTE: assumes shadow rendering doubles render time + } + } + } + else + { + mTooSlow = false; + mTooSlowWithoutShadows = false; + + if (ignore_tune) + { + return; + } + } + if(mTooSlow && !mTuned) + { + LLPerfStats::tunedAvatars++; // increment the number of avatars that have been tweaked. + mTuned = true; + } + else if(!mTooSlow && mTuned) + { + LLPerfStats::tunedAvatars--; + mTuned = false; + } +} + +//----------------------------------------------------------------------------- +// findMotion() +//----------------------------------------------------------------------------- +LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const +{ + return mMotionController.findMotion(id); +} + +// This is a semi-deprecated debugging tool - meshes will not show as +// colorized if using deferred rendering. +void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) +{ + if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) + { + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor(color); + } + } + } +} + + +//----------------------------------------------------------------------------- +// updateMeshVisibility() +// Hide the mesh joints if attachments are using baked textures +//----------------------------------------------------------------------------- +void LLVOAvatar::updateMeshVisibility() +{ + bool bake_flag[BAKED_NUM_INDICES]; + memset(bake_flag, 0, BAKED_NUM_INDICES*sizeof(bool)); + + if (getOverallAppearance() == AOA_NORMAL) + { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *objectp = attachment_iter->get(); + if (objectp) + { + for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = objectp->getTE(face_index); + bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); + bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); + bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); + bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); + bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); + bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); + bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); + bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); + bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); + bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); + bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); + } + } + + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); + iter1 != child_list.end(); ++iter1) + { + LLViewerObject* objectchild = *iter1; + if (objectchild) + { + for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = objectchild->getTE(face_index); + bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); + bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); + bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); + bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); + bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); + bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); + bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); + bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); + bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); + bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); + bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); + } + } + } + } + } + } + } + + //LL_INFOS() << "head " << bake_flag[BAKED_HEAD] << "eyes " << bake_flag[BAKED_EYES] << "hair " << bake_flag[BAKED_HAIR] << "lower " << bake_flag[BAKED_LOWER] << "upper " << bake_flag[BAKED_UPPER] << "skirt " << bake_flag[BAKED_SKIRT] << LL_ENDL; + + for (S32 i = 0; i < mMeshLOD.size(); i++) + { + LLAvatarJoint* joint = mMeshLOD[i]; + if (i == MESH_ID_HAIR) + { + joint->setVisible(!bake_flag[BAKED_HAIR], TRUE); + } + else if (i == MESH_ID_HEAD) + { + joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); + } + else if (i == MESH_ID_SKIRT) + { + joint->setVisible(!bake_flag[BAKED_SKIRT], TRUE); + } + else if (i == MESH_ID_UPPER_BODY) + { + joint->setVisible(!bake_flag[BAKED_UPPER], TRUE); + } + else if (i == MESH_ID_LOWER_BODY) + { + joint->setVisible(!bake_flag[BAKED_LOWER], TRUE); + } + else if (i == MESH_ID_EYEBALL_LEFT) + { + joint->setVisible(!bake_flag[BAKED_EYES], TRUE); + } + else if (i == MESH_ID_EYEBALL_RIGHT) + { + joint->setVisible(!bake_flag[BAKED_EYES], TRUE); + } + else if (i == MESH_ID_EYELASH) + { + joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); + } + } +} + +//----------------------------------------------------------------------------- +// updateMeshTextures() +// Uses the current TE values to set the meshes' and layersets' textures. +//----------------------------------------------------------------------------- +// virtual +void LLVOAvatar::updateMeshTextures() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR + static S32 update_counter = 0; + mBakedTextureDebugText.clear(); + + // if user has never specified a texture, assign the default + for (U32 i=0; i < getNumTEs(); i++) + { + const LLViewerTexture* te_image = getImage(i, 0); + if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) + { + // IMG_DEFAULT_AVATAR = a special texture that's never rendered. + const LLUUID& image_id = (i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR); + setImage(i, LLViewerTextureManager::getFetchedTexture(image_id), 0); + } + } + + const BOOL other_culled = !isSelf() && mCulled; + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; + BOOL paused = FALSE; + if(!isSelf()) + { + src_callback_list = &mCallbackTextureList ; + paused = !isVisible(); + } + + std::vector is_layer_baked; + is_layer_baked.resize(mBakedTextureDatas.size(), false); + + std::vector use_lkg_baked_layer; // lkg = "last known good" + use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false); + + mBakedTextureDebugText += llformat("%06d\n",update_counter++); + mBakedTextureDebugText += "indx layerset linvld ltda ilb ulkg ltid\n"; + for (U32 i=0; i < mBakedTextureDatas.size(); i++) + { + is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); + LLViewerTexLayerSet* layerset = NULL; + bool layerset_invalid = false; + if (!other_culled) + { + // When an avatar is changing clothes and not in Appearance mode, + // use the last-known good baked texture until it finishes the first + // render of the new layerset. + layerset = getTexLayerSet(i); + layerset_invalid = layerset && ( !layerset->getViewerComposite()->isInitialized() + || !layerset->isLocalTextureDataAvailable() ); + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && (mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR) + && layerset_invalid); + if (use_lkg_baked_layer[i]) + { + layerset->setUpdatesEnabled(TRUE); + } + } + else + { + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR); + } + + std::string last_id_string; + if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT_AVATAR) + last_id_string = "A"; + else if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT) + last_id_string = "D"; + else if (mBakedTextureDatas[i].mLastTextureID == IMG_INVISIBLE) + last_id_string = "I"; + else + last_id_string = "*"; + bool is_ltda = layerset + && layerset->getViewerComposite()->isInitialized() + && layerset->isLocalTextureDataAvailable(); + mBakedTextureDebugText += llformat("%4d %4s %4d %4d %4d %4d %4s\n", + i, + (layerset?"*":"0"), + layerset_invalid, + is_ltda, + is_layer_baked[i], + use_lkg_baked_layer[i], + last_id_string.c_str()); + } + + for (U32 i=0; i < mBakedTextureDatas.size(); i++) { - return false; - } - return mTooSlow; -} + debugColorizeSubMeshes(i, LLColor4::white); -// Udpate Avatar state based on render time -void LLVOAvatar::updateTooSlow() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - static LLCachedControl alwaysRenderFriends(gSavedSettings, "AlwaysRenderFriends"); - static LLCachedControl allowSelfImpostor(gSavedSettings, "AllowSelfImpostor"); - const auto id = getID(); + LLViewerTexLayerSet* layerset = getTexLayerSet(i); + if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) + { + // use last known good layer (no new one) + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); + mBakedTextureDatas[i].mIsUsed = TRUE; - // mTooSlow - Is the avatar flagged as being slow (includes shadow time) - // mTooSlowWithoutShadows - Is the avatar flagged as being slow even with shadows removed. - - // get max render time in ms - F32 max_art_ms = (F32) (LLPerfStats::renderAvatarMaxART_ns / 1000000.0); + debugColorizeSubMeshes(i,LLColor4::red); + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setTexture( baked_img ); + } + } + } + else if (!isUsingLocalAppearance() && is_layer_baked[i]) + { + // use new layer + LLViewerFetchedTexture* baked_img = + LLViewerTextureManager::staticCastToFetchedTexture( + getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; + if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureID ) + { + // Even though the file may not be finished loading, + // we'll consider it loaded and use it (rather than + // doing compositing). + useBakedTexture( baked_img->getID() ); + mLoadedCallbacksPaused |= !isVisible(); + checkTextureLoading(); + } + else + { + mBakedTextureDatas[i].mIsLoaded = FALSE; + if ( (baked_img->getID() != IMG_INVISIBLE) && + ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) + { + baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), + src_callback_list, paused); + } + baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), + src_callback_list, paused ); + if (baked_img->getDiscardLevel() < 0 && !paused) + { + // mLoadedCallbackTextures will be updated by checkTextureLoading() below + mLastTexCallbackAddedTime.reset(); + } - bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf(); + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; + checkTextureLoading(); + } + } + else if (layerset && isUsingLocalAppearance()) + { + debugColorizeSubMeshes(i,LLColor4::yellow ); - bool ignore_tune = false; - if (autotune && sAVsIgnoringARTLimit.size() > 0) - { - auto it = std::find(sAVsIgnoringARTLimit.begin(), sAVsIgnoringARTLimit.end(), mID); - if (it != sAVsIgnoringARTLimit.end()) + layerset->createComposite(); + layerset->setUpdatesEnabled( TRUE ); + mBakedTextureDatas[i].mIsUsed = FALSE; + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setLayerSet( layerset ); + } + } + } + else { - S32 index = it - sAVsIgnoringARTLimit.begin(); - ignore_tune = (index < (MIN_NONTUNED_AVS - sAvatarsNearby + 1 + LLPerfStats::tunedAvatars)); + debugColorizeSubMeshes(i,LLColor4::blue); } } - bool exceeds_max_ART = - ((LLPerfStats::renderAvatarMaxART_ns > 0) && - (mGPURenderTime >= max_art_ms)); // NOTE: don't use getGPURenderTime accessor here to avoid "isTooSlow" feedback loop - - if (exceeds_max_ART && !ignore_tune) + // set texture and color of hair manually if we are not using a baked image. + // This can happen while loading hair for yourself, or for clients that did not + // bake a hair texture. Still needed for yourself after 1.22 is depricated. + if (!is_layer_baked[BAKED_HAIR]) { - mTooSlow = true; - - if(!mTooSlowWithoutShadows) // if we were not previously above the full impostor cap + const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); + LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); + for (; iter != end; ++iter) { - bool render_friend_or_exception = ( alwaysRenderFriends && LLAvatarTracker::instance().isBuddy( id ) ) || - ( getVisualMuteSettings() == LLVOAvatar::AV_ALWAYS_RENDER ); - if( (!isSelf() || allowSelfImpostor) && !render_friend_or_exception ) + LLAvatarJointMesh* mesh = (*iter); + if (mesh) { - // Note: slow rendering Friends still get their shadows zapped. - mTooSlowWithoutShadows = getGPURenderTime()*2.f >= max_art_ms; // NOTE: assumes shadow rendering doubles render time + mesh->setColor( color ); + mesh->setTexture( hair_img ); } } } - else - { - mTooSlow = false; - mTooSlowWithoutShadows = false; - if (ignore_tune) - { - return; - } - } - if(mTooSlow && !mTuned) + + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); + ++baked_iter) { - LLPerfStats::tunedAvatars++; // increment the number of avatars that have been tweaked. - mTuned = true; + const EBakedTextureIndex baked_index = baked_iter->first; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex texture_index = *local_tex_iter; + const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled; + if (isSelf()) + { + setBakedReady(texture_index, is_baked_ready); + } + } } - else if(!mTooSlow && mTuned) + + // removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack + static bool call_remove_missing = true; + if (call_remove_missing) { - LLPerfStats::tunedAvatars--; - mTuned = false; + call_remove_missing = false; + removeMissingBakedTextures(); // May call back into this function if anything is removed + call_remove_missing = true; } -} -//----------------------------------------------------------------------------- -// findMotion() -//----------------------------------------------------------------------------- -LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const -{ - return mMotionController.findMotion(id); -} + //refresh bakes on any attached objects + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; -// This is a semi-deprecated debugging tool - meshes will not show as -// colorized if using deferred rendering. -void LLVOAvatar::debugColorizeSubMeshes(U32 i, const LLColor4& color) -{ - if (gSavedSettings.getBOOL("DebugAvatarCompositeBaked")) - { - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setColor(color); - } - } - } -} + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = attachment_iter->get(); + if (attached_object && !attached_object->isDead()) + { + attached_object->refreshBakeTexture(); + 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* objectp = *iter; + if (objectp && !objectp->isDead()) + { + objectp->refreshBakeTexture(); + } + } + } + } + } -//----------------------------------------------------------------------------- -// updateMeshVisibility() -// Hide the mesh joints if attachments are using baked textures -//----------------------------------------------------------------------------- -void LLVOAvatar::updateMeshVisibility() -{ - bool bake_flag[BAKED_NUM_INDICES]; - memset(bake_flag, 0, BAKED_NUM_INDICES*sizeof(bool)); - - if (getOverallAppearance() == AOA_NORMAL) - { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *objectp = attachment_iter->get(); - if (objectp) - { - for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++) - { - LLTextureEntry* tex_entry = objectp->getTE(face_index); - bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); - bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); - bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); - bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); - bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); - bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); - bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); - bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); - bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); - bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); - bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); - } - } - - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); - iter1 != child_list.end(); ++iter1) - { - LLViewerObject* objectchild = *iter1; - if (objectchild) - { - for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++) - { - LLTextureEntry* tex_entry = objectchild->getTE(face_index); - bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); - bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); - bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); - bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); - bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); - bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); - bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); - bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); - bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); - bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); - bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); - } - } - } - } - } - } - } - - //LL_INFOS() << "head " << bake_flag[BAKED_HEAD] << "eyes " << bake_flag[BAKED_EYES] << "hair " << bake_flag[BAKED_HAIR] << "lower " << bake_flag[BAKED_LOWER] << "upper " << bake_flag[BAKED_UPPER] << "skirt " << bake_flag[BAKED_SKIRT] << LL_ENDL; - - for (S32 i = 0; i < mMeshLOD.size(); i++) - { - LLAvatarJoint* joint = mMeshLOD[i]; - if (i == MESH_ID_HAIR) - { - joint->setVisible(!bake_flag[BAKED_HAIR], TRUE); - } - else if (i == MESH_ID_HEAD) - { - joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); - } - else if (i == MESH_ID_SKIRT) - { - joint->setVisible(!bake_flag[BAKED_SKIRT], TRUE); - } - else if (i == MESH_ID_UPPER_BODY) - { - joint->setVisible(!bake_flag[BAKED_UPPER], TRUE); - } - else if (i == MESH_ID_LOWER_BODY) - { - joint->setVisible(!bake_flag[BAKED_LOWER], TRUE); - } - else if (i == MESH_ID_EYEBALL_LEFT) - { - joint->setVisible(!bake_flag[BAKED_EYES], TRUE); - } - else if (i == MESH_ID_EYEBALL_RIGHT) - { - joint->setVisible(!bake_flag[BAKED_EYES], TRUE); - } - else if (i == MESH_ID_EYELASH) - { - joint->setVisible(!bake_flag[BAKED_HEAD], TRUE); - } - } -} -//----------------------------------------------------------------------------- -// updateMeshTextures() -// Uses the current TE values to set the meshes' and layersets' textures. -//----------------------------------------------------------------------------- -// virtual -void LLVOAvatar::updateMeshTextures() -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR - static S32 update_counter = 0; - mBakedTextureDebugText.clear(); - - // if user has never specified a texture, assign the default - for (U32 i=0; i < getNumTEs(); i++) - { - const LLViewerTexture* te_image = getImage(i, 0); - if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) - { - // IMG_DEFAULT_AVATAR = a special texture that's never rendered. - const LLUUID& image_id = (i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR); - setImage(i, LLViewerTextureManager::getFetchedTexture(image_id), 0); - } - } - - const BOOL other_culled = !isSelf() && mCulled; - LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; - BOOL paused = FALSE; - if(!isSelf()) - { - src_callback_list = &mCallbackTextureList ; - paused = !isVisible(); - } - - std::vector is_layer_baked; - is_layer_baked.resize(mBakedTextureDatas.size(), false); - - std::vector use_lkg_baked_layer; // lkg = "last known good" - use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false); - - mBakedTextureDebugText += llformat("%06d\n",update_counter++); - mBakedTextureDebugText += "indx layerset linvld ltda ilb ulkg ltid\n"; - for (U32 i=0; i < mBakedTextureDatas.size(); i++) - { - is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); - LLViewerTexLayerSet* layerset = NULL; - bool layerset_invalid = false; - if (!other_culled) - { - // When an avatar is changing clothes and not in Appearance mode, - // use the last-known good baked texture until it finishes the first - // render of the new layerset. - layerset = getTexLayerSet(i); - layerset_invalid = layerset && ( !layerset->getViewerComposite()->isInitialized() - || !layerset->isLocalTextureDataAvailable() ); - use_lkg_baked_layer[i] = (!is_layer_baked[i] - && (mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR) - && layerset_invalid); - if (use_lkg_baked_layer[i]) - { - layerset->setUpdatesEnabled(TRUE); - } - } - else - { - use_lkg_baked_layer[i] = (!is_layer_baked[i] - && mBakedTextureDatas[i].mLastTextureID != IMG_DEFAULT_AVATAR); - } - - std::string last_id_string; - if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT_AVATAR) - last_id_string = "A"; - else if (mBakedTextureDatas[i].mLastTextureID == IMG_DEFAULT) - last_id_string = "D"; - else if (mBakedTextureDatas[i].mLastTextureID == IMG_INVISIBLE) - last_id_string = "I"; - else - last_id_string = "*"; - bool is_ltda = layerset - && layerset->getViewerComposite()->isInitialized() - && layerset->isLocalTextureDataAvailable(); - mBakedTextureDebugText += llformat("%4d %4s %4d %4d %4d %4d %4s\n", - i, - (layerset?"*":"0"), - layerset_invalid, - is_ltda, - is_layer_baked[i], - use_lkg_baked_layer[i], - last_id_string.c_str()); - } - - for (U32 i=0; i < mBakedTextureDatas.size(); i++) - { - debugColorizeSubMeshes(i, LLColor4::white); - - LLViewerTexLayerSet* layerset = getTexLayerSet(i); - if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) - { - // use last known good layer (no new one) - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); - mBakedTextureDatas[i].mIsUsed = TRUE; - - debugColorizeSubMeshes(i,LLColor4::red); - - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setTexture( baked_img ); - } - } - } - else if (!isUsingLocalAppearance() && is_layer_baked[i]) - { - // use new layer - LLViewerFetchedTexture* baked_img = - LLViewerTextureManager::staticCastToFetchedTexture( - getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; - if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureID ) - { - // Even though the file may not be finished loading, - // we'll consider it loaded and use it (rather than - // doing compositing). - useBakedTexture( baked_img->getID() ); - mLoadedCallbacksPaused |= !isVisible(); - checkTextureLoading(); - } - else - { - mBakedTextureDatas[i].mIsLoaded = FALSE; - if ( (baked_img->getID() != IMG_INVISIBLE) && - ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) - { - baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), - src_callback_list, paused); - } - baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), - src_callback_list, paused ); - if (baked_img->getDiscardLevel() < 0 && !paused) - { - // mLoadedCallbackTextures will be updated by checkTextureLoading() below - mLastTexCallbackAddedTime.reset(); - } - - // this could add paused texture callbacks - mLoadedCallbacksPaused |= paused; - checkTextureLoading(); - } - } - else if (layerset && isUsingLocalAppearance()) - { - debugColorizeSubMeshes(i,LLColor4::yellow ); - - layerset->createComposite(); - layerset->setUpdatesEnabled( TRUE ); - mBakedTextureDatas[i].mIsUsed = FALSE; - - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setLayerSet( layerset ); - } - } - } - else - { - debugColorizeSubMeshes(i,LLColor4::blue); - } - } - - // set texture and color of hair manually if we are not using a baked image. - // This can happen while loading hair for yourself, or for clients that did not - // bake a hair texture. Still needed for yourself after 1.22 is depricated. - if (!is_layer_baked[BAKED_HAIR]) - { - const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); - LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 ); - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[BAKED_HAIR].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setColor( color ); - mesh->setTexture( hair_img ); - } - } - } - - - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = - LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); - ++baked_iter) - { - const EBakedTextureIndex baked_index = baked_iter->first; - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex texture_index = *local_tex_iter; - const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled; - if (isSelf()) - { - setBakedReady(texture_index, is_baked_ready); - } - } - } - - // removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack - static bool call_remove_missing = true; - if (call_remove_missing) - { - call_remove_missing = false; - removeMissingBakedTextures(); // May call back into this function if anything is removed - call_remove_missing = true; - } - - //refresh bakes on any attached objects - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object && !attached_object->isDead()) - { - attached_object->refreshBakeTexture(); - - 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* objectp = *iter; - if (objectp && !objectp->isDead()) - { - objectp->refreshBakeTexture(); - } - } - } - } - } - - } @@ -8867,92 +8867,92 @@ void LLVOAvatar::updateMeshTextures() //----------------------------------------------------------------------------- void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, BOOL baked_version_ready, U32 index ) { - // invalid for anyone but self - llassert(0); + // invalid for anyone but self + llassert(0); } -//virtual +//virtual void LLVOAvatar::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { - // invalid for anyone but self - llassert(0); + // invalid for anyone but self + llassert(0); } void LLVOAvatar::addChat(const LLChat& chat) { - std::deque::iterator chat_iter; + std::deque::iterator chat_iter; - mChats.push_back(chat); + mChats.push_back(chat); - S32 chat_length = 0; - for( chat_iter = mChats.begin(); chat_iter != mChats.end(); ++chat_iter) - { - chat_length += chat_iter->mText.size(); - } + S32 chat_length = 0; + for( chat_iter = mChats.begin(); chat_iter != mChats.end(); ++chat_iter) + { + chat_length += chat_iter->mText.size(); + } - // remove any excess chat - chat_iter = mChats.begin(); - while ((chat_length > MAX_BUBBLE_CHAT_LENGTH || mChats.size() > MAX_BUBBLE_CHAT_UTTERANCES) && chat_iter != mChats.end()) - { - chat_length -= chat_iter->mText.size(); - mChats.pop_front(); - chat_iter = mChats.begin(); - } + // remove any excess chat + chat_iter = mChats.begin(); + while ((chat_length > MAX_BUBBLE_CHAT_LENGTH || mChats.size() > MAX_BUBBLE_CHAT_UTTERANCES) && chat_iter != mChats.end()) + { + chat_length -= chat_iter->mText.size(); + mChats.pop_front(); + chat_iter = mChats.begin(); + } - mChatTimer.reset(); + mChatTimer.reset(); } void LLVOAvatar::clearChat() { - mChats.clear(); + mChats.clear(); } void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index) { - if (index >= BAKED_NUM_INDICES) - { - LL_WARNS() << "invalid baked texture index passed to applyMorphMask" << LL_ENDL; - return; - } + if (index >= BAKED_NUM_INDICES) + { + LL_WARNS() << "invalid baked texture index passed to applyMorphMask" << LL_ENDL; + return; + } - for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); - iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) - { - const LLMaskedMorph* maskedMorph = (*iter); - LLPolyMorphTarget* morph_target = dynamic_cast(maskedMorph->mMorphTarget); - if (morph_target) - { - morph_target->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); - } - } + for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin(); + iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter) + { + const LLMaskedMorph* maskedMorph = (*iter); + LLPolyMorphTarget* morph_target = dynamic_cast(maskedMorph->mMorphTarget); + if (morph_target) + { + morph_target->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); + } + } } // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIndex index) { - if (index >= BAKED_NUM_INDICES) - { - return FALSE; - } + if (index >= BAKED_NUM_INDICES) + { + return FALSE; + } - if (!mBakedTextureDatas[index].mMaskedMorphs.empty()) - { - if (isSelf()) - { - LLViewerTexLayerSet *layer_set = getTexLayerSet(index); - if (layer_set) - { - return !layer_set->isMorphValid(); - } - } - else - { - return FALSE; - } - } + if (!mBakedTextureDatas[index].mMaskedMorphs.empty()) + { + if (isSelf()) + { + LLViewerTexLayerSet *layer_set = getTexLayerSet(index); + if (layer_set) + { + return !layer_set->isMorphValid(); + } + } + else + { + return FALSE; + } + } - return FALSE; + return FALSE; } //----------------------------------------------------------------------------- @@ -8964,66 +8964,66 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLAvatarAppearanceDefines::EBakedTextureIn //----------------------------------------------------------------------------- void LLVOAvatar::releaseComponentTextures() { - // ! BACKWARDS COMPATIBILITY ! - // Detect if the baked hair texture actually wasn't sent, and if so set to default - if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID()) - { - if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE) - { - // Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default - setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR); - } - } - - for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) - { - const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); - // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID - if (!isTextureDefined(bakedDicEntry->mTextureIndex) - && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) - { - continue; - } - - for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++) - { - const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture]; - setTETexture(te, IMG_DEFAULT_AVATAR); - } - } + // ! BACKWARDS COMPATIBILITY ! + // Detect if the baked hair texture actually wasn't sent, and if so set to default + if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID()) + { + if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE) + { + // Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default + setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR); + } + } + + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) + { + const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); + // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID + if (!isTextureDefined(bakedDicEntry->mTextureIndex) + && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) + { + continue; + } + + for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++) + { + const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture]; + setTETexture(te, IMG_DEFAULT_AVATAR); + } + } } void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const -{ - LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); - iter != LLAvatarAppearance::getDictionary()->getTextures().end(); - ++iter) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - // TODO: MULTI-WEARABLE: handle multiple textures for self - const LLViewerTexture* te_image = getImage(iter->first,0); - if( !te_image ) - { - LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null ptr" << LL_ENDL; - } - else if( te_image->getID().isNull() ) - { - LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null UUID" << LL_ENDL; - } - else if( te_image->getID() == IMG_DEFAULT ) - { - LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT" << LL_ENDL; - } - else if( te_image->getID() == IMG_DEFAULT_AVATAR ) - { - LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << LL_ENDL; - } - else - { - LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": " << te_image->getID() << LL_ENDL; - } - } +{ + LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); + ++iter) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + // TODO: MULTI-WEARABLE: handle multiple textures for self + const LLViewerTexture* te_image = getImage(iter->first,0); + if( !te_image ) + { + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null ptr" << LL_ENDL; + } + else if( te_image->getID().isNull() ) + { + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": null UUID" << LL_ENDL; + } + else if( te_image->getID() == IMG_DEFAULT ) + { + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT" << LL_ENDL; + } + else if( te_image->getID() == IMG_DEFAULT_AVATAR ) + { + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << avString() << " " << texture_dict->mName << ": " << te_image->getID() << LL_ENDL; + } + } } //----------------------------------------------------------------------------- @@ -9031,74 +9031,74 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const //----------------------------------------------------------------------------- void LLVOAvatar::clampAttachmentPositions() { - if (isDead()) - { - return; - } - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment) - { - attachment->clampObjectPosition(); - } - } + if (isDead()) + { + return; + } + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment) + { + attachment->clampObjectPosition(); + } + } } BOOL LLVOAvatar::hasHUDAttachment() const { - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0) - { - return TRUE; - } - } - return FALSE; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0) + { + return TRUE; + } + } + return FALSE; } LLBBox LLVOAvatar::getHUDBBox() const { - LLBBox bbox; - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getIsHUDAttachment()) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - const LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object == NULL) - { - LL_WARNS() << "HUD attached object is NULL!" << LL_ENDL; - continue; - } - // initialize bounding box to contain identity orientation and center point for attached object - bbox.addPointLocal(attached_object->getPosition()); - // add rotated bounding box for attached object - bbox.addBBoxAgent(attached_object->getBoundingBoxAgent()); - 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) - { - const LLViewerObject* child_objectp = *iter; - bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent()); - } - } - } - } - - return bbox; + LLBBox bbox; + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment()) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + const LLViewerObject* attached_object = attachment_iter->get(); + if (attached_object == NULL) + { + LL_WARNS() << "HUD attached object is NULL!" << LL_ENDL; + continue; + } + // initialize bounding box to contain identity orientation and center point for attached object + bbox.addPointLocal(attached_object->getPosition()); + // add rotated bounding box for attached object + bbox.addBBoxAgent(attached_object->getBoundingBoxAgent()); + 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) + { + const LLViewerObject* child_objectp = *iter; + bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent()); + } + } + } + } + + return bbox; } //----------------------------------------------------------------------------- @@ -9106,53 +9106,53 @@ LLBBox LLVOAvatar::getHUDBBox() const //----------------------------------------------------------------------------- void LLVOAvatar::onFirstTEMessageReceived() { - LL_DEBUGS("Avatar") << avString() << LL_ENDL; - if( !mFirstTEMessageReceived ) - { - mFirstTEMessageReceived = TRUE; - - LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; - BOOL paused = FALSE ; - if(!isSelf()) - { - src_callback_list = &mCallbackTextureList ; - paused = !isVisible(); - } - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - const BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); - - // Use any baked textures that we have even if they haven't downloaded yet. - // (That is, don't do a transition from unbaked to baked.) - if (layer_baked) - { - LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; - mBakedTextureDatas[i].mLastTextureID = image->getID(); - // If we have more than one texture for the other baked layers, we'll want to call this for them too. - if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) - { - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), - src_callback_list, paused); - } - LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), - src_callback_list, paused ); - if (image->getDiscardLevel() < 0 && !paused) - { - mLastTexCallbackAddedTime.reset(); - } + LL_DEBUGS("Avatar") << avString() << LL_ENDL; + if( !mFirstTEMessageReceived ) + { + mFirstTEMessageReceived = TRUE; + + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ; + BOOL paused = FALSE ; + if(!isSelf()) + { + src_callback_list = &mCallbackTextureList ; + paused = !isVisible(); + } + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); + + // Use any baked textures that we have even if they haven't downloaded yet. + // (That is, don't do a transition from unbaked to baked.) + if (layer_baked) + { + LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; + mBakedTextureDatas[i].mLastTextureID = image->getID(); + // If we have more than one texture for the other baked layers, we'll want to call this for them too. + if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) + { + image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), + src_callback_list, paused); + } + LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; + image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), + src_callback_list, paused ); + if (image->getDiscardLevel() < 0 && !paused) + { + mLastTexCallbackAddedTime.reset(); + } // this could add paused texture callbacks - mLoadedCallbacksPaused |= paused; - } - } + mLoadedCallbacksPaused |= paused; + } + } mMeshTexturesDirty = TRUE; - gPipeline.markGLRebuild(this); + gPipeline.markGLRebuild(this); mFirstAppearanceMessageTimer.reset(); mFullyLoadedTimer.reset(); - } + } } //----------------------------------------------------------------------------- @@ -9160,240 +9160,240 @@ void LLVOAvatar::onFirstTEMessageReceived() //----------------------------------------------------------------------------- bool LLVOAvatar::visualParamWeightsAreDefault() { - bool rtn = true; - - bool is_wearing_skirt = isWearingWearableType(LLWearableType::WT_SKIRT); - for (LLVisualParam *param = getFirstVisualParam(); - param; - param = getNextVisualParam()) - { - if (param->isTweakable()) - { - LLViewerVisualParam* vparam = dynamic_cast(param); - llassert(vparam); - bool is_skirt_param = vparam && - LLWearableType::WT_SKIRT == vparam->getWearableType(); - if (param->getWeight() != param->getDefaultWeight() && - // we have to not care whether skirt weights are default, if we're not actually wearing a skirt - (is_wearing_skirt || !is_skirt_param)) - { - //LL_INFOS() << "param '" << param->getName() << "'=" << param->getWeight() << " which differs from default=" << param->getDefaultWeight() << LL_ENDL; - rtn = false; - break; - } - } - } - - //LL_INFOS() << "params are default ? " << int(rtn) << LL_ENDL; - - return rtn; + bool rtn = true; + + bool is_wearing_skirt = isWearingWearableType(LLWearableType::WT_SKIRT); + for (LLVisualParam *param = getFirstVisualParam(); + param; + param = getNextVisualParam()) + { + if (param->isTweakable()) + { + LLViewerVisualParam* vparam = dynamic_cast(param); + llassert(vparam); + bool is_skirt_param = vparam && + LLWearableType::WT_SKIRT == vparam->getWearableType(); + if (param->getWeight() != param->getDefaultWeight() && + // we have to not care whether skirt weights are default, if we're not actually wearing a skirt + (is_wearing_skirt || !is_skirt_param)) + { + //LL_INFOS() << "param '" << param->getName() << "'=" << param->getWeight() << " which differs from default=" << param->getDefaultWeight() << LL_ENDL; + rtn = false; + break; + } + } + } + + //LL_INFOS() << "params are default ? " << int(rtn) << LL_ENDL; + + return rtn; } void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value) { - std::string type_string = "unknown"; - if (dynamic_cast(viewer_param)) - type_string = "param_alpha"; - if (dynamic_cast(viewer_param)) - type_string = "param_color"; - if (dynamic_cast(viewer_param)) - type_string = "param_driver"; - if (dynamic_cast(viewer_param)) - type_string = "param_morph"; - if (dynamic_cast(viewer_param)) - type_string = "param_skeleton"; - S32 wtype = -1; - LLViewerVisualParam *vparam = dynamic_cast(viewer_param); - if (vparam) - { - wtype = vparam->getWearableType(); - } - S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); - apr_file_printf(file, "\t\t\n", - viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getDisplayName().c_str(), value, u8_value, type_string.c_str(), - LLWearableType::getInstance()->getTypeName(LLWearableType::EType(wtype)).c_str(), - viewer_param->getGroup()); - } - + std::string type_string = "unknown"; + if (dynamic_cast(viewer_param)) + type_string = "param_alpha"; + if (dynamic_cast(viewer_param)) + type_string = "param_color"; + if (dynamic_cast(viewer_param)) + type_string = "param_driver"; + if (dynamic_cast(viewer_param)) + type_string = "param_morph"; + if (dynamic_cast(viewer_param)) + type_string = "param_skeleton"; + S32 wtype = -1; + LLViewerVisualParam *vparam = dynamic_cast(viewer_param); + if (vparam) + { + wtype = vparam->getWearableType(); + } + S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); + apr_file_printf(file, "\t\t\n", + viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getDisplayName().c_str(), value, u8_value, type_string.c_str(), + LLWearableType::getInstance()->getTypeName(LLWearableType::EType(wtype)).c_str(), + viewer_param->getGroup()); + } + void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, - const LLAppearanceMessageContents& contents) -{ - std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml"); - const std::vector& params_for_dump = contents.mParamWeights; - const LLTEContents& tec = contents.mTEContents; - - LLAPRFile outfile; - std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); - outfile.open(fullpath, LL_APR_WB ); - apr_file_t* file = outfile.getFileHandle(); - if (!file) - { - return; - } - else - { - LL_DEBUGS("Avatar") << "dumping appearance message to " << fullpath << LL_ENDL; - } - - apr_file_printf(file, "
\n"); - apr_file_printf(file, "\t\t\n", contents.mCOFVersion); - apr_file_printf(file, "\t\t\n", contents.mAppearanceVersion); - apr_file_printf(file, "
\n"); - - apr_file_printf(file, "\n\n"); - LLVisualParam* param = getFirstVisualParam(); - for (S32 i = 0; i < params_for_dump.size(); i++) - { - while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && - (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT - { - param = getNextVisualParam(); - } - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - F32 value = params_for_dump[i]; - dump_visual_param(file, viewer_param, value); - param = getNextVisualParam(); - } - apr_file_printf(file, "\n"); - - apr_file_printf(file, "\n\n"); - for (U32 i = 0; i < tec.face_count; i++) - { - std::string uuid_str; - ((LLUUID*)tec.image_data)[i].toString(uuid_str); - apr_file_printf( file, "\t\t\n", i, uuid_str.c_str()); - } - apr_file_printf(file, "\n"); + const LLAppearanceMessageContents& contents) +{ + std::string outfilename = get_sequential_numbered_file_name(dump_prefix,".xml"); + const std::vector& params_for_dump = contents.mParamWeights; + const LLTEContents& tec = contents.mTEContents; + + LLAPRFile outfile; + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + outfile.open(fullpath, LL_APR_WB ); + apr_file_t* file = outfile.getFileHandle(); + if (!file) + { + return; + } + else + { + LL_DEBUGS("Avatar") << "dumping appearance message to " << fullpath << LL_ENDL; + } + + apr_file_printf(file, "
\n"); + apr_file_printf(file, "\t\t\n", contents.mCOFVersion); + apr_file_printf(file, "\t\t\n", contents.mAppearanceVersion); + apr_file_printf(file, "
\n"); + + apr_file_printf(file, "\n\n"); + LLVisualParam* param = getFirstVisualParam(); + for (S32 i = 0; i < params_for_dump.size(); i++) + { + while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && + (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + { + param = getNextVisualParam(); + } + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + F32 value = params_for_dump[i]; + dump_visual_param(file, viewer_param, value); + param = getNextVisualParam(); + } + apr_file_printf(file, "\n"); + + apr_file_printf(file, "\n\n"); + for (U32 i = 0; i < tec.face_count; i++) + { + std::string uuid_str; + ((LLUUID*)tec.image_data)[i].toString(uuid_str); + apr_file_printf( file, "\t\t\n", i, uuid_str.c_str()); + } + apr_file_printf(file, "\n"); } void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMessageContents& contents) { - parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, contents.mTEContents); - - // Parse the AppearanceData field, if any. - if (mesgsys->has(_PREHASH_AppearanceData)) - { - U8 av_u8; - mesgsys->getU8Fast(_PREHASH_AppearanceData, _PREHASH_AppearanceVersion, av_u8, 0); - contents.mAppearanceVersion = av_u8; - //LL_DEBUGS("Avatar") << "appversion set by AppearanceData field: " << contents.mAppearanceVersion << LL_ENDL; - mesgsys->getS32Fast(_PREHASH_AppearanceData, _PREHASH_CofVersion, contents.mCOFVersion, 0); - // For future use: - //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); - } - - // Parse the AppearanceData field, if any. - contents.mHoverOffsetWasSet = false; - if (mesgsys->has(_PREHASH_AppearanceHover)) - { - LLVector3 hover; - mesgsys->getVector3Fast(_PREHASH_AppearanceHover, _PREHASH_HoverHeight, hover); - //LL_DEBUGS("Avatar") << avString() << " hover received " << hover.mV[ VX ] << "," << hover.mV[ VY ] << "," << hover.mV[ VZ ] << LL_ENDL; - contents.mHoverOffset = hover; - contents.mHoverOffsetWasSet = true; - } - - // Parse visual params, if any. - S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); + parseTEMessage(mesgsys, _PREHASH_ObjectData, -1, contents.mTEContents); + + // Parse the AppearanceData field, if any. + if (mesgsys->has(_PREHASH_AppearanceData)) + { + U8 av_u8; + mesgsys->getU8Fast(_PREHASH_AppearanceData, _PREHASH_AppearanceVersion, av_u8, 0); + contents.mAppearanceVersion = av_u8; + //LL_DEBUGS("Avatar") << "appversion set by AppearanceData field: " << contents.mAppearanceVersion << LL_ENDL; + mesgsys->getS32Fast(_PREHASH_AppearanceData, _PREHASH_CofVersion, contents.mCOFVersion, 0); + // For future use: + //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); + } + + // Parse the AppearanceData field, if any. + contents.mHoverOffsetWasSet = false; + if (mesgsys->has(_PREHASH_AppearanceHover)) + { + LLVector3 hover; + mesgsys->getVector3Fast(_PREHASH_AppearanceHover, _PREHASH_HoverHeight, hover); + //LL_DEBUGS("Avatar") << avString() << " hover received " << hover.mV[ VX ] << "," << hover.mV[ VY ] << "," << hover.mV[ VZ ] << LL_ENDL; + contents.mHoverOffset = hover; + contents.mHoverOffsetWasSet = true; + } + + // Parse visual params, if any. + S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); static LLCachedControl block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams"); - bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing - if( num_blocks > 1 && !drop_visual_params_debug) - { - //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; - - LLVisualParam* param = getFirstVisualParam(); - llassert(param); // if this ever fires, we should do the same as when num_blocks<=1 - if (!param) - { - LL_WARNS() << "No visual params!" << LL_ENDL; - } - else - { - for( S32 i = 0; i < num_blocks; i++ ) - { - while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && - (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT - { - param = getNextVisualParam(); - } - - if( !param ) - { - // more visual params supplied than expected - just process what we know about - break; - } - - U8 value; - mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); - F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); - contents.mParamWeights.push_back(newWeight); - contents.mParams.push_back(param); - - param = getNextVisualParam(); - } - } - - const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) + - getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT - if (num_blocks != expected_tweakable_count) - { - LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL; - } - } - else - { - if (drop_visual_params_debug) - { - LL_INFOS() << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << LL_ENDL; - } - else - { - LL_DEBUGS("Avatar") << "AvatarAppearance msg received without any parameters, object: " << getID() << LL_ENDL; - } - } - - LLVisualParam* appearance_version_param = getVisualParam(11000); - if (appearance_version_param) - { - std::vector::iterator it = std::find(contents.mParams.begin(), contents.mParams.end(),appearance_version_param); - if (it != contents.mParams.end()) - { - S32 index = it - contents.mParams.begin(); - contents.mParamAppearanceVersion = ll_round(contents.mParamWeights[index]); - //LL_DEBUGS("Avatar") << "appversion req by appearance_version param: " << contents.mParamAppearanceVersion << LL_ENDL; - } - } + bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing + if( num_blocks > 1 && !drop_visual_params_debug) + { + //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL; + + LLVisualParam* param = getFirstVisualParam(); + llassert(param); // if this ever fires, we should do the same as when num_blocks<=1 + if (!param) + { + LL_WARNS() << "No visual params!" << LL_ENDL; + } + else + { + for( S32 i = 0; i < num_blocks; i++ ) + { + while( param && ((param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && + (param->getGroup() != VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE)) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + { + param = getNextVisualParam(); + } + + if( !param ) + { + // more visual params supplied than expected - just process what we know about + break; + } + + U8 value; + mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i); + F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + contents.mParamWeights.push_back(newWeight); + contents.mParams.push_back(param); + + param = getNextVisualParam(); + } + } + + const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) + + getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + if (num_blocks != expected_tweakable_count) + { + LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL; + } + } + else + { + if (drop_visual_params_debug) + { + LL_INFOS() << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << "AvatarAppearance msg received without any parameters, object: " << getID() << LL_ENDL; + } + } + + LLVisualParam* appearance_version_param = getVisualParam(11000); + if (appearance_version_param) + { + std::vector::iterator it = std::find(contents.mParams.begin(), contents.mParams.end(),appearance_version_param); + if (it != contents.mParams.end()) + { + S32 index = it - contents.mParams.begin(); + contents.mParamAppearanceVersion = ll_round(contents.mParamWeights[index]); + //LL_DEBUGS("Avatar") << "appversion req by appearance_version param: " << contents.mParamAppearanceVersion << LL_ENDL; + } + } } bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32& appearance_version) { - appearance_version = -1; - - if ((contents.mAppearanceVersion) >= 0 && - (contents.mParamAppearanceVersion >= 0) && - (contents.mAppearanceVersion != contents.mParamAppearanceVersion)) - { - LL_WARNS() << "inconsistent appearance_version settings - field: " << - contents.mAppearanceVersion << ", param: " << contents.mParamAppearanceVersion << LL_ENDL; - return false; - } - if (contents.mParamAppearanceVersion >= 0) // use visual param if available. - { - appearance_version = contents.mParamAppearanceVersion; - } - else if (contents.mAppearanceVersion > 0) - { - appearance_version = contents.mAppearanceVersion; - } - else // still not set, go with 1. - { - appearance_version = 1; - } - //LL_DEBUGS("Avatar") << "appearance version info - field " << contents.mAppearanceVersion - // << " param: " << contents.mParamAppearanceVersion - // << " final: " << appearance_version << LL_ENDL; - return true; + appearance_version = -1; + + if ((contents.mAppearanceVersion) >= 0 && + (contents.mParamAppearanceVersion >= 0) && + (contents.mAppearanceVersion != contents.mParamAppearanceVersion)) + { + LL_WARNS() << "inconsistent appearance_version settings - field: " << + contents.mAppearanceVersion << ", param: " << contents.mParamAppearanceVersion << LL_ENDL; + return false; + } + if (contents.mParamAppearanceVersion >= 0) // use visual param if available. + { + appearance_version = contents.mParamAppearanceVersion; + } + else if (contents.mAppearanceVersion > 0) + { + appearance_version = contents.mAppearanceVersion; + } + else // still not set, go with 1. + { + appearance_version = 1; + } + //LL_DEBUGS("Avatar") << "appearance version info - field " << contents.mAppearanceVersion + // << " param: " << contents.mParamAppearanceVersion + // << " final: " << appearance_version << LL_ENDL; + return true; } //----------------------------------------------------------------------------- @@ -9401,46 +9401,46 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32 //----------------------------------------------------------------------------- void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { - LL_DEBUGS("Avatar") << "starts" << LL_ENDL; + LL_DEBUGS("Avatar") << "starts" << LL_ENDL; static LLCachedControl enable_verbose_dumps(gSavedSettings, "DebugAvatarAppearanceMessage"); static LLCachedControl block_avatar_appearance_messages(gSavedSettings, "BlockAvatarAppearanceMessages"); - std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_"; - if (block_avatar_appearance_messages) - { - LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL; - return; - } - - mLastAppearanceMessageTimer.reset(); - - LLPointer contents(new LLAppearanceMessageContents); - parseAppearanceMessage(mesgsys, *contents); - if (enable_verbose_dumps) - { - dumpAppearanceMsgParams(dump_prefix + "appearance_msg", *contents); - } - - S32 appearance_version; - if (!resolve_appearance_version(*contents, appearance_version)) - { - LL_WARNS() << "bad appearance version info, discarding" << LL_ENDL; - return; - } - llassert(appearance_version > 0); - if (appearance_version > 1) - { - LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL; - return; - } + std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_"; + if (block_avatar_appearance_messages) + { + LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL; + return; + } + + mLastAppearanceMessageTimer.reset(); + + LLPointer contents(new LLAppearanceMessageContents); + parseAppearanceMessage(mesgsys, *contents); + if (enable_verbose_dumps) + { + dumpAppearanceMsgParams(dump_prefix + "appearance_msg", *contents); + } + + S32 appearance_version; + if (!resolve_appearance_version(*contents, appearance_version)) + { + LL_WARNS() << "bad appearance version info, discarding" << LL_ENDL; + return; + } + llassert(appearance_version > 0); + if (appearance_version > 1) + { + LL_WARNS() << "unsupported appearance version " << appearance_version << ", discarding appearance message" << LL_ENDL; + return; + } S32 thisAppearanceVersion(contents->mCOFVersion); if (isSelf()) - { // In the past this was considered to be the canonical COF version, - // that is no longer the case. The canonical version is maintained + { // In the past this was considered to be the canonical COF version, + // that is no longer the case. The canonical version is maintained // by the AIS code and should match the COF version there. Even so, - // we must prevent rolling this one backwards backwards or processing + // we must prevent rolling this one backwards backwards or processing // stale versions. S32 aisCOFVersion(LLAppearanceMgr::instance().getCOFVersion()); @@ -9464,23 +9464,23 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } - // SUNSHINE CLEANUP - is this case OK now? - S32 num_params = contents->mParamWeights.size(); - if (num_params <= 1) - { - // In this case, we have no reliable basis for knowing - // appearance version, which may cause us to look for baked - // textures in the wrong place and flag them as missing - // assets. - LL_DEBUGS("Avatar") << "ignoring appearance message due to lack of params" << LL_ENDL; - return; - } + // SUNSHINE CLEANUP - is this case OK now? + S32 num_params = contents->mParamWeights.size(); + if (num_params <= 1) + { + // In this case, we have no reliable basis for knowing + // appearance version, which may cause us to look for baked + // textures in the wrong place and flag them as missing + // assets. + LL_DEBUGS("Avatar") << "ignoring appearance message due to lack of params" << LL_ENDL; + return; + } - // No backsies zone - if we get here, the message should be valid and usable, will be processed. - // Note: - // RequestAgentUpdateAppearanceResponder::onRequestRequested() - // assumes that cof version is only updated with server-bake - // appearance messages. + // No backsies zone - if we get here, the message should be valid and usable, will be processed. + // Note: + // RequestAgentUpdateAppearanceResponder::onRequestRequested() + // assumes that cof version is only updated with server-bake + // appearance messages. if (isSelf()) { LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; @@ -9492,202 +9492,202 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // Note: // locally the COF is maintained via LLInventoryModel::accountForUpdate - // which is called from various places. This should match the simhost's + // which is called from various places. This should match the simhost's // idea of what the COF version is. AIS however maintains its own version - // of the COF that should be considered canonical. + // of the COF that should be considered canonical. mLastUpdateReceivedCOFVersion = thisAppearanceVersion; mLastProcessedAppearance = contents; bool slam_params = false; - applyParsedAppearanceMessage(*contents, slam_params); - if (getOverallAppearance() != AOA_NORMAL) - { - resetSkeleton(false); - } + applyParsedAppearanceMessage(*contents, slam_params); + if (getOverallAppearance() != AOA_NORMAL) + { + resetSkeleton(false); + } } void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params) { - S32 num_params = contents.mParamWeights.size(); - ESex old_sex = getSex(); + S32 num_params = contents.mParamWeights.size(); + ESex old_sex = getSex(); if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE)) { updateVisualComplexity(); } - // prevent the overwriting of valid baked textures with invalid baked textures - for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) - { - if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) - && mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT - && baked_index != BAKED_SKIRT && baked_index != BAKED_LEFT_ARM && baked_index != BAKED_LEFT_LEG && baked_index != BAKED_AUX1 && baked_index != BAKED_AUX2 && baked_index != BAKED_AUX3) - { - LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL; - setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); - } - else - { - LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using texture id " - << getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << LL_ENDL; - } - } - - // runway - was - // if (!is_first_appearance_message ) - // which means it would be called on second appearance message - probably wrong. - BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; - mFirstAppearanceMessageReceived = TRUE; - - //LL_DEBUGS("Avatar") << avString() << "processAvatarAppearance start " << mID + // prevent the overwriting of valid baked textures with invalid baked textures + for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) + { + if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) + && mBakedTextureDatas[baked_index].mLastTextureID != IMG_DEFAULT + && baked_index != BAKED_SKIRT && baked_index != BAKED_LEFT_ARM && baked_index != BAKED_LEFT_LEG && baked_index != BAKED_AUX1 && baked_index != BAKED_AUX2 && baked_index != BAKED_AUX3) + { + LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL; + setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + } + else + { + LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using texture id " + << getTE(mBakedTextureDatas[baked_index].mTextureIndex)->getID() << LL_ENDL; + } + } + + // runway - was + // if (!is_first_appearance_message ) + // which means it would be called on second appearance message - probably wrong. + BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived; + mFirstAppearanceMessageReceived = TRUE; + + //LL_DEBUGS("Avatar") << avString() << "processAvatarAppearance start " << mID // << " first? " << is_first_appearance_message << " self? " << isSelf() << LL_ENDL; - if (is_first_appearance_message ) - { - onFirstTEMessageReceived(); - } - - setCompositeUpdatesEnabled( FALSE ); - gPipeline.markGLRebuild(this); - - // Apply visual params - if( num_params > 1) - { - //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_params " << num_params << LL_ENDL; - BOOL params_changed = FALSE; - BOOL interp_params = FALSE; - S32 params_changed_count = 0; - - for( S32 i = 0; i < num_params; i++ ) - { - LLVisualParam* param = contents.mParams[i]; - F32 newWeight = contents.mParamWeights[i]; - - if (slam_params || is_first_appearance_message || (param->getWeight() != newWeight)) - { - params_changed = TRUE; - params_changed_count++; - - if(is_first_appearance_message || slam_params) - { - //LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL; - param->setWeight(newWeight); - } - else - { - interp_params = TRUE; - param->setAnimationTarget(newWeight); - } - } - } - const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) + - getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT - if (num_params != expected_tweakable_count) - { - LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL; - } - - LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << LL_ENDL; - if (params_changed) - { - if (interp_params) - { - startAppearanceAnimation(); - } - updateVisualParams(); - - ESex new_sex = getSex(); - if( old_sex != new_sex ) - { - updateSexDependentLayerSets(); - } - } - - llassert( getSex() == ((getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE) ); - } - else - { - // AvatarAppearance message arrived without visual params - LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; - - const F32 LOADING_TIMEOUT_SECONDS = 60.f; - // this isn't really a problem if we already have a non-default shape - if (visualParamWeightsAreDefault() && mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT_SECONDS) - { - // re-request appearance, hoping that it comes back with a shape next time - LL_INFOS() << "Re-requesting AvatarAppearance for object: " << getID() << LL_ENDL; - LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); - mRuthTimer.reset(); - } - else - { - LL_INFOS() << "That's okay, we already have a non-default shape for object: " << getID() << LL_ENDL; - // we don't really care. - } - } - - if (contents.mHoverOffsetWasSet && !isSelf()) - { - // Got an update for some other avatar - // Ignore updates for self, because we have a more authoritative value in the preferences. - setHoverOffset(contents.mHoverOffset); - LL_DEBUGS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL; - } - - if (!contents.mHoverOffsetWasSet && !isSelf()) - { - // If we don't get a value at all, we are presumably in a - // region that does not support hover height. - LL_WARNS() << avString() << "zeroing hover because not defined in appearance message" << LL_ENDL; - setHoverOffset(LLVector3(0.0, 0.0, 0.0)); - } - - setCompositeUpdatesEnabled( TRUE ); - - // If all of the avatars are completely baked, release the global image caches to conserve memory. - LLVOAvatar::cullAvatarsByPixelArea(); - - if (isSelf()) - { - mUseLocalAppearance = false; - } - - updateMeshTextures(); - updateMeshVisibility(); + if (is_first_appearance_message ) + { + onFirstTEMessageReceived(); + } + + setCompositeUpdatesEnabled( FALSE ); + gPipeline.markGLRebuild(this); + + // Apply visual params + if( num_params > 1) + { + //LL_DEBUGS("Avatar") << avString() << " handle visual params, num_params " << num_params << LL_ENDL; + BOOL params_changed = FALSE; + BOOL interp_params = FALSE; + S32 params_changed_count = 0; + + for( S32 i = 0; i < num_params; i++ ) + { + LLVisualParam* param = contents.mParams[i]; + F32 newWeight = contents.mParamWeights[i]; + + if (slam_params || is_first_appearance_message || (param->getWeight() != newWeight)) + { + params_changed = TRUE; + params_changed_count++; + + if(is_first_appearance_message || slam_params) + { + //LL_DEBUGS("Avatar") << "param slam " << i << " " << newWeight << LL_ENDL; + param->setWeight(newWeight); + } + else + { + interp_params = TRUE; + param->setAnimationTarget(newWeight); + } + } + } + const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE) + + getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TRANSMIT_NOT_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT + if (num_params != expected_tweakable_count) + { + LL_DEBUGS("Avatar") << "Number of params in AvatarAppearance msg (" << num_params << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << LL_ENDL; + } + + LL_DEBUGS("Avatar") << "Changed " << params_changed_count << " params" << LL_ENDL; + if (params_changed) + { + if (interp_params) + { + startAppearanceAnimation(); + } + updateVisualParams(); + + ESex new_sex = getSex(); + if( old_sex != new_sex ) + { + updateSexDependentLayerSets(); + } + } + + llassert( getSex() == ((getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE) ); + } + else + { + // AvatarAppearance message arrived without visual params + LL_DEBUGS("Avatar") << avString() << "no visual params" << LL_ENDL; + + const F32 LOADING_TIMEOUT_SECONDS = 60.f; + // this isn't really a problem if we already have a non-default shape + if (visualParamWeightsAreDefault() && mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT_SECONDS) + { + // re-request appearance, hoping that it comes back with a shape next time + LL_INFOS() << "Re-requesting AvatarAppearance for object: " << getID() << LL_ENDL; + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); + mRuthTimer.reset(); + } + else + { + LL_INFOS() << "That's okay, we already have a non-default shape for object: " << getID() << LL_ENDL; + // we don't really care. + } + } + + if (contents.mHoverOffsetWasSet && !isSelf()) + { + // Got an update for some other avatar + // Ignore updates for self, because we have a more authoritative value in the preferences. + setHoverOffset(contents.mHoverOffset); + LL_DEBUGS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL; + } + + if (!contents.mHoverOffsetWasSet && !isSelf()) + { + // If we don't get a value at all, we are presumably in a + // region that does not support hover height. + LL_WARNS() << avString() << "zeroing hover because not defined in appearance message" << LL_ENDL; + setHoverOffset(LLVector3(0.0, 0.0, 0.0)); + } + + setCompositeUpdatesEnabled( TRUE ); + + // If all of the avatars are completely baked, release the global image caches to conserve memory. + LLVOAvatar::cullAvatarsByPixelArea(); + + if (isSelf()) + { + mUseLocalAppearance = false; + } + + updateMeshTextures(); + updateMeshVisibility(); } LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te) { - if (te < 0 || te >= BAKED_NUM_INDICES) - { - return NULL; - } + if (te < 0 || te >= BAKED_NUM_INDICES) + { + return NULL; + } + + BOOL is_layer_baked = isTextureDefined(mBakedTextureDatas[te].mTextureIndex); + + LLViewerTexLayerSet* layerset = NULL; + layerset = getTexLayerSet(te); - BOOL is_layer_baked = isTextureDefined(mBakedTextureDatas[te].mTextureIndex); - - LLViewerTexLayerSet* layerset = NULL; - layerset = getTexLayerSet(te); - - if (!isEditingAppearance() && is_layer_baked) - { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage(mBakedTextureDatas[te].mTextureIndex, 0), TRUE); - return baked_img; - } - else if (layerset && isEditingAppearance()) - { - layerset->createComposite(); - layerset->setUpdatesEnabled(TRUE); + if (!isEditingAppearance() && is_layer_baked) + { + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage(mBakedTextureDatas[te].mTextureIndex, 0), TRUE); + return baked_img; + } + else if (layerset && isEditingAppearance()) + { + layerset->createComposite(); + layerset->setUpdatesEnabled(TRUE); + + return layerset->getViewerComposite(); + } - return layerset->getViewerComposite(); - } + return NULL; - return NULL; - } const LLVOAvatar::MatrixPaletteCache& LLVOAvatar::updateSkinInfoMatrixPalette(const LLMeshSkinInfo* skin) @@ -9741,262 +9741,262 @@ const LLVOAvatar::MatrixPaletteCache& LLVOAvatar::updateSkinInfoMatrixPalette(co // static void LLVOAvatar::getAnimLabels( std::vector* labels ) { - S32 i; - labels->reserve(gUserAnimStatesCount); - for( i = 0; i < gUserAnimStatesCount; i++ ) - { - labels->push_back( LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ) ); - } + S32 i; + labels->reserve(gUserAnimStatesCount); + for( i = 0; i < gUserAnimStatesCount; i++ ) + { + labels->push_back( LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ) ); + } - // Special case to trigger away (AFK) state - labels->push_back( "Away From Keyboard" ); + // Special case to trigger away (AFK) state + labels->push_back( "Away From Keyboard" ); } -// static +// static void LLVOAvatar::getAnimNames( std::vector* names ) { - S32 i; + S32 i; - names->reserve(gUserAnimStatesCount); - for( i = 0; i < gUserAnimStatesCount; i++ ) - { - names->push_back( std::string(gUserAnimStates[i].mName) ); - } + names->reserve(gUserAnimStatesCount); + for( i = 0; i < gUserAnimStatesCount; i++ ) + { + names->push_back( std::string(gUserAnimStates[i].mName) ); + } - // Special case to trigger away (AFK) state - names->push_back( "enter_away_from_keyboard_state" ); + // Special case to trigger away (AFK) state + names->push_back( "enter_away_from_keyboard_state" ); } // static void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - if (!userdata) return; - - //LL_INFOS() << "onBakedTextureMasksLoaded: " << src_vi->getID() << LL_ENDL; - const LLUUID id = src_vi->getID(); - - LLTextureMaskData* maskData = (LLTextureMaskData*) userdata; - LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID ); - - // if discard level is 2 less than last discard level we processed, or we hit 0, - // then generate morph masks - if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0)) - { - if(aux_src && aux_src->getComponents() == 1) - { - if (!aux_src->getData()) - { - LL_ERRS() << "No auxiliary source (morph mask) data for image id " << id << LL_ENDL; - return; - } - - U32 gl_name; - LLImageGL::generateTextures(1, &gl_name ); - stop_glerror(); - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); - stop_glerror(); - - LLImageGL::setManualImage( - GL_TEXTURE_2D, 0, GL_ALPHA8, - aux_src->getWidth(), aux_src->getHeight(), - GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); - stop_glerror(); - - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - - /* if( id == head_baked->getID() ) - if (self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) - //LL_INFOS() << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << LL_ENDL; - self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; */ - BOOL found_texture_id = false; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); - iter != LLAvatarAppearance::getDictionary()->getTextures().end(); - ++iter) - { - - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - if (texture_dict->mIsUsedByBakedTexture) - { - const ETextureIndex texture_index = iter->first; - const LLViewerTexture *baked_img = self->getImage(texture_index, 0); - if (baked_img && id == baked_img->getID()) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index); - maskData->mLastDiscardLevel = discard_level; - if (self->mBakedTextureDatas[baked_index].mMaskTexName) - { - LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); - } - self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; - found_texture_id = true; - break; - } - } - } - if (!found_texture_id) - { - LL_INFOS() << "unexpected image id: " << id << LL_ENDL; - } - self->dirtyMesh(); - } - else - { - // this can happen when someone uses an old baked texture possibly provided by + if (!userdata) return; + + //LL_INFOS() << "onBakedTextureMasksLoaded: " << src_vi->getID() << LL_ENDL; + const LLUUID id = src_vi->getID(); + + LLTextureMaskData* maskData = (LLTextureMaskData*) userdata; + LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID ); + + // if discard level is 2 less than last discard level we processed, or we hit 0, + // then generate morph masks + if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0)) + { + if(aux_src && aux_src->getComponents() == 1) + { + if (!aux_src->getData()) + { + LL_ERRS() << "No auxiliary source (morph mask) data for image id " << id << LL_ENDL; + return; + } + + U32 gl_name; + LLImageGL::generateTextures(1, &gl_name ); + stop_glerror(); + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name); + stop_glerror(); + + LLImageGL::setManualImage( + GL_TEXTURE_2D, 0, GL_ALPHA8, + aux_src->getWidth(), aux_src->getHeight(), + GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData()); + stop_glerror(); + + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + + /* if( id == head_baked->getID() ) + if (self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) + //LL_INFOS() << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << LL_ENDL; + self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + maskData->mLastDiscardLevel = discard_level; */ + BOOL found_texture_id = false; + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); + ++iter) + { + + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (texture_dict->mIsUsedByBakedTexture) + { + const ETextureIndex texture_index = iter->first; + const LLViewerTexture *baked_img = self->getImage(texture_index, 0); + if (baked_img && id == baked_img->getID()) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index); + maskData->mLastDiscardLevel = discard_level; + if (self->mBakedTextureDatas[baked_index].mMaskTexName) + { + LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); + } + self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; + found_texture_id = true; + break; + } + } + } + if (!found_texture_id) + { + LL_INFOS() << "unexpected image id: " << id << LL_ENDL; + } + self->dirtyMesh(); + } + else + { + // this can happen when someone uses an old baked texture possibly provided by // viewer-side baked texture caching - LL_WARNS() << "Masks loaded callback but NO aux source, id " << id << LL_ENDL; - } - } + LL_WARNS() << "Masks loaded callback but NO aux source, id " << id << LL_ENDL; + } + } - if (final || !success) - { - delete maskData; - } + if (final || !success) + { + delete maskData; + } } // static void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - LLUUID *avatar_idp = (LLUUID *)userdata; - LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + LLUUID *avatar_idp = (LLUUID *)userdata; + LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); - if (selfp) - { - //LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; - } + if (selfp) + { + //LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; + } - if (!success && selfp) - { - selfp->removeMissingBakedTextures(); - } - if (final || !success ) - { - delete avatar_idp; - } + if (!success && selfp) + { + selfp->removeMissingBakedTextures(); + } + if (final || !success ) + { + delete avatar_idp; + } } // Static void LLVOAvatar::onBakedTextureLoaded(BOOL success, - LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, - S32 discard_level, BOOL final, void* userdata) + LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, + S32 discard_level, BOOL final, void* userdata) { - //LL_DEBUGS("Avatar") << "onBakedTextureLoaded: " << src_vi->getID() << LL_ENDL; + //LL_DEBUGS("Avatar") << "onBakedTextureLoaded: " << src_vi->getID() << LL_ENDL; - LLUUID id = src_vi->getID(); - LLUUID *avatar_idp = (LLUUID *)userdata; - LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); - if (selfp) - { - //LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << " id " << src_vi->getID() << LL_ENDL; - } + LLUUID id = src_vi->getID(); + LLUUID *avatar_idp = (LLUUID *)userdata; + LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); + if (selfp) + { + //LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << " id " << src_vi->getID() << LL_ENDL; + } - if (selfp && !success) - { - selfp->removeMissingBakedTextures(); - } + if (selfp && !success) + { + selfp->removeMissingBakedTextures(); + } - if( final || !success ) - { - delete avatar_idp; - } + if( final || !success ) + { + delete avatar_idp; + } - if( selfp && success && final ) - { - selfp->useBakedTexture( id ); - } + if( selfp && success && final ) + { + selfp->useBakedTexture( id ); + } } // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); - if (id == image_baked->getID()) - { - //LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; - mBakedTextureDatas[i].mIsLoaded = true; - mBakedTextureDatas[i].mLastTextureID = id; - mBakedTextureDatas[i].mIsUsed = true; - - if (isUsingLocalAppearance()) - { - LL_INFOS() << "not changing to baked texture while isUsingLocalAppearance" << LL_ENDL; - } - else - { - debugColorizeSubMeshes(i,LLColor4::green); - - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setTexture( image_baked ); - } - } - } - - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = - LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)i); - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - if (isSelf()) setBakedReady(*local_tex_iter, TRUE); - } - - // ! BACKWARDS COMPATIBILITY ! - // Workaround for viewing avatars from old viewers that haven't baked hair textures. - // This is paired with similar code in updateMeshTextures that sets hair mesh color. - if (i == BAKED_HAIR) - { - avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); - avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); - for (; iter != end; ++iter) - { - LLAvatarJointMesh* mesh = (*iter); - if (mesh) - { - mesh->setColor( LLColor4::white ); - } - } - } - } - } - - dirtyMesh(); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); + if (id == image_baked->getID()) + { + //LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; + mBakedTextureDatas[i].mIsLoaded = true; + mBakedTextureDatas[i].mLastTextureID = id; + mBakedTextureDatas[i].mIsUsed = true; + + if (isUsingLocalAppearance()) + { + LL_INFOS() << "not changing to baked texture while isUsingLocalAppearance" << LL_ENDL; + } + else + { + debugColorizeSubMeshes(i,LLColor4::green); + + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setTexture( image_baked ); + } + } + } + + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = + LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + if (isSelf()) setBakedReady(*local_tex_iter, TRUE); + } + + // ! BACKWARDS COMPATIBILITY ! + // Workaround for viewing avatars from old viewers that haven't baked hair textures. + // This is paired with similar code in updateMeshTextures that sets hair mesh color. + if (i == BAKED_HAIR) + { + avatar_joint_mesh_list_t::iterator iter = mBakedTextureDatas[i].mJointMeshes.begin(); + avatar_joint_mesh_list_t::iterator end = mBakedTextureDatas[i].mJointMeshes.end(); + for (; iter != end; ++iter) + { + LLAvatarJointMesh* mesh = (*iter); + if (mesh) + { + mesh->setColor( LLColor4::white ); + } + } + } + } + } + + dirtyMesh(); } std::string get_sequential_numbered_file_name(const std::string& prefix, - const std::string& suffix) -{ - typedef std::map file_num_type; - static file_num_type file_nums; - file_num_type::iterator it = file_nums.find(prefix); - S32 num = 0; - if (it != file_nums.end()) - { - num = it->second; - } - file_nums[prefix] = num+1; - std::string outfilename = prefix + " " + llformat("%04d",num) + ".xml"; - std::replace(outfilename.begin(),outfilename.end(),' ','_'); - return outfilename; + const std::string& suffix) +{ + typedef std::map file_num_type; + static file_num_type file_nums; + file_num_type::iterator it = file_nums.find(prefix); + S32 num = 0; + if (it != file_nums.end()) + { + num = it->second; + } + file_nums[prefix] = num+1; + std::string outfilename = prefix + " " + llformat("%04d",num) + ".xml"; + std::replace(outfilename.begin(),outfilename.end(),' ','_'); + return outfilename; } void dump_sequential_xml(const std::string outprefix, const LLSD& content) { - std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); - std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); - llofstream ofs(fullpath.c_str(), std::ios_base::out); - ofs << LLSDOStreamer(content, LLSDFormatter::OPTIONS_PRETTY); - LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL; + std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + llofstream ofs(fullpath.c_str(), std::ios_base::out); + ofs << LLSDOStreamer(content, LLSDFormatter::OPTIONS_PRETTY); + LL_DEBUGS("Avatar") << "results saved to: " << fullpath << LL_ENDL; } void LLVOAvatar::getSortedJointNames(S32 joint_type, std::vector& result) const @@ -10006,125 +10006,125 @@ void LLVOAvatar::getSortedJointNames(S32 joint_type, std::vector& r { avatar_joint_list_t::const_iterator iter = mSkeleton.begin(); avatar_joint_list_t::const_iterator end = mSkeleton.end(); - for (; iter != end; ++iter) - { - LLJoint* pJoint = (*iter); + for (; iter != end; ++iter) + { + LLJoint* pJoint = (*iter); + result.push_back(pJoint->getName()); + } + } + else if (joint_type==1) + { + for (S32 i = 0; i < mNumCollisionVolumes; i++) + { + LLAvatarJointCollisionVolume* pJoint = &mCollisionVolumes[i]; result.push_back(pJoint->getName()); } - } - else if (joint_type==1) - { - for (S32 i = 0; i < mNumCollisionVolumes; i++) + } + else if (joint_type==2) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* pJoint = iter->second; + if (!pJoint) continue; + result.push_back(pJoint->getName()); + } + } + std::sort(result.begin(), result.end()); +} + +void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables ) +{ + std::string outprefix(prefix); + if (outprefix.empty()) + { + outprefix = getFullname() + (isSelf()?"_s":"_o"); + } + if (outprefix.empty()) + { + outprefix = std::string("new_archetype"); + } + std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + + LLAPRFile outfile; + LLWearableType *wr_inst = LLWearableType::getInstance(); + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) + { + apr_file_t* file = outfile.getFileHandle(); + LL_INFOS() << "xmlfile write handle obtained : " << fullpath << LL_ENDL; + + apr_file_printf( file, "\n" ); + apr_file_printf( file, "\n" ); + apr_file_printf( file, "\n\t\n" ); + + bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery(); + + if (group_by_wearables) + { + for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) + { + const std::string& wearable_name = wr_inst->getTypeName((LLWearableType::EType)type); + apr_file_printf( file, "\n\t\t\n", wearable_name.c_str() ); + + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + if( (viewer_param->getWearableType() == type) && + (viewer_param->isTweakable() ) ) + { + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) + { + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)te) == type) + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + std::string uuid_str = LLUUID().asString(); + if (agent_is_godlike) + { + te_image->getID().toString(uuid_str); + } + apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); + } + } + } + } + } + else { - LLAvatarJointCollisionVolume* pJoint = &mCollisionVolumes[i]; - result.push_back(pJoint->getName()); - } - } - else if (joint_type==2) - { - for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ++iter) - { - LLViewerJointAttachment* pJoint = iter->second; - if (!pJoint) continue; - result.push_back(pJoint->getName()); - } - } - std::sort(result.begin(), result.end()); -} + // Just dump all params sequentially. + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + dump_visual_param(file, viewer_param, viewer_param->getWeight()); + } -void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_wearables ) -{ - std::string outprefix(prefix); - if (outprefix.empty()) - { - outprefix = getFullname() + (isSelf()?"_s":"_o"); - } - if (outprefix.empty()) - { - outprefix = std::string("new_archetype"); - } - std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); - - LLAPRFile outfile; - LLWearableType *wr_inst = LLWearableType::getInstance(); - std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); - if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) - { - apr_file_t* file = outfile.getFileHandle(); - LL_INFOS() << "xmlfile write handle obtained : " << fullpath << LL_ENDL; - - apr_file_printf( file, "\n" ); - apr_file_printf( file, "\n" ); - apr_file_printf( file, "\n\t\n" ); - - bool agent_is_godlike = gAgent.isGodlikeWithoutAdminMenuFakery(); - - if (group_by_wearables) - { - for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) - { - const std::string& wearable_name = wr_inst->getTypeName((LLWearableType::EType)type); - apr_file_printf( file, "\n\t\t\n", wearable_name.c_str() ); - - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) - { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - if( (viewer_param->getWearableType() == type) && - (viewer_param->isTweakable() ) ) - { - dump_visual_param(file, viewer_param, viewer_param->getWeight()); - } - } - - for (U8 te = 0; te < TEX_NUM_INDICES; te++) - { - if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)te) == type) - { - // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); - if( te_image ) - { - std::string uuid_str = LLUUID().asString(); - if (agent_is_godlike) - { - te_image->getID().toString(uuid_str); - } - apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); - } - } - } - } - } - else - { - // Just dump all params sequentially. - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) - { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - dump_visual_param(file, viewer_param, viewer_param->getWeight()); - } - - for (U8 te = 0; te < TEX_NUM_INDICES; te++) - { - // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); - if( te_image ) - { - std::string uuid_str = LLUUID().asString(); - if (agent_is_godlike) - { - te_image->getID().toString(uuid_str); - } - apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); - } - } - } + for (U8 te = 0; te < TEX_NUM_INDICES; te++) + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + std::string uuid_str = LLUUID().asString(); + if (agent_is_godlike) + { + te_image->getID().toString(uuid_str); + } + apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); + } + } + } // Root joint const LLVector3& pos = mRoot->getPosition(); const LLVector3& scale = mRoot->getScale(); - apr_file_printf( file, "\t\t\n", + apr_file_printf( file, "\t\t\n", mRoot->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); // Bones @@ -10140,10 +10140,10 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara name_iter != bone_names.end(); ++name_iter) { LLJoint *pJoint = getJoint(*name_iter); - const LLVector3& pos = pJoint->getPosition(); - const LLVector3& scale = pJoint->getScale(); - apr_file_printf( file, "\t\t\n", - pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); + const LLVector3& pos = pJoint->getPosition(); + const LLVector3& scale = pJoint->getScale(); + apr_file_printf( file, "\t\t\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); } // Collision volumes @@ -10151,10 +10151,10 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara name_iter != cv_names.end(); ++name_iter) { LLJoint *pJoint = getJoint(*name_iter); - const LLVector3& pos = pJoint->getPosition(); - const LLVector3& scale = pJoint->getScale(); - apr_file_printf( file, "\t\t\n", - pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); + const LLVector3& pos = pJoint->getPosition(); + const LLVector3& scale = pJoint->getScale(); + apr_file_printf( file, "\t\t\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); } // Attachment joints @@ -10162,63 +10162,63 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara name_iter != attach_names.end(); ++name_iter) { LLJoint *pJoint = getJoint(*name_iter); - if (!pJoint) continue; - const LLVector3& pos = pJoint->getPosition(); - const LLVector3& scale = pJoint->getScale(); - apr_file_printf( file, "\t\t\n", - pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); + if (!pJoint) continue; + const LLVector3& pos = pJoint->getPosition(); + const LLVector3& scale = pJoint->getScale(); + apr_file_printf( file, "\t\t\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], scale[0], scale[1], scale[2]); } - + // Joint pos overrides for (std::vector::iterator name_iter = all_names.begin(); name_iter != all_names.end(); ++name_iter) { LLJoint *pJoint = getJoint(*name_iter); - - LLVector3 pos; - LLUUID mesh_id; - if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) - { + LLVector3 pos; + LLUUID mesh_id; + + if (pJoint && pJoint->hasAttachmentPosOverride(pos,mesh_id)) + { S32 num_pos_overrides; std::set distinct_pos_overrides; pJoint->getAllAttachmentPosOverrides(num_pos_overrides, distinct_pos_overrides); - apr_file_printf( file, "\t\t\n", - pJoint->getName().c_str(), pos[0], pos[1], pos[2], mesh_id.asString().c_str(), + apr_file_printf( file, "\t\t\n", + pJoint->getName().c_str(), pos[0], pos[1], pos[2], mesh_id.asString().c_str(), num_pos_overrides, (S32) distinct_pos_overrides.size()); - } - } + } + } // Joint scale overrides for (std::vector::iterator name_iter = all_names.begin(); name_iter != all_names.end(); ++name_iter) { LLJoint *pJoint = getJoint(*name_iter); - - LLVector3 scale; - LLUUID mesh_id; - if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) - { + LLVector3 scale; + LLUUID mesh_id; + + if (pJoint && pJoint->hasAttachmentScaleOverride(scale,mesh_id)) + { S32 num_scale_overrides; std::set distinct_scale_overrides; pJoint->getAllAttachmentPosOverrides(num_scale_overrides, distinct_scale_overrides); - apr_file_printf( file, "\t\t\n", - pJoint->getName().c_str(), scale[0], scale[1], scale[2], mesh_id.asString().c_str(), + apr_file_printf( file, "\t\t\n", + pJoint->getName().c_str(), scale[0], scale[1], scale[2], mesh_id.asString().c_str(), num_scale_overrides, (S32) distinct_scale_overrides.size()); - } - } - F32 pelvis_fixup; - LLUUID mesh_id; - if (hasPelvisFixup(pelvis_fixup, mesh_id)) - { - apr_file_printf( file, "\t\t\n", - pelvis_fixup, mesh_id.asString().c_str()); - } + } + } + F32 pelvis_fixup; + LLUUID mesh_id; + if (hasPelvisFixup(pelvis_fixup, mesh_id)) + { + apr_file_printf( file, "\t\t\n", + pelvis_fixup, mesh_id.asString().c_str()); + } LLVector3 rp = getRootJoint()->getWorldPosition(); LLVector4a rpv; rpv.load3(rp.mV); - + for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) { LLJoint *joint = getJoint(joint_num); @@ -10234,7 +10234,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara LLVector4a rrp[2]; rrp[0].setSub(new_extents[0],rpv); rrp[1].setSub(new_extents[1],rpv); - apr_file_printf( file, "\t\t\n", + apr_file_printf( file, "\t\t\n", joint_num, joint->getName().c_str(), rig_info.getRiggedExtents()[0][0], @@ -10253,134 +10253,134 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara } } - bool ultra_verbose = false; - if (isSelf() && ultra_verbose) - { - // show the cloned params inside the wearables as well. - gAgentAvatarp->dumpWearableInfo(outfile); - } + bool ultra_verbose = false; + if (isSelf() && ultra_verbose) + { + // show the cloned params inside the wearables as well. + gAgentAvatarp->dumpWearableInfo(outfile); + } - apr_file_printf( file, "\t\n" ); - apr_file_printf( file, "\n\n" ); + apr_file_printf( file, "\t\n" ); + apr_file_printf( file, "\n\n" ); - LLSD args; - args["PATH"] = fullpath; - LLNotificationsUtil::add("AppearanceToXMLSaved", args); - } - else - { - LLNotificationsUtil::add("AppearanceToXMLFailed"); - } - // File will close when handle goes out of scope + LLSD args; + args["PATH"] = fullpath; + LLNotificationsUtil::add("AppearanceToXMLSaved", args); + } + else + { + LLNotificationsUtil::add("AppearanceToXMLFailed"); + } + // File will close when handle goes out of scope } void LLVOAvatar::setVisibilityRank(U32 rank) { - if (mDrawable.isNull() || mDrawable->isDead()) - { - // do nothing - return; - } - mVisibilityRank = rank; + if (mDrawable.isNull() || mDrawable->isDead()) + { + // do nothing + return; + } + mVisibilityRank = rank; } // Assumes LLVOAvatar::sInstances has already been sorted. S32 LLVOAvatar::getUnbakedPixelAreaRank() { - S32 rank = 1; - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - if (inst == this) - { - return rank; - } - else if (!inst->isDead() && !inst->isFullyBaked()) - { - rank++; - } - } - - llassert(0); - return 0; + S32 rank = 1; + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + if (inst == this) + { + return rank; + } + else if (!inst->isDead() && !inst->isFullyBaked()) + { + rank++; + } + } + + llassert(0); + return 0; } struct CompareScreenAreaGreater { - BOOL operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) - { - return lhs->getPixelArea() > rhs->getPixelArea(); - } + BOOL operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) + { + return lhs->getPixelArea() > rhs->getPixelArea(); + } }; // static void LLVOAvatar::cullAvatarsByPixelArea() { - std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); - - // Update the avatars that have changed status - U32 rank = 2; //1 is reserved for self. - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* inst = (LLVOAvatar*) *iter; - BOOL culled; - if (inst->isSelf() || inst->isFullyBaked()) - { - culled = FALSE; - } - else - { - culled = TRUE; - } - - if (inst->mCulled != culled) - { - inst->mCulled = culled; - LL_DEBUGS() << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << LL_ENDL; - inst->updateMeshTextures(); - } - - if (inst->isSelf()) - { - inst->setVisibilityRank(1); - } - else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) - { - inst->setVisibilityRank(rank++); - } - } - - // runway - this doesn't really detect gray/grey state. - S32 grey_avatars = 0; - if (!LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) - { - if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame - { - sUnbakedUpdateTime = gFrameTimeSeconds; - sUnbakedTime += gFrameIntervalSeconds.value(); - } - if (grey_avatars > 0) - { - if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame - { - sGreyUpdateTime = gFrameTimeSeconds; - sGreyTime += gFrameIntervalSeconds.value(); - } - } - } + std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); + + // Update the avatars that have changed status + U32 rank = 2; //1 is reserved for self. + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* inst = (LLVOAvatar*) *iter; + BOOL culled; + if (inst->isSelf() || inst->isFullyBaked()) + { + culled = FALSE; + } + else + { + culled = TRUE; + } + + if (inst->mCulled != culled) + { + inst->mCulled = culled; + LL_DEBUGS() << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << LL_ENDL; + inst->updateMeshTextures(); + } + + if (inst->isSelf()) + { + inst->setVisibilityRank(1); + } + else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) + { + inst->setVisibilityRank(rank++); + } + } + + // runway - this doesn't really detect gray/grey state. + S32 grey_avatars = 0; + if (!LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars)) + { + if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame + { + sUnbakedUpdateTime = gFrameTimeSeconds; + sUnbakedTime += gFrameIntervalSeconds.value(); + } + if (grey_avatars > 0) + { + if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame + { + sGreyUpdateTime = gFrameTimeSeconds; + sGreyTime += gFrameIntervalSeconds.value(); + } + } + } } void LLVOAvatar::startAppearanceAnimation() { - if(!mAppearanceAnimating) - { - mAppearanceAnimating = TRUE; - mAppearanceMorphTimer.reset(); - mLastAppearanceBlendTime = 0.f; - } + if(!mAppearanceAnimating) + { + mAppearanceAnimating = TRUE; + mAppearanceMorphTimer.reset(); + mLastAppearanceBlendTime = 0.f; + } } // virtual @@ -10391,35 +10391,35 @@ void LLVOAvatar::removeMissingBakedTextures() //virtual void LLVOAvatar::updateRegion(LLViewerRegion *regionp) { - LLViewerObject::updateRegion(regionp); + LLViewerObject::updateRegion(regionp); } // virtual std::string LLVOAvatar::getFullname() const { - std::string name; + std::string name; - LLNameValue* first = getNVPair("FirstName"); - LLNameValue* last = getNVPair("LastName"); - if (first && last) - { - name = LLCacheName::buildFullName( first->getString(), last->getString() ); - } + LLNameValue* first = getNVPair("FirstName"); + LLNameValue* last = getNVPair("LastName"); + if (first && last) + { + name = LLCacheName::buildFullName( first->getString(), last->getString() ); + } - return name; + return name; } LLHost LLVOAvatar::getObjectHost() const { - LLViewerRegion* region = getRegion(); - if (region && !isDead()) - { - return region->getHost(); - } - else - { - return LLHost(); - } + LLViewerRegion* region = getRegion(); + if (region && !isDead()) + { + return region->getHost(); + } + else + { + return LLHost(); + } } BOOL LLVOAvatar::updateLOD() @@ -10428,36 +10428,36 @@ BOOL LLVOAvatar::updateLOD() { return FALSE; } - - if (!LLPipeline::sImpostorRender && isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry()) - { - return TRUE; - } - BOOL res = updateJointLODs(); + if (!LLPipeline::sImpostorRender && isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry()) + { + return TRUE; + } + + BOOL res = updateJointLODs(); - LLFace* facep = mDrawable->getFace(0); - if (!facep || !facep->getVertexBuffer()) - { - dirtyMesh(2); - } + LLFace* facep = mDrawable->getFace(0); + if (!facep || !facep->getVertexBuffer()) + { + dirtyMesh(2); + } - if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) - { //LOD changed or new mesh created, allocate new vertex buffer if needed - updateMeshData(); - mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } - updateVisibility(); + if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + { //LOD changed or new mesh created, allocate new vertex buffer if needed + updateMeshData(); + mDirtyMesh = 0; + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } + updateVisibility(); - return res; + return res; } void LLVOAvatar::updateLODRiggedAttachments() { - updateLOD(); - rebuildRiggedAttachments(); + updateLOD(); + rebuildRiggedAttachments(); } void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& count_rigged, S32& count_box) @@ -10471,7 +10471,7 @@ void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& { count_rigged++; LLJoint *joint = avatar->getJoint(i); - LL_DEBUGS("RigSpam") << "joint " << i << " name " << joint->getName() << " box " + LL_DEBUGS("RigSpam") << "joint " << i << " name " << joint->getName() << " box " << tab[i].getRiggedExtents()[0] << ", " << tab[i].getRiggedExtents()[1] << LL_ENDL; if ((!tab[i].getRiggedExtents()[0].equals3(zero_vec)) || (!tab[i].getRiggedExtents()[1].equals3(zero_vec))) @@ -10485,15 +10485,15 @@ void showRigInfoTabExtents(LLVOAvatar *avatar, LLJointRiggingInfoTab& tab, S32& void LLVOAvatar::getAssociatedVolumes(std::vector& volumes) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - for ( LLVOAvatar::attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) - { - LLViewerJointAttachment* attachment = iter->second; - LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end(); - - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin(); - attach_iter != attach_end; ++attach_iter) - { - LLViewerObject* attached_object = attach_iter->get(); + for ( LLVOAvatar::attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) + { + LLViewerJointAttachment* attachment = iter->second; + LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end(); + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin(); + attach_iter != attach_end; ++attach_iter) + { + LLViewerObject* attached_object = attach_iter->get(); LLVOVolume *volume = dynamic_cast(attached_object); if (volume) { @@ -10551,31 +10551,31 @@ void LLVOAvatar::updateRiggingInfo() std::vector volumes; - getAssociatedVolumes(volumes); - - std::map curr_rigging_info_key; - { - // Get current rigging info key - for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) - { - LLVOVolume *vol = *it; - if (vol->isMesh() && vol->getVolume()) - { - const LLUUID& mesh_id = vol->getVolume()->getParams().getSculptID(); - S32 max_lod = llmax(vol->getLOD(), vol->mLastRiggingInfoLOD); - curr_rigging_info_key[mesh_id] = max_lod; - } - } - - // Check for key change, which indicates some change in volume composition or LOD. - if (curr_rigging_info_key == mLastRiggingInfoKey) - { - return; - } - } - - // Something changed. Update. - mLastRiggingInfoKey = curr_rigging_info_key; + getAssociatedVolumes(volumes); + + std::map curr_rigging_info_key; + { + // Get current rigging info key + for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) + { + LLVOVolume *vol = *it; + if (vol->isMesh() && vol->getVolume()) + { + const LLUUID& mesh_id = vol->getVolume()->getParams().getSculptID(); + S32 max_lod = llmax(vol->getLOD(), vol->mLastRiggingInfoLOD); + curr_rigging_info_key[mesh_id] = max_lod; + } + } + + // Check for key change, which indicates some change in volume composition or LOD. + if (curr_rigging_info_key == mLastRiggingInfoKey) + { + return; + } + } + + // Something changed. Update. + mLastRiggingInfoKey = curr_rigging_info_key; mJointRiggingInfoTab.clear(); for (std::vector::iterator it = volumes.begin(); it != volumes.end(); ++it) { @@ -10598,112 +10598,112 @@ void LLVOAvatar::onActiveOverrideMeshesChanged() } U32 LLVOAvatar::getPartitionType() const -{ - // Avatars merely exist as drawables in the bridge partition - return mIsControlAvatar ? LLViewerRegion::PARTITION_CONTROL_AV : LLViewerRegion::PARTITION_AVATAR; +{ + // Avatars merely exist as drawables in the bridge partition + return mIsControlAvatar ? LLViewerRegion::PARTITION_CONTROL_AV : LLViewerRegion::PARTITION_AVATAR; } //static void LLVOAvatar::updateImpostors() { - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; std::vector instances_copy = LLCharacter::sInstances; - for (std::vector::iterator iter = instances_copy.begin(); - iter != instances_copy.end(); ++iter) - { - LLVOAvatar* avatar = (LLVOAvatar*) *iter; - if (!avatar->isDead() - && avatar->isVisible() - && avatar->isImpostor() - && avatar->needsImpostorUpdate()) - { + for (std::vector::iterator iter = instances_copy.begin(); + iter != instances_copy.end(); ++iter) + { + LLVOAvatar* avatar = (LLVOAvatar*) *iter; + if (!avatar->isDead() + && avatar->isVisible() + && avatar->isImpostor() + && avatar->needsImpostorUpdate()) + { avatar->calcMutedAVColor(); - gPipeline.generateImpostor(avatar); - } - } + gPipeline.generateImpostor(avatar); + } + } - LLCharacter::sAllowInstancesChange = TRUE; + LLCharacter::sAllowInstancesChange = TRUE; } // virtual BOOL LLVOAvatar::isImpostor() { - return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1)); + return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1)); } BOOL LLVOAvatar::shouldImpostor(const F32 rank_factor) { - if (isSelf()) - { - return false; - } - if (isVisuallyMuted()) - { - return true; - } - return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor); + if (isSelf()) + { + return false; + } + if (isVisuallyMuted()) + { + return true; + } + return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor); } BOOL LLVOAvatar::needsImpostorUpdate() const { - return mNeedsImpostorUpdate; + return mNeedsImpostorUpdate; } const LLVector3& LLVOAvatar::getImpostorOffset() const { - return mImpostorOffset; + return mImpostorOffset; } const LLVector2& LLVOAvatar::getImpostorDim() const { - return mImpostorDim; + return mImpostorDim; } void LLVOAvatar::setImpostorDim(const LLVector2& dim) { - mImpostorDim = dim; + mImpostorDim = dim; } void LLVOAvatar::cacheImpostorValues() { - getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance); + getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance); } void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const { - const LLVector4a* ext = mDrawable->getSpatialExtents(); - extents[0] = ext[0]; - extents[1] = ext[1]; + const LLVector4a* ext = mDrawable->getSpatialExtents(); + extents[0] = ext[0]; + extents[1] = ext[1]; - LLVector3 at = LLViewerCamera::getInstance()->getOrigin()-(getRenderPosition()+mImpostorOffset); - distance = at.normalize(); - F32 da = 1.f - (at*LLViewerCamera::getInstance()->getAtAxis()); - angle.mV[0] = LLViewerCamera::getInstance()->getYaw()*da; - angle.mV[1] = LLViewerCamera::getInstance()->getPitch()*da; - angle.mV[2] = da; + LLVector3 at = LLViewerCamera::getInstance()->getOrigin()-(getRenderPosition()+mImpostorOffset); + distance = at.normalize(); + F32 da = 1.f - (at*LLViewerCamera::getInstance()->getAtAxis()); + angle.mV[0] = LLViewerCamera::getInstance()->getYaw()*da; + angle.mV[1] = LLViewerCamera::getInstance()->getPitch()*da; + angle.mV[2] = da; } // static const U32 LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors - * slider in panel_preferences_graphics1.xml */ + * slider in panel_preferences_graphics1.xml */ // static void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue) { - U32 oldmax = sMaxNonImpostors; - bool oldflg = sLimitNonImpostors; - - if (NON_IMPOSTORS_MAX_SLIDER <= newMaxNonImpostorsValue) - { - sMaxNonImpostors = 0; - } - else - { - sMaxNonImpostors = newMaxNonImpostorsValue; - } - // the sLimitNonImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0) - sLimitNonImpostors = (0 != sMaxNonImpostors); + U32 oldmax = sMaxNonImpostors; + bool oldflg = sLimitNonImpostors; + + if (NON_IMPOSTORS_MAX_SLIDER <= newMaxNonImpostorsValue) + { + sMaxNonImpostors = 0; + } + else + { + sMaxNonImpostors = newMaxNonImpostorsValue; + } + // the sLimitNonImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0) + sLimitNonImpostors = (0 != sMaxNonImpostors); if ( oldflg != sLimitNonImpostors ) { LL_DEBUGS("AvatarRender") @@ -10729,9 +10729,9 @@ void LLVOAvatar::idleUpdateRenderComplexity() } // Render Complexity - calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed + calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed - bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf(); + bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf(); if (autotune && !isDead()) { static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); @@ -10764,7 +10764,7 @@ void LLVOAvatar::updateNearbyAvatarCount() { static LLFrameTimer agent_update_timer; - if (agent_update_timer.getElapsedTimeF32() > 1.0f) + if (agent_update_timer.getElapsedTimeF32() > 1.0f) { S32 avs_nearby = 0; static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); @@ -10792,90 +10792,90 @@ void LLVOAvatar::updateNearbyAvatarCount() void LLVOAvatar::idleUpdateDebugInfo() { - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO)) - { - std::string info_line; - F32 red_level; - F32 green_level; - LLColor4 info_color; - LLFontGL::StyleFlags info_style; - - if ( !mText ) - { - initHudText(); - mText->setFadeDistance(20.0, 5.0); // limit clutter in large crowds - } - else - { - mText->clearString(); // clear debug text - } - - /* - * NOTE: the logic for whether or not each of the values below - * controls muting MUST match that in the isVisuallyMuted and isTooComplex methods. - */ - - static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0); - info_line = llformat("%d Complexity", mVisualComplexity); - - if (max_render_cost != 0) // zero means don't care, so don't bother coloring based on this - { - green_level = 1.f-llclamp(((F32) mVisualComplexity-(F32)max_render_cost)/(F32)max_render_cost, 0.f, 1.f); - red_level = llmin((F32) mVisualComplexity/(F32)max_render_cost, 1.f); - info_color.set(red_level, green_level, 0.0, 1.0); - info_style = ( mVisualComplexity > max_render_cost - ? LLFontGL::BOLD : LLFontGL::NORMAL ); - } - else - { - info_color.set(LLColor4::grey); - info_style = LLFontGL::NORMAL; - } - mText->addLine(info_line, info_color, info_style); - - // Visual rank - info_line = llformat("%d rank", mVisibilityRank); - // Use grey for imposters, white for normal rendering or no impostors - info_color.set(isImpostor() ? LLColor4::grey : (isControlAvatar() ? LLColor4::yellow : LLColor4::white)); - info_style = LLFontGL::NORMAL; - mText->addLine(info_line, info_color, info_style); + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO)) + { + std::string info_line; + F32 red_level; + F32 green_level; + LLColor4 info_color; + LLFontGL::StyleFlags info_style; + + if ( !mText ) + { + initHudText(); + mText->setFadeDistance(20.0, 5.0); // limit clutter in large crowds + } + else + { + mText->clearString(); // clear debug text + } + + /* + * NOTE: the logic for whether or not each of the values below + * controls muting MUST match that in the isVisuallyMuted and isTooComplex methods. + */ + + static LLCachedControl max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0); + info_line = llformat("%d Complexity", mVisualComplexity); + + if (max_render_cost != 0) // zero means don't care, so don't bother coloring based on this + { + green_level = 1.f-llclamp(((F32) mVisualComplexity-(F32)max_render_cost)/(F32)max_render_cost, 0.f, 1.f); + red_level = llmin((F32) mVisualComplexity/(F32)max_render_cost, 1.f); + info_color.set(red_level, green_level, 0.0, 1.0); + info_style = ( mVisualComplexity > max_render_cost + ? LLFontGL::BOLD : LLFontGL::NORMAL ); + } + else + { + info_color.set(LLColor4::grey); + info_style = LLFontGL::NORMAL; + } + mText->addLine(info_line, info_color, info_style); + + // Visual rank + info_line = llformat("%d rank", mVisibilityRank); + // Use grey for imposters, white for normal rendering or no impostors + info_color.set(isImpostor() ? LLColor4::grey : (isControlAvatar() ? LLColor4::yellow : LLColor4::white)); + info_style = LLFontGL::NORMAL; + mText->addLine(info_line, info_color, info_style); // Triangle count - mText->addLine(std::string("VisTris ") + LLStringOps::getReadableNumber(mAttachmentVisibleTriangleCount), + mText->addLine(std::string("VisTris ") + LLStringOps::getReadableNumber(mAttachmentVisibleTriangleCount), info_color, info_style); - mText->addLine(std::string("EstMaxTris ") + LLStringOps::getReadableNumber(mAttachmentEstTriangleCount), + mText->addLine(std::string("EstMaxTris ") + LLStringOps::getReadableNumber(mAttachmentEstTriangleCount), info_color, info_style); - // Attachment Surface Area - static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); - info_line = llformat("%.0f m^2", mAttachmentSurfaceArea); + // Attachment Surface Area + static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f); + info_line = llformat("%.0f m^2", mAttachmentSurfaceArea); - if (max_render_cost != 0 && max_attachment_area != 0) // zero means don't care, so don't bother coloring based on this - { - green_level = 1.f-llclamp((mAttachmentSurfaceArea-max_attachment_area)/max_attachment_area, 0.f, 1.f); - red_level = llmin(mAttachmentSurfaceArea/max_attachment_area, 1.f); - info_color.set(red_level, green_level, 0.0, 1.0); - info_style = ( mAttachmentSurfaceArea > max_attachment_area - ? LLFontGL::BOLD : LLFontGL::NORMAL ); + if (max_render_cost != 0 && max_attachment_area != 0) // zero means don't care, so don't bother coloring based on this + { + green_level = 1.f-llclamp((mAttachmentSurfaceArea-max_attachment_area)/max_attachment_area, 0.f, 1.f); + red_level = llmin(mAttachmentSurfaceArea/max_attachment_area, 1.f); + info_color.set(red_level, green_level, 0.0, 1.0); + info_style = ( mAttachmentSurfaceArea > max_attachment_area + ? LLFontGL::BOLD : LLFontGL::NORMAL ); - } - else - { - info_color.set(LLColor4::grey); - info_style = LLFontGL::NORMAL; - } + } + else + { + info_color.set(LLColor4::grey); + info_style = LLFontGL::NORMAL; + } - mText->addLine(info_line, info_color, info_style); + mText->addLine(info_line, info_color, info_style); - updateText(); // corrects position - } + updateText(); // corrects position + } } void LLVOAvatar::updateVisualComplexity() { - LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL; - // Set the cache time to in the past so it's updated ASAP - mVisualComplexityStale = true; + LL_DEBUGS("AvatarRender") << "avatar " << getID() << " appearance changed" << LL_ENDL; + // Set the cache time to in the past so it's updated ASAP + mVisualComplexityStale = true; } @@ -11042,7 +11042,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() * the official viewer for consideration. *****************************************************************/ if (mVisualComplexityStale) - { + { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; static const U32 COMPLEXITY_BODY_PART_COST = 200; @@ -11053,18 +11053,18 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // Diagnostic list of all textures on our avatar static std::unordered_set all_textures; - U32 cost = VISUAL_COMPLEXITY_UNKNOWN; - LLVOVolume::texture_cost_t textures; - hud_complexity_list_t hud_complexity_list; + U32 cost = VISUAL_COMPLEXITY_UNKNOWN; + LLVOVolume::texture_cost_t textures; + hud_complexity_list_t hud_complexity_list; object_complexity_list_t object_complexity_list; - for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict - = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); - ETextureIndex tex_index = baked_dict->mTextureIndex; - if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) - { + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict + = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); + ETextureIndex tex_index = baked_dict->mTextureIndex; + if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) + { // Same as isTextureVisible(), but doesn't account for isSelf to ensure identical numbers for all avatars if (isIndexLocalTexture(tex_index)) { @@ -11082,14 +11082,14 @@ void LLVOAvatar::calculateUpdateRenderComplexity() cost += COMPLEXITY_BODY_PART_COST; } } - } - } + } + } LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL; mAttachmentVisibleTriangleCount = 0; mAttachmentEstTriangleCount = 0.f; mAttachmentSurfaceArea = 0.f; - + // A standalone animated object needs to be accounted for // using its associated volume. Attached animated objects // will be covered by the subsequent loop over attachments. @@ -11105,20 +11105,20 @@ void LLVOAvatar::calculateUpdateRenderComplexity() } // Account for complexity of all attachments. - for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin(); - attachment_point != mAttachmentPoints.end(); - ++attachment_point) - { - LLViewerJointAttachment* attachment = attachment_point->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { + for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin(); + attachment_point != mAttachmentPoints.end(); + ++attachment_point) + { + LLViewerJointAttachment* attachment = attachment_point->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { LLViewerObject* attached_object = attachment_iter->get(); accountRenderComplexityForObject(attached_object, max_attachment_complexity, textures, cost, hud_complexity_list, object_complexity_list); - } - } + } + } if ( cost != mVisualComplexity ) { @@ -11134,8 +11134,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity() << " reported " << mReportedVisualComplexity << LL_ENDL; } - mVisualComplexity = cost; - mVisualComplexityStale = false; + mVisualComplexity = cost; + mVisualComplexityStale = false; static LLCachedControl show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20); @@ -11149,7 +11149,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() } //schedule an update to ART next frame if needed - if (LLPerfStats::tunables.userAutoTuneEnabled && + if (LLPerfStats::tunables.userAutoTuneEnabled && LLPerfStats::tunables.userFPSTuningStrategy != LLPerfStats::TUNE_SCENE_ONLY && !isVisuallyMuted()) { @@ -11169,7 +11169,7 @@ void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set) { mVisuallyMuteSetting = set; mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 7; + mLastImpostorUpdateReason = 7; LLRenderMuteList::getInstance()->saveVisualMuteSetting(getID(), S32(set)); } @@ -11177,51 +11177,51 @@ void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set) void LLVOAvatar::setOverallAppearanceNormal() { - if (isControlAvatar()) - return; + if (isControlAvatar()) + return; LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); - resetSkeleton(false); + resetSkeleton(false); getJoint("mPelvis")->setPosition(pelvis_pos); - for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) - { - bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); - LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; - if (!is_playing) - { - // Anim was not requested for this av by sim, but may be playing locally - stopMotion(*it); - } - } - mJellyAnims.clear(); + for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) + { + bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); + LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; + if (!is_playing) + { + // Anim was not requested for this av by sim, but may be playing locally + stopMotion(*it); + } + } + mJellyAnims.clear(); - processAnimationStateChanges(); + processAnimationStateChanges(); } void LLVOAvatar::setOverallAppearanceJellyDoll() { - if (isControlAvatar()) - return; - - // stop current animations - { - for ( LLVOAvatar::AnimIterator anim_it= mPlayingAnimations.begin(); - anim_it != mPlayingAnimations.end(); - ++anim_it) - { - { - stopMotion(anim_it->first, TRUE); - } - } - } - processAnimationStateChanges(); - - // Start any needed anims for jellydoll - updateOverallAppearanceAnimations(); - + if (isControlAvatar()) + return; + + // stop current animations + { + for ( LLVOAvatar::AnimIterator anim_it= mPlayingAnimations.begin(); + anim_it != mPlayingAnimations.end(); + ++anim_it) + { + { + stopMotion(anim_it->first, TRUE); + } + } + } + processAnimationStateChanges(); + + // Start any needed anims for jellydoll + updateOverallAppearanceAnimations(); + LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); - resetSkeleton(false); + resetSkeleton(false); getJoint("mPelvis")->setPosition(pelvis_pos); } @@ -11232,114 +11232,114 @@ void LLVOAvatar::setOverallAppearanceInvisible() void LLVOAvatar::updateOverallAppearance() { - AvatarOverallAppearance new_overall = getOverallAppearance(); - if (new_overall != mOverallAppearance) - { - switch (new_overall) - { - case AOA_NORMAL: - setOverallAppearanceNormal(); - break; - case AOA_JELLYDOLL: - setOverallAppearanceJellyDoll(); - break; - case AOA_INVISIBLE: - setOverallAppearanceInvisible(); - break; - } - mOverallAppearance = new_overall; - if (!isSelf()) - { - mNeedsImpostorUpdate = TRUE; - mLastImpostorUpdateReason = 8; - } - updateMeshVisibility(); - } - - // This needs to be done even if overall appearance has not - // changed, since sit/stand status can be different. - updateOverallAppearanceAnimations(); + AvatarOverallAppearance new_overall = getOverallAppearance(); + if (new_overall != mOverallAppearance) + { + switch (new_overall) + { + case AOA_NORMAL: + setOverallAppearanceNormal(); + break; + case AOA_JELLYDOLL: + setOverallAppearanceJellyDoll(); + break; + case AOA_INVISIBLE: + setOverallAppearanceInvisible(); + break; + } + mOverallAppearance = new_overall; + if (!isSelf()) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 8; + } + updateMeshVisibility(); + } + + // This needs to be done even if overall appearance has not + // changed, since sit/stand status can be different. + updateOverallAppearanceAnimations(); } void LLVOAvatar::updateOverallAppearanceAnimations() { - if (isControlAvatar()) - return; - - if (getOverallAppearance() == AOA_JELLYDOLL) - { - LLUUID motion_id; - if (isSitting() && getParent()) // sitting on object - { - motion_id = ANIM_AGENT_SIT_FEMALE; - } - else if (isSitting()) // sitting on ground - { - motion_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED; - } - else // standing - { - motion_id = ANIM_AGENT_STAND; - } - if (mJellyAnims.find(motion_id) == mJellyAnims.end()) - { - for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) - { - bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); - LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; - if (!is_playing) - { - // Anim was not requested for this av by sim, but may be playing locally - stopMotion(*it, TRUE); - } - } - mJellyAnims.clear(); - - startMotion(motion_id); - mJellyAnims.insert(motion_id); - - processAnimationStateChanges(); - } - } + if (isControlAvatar()) + return; + + if (getOverallAppearance() == AOA_JELLYDOLL) + { + LLUUID motion_id; + if (isSitting() && getParent()) // sitting on object + { + motion_id = ANIM_AGENT_SIT_FEMALE; + } + else if (isSitting()) // sitting on ground + { + motion_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED; + } + else // standing + { + motion_id = ANIM_AGENT_STAND; + } + if (mJellyAnims.find(motion_id) == mJellyAnims.end()) + { + for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) + { + bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); + LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; + if (!is_playing) + { + // Anim was not requested for this av by sim, but may be playing locally + stopMotion(*it, TRUE); + } + } + mJellyAnims.clear(); + + startMotion(motion_id); + mJellyAnims.insert(motion_id); + + processAnimationStateChanges(); + } + } } // Based on isVisuallyMuted(), but has 3 possible results. LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - AvatarOverallAppearance result = AOA_NORMAL; - - // Priority order (highest priority first) - // * own avatar is always drawn normally - // * if on the "always draw normally" list, draw them normally - // * if on the "always visually mute" list, show as jellydoll - // * if explicitly muted (blocked), show as invisible - // * check against the render cost and attachment limits - if too complex, show as jellydoll - if (isSelf()) - { - result = AOA_NORMAL; - } - else // !isSelf() - { - if (isInMuteList()) - { - result = AOA_INVISIBLE; - } - else if (mVisuallyMuteSetting == AV_ALWAYS_RENDER) - { - result = AOA_NORMAL; - } - else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) - { // Always want to see this AV as an impostor - result = AOA_JELLYDOLL; - } - else if (isTooComplex() || isTooSlow()) - { - result = AOA_JELLYDOLL; - } - } - - return result; + AvatarOverallAppearance result = AOA_NORMAL; + + // Priority order (highest priority first) + // * own avatar is always drawn normally + // * if on the "always draw normally" list, draw them normally + // * if on the "always visually mute" list, show as jellydoll + // * if explicitly muted (blocked), show as invisible + // * check against the render cost and attachment limits - if too complex, show as jellydoll + if (isSelf()) + { + result = AOA_NORMAL; + } + else // !isSelf() + { + if (isInMuteList()) + { + result = AOA_INVISIBLE; + } + else if (mVisuallyMuteSetting == AV_ALWAYS_RENDER) + { + result = AOA_NORMAL; + } + else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) + { // Always want to see this AV as an impostor + result = AOA_JELLYDOLL; + } + else if (isTooComplex() || isTooSlow()) + { + result = AOA_JELLYDOLL; + } + } + + return result; } void LLVOAvatar::calcMutedAVColor() @@ -11367,7 +11367,7 @@ void LLVOAvatar::calcMutedAVColor() } #ifdef COLORIZE_JELLYDOLLS else if ( mMutedAVColor == LLColor4::white || mMutedAVColor == LLColor4::grey3 || mMutedAVColor == LLColor4::grey4 ) - { + { // select a color based on the first byte of the agents uuid so any muted agent is always the same color F32 color_value = (F32) (av_id.mData[0]); F32 spectrum = (color_value / 256.0); // spectrum is between 0 and 1.f @@ -11383,17 +11383,17 @@ void LLVOAvatar::calcMutedAVColor() F32 fractBetween = spectrum - (F32)(spectrum_index_1); // distance between the two indexes (0-1) new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); - new_color.normalize(); + new_color.normalize(); new_color *= 0.28f; // Tone it down - } + } #endif else { - new_color = LLColor4::grey4; + new_color = LLColor4::grey4; change_msg = " over limit color "; } - if (mMutedAVColor != new_color) + if (mMutedAVColor != new_color) { LL_DEBUGS("AvatarRender") << "avatar "<< av_id << change_msg << std::setprecision(3) << new_color << LL_ENDL; mMutedAVColor = new_color; @@ -11403,40 +11403,40 @@ void LLVOAvatar::calcMutedAVColor() // static BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { - return (index < 0 || index >= TEX_NUM_INDICES) - ? false - : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsLocalTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsLocalTexture; } // static BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { - return (index < 0 || index >= TEX_NUM_INDICES) - ? false - : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsBakedTexture; + return (index < 0 || index >= TEX_NUM_INDICES) + ? false + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const { - std::string line; + std::string line; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); - iter != LLAvatarAppearance::getDictionary()->getTextures().end(); - ++iter) - { - const ETextureIndex index = iter->first; - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - if (texture_dict->mIsBakedTexture) - { - line += texture_dict->mName; - if (isTextureDefined(index)) - { - line += "_baked"; - } - line += " "; - } - } - return line; + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (texture_dict->mIsBakedTexture) + { + line += texture_dict->mName; + if (isTextureDefined(index)) + { + line += "_baked"; + } + line += " "; + } + } + return line; } @@ -11444,7 +11444,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const //virtual S32 LLVOAvatar::getTexImageSize() const { - return TEX_IMAGE_SIZE_OTHER; + return TEX_IMAGE_SIZE_OTHER; } //----------------------------------------------------------------------------- @@ -11453,48 +11453,48 @@ S32 LLVOAvatar::getTexImageSize() const F32 calc_bouncy_animation(F32 x) { - return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; + return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; } //virtual BOOL LLVOAvatar::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index ) const { - if (isIndexLocalTexture(te)) - { - return FALSE; - } - - if( !getImage( te, index ) ) - { - LL_WARNS() << "getImage( " << te << ", " << index << " ) returned 0" << LL_ENDL; - return FALSE; - } + if (isIndexLocalTexture(te)) + { + return FALSE; + } + + if( !getImage( te, index ) ) + { + LL_WARNS() << "getImage( " << te << ", " << index << " ) returned 0" << LL_ENDL; + return FALSE; + } - return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR && - getImage(te, index)->getID() != IMG_DEFAULT); + return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR && + getImage(te, index)->getID() != IMG_DEFAULT); } //virtual BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { - if (isIndexLocalTexture(type)) - { - return isTextureDefined(type, index); - } - else - { - // baked textures can use TE images directly - return ((isTextureDefined(type) || isSelf()) - && (getTEImage(type)->getID() != IMG_INVISIBLE - || LLDrawPoolAlpha::sShowDebugAlpha)); - } + if (isIndexLocalTexture(type)) + { + return isTextureDefined(type, index); + } + else + { + // baked textures can use TE images directly + return ((isTextureDefined(type) || isSelf()) + && (getTEImage(type)->getID() != IMG_INVISIBLE + || LLDrawPoolAlpha::sShowDebugAlpha)); + } } //virtual BOOL LLVOAvatar::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { - // non-self avatars don't have wearables - return FALSE; + // non-self avatars don't have wearables + return FALSE; } void LLVOAvatar::placeProfileQuery() diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 01e030a300..0a13b7d309 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvoavatar.cpp * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -47,7 +47,7 @@ #include "lllocaltextureobject.h" #include "llnotificationsutil.h" #include "llselectmgr.h" -#include "lltoolgrab.h" // for needsRenderBeam +#include "lltoolgrab.h" // for needsRenderBeam #include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" #include "lltrans.h" @@ -80,31 +80,31 @@ LLPointer gAgentAvatarp = NULL; BOOL isAgentAvatarValid() { - return (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()); + return (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()); } void selfStartPhase(const std::string& phase_name) { - if (isAgentAvatarValid()) - { - gAgentAvatarp->startPhase(phase_name); - } + if (isAgentAvatarValid()) + { + gAgentAvatarp->startPhase(phase_name); + } } void selfStopPhase(const std::string& phase_name, bool err_check) { - if (isAgentAvatarValid()) - { - gAgentAvatarp->stopPhase(phase_name, err_check); - } + if (isAgentAvatarValid()) + { + gAgentAvatarp->stopPhase(phase_name, err_check); + } } void selfClearPhases() { - if (isAgentAvatarValid()) - { - gAgentAvatarp->clearPhases(); - } + if (isAgentAvatarValid()) + { + gAgentAvatarp->clearPhases(); + } } using namespace LLAvatarAppearanceDefines; @@ -120,18 +120,18 @@ LLSD summarize_by_buckets(std::vector in_records, std::vector struct LocalTextureData { - LocalTextureData() : - mIsBakedReady(false), - mDiscard(MAX_DISCARD_LEVEL+1), - mImage(NULL), - mWearableID(IMG_DEFAULT_AVATAR), - mTexEntry(NULL) - {} - LLPointer mImage; - bool mIsBakedReady; - S32 mDiscard; - LLUUID mWearableID; // UUID of the wearable that this texture belongs to, not of the image itself - LLTextureEntry *mTexEntry; + LocalTextureData() : + mIsBakedReady(false), + mDiscard(MAX_DISCARD_LEVEL+1), + mImage(NULL), + mWearableID(IMG_DEFAULT_AVATAR), + mTexEntry(NULL) + {} + LLPointer mImage; + bool mIsBakedReady; + S32 mDiscard; + LLUUID mWearableID; // UUID of the wearable that this texture belongs to, not of the image itself + LLTextureEntry *mTexEntry; }; //----------------------------------------------------------------------------- @@ -160,512 +160,512 @@ std::map< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames; **/ LLVOAvatarSelf::LLVOAvatarSelf(const LLUUID& id, - const LLPCode pcode, - LLViewerRegion* regionp) : - LLVOAvatar(id, pcode, regionp), - mScreenp(NULL), - mLastRegionHandle(0), - mRegionCrossingCount(0), - // Value outside legal range, so will always be a mismatch the - // first time through. - mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f)), + const LLPCode pcode, + LLViewerRegion* regionp) : + LLVOAvatar(id, pcode, regionp), + mScreenp(NULL), + mLastRegionHandle(0), + mRegionCrossingCount(0), + // Value outside legal range, so will always be a mismatch the + // first time through. + mLastHoverOffsetSent(LLVector3(0.0f, 0.0f, -999.0f)), mInitialMetric(true), mMetricSequence(0) { - mMotionController.mIsSelf = TRUE; + mMotionController.mIsSelf = TRUE; - LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL; + LL_DEBUGS() << "Marking avatar as self " << id << LL_ENDL; } // Called periodically for diagnostics, return true when done. bool output_self_av_texture_diagnostics() { - if (!isAgentAvatarValid()) - return true; // done checking + if (!isAgentAvatarValid()) + return true; // done checking - gAgentAvatarp->outputRezDiagnostics(); + gAgentAvatarp->outputRezDiagnostics(); - return false; + return false; } bool update_avatar_rez_metrics() { - if (!isAgentAvatarValid()) - return true; - - gAgentAvatarp->updateAvatarRezMetrics(false); + if (!isAgentAvatarValid()) + return true; - return false; + gAgentAvatarp->updateAvatarRezMetrics(false); + + return false; } void LLVOAvatarSelf::initInstance() { - BOOL status = TRUE; - // creates hud joint(mScreen) among other things - status &= loadAvatarSelf(); - - // adds attachment points to mScreen among other things - LLVOAvatar::initInstance(); - - LL_INFOS() << "Self avatar object created. Starting timer." << LL_ENDL; - mDebugSelfLoadTimer.reset(); - // clear all times to -1 for debugging - for (U32 i =0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) - { - for (U32 j = 0; j <= MAX_DISCARD_LEVEL; ++j) - { - mDebugTextureLoadTimes[i][j] = -1.0f; - } - } - - for (U32 i =0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) - { - mDebugBakedTextureTimes[i][0] = -1.0f; - mDebugBakedTextureTimes[i][1] = -1.0f; - } - - status &= buildMenus(); - if (!status) - { - LL_ERRS() << "Unable to load user's avatar" << LL_ENDL; - return; - } - - setHoverIfRegionEnabled(); - - //doPeriodically(output_self_av_texture_diagnostics, 30.0); - doPeriodically(update_avatar_rez_metrics, 5.0); - doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0); + BOOL status = TRUE; + // creates hud joint(mScreen) among other things + status &= loadAvatarSelf(); + + // adds attachment points to mScreen among other things + LLVOAvatar::initInstance(); + + LL_INFOS() << "Self avatar object created. Starting timer." << LL_ENDL; + mDebugSelfLoadTimer.reset(); + // clear all times to -1 for debugging + for (U32 i =0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) + { + for (U32 j = 0; j <= MAX_DISCARD_LEVEL; ++j) + { + mDebugTextureLoadTimes[i][j] = -1.0f; + } + } + + for (U32 i =0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) + { + mDebugBakedTextureTimes[i][0] = -1.0f; + mDebugBakedTextureTimes[i][1] = -1.0f; + } + + status &= buildMenus(); + if (!status) + { + LL_ERRS() << "Unable to load user's avatar" << LL_ENDL; + return; + } + + setHoverIfRegionEnabled(); + + //doPeriodically(output_self_av_texture_diagnostics, 30.0); + doPeriodically(update_avatar_rez_metrics, 5.0); + doPeriodically(boost::bind(&LLVOAvatarSelf::checkStuckAppearance, this), 30.0); mInitFlags |= 1<<2; } void LLVOAvatarSelf::setHoverIfRegionEnabled() { - if (getRegion() && getRegion()->simulatorFeaturesReceived()) - { - if (getRegion()->avatarHoverHeightEnabled()) - { - F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ"); - setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z))); - LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << hover_z << LL_ENDL; - } - else - { - setHoverOffset(LLVector3(0.0, 0.0, 0.0)); - LL_INFOS("Avatar") << avString() << " zeroing hover height, region does not support" << LL_ENDL; - } - } - else - { - LL_INFOS("Avatar") << avString() << " region or simulator features not known, no change on hover" << LL_ENDL; - if (getRegion()) - { - getRegion()->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1)); - } - - } + if (getRegion() && getRegion()->simulatorFeaturesReceived()) + { + if (getRegion()->avatarHoverHeightEnabled()) + { + F32 hover_z = gSavedPerAccountSettings.getF32("AvatarHoverOffsetZ"); + setHoverOffset(LLVector3(0.0, 0.0, llclamp(hover_z,MIN_HOVER_Z,MAX_HOVER_Z))); + LL_INFOS("Avatar") << avString() << " set hover height from debug setting " << hover_z << LL_ENDL; + } + else + { + setHoverOffset(LLVector3(0.0, 0.0, 0.0)); + LL_INFOS("Avatar") << avString() << " zeroing hover height, region does not support" << LL_ENDL; + } + } + else + { + LL_INFOS("Avatar") << avString() << " region or simulator features not known, no change on hover" << LL_ENDL; + if (getRegion()) + { + getRegion()->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1)); + } + + } } bool LLVOAvatarSelf::checkStuckAppearance() { - const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0; - const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0; - - if (gAgentWearables.isCOFChangeInProgress()) - { - LL_DEBUGS("Avatar") << "checking for stuck appearance" << LL_ENDL; - F32 change_time = gAgentWearables.getCOFChangeTime(); - LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << LL_ENDL; - S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns(); - LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << LL_ENDL; - S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations(); - LL_DEBUGS("Avatar") << "active copy operations " << active_copies << LL_ENDL; - - if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) || - (change_time > UNCONDITIONAL_UNSTICK_INTERVAL)) - { - gAgentWearables.notifyLoadingFinished(); - } - } - - // Return false to continue running check periodically. - return LLApp::isExiting(); + const F32 CONDITIONAL_UNSTICK_INTERVAL = 300.0; + const F32 UNCONDITIONAL_UNSTICK_INTERVAL = 600.0; + + if (gAgentWearables.isCOFChangeInProgress()) + { + LL_DEBUGS("Avatar") << "checking for stuck appearance" << LL_ENDL; + F32 change_time = gAgentWearables.getCOFChangeTime(); + LL_DEBUGS("Avatar") << "change in progress for " << change_time << " seconds" << LL_ENDL; + S32 active_hp = LLAppearanceMgr::instance().countActiveHoldingPatterns(); + LL_DEBUGS("Avatar") << "active holding patterns " << active_hp << " seconds" << LL_ENDL; + S32 active_copies = LLAppearanceMgr::instance().getActiveCopyOperations(); + LL_DEBUGS("Avatar") << "active copy operations " << active_copies << LL_ENDL; + + if ((change_time > CONDITIONAL_UNSTICK_INTERVAL && active_copies == 0) || + (change_time > UNCONDITIONAL_UNSTICK_INTERVAL)) + { + gAgentWearables.notifyLoadingFinished(); + } + } + + // Return false to continue running check periodically. + return LLApp::isExiting(); } // virtual void LLVOAvatarSelf::markDead() { - mBeam = NULL; - LLVOAvatar::markDead(); + mBeam = NULL; + LLVOAvatar::markDead(); } /*virtual*/ BOOL LLVOAvatarSelf::loadAvatar() { - BOOL success = LLVOAvatar::loadAvatar(); + BOOL success = LLVOAvatar::loadAvatar(); - // set all parameters stored directly in the avatar to have - // the isSelfParam to be TRUE - this is used to prevent - // them from being animated or trigger accidental rebakes - // when we copy params from the wearable to the base avatar. - for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) getNextVisualParam()) - { - if (param->getWearableType() != LLWearableType::WT_INVALID) - { - param->setIsDummy(TRUE); - } - } + // set all parameters stored directly in the avatar to have + // the isSelfParam to be TRUE - this is used to prevent + // them from being animated or trigger accidental rebakes + // when we copy params from the wearable to the base avatar. + for (LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) getNextVisualParam()) + { + if (param->getWearableType() != LLWearableType::WT_INVALID) + { + param->setIsDummy(TRUE); + } + } - return success; + return success; } BOOL LLVOAvatarSelf::loadAvatarSelf() { - BOOL success = TRUE; - // avatar_skeleton.xml - if (!buildSkeletonSelf(sAvatarSkeletonInfo)) - { - LL_WARNS() << "avatar file: buildSkeleton() failed" << LL_ENDL; - return FALSE; - } + BOOL success = TRUE; + // avatar_skeleton.xml + if (!buildSkeletonSelf(sAvatarSkeletonInfo)) + { + LL_WARNS() << "avatar file: buildSkeleton() failed" << LL_ENDL; + return FALSE; + } - return success; + return success; } BOOL LLVOAvatarSelf::buildSkeletonSelf(const LLAvatarSkeletonInfo *info) { - // add special-purpose "screen" joint - mScreenp = new LLViewerJoint("mScreen", NULL); - // for now, put screen at origin, as it is only used during special - // HUD rendering mode - F32 aspect = LLViewerCamera::getInstance()->getAspect(); - LLVector3 scale(1.f, aspect, 1.f); - mScreenp->setScale(scale); - // SL-315 - mScreenp->setWorldPosition(LLVector3::zero); - // need to update screen agressively when sidebar opens/closes, for example - mScreenp->mUpdateXform = TRUE; - return TRUE; + // add special-purpose "screen" joint + mScreenp = new LLViewerJoint("mScreen", NULL); + // for now, put screen at origin, as it is only used during special + // HUD rendering mode + F32 aspect = LLViewerCamera::getInstance()->getAspect(); + LLVector3 scale(1.f, aspect, 1.f); + mScreenp->setScale(scale); + // SL-315 + mScreenp->setWorldPosition(LLVector3::zero); + // need to update screen agressively when sidebar opens/closes, for example + mScreenp->mUpdateXform = TRUE; + return TRUE; } BOOL LLVOAvatarSelf::buildMenus() { - //------------------------------------------------------------------------- - // build the attach and detach menus - //------------------------------------------------------------------------- - gAttachBodyPartPieMenus[0] = NULL; - - LLContextMenu::Params params; - params.label(LLTrans::getString("BodyPartsRightArm")); - params.name(params.label); - params.visible(false); - gAttachBodyPartPieMenus[1] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsHead")); - params.name(params.label); - gAttachBodyPartPieMenus[2] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsLeftArm")); - params.name(params.label); - gAttachBodyPartPieMenus[3] = LLUICtrlFactory::create (params); - - gAttachBodyPartPieMenus[4] = NULL; - - params.label(LLTrans::getString("BodyPartsLeftLeg")); - params.name(params.label); - gAttachBodyPartPieMenus[5] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsTorso")); - params.name(params.label); - gAttachBodyPartPieMenus[6] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsRightLeg")); - params.name(params.label); - gAttachBodyPartPieMenus[7] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsEnhancedSkeleton")); - params.name(params.label); - gAttachBodyPartPieMenus[8] = LLUICtrlFactory::create(params); - - gDetachBodyPartPieMenus[0] = NULL; - - params.label(LLTrans::getString("BodyPartsRightArm")); - params.name(params.label); - gDetachBodyPartPieMenus[1] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsHead")); - params.name(params.label); - gDetachBodyPartPieMenus[2] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsLeftArm")); - params.name(params.label); - gDetachBodyPartPieMenus[3] = LLUICtrlFactory::create (params); - - gDetachBodyPartPieMenus[4] = NULL; - - params.label(LLTrans::getString("BodyPartsLeftLeg")); - params.name(params.label); - gDetachBodyPartPieMenus[5] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsTorso")); - params.name(params.label); - gDetachBodyPartPieMenus[6] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsRightLeg")); - params.name(params.label); - gDetachBodyPartPieMenus[7] = LLUICtrlFactory::create (params); - - params.label(LLTrans::getString("BodyPartsEnhancedSkeleton")); - params.name(params.label); - gDetachBodyPartPieMenus[8] = LLUICtrlFactory::create(params); - - for (S32 i = 0; i < 9; i++) - { - if (gAttachBodyPartPieMenus[i]) - { - gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] ); - } - else - { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment && attachment->getGroup() == i) - { - LLMenuItemCallGL::Params item_params; - - std::string sub_piemenu_name = attachment->getName(); - if (LLTrans::getString(sub_piemenu_name) != "") - { - item_params.label = LLTrans::getString(sub_piemenu_name); - } - else - { - item_params.label = sub_piemenu_name; - } - item_params.name =(item_params.label ); - item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = iter->first; - LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); - - gAttachPieMenu->addChild(item); - - break; - - } - } - } - - if (gDetachBodyPartPieMenus[i]) - { - gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); - gDetachAttSelfMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); - gDetachAvatarMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); - } - else - { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment && attachment->getGroup() == i) - { - LLMenuItemCallGL::Params item_params; - std::string sub_piemenu_name = attachment->getName(); - if (LLTrans::getString(sub_piemenu_name) != "") - { - item_params.label = LLTrans::getString(sub_piemenu_name); - } - else - { - item_params.label = sub_piemenu_name; - } - item_params.name =(item_params.label ); - item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = iter->first; - LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); - - gDetachPieMenu->addChild(item); - gDetachAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); - gDetachAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); - break; - } - } - } - } - - - // add screen attachments - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getGroup() == 9) - { - LLMenuItemCallGL::Params item_params; - std::string sub_piemenu_name = attachment->getName(); - if (LLTrans::getString(sub_piemenu_name) != "") - { - item_params.label = LLTrans::getString(sub_piemenu_name); - } - else - { - item_params.label = sub_piemenu_name; - } - item_params.name =(item_params.label ); - item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = iter->first; - LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); - gAttachScreenPieMenu->addChild(item); - - item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = iter->first; - item = LLUICtrlFactory::create(item_params); - gDetachScreenPieMenu->addChild(item); - gDetachHUDAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); - gDetachHUDAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); - } - } - - for (S32 pass = 0; pass < 2; pass++) - { - // *TODO: Skinning - gAttachSubMenu is an awful, awful hack - if (!gAttachSubMenu) - { - break; - } - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getIsHUDAttachment() != (pass == 1)) - { - continue; - } - LLMenuItemCallGL::Params item_params; - std::string sub_piemenu_name = attachment->getName(); - if (LLTrans::getString(sub_piemenu_name) != "") - { - item_params.label = LLTrans::getString(sub_piemenu_name); - } - else - { - item_params.label = sub_piemenu_name; - } - item_params.name =(item_params.label ); - item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = iter->first; - //* TODO: Skinning: - //LLSD params; - //params["index"] = iter->first; - //params["label"] = attachment->getName(); - //item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); - - LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); - gAttachSubMenu->addChild(item); - - item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = iter->first; - item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = iter->first; - //* TODO: Skinning: item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); - - item = LLUICtrlFactory::create(item_params); - gDetachSubMenu->addChild(item); - } - if (pass == 0) - { - // put separator between non-hud and hud attachments - gAttachSubMenu->addSeparator(); - gDetachSubMenu->addSeparator(); - } - } - - for (S32 group = 0; group < 9; group++) - { - // skip over groups that don't have sub menus - if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group]) - { - continue; - } - - std::multimap attachment_pie_menu_map; - - // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if(attachment && attachment->getGroup() == group) - { - // use multimap to provide a partial order off of the pie slice key - S32 pie_index = attachment->getPieSlice(); - attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first)); - } - } - - // add in requested order to pie menu, inserting separators as necessary - for (std::multimap::iterator attach_it = attachment_pie_menu_map.begin(); - attach_it != attachment_pie_menu_map.end(); ++attach_it) - { - S32 attach_index = attach_it->second; - - LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); - if (attachment) - { - LLMenuItemCallGL::Params item_params; - item_params.name = attachment->getName(); - item_params.label = LLTrans::getString(attachment->getName()); - item_params.on_click.function_name = "Object.AttachToAvatar"; - item_params.on_click.parameter = attach_index; - item_params.on_enable.function_name = "Object.EnableWear"; - item_params.on_enable.parameter = attach_index; - - LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); - gAttachBodyPartPieMenus[group]->addChild(item); - - item_params.on_click.function_name = "Attachment.DetachFromPoint"; - item_params.on_click.parameter = attach_index; - item_params.on_enable.function_name = "Attachment.PointFilled"; - item_params.on_enable.parameter = attach_index; - item = LLUICtrlFactory::create(item_params); - gDetachBodyPartPieMenus[group]->addChild(item); - } - } - } - return TRUE; + //------------------------------------------------------------------------- + // build the attach and detach menus + //------------------------------------------------------------------------- + gAttachBodyPartPieMenus[0] = NULL; + + LLContextMenu::Params params; + params.label(LLTrans::getString("BodyPartsRightArm")); + params.name(params.label); + params.visible(false); + gAttachBodyPartPieMenus[1] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsHead")); + params.name(params.label); + gAttachBodyPartPieMenus[2] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsLeftArm")); + params.name(params.label); + gAttachBodyPartPieMenus[3] = LLUICtrlFactory::create (params); + + gAttachBodyPartPieMenus[4] = NULL; + + params.label(LLTrans::getString("BodyPartsLeftLeg")); + params.name(params.label); + gAttachBodyPartPieMenus[5] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsTorso")); + params.name(params.label); + gAttachBodyPartPieMenus[6] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsRightLeg")); + params.name(params.label); + gAttachBodyPartPieMenus[7] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsEnhancedSkeleton")); + params.name(params.label); + gAttachBodyPartPieMenus[8] = LLUICtrlFactory::create(params); + + gDetachBodyPartPieMenus[0] = NULL; + + params.label(LLTrans::getString("BodyPartsRightArm")); + params.name(params.label); + gDetachBodyPartPieMenus[1] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsHead")); + params.name(params.label); + gDetachBodyPartPieMenus[2] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsLeftArm")); + params.name(params.label); + gDetachBodyPartPieMenus[3] = LLUICtrlFactory::create (params); + + gDetachBodyPartPieMenus[4] = NULL; + + params.label(LLTrans::getString("BodyPartsLeftLeg")); + params.name(params.label); + gDetachBodyPartPieMenus[5] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsTorso")); + params.name(params.label); + gDetachBodyPartPieMenus[6] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsRightLeg")); + params.name(params.label); + gDetachBodyPartPieMenus[7] = LLUICtrlFactory::create (params); + + params.label(LLTrans::getString("BodyPartsEnhancedSkeleton")); + params.name(params.label); + gDetachBodyPartPieMenus[8] = LLUICtrlFactory::create(params); + + for (S32 i = 0; i < 9; i++) + { + if (gAttachBodyPartPieMenus[i]) + { + gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] ); + } + else + { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment && attachment->getGroup() == i) + { + LLMenuItemCallGL::Params item_params; + + std::string sub_piemenu_name = attachment->getName(); + if (LLTrans::getString(sub_piemenu_name) != "") + { + item_params.label = LLTrans::getString(sub_piemenu_name); + } + else + { + item_params.label = sub_piemenu_name; + } + item_params.name =(item_params.label ); + item_params.on_click.function_name = "Object.AttachToAvatar"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Object.EnableWear"; + item_params.on_enable.parameter = iter->first; + LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); + + gAttachPieMenu->addChild(item); + + break; + + } + } + } + + if (gDetachBodyPartPieMenus[i]) + { + gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); + gDetachAttSelfMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); + gDetachAvatarMenu->appendContextSubMenu(gDetachBodyPartPieMenus[i]); + } + else + { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment && attachment->getGroup() == i) + { + LLMenuItemCallGL::Params item_params; + std::string sub_piemenu_name = attachment->getName(); + if (LLTrans::getString(sub_piemenu_name) != "") + { + item_params.label = LLTrans::getString(sub_piemenu_name); + } + else + { + item_params.label = sub_piemenu_name; + } + item_params.name =(item_params.label ); + item_params.on_click.function_name = "Attachment.DetachFromPoint"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Attachment.PointFilled"; + item_params.on_enable.parameter = iter->first; + LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); + + gDetachPieMenu->addChild(item); + gDetachAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); + gDetachAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); + break; + } + } + } + } + + + // add screen attachments + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getGroup() == 9) + { + LLMenuItemCallGL::Params item_params; + std::string sub_piemenu_name = attachment->getName(); + if (LLTrans::getString(sub_piemenu_name) != "") + { + item_params.label = LLTrans::getString(sub_piemenu_name); + } + else + { + item_params.label = sub_piemenu_name; + } + item_params.name =(item_params.label ); + item_params.on_click.function_name = "Object.AttachToAvatar"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Object.EnableWear"; + item_params.on_enable.parameter = iter->first; + LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); + gAttachScreenPieMenu->addChild(item); + + item_params.on_click.function_name = "Attachment.DetachFromPoint"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Attachment.PointFilled"; + item_params.on_enable.parameter = iter->first; + item = LLUICtrlFactory::create(item_params); + gDetachScreenPieMenu->addChild(item); + gDetachHUDAttSelfMenu->addChild(LLUICtrlFactory::create(item_params)); + gDetachHUDAvatarMenu->addChild(LLUICtrlFactory::create(item_params)); + } + } + + for (S32 pass = 0; pass < 2; pass++) + { + // *TODO: Skinning - gAttachSubMenu is an awful, awful hack + if (!gAttachSubMenu) + { + break; + } + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment() != (pass == 1)) + { + continue; + } + LLMenuItemCallGL::Params item_params; + std::string sub_piemenu_name = attachment->getName(); + if (LLTrans::getString(sub_piemenu_name) != "") + { + item_params.label = LLTrans::getString(sub_piemenu_name); + } + else + { + item_params.label = sub_piemenu_name; + } + item_params.name =(item_params.label ); + item_params.on_click.function_name = "Object.AttachToAvatar"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Object.EnableWear"; + item_params.on_enable.parameter = iter->first; + //* TODO: Skinning: + //LLSD params; + //params["index"] = iter->first; + //params["label"] = attachment->getName(); + //item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); + + LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); + gAttachSubMenu->addChild(item); + + item_params.on_click.function_name = "Attachment.DetachFromPoint"; + item_params.on_click.parameter = iter->first; + item_params.on_enable.function_name = "Attachment.PointFilled"; + item_params.on_enable.parameter = iter->first; + //* TODO: Skinning: item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params)); + + item = LLUICtrlFactory::create(item_params); + gDetachSubMenu->addChild(item); + } + if (pass == 0) + { + // put separator between non-hud and hud attachments + gAttachSubMenu->addSeparator(); + gDetachSubMenu->addSeparator(); + } + } + + for (S32 group = 0; group < 9; group++) + { + // skip over groups that don't have sub menus + if (!gAttachBodyPartPieMenus[group] || !gDetachBodyPartPieMenus[group]) + { + continue; + } + + std::multimap attachment_pie_menu_map; + + // gather up all attachment points assigned to this group, and throw into map sorted by pie slice number + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if(attachment && attachment->getGroup() == group) + { + // use multimap to provide a partial order off of the pie slice key + S32 pie_index = attachment->getPieSlice(); + attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first)); + } + } + + // add in requested order to pie menu, inserting separators as necessary + for (std::multimap::iterator attach_it = attachment_pie_menu_map.begin(); + attach_it != attachment_pie_menu_map.end(); ++attach_it) + { + S32 attach_index = attach_it->second; + + LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); + if (attachment) + { + LLMenuItemCallGL::Params item_params; + item_params.name = attachment->getName(); + item_params.label = LLTrans::getString(attachment->getName()); + item_params.on_click.function_name = "Object.AttachToAvatar"; + item_params.on_click.parameter = attach_index; + item_params.on_enable.function_name = "Object.EnableWear"; + item_params.on_enable.parameter = attach_index; + + LLMenuItemCallGL* item = LLUICtrlFactory::create(item_params); + gAttachBodyPartPieMenus[group]->addChild(item); + + item_params.on_click.function_name = "Attachment.DetachFromPoint"; + item_params.on_click.parameter = attach_index; + item_params.on_enable.function_name = "Attachment.PointFilled"; + item_params.on_enable.parameter = attach_index; + item = LLUICtrlFactory::create(item_params); + gDetachBodyPartPieMenus[group]->addChild(item); + } + } + } + return TRUE; } void LLVOAvatarSelf::cleanup() { - markDead(); - delete mScreenp; - mScreenp = NULL; - mRegionp = NULL; + markDead(); + delete mScreenp; + mScreenp = NULL; + mRegionp = NULL; } LLVOAvatarSelf::~LLVOAvatarSelf() { - cleanup(); + cleanup(); } /** @@ -677,33 +677,33 @@ LLVOAvatarSelf::~LLVOAvatarSelf() // virtual bool LLVOAvatarSelf::updateCharacter(LLAgent &agent) { - // update screen joint size - if (mScreenp) - { - F32 aspect = LLViewerCamera::getInstance()->getAspect(); - LLVector3 scale(1.f, aspect, 1.f); - mScreenp->setScale(scale); - mScreenp->updateWorldMatrixChildren(); - resetHUDAttachments(); - } - - return LLVOAvatar::updateCharacter(agent); + // update screen joint size + if (mScreenp) + { + F32 aspect = LLViewerCamera::getInstance()->getAspect(); + LLVector3 scale(1.f, aspect, 1.f); + mScreenp->setScale(scale); + mScreenp->updateWorldMatrixChildren(); + resetHUDAttachments(); + } + + return LLVOAvatar::updateCharacter(agent); } // virtual BOOL LLVOAvatarSelf::isValid() const { - return ((getRegion() != NULL) && !isDead()); + return ((getRegion() != NULL) && !isDead()); } // virtual void LLVOAvatarSelf::idleUpdate(LLAgent &agent, const F64 &time) { - if (isValid()) - { - LLVOAvatar::idleUpdate(agent, time); - idleUpdateTractorBeam(); - } + if (isValid()) + { + LLVOAvatar::idleUpdate(agent, time); + idleUpdateTractorBeam(); + } } // virtual @@ -711,14 +711,14 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) { LLJoint *jointp = NULL; jointp = LLVOAvatar::getJoint(name); - if (!jointp && mScreenp) - { - jointp = mScreenp->findJoint(name); + if (!jointp && mScreenp) + { + jointp = mScreenp->findJoint(name); if (jointp) { mJointMap[name] = jointp; } - } + } if (jointp && jointp != mScreenp && jointp != mRoot) { llassert(LLVOAvatar::getJoint((S32)jointp->getJointNum())==jointp); @@ -729,238 +729,238 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) // virtual BOOL LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight) { - if (!which_param) - { - return FALSE; - } - LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID()); - return setParamWeight(param,weight); + if (!which_param) + { + return FALSE; + } + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID()); + return setParamWeight(param,weight); } // virtual BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight) { - if (!param_name) - { - return FALSE; - } - LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name); - return setParamWeight(param,weight); + if (!param_name) + { + return FALSE; + } + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name); + return setParamWeight(param,weight); } // virtual BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight) { - LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index); - return setParamWeight(param,weight); + LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index); + return setParamWeight(param,weight); } BOOL LLVOAvatarSelf::setParamWeight(const LLViewerVisualParam *param, F32 weight) { - if (!param) - { - return FALSE; - } - - if (param->getCrossWearable()) - { - LLWearableType::EType type = (LLWearableType::EType)param->getWearableType(); - U32 size = gAgentWearables.getWearableCount(type); - for (U32 count = 0; count < size; ++count) - { - LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count); - if (wearable) - { - wearable->setVisualParamWeight(param->getID(), weight); - } - } - } - - return LLCharacter::setVisualParamWeight(param,weight); -} - -/*virtual*/ + if (!param) + { + return FALSE; + } + + if (param->getCrossWearable()) + { + LLWearableType::EType type = (LLWearableType::EType)param->getWearableType(); + U32 size = gAgentWearables.getWearableCount(type); + for (U32 count = 0; count < size; ++count) + { + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(type,count); + if (wearable) + { + wearable->setVisualParamWeight(param->getID(), weight); + } + } + } + + return LLCharacter::setVisualParamWeight(param,weight); +} + +/*virtual*/ void LLVOAvatarSelf::updateVisualParams() { - LLVOAvatar::updateVisualParams(); + LLVOAvatar::updateVisualParams(); } void LLVOAvatarSelf::writeWearablesToAvatar() { - for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) - { - LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); - if (wearable) - { - wearable->writeToAvatar(this); - } - } + for (U32 type = 0; type < LLWearableType::WT_COUNT; type++) + { + LLWearable *wearable = gAgentWearables.getTopWearable((LLWearableType::EType)type); + if (wearable) + { + wearable->writeToAvatar(this); + } + } } /*virtual*/ void LLVOAvatarSelf::idleUpdateAppearanceAnimation() { - // Animate all top-level wearable visual parameters - gAgentWearables.animateAllWearableParams(calcMorphAmount()); + // Animate all top-level wearable visual parameters + gAgentWearables.animateAllWearableParams(calcMorphAmount()); - // Apply wearable visual params to avatar - writeWearablesToAvatar(); + // Apply wearable visual params to avatar + writeWearablesToAvatar(); - //allow avatar to process updates - LLVOAvatar::idleUpdateAppearanceAnimation(); + //allow avatar to process updates + LLVOAvatar::idleUpdateAppearanceAnimation(); } // virtual void LLVOAvatarSelf::requestStopMotion(LLMotion* motion) { - // Only agent avatars should handle the stop motion notifications. + // Only agent avatars should handle the stop motion notifications. - // Notify agent that motion has stopped - gAgent.requestStopMotion(motion); + // Notify agent that motion has stopped + gAgent.requestStopMotion(motion); } // virtual bool LLVOAvatarSelf::hasMotionFromSource(const LLUUID& source_id) { - AnimSourceIterator motion_it = mAnimationSources.find(source_id); - return motion_it != mAnimationSources.end(); + AnimSourceIterator motion_it = mAnimationSources.find(source_id); + return motion_it != mAnimationSources.end(); } // virtual void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) { - for (AnimSourceIterator motion_it = mAnimationSources.find(source_id); motion_it != mAnimationSources.end(); ) - { - gAgent.sendAnimationRequest(motion_it->second, ANIM_REQUEST_STOP); - mAnimationSources.erase(motion_it); - // Must find() after each erase() to deal with potential iterator invalidation - // This also ensures that we don't go past the end of this source's animations - // into those of another source. - motion_it = mAnimationSources.find(source_id); - } + for (AnimSourceIterator motion_it = mAnimationSources.find(source_id); motion_it != mAnimationSources.end(); ) + { + gAgent.sendAnimationRequest(motion_it->second, ANIM_REQUEST_STOP); + mAnimationSources.erase(motion_it); + // Must find() after each erase() to deal with potential iterator invalidation + // This also ensures that we don't go past the end of this source's animations + // into those of another source. + motion_it = mAnimationSources.find(source_id); + } - LLViewerObject* object = gObjectList.findObject(source_id); - if (object) - { - object->setFlagsWithoutUpdate(FLAGS_ANIM_SOURCE, FALSE); - } + LLViewerObject* object = gObjectList.findObject(source_id); + if (object) + { + object->setFlagsWithoutUpdate(FLAGS_ANIM_SOURCE, FALSE); + } } void LLVOAvatarSelf::setLocalTextureTE(U8 te, LLViewerTexture* image, U32 index) { - if (te >= TEX_NUM_INDICES) - { - llassert(0); - return; - } + if (te >= TEX_NUM_INDICES) + { + llassert(0); + return; + } - if (getTEImage(te)->getID() == image->getID()) - { - return; - } + if (getTEImage(te)->getID() == image->getID()) + { + return; + } - if (isIndexBakedTexture((ETextureIndex)te)) - { - llassert(0); - return; - } + if (isIndexBakedTexture((ETextureIndex)te)) + { + llassert(0); + return; + } - setTEImage(te, image); + setTEImage(te, image); } //virtual void LLVOAvatarSelf::removeMissingBakedTextures() -{ - BOOL removed = FALSE; - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - const S32 te = mBakedTextureDatas[i].mTextureIndex; - const LLViewerTexture* tex = getTEImage(te); - - // Replace with default if we can't find the asset, assuming the - // default is actually valid (which it should be unless something - // is seriously wrong). - if (!tex || tex->isMissingAsset()) - { - LLViewerTexture *imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); - if (imagep && imagep != tex) - { - setTEImage(te, imagep); - removed = TRUE; - } - } - } - - if (removed) - { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - LLViewerTexLayerSet *layerset = getTexLayerSet(i); - layerset->setUpdatesEnabled(TRUE); - invalidateComposite(layerset); - } - updateMeshTextures(); - } +{ + BOOL removed = FALSE; + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const S32 te = mBakedTextureDatas[i].mTextureIndex; + const LLViewerTexture* tex = getTEImage(te); + + // Replace with default if we can't find the asset, assuming the + // default is actually valid (which it should be unless something + // is seriously wrong). + if (!tex || tex->isMissingAsset()) + { + LLViewerTexture *imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); + if (imagep && imagep != tex) + { + setTEImage(te, imagep); + removed = TRUE; + } + } + } + + if (removed) + { + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + layerset->setUpdatesEnabled(TRUE); + invalidateComposite(layerset); + } + updateMeshTextures(); + } } void LLVOAvatarSelf::onSimulatorFeaturesReceived(const LLUUID& region_id) { - LL_INFOS("Avatar") << "simulator features received, setting hover based on region props" << LL_ENDL; - setHoverIfRegionEnabled(); + LL_INFOS("Avatar") << "simulator features received, setting hover based on region props" << LL_ENDL; + setHoverIfRegionEnabled(); } //virtual void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) { - // Save the global position - LLVector3d global_pos_from_old_region = getPositionGlobal(); - - // Change the region - setRegion(regionp); - - if (regionp) - { // Set correct region-relative position from global coordinates - setPositionGlobal(global_pos_from_old_region); - - // Diagnostic info - //LLVector3d pos_from_new_region = getPositionGlobal(); - //LL_INFOS() << "pos_from_old_region is " << global_pos_from_old_region - // << " while pos_from_new_region is " << pos_from_new_region - // << LL_ENDL; - - // Update hover height, or schedule callback, based on whether - // it's supported in this region. - if (regionp->simulatorFeaturesReceived()) - { - setHoverIfRegionEnabled(); - } - else - { - regionp->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1)); - } - } - - if (!regionp || (regionp->getHandle() != mLastRegionHandle)) - { - if (mLastRegionHandle != 0) - { - ++mRegionCrossingCount; - F64Seconds delta(mRegionCrossingTimer.getElapsedTimeF32()); - record(LLStatViewer::REGION_CROSSING_TIME, delta); - - // Diagnostics - LL_INFOS() << "Region crossing took " << (F32)(delta * 1000.0).value() << " ms " << LL_ENDL; - } - if (regionp) - { - mLastRegionHandle = regionp->getHandle(); - } - } - mRegionCrossingTimer.reset(); - LLViewerObject::updateRegion(regionp); + // Save the global position + LLVector3d global_pos_from_old_region = getPositionGlobal(); + + // Change the region + setRegion(regionp); + + if (regionp) + { // Set correct region-relative position from global coordinates + setPositionGlobal(global_pos_from_old_region); + + // Diagnostic info + //LLVector3d pos_from_new_region = getPositionGlobal(); + //LL_INFOS() << "pos_from_old_region is " << global_pos_from_old_region + // << " while pos_from_new_region is " << pos_from_new_region + // << LL_ENDL; + + // Update hover height, or schedule callback, based on whether + // it's supported in this region. + if (regionp->simulatorFeaturesReceived()) + { + setHoverIfRegionEnabled(); + } + else + { + regionp->setSimulatorFeaturesReceivedCallback(boost::bind(&LLVOAvatarSelf::onSimulatorFeaturesReceived,this,_1)); + } + } + + if (!regionp || (regionp->getHandle() != mLastRegionHandle)) + { + if (mLastRegionHandle != 0) + { + ++mRegionCrossingCount; + F64Seconds delta(mRegionCrossingTimer.getElapsedTimeF32()); + record(LLStatViewer::REGION_CROSSING_TIME, delta); + + // Diagnostics + LL_INFOS() << "Region crossing took " << (F32)(delta * 1000.0).value() << " ms " << LL_ENDL; + } + if (regionp) + { + mLastRegionHandle = regionp->getHandle(); + } + } + mRegionCrossingTimer.reset(); + LLViewerObject::updateRegion(regionp); } //-------------------------------------------------------------------- @@ -969,65 +969,65 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) //virtual void LLVOAvatarSelf::idleUpdateTractorBeam() { - // This is only done for yourself (maybe it should be in the agent?) - if (!needsRenderBeam() || !isBuilt()) - { - mBeam = NULL; - } - else if (!mBeam || mBeam->isDead()) - { - // VEFFECT: Tractor Beam - mBeam = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM); - mBeam->setColor(LLColor4U(gAgent.getEffectColor())); - mBeam->setSourceObject(this); - mBeamTimer.reset(); - } - - if (!mBeam.isNull()) - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - - if (gAgentCamera.mPointAt.notNull()) - { - // get point from pointat effect - mBeam->setPositionGlobal(gAgentCamera.mPointAt->getPointAtPosGlobal()); - mBeam->triggerLocal(); - } - else if (selection->getFirstRootObject() && - selection->getSelectType() != SELECT_TYPE_HUD) - { - LLViewerObject* objectp = selection->getFirstRootObject(); - mBeam->setTargetObject(objectp); - } - else - { - mBeam->setTargetObject(NULL); - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - if (tool->isEditing()) - { - if (tool->getEditingObject()) - { - mBeam->setTargetObject(tool->getEditingObject()); - } - else - { - mBeam->setPositionGlobal(tool->getEditingPointGlobal()); - } - } - else - { - const LLPickInfo& pick = gViewerWindow->getLastPick(); - mBeam->setPositionGlobal(pick.mPosGlobal); - } - - } - if (mBeamTimer.getElapsedTimeF32() > 0.25f) - { - mBeam->setColor(LLColor4U(gAgent.getEffectColor())); - mBeam->setNeedsSendToSim(TRUE); - mBeamTimer.reset(); - } - } + // This is only done for yourself (maybe it should be in the agent?) + if (!needsRenderBeam() || !isBuilt()) + { + mBeam = NULL; + } + else if (!mBeam || mBeam->isDead()) + { + // VEFFECT: Tractor Beam + mBeam = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM); + mBeam->setColor(LLColor4U(gAgent.getEffectColor())); + mBeam->setSourceObject(this); + mBeamTimer.reset(); + } + + if (!mBeam.isNull()) + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + + if (gAgentCamera.mPointAt.notNull()) + { + // get point from pointat effect + mBeam->setPositionGlobal(gAgentCamera.mPointAt->getPointAtPosGlobal()); + mBeam->triggerLocal(); + } + else if (selection->getFirstRootObject() && + selection->getSelectType() != SELECT_TYPE_HUD) + { + LLViewerObject* objectp = selection->getFirstRootObject(); + mBeam->setTargetObject(objectp); + } + else + { + mBeam->setTargetObject(NULL); + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + if (tool->isEditing()) + { + if (tool->getEditingObject()) + { + mBeam->setTargetObject(tool->getEditingObject()); + } + else + { + mBeam->setPositionGlobal(tool->getEditingPointGlobal()); + } + } + else + { + const LLPickInfo& pick = gViewerWindow->getLastPick(); + mBeam->setPositionGlobal(pick.mPosGlobal); + } + + } + if (mBeamTimer.getElapsedTimeF32() > 0.25f) + { + mBeam->setColor(LLColor4U(gAgent.getEffectColor())); + mBeam->setNeedsSendToSim(TRUE); + mBeamTimer.reset(); + } + } } //----------------------------------------------------------------------------- @@ -1036,13 +1036,13 @@ void LLVOAvatarSelf::idleUpdateTractorBeam() // virtual void LLVOAvatarSelf::restoreMeshData() { - //LL_INFOS() << "Restoring" << LL_ENDL; - mMeshValid = TRUE; - updateJointLODs(); - updateAttachmentVisibility(gAgentCamera.getCameraMode()); + //LL_INFOS() << "Restoring" << LL_ENDL; + mMeshValid = TRUE; + updateJointLODs(); + updateAttachmentVisibility(gAgentCamera.getCameraMode()); - // force mesh update as LOD might not have changed to trigger this - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + // force mesh update as LOD might not have changed to trigger this + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); } @@ -1052,35 +1052,35 @@ void LLVOAvatarSelf::restoreMeshData() //----------------------------------------------------------------------------- void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (attachment->getIsHUDAttachment()) - { - attachment->setAttachmentVisibility(TRUE); - } - else - { - switch (camera_mode) - { - case CAMERA_MODE_MOUSELOOK: - if ((LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) || gPipeline.mHeroProbeManager.isMirrorPass()) - { - attachment->setAttachmentVisibility(TRUE); - } - else - { - attachment->setAttachmentVisibility(FALSE); - } - break; - default: - attachment->setAttachmentVisibility(TRUE); - break; - } - } - } + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment->getIsHUDAttachment()) + { + attachment->setAttachmentVisibility(TRUE); + } + else + { + switch (camera_mode) + { + case CAMERA_MODE_MOUSELOOK: + if ((LLVOAvatar::sVisibleInFirstPerson && attachment->getVisibleInFirstPerson()) || gPipeline.mHeroProbeManager.isMirrorPass()) + { + attachment->setAttachmentVisibility(TRUE); + } + else + { + attachment->setAttachmentVisibility(FALSE); + } + break; + default: + attachment->setAttachmentVisibility(TRUE); + break; + } + } + } } //----------------------------------------------------------------------------- @@ -1090,33 +1090,33 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode) //----------------------------------------------------------------------------- void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type) { - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - const LLAvatarAppearanceDefines::EBakedTextureIndex index = baked_iter->first; - - if (baked_dict) - { - for (LLAvatarAppearanceDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); - type_iter != baked_dict->mWearables.end(); - ++type_iter) - { - const LLWearableType::EType comp_type = *type_iter; - if (comp_type == type) - { - LLViewerTexLayerSet *layerset = getLayerSet(index); - if (layerset) - { - layerset->setUpdatesEnabled(true); - invalidateComposite(layerset); - } - break; - } - } - } - } + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + const LLAvatarAppearanceDefines::EBakedTextureIndex index = baked_iter->first; + + if (baked_dict) + { + for (LLAvatarAppearanceDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin(); + type_iter != baked_dict->mWearables.end(); + ++type_iter) + { + const LLWearableType::EType comp_type = *type_iter; + if (comp_type == type) + { + LLViewerTexLayerSet *layerset = getLayerSet(index); + if (layerset) + { + layerset->setUpdatesEnabled(true); + invalidateComposite(layerset); + } + break; + } + } + } + } } //----------------------------------------------------------------------------- @@ -1124,18 +1124,18 @@ void LLVOAvatarSelf::wearableUpdated(LLWearableType::EType type) //----------------------------------------------------------------------------- BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const { - const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment* attachment = iter->second; - if (attachment->getAttachedObject(base_inv_item_id)) - { - return TRUE; - } - } - return FALSE; + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) + { + return TRUE; + } + } + return FALSE; } //----------------------------------------------------------------------------- @@ -1143,113 +1143,113 @@ BOOL LLVOAvatarSelf::isWearingAttachment(const LLUUID& inv_item_id) const //----------------------------------------------------------------------------- LLViewerObject* LLVOAvatarSelf::getWornAttachment(const LLUUID& inv_item_id) { - const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id)) - { - return attached_object; - } - } - return NULL; + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id)) + { + return attached_object; + } + } + return NULL; } bool LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id, std::string& name) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (!gInventory.getItem(inv_item_id)) - { - name = "ATTACHMENT_MISSING_ITEM"; - return false; - } - const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); - if (!gInventory.getItem(base_inv_item_id)) - { - name = "ATTACHMENT_MISSING_BASE_ITEM"; - return false; - } - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - const LLViewerJointAttachment* attachment = iter->second; - if (attachment->getAttachedObject(base_inv_item_id)) - { - name = attachment->getName(); - return true; - } - } - - name = "ATTACHMENT_NOT_ATTACHED"; - return false; + if (!gInventory.getItem(inv_item_id)) + { + name = "ATTACHMENT_MISSING_ITEM"; + return false; + } + const LLUUID& base_inv_item_id = gInventory.getLinkedItemID(inv_item_id); + if (!gInventory.getItem(base_inv_item_id)) + { + name = "ATTACHMENT_MISSING_BASE_ITEM"; + return false; + } + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + const LLViewerJointAttachment* attachment = iter->second; + if (attachment->getAttachedObject(base_inv_item_id)) + { + name = attachment->getName(); + return true; + } + } + + name = "ATTACHMENT_NOT_ATTACHED"; + return false; } //virtual const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object) { - const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object); - if (!attachment) - { - return 0; - } + const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object); + if (!attachment) + { + return 0; + } - updateAttachmentVisibility(gAgentCamera.getCameraMode()); - - // Then make sure the inventory is in sync with the avatar. + updateAttachmentVisibility(gAgentCamera.getCameraMode()); - // Should just be the last object added - if (attachment->isObjectAttached(viewer_object)) - { - const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); - LLAppearanceMgr::instance().registerAttachment(attachment_id); - updateLODRiggedAttachments(); - } + // Then make sure the inventory is in sync with the avatar. - return attachment; + // Should just be the last object added + if (attachment->isObjectAttached(viewer_object)) + { + const LLUUID& attachment_id = viewer_object->getAttachmentItemID(); + LLAppearanceMgr::instance().registerAttachment(attachment_id); + updateLODRiggedAttachments(); + } + + return attachment; } //virtual BOOL LLVOAvatarSelf::detachObject(LLViewerObject *viewer_object) { - const LLUUID attachment_id = viewer_object->getAttachmentItemID(); - if ( LLVOAvatar::detachObject(viewer_object) ) - { - // the simulator should automatically handle permission revocation - - stopMotionFromSource(attachment_id); - LLFollowCamMgr::getInstance()->setCameraActive(viewer_object->getID(), FALSE); - - LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); - ++iter) - { - LLViewerObject* child_objectp = *iter; - // the simulator should automatically handle - // permissions revocation - - stopMotionFromSource(child_objectp->getID()); - LLFollowCamMgr::getInstance()->setCameraActive(child_objectp->getID(), FALSE); - } - - // Make sure the inventory is in sync with the avatar. - - // Update COF contents, don't trigger appearance update. - if (!isValid()) - { - LL_INFOS() << "removeItemLinks skipped, avatar is under destruction" << LL_ENDL; - } - else - { - LLAppearanceMgr::instance().unregisterAttachment(attachment_id); - } - - return TRUE; - } - return FALSE; + const LLUUID attachment_id = viewer_object->getAttachmentItemID(); + if ( LLVOAvatar::detachObject(viewer_object) ) + { + // the simulator should automatically handle permission revocation + + stopMotionFromSource(attachment_id); + LLFollowCamMgr::getInstance()->setCameraActive(viewer_object->getID(), FALSE); + + LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); + ++iter) + { + LLViewerObject* child_objectp = *iter; + // the simulator should automatically handle + // permissions revocation + + stopMotionFromSource(child_objectp->getID()); + LLFollowCamMgr::getInstance()->setCameraActive(child_objectp->getID(), FALSE); + } + + // Make sure the inventory is in sync with the avatar. + + // Update COF contents, don't trigger appearance update. + if (!isValid()) + { + LL_INFOS() << "removeItemLinks skipped, avatar is under destruction" << LL_ENDL; + } + else + { + LLAppearanceMgr::instance().unregisterAttachment(attachment_id); + } + + return TRUE; + } + return FALSE; } bool LLVOAvatarSelf::hasAttachmentsInTrash() @@ -1276,140 +1276,140 @@ bool LLVOAvatarSelf::hasAttachmentsInTrash() // static BOOL LLVOAvatarSelf::detachAttachmentIntoInventory(const LLUUID &item_id) { - LLInventoryItem* item = gInventory.getItem(item_id); - if (item) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); - gMessageSystem->sendReliable(gAgent.getRegionHost()); - - // This object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject(item_id); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - - // Error checking in case this object was attached to an invalid point - // In that case, just remove the item from COF preemptively since detach - // will fail. - if (isAgentAvatarValid()) - { - const LLViewerObject *attached_obj = gAgentAvatarp->getWornAttachment(item_id); - if (!attached_obj) - { - LLAppearanceMgr::instance().removeCOFItemLinks(item_id); - } - } - return TRUE; - } - return FALSE; + LLInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); + gMessageSystem->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, item_id); + gMessageSystem->sendReliable(gAgent.getRegionHost()); + + // This object might have been selected, so let the selection manager know it's gone now + LLViewerObject *found_obj = gObjectList.findObject(item_id); + if (found_obj) + { + LLSelectMgr::getInstance()->remove(found_obj); + } + + // Error checking in case this object was attached to an invalid point + // In that case, just remove the item from COF preemptively since detach + // will fail. + if (isAgentAvatarValid()) + { + const LLViewerObject *attached_obj = gAgentAvatarp->getWornAttachment(item_id); + if (!attached_obj) + { + LLAppearanceMgr::instance().removeCOFItemLinks(item_id); + } + } + return TRUE; + } + return FALSE; } U32 LLVOAvatarSelf::getNumWearables(LLAvatarAppearanceDefines::ETextureIndex i) const { - LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); - return gAgentWearables.getWearableCount(type); + LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); + return gAgentWearables.getWearableCount(type); } // virtual void LLVOAvatarSelf::localTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) -{ - - const LLUUID& src_id = src_vi->getID(); - LLAvatarTexData *data = (LLAvatarTexData *)userdata; - ETextureIndex index = data->mIndex; - if (!isIndexLocalTexture(index)) return; - - LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); - - // fix for EXT-268. Preventing using of NULL pointer - if(NULL == local_tex_obj) - { - LL_WARNS("TAG") << "There is no Local Texture Object with index: " << index - << ", final: " << final - << LL_ENDL; - return; - } - if (success) - { - if (!local_tex_obj->getBakedReady() && - local_tex_obj->getImage() != NULL && - (local_tex_obj->getID() == src_id) && - discard_level < local_tex_obj->getDiscard()) - { - local_tex_obj->setDiscard(discard_level); - requestLayerSetUpdate(index); - if (isEditingAppearance()) - { - LLVisualParamHint::requestHintUpdates(); - } - updateMeshTextures(); - } - } - else if (final) - { - // Failed: asset is missing - if (!local_tex_obj->getBakedReady() && - local_tex_obj->getImage() != NULL && - local_tex_obj->getImage()->getID() == src_id) - { - local_tex_obj->setDiscard(0); - requestLayerSetUpdate(index); - updateMeshTextures(); - } - } +{ + + const LLUUID& src_id = src_vi->getID(); + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + ETextureIndex index = data->mIndex; + if (!isIndexLocalTexture(index)) return; + + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(index, 0); + + // fix for EXT-268. Preventing using of NULL pointer + if(NULL == local_tex_obj) + { + LL_WARNS("TAG") << "There is no Local Texture Object with index: " << index + << ", final: " << final + << LL_ENDL; + return; + } + if (success) + { + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + (local_tex_obj->getID() == src_id) && + discard_level < local_tex_obj->getDiscard()) + { + local_tex_obj->setDiscard(discard_level); + requestLayerSetUpdate(index); + if (isEditingAppearance()) + { + LLVisualParamHint::requestHintUpdates(); + } + updateMeshTextures(); + } + } + else if (final) + { + // Failed: asset is missing + if (!local_tex_obj->getBakedReady() && + local_tex_obj->getImage() != NULL && + local_tex_obj->getImage()->getID() == src_id) + { + local_tex_obj->setDiscard(0); + requestLayerSetUpdate(index); + updateMeshTextures(); + } + } } // virtual BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex_pp, U32 index) const { - *tex_pp = NULL; + *tex_pp = NULL; - if (!isIndexLocalTexture(type)) return FALSE; - if (getLocalTextureID(type, index) == IMG_DEFAULT_AVATAR) return TRUE; + if (!isIndexLocalTexture(type)) return FALSE; + if (getLocalTextureID(type, index) == IMG_DEFAULT_AVATAR) return TRUE; - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); - if (!local_tex_obj) - { - return FALSE; - } - *tex_pp = dynamic_cast (local_tex_obj->getImage()); - return TRUE; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (!local_tex_obj) + { + return FALSE; + } + *tex_pp = dynamic_cast (local_tex_obj->getImage()); + return TRUE; } LLViewerFetchedTexture* LLVOAvatarSelf::getLocalTextureGL(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { - if (!isIndexLocalTexture(type)) - { - return NULL; - } + if (!isIndexLocalTexture(type)) + { + return NULL; + } - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); - if (!local_tex_obj) - { - return NULL; - } - if (local_tex_obj->getID() == IMG_DEFAULT_AVATAR) - { - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); - } - return dynamic_cast (local_tex_obj->getImage()); + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (!local_tex_obj) + { + return NULL; + } + if (local_tex_obj->getID() == IMG_DEFAULT_AVATAR) + { + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); + } + return dynamic_cast (local_tex_obj->getImage()); } const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) const { - if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR; + if (!isIndexLocalTexture(type)) return IMG_DEFAULT_AVATAR; - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); - if (local_tex_obj && local_tex_obj->getImage() != NULL) - { - return local_tex_obj->getImage()->getID(); - } - return IMG_DEFAULT_AVATAR; -} + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index); + if (local_tex_obj && local_tex_obj->getImage() != NULL) + { + return local_tex_obj->getImage()->getID(); + } + return IMG_DEFAULT_AVATAR; +} //----------------------------------------------------------------------------- @@ -1419,35 +1419,35 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c //----------------------------------------------------------------------------- BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* layerset) const { - /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) - return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const EBakedTextureIndex baked_index = baked_iter->first; - if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) - { - BOOL ret = true; - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - BOOL tex_avail = (getLocalDiscardLevel(tex_index, wearable_index) >= 0); - ret &= tex_avail; - } - } - return ret; - } - } - llassert(0); - return FALSE; + /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) + return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + BOOL ret = true; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + BOOL tex_avail = (getLocalDiscardLevel(tex_index, wearable_index) >= 0); + ret &= tex_avail; + } + } + return ret; + } + } + llassert(0); + return FALSE; } //----------------------------------------------------------------------------- @@ -1458,159 +1458,159 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLViewerTexLayerSet* laye //----------------------------------------------------------------------------- BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLViewerTexLayerSet* layerset) const { - const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); - // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels. - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - if (layerset == mBakedTextureDatas[i].mTexLayerSet) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); - if ((local_discard_level > (S32)(desired_tex_discard_level)) || - (local_discard_level < 0 )) - { - return FALSE; - } - } - } - return TRUE; - } - } - llassert(0); - return FALSE; + const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels. + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (layerset == mBakedTextureDatas[i].mTexLayerSet) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) + { + return FALSE; + } + } + } + return TRUE; + } + } + llassert(0); + return FALSE; } BOOL LLVOAvatarSelf::isAllLocalTextureDataFinal() const { - const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); - // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); - if ((local_discard_level > (S32)(desired_tex_discard_level)) || - (local_discard_level < 0 )) - { - return FALSE; - } - } - } - } - return TRUE; + const U32 desired_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + // const U32 desired_tex_discard_level = 0; // hack to not bake textures on lower discard levels + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + S32 local_discard_level = getLocalDiscardLevel(*local_tex_iter, wearable_index); + if ((local_discard_level > (S32)(desired_tex_discard_level)) || + (local_discard_level < 0 )) + { + return FALSE; + } + } + } + } + return TRUE; } BOOL LLVOAvatarSelf::isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { - LLUUID id; - BOOL isDefined = TRUE; - if (isIndexLocalTexture(type)) - { - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - if (index >= wearable_count) - { - // invalid index passed in. check all textures of a given type - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - id = getLocalTextureID(type, wearable_index); - isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); - } - } - else - { - id = getLocalTextureID(type, index); - isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); - } - } - else - { - id = getTEImage(type)->getID(); - isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); - } - - return isDefined; + LLUUID id; + BOOL isDefined = TRUE; + if (isIndexLocalTexture(type)) + { + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (index >= wearable_count) + { + // invalid index passed in. check all textures of a given type + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + id = getLocalTextureID(type, wearable_index); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + } + else + { + id = getLocalTextureID(type, index); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + } + else + { + id = getTEImage(type)->getID(); + isDefined &= (id != IMG_DEFAULT_AVATAR && id != IMG_DEFAULT); + } + + return isDefined; } //virtual BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, U32 index) const { - if (isIndexBakedTexture(type)) - { - return LLVOAvatar::isTextureVisible(type, (U32)0); - } + if (isIndexBakedTexture(type)) + { + return LLVOAvatar::isTextureVisible(type, (U32)0); + } - LLUUID tex_id = getLocalTextureID(type,index); - return (tex_id != IMG_INVISIBLE) - || (LLDrawPoolAlpha::sShowDebugAlpha); + LLUUID tex_id = getLocalTextureID(type,index); + return (tex_id != IMG_INVISIBLE) + || (LLDrawPoolAlpha::sShowDebugAlpha); } //virtual BOOL LLVOAvatarSelf::isTextureVisible(LLAvatarAppearanceDefines::ETextureIndex type, LLViewerWearable *wearable) const { - if (isIndexBakedTexture(type)) - { - return LLVOAvatar::isTextureVisible(type); - } + if (isIndexBakedTexture(type)) + { + return LLVOAvatar::isTextureVisible(type); + } - U32 index; - if (gAgentWearables.getWearableIndex(wearable,index)) - { - return isTextureVisible(type,index); - } - else - { - LL_WARNS() << "Wearable not found" << LL_ENDL; - return FALSE; - } + U32 index; + if (gAgentWearables.getWearableIndex(wearable,index)) + { + return isTextureVisible(type,index); + } + else + { + LL_WARNS() << "Wearable not found" << LL_ENDL; + return FALSE; + } } bool LLVOAvatarSelf::areTexturesCurrent() const { - return gAgentWearables.areWearablesLoaded(); + return gAgentWearables.areWearablesLoaded(); } void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset) { - LLViewerTexLayerSet *layer_set = dynamic_cast(layerset); - if( !layer_set || !layer_set->getUpdatesEnabled() ) - { - return; - } - // LL_INFOS() << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegionName() << LL_ENDL; + LLViewerTexLayerSet *layer_set = dynamic_cast(layerset); + if( !layer_set || !layer_set->getUpdatesEnabled() ) + { + return; + } + // LL_INFOS() << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegionName() << LL_ENDL; - layer_set->requestUpdate(); - layer_set->invalidateMorphMasks(); + layer_set->requestUpdate(); + layer_set->invalidateMorphMasks(); } void LLVOAvatarSelf::invalidateAll() { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - LLViewerTexLayerSet *layerset = getTexLayerSet(i); - invalidateComposite(layerset); - } - //mDebugSelfLoadTimer.reset(); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + invalidateComposite(layerset); + } + //mDebugSelfLoadTimer.reset(); } //----------------------------------------------------------------------------- @@ -1618,593 +1618,593 @@ void LLVOAvatarSelf::invalidateAll() //----------------------------------------------------------------------------- void LLVOAvatarSelf::setCompositeUpdatesEnabled( bool b ) { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - setCompositeUpdatesEnabled(i, b); - } + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + setCompositeUpdatesEnabled(i, b); + } } void LLVOAvatarSelf::setCompositeUpdatesEnabled(U32 index, bool b) { - LLViewerTexLayerSet *layerset = getTexLayerSet(index); - if (layerset ) - { - layerset->setUpdatesEnabled( b ); - } + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset ) + { + layerset->setUpdatesEnabled( b ); + } } bool LLVOAvatarSelf::isCompositeUpdateEnabled(U32 index) { - LLViewerTexLayerSet *layerset = getTexLayerSet(index); - if (layerset) - { - return layerset->getUpdatesEnabled(); - } - return false; + LLViewerTexLayerSet *layerset = getTexLayerSet(index); + if (layerset) + { + return layerset->getUpdatesEnabled(); + } + return false; } void LLVOAvatarSelf::setupComposites() { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; - BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); - LLViewerTexLayerSet *layerset = getTexLayerSet(i); - if (layerset) - { - layerset->setUpdatesEnabled(!layer_baked); - } - } + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex tex_index = mBakedTextureDatas[i].mTextureIndex; + BOOL layer_baked = isTextureDefined(tex_index, gAgentWearables.getWearableCount(tex_index)); + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset) + { + layerset->setUpdatesEnabled(!layer_baked); + } + } } void LLVOAvatarSelf::updateComposites() { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - LLViewerTexLayerSet *layerset = getTexLayerSet(i); - if (layerset - && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT))) - { - layerset->updateComposite(); - } - } + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + LLViewerTexLayerSet *layerset = getTexLayerSet(i); + if (layerset + && ((i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT))) + { + layerset->updateComposite(); + } + } } // virtual S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const { - if (!isIndexLocalTexture(type)) return FALSE; - - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index); - if (local_tex_obj) - { - const LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); - if (type >= 0 - && local_tex_obj->getID() != IMG_DEFAULT_AVATAR - && !image->isMissingAsset()) - { - return image->getDiscardLevel(); - } - else - { - // We don't care about this (no image associated with the layer) treat as fully loaded. - return 0; - } - } - return 0; + if (!isIndexLocalTexture(type)) return FALSE; + + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index); + if (local_tex_obj) + { + const LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); + if (type >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !image->isMissingAsset()) + { + return image->getDiscardLevel(); + } + else + { + // We don't care about this (no image associated with the layer) treat as fully loaded. + return 0; + } + } + return 0; } // virtual // Counts the memory footprint of local textures. void LLVOAvatarSelf::getLocalTextureByteCount(S32* gl_bytes) const { - *gl_bytes = 0; - for (S32 type = 0; type < TEX_NUM_INDICES; type++) - { - if (!isIndexLocalTexture((ETextureIndex)type)) continue; - U32 max_tex = getNumWearables((ETextureIndex) type); - for (U32 num = 0; num < max_tex; num++) - { - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); - if (local_tex_obj) - { - const LLViewerFetchedTexture* image_gl = dynamic_cast( local_tex_obj->getImage() ); - if (image_gl) - { - S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); - - if (image_gl->hasGLTexture()) - { - *gl_bytes += bytes; - } - } - } - } - } -} - -// virtual + *gl_bytes = 0; + for (S32 type = 0; type < TEX_NUM_INDICES; type++) + { + if (!isIndexLocalTexture((ETextureIndex)type)) continue; + U32 max_tex = getNumWearables((ETextureIndex) type); + for (U32 num = 0; num < max_tex; num++) + { + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject((ETextureIndex) type, num); + if (local_tex_obj) + { + const LLViewerFetchedTexture* image_gl = dynamic_cast( local_tex_obj->getImage() ); + if (image_gl) + { + S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); + + if (image_gl->hasGLTexture()) + { + *gl_bytes += bytes; + } + } + } + } + } +} + +// virtual void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_tex, BOOL baked_version_ready, U32 index) { - if (!isIndexLocalTexture(type)) return; - - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(src_tex, TRUE) ; - if(!tex) - { - return ; - } - - S32 desired_discard = isSelf() ? 0 : 2; - LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); - if (!local_tex_obj) - { - if (type >= TEX_NUM_INDICES) - { - LL_ERRS() << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << LL_ENDL; - return; - } - LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); - if (!gAgentWearables.getViewerWearable(wearable_type,index)) - { - // no wearable is loaded, cannot set the texture. - return; - } - gAgentWearables.addLocalTextureObject(wearable_type,type,index); - local_tex_obj = getLocalTextureObject(type,index); - if (!local_tex_obj) - { - LL_ERRS() << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << LL_ENDL; - return; - } - - LLViewerTexLayerSet *layer_set = getLayerSet(type); - if (layer_set) - { - layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getViewerWearable(wearable_type,index)); - } - - } - if (!baked_version_ready) - { - if (tex != local_tex_obj->getImage() || local_tex_obj->getBakedReady()) - { - local_tex_obj->setDiscard(MAX_DISCARD_LEVEL+1); - } - if (tex->getID() != IMG_DEFAULT_AVATAR) - { - if (local_tex_obj->getDiscard() > desired_discard) - { - S32 tex_discard = tex->getDiscardLevel(); - if (tex_discard >= 0 && tex_discard <= desired_discard) - { - local_tex_obj->setDiscard(tex_discard); - if (isSelf()) - { - requestLayerSetUpdate(type); - if (isEditingAppearance()) - { - LLVisualParamHint::requestHintUpdates(); - } - } - } - else - { - tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); - } - } - tex->setMinDiscardLevel(desired_discard); - } - } - local_tex_obj->setImage(tex); - local_tex_obj->setID(tex->getID()); - setBakedReady(type,baked_version_ready,index); + if (!isIndexLocalTexture(type)) return; + + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(src_tex, TRUE) ; + if(!tex) + { + return ; + } + + S32 desired_discard = isSelf() ? 0 : 2; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + if (type >= TEX_NUM_INDICES) + { + LL_ERRS() << "Tried to set local texture with invalid type: (" << (U32) type << ", " << index << ")" << LL_ENDL; + return; + } + LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(type); + if (!gAgentWearables.getViewerWearable(wearable_type,index)) + { + // no wearable is loaded, cannot set the texture. + return; + } + gAgentWearables.addLocalTextureObject(wearable_type,type,index); + local_tex_obj = getLocalTextureObject(type,index); + if (!local_tex_obj) + { + LL_ERRS() << "Unable to create LocalTextureObject for wearable type & index: (" << (U32) wearable_type << ", " << index << ")" << LL_ENDL; + return; + } + + LLViewerTexLayerSet *layer_set = getLayerSet(type); + if (layer_set) + { + layer_set->cloneTemplates(local_tex_obj, type, gAgentWearables.getViewerWearable(wearable_type,index)); + } + + } + if (!baked_version_ready) + { + if (tex != local_tex_obj->getImage() || local_tex_obj->getBakedReady()) + { + local_tex_obj->setDiscard(MAX_DISCARD_LEVEL+1); + } + if (tex->getID() != IMG_DEFAULT_AVATAR) + { + if (local_tex_obj->getDiscard() > desired_discard) + { + S32 tex_discard = tex->getDiscardLevel(); + if (tex_discard >= 0 && tex_discard <= desired_discard) + { + local_tex_obj->setDiscard(tex_discard); + if (isSelf()) + { + requestLayerSetUpdate(type); + if (isEditingAppearance()) + { + LLVisualParamHint::requestHintUpdates(); + } + } + } + else + { + tex->setLoadedCallback(onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), type), NULL); + } + } + tex->setMinDiscardLevel(desired_discard); + } + } + local_tex_obj->setImage(tex); + local_tex_obj->setID(tex->getID()); + setBakedReady(type,baked_version_ready,index); } //virtual void LLVOAvatarSelf::setBakedReady(LLAvatarAppearanceDefines::ETextureIndex type, BOOL baked_version_exists, U32 index) { - if (!isIndexLocalTexture(type)) return; - LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); - if (local_tex_obj) - { - local_tex_obj->setBakedReady( baked_version_exists ); - } + if (!isIndexLocalTexture(type)) return; + LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type,index); + if (local_tex_obj) + { + local_tex_obj->setBakedReady( baked_version_exists ); + } } // virtual void LLVOAvatarSelf::dumpLocalTextures() const { - LL_INFOS() << "Local Textures:" << LL_ENDL; - - /* ETextureIndex baked_equiv[] = { - TEX_UPPER_BAKED, - if (isTextureDefined(baked_equiv[i])) */ - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); - iter != sAvatarDictionary->getTextures().end(); - ++iter) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) - continue; - - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - const ETextureIndex baked_equiv = sAvatarDictionary->getBakedTexture(baked_index)->mTextureIndex; - - const std::string &name = texture_dict->mName; - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); - // index is baked texture - index is not relevant. putting in 0 as placeholder - if (isTextureDefined(baked_equiv, 0)) - { + LL_INFOS() << "Local Textures:" << LL_ENDL; + + /* ETextureIndex baked_equiv[] = { + TEX_UPPER_BAKED, + if (isTextureDefined(baked_equiv[i])) */ + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); + ++iter) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + continue; + + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + const ETextureIndex baked_equiv = sAvatarDictionary->getBakedTexture(baked_index)->mTextureIndex; + + const std::string &name = texture_dict->mName; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0); + // index is baked texture - index is not relevant. putting in 0 as placeholder + if (isTextureDefined(baked_equiv, 0)) + { #if LL_RELEASE_FOR_DOWNLOAD - // End users don't get to trivially see avatar texture IDs, makes textures - // easier to steal. JC - LL_INFOS() << "LocTex " << name << ": Baked " << LL_ENDL; + // End users don't get to trivially see avatar texture IDs, makes textures + // easier to steal. JC + LL_INFOS() << "LocTex " << name << ": Baked " << LL_ENDL; #else - LL_INFOS() << "LocTex " << name << ": Baked " << getTEImage(baked_equiv)->getID() << LL_ENDL; + LL_INFOS() << "LocTex " << name << ": Baked " << getTEImage(baked_equiv)->getID() << LL_ENDL; #endif - } - else if (local_tex_obj && local_tex_obj->getImage() != NULL) - { - if (local_tex_obj->getImage()->getID() == IMG_DEFAULT_AVATAR) - { - LL_INFOS() << "LocTex " << name << ": None" << LL_ENDL; - } - else - { - LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); - - LL_INFOS() << "LocTex " << name << ": " - << "Discard " << image->getDiscardLevel() << ", " - << "(" << image->getWidth() << ", " << image->getHeight() << ") " + } + else if (local_tex_obj && local_tex_obj->getImage() != NULL) + { + if (local_tex_obj->getImage()->getID() == IMG_DEFAULT_AVATAR) + { + LL_INFOS() << "LocTex " << name << ": None" << LL_ENDL; + } + else + { + LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); + + LL_INFOS() << "LocTex " << name << ": " + << "Discard " << image->getDiscardLevel() << ", " + << "(" << image->getWidth() << ", " << image->getHeight() << ") " #if !LL_RELEASE_FOR_DOWNLOAD - // End users don't get to trivially see avatar texture IDs, - // makes textures easier to steal - << image->getID() << " " + // End users don't get to trivially see avatar texture IDs, + // makes textures easier to steal + << image->getID() << " " #endif - << "Priority: " << image->getMaxVirtualSize() - << LL_ENDL; - } - } - else - { - LL_INFOS() << "LocTex " << name << ": No LLViewerTexture" << LL_ENDL; - } - } + << "Priority: " << image->getMaxVirtualSize() + << LL_ENDL; + } + } + else + { + LL_INFOS() << "LocTex " << name << ": No LLViewerTexture" << LL_ENDL; + } + } } //----------------------------------------------------------------------------- -// static +// static // onLocalTextureLoaded() //----------------------------------------------------------------------------- void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - LLAvatarTexData *data = (LLAvatarTexData *)userdata; - LLVOAvatarSelf *self = (LLVOAvatarSelf *)gObjectList.findObject(data->mAvatarID); - if (self) - { - // We should only be handling local textures for ourself - self->localTextureLoaded(success, src_vi, src_raw, aux_src, discard_level, final, userdata); - } - // ensure data is cleaned up - if (final || !success) - { - delete data; - } + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + LLVOAvatarSelf *self = (LLVOAvatarSelf *)gObjectList.findObject(data->mAvatarID); + if (self) + { + // We should only be handling local textures for ourself + self->localTextureLoaded(success, src_vi, src_raw, aux_src, discard_level, final, userdata); + } + // ensure data is cleaned up + if (final || !success) + { + delete data; + } } -/*virtual*/ void LLVOAvatarSelf::setImage(const U8 te, LLViewerTexture *imagep, const U32 index) +/*virtual*/ void LLVOAvatarSelf::setImage(const U8 te, LLViewerTexture *imagep, const U32 index) { - if (isIndexLocalTexture((ETextureIndex)te)) - { - setLocalTexture((ETextureIndex)te, imagep, FALSE ,index); - } - else - { - setTEImage(te,imagep); - } + if (isIndexLocalTexture((ETextureIndex)te)) + { + setLocalTexture((ETextureIndex)te, imagep, FALSE ,index); + } + else + { + setTEImage(te,imagep); + } } /*virtual*/ LLViewerTexture* LLVOAvatarSelf::getImage(const U8 te, const U32 index) const { - if (isIndexLocalTexture((ETextureIndex)te)) - { - return getLocalTextureGL((ETextureIndex)te,index); - } - else - { - return getTEImage(te); - } + if (isIndexLocalTexture((ETextureIndex)te)) + { + return getLocalTextureGL((ETextureIndex)te,index); + } + else + { + return getTEImage(te); + } } // static void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() { - S32 gl_bytes = 0; - gAgentAvatarp->getLocalTextureByteCount(&gl_bytes); - LL_INFOS() << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << LL_ENDL; + S32 gl_bytes = 0; + gAgentAvatarp->getLocalTextureByteCount(&gl_bytes); + LL_INFOS() << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << LL_ENDL; } bool LLVOAvatarSelf::getIsCloud() const { - // Let people know why they're clouded without spamming them into oblivion. - bool do_warn = false; - static LLTimer time_since_notice; - F32 update_freq = 30.0; - if (time_since_notice.getElapsedTimeF32() > update_freq) - { - time_since_notice.reset(); - do_warn = true; - } - - // do we have our body parts? - S32 shape_count = gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE); - S32 hair_count = gAgentWearables.getWearableCount(LLWearableType::WT_HAIR); - S32 eye_count = gAgentWearables.getWearableCount(LLWearableType::WT_EYES); - S32 skin_count = gAgentWearables.getWearableCount(LLWearableType::WT_SKIN); - if (!shape_count || !hair_count || !eye_count || !skin_count) - { - if (do_warn) - { - LL_INFOS() << "Self is clouded due to missing one or more required body parts: " - << (shape_count ? "" : "SHAPE ") - << (hair_count ? "" : "HAIR ") - << (eye_count ? "" : "EYES ") - << (skin_count ? "" : "SKIN ") - << LL_ENDL; - } - return true; - } - - if (!isTextureDefined(TEX_HAIR, 0)) - { - if (do_warn) - { - LL_INFOS() << "Self is clouded because of no hair texture" << LL_ENDL; - } - return true; - } - - if (!mPreviousFullyLoaded) - { - if (!isLocalTextureDataAvailable(getLayerSet(BAKED_LOWER)) && - (!isTextureDefined(TEX_LOWER_BAKED, 0))) - { - if (do_warn) - { - LL_INFOS() << "Self is clouded because lower textures not baked" << LL_ENDL; - } - return true; - } - - if (!isLocalTextureDataAvailable(getLayerSet(BAKED_UPPER)) && - (!isTextureDefined(TEX_UPPER_BAKED, 0))) - { - if (do_warn) - { - LL_INFOS() << "Self is clouded because upper textures not baked" << LL_ENDL; - } - return true; - } - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - if (i == BAKED_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) - continue; - - const BakedTextureData& texture_data = mBakedTextureDatas[i]; - if (!isTextureDefined(texture_data.mTextureIndex, 0)) - continue; - - // Check for the case that texture is defined but not sufficiently loaded to display anything. - const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); - if (!baked_img || !baked_img->hasGLTexture()) - { - if (do_warn) - { - LL_INFOS() << "Self is clouded because texture at index " << i - << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << LL_ENDL; - } - return true; - } - } - - LL_DEBUGS() << "Avatar de-clouded" << LL_ENDL; - } - return false; + // Let people know why they're clouded without spamming them into oblivion. + bool do_warn = false; + static LLTimer time_since_notice; + F32 update_freq = 30.0; + if (time_since_notice.getElapsedTimeF32() > update_freq) + { + time_since_notice.reset(); + do_warn = true; + } + + // do we have our body parts? + S32 shape_count = gAgentWearables.getWearableCount(LLWearableType::WT_SHAPE); + S32 hair_count = gAgentWearables.getWearableCount(LLWearableType::WT_HAIR); + S32 eye_count = gAgentWearables.getWearableCount(LLWearableType::WT_EYES); + S32 skin_count = gAgentWearables.getWearableCount(LLWearableType::WT_SKIN); + if (!shape_count || !hair_count || !eye_count || !skin_count) + { + if (do_warn) + { + LL_INFOS() << "Self is clouded due to missing one or more required body parts: " + << (shape_count ? "" : "SHAPE ") + << (hair_count ? "" : "HAIR ") + << (eye_count ? "" : "EYES ") + << (skin_count ? "" : "SKIN ") + << LL_ENDL; + } + return true; + } + + if (!isTextureDefined(TEX_HAIR, 0)) + { + if (do_warn) + { + LL_INFOS() << "Self is clouded because of no hair texture" << LL_ENDL; + } + return true; + } + + if (!mPreviousFullyLoaded) + { + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_LOWER)) && + (!isTextureDefined(TEX_LOWER_BAKED, 0))) + { + if (do_warn) + { + LL_INFOS() << "Self is clouded because lower textures not baked" << LL_ENDL; + } + return true; + } + + if (!isLocalTextureDataAvailable(getLayerSet(BAKED_UPPER)) && + (!isTextureDefined(TEX_UPPER_BAKED, 0))) + { + if (do_warn) + { + LL_INFOS() << "Self is clouded because upper textures not baked" << LL_ENDL; + } + return true; + } + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (i == BAKED_SKIRT && !isWearingWearableType(LLWearableType::WT_SKIRT)) + continue; + + const BakedTextureData& texture_data = mBakedTextureDatas[i]; + if (!isTextureDefined(texture_data.mTextureIndex, 0)) + continue; + + // Check for the case that texture is defined but not sufficiently loaded to display anything. + const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); + if (!baked_img || !baked_img->hasGLTexture()) + { + if (do_warn) + { + LL_INFOS() << "Self is clouded because texture at index " << i + << " (texture index is " << texture_data.mTextureIndex << ") is not loaded" << LL_ENDL; + } + return true; + } + } + + LL_DEBUGS() << "Avatar de-clouded" << LL_ENDL; + } + return false; } /*static*/ void LLVOAvatarSelf::debugOnTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - if (gAgentAvatarp.notNull()) - { - gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata); - } + if (gAgentAvatarp.notNull()) + { + gAgentAvatarp->debugTimingLocalTexLoaded(success, src_vi, src, aux_src, discard_level, final, userdata); + } } void LLVOAvatarSelf::debugTimingLocalTexLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata) { - LLAvatarTexData *data = (LLAvatarTexData *)userdata; - if (!data) - { - return; - } - - ETextureIndex index = data->mIndex; - - if (index < 0 || index >= TEX_NUM_INDICES) - { - return; - } - - if (discard_level >=0 && discard_level <= MAX_DISCARD_LEVEL) // ignore discard level -1, as it means we have no data. - { - mDebugTextureLoadTimes[(U32)index][(U32)discard_level] = mDebugSelfLoadTimer.getElapsedTimeF32(); - } - if (final) - { - delete data; - } + LLAvatarTexData *data = (LLAvatarTexData *)userdata; + if (!data) + { + return; + } + + ETextureIndex index = data->mIndex; + + if (index < 0 || index >= TEX_NUM_INDICES) + { + return; + } + + if (discard_level >=0 && discard_level <= MAX_DISCARD_LEVEL) // ignore discard level -1, as it means we have no data. + { + mDebugTextureLoadTimes[(U32)index][(U32)discard_level] = mDebugSelfLoadTimer.getElapsedTimeF32(); + } + if (final) + { + delete data; + } } void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL finished) { - U32 done = 0; - if (finished) - { - done = 1; - } - mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); + U32 done = 0; + if (finished) + { + done = 1; + } + mDebugBakedTextureTimes[index][done] = mDebugSelfLoadTimer.getElapsedTimeF32(); } const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { - std::ostringstream outbuf; + std::ostringstream outbuf; LLWearableType *wr_inst = LLWearableType::getInstance(); - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = - sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const EBakedTextureIndex baked_index = baked_iter->first; - if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) - { - outbuf << "baked_index: " << baked_index << "\n"; - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const std::string tex_name = sAvatarDictionary->getTexture(tex_index)->mName; - outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - if (wearable_count > 0) - { - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - outbuf << " " << wr_inst->getTypeName(wearable_type) << " " << wearable_index << ":"; - const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); - if (local_tex_obj) - { - LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); - if (tex_index >= 0 - && local_tex_obj->getID() != IMG_DEFAULT_AVATAR - && !image->isMissingAsset()) - { - outbuf << " id: " << image->getID() - << " refs: " << image->getNumRefs() - << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) - << " discard: " << image->getDiscardLevel() - << " desired: " << image->getDesiredDiscardLevel() - << " vsize: " << image->getMaxVirtualSize() - << " ts: " << image->getTextureState() - << " bl: " << image->getBoostLevel() - << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. - << " cl: " << (image->isFullyLoaded() && image->getDiscardLevel()==0) // "completely loaded" - << " mvs: " << image->getMaxVirtualSize() - << " mvsc: " << image->getMaxVirtualSizeResetCounter() - << " mem: " << image->getTextureMemory(); - } - } - outbuf << "\n"; - } - } - } - break; - } - } - return outbuf.str(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = + sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + outbuf << "baked_index: " << baked_index << "\n"; + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const std::string tex_name = sAvatarDictionary->getTexture(tex_index)->mName; + outbuf << " tex_index " << (S32) tex_index << " name " << tex_name << "\n"; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + outbuf << " " << wr_inst->getTypeName(wearable_type) << " " << wearable_index << ":"; + const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index); + if (local_tex_obj) + { + LLViewerFetchedTexture* image = dynamic_cast( local_tex_obj->getImage() ); + if (tex_index >= 0 + && local_tex_obj->getID() != IMG_DEFAULT_AVATAR + && !image->isMissingAsset()) + { + outbuf << " id: " << image->getID() + << " refs: " << image->getNumRefs() + << " glocdisc: " << getLocalDiscardLevel(tex_index, wearable_index) + << " discard: " << image->getDiscardLevel() + << " desired: " << image->getDesiredDiscardLevel() + << " vsize: " << image->getMaxVirtualSize() + << " ts: " << image->getTextureState() + << " bl: " << image->getBoostLevel() + << " fl: " << image->isFullyLoaded() // this is not an accessor for mFullyLoaded - see comment there. + << " cl: " << (image->isFullyLoaded() && image->getDiscardLevel()==0) // "completely loaded" + << " mvs: " << image->getMaxVirtualSize() + << " mvsc: " << image->getMaxVirtualSizeResetCounter() + << " mem: " << image->getTextureMemory(); + } + } + outbuf << "\n"; + } + } + } + break; + } + } + return outbuf.str(); } void LLVOAvatarSelf::dumpAllTextures() const { - std::string vd_text = "Local textures per baked index and wearable:\n"; - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); - if (!layerset) continue; - const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); - if (!layerset_buffer) continue; - vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); - } - LL_DEBUGS("Avatar") << vd_text << LL_ENDL; + std::string vd_text = "Local textures per baked index and wearable:\n"; + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + vd_text += verboseDebugDumpLocalTextureDataInfo(layerset); + } + LL_DEBUGS("Avatar") << vd_text << LL_ENDL; } const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const { - std::string text=""; + std::string text=""; LLWearableType *wr_inst = LLWearableType::getInstance(); - text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset)); - - /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) - return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const EBakedTextureIndex baked_index = baked_iter->first; - if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; - text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str()); - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - if (wearable_count > 0) - { - text += wr_inst->getTypeName(wearable_type) + ":"; - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index); - std::string discard_str = llformat("%d ",discard_level); - text += llformat("%d ",discard_level); - } - } - } - text += ")"; - break; - } - } - return text; + text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset)); + + /* if (layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) + return getLocalDiscardLevel(TEX_HEAD_BODYPAINT) >= 0; */ + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second; + text += llformat("%d-%s ( ",baked_index, baked_dict->mName.c_str()); + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + if (wearable_count > 0) + { + text += wr_inst->getTypeName(wearable_type) + ":"; + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index); + std::string discard_str = llformat("%d ",discard_level); + text += llformat("%d ",discard_level); + } + } + } + text += ")"; + break; + } + } + return text; } const std::string LLVOAvatarSelf::debugDumpAllLocalTextureDataInfo() const { - std::string text; - const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); - BOOL is_texture_final = TRUE; - for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); - local_tex_iter != baked_dict->mLocalTextures.end(); - ++local_tex_iter) - { - const ETextureIndex tex_index = *local_tex_iter; - const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); - const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); - for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) - { - is_texture_final &= (getLocalDiscardLevel(*local_tex_iter, wearable_index) <= (S32)(override_tex_discard_level)); - } - } - text += llformat("%s:%d ",baked_dict->mName.c_str(),is_texture_final); - } - return text; + std::string text; + const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture((EBakedTextureIndex)i); + BOOL is_texture_final = TRUE; + for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); + local_tex_iter != baked_dict->mLocalTextures.end(); + ++local_tex_iter) + { + const ETextureIndex tex_index = *local_tex_iter; + const LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(tex_index); + const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type); + for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++) + { + is_texture_final &= (getLocalDiscardLevel(*local_tex_iter, wearable_index) <= (S32)(override_tex_discard_level)); + } + } + text += llformat("%s:%d ",baked_dict->mName.c_str(),is_texture_final); + } + return text; } void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url) @@ -2241,7 +2241,7 @@ void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url) msg["nearby"][rez_status_name] = rez_counts[rez_stat]; } - // std::vector bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake"); + // std::vector bucket_fields("timer_name","is_self","grid_x","grid_y","is_using_server_bake"); std::vector by_fields; by_fields.push_back("timer_name"); by_fields.push_back("completed"); @@ -2280,233 +2280,233 @@ void LLVOAvatarSelf::appearanceChangeMetricsCoro(std::string url) bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send) { - const F32 AV_METRICS_INTERVAL_QA = 30.0; - F32 send_period = 300.0; + const F32 AV_METRICS_INTERVAL_QA = 30.0; + F32 send_period = 300.0; + + static LLCachedControl qa_mode_metrics(gSavedSettings,"QAModeMetrics"); + if (qa_mode_metrics) + { + send_period = AV_METRICS_INTERVAL_QA; + } - static LLCachedControl qa_mode_metrics(gSavedSettings,"QAModeMetrics"); - if (qa_mode_metrics) - { - send_period = AV_METRICS_INTERVAL_QA; - } + if (force_send || mTimeSinceLastRezMessage.getElapsedTimeF32() > send_period) + { + // Stats for completed phases have been getting logged as they + // complete. This will give us stats for any timers that + // haven't finished as of the metric's being sent. - if (force_send || mTimeSinceLastRezMessage.getElapsedTimeF32() > send_period) - { - // Stats for completed phases have been getting logged as they - // complete. This will give us stats for any timers that - // haven't finished as of the metric's being sent. - - if (force_send) - { - LLVOAvatar::logPendingPhasesAllAvatars(); - } - sendViewerAppearanceChangeMetrics(); - } + if (force_send) + { + LLVOAvatar::logPendingPhasesAllAvatars(); + } + sendViewerAppearanceChangeMetrics(); + } - return false; + return false; } void LLVOAvatarSelf::addMetricsTimerRecord(const LLSD& record) { - mPendingTimerRecords.push_back(record); + mPendingTimerRecords.push_back(record); } bool operator<(const LLSD& a, const LLSD& b) { - std::ostringstream aout, bout; - aout << LLSDNotationStreamer(a); - bout << LLSDNotationStreamer(b); - std::string astring = aout.str(); - std::string bstring = bout.str(); + std::ostringstream aout, bout; + aout << LLSDNotationStreamer(a); + bout << LLSDNotationStreamer(b); + std::string astring = aout.str(); + std::string bstring = bout.str(); - return astring < bstring; + return astring < bstring; } // Given a vector of LLSD records, return an LLSD array of bucketed stats for val_field. LLSD summarize_by_buckets(std::vector in_records, - std::vector by_fields, - std::string val_field) -{ - LLSD result = LLSD::emptyArray(); - std::map accum; - for (std::vector::iterator in_record_iter = in_records.begin(); - in_record_iter != in_records.end(); ++in_record_iter) - { - LLSD& record = *in_record_iter; - LLSD key; - for (std::vector::iterator field_iter = by_fields.begin(); - field_iter != by_fields.end(); ++field_iter) - { - const std::string& field = *field_iter; - key[field] = record[field]; - } - LLViewerStats::StatsAccumulator& stats = accum[key]; - F32 value = record[val_field].asReal(); - stats.push(value); - } - for (std::map::iterator accum_it = accum.begin(); - accum_it != accum.end(); ++accum_it) - { - LLSD out_record = accum_it->first; - out_record["stats"] = accum_it->second.asLLSD(); - result.append(out_record); - } - return result; + std::vector by_fields, + std::string val_field) +{ + LLSD result = LLSD::emptyArray(); + std::map accum; + for (std::vector::iterator in_record_iter = in_records.begin(); + in_record_iter != in_records.end(); ++in_record_iter) + { + LLSD& record = *in_record_iter; + LLSD key; + for (std::vector::iterator field_iter = by_fields.begin(); + field_iter != by_fields.end(); ++field_iter) + { + const std::string& field = *field_iter; + key[field] = record[field]; + } + LLViewerStats::StatsAccumulator& stats = accum[key]; + F32 value = record[val_field].asReal(); + stats.push(value); + } + for (std::map::iterator accum_it = accum.begin(); + accum_it != accum.end(); ++accum_it) + { + LLSD out_record = accum_it->first; + out_record["stats"] = accum_it->second.asLLSD(); + result.append(out_record); + } + return result; } void LLVOAvatarSelf::sendViewerAppearanceChangeMetrics() { - std::string caps_url; - if (getRegion()) - { - // runway - change here to activate. - caps_url = getRegion()->getCapability("ViewerMetrics"); - } - if (!caps_url.empty()) - { + std::string caps_url; + if (getRegion()) + { + // runway - change here to activate. + caps_url = getRegion()->getCapability("ViewerMetrics"); + } + if (!caps_url.empty()) + { LLCoros::instance().launch("LLVOAvatarSelf::appearanceChangeMetricsCoro", boost::bind(&LLVOAvatarSelf::appearanceChangeMetricsCoro, this, caps_url)); - mTimeSinceLastRezMessage.reset(); - } + mTimeSinceLastRezMessage.reset(); + } } const LLUUID& LLVOAvatarSelf::grabBakedTexture(EBakedTextureIndex baked_index) const { - if (canGrabBakedTexture(baked_index)) - { - ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); - if (tex_index == TEX_NUM_INDICES) - { - return LLUUID::null; - } - return getTEImage( tex_index )->getID(); - } - return LLUUID::null; + if (canGrabBakedTexture(baked_index)) + { + ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); + if (tex_index == TEX_NUM_INDICES) + { + return LLUUID::null; + } + return getTEImage( tex_index )->getID(); + } + return LLUUID::null; } BOOL LLVOAvatarSelf::canGrabBakedTexture(EBakedTextureIndex baked_index) const { - ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); - if (tex_index == TEX_NUM_INDICES) - { - return FALSE; - } - // Check if the texture hasn't been baked yet. - if (!isTextureDefined(tex_index, 0)) - { - LL_DEBUGS() << "getTEImage( " << (U32) tex_index << " )->getID() == IMG_DEFAULT_AVATAR" << LL_ENDL; - return FALSE; - } - - if (gAgent.isGodlikeWithoutAdminMenuFakery()) - return TRUE; - - // Check permissions of textures that show up in the - // baked texture. We don't want people copying people's - // work via baked textures. - - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture(baked_index); - for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); - iter != baked_dict->mLocalTextures.end(); - ++iter) - { - const ETextureIndex t_index = (*iter); - LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(t_index); - U32 count = gAgentWearables.getWearableCount(wearable_type); - LL_DEBUGS() << "Checking index " << (U32) t_index << " count: " << count << LL_ENDL; - - for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) - { - LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, wearable_index); - if (wearable) - { - const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); - const LLUUID& texture_id = texture->getID(); - if (texture_id != IMG_DEFAULT_AVATAR) - { - // Search inventory for this texture. - LLViewerInventoryCategory::cat_array_t cats; - LLViewerInventoryItem::item_array_t items; - LLAssetIDMatches asset_id_matches(texture_id); - gInventory.collectDescendentsIf(LLUUID::null, - cats, - items, - LLInventoryModel::INCLUDE_TRASH, - asset_id_matches); - - BOOL can_grab = FALSE; - LL_DEBUGS() << "item count for asset " << texture_id << ": " << items.size() << LL_ENDL; - if (items.size()) - { - // search for full permissions version - for (S32 i = 0; i < items.size(); i++) - { - LLViewerInventoryItem* itemp = items[i]; - if (itemp->getIsFullPerm()) - { - can_grab = TRUE; - break; - } - } - } - if (!can_grab) return FALSE; - } - } - } - } - - return TRUE; + ETextureIndex tex_index = sAvatarDictionary->bakedToLocalTextureIndex(baked_index); + if (tex_index == TEX_NUM_INDICES) + { + return FALSE; + } + // Check if the texture hasn't been baked yet. + if (!isTextureDefined(tex_index, 0)) + { + LL_DEBUGS() << "getTEImage( " << (U32) tex_index << " )->getID() == IMG_DEFAULT_AVATAR" << LL_ENDL; + return FALSE; + } + + if (gAgent.isGodlikeWithoutAdminMenuFakery()) + return TRUE; + + // Check permissions of textures that show up in the + // baked texture. We don't want people copying people's + // work via baked textures. + + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = sAvatarDictionary->getBakedTexture(baked_index); + for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); + iter != baked_dict->mLocalTextures.end(); + ++iter) + { + const ETextureIndex t_index = (*iter); + LLWearableType::EType wearable_type = sAvatarDictionary->getTEWearableType(t_index); + U32 count = gAgentWearables.getWearableCount(wearable_type); + LL_DEBUGS() << "Checking index " << (U32) t_index << " count: " << count << LL_ENDL; + + for (U32 wearable_index = 0; wearable_index < count; ++wearable_index) + { + LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, wearable_index); + if (wearable) + { + const LLLocalTextureObject *texture = wearable->getLocalTextureObject((S32)t_index); + const LLUUID& texture_id = texture->getID(); + if (texture_id != IMG_DEFAULT_AVATAR) + { + // Search inventory for this texture. + LLViewerInventoryCategory::cat_array_t cats; + LLViewerInventoryItem::item_array_t items; + LLAssetIDMatches asset_id_matches(texture_id); + gInventory.collectDescendentsIf(LLUUID::null, + cats, + items, + LLInventoryModel::INCLUDE_TRASH, + asset_id_matches); + + BOOL can_grab = FALSE; + LL_DEBUGS() << "item count for asset " << texture_id << ": " << items.size() << LL_ENDL; + if (items.size()) + { + // search for full permissions version + for (S32 i = 0; i < items.size(); i++) + { + LLViewerInventoryItem* itemp = items[i]; + if (itemp->getIsFullPerm()) + { + can_grab = TRUE; + break; + } + } + } + if (!can_grab) return FALSE; + } + } + } + } + + return TRUE; } void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTexture* imagep, - F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) -{ - if (!isIndexLocalTexture(type)) return; - - // Sunshine - ignoring covered_by_baked will force local textures - // to always load. Fix for SH-4001 and many related issues. Do - // not restore this without some more targetted fix for the local - // textures failing to load issue. - //if (!covered_by_baked) - { - if (imagep->getID() != IMG_DEFAULT_AVATAR) - { - imagep->setNoDelete(); - if (imagep->getDiscardLevel() != 0) - { - F32 desired_pixels; - desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); - imagep->addTextureStats( desired_pixels / texel_area_ratio ); - imagep->forceUpdateBindStats() ; - if (imagep->getDiscardLevel() < 0) - { - mHasGrey = TRUE; // for statistics gathering - } - } - } - else - { - // texture asset is missing - mHasGrey = TRUE; // for statistics gathering - } - } + F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked) +{ + if (!isIndexLocalTexture(type)) return; + + // Sunshine - ignoring covered_by_baked will force local textures + // to always load. Fix for SH-4001 and many related issues. Do + // not restore this without some more targetted fix for the local + // textures failing to load issue. + //if (!covered_by_baked) + { + if (imagep->getID() != IMG_DEFAULT_AVATAR) + { + imagep->setNoDelete(); + if (imagep->getDiscardLevel() != 0) + { + F32 desired_pixels; + desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); + + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->resetTextureStats(); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); + imagep->addTextureStats( desired_pixels / texel_area_ratio ); + imagep->forceUpdateBindStats() ; + if (imagep->getDiscardLevel() < 0) + { + mHasGrey = TRUE; // for statistics gathering + } + } + } + else + { + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering + } + } } LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDefines::ETextureIndex i, U32 wearable_index) const { - LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); - LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_index); - if (wearable) - { - return wearable->getLocalTextureObject(i); - } + LLWearableType::EType type = sAvatarDictionary->getTEWearableType(i); + LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, wearable_index); + if (wearable) + { + return wearable->getLocalTextureObject(i); + } - return NULL; + return NULL; } //----------------------------------------------------------------------------- @@ -2515,119 +2515,119 @@ LLLocalTextureObject* LLVOAvatarSelf::getLocalTextureObject(LLAvatarAppearanceDe //----------------------------------------------------------------------------- ETextureIndex LLVOAvatarSelf::getBakedTE( const LLViewerTexLayerSet* layerset ) const { - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - if (layerset == mBakedTextureDatas[i].mTexLayerSet ) - { - return mBakedTextureDatas[i].mTextureIndex; - } - } - llassert(0); - return TEX_HEAD_BAKED; + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + if (layerset == mBakedTextureDatas[i].mTexLayerSet ) + { + return mBakedTextureDatas[i].mTextureIndex; + } + } + llassert(0); + return TEX_HEAD_BAKED; } // FIXME: This is not called consistently. Something may be broken. void LLVOAvatarSelf::outputRezDiagnostics() const { - if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) - { - return ; - } - - const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32(); - LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << LL_ENDL; - LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << LL_ENDL; - LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << LL_ENDL; - LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << LL_ENDL; - LL_DEBUGS("Avatar") << "\t Load time for each texture: " << LL_ENDL; - for (U32 i = 0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) - { - std::stringstream out; - out << "\t\t (" << i << ") "; - U32 j=0; - for (j=0; j <= MAX_DISCARD_LEVEL; j++) - { - out << "\t"; - S32 load_time = (S32)mDebugTextureLoadTimes[i][j]; - if (load_time == -1) - { - out << "*"; - if (j == 0) - break; - } - else - { - out << load_time; - } - } - - // Don't print out non-existent textures. - if (j != 0) - { - LL_DEBUGS("Avatar") << out.str() << LL_ENDL; - } - } - LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << LL_ENDL; - for (U32 i = 0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) - { - LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << LL_ENDL; - } - - for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); - baked_iter != sAvatarDictionary->getBakedTextures().end(); - ++baked_iter) - { - const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; - const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); - if (!layerset) continue; - const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); - if (!layerset_buffer) continue; - LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << LL_ENDL; - } - - dumpAllTextures(); + if(!gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) + { + return ; + } + + const F32 final_time = mDebugSelfLoadTimer.getElapsedTimeF32(); + LL_DEBUGS("Avatar") << "REZTIME: Myself rez stats:" << LL_ENDL; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to load wearables: " << (S32)mDebugTimeWearablesLoaded << LL_ENDL; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud: " << (S32)mDebugTimeAvatarVisible << LL_ENDL; + LL_DEBUGS("Avatar") << "\t Time from avatar creation to de-cloud for others: " << (S32)final_time << LL_ENDL; + LL_DEBUGS("Avatar") << "\t Load time for each texture: " << LL_ENDL; + for (U32 i = 0; i < LLAvatarAppearanceDefines::TEX_NUM_INDICES; ++i) + { + std::stringstream out; + out << "\t\t (" << i << ") "; + U32 j=0; + for (j=0; j <= MAX_DISCARD_LEVEL; j++) + { + out << "\t"; + S32 load_time = (S32)mDebugTextureLoadTimes[i][j]; + if (load_time == -1) + { + out << "*"; + if (j == 0) + break; + } + else + { + out << load_time; + } + } + + // Don't print out non-existent textures. + if (j != 0) + { + LL_DEBUGS("Avatar") << out.str() << LL_ENDL; + } + } + LL_DEBUGS("Avatar") << "\t Time points for each upload (start / finish)" << LL_ENDL; + for (U32 i = 0; i < LLAvatarAppearanceDefines::BAKED_NUM_INDICES; ++i) + { + LL_DEBUGS("Avatar") << "\t\t (" << i << ") \t" << (S32)mDebugBakedTextureTimes[i][0] << " / " << (S32)mDebugBakedTextureTimes[i][1] << LL_ENDL; + } + + for (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin(); + baked_iter != sAvatarDictionary->getBakedTextures().end(); + ++baked_iter) + { + const LLAvatarAppearanceDefines::EBakedTextureIndex baked_index = baked_iter->first; + const LLViewerTexLayerSet *layerset = debugGetLayerSet(baked_index); + if (!layerset) continue; + const LLViewerTexLayerSetBuffer *layerset_buffer = layerset->getViewerComposite(); + if (!layerset_buffer) continue; + LL_DEBUGS("Avatar") << layerset_buffer->dumpTextureInfo() << LL_ENDL; + } + + dumpAllTextures(); } void LLVOAvatarSelf::outputRezTiming(const std::string& msg) const { - LL_DEBUGS("Avatar") - << avString() - << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) - << LL_ENDL; + LL_DEBUGS("Avatar") + << avString() + << llformat("%s. Time from avatar creation: %.2f", msg.c_str(), mDebugSelfLoadTimer.getElapsedTimeF32()) + << LL_ENDL; } void LLVOAvatarSelf::reportAvatarRezTime() const { - // TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow. + // TODO: report mDebugSelfLoadTimer.getElapsedTimeF32() somehow. } // SUNSHINE CLEANUP - not clear we need any of this, may be sufficient to request server appearance in llviewermenu.cpp:handle_rebake_textures() void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) { - LL_INFOS() << "TAT: forced full rebake. " << LL_ENDL; + LL_INFOS() << "TAT: forced full rebake. " << LL_ENDL; - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; - LLViewerTexLayerSet* layer_set = getLayerSet(baked_index); - if (layer_set) - { - if (slam_for_debug) - { - layer_set->setUpdatesEnabled(TRUE); - } + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; + LLViewerTexLayerSet* layer_set = getLayerSet(baked_index); + if (layer_set) + { + if (slam_for_debug) + { + layer_set->setUpdatesEnabled(TRUE); + } - invalidateComposite(layer_set); - add(LLStatViewer::TEX_REBAKES, 1); - } - else - { - LL_WARNS() << "TAT: NO LAYER SET FOR " << (S32)baked_index << LL_ENDL; - } - } + invalidateComposite(layer_set); + add(LLStatViewer::TEX_REBAKES, 1); + } + else + { + LL_WARNS() << "TAT: NO LAYER SET FOR " << (S32)baked_index << LL_ENDL; + } + } - // Don't know if this is needed - updateMeshTextures(); + // Don't know if this is needed + updateMeshTextures(); } //----------------------------------------------------------------------------- @@ -2635,21 +2635,21 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) //----------------------------------------------------------------------------- void LLVOAvatarSelf::requestLayerSetUpdate(ETextureIndex index ) { - /* switch(index) - case LOCTEX_UPPER_BODYPAINT: - case LOCTEX_UPPER_SHIRT: - if( mUpperBodyLayerSet ) - mUpperBodyLayerSet->requestUpdate(); */ - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = sAvatarDictionary->getTexture(index); - if (!texture_dict) - return; - if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) - return; - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - if (mBakedTextureDatas[baked_index].mTexLayerSet) - { - mBakedTextureDatas[baked_index].mTexLayerSet->requestUpdate(); - } + /* switch(index) + case LOCTEX_UPPER_BODYPAINT: + case LOCTEX_UPPER_SHIRT: + if( mUpperBodyLayerSet ) + mUpperBodyLayerSet->requestUpdate(); */ + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = sAvatarDictionary->getTexture(index); + if (!texture_dict) + return; + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + return; + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (mBakedTextureDatas[baked_index].mTexLayerSet) + { + mBakedTextureDatas[baked_index].mTexLayerSet->requestUpdate(); + } } LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(ETextureIndex index) const @@ -2675,7 +2675,7 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) return mHeadLayerSet; */ if (baked_index >= 0 && baked_index < BAKED_NUM_INDICES) { - return getTexLayerSet(baked_index); + return getTexLayerSet(baked_index); } return NULL; } @@ -2686,54 +2686,54 @@ LLViewerTexLayerSet* LLVOAvatarSelf::getLayerSet(EBakedTextureIndex baked_index) // static void LLVOAvatarSelf::onCustomizeStart(bool disable_camera_switch) { - if (isAgentAvatarValid()) - { - LLUIUsage::instance().logCommand("Avatar.CustomizeStart"); - if (!gAgentAvatarp->mEndCustomizeCallback.get()) - { - gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy; - } - - gAgentAvatarp->mIsEditingAppearance = true; - gAgentAvatarp->mUseLocalAppearance = true; - - if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) - { - gAgentCamera.changeCameraToCustomizeAvatar(); - } - - gAgentAvatarp->invalidateAll(); // mark all bakes as dirty, request updates - gAgentAvatarp->updateMeshTextures(); // make sure correct textures are applied to the avatar mesh. - gAgentAvatarp->updateTextures(); // call updateTextureStats - } + if (isAgentAvatarValid()) + { + LLUIUsage::instance().logCommand("Avatar.CustomizeStart"); + if (!gAgentAvatarp->mEndCustomizeCallback.get()) + { + gAgentAvatarp->mEndCustomizeCallback = new LLUpdateAppearanceOnDestroy; + } + + gAgentAvatarp->mIsEditingAppearance = true; + gAgentAvatarp->mUseLocalAppearance = true; + + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToCustomizeAvatar(); + } + + gAgentAvatarp->invalidateAll(); // mark all bakes as dirty, request updates + gAgentAvatarp->updateMeshTextures(); // make sure correct textures are applied to the avatar mesh. + gAgentAvatarp->updateTextures(); // call updateTextureStats + } } // static void LLVOAvatarSelf::onCustomizeEnd(bool disable_camera_switch) { - if (isAgentAvatarValid()) - { - gAgentAvatarp->mIsEditingAppearance = false; - gAgentAvatarp->invalidateAll(); + if (isAgentAvatarValid()) + { + gAgentAvatarp->mIsEditingAppearance = false; + gAgentAvatarp->invalidateAll(); - if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) - { - gAgentCamera.changeCameraToDefault(); - gAgentCamera.resetView(); - } + if (gSavedSettings.getBOOL("AppearanceCameraMovement") && !disable_camera_switch) + { + gAgentCamera.changeCameraToDefault(); + gAgentCamera.resetView(); + } - // Dereferencing the previous callback will cause - // updateAppearanceFromCOF to be called, whenever all refs - // have resolved. - gAgentAvatarp->mEndCustomizeCallback = NULL; - } + // Dereferencing the previous callback will cause + // updateAppearanceFromCOF to be called, whenever all refs + // have resolved. + gAgentAvatarp->mEndCustomizeCallback = NULL; + } } // virtual bool LLVOAvatarSelf::shouldRenderRigged() const { - return gAgent.needsRenderAvatar(); + return gAgent.needsRenderAvatar(); } // HACK: this will null out the avatar's local texture IDs before the TE message is sent @@ -2743,39 +2743,39 @@ bool LLVOAvatarSelf::shouldRenderRigged() const // This will involve further refactoring that is too risky for the initial release of 2.0. bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { - LLUUID texture_id[TEX_NUM_INDICES]; - // pack away current TEs to make sure we don't send them out - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); - iter != sAvatarDictionary->getTextures().end(); - ++iter) - { - const ETextureIndex index = iter->first; - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - if (!texture_dict->mIsBakedTexture) - { - LLTextureEntry* entry = getTE((U8) index); - texture_id[index] = entry->getID(); - entry->setID(IMG_DEFAULT_AVATAR); - } - } - - bool success = packTEMessage(mesgsys); - - // unpack TEs to make sure we don't re-trigger a bake - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); - iter != sAvatarDictionary->getTextures().end(); - ++iter) - { - const ETextureIndex index = iter->first; - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; - if (!texture_dict->mIsBakedTexture) - { - LLTextureEntry* entry = getTE((U8) index); - entry->setID(texture_id[index]); - } - } - - return success; + LLUUID texture_id[TEX_NUM_INDICES]; + // pack away current TEs to make sure we don't send them out + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsBakedTexture) + { + LLTextureEntry* entry = getTE((U8) index); + texture_id[index] = entry->getID(); + entry->setID(IMG_DEFAULT_AVATAR); + } + } + + bool success = packTEMessage(mesgsys); + + // unpack TEs to make sure we don't re-trigger a bake + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = sAvatarDictionary->getTextures().begin(); + iter != sAvatarDictionary->getTextures().end(); + ++iter) + { + const ETextureIndex index = iter->first; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; + if (!texture_dict->mIsBakedTexture) + { + LLTextureEntry* entry = getTE((U8) index); + entry->setID(texture_id[index]); + } + } + + return success; } //------------------------------------------------------------------------ @@ -2783,37 +2783,37 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const //------------------------------------------------------------------------ void LLVOAvatarSelf::sendHoverHeight() const { - std::string url = gAgent.getRegionCapability("AgentPreferences"); + std::string url = gAgent.getRegionCapability("AgentPreferences"); - if (!url.empty()) - { - LLSD update = LLSD::emptyMap(); - const LLVector3& hover_offset = getHoverOffset(); - update["hover_height"] = hover_offset[2]; + if (!url.empty()) + { + LLSD update = LLSD::emptyMap(); + const LLVector3& hover_offset = getHoverOffset(); + update["hover_height"] = hover_offset[2]; - LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "sending hover height value " << hover_offset[2] << LL_ENDL; // *TODO: - this class doesn't really do anything, could just use a base - // class responder if nothing else gets added. + // class responder if nothing else gets added. // (comment from removed Responder) - LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, update, + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, update, "Hover height sent to sim", "Hover height not sent to sim"); - mLastHoverOffsetSent = hover_offset; - } + mLastHoverOffsetSent = hover_offset; + } } void LLVOAvatarSelf::setHoverOffset(const LLVector3& hover_offset, bool send_update) { - if (getHoverOffset() != hover_offset) - { - LL_INFOS("Avatar") << avString() << " setting hover due to change " << hover_offset[2] << LL_ENDL; - LLVOAvatar::setHoverOffset(hover_offset, send_update); - } - if (send_update && (hover_offset != mLastHoverOffsetSent)) - { - LL_INFOS("Avatar") << avString() << " sending hover due to change " << hover_offset[2] << LL_ENDL; - sendHoverHeight(); - } + if (getHoverOffset() != hover_offset) + { + LL_INFOS("Avatar") << avString() << " setting hover due to change " << hover_offset[2] << LL_ENDL; + LLVOAvatar::setHoverOffset(hover_offset, send_update); + } + if (send_update && (hover_offset != mLastHoverOffsetSent)) + { + LL_INFOS("Avatar") << avString() << " sending hover due to change " << hover_offset[2] << LL_ENDL; + sendHoverHeight(); + } } //------------------------------------------------------------------------ @@ -2821,9 +2821,9 @@ void LLVOAvatarSelf::setHoverOffset(const LLVector3& hover_offset, bool send_upd //------------------------------------------------------------------------ BOOL LLVOAvatarSelf::needsRenderBeam() { - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - BOOL is_touching_or_grabbing = (tool == LLToolGrab::getInstance() && LLToolGrab::getInstance()->isEditing()); + BOOL is_touching_or_grabbing = (tool == LLToolGrab::getInstance() && LLToolGrab::getInstance()->isEditing()); LLViewerObject* objp = LLToolGrab::getInstance()->getEditingObject(); if (objp // might need to be "!objp ||" instead of "objp &&". && (objp->isAttachment() || objp->isAvatar())) @@ -2832,65 +2832,65 @@ BOOL LLVOAvatarSelf::needsRenderBeam() // attachments or avatars is_touching_or_grabbing = FALSE; } - return is_touching_or_grabbing || (getAttachmentState() & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); + return is_touching_or_grabbing || (getAttachmentState() & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); } // static void LLVOAvatarSelf::deleteScratchTextures() { - for(std::map< LLGLenum, LLGLuint*>::iterator it = sScratchTexNames.begin(), end_it = sScratchTexNames.end(); - it != end_it; - ++it) - { - LLImageGL::deleteTextures(1, (U32 *)it->second ); - stop_glerror(); - } + for(std::map< LLGLenum, LLGLuint*>::iterator it = sScratchTexNames.begin(), end_it = sScratchTexNames.end(); + it != end_it; + ++it) + { + LLImageGL::deleteTextures(1, (U32 *)it->second ); + stop_glerror(); + } - if( sScratchTexBytes.value() ) - { - LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << LL_ENDL; + if( sScratchTexBytes.value() ) + { + LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << LL_ENDL; - delete_and_clear(sScratchTexNames); - sScratchTexBytes = S32Bytes(0); - } + delete_and_clear(sScratchTexNames); + sScratchTexBytes = S32Bytes(0); + } } -// static +// static void LLVOAvatarSelf::dumpScratchTextureByteCount() { - LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; + LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; } void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) { - apr_file_t* file = outfile.getFileHandle(); - if (!file) - { - return; - } + apr_file_t* file = outfile.getFileHandle(); + if (!file) + { + return; + } + - - apr_file_printf( file, "\n\n" ); + apr_file_printf( file, "\n\n" ); - LLWearableData *wd = getWearableData(); + LLWearableData *wd = getWearableData(); LLWearableType *wr_inst = LLWearableType::getInstance(); - for (S32 type = 0; type < LLWearableType::WT_COUNT; type++) - { - const std::string& type_name = wr_inst->getTypeName((LLWearableType::EType)type); - for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++) - { - LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j); - apr_file_printf( file, "\n\t \n", - type_name.c_str(), wearable->getName().c_str() ); - LLWearable::visual_param_vec_t v_params; - wearable->getVisualParams(v_params); - for (LLWearable::visual_param_vec_t::iterator it = v_params.begin(); - it != v_params.end(); ++it) - { - LLVisualParam *param = *it; - dump_visual_param(file, param, param->getWeight()); - } - } - } - apr_file_printf( file, "\n\n" ); + for (S32 type = 0; type < LLWearableType::WT_COUNT; type++) + { + const std::string& type_name = wr_inst->getTypeName((LLWearableType::EType)type); + for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++) + { + LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j); + apr_file_printf( file, "\n\t \n", + type_name.c_str(), wearable->getName().c_str() ); + LLWearable::visual_param_vec_t v_params; + wearable->getVisualParams(v_params); + for (LLWearable::visual_param_vec_t::iterator it = v_params.begin(); + it != v_params.end(); ++it) + { + LLVisualParam *param = *it; + dump_visual_param(file, param, param->getWeight()); + } + } + } + apr_file_printf( file, "\n\n" ); } diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 8dad833eaa..bfac68b68f 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvocache.cpp * @brief Cache of objects on the viewer. * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -45,14 +45,14 @@ BOOL LLVOCachePartition::sNeedsOcclusionCheck = FALSE; const S32 ENTRY_HEADER_SIZE = 6 * sizeof(S32); const S32 MAX_ENTRY_BODY_SIZE = 10000; -BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) +BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) { - return apr_file->read(src, n_bytes) == n_bytes ; + return apr_file->read(src, n_bytes) == n_bytes ; } -BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) +BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) { - return apr_file->write(src, n_bytes) == n_bytes ; + return apr_file->write(src, n_bytes) == n_bytes ; } // Material Override Cache needs a version label, so we can upgrade this later. @@ -62,7 +62,7 @@ const int LLGLTFOverrideCacheEntry::VERSION = 1; bool LLGLTFOverrideCacheEntry::fromLLSD(const LLSD& data) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - + llassert(data.has("local_id")); llassert(data.has("object_id")); llassert(data.has("region_handle_x") && data.has("region_handle_y")); @@ -156,57 +156,57 @@ LLSD LLGLTFOverrideCacheEntry::toLLSD() const //--------------------------------------------------------------------------- LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) -: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), - mLocalID(local_id), - mCRC(crc), - mUpdateFlags(-1), - mHitCount(0), - mDupeCount(0), - mCRCChangeCount(0), - mState(INACTIVE), - mSceneContrib(0.f), - mValid(TRUE), - mParentID(0), - mBSphereRadius(-1.0f) -{ - mBuffer = new U8[dp.getBufferSize()]; - mDP.assignBuffer(mBuffer, dp.getBufferSize()); - mDP = dp; +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), + mLocalID(local_id), + mCRC(crc), + mUpdateFlags(-1), + mHitCount(0), + mDupeCount(0), + mCRCChangeCount(0), + mState(INACTIVE), + mSceneContrib(0.f), + mValid(TRUE), + mParentID(0), + mBSphereRadius(-1.0f) +{ + mBuffer = new U8[dp.getBufferSize()]; + mDP.assignBuffer(mBuffer, dp.getBufferSize()); + mDP = dp; } LLVOCacheEntry::LLVOCacheEntry() -: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), - mLocalID(0), - mCRC(0), - mUpdateFlags(-1), - mHitCount(0), - mDupeCount(0), - mCRCChangeCount(0), - mBuffer(NULL), - mState(INACTIVE), - mSceneContrib(0.f), - mValid(TRUE), - mParentID(0), - mBSphereRadius(-1.0f) -{ - mDP.assignBuffer(mBuffer, 0); +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), + mLocalID(0), + mCRC(0), + mUpdateFlags(-1), + mHitCount(0), + mDupeCount(0), + mCRCChangeCount(0), + mBuffer(NULL), + mState(INACTIVE), + mSceneContrib(0.f), + mValid(TRUE), + mParentID(0), + mBSphereRadius(-1.0f) +{ + mDP.assignBuffer(mBuffer, 0); } LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) -: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), - mBuffer(NULL), - mUpdateFlags(-1), - mState(INACTIVE), - mSceneContrib(0.f), - mValid(FALSE), - mParentID(0), - mBSphereRadius(-1.0f) -{ - S32 size = -1; - BOOL success; +: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), + mBuffer(NULL), + mUpdateFlags(-1), + mState(INACTIVE), + mSceneContrib(0.f), + mValid(FALSE), + mParentID(0), + mBSphereRadius(-1.0f) +{ + S32 size = -1; + BOOL success; static U8 data_buffer[ENTRY_HEADER_SIZE]; - mDP.assignBuffer(mBuffer, 0); + mDP.assignBuffer(mBuffer, 0); success = check_read(apr_file, (void *)data_buffer, ENTRY_HEADER_SIZE); if (success) @@ -218,216 +218,216 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) memcpy(&mCRCChangeCount, data_buffer + (4 * sizeof(U32)), sizeof(S32)); memcpy(&size, data_buffer + (5 * sizeof(U32)), sizeof(S32)); - // Corruption in the cache entries - if ((size > MAX_ENTRY_BODY_SIZE) || (size < 1)) - { - // We've got a bogus size, skip reading it. - // We won't bother seeking, because the rest of this file - // is likely bogus, and will be tossed anyway. - LL_WARNS() << "Bogus cache entry, size " << size << ", aborting!" << LL_ENDL; - success = FALSE; - } - } - if(success && size > 0) - { - mBuffer = new U8[size]; - success = check_read(apr_file, mBuffer, size); - - if(success) - { - mDP.assignBuffer(mBuffer, size); - } - else - { - // Improve logging around vocache - LL_WARNS() << "Error loading cache entry for " << mLocalID << ", size " << size << " aborting!" << LL_ENDL; - delete[] mBuffer ; - mBuffer = NULL ; - } - } - - if(!success) - { - mLocalID = 0; - mCRC = 0; - mHitCount = 0; - mDupeCount = 0; - mCRCChangeCount = 0; - mBuffer = NULL; - mEntry = NULL; - mState = INACTIVE; - } + // Corruption in the cache entries + if ((size > MAX_ENTRY_BODY_SIZE) || (size < 1)) + { + // We've got a bogus size, skip reading it. + // We won't bother seeking, because the rest of this file + // is likely bogus, and will be tossed anyway. + LL_WARNS() << "Bogus cache entry, size " << size << ", aborting!" << LL_ENDL; + success = FALSE; + } + } + if(success && size > 0) + { + mBuffer = new U8[size]; + success = check_read(apr_file, mBuffer, size); + + if(success) + { + mDP.assignBuffer(mBuffer, size); + } + else + { + // Improve logging around vocache + LL_WARNS() << "Error loading cache entry for " << mLocalID << ", size " << size << " aborting!" << LL_ENDL; + delete[] mBuffer ; + mBuffer = NULL ; + } + } + + if(!success) + { + mLocalID = 0; + mCRC = 0; + mHitCount = 0; + mDupeCount = 0; + mCRCChangeCount = 0; + mBuffer = NULL; + mEntry = NULL; + mState = INACTIVE; + } } LLVOCacheEntry::~LLVOCacheEntry() { - mDP.freeBuffer(); + mDP.freeBuffer(); } void LLVOCacheEntry::updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp) -{ - if(mCRC != crc) - { - mCRC = crc; - mCRCChangeCount++; - } - - mDP.freeBuffer(); - - llassert_always(dp.getBufferSize() > 0); - mBuffer = new U8[dp.getBufferSize()]; - mDP.assignBuffer(mBuffer, dp.getBufferSize()); - mDP = dp; +{ + if(mCRC != crc) + { + mCRC = crc; + mCRCChangeCount++; + } + + mDP.freeBuffer(); + + llassert_always(dp.getBufferSize() > 0); + mBuffer = new U8[dp.getBufferSize()]; + mDP.assignBuffer(mBuffer, dp.getBufferSize()); + mDP = dp; } -void LLVOCacheEntry::setParentID(U32 id) +void LLVOCacheEntry::setParentID(U32 id) { - if(mParentID != id) - { - removeAllChildren(); - mParentID = id; - } + if(mParentID != id) + { + removeAllChildren(); + mParentID = id; + } } void LLVOCacheEntry::removeAllChildren() { - if(mChildrenList.empty()) - { - return; - } + if(mChildrenList.empty()) + { + return; + } - for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter) - { - (*iter)->setParentID(0); - } - mChildrenList.clear(); + for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter) + { + (*iter)->setParentID(0); + } + mChildrenList.clear(); - return; + return; } -//virtual +//virtual void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry) { - if(!entry && mDP.getBufferSize() > 0) - { - LLUUID fullid; - LLViewerObject::unpackUUID(&mDP, fullid, "ID"); - - LLViewerObject* obj = gObjectList.findObject(fullid); - if(obj && obj->mDrawable) - { - entry = obj->mDrawable->getEntry(); - } - } - - LLViewerOctreeEntryData::setOctreeEntry(entry); + if(!entry && mDP.getBufferSize() > 0) + { + LLUUID fullid; + LLViewerObject::unpackUUID(&mDP, fullid, "ID"); + + LLViewerObject* obj = gObjectList.findObject(fullid); + if(obj && obj->mDrawable) + { + entry = obj->mDrawable->getEntry(); + } + } + + LLViewerOctreeEntryData::setOctreeEntry(entry); } void LLVOCacheEntry::setState(U32 state) { - if(state > LOW_BITS) //special states - { - mState |= (HIGH_BITS & state); - return; - } - - // - //otherwise LOW_BITS states - // - clearState(LOW_BITS); - mState |= (LOW_BITS & state); - - if(getState() == ACTIVE) - { - const S32 MIN_INTERVAL = 64 + sMinFrameRange; - U32 last_visible = getVisible(); - - setVisible(); - - U32 cur_visible = getVisible(); - if(cur_visible - last_visible > MIN_INTERVAL || - cur_visible < MIN_INTERVAL) - { - mLastCameraUpdated = 0; //reset - } - else - { - mLastCameraUpdated = LLViewerRegion::sLastCameraUpdated; - } - } + if(state > LOW_BITS) //special states + { + mState |= (HIGH_BITS & state); + return; + } + + // + //otherwise LOW_BITS states + // + clearState(LOW_BITS); + mState |= (LOW_BITS & state); + + if(getState() == ACTIVE) + { + const S32 MIN_INTERVAL = 64 + sMinFrameRange; + U32 last_visible = getVisible(); + + setVisible(); + + U32 cur_visible = getVisible(); + if(cur_visible - last_visible > MIN_INTERVAL || + cur_visible < MIN_INTERVAL) + { + mLastCameraUpdated = 0; //reset + } + else + { + mLastCameraUpdated = LLViewerRegion::sLastCameraUpdated; + } + } } void LLVOCacheEntry::addChild(LLVOCacheEntry* entry) { - llassert(entry != NULL); - llassert(entry->getParentID() == mLocalID); - llassert(entry->getEntry() != NULL); - - if(!entry || !entry->getEntry() || entry->getParentID() != mLocalID) - { - return; - } - - mChildrenList.insert(entry); - - //update parent bbox - if(getEntry() != NULL && isState(INACTIVE)) - { - updateParentBoundingInfo(entry); - resetVisible(); - } + llassert(entry != NULL); + llassert(entry->getParentID() == mLocalID); + llassert(entry->getEntry() != NULL); + + if(!entry || !entry->getEntry() || entry->getParentID() != mLocalID) + { + return; + } + + mChildrenList.insert(entry); + + //update parent bbox + if(getEntry() != NULL && isState(INACTIVE)) + { + updateParentBoundingInfo(entry); + resetVisible(); + } } - + void LLVOCacheEntry::removeChild(LLVOCacheEntry* entry) { - entry->setParentID(0); + entry->setParentID(0); - vocache_entry_set_t::iterator iter = mChildrenList.find(entry); - if(iter != mChildrenList.end()) - { - mChildrenList.erase(iter); - } + vocache_entry_set_t::iterator iter = mChildrenList.find(entry); + if(iter != mChildrenList.end()) + { + mChildrenList.erase(iter); + } } //remove the first child, and return it. LLVOCacheEntry* LLVOCacheEntry::getChild() { - LLVOCacheEntry* child = NULL; - vocache_entry_set_t::iterator iter = mChildrenList.begin(); - if(iter != mChildrenList.end()) - { - child = *iter; - mChildrenList.erase(iter); - } + LLVOCacheEntry* child = NULL; + vocache_entry_set_t::iterator iter = mChildrenList.begin(); + if(iter != mChildrenList.end()) + { + child = *iter; + mChildrenList.erase(iter); + } - return child; + return child; } LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() { - if (mDP.getBufferSize() == 0) - { - //LL_INFOS() << "Not getting cache entry, invalid!" << LL_ENDL; - return NULL; - } - - return &mDP; + if (mDP.getBufferSize() == 0) + { + //LL_INFOS() << "Not getting cache entry, invalid!" << LL_ENDL; + return NULL; + } + + return &mDP; } void LLVOCacheEntry::recordHit() { - mHitCount++; + mHitCount++; } void LLVOCacheEntry::dump() const { - LL_INFOS() << "local " << mLocalID - << " crc " << mCRC - << " hits " << mHitCount - << " dupes " << mDupeCount - << " change " << mCRCChangeCount - << LL_ENDL; + LL_INFOS() << "local " << mLocalID + << " crc " << mCRC + << " hits " << mHitCount + << " dupes " << mDupeCount + << " change " << mCRCChangeCount + << LL_ENDL; } S32 LLVOCacheEntry::writeToBuffer(U8 *data_buffer) const @@ -452,34 +452,34 @@ S32 LLVOCacheEntry::writeToBuffer(U8 *data_buffer) const } #ifndef LL_TEST -//static +//static void LLVOCacheEntry::updateDebugSettings() { - static LLFrameTimer timer; - if(timer.getElapsedTimeF32() < 1.0f) //update frequency once per second. - { - return; - } - timer.reset(); - - //objects within the view frustum whose visible area is greater than this threshold will be loaded - static LLCachedControl front_pixel_threshold(gSavedSettings,"SceneLoadFrontPixelThreshold"); - sFrontPixelThreshold = front_pixel_threshold; - - //objects out of the view frustum whose visible area is greater than this threshold will remain loaded - static LLCachedControl rear_pixel_threshold(gSavedSettings,"SceneLoadRearPixelThreshold"); - sRearPixelThreshold = rear_pixel_threshold; - sRearPixelThreshold = llmax(sRearPixelThreshold, sFrontPixelThreshold); //can not be smaller than sFrontPixelThreshold. - - //make parameters adaptive to memory usage - //starts to put restrictions from low_mem_bound_MB, apply tightest restrictions when hits high_mem_bound_MB - static LLCachedControl low_mem_bound_MB(gSavedSettings,"SceneLoadLowMemoryBound"); - static LLCachedControl high_mem_bound_MB(gSavedSettings,"SceneLoadHighMemoryBound"); - - LLMemory::updateMemoryInfo() ; - U32 allocated_mem = LLMemory::getAllocatedMemKB().value(); + static LLFrameTimer timer; + if(timer.getElapsedTimeF32() < 1.0f) //update frequency once per second. + { + return; + } + timer.reset(); + + //objects within the view frustum whose visible area is greater than this threshold will be loaded + static LLCachedControl front_pixel_threshold(gSavedSettings,"SceneLoadFrontPixelThreshold"); + sFrontPixelThreshold = front_pixel_threshold; + + //objects out of the view frustum whose visible area is greater than this threshold will remain loaded + static LLCachedControl rear_pixel_threshold(gSavedSettings,"SceneLoadRearPixelThreshold"); + sRearPixelThreshold = rear_pixel_threshold; + sRearPixelThreshold = llmax(sRearPixelThreshold, sFrontPixelThreshold); //can not be smaller than sFrontPixelThreshold. + + //make parameters adaptive to memory usage + //starts to put restrictions from low_mem_bound_MB, apply tightest restrictions when hits high_mem_bound_MB + static LLCachedControl low_mem_bound_MB(gSavedSettings,"SceneLoadLowMemoryBound"); + static LLCachedControl high_mem_bound_MB(gSavedSettings,"SceneLoadHighMemoryBound"); + + LLMemory::updateMemoryInfo() ; + U32 allocated_mem = LLMemory::getAllocatedMemKB().value(); static const F32 KB_to_MB = 1.f / 1024.f; - U32 clamped_memory = llclamp(allocated_mem * KB_to_MB, (F32) low_mem_bound_MB, (F32) high_mem_bound_MB); + U32 clamped_memory = llclamp(allocated_mem * KB_to_MB, (F32) low_mem_bound_MB, (F32) high_mem_bound_MB); const F32 adjust_range = high_mem_bound_MB - low_mem_bound_MB; const F32 adjust_factor = (high_mem_bound_MB - clamped_memory) / adjust_range; // [0, 1] @@ -506,613 +506,613 @@ void LLVOCacheEntry::updateDebugSettings() } #endif // LL_TEST -//static +//static F32 LLVOCacheEntry::getSquaredPixelThreshold(bool is_front) { - F32 threshold; - if(is_front) - { - threshold = sFrontPixelThreshold; - } - else - { - threshold = sRearPixelThreshold; - } - - //object projected area threshold - F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio(); - F32 projection_threshold = pixel_meter_ratio > 0.f ? threshold / pixel_meter_ratio : 0.f; - projection_threshold *= projection_threshold; - - return projection_threshold; + F32 threshold; + if(is_front) + { + threshold = sFrontPixelThreshold; + } + else + { + threshold = sRearPixelThreshold; + } + + //object projected area threshold + F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio(); + F32 projection_threshold = pixel_meter_ratio > 0.f ? threshold / pixel_meter_ratio : 0.f; + projection_threshold *= projection_threshold; + + return projection_threshold; } bool LLVOCacheEntry::isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold) { - LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)getGroup(); - if(!group) - { - return false; - } - - //any visible - bool vis = group->isAnyRecentlyVisible(); - - //not ready to remove - if(!vis) - { - S32 cur_vis = llmax(group->getAnyVisible(), (S32)getVisible()); - vis = (cur_vis + sMinFrameRange > LLViewerOctreeEntryData::getCurrentFrame()); - } - - //within the back sphere - if(!vis && !mParentID && !group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) - { - LLVector4a lookAt; - - if(mBSphereRadius > 0.f) - { - lookAt.setSub(mBSphereCenter, local_camera_origin); - dist_threshold += mBSphereRadius; - } - else - { - lookAt.setSub(getPositionGroup(), camera_origin); - dist_threshold += getBinRadius(); - } - - vis = (lookAt.dot3(lookAt).getF32() < dist_threshold * dist_threshold); - } - - return vis; + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)getGroup(); + if(!group) + { + return false; + } + + //any visible + bool vis = group->isAnyRecentlyVisible(); + + //not ready to remove + if(!vis) + { + S32 cur_vis = llmax(group->getAnyVisible(), (S32)getVisible()); + vis = (cur_vis + sMinFrameRange > LLViewerOctreeEntryData::getCurrentFrame()); + } + + //within the back sphere + if(!vis && !mParentID && !group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { + LLVector4a lookAt; + + if(mBSphereRadius > 0.f) + { + lookAt.setSub(mBSphereCenter, local_camera_origin); + dist_threshold += mBSphereRadius; + } + else + { + lookAt.setSub(getPositionGroup(), camera_origin); + dist_threshold += getBinRadius(); + } + + vis = (lookAt.dot3(lookAt).getF32() < dist_threshold * dist_threshold); + } + + return vis; } void LLVOCacheEntry::calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 max_dist) { - if(!needs_update && getVisible() >= last_update) - { - return; //no need to update - } - - LLVector4a lookAt; - lookAt.setSub(getPositionGroup(), camera_origin); - F32 distance = lookAt.getLength3().getF32(); - distance -= sNearRadius; - - if(distance <= 0.f) - { - //nearby objects, set a large number - const F32 LARGE_SCENE_CONTRIBUTION = 1000.f; //a large number to force to load the object. - mSceneContrib = LARGE_SCENE_CONTRIBUTION; - } - else - { - F32 rad = getBinRadius(); - max_dist += rad; - - if(distance + sNearRadius < max_dist) - { - mSceneContrib = (rad * rad) / distance; - } - else - { - mSceneContrib = 0.f; //out of draw distance, not to load - } - } - - setVisible(); + if(!needs_update && getVisible() >= last_update) + { + return; //no need to update + } + + LLVector4a lookAt; + lookAt.setSub(getPositionGroup(), camera_origin); + F32 distance = lookAt.getLength3().getF32(); + distance -= sNearRadius; + + if(distance <= 0.f) + { + //nearby objects, set a large number + const F32 LARGE_SCENE_CONTRIBUTION = 1000.f; //a large number to force to load the object. + mSceneContrib = LARGE_SCENE_CONTRIBUTION; + } + else + { + F32 rad = getBinRadius(); + max_dist += rad; + + if(distance + sNearRadius < max_dist) + { + mSceneContrib = (rad * rad) / distance; + } + else + { + mSceneContrib = 0.f; //out of draw distance, not to load + } + } + + setVisible(); } void LLVOCacheEntry::saveBoundingSphere() { - mBSphereCenter = getPositionGroup(); - mBSphereRadius = getBinRadius(); + mBSphereCenter = getPositionGroup(); + mBSphereRadius = getBinRadius(); } void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scale) { - LLVector4a center, newMin, newMax; - center.load3(pos.mV); - LLVector4a size; - size.load3(scale.mV); - newMin.setSub(center, size); - newMax.setAdd(center, size); - - setPositionGroup(center); - setSpatialExtents(newMin, newMax); - - if(getNumOfChildren() > 0) //has children - { - updateParentBoundingInfo(); - } - else - { - setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); - } + LLVector4a center, newMin, newMax; + center.load3(pos.mV); + LLVector4a size; + size.load3(scale.mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + setPositionGroup(center); + setSpatialExtents(newMin, newMax); + + if(getNumOfChildren() > 0) //has children + { + updateParentBoundingInfo(); + } + else + { + setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); + } } //make the parent bounding box to include all children void LLVOCacheEntry::updateParentBoundingInfo() { - if(mChildrenList.empty()) - { - return; - } + if(mChildrenList.empty()) + { + return; + } - for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter) - { - updateParentBoundingInfo(*iter); - } - resetVisible(); + for(vocache_entry_set_t::iterator iter = mChildrenList.begin(); iter != mChildrenList.end(); ++iter) + { + updateParentBoundingInfo(*iter); + } + resetVisible(); } //make the parent bounding box to include this child void LLVOCacheEntry::updateParentBoundingInfo(const LLVOCacheEntry* child) { - const LLVector4a* child_exts = child->getSpatialExtents(); - LLVector4a newMin, newMax; - newMin = child_exts[0]; - newMax = child_exts[1]; - - //move to regional space. - { - const LLVector4a& parent_pos = getPositionGroup(); - newMin.add(parent_pos); - newMax.add(parent_pos); - } - - //update parent's bbox(min, max) - const LLVector4a* parent_exts = getSpatialExtents(); - update_min_max(newMin, newMax, parent_exts[0]); - update_min_max(newMin, newMax, parent_exts[1]); - for(S32 i = 0; i < 4; i++) - { - llclamp(newMin[i], 0.f, 256.f); - llclamp(newMax[i], 0.f, 256.f); - } - setSpatialExtents(newMin, newMax); - - //update parent's bbox center - LLVector4a center; - center.setAdd(newMin, newMax); - center.mul(0.5f); - setPositionGroup(center); - - //update parent's bbox size vector - LLVector4a size; - size.setSub(newMax, newMin); - size.mul(0.5f); - setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); + const LLVector4a* child_exts = child->getSpatialExtents(); + LLVector4a newMin, newMax; + newMin = child_exts[0]; + newMax = child_exts[1]; + + //move to regional space. + { + const LLVector4a& parent_pos = getPositionGroup(); + newMin.add(parent_pos); + newMax.add(parent_pos); + } + + //update parent's bbox(min, max) + const LLVector4a* parent_exts = getSpatialExtents(); + update_min_max(newMin, newMax, parent_exts[0]); + update_min_max(newMin, newMax, parent_exts[1]); + for(S32 i = 0; i < 4; i++) + { + llclamp(newMin[i], 0.f, 256.f); + llclamp(newMax[i], 0.f, 256.f); + } + setSpatialExtents(newMin, newMax); + + //update parent's bbox center + LLVector4a center; + center.setAdd(newMin, newMax); + center.mul(0.5f); + setPositionGroup(center); + + //update parent's bbox size vector + LLVector4a size; + size.setSub(newMax, newMin); + size.mul(0.5f); + setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); } //------------------------------------------------------------------- //LLVOCachePartition //------------------------------------------------------------------- LLVOCacheGroup::~LLVOCacheGroup() { - if(mOcclusionState[LLViewerCamera::CAMERA_WORLD] & ACTIVE_OCCLUSION) - { - ((LLVOCachePartition*)mSpatialPartition)->removeOccluder(this); - } + if(mOcclusionState[LLViewerCamera::CAMERA_WORLD] & ACTIVE_OCCLUSION) + { + ((LLVOCachePartition*)mSpatialPartition)->removeOccluder(this); + } } //virtual void LLVOCacheGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { - if (child->getListenerCount() == 0) - { - new LLVOCacheGroup(child, mSpatialPartition); - } - else - { - OCT_ERRS << "LLVOCacheGroup redundancy detected." << LL_ENDL; - } - - unbound(); - - ((LLViewerOctreeGroup*)child->getListener(0))->unbound(); + if (child->getListenerCount() == 0) + { + new LLVOCacheGroup(child, mSpatialPartition); + } + else + { + OCT_ERRS << "LLVOCacheGroup redundancy detected." << LL_ENDL; + } + + unbound(); + + ((LLViewerOctreeGroup*)child->getListener(0))->unbound(); } LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) { - mLODPeriod = 16; - mRegionp = regionp; - mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; - mBackSlectionEnabled = -1; - mIdleHash = 0; - - for(S32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mCulledTime[i] = 0; - } - mCullHistory = -1; - - new LLVOCacheGroup(mOctree, this); + mLODPeriod = 16; + mRegionp = regionp; + mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; + mBackSlectionEnabled = -1; + mIdleHash = 0; + + for(S32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mCulledTime[i] = 0; + } + mCullHistory = -1; + + new LLVOCacheGroup(mOctree, this); } LLVOCachePartition::~LLVOCachePartition() { // SL-17276 make sure to do base class cleanup while this instance - // can still be treated as an LLVOCachePartition + // can still be treated as an LLVOCachePartition cleanup(); } bool LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry) { - llassert(entry->hasVOCacheEntry()); + llassert(entry->hasVOCacheEntry()); - if(!llfinite(entry->getBinRadius()) || !entry->getPositionGroup().isFinite3()) - { - return false; //data corrupted - } + if(!llfinite(entry->getBinRadius()) || !entry->getPositionGroup().isFinite3()) + { + return false; //data corrupted + } - mOctree->insert(entry); + mOctree->insert(entry); - return true; + return true; } - + void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry) { - entry->getVOCacheEntry()->setGroup(NULL); + entry->getVOCacheEntry()->setGroup(NULL); - llassert(!entry->getGroup()); + llassert(!entry->getGroup()); } - + class LLVOCacheOctreeCull : public LLViewerOctreeCull { public: - LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, - const LLVector3& shift, bool use_object_cache_occlusion, F32 pixel_threshold, LLVOCachePartition* part) - : LLViewerOctreeCull(camera), - mRegionp(regionp), - mPartition(part), - mPixelThreshold(pixel_threshold) - { - mLocalShift = shift; - mUseObjectCacheOcclusion = use_object_cache_occlusion; - mNearRadius = LLVOCacheEntry::sNearRadius; - } - - virtual bool earlyFail(LLViewerOctreeGroup* base_group) - { - if( mUseObjectCacheOcclusion && - base_group->getOctreeNode()->getParent()) //never occlusion cull the root node - { - LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; - if(group->needsUpdate()) - { - //needs to issue new occlusion culling check, perform view culling check first. - return false; - } - - group->checkOcclusion(); - - if (group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) - { - return true; - } - } - - return false; - } - - virtual S32 frustumCheck(const LLViewerOctreeGroup* group) - { + LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, + const LLVector3& shift, bool use_object_cache_occlusion, F32 pixel_threshold, LLVOCachePartition* part) + : LLViewerOctreeCull(camera), + mRegionp(regionp), + mPartition(part), + mPixelThreshold(pixel_threshold) + { + mLocalShift = shift; + mUseObjectCacheOcclusion = use_object_cache_occlusion; + mNearRadius = LLVOCacheEntry::sNearRadius; + } + + virtual bool earlyFail(LLViewerOctreeGroup* base_group) + { + if( mUseObjectCacheOcclusion && + base_group->getOctreeNode()->getParent()) //never occlusion cull the root node + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; + if(group->needsUpdate()) + { + //needs to issue new occlusion culling check, perform view culling check first. + return false; + } + + group->checkOcclusion(); + + if (group->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { + return true; + } + } + + return false; + } + + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) + { #if 0 - S32 res = AABBInRegionFrustumGroupBounds(group); -#else - S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group); - if (res != 0) - { - res = llmin(res, AABBRegionSphereIntersectGroupExtents(group, mLocalShift)); - } + S32 res = AABBInRegionFrustumGroupBounds(group); +#else + S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group); + if (res != 0) + { + res = llmin(res, AABBRegionSphereIntersectGroupExtents(group, mLocalShift)); + } #endif - return res; - } + return res; + } - virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) - { + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) + { #if 0 - S32 res = AABBInRegionFrustumObjectBounds(group); + S32 res = AABBInRegionFrustumObjectBounds(group); #else - S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group); - if (res != 0) - { - res = llmin(res, AABBRegionSphereIntersectObjectExtents(group, mLocalShift)); - } + S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group); + if (res != 0) + { + res = llmin(res, AABBRegionSphereIntersectObjectExtents(group, mLocalShift)); + } #endif - if(res != 0) - { - //check if the objects projection large enough - const LLVector4a* exts = group->getObjectExtents(); - res = checkProjectionArea(exts[0], exts[1], mLocalShift, mPixelThreshold, mNearRadius); - } - - return res; - } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - if( !mUseObjectCacheOcclusion || - !base_group->getOctreeNode()->getParent()) - { - //no occlusion check - if(mRegionp->addVisibleGroup(base_group)) - { - base_group->setVisible(); - } - return; - } - - LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; - if(group->needsUpdate() || !group->isRecentlyVisible())//needs to issue new occlusion culling check. - { - mPartition->addOccluders(group); - group->setVisible(); - return ; //wait for occlusion culling result - } - - if(group->isOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING) || - group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) - { - //keep waiting - group->setVisible(); - } - else - { - if(mRegionp->addVisibleGroup(base_group)) - { - base_group->setVisible(); - } - } - } + if(res != 0) + { + //check if the objects projection large enough + const LLVector4a* exts = group->getObjectExtents(); + res = checkProjectionArea(exts[0], exts[1], mLocalShift, mPixelThreshold, mNearRadius); + } + + return res; + } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + if( !mUseObjectCacheOcclusion || + !base_group->getOctreeNode()->getParent()) + { + //no occlusion check + if(mRegionp->addVisibleGroup(base_group)) + { + base_group->setVisible(); + } + return; + } + + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; + if(group->needsUpdate() || !group->isRecentlyVisible())//needs to issue new occlusion culling check. + { + mPartition->addOccluders(group); + group->setVisible(); + return ; //wait for occlusion culling result + } + + if(group->isOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING) || + group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) + { + //keep waiting + group->setVisible(); + } + else + { + if(mRegionp->addVisibleGroup(base_group)) + { + base_group->setVisible(); + } + } + } private: - LLVOCachePartition* mPartition; - LLViewerRegion* mRegionp; - LLVector3 mLocalShift; //shift vector from agent space to local region space. - F32 mPixelThreshold; - F32 mNearRadius; - bool mUseObjectCacheOcclusion; + LLVOCachePartition* mPartition; + LLViewerRegion* mRegionp; + LLVector3 mLocalShift; //shift vector from agent space to local region space. + F32 mPixelThreshold; + F32 mNearRadius; + bool mUseObjectCacheOcclusion; }; //select objects behind camera class LLVOCacheOctreeBackCull : public LLViewerOctreeCull { public: - LLVOCacheOctreeBackCull(LLCamera* camera, const LLVector3& shift, LLViewerRegion* regionp, F32 pixel_threshold, bool use_occlusion) - : LLViewerOctreeCull(camera), mRegionp(regionp), mPixelThreshold(pixel_threshold), mUseObjectCacheOcclusion(use_occlusion) - { - mLocalShift = shift; - mSphereRadius = LLVOCacheEntry::sRearFarRadius; - } - - virtual bool earlyFail(LLViewerOctreeGroup* base_group) - { - if( mUseObjectCacheOcclusion && - base_group->getOctreeNode()->getParent()) //never occlusion cull the root node - { - LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; - - if (group->getOcclusionState() > 0) //occlusion state is not clear. - { - return true; - } - } - - return false; - } - - virtual S32 frustumCheck(const LLViewerOctreeGroup* group) - { - const LLVector4a* exts = group->getExtents(); - return backSphereCheck(exts[0], exts[1]); - } - - virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) - { - const LLVector4a* exts = group->getObjectExtents(); - if(backSphereCheck(exts[0], exts[1])) - { - //check if the objects projection large enough - const LLVector4a* exts = group->getObjectExtents(); - return checkProjectionArea(exts[0], exts[1], mLocalShift, mPixelThreshold, mSphereRadius); - } - return false; - } - - virtual void processGroup(LLViewerOctreeGroup* base_group) - { - mRegionp->addVisibleGroup(base_group); - return; - } + LLVOCacheOctreeBackCull(LLCamera* camera, const LLVector3& shift, LLViewerRegion* regionp, F32 pixel_threshold, bool use_occlusion) + : LLViewerOctreeCull(camera), mRegionp(regionp), mPixelThreshold(pixel_threshold), mUseObjectCacheOcclusion(use_occlusion) + { + mLocalShift = shift; + mSphereRadius = LLVOCacheEntry::sRearFarRadius; + } + + virtual bool earlyFail(LLViewerOctreeGroup* base_group) + { + if( mUseObjectCacheOcclusion && + base_group->getOctreeNode()->getParent()) //never occlusion cull the root node + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; + + if (group->getOcclusionState() > 0) //occlusion state is not clear. + { + return true; + } + } + + return false; + } + + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) + { + const LLVector4a* exts = group->getExtents(); + return backSphereCheck(exts[0], exts[1]); + } + + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) + { + const LLVector4a* exts = group->getObjectExtents(); + if(backSphereCheck(exts[0], exts[1])) + { + //check if the objects projection large enough + const LLVector4a* exts = group->getObjectExtents(); + return checkProjectionArea(exts[0], exts[1], mLocalShift, mPixelThreshold, mSphereRadius); + } + return false; + } + + virtual void processGroup(LLViewerOctreeGroup* base_group) + { + mRegionp->addVisibleGroup(base_group); + return; + } private: - //a sphere around the camera origin, including objects behind camera. - S32 backSphereCheck(const LLVector4a& min, const LLVector4a& max) - { - return AABBSphereIntersect(min, max, mCamera->getOrigin() - mLocalShift, mSphereRadius); - } + //a sphere around the camera origin, including objects behind camera. + S32 backSphereCheck(const LLVector4a& min, const LLVector4a& max) + { + return AABBSphereIntersect(min, max, mCamera->getOrigin() - mLocalShift, mSphereRadius); + } private: - F32 mSphereRadius; - LLViewerRegion* mRegionp; - LLVector3 mLocalShift; //shift vector from agent space to local region space. - F32 mPixelThreshold; - bool mUseObjectCacheOcclusion; + F32 mSphereRadius; + LLViewerRegion* mRegionp; + LLVector3 mLocalShift; //shift vector from agent space to local region space. + F32 mPixelThreshold; + bool mUseObjectCacheOcclusion; }; void LLVOCachePartition::selectBackObjects(LLCamera &camera, F32 pixel_threshold, bool use_occlusion) { - if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) - { - return; - } - - if(mBackSlectionEnabled < 0) - { - mBackSlectionEnabled = LLVOCacheEntry::sMinFrameRange - 1; - mBackSlectionEnabled = llmax(mBackSlectionEnabled, (S32)1); - } - - if(!mBackSlectionEnabled) - { - return; - } - - //localize the camera - LLVector3 region_agent = mRegionp->getOriginAgent(); - - LLVOCacheOctreeBackCull culler(&camera, region_agent, mRegionp, pixel_threshold, use_occlusion); - culler.traverse(mOctree); - - mBackSlectionEnabled--; - if(!mRegionp->getNumOfVisibleGroups()) - { - mBackSlectionEnabled = 0; - } - - return; + if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + return; + } + + if(mBackSlectionEnabled < 0) + { + mBackSlectionEnabled = LLVOCacheEntry::sMinFrameRange - 1; + mBackSlectionEnabled = llmax(mBackSlectionEnabled, (S32)1); + } + + if(!mBackSlectionEnabled) + { + return; + } + + //localize the camera + LLVector3 region_agent = mRegionp->getOriginAgent(); + + LLVOCacheOctreeBackCull culler(&camera, region_agent, mRegionp, pixel_threshold, use_occlusion); + culler.traverse(mOctree); + + mBackSlectionEnabled--; + if(!mRegionp->getNumOfVisibleGroups()) + { + mBackSlectionEnabled = 0; + } + + return; } #ifndef LL_TEST S32 LLVOCachePartition::cull(LLCamera &camera, bool do_occlusion) { - static LLCachedControl use_object_cache_occlusion(gSavedSettings,"UseObjectCacheOcclusion"); - - if(!LLViewerRegion::sVOCacheCullingEnabled) - { - return 0; - } - if(mRegionp->isPaused()) - { - return 0; - } - - ((LLViewerOctreeGroup*)mOctree->getListener(0))->rebound(); - - if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) - { - return 0; //no need for those cameras. - } - - if(mCulledTime[LLViewerCamera::sCurCameraID] == LLViewerOctreeEntryData::getCurrentFrame()) - { - return 0; //already culled - } - mCulledTime[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); - - if(!mCullHistory && LLViewerRegion::isViewerCameraStatic()) - { - U32 seed = llmax(mLODPeriod >> 1, (U32)4); - if(LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - if(!(LLViewerOctreeEntryData::getCurrentFrame() % seed)) - { - mIdleHash = (mIdleHash + 1) % seed; - } - } - if(LLViewerOctreeEntryData::getCurrentFrame() % seed != mIdleHash) - { - mFrontCull = FALSE; - - //process back objects selection - selectBackObjects(camera, LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull), - do_occlusion && use_object_cache_occlusion); - return 0; //nothing changed, reduce frequency of culling - } - } - else - { - mBackSlectionEnabled = -1; //reset it. - } - - //localize the camera - LLVector3 region_agent = mRegionp->getOriginAgent(); - camera.calcRegionFrustumPlanes(region_agent, gAgentCamera.mDrawDistance); - - mFrontCull = TRUE; - LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, do_occlusion && use_object_cache_occlusion, - LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull), this); - culler.traverse(mOctree); - - if(!sNeedsOcclusionCheck) - { - sNeedsOcclusionCheck = !mOccludedGroups.empty(); - } - return 1; + static LLCachedControl use_object_cache_occlusion(gSavedSettings,"UseObjectCacheOcclusion"); + + if(!LLViewerRegion::sVOCacheCullingEnabled) + { + return 0; + } + if(mRegionp->isPaused()) + { + return 0; + } + + ((LLViewerOctreeGroup*)mOctree->getListener(0))->rebound(); + + if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + return 0; //no need for those cameras. + } + + if(mCulledTime[LLViewerCamera::sCurCameraID] == LLViewerOctreeEntryData::getCurrentFrame()) + { + return 0; //already culled + } + mCulledTime[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); + + if(!mCullHistory && LLViewerRegion::isViewerCameraStatic()) + { + U32 seed = llmax(mLODPeriod >> 1, (U32)4); + if(LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + if(!(LLViewerOctreeEntryData::getCurrentFrame() % seed)) + { + mIdleHash = (mIdleHash + 1) % seed; + } + } + if(LLViewerOctreeEntryData::getCurrentFrame() % seed != mIdleHash) + { + mFrontCull = FALSE; + + //process back objects selection + selectBackObjects(camera, LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull), + do_occlusion && use_object_cache_occlusion); + return 0; //nothing changed, reduce frequency of culling + } + } + else + { + mBackSlectionEnabled = -1; //reset it. + } + + //localize the camera + LLVector3 region_agent = mRegionp->getOriginAgent(); + camera.calcRegionFrustumPlanes(region_agent, gAgentCamera.mDrawDistance); + + mFrontCull = TRUE; + LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, do_occlusion && use_object_cache_occlusion, + LLVOCacheEntry::getSquaredPixelThreshold(mFrontCull), this); + culler.traverse(mOctree); + + if(!sNeedsOcclusionCheck) + { + sNeedsOcclusionCheck = !mOccludedGroups.empty(); + } + return 1; } #endif // LL_TEST void LLVOCachePartition::setCullHistory(BOOL has_new_object) { - mCullHistory <<= 1; - mCullHistory |= has_new_object; + mCullHistory <<= 1; + mCullHistory |= has_new_object; } void LLVOCachePartition::addOccluders(LLViewerOctreeGroup* gp) { - LLVOCacheGroup* group = (LLVOCacheGroup*)gp; + LLVOCacheGroup* group = (LLVOCacheGroup*)gp; - if(!group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) - { - group->setOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); - mOccludedGroups.insert(group); - } + if(!group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) + { + group->setOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); + mOccludedGroups.insert(group); + } } void LLVOCachePartition::processOccluders(LLCamera* camera) { - if(mOccludedGroups.empty()) - { - return; - } - if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) - { - return; //no need for those cameras. - } - - LLVector3 region_agent = mRegionp->getOriginAgent(); - LLVector4a shift(region_agent[0], region_agent[1], region_agent[2]); - for(std::set::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter) - { - LLVOCacheGroup* group = *iter; - if(group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) - { - group->doOcclusion(camera, &shift); - group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); - } - } - - //safe to clear mOccludedGroups here because only the world camera accesses it. - mOccludedGroups.clear(); - sNeedsOcclusionCheck = FALSE; + if(mOccludedGroups.empty()) + { + return; + } + if(LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) + { + return; //no need for those cameras. + } + + LLVector3 region_agent = mRegionp->getOriginAgent(); + LLVector4a shift(region_agent[0], region_agent[1], region_agent[2]); + for(std::set::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter) + { + LLVOCacheGroup* group = *iter; + if(group->isOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION)) + { + group->doOcclusion(camera, &shift); + group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); + } + } + + //safe to clear mOccludedGroups here because only the world camera accesses it. + mOccludedGroups.clear(); + sNeedsOcclusionCheck = FALSE; } void LLVOCachePartition::resetOccluders() { - if(mOccludedGroups.empty()) - { - return; - } - - for(std::set::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter) - { - LLVOCacheGroup* group = *iter; - group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); - } - mOccludedGroups.clear(); - sNeedsOcclusionCheck = FALSE; + if(mOccludedGroups.empty()) + { + return; + } + + for(std::set::iterator iter = mOccludedGroups.begin(); iter != mOccludedGroups.end(); ++iter) + { + LLVOCacheGroup* group = *iter; + group->clearOcclusionState(LLOcclusionCullingGroup::ACTIVE_OCCLUSION); + } + mOccludedGroups.clear(); + sNeedsOcclusionCheck = FALSE; } void LLVOCachePartition::removeOccluder(LLVOCacheGroup* group) { - if(mOccludedGroups.empty()) - { - return; - } - mOccludedGroups.erase(group); + if(mOccludedGroups.empty()) + { + return; + } + mOccludedGroups.erase(group); } //------------------------------------------------------------------- //LLVOCache @@ -1129,148 +1129,148 @@ const char* header_filename = "object.cache"; LLVOCache::LLVOCache(bool read_only) : - mInitialized(false), - mReadOnly(read_only), - mNumEntries(0), - mCacheSize(1), + mInitialized(false), + mReadOnly(read_only), + mNumEntries(0), + mCacheSize(1), mEnabled(true) { #ifndef LL_TEST - mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); + mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); #endif - mLocalAPRFilePoolp = new LLVolatileAPRPool() ; + mLocalAPRFilePoolp = new LLVolatileAPRPool() ; } LLVOCache::~LLVOCache() { - if(mEnabled) - { - writeCacheHeader(); - clearCacheInMemory(); - } - delete mLocalAPRFilePoolp; + if(mEnabled) + { + writeCacheHeader(); + clearCacheInMemory(); + } + delete mLocalAPRFilePoolp; } void LLVOCache::setDirNames(ELLPath location) { - mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); - mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); + mHeaderFileName = gDirUtilp->getExpandedFilename(location, object_cache_dirname, header_filename); + mObjectCacheDirName = gDirUtilp->getExpandedFilename(location, object_cache_dirname); } void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) { - if(!mEnabled) - { - LL_WARNS() << "Not initializing cache: Cache is currently disabled." << LL_ENDL; - return ; - } - - if(mInitialized) - { - LL_WARNS() << "Cache already initialized." << LL_ENDL; - return ; - } - mInitialized = true; - - setDirNames(location); - if (!mReadOnly) - { - LLFile::mkdir(mObjectCacheDirName); - } - mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES); - mMetaInfo.mVersion = cache_version; + if(!mEnabled) + { + LL_WARNS() << "Not initializing cache: Cache is currently disabled." << LL_ENDL; + return ; + } + + if(mInitialized) + { + LL_WARNS() << "Cache already initialized." << LL_ENDL; + return ; + } + mInitialized = true; + + setDirNames(location); + if (!mReadOnly) + { + LLFile::mkdir(mObjectCacheDirName); + } + mCacheSize = llclamp(size, MIN_ENTRIES_TO_PURGE, MAX_NUM_OBJECT_ENTRIES); + mMetaInfo.mVersion = cache_version; #if defined(ADDRESS_SIZE) - U32 expected_address = ADDRESS_SIZE; + U32 expected_address = ADDRESS_SIZE; #else - U32 expected_address = 32; + U32 expected_address = 32; #endif - mMetaInfo.mAddressSize = expected_address; - - readCacheHeader(); - - LL_INFOS() << "Viewer Object Cache Versions - expected: " << cache_version << " found: " << mMetaInfo.mVersion << LL_ENDL; - - if( mMetaInfo.mVersion != cache_version - || mMetaInfo.mAddressSize != expected_address) - { - mMetaInfo.mVersion = cache_version ; - mMetaInfo.mAddressSize = expected_address; - if(mReadOnly) //disable cache - { - clearCacheInMemory(); - } - else //delete the current cache if the format does not match. - { - LL_INFOS() << "Viewer Object Cache Versions unmatched. clearing cache." << LL_ENDL; - removeCache(); - } - } + mMetaInfo.mAddressSize = expected_address; + + readCacheHeader(); + + LL_INFOS() << "Viewer Object Cache Versions - expected: " << cache_version << " found: " << mMetaInfo.mVersion << LL_ENDL; + + if( mMetaInfo.mVersion != cache_version + || mMetaInfo.mAddressSize != expected_address) + { + mMetaInfo.mVersion = cache_version ; + mMetaInfo.mAddressSize = expected_address; + if(mReadOnly) //disable cache + { + clearCacheInMemory(); + } + else //delete the current cache if the format does not match. + { + LL_INFOS() << "Viewer Object Cache Versions unmatched. clearing cache." << LL_ENDL; + removeCache(); + } + } } - -void LLVOCache::removeCache(ELLPath location, bool started) -{ - if(started) - { - removeCache(); - return; - } - - if(mReadOnly) - { - LL_WARNS() << "Not removing cache at " << location << ": Cache is currently in read-only mode." << LL_ENDL; - return ; - } - - LL_INFOS() << "about to remove the object cache due to settings." << LL_ENDL ; - - std::string mask = "*"; - std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); - LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL; - gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files - LLFile::rmdir(cache_dir); - - clearCacheInMemory(); - mInitialized = false; + +void LLVOCache::removeCache(ELLPath location, bool started) +{ + if(started) + { + removeCache(); + return; + } + + if(mReadOnly) + { + LL_WARNS() << "Not removing cache at " << location << ": Cache is currently in read-only mode." << LL_ENDL; + return ; + } + + LL_INFOS() << "about to remove the object cache due to settings." << LL_ENDL ; + + std::string mask = "*"; + std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname); + LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL; + gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files + LLFile::rmdir(cache_dir); + + clearCacheInMemory(); + mInitialized = false; } -void LLVOCache::removeCache() +void LLVOCache::removeCache() { - if(!mInitialized) - { - //OK to remove cache even it is not initialized. - LL_WARNS() << "Object cache is not initialized yet." << LL_ENDL; - } + if(!mInitialized) + { + //OK to remove cache even it is not initialized. + LL_WARNS() << "Object cache is not initialized yet." << LL_ENDL; + } - if(mReadOnly) - { - LL_WARNS() << "Not clearing object cache: Cache is currently in read-only mode." << LL_ENDL; - return ; - } + if(mReadOnly) + { + LL_WARNS() << "Not clearing object cache: Cache is currently in read-only mode." << LL_ENDL; + return ; + } - std::string mask = "*"; - LL_INFOS() << "Removing object cache at " << mObjectCacheDirName << LL_ENDL; - gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); + std::string mask = "*"; + LL_INFOS() << "Removing object cache at " << mObjectCacheDirName << LL_ENDL; + gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); - clearCacheInMemory() ; - writeCacheHeader(); + clearCacheInMemory() ; + writeCacheHeader(); } -void LLVOCache::removeEntry(HeaderEntryInfo* entry) -{ - llassert_always(mInitialized); - if(mReadOnly) - { - return; - } - if(!entry) - { - return; - } - // Bit more tracking of cache creation/destruction. - std::string filename; - getObjectCacheFilename(entry->mHandle, filename); - LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL; +void LLVOCache::removeEntry(HeaderEntryInfo* entry) +{ + llassert_always(mInitialized); + if(mReadOnly) + { + return; + } + if(!entry) + { + return; + } + // Bit more tracking of cache creation/destruction. + std::string filename; + getObjectCacheFilename(entry->mHandle, filename); + LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL; // make sure corresponding LLViewerRegion also clears its in-memory cache LLViewerRegion* regionp = LLWorld::instance().getRegionFromHandle(entry->mHandle); @@ -1279,53 +1279,53 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry) regionp->clearVOCacheFromMemory(); } - header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); - if(iter != mHeaderEntryQueue.end()) - { - mHandleEntryMap.erase(entry->mHandle); - mHeaderEntryQueue.erase(iter); - removeFromCache(entry); - delete entry; + header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); + if(iter != mHeaderEntryQueue.end()) + { + mHandleEntryMap.erase(entry->mHandle); + mHeaderEntryQueue.erase(iter); + removeFromCache(entry); + delete entry; - mNumEntries = mHandleEntryMap.size() ; - } + mNumEntries = mHandleEntryMap.size() ; + } } -void LLVOCache::removeEntry(U64 handle) +void LLVOCache::removeEntry(U64 handle) { - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //no cache - { - return ; - } - HeaderEntryInfo* entry = iter->second ; - removeEntry(entry) ; + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //no cache + { + return ; + } + HeaderEntryInfo* entry = iter->second ; + removeEntry(entry) ; } void LLVOCache::clearCacheInMemory() { - if(!mHeaderEntryQueue.empty()) - { - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter) - { - delete *iter ; - } - mHeaderEntryQueue.clear(); - mHandleEntryMap.clear(); - mNumEntries = 0 ; - } + if(!mHeaderEntryQueue.empty()) + { + for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin(); iter != mHeaderEntryQueue.end(); ++iter) + { + delete *iter ; + } + mHeaderEntryQueue.clear(); + mHandleEntryMap.clear(); + mNumEntries = 0 ; + } } -void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) +void LLVOCache::getObjectCacheFilename(U64 handle, std::string& filename) { - U32 region_x, region_y; + U32 region_x, region_y; - grid_from_region_handle(handle, ®ion_x, ®ion_y); - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, - llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); + grid_from_region_handle(handle, ®ion_x, ®ion_y); + filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, object_cache_dirname, + llformat(OBJECT_CACHE_FILENAME, region_x, region_y)); - return ; + return ; } std::string LLVOCache::getObjectCacheExtrasFilename(U64 handle) @@ -1339,238 +1339,238 @@ std::string LLVOCache::getObjectCacheExtrasFilename(U64 handle) void LLVOCache::removeFromCache(HeaderEntryInfo* entry) { - if(mReadOnly) - { - LL_WARNS() << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << LL_ENDL; - return ; - } + if(mReadOnly) + { + LL_WARNS() << "Not removing cache for handle " << entry->mHandle << ": Cache is currently in read-only mode." << LL_ENDL; + return ; + } - std::string filename; - getObjectCacheFilename(entry->mHandle, filename); + std::string filename; + getObjectCacheFilename(entry->mHandle, filename); LL_WARNS("GLTF", "VOCache") << "Removing object cache for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL; - LLAPRFile::remove(filename, mLocalAPRFilePoolp); - + LLAPRFile::remove(filename, mLocalAPRFilePoolp); + // Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry. - // as such this now includes the generic extras + // as such this now includes the generic extras filename = getObjectCacheExtrasFilename(entry->mHandle); LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL; LLFile::remove(filename); - entry->mTime = INVALID_TIME ; - updateEntry(entry) ; //update the head file. + entry->mTime = INVALID_TIME ; + updateEntry(entry) ; //update the head file. } void LLVOCache::readCacheHeader() { - if(!mEnabled) - { - LL_WARNS() << "Not reading cache header: Cache is currently disabled." << LL_ENDL; - return; - } - - //clear stale info. - clearCacheInMemory(); - - bool success = true ; - if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) - { - LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - - //read the meta element - success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; - - if(success) - { - HeaderEntryInfo* entry = NULL ; - mNumEntries = 0 ; - U32 num_read = 0 ; - while(num_read++ < MAX_NUM_OBJECT_ENTRIES) - { - if(!entry) - { - entry = new HeaderEntryInfo() ; - } - success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); - - if(!success) //failed - { - LL_WARNS() << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << LL_ENDL; - delete entry ; - entry = NULL ; - break ; - } - else if(entry->mTime == INVALID_TIME) - { - continue ; //an empty entry - } - - entry->mIndex = mNumEntries++ ; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[entry->mHandle] = entry ; - entry = NULL ; - } - if(entry) - { - delete entry ; - } - } - - //--------- - //debug code - //---------- - //std::string name ; - //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) - //{ - // getObjectCacheFilename((*iter)->mHandle, name) ; - // LL_INFOS() << name << LL_ENDL ; - //} - //----------- - } - else - { - writeCacheHeader() ; - } - - if(!success) - { - removeCache() ; //failed to read header, clear the cache - } - else if(mNumEntries >= mCacheSize) - { - purgeEntries(mCacheSize) ; - } - - return ; + if(!mEnabled) + { + LL_WARNS() << "Not reading cache header: Cache is currently disabled." << LL_ENDL; + return; + } + + //clear stale info. + clearCacheInMemory(); + + bool success = true ; + if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp)) + { + LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + + //read the meta element + success = check_read(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + if(success) + { + HeaderEntryInfo* entry = NULL ; + mNumEntries = 0 ; + U32 num_read = 0 ; + while(num_read++ < MAX_NUM_OBJECT_ENTRIES) + { + if(!entry) + { + entry = new HeaderEntryInfo() ; + } + success = check_read(&apr_file, entry, sizeof(HeaderEntryInfo)); + + if(!success) //failed + { + LL_WARNS() << "Error reading cache header entry. (entry_index=" << mNumEntries << ")" << LL_ENDL; + delete entry ; + entry = NULL ; + break ; + } + else if(entry->mTime == INVALID_TIME) + { + continue ; //an empty entry + } + + entry->mIndex = mNumEntries++ ; + mHeaderEntryQueue.insert(entry) ; + mHandleEntryMap[entry->mHandle] = entry ; + entry = NULL ; + } + if(entry) + { + delete entry ; + } + } + + //--------- + //debug code + //---------- + //std::string name ; + //for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) + //{ + // getObjectCacheFilename((*iter)->mHandle, name) ; + // LL_INFOS() << name << LL_ENDL ; + //} + //----------- + } + else + { + writeCacheHeader() ; + } + + if(!success) + { + removeCache() ; //failed to read header, clear the cache + } + else if(mNumEntries >= mCacheSize) + { + purgeEntries(mCacheSize) ; + } + + return ; } void LLVOCache::writeCacheHeader() { - if (!mEnabled) - { - LL_WARNS() << "Not writing cache header: Cache is currently disabled." << LL_ENDL; - return; - } - - if(mReadOnly) - { - LL_WARNS() << "Not writing cache header: Cache is currently in read-only mode." << LL_ENDL; - return; - } - - bool success = true ; - { - LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - - //write the meta element - success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; - - - mNumEntries = 0 ; - for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) - { - (*iter)->mIndex = mNumEntries++ ; - success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo)); - } - - mNumEntries = mHeaderEntryQueue.size() ; - if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) - { - HeaderEntryInfo* entry = new HeaderEntryInfo() ; - entry->mTime = INVALID_TIME ; - for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) - { - //fill the cache with the default entry. - success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ; - - } - delete entry ; - } - } - - if(!success) - { - clearCacheInMemory() ; - mReadOnly = TRUE ; //disable the cache. - } - return ; + if (!mEnabled) + { + LL_WARNS() << "Not writing cache header: Cache is currently disabled." << LL_ENDL; + return; + } + + if(mReadOnly) + { + LL_WARNS() << "Not writing cache header: Cache is currently in read-only mode." << LL_ENDL; + return; + } + + bool success = true ; + { + LLAPRFile apr_file(mHeaderFileName, APR_CREATE|APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + + //write the meta element + success = check_write(&apr_file, &mMetaInfo, sizeof(HeaderMetaInfo)) ; + + + mNumEntries = 0 ; + for(header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; success && iter != mHeaderEntryQueue.end(); ++iter) + { + (*iter)->mIndex = mNumEntries++ ; + success = check_write(&apr_file, (void*)*iter, sizeof(HeaderEntryInfo)); + } + + mNumEntries = mHeaderEntryQueue.size() ; + if(success && mNumEntries < MAX_NUM_OBJECT_ENTRIES) + { + HeaderEntryInfo* entry = new HeaderEntryInfo() ; + entry->mTime = INVALID_TIME ; + for(S32 i = mNumEntries ; success && i < MAX_NUM_OBJECT_ENTRIES ; i++) + { + //fill the cache with the default entry. + success = check_write(&apr_file, entry, sizeof(HeaderEntryInfo)) ; + + } + delete entry ; + } + } + + if(!success) + { + clearCacheInMemory() ; + mReadOnly = TRUE ; //disable the cache. + } + return ; } BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) { - LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); - apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; + LLAPRFile apr_file(mHeaderFileName, APR_WRITE|APR_BINARY, mLocalAPRFilePoolp); + apr_file.seek(APR_SET, entry->mIndex * sizeof(HeaderEntryInfo) + sizeof(HeaderMetaInfo)) ; - return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; + return check_write(&apr_file, (void*)entry, sizeof(HeaderEntryInfo)) ; } // we now return bool to trigger dirty cache // this in turn forces a rewrite after a partial read due to corruption. -bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) -{ - if(!mEnabled) - { - LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; - return true; // no problem we're just read only - } - llassert_always(mInitialized); - - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //no cache - { - LL_WARNS() << "No handle map entry for " << handle << LL_ENDL; - return false; // arguably no a problem, but we'll mark this as dirty anyway. - } - - bool success = true ; - S32 num_entries = 0 ; // lifted out of inner loop. - std::string filename; // lifted out of loop - { - LLUUID cache_id; - getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); - - success = check_read(&apr_file, cache_id.mData, UUID_BYTES); - - if(success) - { - if(cache_id != id) - { - LL_INFOS() << "Cache ID doesn't match for this region, discarding"<< LL_ENDL; - success = false ; - } - - if(success) - { - success = check_read(&apr_file, &num_entries, sizeof(S32)) ; - - if(success) - { - for (S32 i = 0; i < num_entries && apr_file.eof() != APR_EOF; i++) - { - LLPointer entry = new LLVOCacheEntry(&apr_file); - if (!entry->getLocalID()) - { - LL_WARNS() << "Aborting cache file load for " << filename << ", cache file corruption!" << LL_ENDL; - success = false ; - break ; - } - cache_entry_map[entry->getLocalID()] = entry; - } - } - } - } - } - - if(!success) - { - if(cache_entry_map.empty()) - { - removeEntry(iter->second) ; - } - } - - LL_DEBUGS("GLTF", "VOCache") << "Read " << cache_entry_map.size() << " entries from object cache " << filename << ", expected " << num_entries << ", success=" << (success?"True":"False") << LL_ENDL; - return success; +bool LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) +{ + if(!mEnabled) + { + LL_WARNS() << "Not reading cache for handle " << handle << "): Cache is currently disabled." << LL_ENDL; + return true; // no problem we're just read only + } + llassert_always(mInitialized); + + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //no cache + { + LL_WARNS() << "No handle map entry for " << handle << LL_ENDL; + return false; // arguably no a problem, but we'll mark this as dirty anyway. + } + + bool success = true ; + S32 num_entries = 0 ; // lifted out of inner loop. + std::string filename; // lifted out of loop + { + LLUUID cache_id; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_READ|APR_BINARY, mLocalAPRFilePoolp); + + success = check_read(&apr_file, cache_id.mData, UUID_BYTES); + + if(success) + { + if(cache_id != id) + { + LL_INFOS() << "Cache ID doesn't match for this region, discarding"<< LL_ENDL; + success = false ; + } + + if(success) + { + success = check_read(&apr_file, &num_entries, sizeof(S32)) ; + + if(success) + { + for (S32 i = 0; i < num_entries && apr_file.eof() != APR_EOF; i++) + { + LLPointer entry = new LLVOCacheEntry(&apr_file); + if (!entry->getLocalID()) + { + LL_WARNS() << "Aborting cache file load for " << filename << ", cache file corruption!" << LL_ENDL; + success = false ; + break ; + } + cache_entry_map[entry->getLocalID()] = entry; + } + } + } + } + } + + if(!success) + { + if(cache_entry_map.empty()) + { + removeEntry(iter->second) ; + } + } + + LL_DEBUGS("GLTF", "VOCache") << "Read " << cache_entry_map.size() << " entries from object cache " << filename << ", expected " << num_entries << ", success=" << (success?"True":"False") << LL_ENDL; + return success; } // We now pass in the cache entry map, so that we can remove entries from extras that are no longer in the primary cache. @@ -1599,7 +1599,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac std::string line; std::getline(in, line); - if(!in.good()) + if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; in.close(); @@ -1609,7 +1609,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac // file formats need versions, let's add one. legacy cache files will be considered version 0 // This will make it easier to upgrade/revise later. int versionNumber=0; - if (line.compare(0, LLGLTFOverrideCacheEntry::VERSION_LABEL.length(), LLGLTFOverrideCacheEntry::VERSION_LABEL) == 0) + if (line.compare(0, LLGLTFOverrideCacheEntry::VERSION_LABEL.length(), LLGLTFOverrideCacheEntry::VERSION_LABEL) == 0) { std::string versionStr = line.substr(LLGLTFOverrideCacheEntry::VERSION_LABEL.length()+1); // skip the version label and ':' versionNumber = std::stol(versionStr); @@ -1646,14 +1646,14 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac U32 num_entries; // if removal was enabled during write num_entries might be wrong std::getline(in, line); - if(!in.good()) + if(!in.good()) { LL_WARNS() << "Failed reading extras cache for handle " << handle << LL_ENDL; in.close(); removeGenericExtrasForHandle(handle); return; } - try + try { num_entries = std::stol(line); } @@ -1673,7 +1673,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac static const U32 max_size = 4096; bool success = LLSDSerialize::deserialize(entry_llsd, in, max_size); // check bool(in) this time since eof is not a failure condition here - if(!success || !in) + if(!success || !in) { LL_WARNS() << "Failed reading extras cache for handle " << handle << ", entry number " << i << " cache patrtial load only." << LL_ENDL; in.close(); @@ -1706,90 +1706,90 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac void LLVOCache::purgeEntries(U32 size) { - LL_DEBUGS("VOCache","GLTF") << "Purging " << size << " entries from cache" << LL_ENDL; - while(mHeaderEntryQueue.size() > size) - { - header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; - HeaderEntryInfo* entry = *iter ; - mHandleEntryMap.erase(entry->mHandle) ; - mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; // This now handles removing extras cache where appropriate. - delete entry; - } - mNumEntries = mHandleEntryMap.size() ; + LL_DEBUGS("VOCache","GLTF") << "Purging " << size << " entries from cache" << LL_ENDL; + while(mHeaderEntryQueue.size() > size) + { + header_entry_queue_t::iterator iter = mHeaderEntryQueue.begin() ; + HeaderEntryInfo* entry = *iter ; + mHandleEntryMap.erase(entry->mHandle) ; + mHeaderEntryQueue.erase(iter) ; + removeFromCache(entry) ; // This now handles removing extras cache where appropriate. + delete entry; + } + mNumEntries = mHandleEntryMap.size() ; } -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled) -{ - std::string filename; - getObjectCacheFilename(handle, filename); - if(!mEnabled) - { - LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently disabled." << LL_ENDL; - return ; - } - llassert_always(mInitialized); - - if(mReadOnly) - { - LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently in read-only mode." << LL_ENDL; - return ; - } - - HeaderEntryInfo* entry; - handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; - if(iter == mHandleEntryMap.end()) //new entry - { - if(mNumEntries >= mCacheSize - 1) - { - purgeEntries(mCacheSize - 1) ; - } - - entry = new HeaderEntryInfo(); - entry->mHandle = handle ; - entry->mTime = time(NULL) ; - entry->mIndex = mNumEntries++; - mHeaderEntryQueue.insert(entry) ; - mHandleEntryMap[handle] = entry ; - } - else - { - // Update access time. - entry = iter->second ; - - //resort - mHeaderEntryQueue.erase(entry) ; - - entry->mTime = time(NULL) ; - mHeaderEntryQueue.insert(entry) ; - } - - //update cache header - if(!updateEntry(entry)) - { - LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". " << filename << " handle = " << handle << LL_ENDL; - return ; //update failed. - } - - if(!dirty_cache) - { - LL_WARNS() << "Skipping write to cache for " << filename << " (handle:" << handle << "): cache not dirty" << LL_ENDL; - return ; //nothing changed, no need to update. - } - - //write to cache file - bool success = true ; - { - std::string filename; - getObjectCacheFilename(handle, filename); - LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY|APR_TRUNCATE, mLocalAPRFilePoolp); - - success = check_write(&apr_file, (void*)id.mData, UUID_BYTES); - - if(success) - { - S32 num_entries = cache_entry_map.size(); // if removal is enabled num_entries might be wrong - success = check_write(&apr_file, &num_entries, sizeof(S32)); +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled) +{ + std::string filename; + getObjectCacheFilename(handle, filename); + if(!mEnabled) + { + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently disabled." << LL_ENDL; + return ; + } + llassert_always(mInitialized); + + if(mReadOnly) + { + LL_WARNS() << "Not writing cache for " << filename << " (handle:" << handle << "): Cache is currently in read-only mode." << LL_ENDL; + return ; + } + + HeaderEntryInfo* entry; + handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; + if(iter == mHandleEntryMap.end()) //new entry + { + if(mNumEntries >= mCacheSize - 1) + { + purgeEntries(mCacheSize - 1) ; + } + + entry = new HeaderEntryInfo(); + entry->mHandle = handle ; + entry->mTime = time(NULL) ; + entry->mIndex = mNumEntries++; + mHeaderEntryQueue.insert(entry) ; + mHandleEntryMap[handle] = entry ; + } + else + { + // Update access time. + entry = iter->second ; + + //resort + mHeaderEntryQueue.erase(entry) ; + + entry->mTime = time(NULL) ; + mHeaderEntryQueue.insert(entry) ; + } + + //update cache header + if(!updateEntry(entry)) + { + LL_WARNS() << "Failed to update cache header index " << entry->mIndex << ". " << filename << " handle = " << handle << LL_ENDL; + return ; //update failed. + } + + if(!dirty_cache) + { + LL_WARNS() << "Skipping write to cache for " << filename << " (handle:" << handle << "): cache not dirty" << LL_ENDL; + return ; //nothing changed, no need to update. + } + + //write to cache file + bool success = true ; + { + std::string filename; + getObjectCacheFilename(handle, filename); + LLAPRFile apr_file(filename, APR_CREATE|APR_WRITE|APR_BINARY|APR_TRUNCATE, mLocalAPRFilePoolp); + + success = check_write(&apr_file, (void*)id.mData, UUID_BYTES); + + if(success) + { + S32 num_entries = cache_entry_map.size(); // if removal is enabled num_entries might be wrong + success = check_write(&apr_file, &num_entries, sizeof(S32)); if (success) { const S32 buffer_size = 32768; //should be large enough for couple MAX_ENTRY_BODY_SIZE @@ -1840,15 +1840,15 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: } LL_DEBUGS("VOCache") << "Wrote " << num_entries << " entries to the primary VOCache file " << filename << ". success = " << (success ? "True":"False") << LL_ENDL; } - } - } + } + } - if(!success) - { - removeEntry(entry) ; - } + if(!success) + { + removeEntry(entry) ; + } - return ; + return ; } void LLVOCache::removeGenericExtrasForHandle(U64 handle) @@ -1858,7 +1858,7 @@ void LLVOCache::removeGenericExtrasForHandle(U64 handle) LL_WARNS() << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << LL_ENDL; return ; } - + // NOTE: when removing the extras, we must also remove the objects so the simulator will send us a full upddate with the valid overrides auto* entry = mHandleEntryMap[handle]; if (entry) @@ -1906,16 +1906,16 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; - removeGenericExtrasForHandle(handle); + removeGenericExtrasForHandle(handle); return; } - // Because we don't write out all the entries we need to record a placeholder and rewrite this later + // Because we don't write out all the entries we need to record a placeholder and rewrite this later auto num_entries_placeholder = out.tellp(); out << std::setw(10) << std::setfill('0') << 0 << '\n'; if(!out.good()) { LL_WARNS() << "Failed writing extras cache for handle " << handle << LL_ENDL; - removeGenericExtrasForHandle(handle); + removeGenericExtrasForHandle(handle); return; } @@ -1932,7 +1932,7 @@ void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LL // worst case we have an extra cache miss. // Note: A null mObjectId is valid when in memory as we might have a data race between GLTF of the object itself. // This remains a valid state to persist as it is consistent with the localid checks on import with the main cache. - // the mObjectId will be updated if/when the local object is updated from the gObject list (due to full update) + // the mObjectId will be updated if/when the local object is updated from the gObject list (due to full update) if(entry.mObjectId.isNull() && pRegion) { gObjectList.getUUIDFromLocal( entry.mObjectId, local_id, pRegion->getHost().getAddress(), pRegion->getHost().getPort() ); diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index d94e79ce1b..b2578085d8 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -1,25 +1,25 @@ -/** +/** * @file llvocache.h * @brief Cache of objects on the viewer. * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -55,189 +55,189 @@ public: U64 mRegionHandle = 0; }; -class LLVOCacheEntry -: public LLViewerOctreeEntryData +class LLVOCacheEntry +: public LLViewerOctreeEntryData { LL_ALIGN_NEW public: - enum - { - //low 16-bit state - INACTIVE = 0x00000000, //not visible - IN_QUEUE = 0x00000001, //in visible queue, object to be created - WAITING = 0x00000002, //object creation request sent - ACTIVE = 0x00000004, //object created, and in rendering pipeline. - - //high 16-bit state - IN_VO_TREE = 0x00010000, //the entry is in the object cache tree. - - LOW_BITS = 0x0000ffff, - HIGH_BITS = 0xffff0000 - }; - - struct CompareVOCacheEntry - { - bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) const - { - F32 lpa = lhs->getSceneContribution(); - F32 rpa = rhs->getSceneContribution(); - - //larger pixel area first - if(lpa > rpa) - { - return true; - } - else if(lpa < rpa) - { - return false; - } - else - { - return lhs < rhs; - } - } - }; + enum + { + //low 16-bit state + INACTIVE = 0x00000000, //not visible + IN_QUEUE = 0x00000001, //in visible queue, object to be created + WAITING = 0x00000002, //object creation request sent + ACTIVE = 0x00000004, //object created, and in rendering pipeline. + + //high 16-bit state + IN_VO_TREE = 0x00010000, //the entry is in the object cache tree. + + LOW_BITS = 0x0000ffff, + HIGH_BITS = 0xffff0000 + }; + + struct CompareVOCacheEntry + { + bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) const + { + F32 lpa = lhs->getSceneContribution(); + F32 rpa = rhs->getSceneContribution(); + + //larger pixel area first + if(lpa > rpa) + { + return true; + } + else if(lpa < rpa) + { + return false; + } + else + { + return lhs < rhs; + } + } + }; protected: - ~LLVOCacheEntry(); + ~LLVOCacheEntry(); public: - LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp); - LLVOCacheEntry(LLAPRFile* apr_file); - LLVOCacheEntry(); - - void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp); - - void clearState(U32 state) {mState &= ~state;} - bool hasState(U32 state) {return mState & state;} - void setState(U32 state); - bool isState(U32 state) {return (mState & LOW_BITS) == state;} - U32 getState() const {return mState & LOW_BITS;} - - bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold); - - U32 getLocalID() const { return mLocalID; } - U32 getCRC() const { return mCRC; } - S32 getHitCount() const { return mHitCount; } - S32 getCRCChangeCount() const { return mCRCChangeCount; } - - void calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 dist_threshold); - void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;} - F32 getSceneContribution() const { return mSceneContrib;} - - void dump() const; - S32 writeToBuffer(U8 *data_buffer) const; - LLDataPackerBinaryBuffer *getDP(); - void recordHit(); - void recordDupe() { mDupeCount++; } - - /*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry); - - void setParentID(U32 id); - U32 getParentID() const {return mParentID;} - bool isChild() const {return mParentID > 0;} - - void addChild(LLVOCacheEntry* entry); - void removeChild(LLVOCacheEntry* entry); - void removeAllChildren(); - LLVOCacheEntry* getChild(); //remove the first child, and return it. - S32 getNumOfChildren() const {return mChildrenList.size();} - - void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message - void updateParentBoundingInfo(); - void saveBoundingSphere(); - - void setValid(BOOL valid = TRUE) {mValid = valid;} - BOOL isValid() const {return mValid;} - - void setUpdateFlags(U32 flags) {mUpdateFlags = flags;} - U32 getUpdateFlags() const {return mUpdateFlags;} - - static void updateDebugSettings(); - static F32 getSquaredPixelThreshold(bool is_front); + LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp); + LLVOCacheEntry(LLAPRFile* apr_file); + LLVOCacheEntry(); + + void updateEntry(U32 crc, LLDataPackerBinaryBuffer &dp); + + void clearState(U32 state) {mState &= ~state;} + bool hasState(U32 state) {return mState & state;} + void setState(U32 state); + bool isState(U32 state) {return (mState & LOW_BITS) == state;} + U32 getState() const {return mState & LOW_BITS;} + + bool isAnyVisible(const LLVector4a& camera_origin, const LLVector4a& local_camera_origin, F32 dist_threshold); + + U32 getLocalID() const { return mLocalID; } + U32 getCRC() const { return mCRC; } + S32 getHitCount() const { return mHitCount; } + S32 getCRCChangeCount() const { return mCRCChangeCount; } + + void calcSceneContribution(const LLVector4a& camera_origin, bool needs_update, U32 last_update, F32 dist_threshold); + void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;} + F32 getSceneContribution() const { return mSceneContrib;} + + void dump() const; + S32 writeToBuffer(U8 *data_buffer) const; + LLDataPackerBinaryBuffer *getDP(); + void recordHit(); + void recordDupe() { mDupeCount++; } + + /*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry); + + void setParentID(U32 id); + U32 getParentID() const {return mParentID;} + bool isChild() const {return mParentID > 0;} + + void addChild(LLVOCacheEntry* entry); + void removeChild(LLVOCacheEntry* entry); + void removeAllChildren(); + LLVOCacheEntry* getChild(); //remove the first child, and return it. + S32 getNumOfChildren() const {return mChildrenList.size();} + + void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); //called from processing object update message + void updateParentBoundingInfo(); + void saveBoundingSphere(); + + void setValid(BOOL valid = TRUE) {mValid = valid;} + BOOL isValid() const {return mValid;} + + void setUpdateFlags(U32 flags) {mUpdateFlags = flags;} + U32 getUpdateFlags() const {return mUpdateFlags;} + + static void updateDebugSettings(); + static F32 getSquaredPixelThreshold(bool is_front); private: - void updateParentBoundingInfo(const LLVOCacheEntry* child); + void updateParentBoundingInfo(const LLVOCacheEntry* child); public: - typedef std::map > vocache_entry_map_t; - typedef std::set vocache_entry_set_t; - typedef std::set vocache_entry_priority_list_t; + typedef std::map > vocache_entry_map_t; + typedef std::set vocache_entry_set_t; + typedef std::set vocache_entry_priority_list_t; typedef std::unordered_map vocache_gltf_overrides_map_t; - S32 mLastCameraUpdated; + S32 mLastCameraUpdated; protected: - U32 mLocalID; - U32 mParentID; - U32 mCRC; - U32 mUpdateFlags; //receive from sim - S32 mHitCount; - S32 mDupeCount; - S32 mCRCChangeCount; - LLDataPackerBinaryBuffer mDP; - U8 *mBuffer; + U32 mLocalID; + U32 mParentID; + U32 mCRC; + U32 mUpdateFlags; //receive from sim + S32 mHitCount; + S32 mDupeCount; + S32 mCRCChangeCount; + LLDataPackerBinaryBuffer mDP; + U8 *mBuffer; - F32 mSceneContrib; //projected scene contributuion of this object. - U32 mState; //high 16 bits reserved for special use. - vocache_entry_set_t mChildrenList; //children entries in a linked set. + F32 mSceneContrib; //projected scene contributuion of this object. + U32 mState; //high 16 bits reserved for special use. + vocache_entry_set_t mChildrenList; //children entries in a linked set. - BOOL mValid; //if set, this entry is valid, otherwise it is invalid and will be removed. + BOOL mValid; //if set, this entry is valid, otherwise it is invalid and will be removed. - LLVector4a mBSphereCenter; //bounding sphere center - F32 mBSphereRadius; //bounding sphere radius + LLVector4a mBSphereCenter; //bounding sphere center + F32 mBSphereRadius; //bounding sphere radius public: - static U32 sMinFrameRange; - static F32 sNearRadius; - static F32 sRearFarRadius; - static F32 sFrontPixelThreshold; - static F32 sRearPixelThreshold; + static U32 sMinFrameRange; + static F32 sNearRadius; + static F32 sRearFarRadius; + static F32 sFrontPixelThreshold; + static F32 sRearPixelThreshold; }; class LLVOCacheGroup : public LLOcclusionCullingGroup { public: - LLVOCacheGroup(OctreeNode* node, LLViewerOctreePartition* part) : LLOcclusionCullingGroup(node, part){} + LLVOCacheGroup(OctreeNode* node, LLViewerOctreePartition* part) : LLOcclusionCullingGroup(node, part){} - //virtual - void handleChildAddition(const OctreeNode* parent, OctreeNode* child); + //virtual + void handleChildAddition(const OctreeNode* parent, OctreeNode* child); protected: - virtual ~LLVOCacheGroup(); + virtual ~LLVOCacheGroup(); }; class LLVOCachePartition : public LLViewerOctreePartition { public: - LLVOCachePartition(LLViewerRegion* regionp); + LLVOCachePartition(LLViewerRegion* regionp); virtual ~LLVOCachePartition(); - bool addEntry(LLViewerOctreeEntry* entry); - void removeEntry(LLViewerOctreeEntry* entry); - /*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion); - void addOccluders(LLViewerOctreeGroup* gp); - void resetOccluders(); - void processOccluders(LLCamera* camera); - void removeOccluder(LLVOCacheGroup* group); + bool addEntry(LLViewerOctreeEntry* entry); + void removeEntry(LLViewerOctreeEntry* entry); + /*virtual*/ S32 cull(LLCamera &camera, bool do_occlusion); + void addOccluders(LLViewerOctreeGroup* gp); + void resetOccluders(); + void processOccluders(LLCamera* camera); + void removeOccluder(LLVOCacheGroup* group); - void setCullHistory(BOOL has_new_object); + void setCullHistory(BOOL has_new_object); - bool isFrontCull() const {return mFrontCull;} + bool isFrontCull() const {return mFrontCull;} private: - void selectBackObjects(LLCamera &camera, F32 projection_area_cutoff, bool use_occlusion); //select objects behind camera. + void selectBackObjects(LLCamera &camera, F32 projection_area_cutoff, bool use_occlusion); //select objects behind camera. public: - static BOOL sNeedsOcclusionCheck; + static BOOL sNeedsOcclusionCheck; private: - BOOL mFrontCull; //the view frustum cull if set, otherwise is back sphere cull. - U32 mCullHistory; - U32 mCulledTime[LLViewerCamera::NUM_CAMERAS]; - std::set mOccludedGroups; + BOOL mFrontCull; //the view frustum cull if set, otherwise is back sphere cull. + U32 mCullHistory; + U32 mCulledTime[LLViewerCamera::NUM_CAMERAS]; + std::set mOccludedGroups; - S32 mBackSlectionEnabled; //enable to select back objects if > 0. - U32 mIdleHash; + S32 mBackSlectionEnabled; //enable to select back objects if > 0. + U32 mIdleHash; }; // @@ -245,83 +245,83 @@ private: // class LLVOCache : public LLParamSingleton { - LLSINGLETON(LLVOCache, bool read_only); - ~LLVOCache() ; + LLSINGLETON(LLVOCache, bool read_only); + ~LLVOCache() ; private: - struct HeaderEntryInfo - { - HeaderEntryInfo() : mIndex(0), mHandle(0), mTime(0) {} - S32 mIndex; - U64 mHandle ; - U32 mTime ; - }; - - struct HeaderMetaInfo - { - HeaderMetaInfo() : mVersion(0), mAddressSize(0) {} - - U32 mVersion; - U32 mAddressSize; - }; - - struct header_entry_less - { - bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const - { - if(lhs->mTime == rhs->mTime) - { - return lhs < rhs ; - } - - return lhs->mTime < rhs->mTime ; // older entry in front of queue (set) - } - }; - typedef std::set header_entry_queue_t; - typedef std::map handle_entry_map_t; + struct HeaderEntryInfo + { + HeaderEntryInfo() : mIndex(0), mHandle(0), mTime(0) {} + S32 mIndex; + U64 mHandle ; + U32 mTime ; + }; + + struct HeaderMetaInfo + { + HeaderMetaInfo() : mVersion(0), mAddressSize(0) {} + + U32 mVersion; + U32 mAddressSize; + }; + + struct header_entry_less + { + bool operator()(const HeaderEntryInfo* lhs, const HeaderEntryInfo* rhs) const + { + if(lhs->mTime == rhs->mTime) + { + return lhs < rhs ; + } + + return lhs->mTime < rhs->mTime ; // older entry in front of queue (set) + } + }; + typedef std::set header_entry_queue_t; + typedef std::map handle_entry_map_t; public: - // We need this init to be separate from constructor, since we might construct cache, purge it, then init. - void initCache(ELLPath location, U32 size, U32 cache_version); - void removeCache(ELLPath location, bool started = false) ; + // We need this init to be separate from constructor, since we might construct cache, purge it, then init. + void initCache(ELLPath location, U32 size, U32 cache_version); + void removeCache(ELLPath location, bool started = false) ; - bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map); + bool readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; + void readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map); - void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); + void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); void writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled); - void removeEntry(U64 handle) ; - void removeGenericExtrasForHandle(U64 handle); + void removeEntry(U64 handle) ; + void removeGenericExtrasForHandle(U64 handle); - U32 getCacheEntries() { return mNumEntries; } - U32 getCacheEntriesMax() { return mCacheSize; } + U32 getCacheEntries() { return mNumEntries; } + U32 getCacheEntriesMax() { return mCacheSize; } private: - void setDirNames(ELLPath location); - // determine the cache filename for the region from the region handle - void getObjectCacheFilename(U64 handle, std::string& filename); + void setDirNames(ELLPath location); + // determine the cache filename for the region from the region handle + void getObjectCacheFilename(U64 handle, std::string& filename); std::string getObjectCacheExtrasFilename(U64 handle); - void removeFromCache(HeaderEntryInfo* entry); - void readCacheHeader(); - void writeCacheHeader(); - void clearCacheInMemory(); - void removeCache() ; - void removeEntry(HeaderEntryInfo* entry) ; - void purgeEntries(U32 size); - BOOL updateEntry(const HeaderEntryInfo* entry); - + void removeFromCache(HeaderEntryInfo* entry); + void readCacheHeader(); + void writeCacheHeader(); + void clearCacheInMemory(); + void removeCache() ; + void removeEntry(HeaderEntryInfo* entry) ; + void purgeEntries(U32 size); + BOOL updateEntry(const HeaderEntryInfo* entry); + private: - bool mEnabled; - bool mInitialized ; - bool mReadOnly ; - HeaderMetaInfo mMetaInfo; - U32 mCacheSize; - U32 mNumEntries; - std::string mHeaderFileName ; - std::string mObjectCacheDirName; - LLVolatileAPRPool* mLocalAPRFilePoolp ; - header_entry_queue_t mHeaderEntryQueue; - handle_entry_map_t mHandleEntryMap; + bool mEnabled; + bool mInitialized ; + bool mReadOnly ; + HeaderMetaInfo mMetaInfo; + U32 mCacheSize; + U32 mNumEntries; + std::string mHeaderFileName ; + std::string mObjectCacheDirName; + LLVolatileAPRPool* mLocalAPRFilePoolp ; + header_entry_queue_t mHeaderEntryQueue; + handle_entry_map_t mHandleEntryMap; }; #endif diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 69b9476d38..405d0e59ce 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvosurfacepatch.cpp * @brief Viewer-object derived "surface patch", which is a piece of terrain * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -47,51 +47,51 @@ F32 LLVOSurfacePatch::sLODFactor = 1.f; LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLStaticViewerObject(id, pcode, regionp), - mDirtiedPatch(FALSE), - mPool(NULL), - mBaseComp(0), - mPatchp(NULL), - mDirtyTexture(FALSE), - mDirtyTerrain(FALSE), - mLastNorthStride(0), - mLastEastStride(0), - mLastStride(0), - mLastLength(0) + : LLStaticViewerObject(id, pcode, regionp), + mDirtiedPatch(FALSE), + mPool(NULL), + mBaseComp(0), + mPatchp(NULL), + mDirtyTexture(FALSE), + mDirtyTerrain(FALSE), + mLastNorthStride(0), + mLastEastStride(0), + mLastStride(0), + mLastLength(0) { - // Terrain must draw during selection passes so it can block objects behind it. - mbCanSelect = TRUE; - setScale(LLVector3(16.f, 16.f, 16.f)); // Hack for setting scale for bounding boxes/visibility. + // Terrain must draw during selection passes so it can block objects behind it. + mbCanSelect = TRUE; + setScale(LLVector3(16.f, 16.f, 16.f)); // Hack for setting scale for bounding boxes/visibility. } LLVOSurfacePatch::~LLVOSurfacePatch() { - mPatchp = NULL; + mPatchp = NULL; } void LLVOSurfacePatch::markDead() { - if (mPatchp) - { - mPatchp->clearVObj(); - mPatchp = NULL; - } - LLViewerObject::markDead(); + if (mPatchp) + { + mPatchp->clearVObj(); + mPatchp = NULL; + } + LLViewerObject::markDead(); } BOOL LLVOSurfacePatch::isActive() const { - return FALSE; + return FALSE; } void LLVOSurfacePatch::setPixelAreaAndAngle(LLAgent &agent) { - mAppAngle = 50; - mPixelArea = 500*500; + mAppAngle = 50; + mPixelArea = 500*500; } @@ -102,145 +102,145 @@ void LLVOSurfacePatch::updateTextures() LLFacePool *LLVOSurfacePatch::getPool() { - mPool = (LLDrawPoolTerrain*) gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture()); + mPool = (LLDrawPoolTerrain*) gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture()); - return mPool; + return mPool; } LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) { - pipeline->allocDrawable(this); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TERRAIN); - - mBaseComp = llfloor(mPatchp->getMinComposition()); - S32 min_comp, max_comp, range; - min_comp = llfloor(mPatchp->getMinComposition()); - max_comp = llceil(mPatchp->getMaxComposition()); - range = (max_comp - min_comp); - range++; - if (range > 3) - { - if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition())) - { - // The top side runs over more - mBaseComp++; - } - range = 3; - } - - LLFacePool *poolp = getPool(); - - mDrawable->addFace(poolp, NULL); - - return mDrawable; + pipeline->allocDrawable(this); + + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TERRAIN); + + mBaseComp = llfloor(mPatchp->getMinComposition()); + S32 min_comp, max_comp, range; + min_comp = llfloor(mPatchp->getMinComposition()); + max_comp = llceil(mPatchp->getMaxComposition()); + range = (max_comp - min_comp); + range++; + if (range > 3) + { + if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition())) + { + // The top side runs over more + mBaseComp++; + } + range = 3; + } + + LLFacePool *poolp = getPool(); + + mDrawable->addFace(poolp, NULL); + + return mDrawable; } void LLVOSurfacePatch::updateGL() { - if (mPatchp) - { - LL_PROFILE_ZONE_SCOPED - mPatchp->updateGL(); - } + if (mPatchp) + { + LL_PROFILE_ZONE_SCOPED + mPatchp->updateGL(); + } } BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED; - dirtySpatialGroup(); - - S32 min_comp, max_comp, range; - min_comp = lltrunc(mPatchp->getMinComposition()); - max_comp = lltrunc(ceil(mPatchp->getMaxComposition())); - range = (max_comp - min_comp); - range++; - S32 new_base_comp = lltrunc(mPatchp->getMinComposition()); - if (range > 3) - { - if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition())) - { - // The top side runs over more - new_base_comp++; - } - range = 3; - } - - // Pick the two closest detail textures for this patch... - // Then create the draw pool for it. - // Actually, should get the average composition instead of the center. - mBaseComp = new_base_comp; - - ////////////////////////// - // - // Figure out the strides - // - // - - U32 patch_width, render_stride, north_stride, east_stride, length; - render_stride = mPatchp->getRenderStride(); - patch_width = mPatchp->getSurface()->getGridsPerPatchEdge(); - - length = patch_width / render_stride; - - if (mPatchp->getNeighborPatch(NORTH)) - { - north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); - } - else - { - north_stride = render_stride; - } - - if (mPatchp->getNeighborPatch(EAST)) - { - east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); - } - else - { - east_stride = render_stride; - } - - mLastLength = length; - mLastStride = render_stride; - mLastNorthStride = north_stride; - mLastEastStride = east_stride; - - return TRUE; + dirtySpatialGroup(); + + S32 min_comp, max_comp, range; + min_comp = lltrunc(mPatchp->getMinComposition()); + max_comp = lltrunc(ceil(mPatchp->getMaxComposition())); + range = (max_comp - min_comp); + range++; + S32 new_base_comp = lltrunc(mPatchp->getMinComposition()); + if (range > 3) + { + if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition())) + { + // The top side runs over more + new_base_comp++; + } + range = 3; + } + + // Pick the two closest detail textures for this patch... + // Then create the draw pool for it. + // Actually, should get the average composition instead of the center. + mBaseComp = new_base_comp; + + ////////////////////////// + // + // Figure out the strides + // + // + + U32 patch_width, render_stride, north_stride, east_stride, length; + render_stride = mPatchp->getRenderStride(); + patch_width = mPatchp->getSurface()->getGridsPerPatchEdge(); + + length = patch_width / render_stride; + + if (mPatchp->getNeighborPatch(NORTH)) + { + north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); + } + else + { + north_stride = render_stride; + } + + if (mPatchp->getNeighborPatch(EAST)) + { + east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); + } + else + { + east_stride = render_stride; + } + + mLastLength = length; + mLastStride = render_stride; + mLastNorthStride = north_stride; + mLastEastStride = east_stride; + + return TRUE; } void LLVOSurfacePatch::updateFaceSize(S32 idx) { LL_PROFILE_ZONE_SCOPED; - if (idx != 0) - { - LL_WARNS() << "Terrain partition requested invalid face!!!" << LL_ENDL; - return; - } - - LLFace* facep = mDrawable->getFace(idx); - if (facep) - { - S32 num_vertices = 0; - S32 num_indices = 0; - - if (mLastStride) - { - getGeomSizesMain(mLastStride, num_vertices, num_indices); - getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); - getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); - } - - facep->setSize(num_vertices, num_indices); - } + if (idx != 0) + { + LL_WARNS() << "Terrain partition requested invalid face!!!" << LL_ENDL; + return; + } + + LLFace* facep = mDrawable->getFace(idx); + if (facep) + { + S32 num_vertices = 0; + S32 num_indices = 0; + + if (mLastStride) + { + getGeomSizesMain(mLastStride, num_vertices, num_indices); + getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); + getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); + } + + facep->setSize(num_vertices, num_indices); + } } BOOL LLVOSurfacePatch::updateLOD() { - return TRUE; + return TRUE; } void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, @@ -249,7 +249,7 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &texCoords1p, LLStrider &indicesp) { - LLFace* facep = mDrawable->getFace(0); + LLFace* facep = mDrawable->getFace(0); if (!facep) { return; @@ -257,21 +257,21 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, U32 index_offset = facep->getGeomIndex(); - updateMainGeometry(facep, + updateMainGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, index_offset); - updateNorthGeometry(facep, + updateNorthGeometry(facep, verticesp, normalsp, texCoords0p, texCoords1p, indicesp, index_offset); - updateEastGeometry(facep, + updateEastGeometry(facep, verticesp, normalsp, texCoords0p, @@ -288,99 +288,99 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, LLStrider &indicesp, U32 &index_offset) { - S32 i, j, x, y; - - U32 patch_size, render_stride; - S32 num_vertices, num_indices; - U32 index; - - llassert(mLastStride > 0); - - render_stride = mLastStride; - patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - S32 vert_size = patch_size / render_stride; - - /////////////////////////// - // - // Render the main patch - // - // - - num_vertices = 0; - num_indices = 0; - // First, figure out how many vertices we need... - getGeomSizesMain(render_stride, num_vertices, num_indices); - - if (num_vertices > 0) - { - facep->mCenterAgent = mPatchp->getPointAgent(8, 8); - - // Generate patch points first - for (j = 0; j < vert_size; j++) - { - for (i = 0; i < vert_size; i++) - { - x = i * render_stride; - y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - } - - for (j = 0; j < (vert_size - 1); j++) - { - if (j % 2) - { - for (i = (vert_size - 1); i > 0; i--) - { - index = (i - 1)+ j*vert_size; - *(indicesp++) = index_offset + index; - - index = i + (j+1)*vert_size; - *(indicesp++) = index_offset + index; - - index = (i - 1) + (j+1)*vert_size; - *(indicesp++) = index_offset + index; - - index = (i - 1) + j*vert_size; - *(indicesp++) = index_offset + index; - - index = i + j*vert_size; - *(indicesp++) = index_offset + index; - - index = i + (j+1)*vert_size; - *(indicesp++) = index_offset + index; - } - } - else - { - for (i = 0; i < (vert_size - 1); i++) - { - index = i + j*vert_size; - *(indicesp++) = index_offset + index; - - index = (i + 1) + (j+1)*vert_size; - *(indicesp++) = index_offset + index; - - index = i + (j+1)*vert_size; - *(indicesp++) = index_offset + index; - - index = i + j*vert_size; - *(indicesp++) = index_offset + index; - - index = (i + 1) + j*vert_size; - *(indicesp++) = index_offset + index; - - index = (i + 1) + (j + 1)*vert_size; - *(indicesp++) = index_offset + index; - } - } - } - } - index_offset += num_vertices; + S32 i, j, x, y; + + U32 patch_size, render_stride; + S32 num_vertices, num_indices; + U32 index; + + llassert(mLastStride > 0); + + render_stride = mLastStride; + patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + S32 vert_size = patch_size / render_stride; + + /////////////////////////// + // + // Render the main patch + // + // + + num_vertices = 0; + num_indices = 0; + // First, figure out how many vertices we need... + getGeomSizesMain(render_stride, num_vertices, num_indices); + + if (num_vertices > 0) + { + facep->mCenterAgent = mPatchp->getPointAgent(8, 8); + + // Generate patch points first + for (j = 0; j < vert_size; j++) + { + for (i = 0; i < vert_size; i++) + { + x = i * render_stride; + y = j * render_stride; + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + } + + for (j = 0; j < (vert_size - 1); j++) + { + if (j % 2) + { + for (i = (vert_size - 1); i > 0; i--) + { + index = (i - 1)+ j*vert_size; + *(indicesp++) = index_offset + index; + + index = i + (j+1)*vert_size; + *(indicesp++) = index_offset + index; + + index = (i - 1) + (j+1)*vert_size; + *(indicesp++) = index_offset + index; + + index = (i - 1) + j*vert_size; + *(indicesp++) = index_offset + index; + + index = i + j*vert_size; + *(indicesp++) = index_offset + index; + + index = i + (j+1)*vert_size; + *(indicesp++) = index_offset + index; + } + } + else + { + for (i = 0; i < (vert_size - 1); i++) + { + index = i + j*vert_size; + *(indicesp++) = index_offset + index; + + index = (i + 1) + (j+1)*vert_size; + *(indicesp++) = index_offset + index; + + index = i + (j+1)*vert_size; + *(indicesp++) = index_offset + index; + + index = i + j*vert_size; + *(indicesp++) = index_offset + index; + + index = (i + 1) + j*vert_size; + *(indicesp++) = index_offset + index; + + index = (i + 1) + (j + 1)*vert_size; + *(indicesp++) = index_offset + index; + } + } + } + } + index_offset += num_vertices; } @@ -392,186 +392,186 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, LLStrider &indicesp, U32 &index_offset) { - S32 i, x, y; - - S32 num_vertices; - - U32 render_stride = mLastStride; - S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - S32 length = patch_size / render_stride; - S32 half_length = length / 2; - U32 north_stride = mLastNorthStride; - - /////////////////////////// - // - // Render the north strip - // - // - - // Stride lengths are the same - if (north_stride == render_stride) - { - num_vertices = 2 * length + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; - - // Main patch - for (i = 0; i < length; i++) - { - x = i * render_stride; - y = 16 - render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - // North patch - for (i = 0; i <= length; i++) - { - x = i * render_stride; - y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - - for (i = 0; i < length; i++) - { - // Generate indices - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + length + i + 1; - *(indicesp++) = index_offset + length + i; - - if (i != length - 1) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + i + 1; - *(indicesp++) = index_offset + length + i + 1; - } - } - } - else if (north_stride > render_stride) - { - // North stride is longer (has less vertices) - num_vertices = length + length/2 + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; - - // Iterate through this patch's points - for (i = 0; i < length; i++) - { - x = i * render_stride; - y = 16 - render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - // Iterate through the north patch's points - for (i = 0; i <= length; i+=2) - { - x = i * render_stride; - y = 16; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - - for (i = 0; i < length; i++) - { - if (!(i % 2)) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + i + 1; - *(indicesp++) = index_offset + length + (i/2); - - *(indicesp++) = index_offset + i + 1; - *(indicesp++) = index_offset + length + (i/2) + 1; - *(indicesp++) = index_offset + length + (i/2); - } - else if (i < (length - 1)) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + i + 1; - *(indicesp++) = index_offset + length + (i/2) + 1; - } - } - } - else - { - // North stride is shorter (more vertices) - length = patch_size / north_stride; - half_length = length / 2; - num_vertices = length + half_length + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; - - // Iterate through this patch's points - for (i = 0; i < length; i+=2) - { - x = i * north_stride; - y = 16 - render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - // Iterate through the north patch's points - for (i = 0; i <= length; i++) - { - x = i * north_stride; - y = 16; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - for (i = 0; i < length; i++) - { - if (!(i%2)) - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + i/2; - *(indicesp++) = index_offset + half_length + i + 1; - } - else if (i < (length - 2)) - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + i/2; - *(indicesp++) = index_offset + i/2 + 1; - - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + i/2 + 1; - *(indicesp++) = index_offset + half_length + i + 1; - } - else - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + i/2; - *(indicesp++) = index_offset + half_length + i + 1; - } - } - } - index_offset += num_vertices; + S32 i, x, y; + + S32 num_vertices; + + U32 render_stride = mLastStride; + S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + S32 length = patch_size / render_stride; + S32 half_length = length / 2; + U32 north_stride = mLastNorthStride; + + /////////////////////////// + // + // Render the north strip + // + // + + // Stride lengths are the same + if (north_stride == render_stride) + { + num_vertices = 2 * length + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; + + // Main patch + for (i = 0; i < length; i++) + { + x = i * render_stride; + y = 16 - render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + // North patch + for (i = 0; i <= length; i++) + { + x = i * render_stride; + y = 16; + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + + for (i = 0; i < length; i++) + { + // Generate indices + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + length + i + 1; + *(indicesp++) = index_offset + length + i; + + if (i != length - 1) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + i + 1; + *(indicesp++) = index_offset + length + i + 1; + } + } + } + else if (north_stride > render_stride) + { + // North stride is longer (has less vertices) + num_vertices = length + length/2 + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; + + // Iterate through this patch's points + for (i = 0; i < length; i++) + { + x = i * render_stride; + y = 16 - render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + // Iterate through the north patch's points + for (i = 0; i <= length; i+=2) + { + x = i * render_stride; + y = 16; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + + for (i = 0; i < length; i++) + { + if (!(i % 2)) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + i + 1; + *(indicesp++) = index_offset + length + (i/2); + + *(indicesp++) = index_offset + i + 1; + *(indicesp++) = index_offset + length + (i/2) + 1; + *(indicesp++) = index_offset + length + (i/2); + } + else if (i < (length - 1)) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + i + 1; + *(indicesp++) = index_offset + length + (i/2) + 1; + } + } + } + else + { + // North stride is shorter (more vertices) + length = patch_size / north_stride; + half_length = length / 2; + num_vertices = length + half_length + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; + + // Iterate through this patch's points + for (i = 0; i < length; i+=2) + { + x = i * north_stride; + y = 16 - render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + // Iterate through the north patch's points + for (i = 0; i <= length; i++) + { + x = i * north_stride; + y = 16; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + for (i = 0; i < length; i++) + { + if (!(i%2)) + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + i/2; + *(indicesp++) = index_offset + half_length + i + 1; + } + else if (i < (length - 2)) + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + i/2; + *(indicesp++) = index_offset + i/2 + 1; + + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + i/2 + 1; + *(indicesp++) = index_offset + half_length + i + 1; + } + else + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + i/2; + *(indicesp++) = index_offset + half_length + i + 1; + } + } + } + index_offset += num_vertices; } void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, @@ -582,408 +582,408 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, LLStrider &indicesp, U32 &index_offset) { - S32 i, x, y; - - S32 num_vertices; - - U32 render_stride = mLastStride; - S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - S32 length = patch_size / render_stride; - S32 half_length = length / 2; - - U32 east_stride = mLastEastStride; - - // Stride lengths are the same - if (east_stride == render_stride) - { - num_vertices = 2 * length + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; - - // Main patch - for (i = 0; i < length; i++) - { - x = 16 - render_stride; - y = i * render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - // East patch - for (i = 0; i <= length; i++) - { - x = 16; - y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - - for (i = 0; i < length; i++) - { - // Generate indices - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + length + i; - *(indicesp++) = index_offset + length + i + 1; - - if (i != length - 1) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + length + i + 1; - *(indicesp++) = index_offset + i + 1; - } - } - } - else if (east_stride > render_stride) - { - // East stride is longer (has less vertices) - num_vertices = length + half_length + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; - - // Iterate through this patch's points - for (i = 0; i < length; i++) - { - x = 16 - render_stride; - y = i * render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - // Iterate through the east patch's points - for (i = 0; i <= length; i+=2) - { - x = 16; - y = i * render_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - for (i = 0; i < length; i++) - { - if (!(i % 2)) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + length + (i/2); - *(indicesp++) = index_offset + i + 1; - - *(indicesp++) = index_offset + i + 1; - *(indicesp++) = index_offset + length + (i/2); - *(indicesp++) = index_offset + length + (i/2) + 1; - } - else if (i < (length - 1)) - { - *(indicesp++) = index_offset + i; - *(indicesp++) = index_offset + length + (i/2) + 1; - *(indicesp++) = index_offset + i + 1; - } - } - } - else - { - // East stride is shorter (more vertices) - length = patch_size / east_stride; - half_length = length / 2; - num_vertices = length + length/2 + 1; - - facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; - - // Iterate through this patch's points - for (i = 0; i < length; i+=2) - { - x = 16 - render_stride; - y = i * east_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - // Iterate through the east patch's points - for (i = 0; i <= length; i++) - { - x = 16; - y = i * east_stride; - - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); - verticesp++; - normalsp++; - texCoords0p++; - texCoords1p++; - } - - for (i = 0; i < length; i++) - { - if (!(i%2)) - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + half_length + i + 1; - *(indicesp++) = index_offset + i/2; - } - else if (i < (length - 2)) - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + i/2 + 1; - *(indicesp++) = index_offset + i/2; - - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + half_length + i + 1; - *(indicesp++) = index_offset + i/2 + 1; - } - else - { - *(indicesp++) = index_offset + half_length + i; - *(indicesp++) = index_offset + half_length + i + 1; - *(indicesp++) = index_offset + i/2; - } - } - } - index_offset += num_vertices; + S32 i, x, y; + + S32 num_vertices; + + U32 render_stride = mLastStride; + S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + S32 length = patch_size / render_stride; + S32 half_length = length / 2; + + U32 east_stride = mLastEastStride; + + // Stride lengths are the same + if (east_stride == render_stride) + { + num_vertices = 2 * length + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(8, 15) + mPatchp->getPointAgent(8, 16))*0.5f; + + // Main patch + for (i = 0; i < length; i++) + { + x = 16 - render_stride; + y = i * render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + // East patch + for (i = 0; i <= length; i++) + { + x = 16; + y = i * render_stride; + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + + for (i = 0; i < length; i++) + { + // Generate indices + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + length + i; + *(indicesp++) = index_offset + length + i + 1; + + if (i != length - 1) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + length + i + 1; + *(indicesp++) = index_offset + i + 1; + } + } + } + else if (east_stride > render_stride) + { + // East stride is longer (has less vertices) + num_vertices = length + half_length + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(7, 15) + mPatchp->getPointAgent(8, 16))*0.5f; + + // Iterate through this patch's points + for (i = 0; i < length; i++) + { + x = 16 - render_stride; + y = i * render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + // Iterate through the east patch's points + for (i = 0; i <= length; i+=2) + { + x = 16; + y = i * render_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + for (i = 0; i < length; i++) + { + if (!(i % 2)) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + length + (i/2); + *(indicesp++) = index_offset + i + 1; + + *(indicesp++) = index_offset + i + 1; + *(indicesp++) = index_offset + length + (i/2); + *(indicesp++) = index_offset + length + (i/2) + 1; + } + else if (i < (length - 1)) + { + *(indicesp++) = index_offset + i; + *(indicesp++) = index_offset + length + (i/2) + 1; + *(indicesp++) = index_offset + i + 1; + } + } + } + else + { + // East stride is shorter (more vertices) + length = patch_size / east_stride; + half_length = length / 2; + num_vertices = length + length/2 + 1; + + facep->mCenterAgent = (mPatchp->getPointAgent(15, 7) + mPatchp->getPointAgent(16, 8))*0.5f; + + // Iterate through this patch's points + for (i = 0; i < length; i+=2) + { + x = 16 - render_stride; + y = i * east_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + // Iterate through the east patch's points + for (i = 0; i <= length; i++) + { + x = 16; + y = i * east_stride; + + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); + verticesp++; + normalsp++; + texCoords0p++; + texCoords1p++; + } + + for (i = 0; i < length; i++) + { + if (!(i%2)) + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + half_length + i + 1; + *(indicesp++) = index_offset + i/2; + } + else if (i < (length - 2)) + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + i/2 + 1; + *(indicesp++) = index_offset + i/2; + + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + half_length + i + 1; + *(indicesp++) = index_offset + i/2 + 1; + } + else + { + *(indicesp++) = index_offset + half_length + i; + *(indicesp++) = index_offset + half_length + i + 1; + *(indicesp++) = index_offset + i/2; + } + } + } + index_offset += num_vertices; } void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp) { - mPatchp = patchp; + mPatchp = patchp; - dirtyPatch(); + dirtyPatch(); }; void LLVOSurfacePatch::dirtyPatch() { - mDirtiedPatch = TRUE; - dirtyGeom(); - mDirtyTerrain = TRUE; - LLVector3 center = mPatchp->getCenterRegion(); - LLSurface *surfacep = mPatchp->getSurface(); + mDirtiedPatch = TRUE; + dirtyGeom(); + mDirtyTerrain = TRUE; + LLVector3 center = mPatchp->getCenterRegion(); + LLSurface *surfacep = mPatchp->getSurface(); - setPositionRegion(center); + setPositionRegion(center); - F32 scale_factor = surfacep->getGridsPerPatchEdge() * surfacep->getMetersPerGrid(); - setScale(LLVector3(scale_factor, scale_factor, mPatchp->getMaxZ() - mPatchp->getMinZ())); + F32 scale_factor = surfacep->getGridsPerPatchEdge() * surfacep->getMetersPerGrid(); + setScale(LLVector3(scale_factor, scale_factor, mPatchp->getMaxZ() - mPatchp->getMinZ())); } void LLVOSurfacePatch::dirtyGeom() { - if (mDrawable) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); - LLFace* facep = mDrawable->getFace(0); - if (facep) - { - facep->setVertexBuffer(NULL); - } - mDrawable->movePartition(); - } + if (mDrawable) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); + LLFace* facep = mDrawable->getFace(0); + if (facep) + { + facep->setVertexBuffer(NULL); + } + mDrawable->movePartition(); + } } void LLVOSurfacePatch::getGeomSizesMain(const S32 stride, S32 &num_vertices, S32 &num_indices) { - S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - - // First, figure out how many vertices we need... - S32 vert_size = patch_size / stride; - if (vert_size >= 2) - { - num_vertices += vert_size * vert_size; - num_indices += 6 * (vert_size - 1)*(vert_size - 1); - } + S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + + // First, figure out how many vertices we need... + S32 vert_size = patch_size / stride; + if (vert_size >= 2) + { + num_vertices += vert_size * vert_size; + num_indices += 6 * (vert_size - 1)*(vert_size - 1); + } } void LLVOSurfacePatch::getGeomSizesNorth(const S32 stride, const S32 north_stride, - S32 &num_vertices, S32 &num_indices) + S32 &num_vertices, S32 &num_indices) { - S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - S32 length = patch_size / stride; - // Stride lengths are the same - if (north_stride == stride) - { - num_vertices += 2 * length + 1; - num_indices += length * 6 - 3; - } - else if (north_stride > stride) - { - // North stride is longer (has less vertices) - num_vertices += length + (length/2) + 1; - num_indices += (length/2)*9 - 3; - } - else - { - // North stride is shorter (more vertices) - length = patch_size / north_stride; - num_vertices += length + (length/2) + 1; - num_indices += 9*(length/2) - 3; - } + S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + S32 length = patch_size / stride; + // Stride lengths are the same + if (north_stride == stride) + { + num_vertices += 2 * length + 1; + num_indices += length * 6 - 3; + } + else if (north_stride > stride) + { + // North stride is longer (has less vertices) + num_vertices += length + (length/2) + 1; + num_indices += (length/2)*9 - 3; + } + else + { + // North stride is shorter (more vertices) + length = patch_size / north_stride; + num_vertices += length + (length/2) + 1; + num_indices += 9*(length/2) - 3; + } } void LLVOSurfacePatch::getGeomSizesEast(const S32 stride, const S32 east_stride, - S32 &num_vertices, S32 &num_indices) + S32 &num_vertices, S32 &num_indices) { - S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); - S32 length = patch_size / stride; - // Stride lengths are the same - if (east_stride == stride) - { - num_vertices += 2 * length + 1; - num_indices += length * 6 - 3; - } - else if (east_stride > stride) - { - // East stride is longer (has less vertices) - num_vertices += length + (length/2) + 1; - num_indices += (length/2)*9 - 3; - } - else - { - // East stride is shorter (more vertices) - length = patch_size / east_stride; - num_vertices += length + (length/2) + 1; - num_indices += 9*(length/2) - 3; - } + S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); + S32 length = patch_size / stride; + // Stride lengths are the same + if (east_stride == stride) + { + num_vertices += 2 * length + 1; + num_indices += length * 6 - 3; + } + else if (east_stride > stride) + { + // East stride is longer (has less vertices) + num_vertices += length + (length/2) + 1; + num_indices += (length/2)*9 - 3; + } + else + { + // East stride is shorter (more vertices) + length = patch_size / east_stride; + num_vertices += length + (length/2) + 1; + num_indices += 9*(length/2) - 3; + } } 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) - + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + { - if (!lineSegmentBoundingBox(start, end)) - { - return FALSE; - } - - LLVector4a da; - da.setSub(end, start); - LLVector3 delta(da.getF32ptr()); - - LLVector3 pdelta = delta; - pdelta.mV[2] = 0; - - F32 plength = pdelta.length(); - - F32 tdelta = 1.f/plength; - - LLVector3 v_start(start.getF32ptr()); - - LLVector3 origin = v_start - mRegionp->getOriginAgent(); - - if (mRegionp->getLandHeightRegion(origin) > origin.mV[2]) - { - //origin is under ground, treat as no intersection - return FALSE; - } - - //step one meter at a time until intersection point found - - //VECTORIZE THIS - const LLVector4a* exta = mDrawable->getSpatialExtents(); - - LLVector3 ext[2]; - ext[0].set(exta[0].getF32ptr()); - ext[1].set(exta[1].getF32ptr()); - - F32 rad = (delta*tdelta).magVecSquared(); - - F32 t = 0.f; - while ( t <= 1.f) - { - LLVector3 sample = origin + delta*t; - - if (AABBSphereIntersectR2(ext[0], ext[1], sample+mRegionp->getOriginAgent(), rad)) - { - F32 height = mRegionp->getLandHeightRegion(sample); - if (height > sample.mV[2]) - { //ray went below ground, positive intersection - //quick and dirty binary search to get impact point - tdelta = -tdelta*0.5f; - F32 err_dist = 0.001f; - F32 dist = fabsf(sample.mV[2] - height); - - while (dist > err_dist && tdelta*tdelta > 0.0f) - { - t += tdelta; - sample = origin+delta*t; - height = mRegionp->getLandHeightRegion(sample); - if ((tdelta < 0 && height < sample.mV[2]) || - (height > sample.mV[2] && tdelta > 0)) - { //jumped over intersection point, go back - tdelta = -tdelta; - } - tdelta *= 0.5f; - dist = fabsf(sample.mV[2] - height); - } - - if (intersection) - { - F32 height = mRegionp->getLandHeightRegion(sample); - if (fabsf(sample.mV[2]-height) < delta.length()*tdelta) - { - sample.mV[2] = mRegionp->getLandHeightRegion(sample); - } - intersection->load3((sample + mRegionp->getOriginAgent()).mV); - } - - if (normal) - { - normal->load3((mRegionp->getLand().resolveNormalGlobal(mRegionp->getPosGlobalFromRegion(sample))).mV); - } - - return TRUE; - } - } - - t += tdelta; - if (t > 1 && t < 1.f+tdelta*0.99f) - { //make sure end point is checked (saves vertical lines coming up negative) - t = 1.f; - } - } - - - return FALSE; + if (!lineSegmentBoundingBox(start, end)) + { + return FALSE; + } + + LLVector4a da; + da.setSub(end, start); + LLVector3 delta(da.getF32ptr()); + + LLVector3 pdelta = delta; + pdelta.mV[2] = 0; + + F32 plength = pdelta.length(); + + F32 tdelta = 1.f/plength; + + LLVector3 v_start(start.getF32ptr()); + + LLVector3 origin = v_start - mRegionp->getOriginAgent(); + + if (mRegionp->getLandHeightRegion(origin) > origin.mV[2]) + { + //origin is under ground, treat as no intersection + return FALSE; + } + + //step one meter at a time until intersection point found + + //VECTORIZE THIS + const LLVector4a* exta = mDrawable->getSpatialExtents(); + + LLVector3 ext[2]; + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); + + F32 rad = (delta*tdelta).magVecSquared(); + + F32 t = 0.f; + while ( t <= 1.f) + { + LLVector3 sample = origin + delta*t; + + if (AABBSphereIntersectR2(ext[0], ext[1], sample+mRegionp->getOriginAgent(), rad)) + { + F32 height = mRegionp->getLandHeightRegion(sample); + if (height > sample.mV[2]) + { //ray went below ground, positive intersection + //quick and dirty binary search to get impact point + tdelta = -tdelta*0.5f; + F32 err_dist = 0.001f; + F32 dist = fabsf(sample.mV[2] - height); + + while (dist > err_dist && tdelta*tdelta > 0.0f) + { + t += tdelta; + sample = origin+delta*t; + height = mRegionp->getLandHeightRegion(sample); + if ((tdelta < 0 && height < sample.mV[2]) || + (height > sample.mV[2] && tdelta > 0)) + { //jumped over intersection point, go back + tdelta = -tdelta; + } + tdelta *= 0.5f; + dist = fabsf(sample.mV[2] - height); + } + + if (intersection) + { + F32 height = mRegionp->getLandHeightRegion(sample); + if (fabsf(sample.mV[2]-height) < delta.length()*tdelta) + { + sample.mV[2] = mRegionp->getLandHeightRegion(sample); + } + intersection->load3((sample + mRegionp->getOriginAgent()).mV); + } + + if (normal) + { + normal->load3((mRegionp->getLand().resolveNormalGlobal(mRegionp->getPosGlobalFromRegion(sample))).mV); + } + + return TRUE; + } + } + + t += tdelta; + if (t > 1 && t < 1.f+tdelta*0.99f) + { //make sure end point is checked (saves vertical lines coming up negative) + t = 1.f; + } + } + + + return FALSE; } void LLVOSurfacePatch::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { - LLVector3 posAgent = getPositionAgent(); - LLVector3 scale = getScale(); - //make z-axis scale at least 1 to avoid shadow artifacts on totally flat land - scale.mV[VZ] = llmax(scale.mV[VZ], 1.f); - newMin.load3( (posAgent-scale*0.5f).mV); // Changing to 2.f makes the culling a -little- better, but still wrong - newMax.load3( (posAgent+scale*0.5f).mV); - LLVector4a pos; - pos.setAdd(newMin,newMax); - pos.mul(0.5f); - mDrawable->setPositionGroup(pos); + LLVector3 posAgent = getPositionAgent(); + LLVector3 scale = getScale(); + //make z-axis scale at least 1 to avoid shadow artifacts on totally flat land + scale.mV[VZ] = llmax(scale.mV[VZ], 1.f); + newMin.load3( (posAgent-scale*0.5f).mV); // Changing to 2.f makes the culling a -little- better, but still wrong + newMax.load3( (posAgent+scale*0.5f).mV); + LLVector4a pos; + pos.setAdd(newMin,newMax); + pos.mul(0.5f); + mDrawable->setPositionGroup(pos); } U32 LLVOSurfacePatch::getPartitionType() const -{ - return LLViewerRegion::PARTITION_TERRAIN; +{ + return LLViewerRegion::PARTITION_TERRAIN; } LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp) : LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, regionp) { - mOcclusionEnabled = FALSE; - mInfiniteFarClip = TRUE; - mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; - mPartitionType = LLViewerRegion::PARTITION_TERRAIN; + mOcclusionEnabled = FALSE; + mInfiniteFarClip = TRUE; + mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; + mPartitionType = LLViewerRegion::PARTITION_TERRAIN; } // Do not add vertices; honor strict vertex count specified by strider_vertex_count @@ -1033,22 +1033,22 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED; - LLVertexBuffer* buffer = group->mVertexBuffer; + LLVertexBuffer* buffer = group->mVertexBuffer; - //get vertex buffer striders - LLStrider vertices_start; - LLStrider normals_start; - LLStrider tangents_start; - LLStrider texcoords_start; - LLStrider texcoords2_start; - LLStrider indices_start; + //get vertex buffer striders + LLStrider vertices_start; + LLStrider normals_start; + LLStrider tangents_start; + LLStrider texcoords_start; + LLStrider texcoords2_start; + LLStrider indices_start; - llassert_always(buffer->getVertexStrider(vertices_start)); - llassert_always(buffer->getNormalStrider(normals_start)); - llassert_always(buffer->getTangentStrider(tangents_start)); - llassert_always(buffer->getTexCoord0Strider(texcoords_start)); - llassert_always(buffer->getTexCoord1Strider(texcoords2_start)); - llassert_always(buffer->getIndexStrider(indices_start)); + llassert_always(buffer->getVertexStrider(vertices_start)); + llassert_always(buffer->getNormalStrider(normals_start)); + llassert_always(buffer->getTangentStrider(tangents_start)); + llassert_always(buffer->getTexCoord0Strider(texcoords_start)); + llassert_always(buffer->getTexCoord1Strider(texcoords2_start)); + llassert_always(buffer->getIndexStrider(indices_start)); U32 indices_index = 0; U32 index_offset = 0; @@ -1088,7 +1088,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) gen_terrain_tangents(index_offset, indices_index, vertices, normals, tangents, texcoords, indices); } - buffer->unmapBuffer(); - mFaceList.clear(); + buffer->unmapBuffer(); + mFaceList.clear(); } diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index a3dcb945d1..a38a5e011f 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -1,25 +1,25 @@ -/** +/** * @file llvosurfacepatch.h * @brief Description of LLVOSurfacePatch class * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -39,103 +39,103 @@ class LLFace; class LLVOSurfacePatch : public LLStaticViewerObject { public: - static F32 sLODFactor; + static F32 sLODFactor; - enum - { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_TEXCOORD1) - }; + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) + }; - LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - /*virtual*/ void markDead(); + /*virtual*/ void markDead(); - // Initialize data that's only inited once per class. - static void initClass(); + // Initialize data that's only inited once per class. + static void initClass(); - virtual U32 getPartitionType() const; + virtual U32 getPartitionType() const; - /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - /*virtual*/ void updateGL(); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ BOOL updateLOD(); - /*virtual*/ void updateFaceSize(S32 idx); + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ void updateGL(); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ BOOL updateLOD(); + /*virtual*/ void updateFaceSize(S32 idx); void getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp); - /*virtual*/ void updateTextures(); - /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area + /*virtual*/ void updateTextures(); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area - /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); - /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); + /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - void setPatch(LLSurfacePatch *patchp); - LLSurfacePatch *getPatch() const { return mPatchp; } + void setPatch(LLSurfacePatch *patchp); + LLSurfacePatch *getPatch() const { return mPatchp; } - void dirtyPatch(); - void dirtyGeom(); + void dirtyPatch(); + void dirtyGeom(); - /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - BOOL pick_rigged = FALSE, + /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + 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 - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); - - BOOL mDirtiedPatch; + 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 + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); + + BOOL mDirtiedPatch; protected: - ~LLVOSurfacePatch(); - - LLFacePool *mPool; - LLFacePool *getPool(); - S32 mBaseComp; - LLSurfacePatch *mPatchp; - BOOL mDirtyTexture; - BOOL mDirtyTerrain; - - S32 mLastNorthStride; - S32 mLastEastStride; - S32 mLastStride; - S32 mLastLength; - - void getGeomSizesMain(const S32 stride, S32 &num_vertices, S32 &num_indices); - void getGeomSizesNorth(const S32 stride, const S32 north_stride, - S32 &num_vertices, S32 &num_indices); - void getGeomSizesEast(const S32 stride, const S32 east_stride, - S32 &num_vertices, S32 &num_indices); - - void updateMainGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset); - void updateNorthGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset); - void updateEastGeometry(LLFace *facep, - LLStrider &verticesp, - LLStrider &normalsp, - LLStrider &texCoords0p, - LLStrider &texCoords1p, - LLStrider &indicesp, - U32 &index_offset); + ~LLVOSurfacePatch(); + + LLFacePool *mPool; + LLFacePool *getPool(); + S32 mBaseComp; + LLSurfacePatch *mPatchp; + BOOL mDirtyTexture; + BOOL mDirtyTerrain; + + S32 mLastNorthStride; + S32 mLastEastStride; + S32 mLastStride; + S32 mLastLength; + + void getGeomSizesMain(const S32 stride, S32 &num_vertices, S32 &num_indices); + void getGeomSizesNorth(const S32 stride, const S32 north_stride, + S32 &num_vertices, S32 &num_indices); + void getGeomSizesEast(const S32 stride, const S32 east_stride, + S32 &num_vertices, S32 &num_indices); + + void updateMainGeometry(LLFace *facep, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset); + void updateNorthGeometry(LLFace *facep, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset); + void updateEastGeometry(LLFace *facep, + LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp, + U32 &index_offset); }; #endif // LL_VOSURFACEPATCH_H diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a956814147..2459f8cd58 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llvovolume.cpp * @brief LLVOVolume class implementation * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -97,7 +97,7 @@ U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 1; BOOL gAnimateTextures = TRUE; F32 LLVOVolume::sLODFactor = 1.f; -F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop +F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; S32 LLVOVolume::mRenderComplexity_last = 0; @@ -111,218 +111,218 @@ extern BOOL gCubeSnapshot; class LLMediaDataClientObjectImpl : public LLMediaDataClientObject { public: - LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) - { - mObject->addMDCImpl(); - } - ~LLMediaDataClientObjectImpl() - { - mObject->removeMDCImpl(); - } - - virtual U8 getMediaDataCount() const - { return mObject->getNumTEs(); } - - virtual LLSD getMediaDataLLSD(U8 index) const - { - LLSD result; - LLTextureEntry *te = mObject->getTE(index); - if (NULL != te) - { - llassert((te->getMediaData() != NULL) == te->hasMedia()); - if (te->getMediaData() != NULL) - { - result = te->getMediaData()->asLLSD(); - // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly - // See DEV-41949 - if (!result.has(LLMediaEntry::WHITELIST_KEY)) - { - result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); - } - } - } - return result; - } - virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const - { - LLTextureEntry *te = mObject->getTE(index); - if (te) - { - if (te->getMediaData()) - { - return (te->getMediaData()->getCurrentURL() == url); - } - } - return url.empty(); - } - - virtual LLUUID getID() const - { return mObject->getID(); } - - virtual void mediaNavigateBounceBack(U8 index) - { mObject->mediaNavigateBounceBack(index); } - - virtual bool hasMedia() const - { return mObject->hasMedia(); } - - virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) - { mObject->updateObjectMediaData(data, version_string); } - - virtual F64 getMediaInterest() const - { - F64 interest = mObject->getTotalMediaInterest(); - if (interest < (F64)0.0) - { - // media interest not valid yet, try pixel area - interest = mObject->getPixelArea(); - // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. - if (interest == 1024.f) - { - const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); - interest = mObject->getPixelArea(); - } - } - return interest; - } - - virtual bool isInterestingEnough() const - { - return LLViewerMedia::getInstance()->isInterestingEnough(mObject, getMediaInterest()); - } - - virtual std::string getCapabilityUrl(const std::string &name) const - { return mObject->getRegion()->getCapability(name); } - - virtual bool isDead() const - { return mObject->isDead(); } - - virtual U32 getMediaVersion() const - { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } - - virtual bool isNew() const - { return mNew; } + LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew) + { + mObject->addMDCImpl(); + } + ~LLMediaDataClientObjectImpl() + { + mObject->removeMDCImpl(); + } + + virtual U8 getMediaDataCount() const + { return mObject->getNumTEs(); } + + virtual LLSD getMediaDataLLSD(U8 index) const + { + LLSD result; + LLTextureEntry *te = mObject->getTE(index); + if (NULL != te) + { + llassert((te->getMediaData() != NULL) == te->hasMedia()); + if (te->getMediaData() != NULL) + { + result = te->getMediaData()->asLLSD(); + // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly + // See DEV-41949 + if (!result.has(LLMediaEntry::WHITELIST_KEY)) + { + result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray(); + } + } + } + return result; + } + virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const + { + LLTextureEntry *te = mObject->getTE(index); + if (te) + { + if (te->getMediaData()) + { + return (te->getMediaData()->getCurrentURL() == url); + } + } + return url.empty(); + } + + virtual LLUUID getID() const + { return mObject->getID(); } + + virtual void mediaNavigateBounceBack(U8 index) + { mObject->mediaNavigateBounceBack(index); } + + virtual bool hasMedia() const + { return mObject->hasMedia(); } + + virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string) + { mObject->updateObjectMediaData(data, version_string); } + + virtual F64 getMediaInterest() const + { + F64 interest = mObject->getTotalMediaInterest(); + if (interest < (F64)0.0) + { + // media interest not valid yet, try pixel area + interest = mObject->getPixelArea(); + // HACK: force recalculation of pixel area if interest is the "magic default" of 1024. + if (interest == 1024.f) + { + const_cast(static_cast(mObject))->setPixelAreaAndAngle(gAgent); + interest = mObject->getPixelArea(); + } + } + return interest; + } + + virtual bool isInterestingEnough() const + { + return LLViewerMedia::getInstance()->isInterestingEnough(mObject, getMediaInterest()); + } + + virtual std::string getCapabilityUrl(const std::string &name) const + { return mObject->getRegion()->getCapability(name); } + + virtual bool isDead() const + { return mObject->isDead(); } + + virtual U32 getMediaVersion() const + { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); } + + virtual bool isNew() const + { return mNew; } private: - LLPointer mObject; - bool mNew; + LLPointer mObject; + bool mNew; }; LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp), - mVolumeImpl(NULL) + : LLViewerObject(id, pcode, regionp), + mVolumeImpl(NULL) { - mTexAnimMode = 0; - mRelativeXform.setIdentity(); - mRelativeXformInvTrans.setIdentity(); + mTexAnimMode = 0; + mRelativeXform.setIdentity(); + mRelativeXformInvTrans.setIdentity(); - mFaceMappingChanged = FALSE; - mLOD = MIN_LOD; + mFaceMappingChanged = FALSE; + mLOD = MIN_LOD; mLODDistance = 0.0f; mLODAdjustedDistance = 0.0f; mLODRadius = 0.0f; - mTextureAnimp = NULL; - mVolumeChanged = FALSE; - mVObjRadius = LLVector3(1,1,0.5f).length(); - mNumFaces = 0; - mLODChanged = FALSE; - mSculptChanged = FALSE; + mTextureAnimp = NULL; + mVolumeChanged = FALSE; + mVObjRadius = LLVector3(1,1,0.5f).length(); + mNumFaces = 0; + mLODChanged = FALSE; + mSculptChanged = FALSE; mColorChanged = FALSE; - mSpotLightPriority = 0.f; + mSpotLightPriority = 0.f; mSkinInfoUnavaliable = false; - mSkinInfo = NULL; + mSkinInfo = NULL; - mMediaImplList.resize(getNumTEs()); - mLastFetchedMediaVersion = -1; + mMediaImplList.resize(getNumTEs()); + mLastFetchedMediaVersion = -1; mServerDrawableUpdateCount = 0; - memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); - mMDCImplCount = 0; - mLastRiggingInfoLOD = -1; - mResetDebugText = false; + memset(&mIndexInTex, 0, sizeof(S32) * LLRender::NUM_VOLUME_TEXTURE_CHANNELS); + mMDCImplCount = 0; + mLastRiggingInfoLOD = -1; + mResetDebugText = false; } LLVOVolume::~LLVOVolume() { LL_PROFILE_ZONE_SCOPED; - delete mTextureAnimp; - mTextureAnimp = NULL; - delete mVolumeImpl; - mVolumeImpl = NULL; + delete mTextureAnimp; + mTextureAnimp = NULL; + delete mVolumeImpl; + mVolumeImpl = NULL; - gMeshRepo.unregisterMesh(this); + gMeshRepo.unregisterMesh(this); - if(!mMediaImplList.empty()) - { - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - if(mMediaImplList[i].notNull()) - { - mMediaImplList[i]->removeObject(this) ; - } - } - } + if(!mMediaImplList.empty()) + { + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + if(mMediaImplList[i].notNull()) + { + mMediaImplList[i]->removeObject(this) ; + } + } + } } void LLVOVolume::markDead() { - if (!mDead) - { + if (!mDead) + { LL_PROFILE_ZONE_SCOPED; if (getVolume()) { LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); } - if(getMDCImplCount() > 0) - { - LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); - if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); - if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); - } - - // Detach all media impls from this object - for(U32 i = 0 ; i < mMediaImplList.size() ; i++) - { - removeMediaImpl(i); - } - - if (mSculptTexture.notNull()) - { - mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); - } - - if (mLightTexture.notNull()) - { - mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); - } - + if(getMDCImplCount() > 0) + { + LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast(this), false); + if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj); + if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj); + } + + // Detach all media impls from this object + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + removeMediaImpl(i); + } + + if (mSculptTexture.notNull()) + { + mSculptTexture->removeVolume(LLRender::SCULPT_TEX, this); + } + + if (mLightTexture.notNull()) + { + mLightTexture->removeVolume(LLRender::LIGHT_TEX, this); + } + if (mIsHeroProbe) { gPipeline.mHeroProbeManager.unregisterViewerObject(this); } - } - - LLViewerObject::markDead(); + } + + LLViewerObject::markDead(); } // static void LLVOVolume::initClass() { - // gSavedSettings better be around - if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) - { - const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); - const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); - const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); - const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); - const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); - sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, - max_sorted_queue_size, max_round_robin_queue_size); - sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, - max_retries, max_sorted_queue_size, max_round_robin_queue_size); - } + // gSavedSettings better be around + if (gSavedSettings.getBOOL("PrimMediaMasterEnabled")) + { + const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay"); + const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay"); + const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries"); + const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize"); + const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize"); + sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries, + max_sorted_queue_size, max_round_robin_queue_size); + sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, + max_retries, max_sorted_queue_size, max_round_robin_queue_size); + } } // static @@ -333,65 +333,65 @@ void LLVOVolume::cleanupClass() } U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, EObjectUpdateType update_type, - LLDataPacker *dp) + void **user_data, + U32 block_num, EObjectUpdateType update_type, + LLDataPacker *dp) { - - LLColor4U color; - const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); + + LLColor4U color; + const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); const bool previously_volume_changed = mVolumeChanged; const bool previously_face_mapping_changed = mFaceMappingChanged; const bool previously_color_changed = mColorChanged; - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); + // Do base class updates... + U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - LLUUID sculpt_id; - U8 sculpt_type = 0; - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - sculpt_id = sculpt_params->getSculptTexture(); - sculpt_type = sculpt_params->getSculptType(); + LLUUID sculpt_id; + U8 sculpt_type = 0; + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + sculpt_id = sculpt_params->getSculptTexture(); + sculpt_type = sculpt_params->getSculptType(); LL_DEBUGS("ObjectUpdate") << "uuid " << mID << " set sculpt_id " << sculpt_id << LL_ENDL; dumpStack("ObjectUpdateStack"); - } - - if (!dp) - { - if (update_type == OUT_FULL) - { - //////////////////////////////// - // - // Unpack texture animation data - // - // - - if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - - mTextureAnimp->unpackTAMessage(mesgsys, block_num); - } - else - { - if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; + } + + if (!dp) + { + if (update_type == OUT_FULL) + { + //////////////////////////////// + // + // Unpack texture animation data + // + // + + if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim)) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + + mTextureAnimp->unpackTAMessage(mesgsys, block_num); + } + else + { + if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; for (S32 i = 0; i < getNumTEs(); i++) { @@ -404,98 +404,98 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, } } - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - - // Unpack volume data - LLVolumeParams volume_params; - LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(); - } - } - - // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... - //////////////////////////// - // - // Unpack texture entry data - // - - S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); - - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - else - { - if (update_type != OUT_TERSE_IMPROVED) - { - LLVolumeParams volume_params; - BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); - if (!res) - { - LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; - LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; - } - - volume_params.setSculptID(sculpt_id, sculpt_type); - - if (setVolume(volume_params, 0)) - { - markForUpdate(); - } - S32 res2 = unpackTEMessage(*dp); - if (TEM_INVALID == res2) - { - // There's something bogus in the data that we're unpacking. - dp->dumpBufferToLog(); - LL_WARNS() << "Flushing cache files" << LL_ENDL; - - if(LLVOCache::instanceExists() && getRegion()) - { - LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; - } - - LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; - } - else - { - if (res2 & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - - U32 value = dp->getPassFlags(); - - if (value & 0x40) - { - if (!mTextureAnimp) - { - mTextureAnimp = new LLViewerTextureAnim(this); - } - else - { - if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) - { - mTextureAnimp->reset(); - } - } - mTexAnimMode = 0; - mTextureAnimp->unpackTAMessage(*dp); - } - else if (mTextureAnimp) - { - delete mTextureAnimp; - mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + + // Unpack volume data + LLVolumeParams volume_params; + LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num); + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(); + } + } + + // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens... + //////////////////////////// + // + // Unpack texture entry data + // + + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); + + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + else + { + if (update_type != OUT_TERSE_IMPROVED) + { + LLVolumeParams volume_params; + BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp); + if (!res) + { + LL_WARNS() << "Bogus volume parameters in object " << getID() << LL_ENDL; + LL_WARNS() << getRegion()->getOriginGlobal() << LL_ENDL; + } + + volume_params.setSculptID(sculpt_id, sculpt_type); + + if (setVolume(volume_params, 0)) + { + markForUpdate(); + } + S32 res2 = unpackTEMessage(*dp); + if (TEM_INVALID == res2) + { + // There's something bogus in the data that we're unpacking. + dp->dumpBufferToLog(); + LL_WARNS() << "Flushing cache files" << LL_ENDL; + + if(LLVOCache::instanceExists() && getRegion()) + { + LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; + } + + LL_WARNS() << "Bogus TE data in " << getID() << LL_ENDL; + } + else + { + if (res2 & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + + U32 value = dp->getPassFlags(); + + if (value & 0x40) + { + if (!mTextureAnimp) + { + mTextureAnimp = new LLViewerTextureAnim(this); + } + else + { + if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH)) + { + mTextureAnimp->reset(); + } + } + mTexAnimMode = 0; + mTextureAnimp->unpackTAMessage(*dp); + } + else if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; for (S32 i = 0; i < getNumTEs(); i++) { @@ -508,59 +508,59 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, } } - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - - if (value & 0x400) - { //particle system (new) - unpackParticleSource(*dp, mOwnerID, false); - } - } - else - { - S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); - if (texture_length) - { - U8 tdpbuffer[1024]; - LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); - S32 result = unpackTEMessage(tdp); - if (result & teDirtyBits) - { - if (mDrawable) + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + + if (value & 0x400) + { //particle system (new) + unpackParticleSource(*dp, mOwnerID, false); + } + } + else + { + S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry); + if (texture_length) + { + U8 tdpbuffer[1024]; + LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num, 1024); + S32 result = unpackTEMessage(tdp); + if (result & teDirtyBits) + { + if (mDrawable) { //on the fly TE updates break batches, isolate in octree shrinkWrap(); } - } - if (result & TEM_CHANGE_MEDIA) - { - retval |= MEDIA_FLAGS_CHANGED; - } - } - } - } - if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) - { - // If only the media URL changed, and it isn't a media version URL, - // ignore it - if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && - mMedia && ! mMedia->mMediaURL.empty() && - ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) - { - // If the media changed at all, request new media data - LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << + } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } + } + } + } + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) + { + // If only the media URL changed, and it isn't a media version URL, + // ignore it + if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) && + mMedia && ! mMedia->mMediaURL.empty() && + ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) ) + { + // If the media changed at all, request new media data + LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; - requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); - } + requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED); + } else { LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " << ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL; } - } - // ...and clean up any media impls - cleanUpMediaImpls(); + } + // ...and clean up any media impls + cleanUpMediaImpls(); if (( (mVolumeChanged && !previously_volume_changed) || @@ -571,7 +571,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, onDrawableUpdateFromServer(); } - return retval; + return retval; } // Called when a volume, material, etc is updated by the server, possibly by a @@ -590,117 +590,117 @@ void LLVOVolume::onDrawableUpdateFromServer() void LLVOVolume::animateTextures() { - if (!mDead) - { + if (!mDead) + { shrinkWrap(); - F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; - S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); - - if (result) - { - if (!mTexAnimMode) - { - mFaceMappingChanged = TRUE; - gPipeline.markTextured(mDrawable); - } - mTexAnimMode = result | mTextureAnimp->mMode; - - S32 start=0, end=mDrawable->getNumFaces()-1; - if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) - { - start = end = mTextureAnimp->mFace; - } - - for (S32 i = start; i <= end; i++) - { - LLFace* facep = mDrawable->getFace(i); - if (!facep) continue; - if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; - - const LLTextureEntry* te = facep->getTextureEntry(); - - if (!te) - { - continue; - } - - if (!(result & LLViewerTextureAnim::ROTATE)) - { - te->getRotation(&rot); - } - if (!(result & LLViewerTextureAnim::TRANSLATE)) - { - te->getOffset(&off_s,&off_t); - } - if (!(result & LLViewerTextureAnim::SCALE)) - { - te->getScale(&scale_s, &scale_t); - } - - if (!facep->mTextureMatrix) - { - facep->mTextureMatrix = new LLMatrix4(); - } - - LLMatrix4& tex_mat = *facep->mTextureMatrix; - tex_mat.setIdentity(); - LLVector3 trans ; - - trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); - tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); - - LLVector3 scale(scale_s, scale_t, 1.f); - LLQuaternion quat; - quat.setQuat(rot, 0, 0, -1.f); - - tex_mat.rotate(quat); - - LLMatrix4 mat; - mat.initAll(scale, LLQuaternion(), LLVector3()); - tex_mat *= mat; - - tex_mat.translate(trans); - } - } - else - { - if (mTexAnimMode && mTextureAnimp->mRate == 0) - { - U8 start, count; - - if (mTextureAnimp->mFace == -1) - { - start = 0; - count = getNumTEs(); - } - else - { - start = (U8) mTextureAnimp->mFace; - count = 1; - } - - for (S32 i = start; i < start + count; i++) - { - if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) - { - setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); - } - if (mTexAnimMode & LLViewerTextureAnim::SCALE) - { - setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); - } - if (mTexAnimMode & LLViewerTextureAnim::ROTATE) - { - setTERotation(i, mTextureAnimp->mRot); - } - } - - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - mTexAnimMode = 0; - } - } - } + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot); + + if (result) + { + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; + + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } + + for (S32 i = start; i <= end; i++) + { + LLFace* facep = mDrawable->getFace(i); + if (!facep) continue; + if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue; + + const LLTextureEntry* te = facep->getTextureEntry(); + + if (!te) + { + continue; + } + + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); + } + + if (!facep->mTextureMatrix) + { + facep->mTextureMatrix = new LLMatrix4(); + } + + LLMatrix4& tex_mat = *facep->mTextureMatrix; + tex_mat.setIdentity(); + LLVector3 trans ; + + trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f)); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + + LLVector3 scale(scale_s, scale_t, 1.f); + LLQuaternion quat; + quat.setQuat(rot, 0, 0, -1.f); + + tex_mat.rotate(quat); + + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + + tex_mat.translate(trans); + } + } + else + { + if (mTexAnimMode && mTextureAnimp->mRate == 0) + { + U8 start, count; + + if (mTextureAnimp->mFace == -1) + { + start = 0; + count = getNumTEs(); + } + else + { + start = (U8) mTextureAnimp->mFace; + count = 1; + } + + for (S32 i = start; i < start + count; i++) + { + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) + { + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); + } + if (mTexAnimMode & LLViewerTextureAnim::SCALE) + { + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); + } + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) + { + setTERotation(i, mTextureAnimp->mRot); + } + } + + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } + } + } } void LLVOVolume::updateTextures() @@ -709,403 +709,403 @@ void LLVOVolume::updateTextures() updateTextureVirtualSize(); } -BOOL LLVOVolume::isVisible() const +BOOL LLVOVolume::isVisible() const { - if(mDrawable.notNull() && mDrawable->isVisible()) - { - return TRUE ; - } + if(mDrawable.notNull() && mDrawable->isVisible()) + { + return TRUE ; + } - if(isAttachment()) - { - LLViewerObject* objp = (LLViewerObject*)getParent() ; - while(objp && !objp->isAvatar()) - { - objp = (LLViewerObject*)objp->getParent() ; - } + if(isAttachment()) + { + LLViewerObject* objp = (LLViewerObject*)getParent() ; + while(objp && !objp->isAvatar()) + { + objp = (LLViewerObject*)objp->getParent() ; + } - return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; - } + return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ; + } - return FALSE ; + return FALSE ; } void LLVOVolume::updateTextureVirtualSize(bool forced) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - // Update the pixel area of all faces + // Update the pixel area of all faces if (mDrawable.isNull() || gCubeSnapshot) { return; } - if(!forced) - { - if(!isVisible()) - { //don't load textures for non-visible faces - const S32 num_faces = mDrawable->getNumFaces(); - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (face) - { - face->setPixelArea(0.f); - face->setVirtualSize(0.f); - } - } - - return ; - } - - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; - } - } - - static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); - - if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) - { - return; - } - - mTextureUpdateTimer.reset(); - - F32 old_area = mPixelArea; - mPixelArea = 0.f; - - const S32 num_faces = mDrawable->getNumFaces(); - F32 min_vsize=999999999.f, max_vsize=0.f; - LLViewerCamera* camera = LLViewerCamera::getInstance(); - std::stringstream debug_text; - for (S32 i = 0; i < num_faces; i++) - { - LLFace* face = mDrawable->getFace(i); - if (!face) continue; - const LLTextureEntry *te = face->getTextureEntry(); - LLViewerTexture *imagep = face->getTexture(); - if (!imagep || !te || - face->mExtents[0].equals3(face->mExtents[1])) - { - continue; - } - - F32 vsize; - F32 old_size = face->getVirtualSize(); - - if (isHUDAttachment()) - { - F32 area = (F32) camera->getScreenPixelArea(); - vsize = area; - imagep->setBoostLevel(LLGLTexture::BOOST_HUD); - face->setPixelArea(area); // treat as full screen - face->setVirtualSize(vsize); - } - else - { - vsize = face->getTextureVirtualSize(); - } - - mPixelArea = llmax(mPixelArea, face->getPixelArea()); + if(!forced) + { + if(!isVisible()) + { //don't load textures for non-visible faces + const S32 num_faces = mDrawable->getNumFaces(); + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (face) + { + face->setPixelArea(0.f); + face->setVirtualSize(0.f); + } + } - // if the face has gotten small enough to turn off texture animation and texture - // animation is running, rebuild the render batch for this face to turn off - // texture animation - if (face->mTextureMatrix != NULL) - { - if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; - if(img) - { - debug_text << img->getDiscardLevel() << ":" << img->getDesiredDiscardLevel() << ":" << img->getWidth() << ":" << (S32) sqrtf(vsize) << ":" << (S32) sqrtf(img->getMaxVirtualSize()) << "\n"; - /*F32 pri = img->getDecodePriority(); - pri = llmax(pri, 0.0f); - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri;*/ - } - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - F32 pri = mPixelArea; - if (pri < min_vsize) min_vsize = pri; - if (pri > max_vsize) max_vsize = pri; - } - } - - if (isSculpted()) - { - updateSculptTexture(); - - - - if (mSculptTexture.notNull()) - { - mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), - (S32)LLGLTexture::BOOST_SCULPTED)); - mSculptTexture->setForSculpt() ; - - if(!mSculptTexture->isCachedRawImageReady()) - { - S32 lod = llmin(mLOD, 3); - F32 lodf = ((F32)(lod + 1.0f)/4.f); - F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; - mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); - } - - S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture - S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; - - if (texture_discard >= 0 && //texture has some data available - (texture_discard < current_discard || //texture has more data than last rebuild - current_discard < 0)) //no previous rebuild - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - mSculptChanged = TRUE; - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) - { - setDebugText(llformat("T%d C%d V%d\n%dx%d", - texture_discard, current_discard, getVolume()->getSculptLevel(), - mSculptTexture->getHeight(), mSculptTexture->getWidth())); - } - } - - } - - if (getLightTextureID().notNull()) - { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - LLUUID id = params->getLightTexture(); - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); - if (mLightTexture.notNull()) - { - F32 rad = getLightRadius(); - mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), - LLVector3(rad,rad,rad), - *camera)); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - //setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - setDebugText(debug_text.str()); - } - else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) - { - setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); - } + return ; + } - if (mPixelArea == 0) - { //flexi phasing issues make this happen - mPixelArea = old_area; - } -} + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } + } -BOOL LLVOVolume::isActive() const -{ - return !mStatic; -} + static LLCachedControl dont_load_textures(gSavedSettings,"TextureDisable", false); -BOOL LLVOVolume::setMaterial(const U8 material) -{ - BOOL res = LLViewerObject::setMaterial(material); - - return res; -} + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) + { + return; + } -void LLVOVolume::setTexture(const S32 face) -{ - llassert(face < getNumTEs()); - gGL.getTexUnit(0)->bind(getTEImage(face)); -} + mTextureUpdateTimer.reset(); -void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) -{ - if (scale != getScale()) - { - // store local radius - LLViewerObject::setScale(scale); + F32 old_area = mPixelArea; + mPixelArea = 0.f; - if (mVolumeImpl) - { - mVolumeImpl->onSetScale(scale, damped); - } - - updateRadius(); + const S32 num_faces = mDrawable->getNumFaces(); + F32 min_vsize=999999999.f, max_vsize=0.f; + LLViewerCamera* camera = LLViewerCamera::getInstance(); + std::stringstream debug_text; + for (S32 i = 0; i < num_faces; i++) + { + LLFace* face = mDrawable->getFace(i); + if (!face) continue; + const LLTextureEntry *te = face->getTextureEntry(); + LLViewerTexture *imagep = face->getTexture(); + if (!imagep || !te || + face->mExtents[0].equals3(face->mExtents[1])) + { + continue; + } - //since drawable transforms do not include scale, changing volume scale - //requires an immediate rebuild of volume verts. - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); + F32 vsize; + F32 old_size = face->getVirtualSize(); - if (mDrawable) + if (isHUDAttachment()) { - shrinkWrap(); + F32 area = (F32) camera->getScreenPixelArea(); + vsize = area; + imagep->setBoostLevel(LLGLTexture::BOOST_HUD); + face->setPixelArea(area); // treat as full screen + face->setVirtualSize(vsize); + } + else + { + vsize = face->getTextureVirtualSize(); } - } -} -LLFace* LLVOVolume::addFace(S32 f) -{ - const LLTextureEntry* te = getTE(f); - LLViewerTexture* imagep = getTEImage(f); - if (te->getMaterialParams().notNull()) - { - LLViewerTexture* normalp = getTENormalMap(f); - LLViewerTexture* specularp = getTESpecularMap(f); - return mDrawable->addFace(te, imagep, normalp, specularp); - } - return mDrawable->addFace(te, imagep); + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + + // if the face has gotten small enough to turn off texture animation and texture + // animation is running, rebuild the render batch for this face to turn off + // texture animation + if (face->mTextureMatrix != NULL) + { + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; + if(img) + { + debug_text << img->getDiscardLevel() << ":" << img->getDesiredDiscardLevel() << ":" << img->getWidth() << ":" << (S32) sqrtf(vsize) << ":" << (S32) sqrtf(img->getMaxVirtualSize()) << "\n"; + /*F32 pri = img->getDecodePriority(); + pri = llmax(pri, 0.0f); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri;*/ + } + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + F32 pri = mPixelArea; + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + + if (isSculpted()) + { + updateSculptTexture(); + + + + if (mSculptTexture.notNull()) + { + mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), + (S32)LLGLTexture::BOOST_SCULPTED)); + mSculptTexture->setForSculpt() ; + + if(!mSculptTexture->isCachedRawImageReady()) + { + S32 lod = llmin(mLOD, 3); + F32 lodf = ((F32)(lod + 1.0f)/4.f); + F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ; + mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE); + } + + S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture + S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ; + + if (texture_discard >= 0 && //texture has some data available + (texture_discard < current_discard || //texture has more data than last rebuild + current_discard < 0)) //no previous rebuild + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + mSculptChanged = TRUE; + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED)) + { + setDebugText(llformat("T%d C%d V%d\n%dx%d", + texture_discard, current_discard, getVolume()->getSculptLevel(), + mSculptTexture->getHeight(), mSculptTexture->getWidth())); + } + } + + } + + if (getLightTextureID().notNull()) + { + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *camera)); + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + //setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + setDebugText(debug_text.str()); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } + + if (mPixelArea == 0) + { //flexi phasing issues make this happen + mPixelArea = old_area; + } +} + +BOOL LLVOVolume::isActive() const +{ + return !mStatic; +} + +BOOL LLVOVolume::setMaterial(const U8 material) +{ + BOOL res = LLViewerObject::setMaterial(material); + + return res; +} + +void LLVOVolume::setTexture(const S32 face) +{ + llassert(face < getNumTEs()); + gGL.getTexUnit(0)->bind(getTEImage(face)); +} + +void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) +{ + if (scale != getScale()) + { + // store local radius + LLViewerObject::setScale(scale); + + if (mVolumeImpl) + { + mVolumeImpl->onSetScale(scale, damped); + } + + updateRadius(); + + //since drawable transforms do not include scale, changing volume scale + //requires an immediate rebuild of volume verts. + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); + + if (mDrawable) + { + shrinkWrap(); + } + } +} + +LLFace* LLVOVolume::addFace(S32 f) +{ + const LLTextureEntry* te = getTE(f); + LLViewerTexture* imagep = getTEImage(f); + if (te->getMaterialParams().notNull()) + { + LLViewerTexture* normalp = getTENormalMap(f); + LLViewerTexture* specularp = getTESpecularMap(f); + return mDrawable->addFace(te, imagep, normalp, specularp); + } + return mDrawable->addFace(te, imagep); } LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) { - pipeline->allocDrawable(this); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); + pipeline->allocDrawable(this); + + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - S32 max_tes_to_set = getNumTEs(); - for (S32 i = 0; i < max_tes_to_set; i++) - { - addFace(i); - } - mNumFaces = max_tes_to_set; + S32 max_tes_to_set = getNumTEs(); + for (S32 i = 0; i < max_tes_to_set; i++) + { + addFace(i); + } + mNumFaces = max_tes_to_set; - if (isAttachment()) - { - mDrawable->makeActive(); - } + if (isAttachment()) + { + mDrawable->makeActive(); + } - if (getIsLight()) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } + if (getIsLight()) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } if (isReflectionProbe()) { updateReflectionProbePtr(); } - - updateRadius(); - bool force_update = true; // avoid non-alpha mDistance update being optimized away - mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); - return mDrawable; + updateRadius(); + bool force_update = true; // avoid non-alpha mDistance update being optimized away + mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update); + + return mDrawable; } BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - LLVolumeParams volume_params = params_in; - - S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; - S32 lod = mLOD; - - BOOL is404 = FALSE; - - if (isSculpted()) - { - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { //meshes might not have all LODs, get the force detail to best existing LOD - if (NO_LOD != lod) - { - lod = gMeshRepo.getActualMeshLOD(volume_params, lod); - if (lod == -1) - { - is404 = TRUE; - lod = 0; - } - } - } - } - - // Check if we need to change implementations - bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); - if (is_flexible) - { - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); - if (!mVolumeImpl) - { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - mVolumeImpl = new LLVolumeImplFlexible(this, data); - } - } - else - { - // Mark the parameter not in use - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); - if (mVolumeImpl) - { - delete mVolumeImpl; - mVolumeImpl = NULL; - if (mDrawable.notNull()) - { - // Undo the damage we did to this matrix - mDrawable->updateXform(FALSE); - } - } - } - - if (is404) - { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); - //render prim proxy when mesh loading attempts give up - volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); - - } - - if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) - { - mFaceMappingChanged = TRUE; - - if (mVolumeImpl) - { - mVolumeImpl->onSetVolume(volume_params, mLOD); - } - - updateSculptTexture(); - - if (isSculpted()) - { - updateSculptTexture(); - // if it's a mesh - if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - { - if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) - { - mSkinInfo = NULL; - mSkinInfoUnavaliable = false; - } - - if (!getVolume()->isMeshAssetLoaded()) - { - //load request not yet issued, request pipeline load this mesh - S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); - if (available_lod != lod) - { - LLPrimitive::setVolume(volume_params, available_lod); - } - } - - if (!mSkinInfo && !mSkinInfoUnavaliable) - { + LLVolumeParams volume_params = params_in; + + S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; + S32 lod = mLOD; + + BOOL is404 = FALSE; + + if (isSculpted()) + { + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + if (NO_LOD != lod) + { + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } + } + } + } + + // Check if we need to change implementations + bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); + if (is_flexible) + { + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false); + if (!mVolumeImpl) + { + LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + mVolumeImpl = new LLVolumeImplFlexible(this, data); + } + } + else + { + // Mark the parameter not in use + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false); + if (mVolumeImpl) + { + delete mVolumeImpl; + mVolumeImpl = NULL; + if (mDrawable.notNull()) + { + // Undo the damage we did to this matrix + mDrawable->updateXform(FALSE); + } + } + } + + if (is404) + { + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); + //render prim proxy when mesh loading attempts give up + volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); + + } + + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) + { + mFaceMappingChanged = TRUE; + + if (mVolumeImpl) + { + mVolumeImpl->onSetVolume(volume_params, mLOD); + } + + updateSculptTexture(); + + if (isSculpted()) + { + updateSculptTexture(); + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) + { + mSkinInfo = NULL; + mSkinInfoUnavaliable = false; + } + + if (!getVolume()->isMeshAssetLoaded()) + { + //load request not yet issued, request pipeline load this mesh + S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); + if (available_lod != lod) + { + LLPrimitive::setVolume(volume_params, available_lod); + } + } + + if (!mSkinInfo && !mSkinInfoUnavaliable) + { LLUUID mesh_id = volume_params.getSculptID(); if (gMeshRepo.hasHeader(mesh_id) && !gMeshRepo.hasSkinInfo(mesh_id)) { @@ -1122,60 +1122,60 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo notifySkinInfoLoaded(skin_info); } } - } - } - else // otherwise is sculptie - { - if (mSculptTexture.notNull()) - { - sculpt(); - } - } - } + } + } + else // otherwise is sculptie + { + if (mSculptTexture.notNull()) + { + sculpt(); + } + } + } return TRUE; - } - else if (NO_LOD == lod) - { - LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); - } + } + else if (NO_LOD == lod) + { + LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); + } - return FALSE; + return FALSE; } void LLVOVolume::updateSculptTexture() { - LLPointer old_sculpt = mSculptTexture; + LLPointer old_sculpt = mSculptTexture; - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) - { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - } + if (isSculpted() && !isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } mSkinInfoUnavaliable = false; - mSkinInfo = NULL; - } - else - { - mSculptTexture = NULL; - } - - if (mSculptTexture != old_sculpt) - { - if (old_sculpt.notNull()) - { - old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); - } - if (mSculptTexture.notNull()) - { - mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); - } - } - + mSkinInfo = NULL; + } + else + { + mSculptTexture = NULL; + } + + if (mSculptTexture != old_sculpt) + { + if (old_sculpt.notNull()) + { + old_sculpt->removeVolume(LLRender::SCULPT_TEX, this); + } + if (mSculptTexture.notNull()) + { + mSculptTexture->addVolume(LLRender::SCULPT_TEX, this); + } + } + } void LLVOVolume::updateVisualComplexity() @@ -1193,9 +1193,9 @@ void LLVOVolume::updateVisualComplexity() } void LLVOVolume::notifyMeshLoaded() -{ - mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); +{ + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); if (!mSkinInfo && !mSkinInfoUnavaliable) { @@ -1225,137 +1225,137 @@ void LLVOVolume::notifyMeshLoaded() void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) { mSkinInfoUnavaliable = false; - mSkinInfo = skin; + mSkinInfo = skin; - notifyMeshLoaded(); + notifyMeshLoaded(); } void LLVOVolume::notifySkinInfoUnavailable() { - mSkinInfoUnavaliable = true; - mSkinInfo = nullptr; + mSkinInfoUnavaliable = true; + mSkinInfo = nullptr; } // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() -{ - if (mSculptTexture.notNull()) - { - U16 sculpt_height = 0; - U16 sculpt_width = 0; - S8 sculpt_components = 0; - const U8* sculpt_data = NULL; - - S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; - LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; - - S32 max_discard = mSculptTexture->getMaxDiscardLevel(); - if (discard_level > max_discard) - { - discard_level = max_discard; // clamp to the best we can do - } - if(discard_level > MAX_DISCARD_LEVEL) - { - return; //we think data is not ready yet. - } - - S32 current_discard = getVolume()->getSculptLevel() ; - if(current_discard < -2) - { - static S32 low_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( low_sculpty_discard_warning_count < 10 || - (low_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is less than -2." - << " Hit this " << low_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - low_sculpty_discard_warning_count++; - - // corrupted volume... don't update the sculpty - return; - } - else if (current_discard > MAX_DISCARD_LEVEL) - { - static S32 high_sculpty_discard_warning_count = 1; - S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); - S32 interval = pow(10.0, exponent); - if ( high_sculpty_discard_warning_count < 10 || - (high_sculpty_discard_warning_count % interval) == 0) - { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs - LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() - << " at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL - << ". Hit this " << high_sculpty_discard_warning_count << " times" - << LL_ENDL; - } - high_sculpty_discard_warning_count++; - - // corrupted volume... don't update the sculpty - return; - } - - if (current_discard == discard_level) // no work to do here - return; - - if(!raw_image) - { - llassert(discard_level < 0) ; - - sculpt_width = 0; - sculpt_height = 0; - sculpt_data = NULL ; - - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); - } - } - else - { - sculpt_height = raw_image->getHeight(); - sculpt_width = raw_image->getWidth(); - sculpt_components = raw_image->getComponents(); - - sculpt_data = raw_image->getData(); - - if(LLViewerTextureManager::sTesterp) - { - mSculptTexture->updateBindStatsForTester() ; - } - } - getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); - - //notify rebuild any other VOVolumes that reference this sculpty volume - for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) - { - LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; - if (volume != this && volume->getVolume() == getVolume()) - { - gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY); - } - } - } -} - -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) -{ - S32 cur_detail; - if (LLPipeline::sDynamicLOD) - { - // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (lod_factor*radius)/distance; - cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); - } - else - { - cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); - } - return cur_detail; +{ + if (mSculptTexture.notNull()) + { + U16 sculpt_height = 0; + U16 sculpt_width = 0; + S8 sculpt_components = 0; + const U8* sculpt_data = NULL; + + S32 discard_level = mSculptTexture->getCachedRawImageLevel() ; + LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ; + + S32 max_discard = mSculptTexture->getMaxDiscardLevel(); + if (discard_level > max_discard) + { + discard_level = max_discard; // clamp to the best we can do + } + if(discard_level > MAX_DISCARD_LEVEL) + { + return; //we think data is not ready yet. + } + + S32 current_discard = getVolume()->getSculptLevel() ; + if(current_discard < -2) + { + static S32 low_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( low_sculpty_discard_warning_count < 10 || + (low_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is less than -2." + << " Hit this " << low_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + low_sculpty_discard_warning_count++; + + // corrupted volume... don't update the sculpty + return; + } + else if (current_discard > MAX_DISCARD_LEVEL) + { + static S32 high_sculpty_discard_warning_count = 1; + S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); + S32 interval = pow(10.0, exponent); + if ( high_sculpty_discard_warning_count < 10 || + (high_sculpty_discard_warning_count % interval) == 0) + { // Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs + LL_WARNS() << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is more than than allowed max of " << MAX_DISCARD_LEVEL + << ". Hit this " << high_sculpty_discard_warning_count << " times" + << LL_ENDL; + } + high_sculpty_discard_warning_count++; + + // corrupted volume... don't update the sculpty + return; + } + + if (current_discard == discard_level) // no work to do here + return; + + if(!raw_image) + { + llassert(discard_level < 0) ; + + sculpt_width = 0; + sculpt_height = 0; + sculpt_data = NULL ; + + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->updateGrayTextureBinding(); + } + } + else + { + sculpt_height = raw_image->getHeight(); + sculpt_width = raw_image->getWidth(); + sculpt_components = raw_image->getComponents(); + + sculpt_data = raw_image->getData(); + + if(LLViewerTextureManager::sTesterp) + { + mSculptTexture->updateBindStatsForTester() ; + } + } + getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset()); + + //notify rebuild any other VOVolumes that reference this sculpty volume + for (S32 i = 0; i < mSculptTexture->getNumVolumes(LLRender::SCULPT_TEX); ++i) + { + LLVOVolume* volume = (*(mSculptTexture->getVolumeList(LLRender::SCULPT_TEX)))[i]; + if (volume != this && volume->getVolume() == getVolume()) + { + gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY); + } + } + } +} + +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) +{ + S32 cur_detail; + if (LLPipeline::sDynamicLOD) + { + // We've got LOD in the profile, and in the twist. Use radius. + F32 tan_angle = (lod_factor*radius)/distance; + cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); + } + else + { + cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3); + } + return cur_detail; } std::string get_debug_object_lod_text(LLVOVolume *rootp) @@ -1400,28 +1400,28 @@ std::string get_debug_object_lod_text(LLVOVolume *rootp) BOOL LLVOVolume::calcLOD() { - if (mDrawable.isNull()) - { - return FALSE; - } + if (mDrawable.isNull()) + { + return FALSE; + } + + S32 cur_detail = 0; - S32 cur_detail = 0; - - F32 radius; - F32 distance; - F32 lod_factor = LLVOVolume::sLODFactor; + F32 radius; + F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; + + if (mDrawable->isState(LLDrawable::RIGGED)) + { + LLVOAvatar* avatar = getAvatar(); - if (mDrawable->isState(LLDrawable::RIGGED)) - { - LLVOAvatar* avatar = getAvatar(); - - // Not sure how this can really happen, but alas it does. Better exit here than crashing. - if( !avatar || !avatar->mDrawable ) - { - return FALSE; - } + // Not sure how this can really happen, but alas it does. Better exit here than crashing. + if( !avatar || !avatar->mDrawable ) + { + return FALSE; + } - distance = avatar->mDrawable->mDistanceWRTCamera; + distance = avatar->mDrawable->mDistanceWRTCamera; if (avatar->isControlAvatar()) @@ -1448,20 +1448,20 @@ BOOL LLVOVolume::calcLOD() LL_DEBUGS("DynamicBox","CalcLOD") << "avatar distance/radius uninitialized, skipping" << LL_ENDL; return FALSE; } - } - else - { - distance = mDrawable->mDistanceWRTCamera; - radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + } + else + { + distance = mDrawable->mDistanceWRTCamera; + radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); if (distance <= 0.f || radius <= 0.f) { LL_DEBUGS("DynamicBox","CalcLOD") << "non-avatar distance/radius uninitialized, skipping" << LL_ENDL; return FALSE; } - } - - //hold onto unmodified distance for debugging - //F32 debug_distance = distance; + } + + //hold onto unmodified distance for debugging + //F32 debug_distance = distance; mLODDistance = distance; mLODRadius = radius; @@ -1487,24 +1487,24 @@ BOOL LLVOVolume::calcLOD() distance *= sDistanceFactor; - F32 rampDist = LLVOVolume::sLODFactor * 2; - - if (distance < rampDist) - { - // Boost LOD when you're REALLY close - distance *= 1.0f/rampDist; - distance *= distance; - distance *= rampDist; - } - - - distance *= F_PI/3.f; - - static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); - if(!ignore_fov_zoom) - { - lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); - } + F32 rampDist = LLVOVolume::sLODFactor * 2; + + if (distance < rampDist) + { + // Boost LOD when you're REALLY close + distance *= 1.0f/rampDist; + distance *= distance; + distance *= rampDist; + } + + + distance *= F_PI/3.f; + + static LLCachedControl ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); + if(!ignore_fov_zoom) + { + lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); + } mLODAdjustedDistance = distance; @@ -1527,189 +1527,189 @@ BOOL LLVOVolume::calcLOD() setDebugText(llformat("TRIS SHOWN %d EST %d", total_tris, est_max_tris)); } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && - mDrawable->getFace(0)) - { + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && + mDrawable->getFace(0)) + { // This is a debug display for LODs. Please don't put the texture index here. setDebugText(llformat("%d", cur_detail)); - } + } - if (cur_detail != mLOD) - { - LL_DEBUGS("DynamicBox","CalcLOD") << "new LOD " << cur_detail << " change from " << mLOD + if (cur_detail != mLOD) + { + LL_DEBUGS("DynamicBox","CalcLOD") << "new LOD " << cur_detail << " change from " << mLOD << " distance " << distance << " radius " << radius << " rampDist " << rampDist << " drawable rigged? " << (mDrawable ? (S32) mDrawable->isState(LLDrawable::RIGGED) : (S32) -1) - << " mRiggedVolume " << (void*)getRiggedVolume() + << " mRiggedVolume " << (void*)getRiggedVolume() << " distanceWRTCamera " << (mDrawable ? mDrawable->mDistanceWRTCamera : -1.f) << LL_ENDL; - - mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - mLOD = cur_detail; + + mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); + mLOD = cur_detail; return TRUE; - } + } - return FALSE; + return FALSE; } BOOL LLVOVolume::updateLOD() { - if (mDrawable.isNull()) - { - return FALSE; - } + if (mDrawable.isNull()) + { + return FALSE; + } LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - BOOL lod_changed = FALSE; - - if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) - { - lod_changed = calcLOD(); - } - else - { - return FALSE; - } - - if (lod_changed) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - mLODChanged = TRUE; - } - else - { - F32 new_radius = getBinRadius(); - F32 old_radius = mDrawable->getBinRadius(); - if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) - { - gPipeline.markPartitionMove(mDrawable); - } - } - - lod_changed = lod_changed || LLViewerObject::updateLOD(); - - return lod_changed; -} - -BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) -{ - if (!LLViewerObject::setDrawableParent(parentp)) - { - // no change in drawable parent - return FALSE; - } - - if (!mDrawable->isRoot()) - { - // rebuild vertices in parent relative space - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - - if (mDrawable->isActive() && !parentp->isActive()) - { - parentp->makeActive(); - } - else if (mDrawable->isStatic() && parentp->isActive()) - { - mDrawable->makeActive(); - } - } - - return TRUE; -} - -void LLVOVolume::updateFaceFlags() -{ - // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() - for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) - { - LLFace *face = mDrawable->getFace(i); - if (face) - { - BOOL fullbright = getTE(i)->getFullbright(); - face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); - - if (fullbright || (mMaterial == LL_MCODE_LIGHT)) - { - face->setState(LLFace::FULLBRIGHT); - } - if (mDrawable->isLight()) - { - face->setState(LLFace::LIGHT); - } - if (isHUDAttachment()) - { - face->setState(LLFace::HUD_RENDER); - } - } - } -} + BOOL lod_changed = FALSE; + + if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID())) + { + lod_changed = calcLOD(); + } + else + { + return FALSE; + } + + if (lod_changed) + { + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + mLODChanged = TRUE; + } + else + { + F32 new_radius = getBinRadius(); + F32 old_radius = mDrawable->getBinRadius(); + if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f) + { + gPipeline.markPartitionMove(mDrawable); + } + } + + lod_changed = lod_changed || LLViewerObject::updateLOD(); + + return lod_changed; +} + +BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) +{ + if (!LLViewerObject::setDrawableParent(parentp)) + { + // no change in drawable parent + return FALSE; + } + + if (!mDrawable->isRoot()) + { + // rebuild vertices in parent relative space + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + + if (mDrawable->isActive() && !parentp->isActive()) + { + parentp->makeActive(); + } + else if (mDrawable->isStatic() && parentp->isActive()) + { + mDrawable->makeActive(); + } + } + + return TRUE; +} + +void LLVOVolume::updateFaceFlags() +{ + // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces() + for (S32 i = 0; i < getVolume()->getNumFaces() && i < mDrawable->getNumFaces(); i++) + { + LLFace *face = mDrawable->getFace(i); + if (face) + { + BOOL fullbright = getTE(i)->getFullbright(); + face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); + + if (fullbright || (mMaterial == LL_MCODE_LIGHT)) + { + face->setState(LLFace::FULLBRIGHT); + } + if (mDrawable->isLight()) + { + face->setState(LLFace::LIGHT); + } + if (isHUDAttachment()) + { + face->setState(LLFace::HUD_RENDER); + } + } + } +} BOOL LLVOVolume::setParent(LLViewerObject* parent) { - BOOL ret = FALSE ; + BOOL ret = FALSE ; LLViewerObject *old_parent = (LLViewerObject*) getParent(); - if (parent != old_parent) - { - ret = LLViewerObject::setParent(parent); - if (ret && mDrawable) - { - gPipeline.markMoved(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - } + if (parent != old_parent) + { + ret = LLViewerObject::setParent(parent); + if (ret && mDrawable) + { + gPipeline.markMoved(mDrawable); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + } onReparent(old_parent, parent); - } + } - return ret ; + return ret ; } // NOTE: regenFaces() MUST be followed by genTriangles()! void LLVOVolume::regenFaces() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - // remove existing faces - BOOL count_changed = mNumFaces != getNumTEs(); - - if (count_changed) - { - deleteFaces(); - // add new faces - mNumFaces = getNumTEs(); - } - - for (S32 i = 0; i < mNumFaces; i++) - { - LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); - if (!facep) continue; - - facep->setTEOffset(i); - facep->setTexture(getTEImage(i)); - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { - facep->setNormalMap(getTENormalMap(i)); - facep->setSpecularMap(getTESpecularMap(i)); - } - facep->setViewerObject(this); - - // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. - // Re-establish the link. - if((int)mMediaImplList.size() > i) - { - if(mMediaImplList[i]) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - } - } - - if (!count_changed) - { - updateFaceFlags(); - } + // remove existing faces + BOOL count_changed = mNumFaces != getNumTEs(); + + if (count_changed) + { + deleteFaces(); + // add new faces + mNumFaces = getNumTEs(); + } + + for (S32 i = 0; i < mNumFaces; i++) + { + LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); + if (!facep) continue; + + facep->setTEOffset(i); + facep->setTexture(getTEImage(i)); + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { + facep->setNormalMap(getTENormalMap(i)); + facep->setSpecularMap(getTESpecularMap(i)); + } + facep->setViewerObject(this); + + // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face. + // Re-establish the link. + if((int)mMediaImplList.size() > i) + { + if(mMediaImplList[i]) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + } + } + + if (!count_changed) + { + updateFaceFlags(); + } } BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds) @@ -1827,7 +1827,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds) mDrawable->setPositionGroup(min); } } - + updateRadius(); mDrawable->movePartition(); } @@ -1841,581 +1841,581 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global, BOOL should_update_octree_bounds) void LLVOVolume::preRebuild() { - if (mVolumeImpl != NULL) - { - mVolumeImpl->preRebuild(); - } + if (mVolumeImpl != NULL) + { + mVolumeImpl->preRebuild(); + } } void LLVOVolume::updateRelativeXform(bool force_identity) { - if (mVolumeImpl) - { - mVolumeImpl->updateRelativeXform(force_identity); - return; - } - - LLDrawable* drawable = mDrawable; - - if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) - { //rigged volume (which is in agent space) is used for generating bounding boxes etc - //inverse of render matrix should go to partition space - mRelativeXform = getRenderMatrix(); - - F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; - F32* src = (F32*) mRelativeXform.mMatrix; - dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; - dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; - dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; - - mRelativeXform.invert(); - mRelativeXformInvTrans.transpose(); - } - else if (drawable->isActive() || force_identity) - { - // setup relative transforms - LLQuaternion delta_rot; - LLVector3 delta_pos, delta_scale; - - //matrix from local space to parent relative/global space - bool use_identity = force_identity || drawable->isSpatialRoot(); - delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); - delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); - delta_scale = mDrawable->getScale(); - - // Vertex transform (4x4) - LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; - LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(delta_pos, 1.f)); - - - // compute inverse transpose for normals - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // mRelativeXformInvTrans.invert(); - // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - // grumble - invert is NOT a matrix invert, so we do it by hand: - - LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } - else - { - LLVector3 pos = getPosition(); - LLVector3 scale = getScale(); - LLQuaternion rot = getRotation(); - - if (mParent) - { - pos *= mParent->getRotation(); - pos += mParent->getPosition(); - rot *= mParent->getRotation(); - } - - //LLViewerRegion* region = getRegion(); - //pos += region->getOriginAgent(); - - LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; - LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; - LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; - - mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(pos, 1.f)); - - // compute inverse transpose for normals - LLMatrix3 rot_inverse = LLMatrix3(~rot); - - LLMatrix3 scale_inverse; - scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], - LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], - LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); - - - mRelativeXformInvTrans = rot_inverse * scale_inverse; - - mRelativeXformInvTrans.transpose(); - } + if (mVolumeImpl) + { + mVolumeImpl->updateRelativeXform(force_identity); + return; + } + + LLDrawable* drawable = mDrawable; + + if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) + { //rigged volume (which is in agent space) is used for generating bounding boxes etc + //inverse of render matrix should go to partition space + mRelativeXform = getRenderMatrix(); + + F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; + F32* src = (F32*) mRelativeXform.mMatrix; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; + dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; + + mRelativeXform.invert(); + mRelativeXformInvTrans.transpose(); + } + else if (drawable->isActive() || force_identity) + { + // setup relative transforms + LLQuaternion delta_rot; + LLVector3 delta_pos, delta_scale; + + //matrix from local space to parent relative/global space + bool use_identity = force_identity || drawable->isSpatialRoot(); + delta_rot = use_identity ? LLQuaternion() : mDrawable->getRotation(); + delta_pos = use_identity ? LLVector3(0,0,0) : mDrawable->getPosition(); + delta_scale = mDrawable->getScale(); + + // Vertex transform (4x4) + LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; + LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(delta_pos, 1.f)); + + + // compute inverse transpose for normals + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // mRelativeXformInvTrans.invert(); + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // grumble - invert is NOT a matrix invert, so we do it by hand: + + LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } + else + { + LLVector3 pos = getPosition(); + LLVector3 scale = getScale(); + LLQuaternion rot = getRotation(); + + if (mParent) + { + pos *= mParent->getRotation(); + pos += mParent->getPosition(); + rot *= mParent->getRotation(); + } + + //LLViewerRegion* region = getRegion(); + //pos += region->getOriginAgent(); + + LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot; + LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot; + LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot; + + mRelativeXform.initRows(LLVector4(x_axis, 0.f), + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(pos, 1.f)); + + // compute inverse transpose for normals + LLMatrix3 rot_inverse = LLMatrix3(~rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); + } } bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &should_update_octree_bounds) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - bool regen_faces = false; + bool regen_faces = false; - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces; + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces; - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces(); - old_volumep = NULL; + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces(); + old_volumep = NULL; - { - const LLVolumeParams &volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } + { + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces(); - new_volumep = NULL; + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces(); + new_volumep = NULL; - if ((new_lod != old_lod) || mSculptChanged) - { + if ((new_lod != old_lod) || mSculptChanged) + { if (mDrawable->isState(LLDrawable::RIGGED)) { updateVisualComplexity(); } - compiled = TRUE; + compiled = TRUE; // new_lod > old_lod breaks a feedback loop between LOD updates and // bounding box updates. should_update_octree_bounds = should_update_octree_bounds || mSculptChanged || new_lod > old_lod; - sNumLODChanges += new_num_faces; - - if ((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } - - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - - { - regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); - if (regen_faces) - { - regenFaces(); - } - - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } - - return regen_faces; + sNumLODChanges += new_num_faces; + + if ((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + + return regen_faces; } BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - - if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) - { + + if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) + { updateRiggedVolume(false); - genBBoxes(FALSE); - mDrawable->clearState(LLDrawable::REBUILD_RIGGED); - } - - if (mVolumeImpl != NULL) - { - BOOL res; - { - res = mVolumeImpl->doUpdateGeometry(drawable); - } - updateFaceFlags(); - return res; - } - - LLSpatialGroup* group = drawable->getSpatialGroup(); - if (group) - { + genBBoxes(FALSE); + mDrawable->clearState(LLDrawable::REBUILD_RIGGED); + } + + if (mVolumeImpl != NULL) + { + BOOL res; + { + res = mVolumeImpl->doUpdateGeometry(drawable); + } + updateFaceFlags(); + return res; + } + + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { group->dirtyMesh(); - } + } + + updateRelativeXform(); - updateRelativeXform(); - - if (mDrawable.isNull()) // Not sure why this is happening, but it is... - { - return TRUE; // No update to complete - } + if (mDrawable.isNull()) // Not sure why this is happening, but it is... + { + return TRUE; // No update to complete + } - BOOL compiled = FALSE; + BOOL compiled = FALSE; // This should be true in most cases, unless we're sure no octree update is // needed. BOOL should_update_octree_bounds = bool(getRiggedVolume()) || mDrawable->isState(LLDrawable::REBUILD_POSITION) || !mDrawable->getSpatialExtents()->isFinite3(); - if (mVolumeChanged || mFaceMappingChanged) - { - dirtySpatialGroup(); + if (mVolumeChanged || mFaceMappingChanged) + { + dirtySpatialGroup(); - bool was_regen_faces = false; + bool was_regen_faces = false; should_update_octree_bounds = true; - if (mVolumeChanged) - { + if (mVolumeChanged) + { was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); - drawable->setState(LLDrawable::REBUILD_VOLUME); - } - else if (mSculptChanged || mLODChanged || mColorChanged) - { - compiled = TRUE; + drawable->setState(LLDrawable::REBUILD_VOLUME); + } + else if (mSculptChanged || mLODChanged || mColorChanged) + { + compiled = TRUE; was_regen_faces = lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); - } - - if (!was_regen_faces) { - regenFaces(); - } - } - else if (mLODChanged || mSculptChanged || mColorChanged) - { - dirtySpatialGroup(); - compiled = TRUE; + } + + if (!was_regen_faces) { + regenFaces(); + } + } + else if (mLODChanged || mSculptChanged || mColorChanged) + { + dirtySpatialGroup(); + compiled = TRUE; lodOrSculptChanged(drawable, compiled, should_update_octree_bounds); - - if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) - { - updateRiggedVolume(false); - } - } - // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local - else - { - compiled = TRUE; - // All it did was move or we changed the texture coordinate offset - } + + if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED)) + { + updateRiggedVolume(false); + } + } + // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local + else + { + compiled = TRUE; + // All it did was move or we changed the texture coordinate offset + } // Generate bounding boxes if needed, and update the object's size in the // octree genBBoxes(FALSE, should_update_octree_bounds); - // Update face flags - updateFaceFlags(); - - if(compiled) - { - LLPipeline::sCompiles++; - } - - mVolumeChanged = FALSE; - mLODChanged = FALSE; - mSculptChanged = FALSE; - mFaceMappingChanged = FALSE; + // Update face flags + updateFaceFlags(); + + if(compiled) + { + LLPipeline::sCompiles++; + } + + mVolumeChanged = FALSE; + mLODChanged = FALSE; + mSculptChanged = FALSE; + mFaceMappingChanged = FALSE; mColorChanged = FALSE; - - return LLViewerObject::updateGeometry(drawable); + + return LLViewerObject::updateGeometry(drawable); } void LLVOVolume::updateFaceSize(S32 idx) { - if( mDrawable->getNumFaces() <= idx ) - { - return; - } - - LLFace* facep = mDrawable->getFace(idx); - if (facep) - { - if (idx >= getVolume()->getNumVolumeFaces()) - { - facep->setSize(0,0, true); - } - else - { - const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, - true); // <--- volume faces should be padded for 16-byte alignment - - } - } + if( mDrawable->getNumFaces() <= idx ) + { + return; + } + + LLFace* facep = mDrawable->getFace(idx); + if (facep) + { + if (idx >= getVolume()->getNumVolumeFaces()) + { + facep->setSize(0,0, true); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + + } + } } BOOL LLVOVolume::isRootEdit() const { - if (mParent && !((LLViewerObject*)mParent)->isAvatar()) - { - return FALSE; - } - return TRUE; + if (mParent && !((LLViewerObject*)mParent)->isAvatar()) + { + return FALSE; + } + return TRUE; } //virtual void LLVOVolume::setNumTEs(const U8 num_tes) { - const U8 old_num_tes = getNumTEs() ; - - if(old_num_tes && old_num_tes < num_tes) //new faces added - { - LLViewerObject::setNumTEs(num_tes) ; - - if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. - { - mMediaImplList.resize(num_tes) ; - const LLTextureEntry* te = getTE(old_num_tes - 1) ; - for(U8 i = old_num_tes; i < num_tes ; i++) - { - setTE(i, *te) ; - mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; - } - mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; - } - } - else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed - { - U8 end = (U8)(mMediaImplList.size()) ; - for(U8 i = num_tes; i < end ; i++) - { - removeMediaImpl(i) ; - } - mMediaImplList.resize(num_tes) ; - - LLViewerObject::setNumTEs(num_tes) ; - } - else - { - LLViewerObject::setNumTEs(num_tes) ; - } - - return ; + const U8 old_num_tes = getNumTEs() ; + + if(old_num_tes && old_num_tes < num_tes) //new faces added + { + LLViewerObject::setNumTEs(num_tes) ; + + if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. + { + mMediaImplList.resize(num_tes) ; + const LLTextureEntry* te = getTE(old_num_tes - 1) ; + for(U8 i = old_num_tes; i < num_tes ; i++) + { + setTE(i, *te) ; + mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; + } + mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; + } + } + else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed + { + U8 end = (U8)(mMediaImplList.size()) ; + for(U8 i = num_tes; i < end ; i++) + { + removeMediaImpl(i) ; + } + mMediaImplList.resize(num_tes) ; + + LLViewerObject::setNumTEs(num_tes) ; + } + else + { + LLViewerObject::setNumTEs(num_tes) ; + } + + return ; } //virtual void LLVOVolume::changeTEImage(S32 index, LLViewerTexture* imagep) { - BOOL changed = (mTEImages[index] != imagep); - LLViewerObject::changeTEImage(index, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } + BOOL changed = (mTEImages[index] != imagep); + LLViewerObject::changeTEImage(index, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } } void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) { - BOOL changed = (mTEImages[te] != imagep); - LLViewerObject::setTEImage(te, imagep); - if (changed) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } + BOOL changed = (mTEImages[te] != imagep); + LLViewerObject::setTEImage(te, imagep); + if (changed) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } } S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) { - S32 res = LLViewerObject::setTETexture(te, uuid); - if (res) - { + S32 res = LLViewerObject::setTETexture(te, uuid); + if (res) + { if (mDrawable) { // dynamic texture changes break batches, isolate in octree shrinkWrap(); gPipeline.markTextured(mDrawable); } - mFaceMappingChanged = TRUE; - } - return res; + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color) { - return setTEColor(te, LLColor4(color)); + return setTEColor(te, LLColor4(color)); } S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) { - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; - } - else if (color != tep->getColor()) - { - F32 old_alpha = tep->getColor().mV[3]; - if (color.mV[3] != old_alpha) - { - gPipeline.markTextured(mDrawable); - //treat this alpha change as an LoD update since render batches may need to get rebuilt - mLODChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); - } - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + } + else if (color != tep->getColor()) + { + F32 old_alpha = tep->getColor().mV[3]; + if (color.mV[3] != old_alpha) + { + gPipeline.markTextured(mDrawable); + //treat this alpha change as an LoD update since render batches may need to get rebuilt + mLODChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME); + } + retval = LLPrimitive::setTEColor(te, color); + if (mDrawable.notNull() && retval) + { + // These should only happen on updates which are not the initial update. mColorChanged = TRUE; - mDrawable->setState(LLDrawable::REBUILD_COLOR); + mDrawable->setState(LLDrawable::REBUILD_COLOR); shrinkWrap(); - dirtyMesh(); - } - } + dirtyMesh(); + } + } - return retval; + return retval; } S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) { - S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) { - S32 res = LLViewerObject::setTETexGen(te, texgen); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTETexGen(te, texgen); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media) { - S32 res = LLViewerObject::setTEMediaTexGen(te, media); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEMediaTexGen(te, media); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) { - S32 res = LLViewerObject::setTEShiny(te, shiny); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEShiny(te, shiny); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) { - S32 res = LLViewerObject::setTEFullbright(te, fullbright); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEFullbright(te, fullbright); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump) { - S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) { - S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow) { - S32 res = LLViewerObject::setTEGlow(te, glow); - if (res) - { + S32 res = LLViewerObject::setTEGlow(te, glow); + if (res) + { if (mDrawable) { gPipeline.markTextured(mDrawable); shrinkWrap(); } - mFaceMappingChanged = TRUE; - } - return res; + mFaceMappingChanged = TRUE; + } + return res; } void LLVOVolume::setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID &pMaterialID, const LLMaterialPtr pMaterialParams, U32 te) { - LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); - if (pVol) - { - LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; - if (te >= pVol->getNumTEs()) - return; + LLVOVolume* pVol = (LLVOVolume*)gObjectList.findObject(objectID); + if (pVol) + { + LL_DEBUGS("MaterialTEs") << "materialid " << pMaterialID.asString() << " to TE " << te << LL_ENDL; + if (te >= pVol->getNumTEs()) + return; - LLTextureEntry* texture_entry = pVol->getTE(te); - if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) - { - pVol->setTEMaterialParams(te, pMaterialParams); - } - } + LLTextureEntry* texture_entry = pVol->getTE(te); + if (texture_entry && (texture_entry->getMaterialID() == pMaterialID)) + { + pVol->setTEMaterialParams(te, pMaterialParams); + } + } } S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) { - S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); - LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - - LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; - if (res) - { - LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); - - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEMaterialID(te, pMaterialID); + LL_DEBUGS("MaterialTEs") << "te "<< (S32)te << " materialid " << pMaterialID.asString() << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + + LL_DEBUGS("MaterialTEs") << " " << pMaterialID.asString() << LL_ENDL; + if (res) + { + LLMaterialMgr::instance().getTE(getRegion()->getRegionID(), pMaterialID, te, boost::bind(&LLVOVolume::setTEMaterialParamsCallbackTE, getID(), _1, _2, _3)); + + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); - LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res - << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) - << LL_ENDL; - setChanged(ALL_CHANGED); - if (!mDrawable.isNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); - } - mFaceMappingChanged = TRUE; - return TEM_CHANGE_TEXTURE; + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res + << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) + << LL_ENDL; + setChanged(ALL_CHANGED); + if (!mDrawable.isNull()) + { + gPipeline.markTextured(mDrawable); + gPipeline.markRebuild(mDrawable,LLDrawable::REBUILD_ALL); + } + mFaceMappingChanged = TRUE; + return TEM_CHANGE_TEXTURE; } S32 LLVOVolume::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat) @@ -2438,230 +2438,230 @@ S32 LLVOVolume::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat) S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) { - S32 res = LLViewerObject::setTEScale(te, s, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScale(te, s, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) { - S32 res = LLViewerObject::setTEScaleS(te, s); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScaleS(te, s); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) { - S32 res = LLViewerObject::setTEScaleT(te, t); - if (res) - { - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - return res; + S32 res = LLViewerObject::setTEScaleT(te, t); + if (res) + { + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + return res; } bool LLVOVolume::hasMedia() const { - bool result = false; - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if(te->hasMedia()) - { - result = true; - break; - } - } - return result; + bool result = false; + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if(te->hasMedia()) + { + result = true; + break; + } + } + return result; } LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) { - LLVolume* volume = getVolume(); - LLVector4a result; - result.clear(); + LLVolume* volume = getVolume(); + LLVector4a result; + result.clear(); + + LLVector3 ret; - LLVector3 ret; + if (volume && face_id < volume->getNumVolumeFaces()) + { + const LLVolumeFace& face = volume->getVolumeFace(face_id); + for (S32 i = 0; i < (S32)face.mNumVertices; ++i) + { + result.add(face.mNormals[i]); + } - if (volume && face_id < volume->getNumVolumeFaces()) - { - const LLVolumeFace& face = volume->getVolumeFace(face_id); - for (S32 i = 0; i < (S32)face.mNumVertices; ++i) - { - result.add(face.mNormals[i]); - } + LLVector3 ret(result.getF32ptr()); + ret = volumeDirectionToAgent(ret); + ret.normVec(); + } - LLVector3 ret(result.getF32ptr()); - ret = volumeDirectionToAgent(ret); - ret.normVec(); - } - - return ret; + return ret; } void LLVOVolume::requestMediaDataUpdate(bool isNew) { if (sObjectMediaClient) - sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); + sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew)); } bool LLVOVolume::isMediaDataBeingFetched() const { - // I know what I'm doing by const_casting this away: this is just - // a wrapper class that is only going to do a lookup. - return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; + // I know what I'm doing by const_casting this away: this is just + // a wrapper class that is only going to do a lookup. + return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast(this), false)) : false; } void LLVOVolume::cleanUpMediaImpls() { - // Iterate through our TEs and remove any Impls that are no longer used - const U8 numTEs = getNumTEs(); - for (U8 i = 0; i < numTEs; i++) - { - const LLTextureEntry* te = getTE(i); - if( ! te->hasMedia()) - { - // Delete the media IMPL! - removeMediaImpl(i) ; - } - } + // Iterate through our TEs and remove any Impls that are no longer used + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if( ! te->hasMedia()) + { + // Delete the media IMPL! + removeMediaImpl(i) ; + } + } } void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version) { - // media_data_array is an array of media entry maps - // media_version is the version string in the response. - U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); - - // Only update it if it is newer! - if ( (S32)fetched_version > mLastFetchedMediaVersion) - { - mLastFetchedMediaVersion = fetched_version; - //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; - - LLSD::array_const_iterator iter = media_data_array.beginArray(); - LLSD::array_const_iterator end = media_data_array.endArray(); - U8 texture_index = 0; - for (; iter != end; ++iter, ++texture_index) - { - syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); - } - } + // media_data_array is an array of media entry maps + // media_version is the version string in the response. + U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version); + + // Only update it if it is newer! + if ( (S32)fetched_version > mLastFetchedMediaVersion) + { + mLastFetchedMediaVersion = fetched_version; + //LL_INFOS() << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << LL_ENDL; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } + } } void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) { - if(mDead) - { - // If the object has been marked dead, don't process media updates. - return; - } - - LLTextureEntry *te = getTE(texture_index); - if(!te) - { - return ; - } - - LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; - - std::string previous_url; - LLMediaEntry* mep = te->getMediaData(); - if(mep) - { - // Save the "current url" from before the update so we can tell if - // it changes. - previous_url = mep->getCurrentURL(); - } - - if (merge) - { - te->mergeIntoMediaData(media_data); - } - else { - // XXX Question: what if the media data is undefined LLSD, but the - // update we got above said that we have media flags?? Here we clobber - // that, assuming the data from the service is more up-to-date. - te->updateMediaData(media_data); - } - - mep = te->getMediaData(); - if(mep) - { - bool update_from_self = false; - if (!ignore_agent) - { - LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); - update_from_self = (updating_agent == gAgent.getID()); - } - viewer_media_t media_impl = LLViewerMedia::getInstance()->updateMediaImpl(mep, previous_url, update_from_self); - - addMediaImpl(media_impl, texture_index) ; - } - else - { - removeMediaImpl(texture_index); - } - - LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index - << " hasMedia = " << te->hasMedia() << " : " - << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + if(mDead) + { + // If the object has been marked dead, don't process media updates. + return; + } + + LLTextureEntry *te = getTE(texture_index); + if(!te) + { + return ; + } + + LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; + + std::string previous_url; + LLMediaEntry* mep = te->getMediaData(); + if(mep) + { + // Save the "current url" from before the update so we can tell if + // it changes. + previous_url = mep->getCurrentURL(); + } + + if (merge) + { + te->mergeIntoMediaData(media_data); + } + else { + // XXX Question: what if the media data is undefined LLSD, but the + // update we got above said that we have media flags?? Here we clobber + // that, assuming the data from the service is more up-to-date. + te->updateMediaData(media_data); + } + + mep = te->getMediaData(); + if(mep) + { + bool update_from_self = false; + if (!ignore_agent) + { + LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); + update_from_self = (updating_agent == gAgent.getID()); + } + viewer_media_t media_impl = LLViewerMedia::getInstance()->updateMediaImpl(mep, previous_url, update_from_self); + + addMediaImpl(media_impl, texture_index) ; + } + else + { + removeMediaImpl(texture_index); + } + + LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index + << " hasMedia = " << te->hasMedia() << " : " + << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << LL_ENDL; } void LLVOVolume::mediaNavigateBounceBack(U8 texture_index) { - // Find the media entry for this navigate - const LLMediaEntry* mep = NULL; - viewer_media_t impl = getMediaImpl(texture_index); - LLTextureEntry *te = getTE(texture_index); - if(te) - { - mep = te->getMediaData(); - } - - if (mep && impl) - { + // Find the media entry for this navigate + const LLMediaEntry* mep = NULL; + viewer_media_t impl = getMediaImpl(texture_index); + LLTextureEntry *te = getTE(texture_index); + if(te) + { + mep = te->getMediaData(); + } + + if (mep && impl) + { std::string url = mep->getCurrentURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } - // If the url we're trying to "bounce back" to is either empty or not - // allowed by the whitelist, try the home url. If *that* doesn't work, - // set the media as failed and unload it + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } + // If the url we're trying to "bounce back" to is either empty or not + // allowed by the whitelist, try the home url. If *that* doesn't work, + // set the media as failed and unload it if (url.empty() || !mep->checkCandidateUrl(url)) { url = mep->getHomeURL(); - // Look for a ":", if not there, assume "http://" - if (!url.empty() && std::string::npos == url.find(':')) - { - url = "http://" + url; - } + // Look for a ":", if not there, assume "http://" + if (!url.empty() && std::string::npos == url.find(':')) + { + url = "http://" + url; + } } if (url.empty() || !mep->checkCandidateUrl(url)) - { - // The url to navigate back to is not good, and we have nowhere else - // to go. - LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; - impl->setMediaFailed(true); - } - // Make sure we are not bouncing to url we came from - else if (impl->getCurrentMediaURL() != url) - { - // Okay, navigate now + { + // The url to navigate back to is not good, and we have nowhere else + // to go. + LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL; + impl->setMediaFailed(true); + } + // Make sure we are not bouncing to url we came from + else if (impl->getCurrentMediaURL() != url) + { + // Okay, navigate now LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL; impl->navigateTo(url, "", false, true); } @@ -2672,153 +2672,153 @@ bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermTy { // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp). if (NULL == media_entry ) return false; // XXX should we assert here? - + // The agent has permissions if: // - world permissions are on, or // - group permissions are on, and agent_id is in the group, or // - agent permissions are on, and agent_id is the owner - - // *NOTE: We *used* to check for modify permissions here (i.e. permissions were - // granted if permModify() was true). However, this doesn't make sense in the - // viewer: we don't want to show controls or allow interaction if the author - // has deemed it so. See DEV-42115. - + + // *NOTE: We *used* to check for modify permissions here (i.e. permissions were + // granted if permModify() was true). However, this doesn't make sense in the + // viewer: we don't want to show controls or allow interaction if the author + // has deemed it so. See DEV-42115. + U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl(); - + // World permissions - if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) + if (0 != (media_perms & LLMediaEntry::PERM_ANYONE)) { return true; } - + // Group permissions else if (0 != (media_perms & LLMediaEntry::PERM_GROUP)) { - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) - { - return true; - } + LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); + if (obj_perm && gAgent.isInGroup(obj_perm->getGroup())) + { + return true; + } } - + // Owner permissions - else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) + else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner()) { return true; } - + return false; - + } void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location) { - bool block_navigation = false; - // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed - // to deal with multiple face indices. - int face_index = getFaceIndexWithMediaImpl(impl, -1); - - // Find the media entry for this navigate - LLMediaEntry* mep = NULL; - LLTextureEntry *te = getTE(face_index); - if(te) - { - mep = te->getMediaData(); - } - - if(mep) - { - if(!mep->checkCandidateUrl(new_location)) - { - block_navigation = true; - } - if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) - { - block_navigation = true; - } - } - else - { - LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; - } - - if(block_navigation) - { - LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; - - // "bounce back" to the current URL from the media entry - mediaNavigateBounceBack(face_index); - } - else if (sObjectMediaNavigateClient) - { - - LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; - - sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); - } + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT)) + { + block_navigation = true; + } + } + else + { + LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL; + } + + if(block_navigation) + { + LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL; + + // "bounce back" to the current URL from the media entry + mediaNavigateBounceBack(face_index); + } + else if (sObjectMediaNavigateClient) + { + + LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL; + + sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location); + } } void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) { - switch(event) - { - - case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getLocation()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: - // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // This is a subsequent location-changed due to a redirect. Don't broadcast. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; - break; - } - } - break; - - case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: - { - switch(impl->getNavState()) - { - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: - { - // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. - mediaNavigated(impl, plugin, plugin->getNavigateURI()); - } - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: - // This navigate didn't change the current URL. - LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; - break; - - case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: - // This is the the navigate complete event from a server-directed nav. Don't broadcast it. - LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; - break; - - default: - // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. - break; - } - } - break; + switch(event) + { + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getLocation()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: + // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // This is a subsequent location-changed due to a redirect. Don't broadcast. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL; + break; + } + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back. + mediaNavigated(impl, plugin, plugin->getNavigateURI()); + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS: + // This navigate didn't change the current URL. + LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL; + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED: + // This is the the navigate complete event from a server-directed nav. Don't broadcast it. + LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL; + break; + + default: + // For all other states, the navigate should have been handled by LOCATION_CHANGED events already. + break; + } + } + break; case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: { @@ -2830,233 +2830,233 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLNotificationsUtil::add("MediaFileDownloadUnsupported"); } break; - - default: - break; - } + + default: + break; + } } void LLVOVolume::sendMediaDataUpdate() { if (sObjectMediaClient) - sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); + sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false)); } void LLVOVolume::removeMediaImpl(S32 texture_index) { - if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) - { - return ; - } - - //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. - if(mDrawable && texture_index < mDrawable->getNumFaces()) - { - LLFace* facep = mDrawable->getFace(texture_index) ; - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->removeMediaFromFace(facep) ; - } - } - } - - //check if some other face(s) of this object reference(s)to this media impl. - S32 i ; - S32 end = (S32)mMediaImplList.size() ; - for(i = 0; i < end ; i++) - { - if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) - { - break ; - } - } - - if(i == end) //this object does not need this media impl. - { - mMediaImplList[texture_index]->removeObject(this) ; - } - - mMediaImplList[texture_index] = NULL ; - return ; + if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) + { + return ; + } + + //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. + if(mDrawable && texture_index < mDrawable->getNumFaces()) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->removeMediaFromFace(facep) ; + } + } + } + + //check if some other face(s) of this object reference(s)to this media impl. + S32 i ; + S32 end = (S32)mMediaImplList.size() ; + for(i = 0; i < end ; i++) + { + if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) + { + break ; + } + } + + if(i == end) //this object does not need this media impl. + { + mMediaImplList[texture_index]->removeObject(this) ; + } + + mMediaImplList[texture_index] = NULL ; + return ; } void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) { - if((S32)mMediaImplList.size() < texture_index + 1) - { - mMediaImplList.resize(texture_index + 1) ; - } - - if(mMediaImplList[texture_index].notNull()) - { - if(mMediaImplList[texture_index] == media_impl) - { - return ; - } - - removeMediaImpl(texture_index) ; - } - - mMediaImplList[texture_index] = media_impl; - media_impl->addObject(this) ; - - //add the face to show the media if it is in playing - if(mDrawable) - { - LLFace* facep(NULL); - if( texture_index < mDrawable->getNumFaces() ) - { - facep = mDrawable->getFace(texture_index) ; - } - - if(facep) - { - LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; - if(media_tex) - { - media_tex->addMediaToFace(facep) ; - } - } - else //the face is not available now, start media on this face later. - { - media_impl->setUpdated(TRUE) ; - } - } - return ; + if((S32)mMediaImplList.size() < texture_index + 1) + { + mMediaImplList.resize(texture_index + 1) ; + } + + if(mMediaImplList[texture_index].notNull()) + { + if(mMediaImplList[texture_index] == media_impl) + { + return ; + } + + removeMediaImpl(texture_index) ; + } + + mMediaImplList[texture_index] = media_impl; + media_impl->addObject(this) ; + + //add the face to show the media if it is in playing + if(mDrawable) + { + LLFace* facep(NULL); + if( texture_index < mDrawable->getNumFaces() ) + { + facep = mDrawable->getFace(texture_index) ; + } + + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + else //the face is not available now, start media on this face later. + { + media_impl->setUpdated(TRUE) ; + } + } + return ; } viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const { - if(mMediaImplList.size() > face_id) - { - return mMediaImplList[face_id]; - } - return NULL; + if(mMediaImplList.size() > face_id) + { + return mMediaImplList[face_id]; + } + return NULL; } F64 LLVOVolume::getTotalMediaInterest() const { - // If this object is currently focused, this object has "high" interest - if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) - return F64_MAX; - - F64 interest = (F64)-1.0; // means not interested; - - // If this object is selected, this object has "high" interest, but since - // there can be more than one, we still add in calculated impl interest - // XXX Sadly, 'contains()' doesn't take a const :( - if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) - interest = F64_MAX / 2.0; - - int i = 0; - const int end = getNumTEs(); - for ( ; i < end; ++i) - { - const viewer_media_t &impl = getMediaImpl(i); - if (!impl.isNull()) - { - if (interest == (F64)-1.0) interest = (F64)0.0; - interest += impl->getInterest(); - } - } - return interest; + // If this object is currently focused, this object has "high" interest + if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID()) + return F64_MAX; + + F64 interest = (F64)-1.0; // means not interested; + + // If this object is selected, this object has "high" interest, but since + // there can be more than one, we still add in calculated impl interest + // XXX Sadly, 'contains()' doesn't take a const :( + if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this))) + interest = F64_MAX / 2.0; + + int i = 0; + const int end = getNumTEs(); + for ( ; i < end; ++i) + { + const viewer_media_t &impl = getMediaImpl(i); + if (!impl.isNull()) + { + if (interest == (F64)-1.0) interest = (F64)0.0; + interest += impl->getInterest(); + } + } + return interest; } S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) { - S32 end = (S32)mMediaImplList.size() ; - for(S32 face_id = start_face_id + 1; face_id < end; face_id++) - { - if(mMediaImplList[face_id] == media_impl) - { - return face_id ; - } - } - return -1 ; + S32 end = (S32)mMediaImplList.size() ; + for(S32 face_id = start_face_id + 1; face_id < end; face_id++) + { + if(mMediaImplList[face_id] == media_impl) + { + return face_id ; + } + } + return -1 ; } //---------------------------------------------------------------------------- void LLVOVolume::setLightTextureID(LLUUID id) { - LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary - if (id.notNull()) - { - if (!hasLightTexture()) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); - } - else if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getLightTexture() != id) - { - param_block->setLightTexture(id); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } - LLViewerTexture* tex = getLightTexture(); - if (tex) - { - tex->addVolume(LLRender::LIGHT_TEX, this); // new texture - } - else - { - LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; - } - } - else if (hasLightTexture()) - { - if (old_texturep) - { - old_texturep->removeVolume(LLRender::LIGHT_TEX, this); - } - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - mLightTexture = NULL; - } + LLViewerTexture* old_texturep = getLightTexture(); // same as mLightTexture, but inits if nessesary + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + else if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + LLViewerTexture* tex = getLightTexture(); + if (tex) + { + tex->addVolume(LLRender::LIGHT_TEX, this); // new texture + } + else + { + LL_WARNS() << "Can't get light texture for ID " << id.asString() << LL_ENDL; + } + } + else if (hasLightTexture()) + { + if (old_texturep) + { + old_texturep->removeVolume(LLRender::LIGHT_TEX, this); + } + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + mLightTexture = NULL; + } } void LLVOVolume::setSpotLightParams(LLVector3 params) { - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block && param_block->getParams() != params) - { - param_block->setParams(params); - parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); - } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } } - + void LLVOVolume::setIsLight(BOOL is_light) { - BOOL was_light = getIsLight(); - if (is_light != was_light) - { - if (is_light) - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); - } - else - { - setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); - } - - if (is_light) - { - // Add it to the pipeline mLightSet - gPipeline.setLight(mDrawable, TRUE); - } - else - { - // Not a light. Remove it from the pipeline's light set. - gPipeline.setLight(mDrawable, FALSE); - } - } + BOOL was_light = getIsLight(); + if (is_light != was_light) + { + if (is_light) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true); + } + else + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true); + } + + if (is_light) + { + // Add it to the pipeline mLightSet + gPipeline.setLight(mDrawable, TRUE); + } + else + { + // Not a light. Remove it from the pipeline's light set. + gPipeline.setLight(mDrawable, FALSE); + } + } } void LLVOVolume::setLightSRGBColor(const LLColor3& color) @@ -3066,69 +3066,69 @@ void LLVOVolume::setLightSRGBColor(const LLColor3& color) void LLVOVolume::setLightLinearColor(const LLColor3& color) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getLinearColor() != color) - { - param_block->setLinearColor(LLColor4(color, param_block->getLinearColor().mV[3])); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - gPipeline.markTextured(mDrawable); - mFaceMappingChanged = TRUE; - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getLinearColor() != color) + { + param_block->setLinearColor(LLColor4(color, param_block->getLinearColor().mV[3])); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + } + } } void LLVOVolume::setLightIntensity(F32 intensity) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getLinearColor().mV[3] != intensity) - { - param_block->setLinearColor(LLColor4(LLColor3(param_block->getLinearColor()), intensity)); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getLinearColor().mV[3] != intensity) + { + param_block->setLinearColor(LLColor4(LLColor3(param_block->getLinearColor()), intensity)); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightRadius(F32 radius) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getRadius() != radius) - { - param_block->setRadius(radius); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getRadius() != radius) + { + param_block->setRadius(radius); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightFalloff(F32 falloff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getFalloff() != falloff) - { - param_block->setFalloff(falloff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getFalloff() != falloff) + { + param_block->setFalloff(falloff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } void LLVOVolume::setLightCutoff(F32 cutoff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - if (param_block->getCutoff() != cutoff) - { - param_block->setCutoff(cutoff); - parameterChanged(LLNetworkData::PARAMS_LIGHT, true); - } - } + LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + if (param_block->getCutoff() != cutoff) + { + param_block->setCutoff(cutoff); + parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + } + } } //---------------------------------------------------------------------------- @@ -3151,15 +3151,15 @@ LLColor3 LLVOVolume::getLightSRGBBaseColor() const LLColor3 LLVOVolume::getLightLinearBaseColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return LLColor3(param_block->getLinearColor()); - } - else - { - return LLColor3(1,1,1); - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return LLColor3(param_block->getLinearColor()); + } + else + { + return LLColor3(1,1,1); + } } LLColor3 LLVOVolume::getLightLinearColor() const @@ -3184,36 +3184,36 @@ LLColor3 LLVOVolume::getLightSRGBColor() const LLUUID LLVOVolume::getLightTextureID() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } - } - - return LLUUID::null; -} - - -LLVector3 LLVOVolume::getSpotLightParams() const + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + } + + return LLUUID::null; +} + + +LLVector3 LLVOVolume::getSpotLightParams() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } - } - - return LLVector3(); + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + } + + return LLVector3(); } F32 LLVOVolume::getSpotLightPriority() const { - return mSpotLightPriority; + return mSpotLightPriority; } void LLVOVolume::updateSpotLightPriority() @@ -3224,104 +3224,104 @@ void LLVOVolume::updateSpotLightPriority() } F32 r = getLightRadius(); - LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 pos = mDrawable->getPositionAgent(); - LLVector3 at(0,0,-1); - at *= getRenderRotation(); - pos += at * r; + LLVector3 at(0,0,-1); + at *= getRenderRotation(); + pos += at * r; - at = LLViewerCamera::getInstance()->getAtAxis(); - pos -= at * r; + at = LLViewerCamera::getInstance()->getAtAxis(); + pos -= at * r; - mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); - if (mLightTexture.notNull()) - { - mLightTexture->addTextureStats(mSpotLightPriority); - } + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + } } bool LLVOVolume::isLightSpotlight() const { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return params->isLightSpotlight(); - } - return false; + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return params->isLightSpotlight(); + } + return false; } LLViewerTexture* LLVOVolume::getLightTexture() { - LLUUID id = getLightTextureID(); + LLUUID id = getLightTextureID(); - if (id.notNull()) - { - if (mLightTexture.isNull() || id != mLightTexture->getID()) - { - mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); - } - } - else - { - mLightTexture = NULL; - } + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE); + } + } + else + { + mLightTexture = NULL; + } - return mLightTexture; + return mLightTexture; } F32 LLVOVolume::getLightIntensity() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getLinearColor().mV[3]; - } - else - { - return 1.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getLinearColor().mV[3]; + } + else + { + return 1.f; + } } F32 LLVOVolume::getLightRadius() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getRadius(); - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getRadius(); + } + else + { + return 0.f; + } } F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getFalloff() * fudge_factor; - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getFalloff() * fudge_factor; + } + else + { + return 0.f; + } } F32 LLVOVolume::getLightCutoff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); - if (param_block) - { - return param_block->getCutoff(); - } - else - { - return 0.f; - } + const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + if (param_block) + { + return param_block->getCutoff(); + } + else + { + return 0.f; + } } BOOL LLVOVolume::isReflectionProbe() const @@ -3424,10 +3424,10 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) param_block->setIsMirror(is_mirror); parameterChanged(LLNetworkData::PARAMS_REFLECTION_PROBE, true); - if (!is_mirror) - gPipeline.mHeroProbeManager.unregisterViewerObject(this); - else - gPipeline.mHeroProbeManager.registerViewerObject(this); + if (!is_mirror) + gPipeline.mHeroProbeManager.unregisterViewerObject(this); + else + gPipeline.mHeroProbeManager.registerViewerObject(this); return true; } @@ -3469,7 +3469,7 @@ bool LLVOVolume::getReflectionProbeIsBox() const { return param_block->getIsBox(); } - + return false; } @@ -3498,68 +3498,68 @@ bool LLVOVolume::getReflectionProbeIsMirror() const U32 LLVOVolume::getVolumeInterfaceID() const { - if (mVolumeImpl) - { - return mVolumeImpl->getID(); - } + if (mVolumeImpl) + { + return mVolumeImpl->getID(); + } - return 0; + return 0; } BOOL LLVOVolume::isFlexible() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) - { - LLVolume* volume = getVolume(); - if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) - { - LLVolumeParams volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - } - return TRUE; - } - else - { - return FALSE; - } + if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + { + LLVolume* volume = getVolume(); + if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) + { + LLVolumeParams volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + } + return TRUE; + } + else + { + return FALSE; + } } BOOL LLVOVolume::isSculpted() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - return TRUE; - } - - return FALSE; + if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + { + return TRUE; + } + + return FALSE; } BOOL LLVOVolume::isMesh() const { - if (isSculpted()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - U8 sculpt_type = sculpt_params->getSculptType(); + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - return TRUE; - } - } + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } - return FALSE; + return FALSE; } BOOL LLVOVolume::hasLightTexture() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) - { - return TRUE; - } + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } - return FALSE; + return FALSE; } bool LLVOVolume::isFlexibleFast() const @@ -3589,67 +3589,67 @@ bool LLVOVolume::isAnimatedObjectFast() const BOOL LLVOVolume::isVolumeGlobal() const { - if (mVolumeImpl) - { - return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; - } - else if (mRiggedVolume.notNull()) - { - return TRUE; - } + if (mVolumeImpl) + { + return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; + } + else if (mRiggedVolume.notNull()) + { + return TRUE; + } - return FALSE; + return FALSE; } BOOL LLVOVolume::canBeFlexible() const { - U8 path = getVolume()->getParams().getPathParams().getCurveType(); - return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); + U8 path = getVolume()->getParams().getPathParams().getCurveType(); + return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE); } BOOL LLVOVolume::setIsFlexible(BOOL is_flexible) { - BOOL res = FALSE; - BOOL was_flexible = isFlexible(); - LLVolumeParams volume_params; - if (is_flexible) - { - if (!was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); - res = TRUE; - setFlags(FLAGS_USE_PHYSICS, FALSE); - setFlags(FLAGS_PHANTOM, TRUE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); - if (mDrawable) - { - mDrawable->makeActive(); - } - } - } - else - { - if (was_flexible) - { - volume_params = getVolume()->getParams(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); - res = TRUE; - setFlags(FLAGS_PHANTOM, FALSE); - setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); - } - } - if (res) - { - res = setVolume(volume_params, 1); - if (res) - { - markForUpdate(); - } - } - return res; + BOOL res = FALSE; + BOOL was_flexible = isFlexible(); + LLVolumeParams volume_params; + if (is_flexible) + { + if (!was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE); + res = TRUE; + setFlags(FLAGS_USE_PHYSICS, FALSE); + setFlags(FLAGS_PHANTOM, TRUE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true); + if (mDrawable) + { + mDrawable->makeActive(); + } + } + } + else + { + if (was_flexible) + { + volume_params = getVolume()->getParams(); + U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); + volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE); + res = TRUE; + setFlags(FLAGS_PHANTOM, FALSE); + setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true); + } + } + if (res) + { + res = setVolume(volume_params, 1); + if (res) + { + markForUpdate(); + } + } + return res; } const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const @@ -3673,16 +3673,16 @@ BOOL LLVOVolume::isRiggedMesh() const //---------------------------------------------------------------------------- U32 LLVOVolume::getExtendedMeshFlags() const { - const LLExtendedMeshParams *param_block = + const LLExtendedMeshParams *param_block = (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); - if (param_block) - { - return param_block->getFlags(); - } - else - { - return 0; - } + if (param_block) + { + return param_block->getFlags(); + } + else + { + return 0; + } } void LLVOVolume::onSetExtendedMeshFlags(U32 flags) @@ -3691,7 +3691,7 @@ void LLVOVolume::onSetExtendedMeshFlags(U32 flags) // The isAnySelected() check was needed at one point to prevent // graphics problems. These are now believed to be fixed so the // check has been disabled. - if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) + if (/*!getRootEdit()->isAnySelected() &&*/ mDrawable.notNull()) { // Need to trigger rebuildGeom(), which is where control avatars get created/removed getRootEdit()->recursiveMarkForUpdate(); @@ -3719,7 +3719,7 @@ void LLVOVolume::setExtendedMeshFlags(U32 flags) { bool in_use = true; setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); - LLExtendedMeshParams *param_block = + LLExtendedMeshParams *param_block = (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); if (param_block) { @@ -3789,13 +3789,13 @@ void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_pare void LLVOVolume::afterReparent() { { - LL_DEBUGS("AnimatedObjects") << "new child added for parent " + LL_DEBUGS("AnimatedObjects") << "new child added for parent " << ((LLViewerObject*)getParent())->getID() << LL_ENDL; } - + if (isAnimatedObject() && getControlAvatar()) { - LL_DEBUGS("AnimatedObjects") << "adding attachment overrides, parent is animated object " + LL_DEBUGS("AnimatedObjects") << "adding attachment overrides, parent is animated object " << ((LLViewerObject*)getParent())->getID() << LL_ENDL; // MAINT-8239 - doing a full rebuild whenever parent is set @@ -3803,15 +3803,15 @@ void LLVOVolume::afterReparent() // addAttachmentOverrides should be sufficient, but in // practice doing a full rebuild helps compensate for // notifyMeshLoaded() not being called reliably enough. - + // was: getControlAvatar()->addAttachmentOverridesForObject(this); //getControlAvatar()->rebuildAttachmentOverrides(); getControlAvatar()->updateAnimations(); } else { - LL_DEBUGS("AnimatedObjects") << "not adding overrides, parent: " - << ((LLViewerObject*)getParent())->getID() + LL_DEBUGS("AnimatedObjects") << "not adding overrides, parent: " + << ((LLViewerObject*)getParent())->getID() << " isAnimated: " << isAnimatedObject() << " cav " << getControlAvatar() << LL_ENDL; } @@ -3844,8 +3844,8 @@ void LLVOVolume::updateRiggingInfo() } // Keep the highest LOD info available. mLastRiggingInfoLOD = getLOD(); - LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume " - << this << " lod " << mLastRiggingInfoLOD + LL_DEBUGS("RigSpammish") << "updated rigging info for LLVOVolume " + << this << " lod " << mLastRiggingInfoLOD << LL_ENDL; } } @@ -3856,86 +3856,86 @@ void LLVOVolume::updateRiggingInfo() void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) { - LLVolume *volume = getVolume(); - - if (volume) - { - LLVector3 view_vector; - view_vector = view_point; - - //transform view vector into volume space - view_vector -= getRenderPosition(); - //mDrawable->mDistanceWRTCamera = view_vector.length(); - LLQuaternion worldRot = getRenderRotation(); - view_vector = view_vector * ~worldRot; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - view_vector.scaleVec(invObjScale); - } - - updateRelativeXform(); - LLMatrix4 trans_mat = mRelativeXform; - if (mDrawable->isStatic()) - { - trans_mat.translate(getRegion()->getOriginAgent()); - } - - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); - - nodep->mSilhouetteExists = TRUE; - } + LLVolume *volume = getVolume(); + + if (volume) + { + LLVector3 view_vector; + view_vector = view_point; + + //transform view vector into volume space + view_vector -= getRenderPosition(); + //mDrawable->mDistanceWRTCamera = view_vector.length(); + LLQuaternion worldRot = getRenderRotation(); + view_vector = view_vector * ~worldRot; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + view_vector.scaleVec(invObjScale); + } + + updateRelativeXform(); + LLMatrix4 trans_mat = mRelativeXform; + if (mDrawable->isStatic()) + { + trans_mat.translate(getRegion()->getOriginAgent()); + } + + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); + + nodep->mSilhouetteExists = TRUE; + } } void LLVOVolume::deleteFaces() { - S32 face_count = mNumFaces; - if (mDrawable.notNull()) - { - mDrawable->deleteFaces(0, face_count); - } + S32 face_count = mNumFaces; + if (mDrawable.notNull()) + { + mDrawable->deleteFaces(0, face_count); + } - mNumFaces = 0; + mNumFaces = 0; } void LLVOVolume::updateRadius() { - if (mDrawable.isNull()) - { - return; - } - - mVObjRadius = getScale().length(); - mDrawable->setRadius(mVObjRadius); + if (mDrawable.isNull()) + { + return; + } + + mVObjRadius = getScale().length(); + mDrawable->setRadius(mVObjRadius); } BOOL LLVOVolume::isAttachment() const { - return mAttachmentState != 0 ; + return mAttachmentState != 0 ; } BOOL LLVOVolume::isHUDAttachment() const { - // *NOTE: we assume hud attachment points are in defined range - // since this range is constant for backwards compatibility - // reasons this is probably a reasonable assumption to make - S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); - return ( attachment_id >= 31 && attachment_id <= 38 ); + // *NOTE: we assume hud attachment points are in defined range + // since this range is constant for backwards compatibility + // reasons this is probably a reasonable assumption to make + S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState); + return ( attachment_id >= 31 && attachment_id <= 38 ); } const LLMatrix4 LLVOVolume::getRenderMatrix() const { - if (mDrawable->isActive() && !mDrawable->isRoot()) - { - return mDrawable->getParent()->getWorldMatrix(); - } - return mDrawable->getWorldMatrix(); + if (mDrawable->isActive() && !mDrawable->isRoot()) + { + return mDrawable->getParent()->getWorldMatrix(); + } + return mDrawable->getWorldMatrix(); } -//static +//static S32 LLVOVolume::getTextureCost(const LLViewerTexture* img) { static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested @@ -3977,57 +3977,57 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const * the official viewer for consideration. *****************************************************************/ - // Get access to params we'll need at various points. - // Skip if this is object doesn't have a volume (e.g. is an avatar). + // Get access to params we'll need at various points. + // Skip if this is object doesn't have a volume (e.g. is an avatar). if (getVolume() == NULL) { return 0; } - U32 num_triangles = 0; + U32 num_triangles = 0; - // per-prim costs - static const U32 ARC_PARTICLE_COST = 1; // determined experimentally - static const U32 ARC_PARTICLE_MAX = 2048; // default values - static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims - static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face + // per-prim costs + static const U32 ARC_PARTICLE_COST = 1; // determined experimentally + static const U32 ARC_PARTICLE_MAX = 2048; // default values + static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims + static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face - // per-prim multipliers - static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance - static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance - static const F32 ARC_FLEXI_MULT = 5; // tested based on performance - static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance - static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance - static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance + // per-prim multipliers + static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance + static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance + static const F32 ARC_FLEXI_MULT = 5; // tested based on performance + static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance + static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance + static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance - static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact - static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance - static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance + static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact + static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance + static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance - F32 shame = 0; + F32 shame = 0; - U32 invisi = 0; - U32 shiny = 0; - U32 glow = 0; - U32 alpha = 0; - U32 flexi = 0; - U32 animtex = 0; - U32 particles = 0; - U32 bump = 0; - U32 planar = 0; - U32 weighted_mesh = 0; - U32 produces_light = 0; - U32 media_faces = 0; + U32 invisi = 0; + U32 shiny = 0; + U32 glow = 0; + U32 alpha = 0; + U32 flexi = 0; + U32 animtex = 0; + U32 particles = 0; + U32 bump = 0; + U32 planar = 0; + U32 weighted_mesh = 0; + U32 produces_light = 0; + U32 media_faces = 0; - const LLDrawable* drawablep = mDrawable; - U32 num_faces = drawablep->getNumFaces(); + const LLDrawable* drawablep = mDrawable; + U32 num_faces = drawablep->getNumFaces(); - const LLVolumeParams& volume_params = getVolume()->getParams(); + const LLVolumeParams& volume_params = getVolume()->getParams(); LLMeshCostData costs; - if (getCostData(costs)) - { + if (getCostData(costs)) + { if (isAnimatedObjectFast() && isRiggedMeshFast()) { // Scaling here is to make animated object vs @@ -4040,58 +4040,58 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const F32 radius = getScale().length()*0.5f; num_triangles = costs.getRadiusWeightedTris(radius); } - } - - - if (num_triangles <= 0) - { - num_triangles = 4; - } - - if (isSculptedFast()) - { - if (isMeshFast()) - { - // base cost is dependent on mesh complexity - // note that 3 is the highest LOD as of the time of this coding. - S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); - if ( size > 0) - { - if (isRiggedMeshFast()) - { - // weighted attachment - 1 point for every 3 bytes - weighted_mesh = 1; - } - } - else - { - // something went wrong - user should know their content isn't render-free - return 0; - } - } - else - { + } + + + if (num_triangles <= 0) + { + num_triangles = 4; + } + + if (isSculptedFast()) + { + if (isMeshFast()) + { + // base cost is dependent on mesh complexity + // note that 3 is the highest LOD as of the time of this coding. + S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(), getLOD()); + if ( size > 0) + { + if (isRiggedMeshFast()) + { + // weighted attachment - 1 point for every 3 bytes + weighted_mesh = 1; + } + } + else + { + // something went wrong - user should know their content isn't render-free + return 0; + } + } + else + { LLViewerFetchedTexture* texture = mSculptTexture; - if (texture && textures.find(texture) == textures.end()) - { + if (texture && textures.find(texture) == textures.end()) + { textures.insert(texture); - } - } - } + } + } + } - if (isFlexibleFast()) - { - flexi = 1; - } - if (isParticleSource()) - { - particles = 1; - } + if (isFlexibleFast()) + { + flexi = 1; + } + if (isParticleSource()) + { + particles = 1; + } - if (getIsLightFast()) - { - produces_light = 1; - } + if (getIsLightFast()) + { + produces_light = 1; + } { LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("ARC - face list"); @@ -4149,79 +4149,79 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const } } - // shame currently has the "base" cost of 1 point per 15 triangles, min 2. - shame = num_triangles * 5.f; - shame = shame < 2.f ? 2.f : shame; - - // multiply by per-face modifiers - if (planar) - { - shame *= planar * ARC_PLANAR_COST; - } - - if (animtex) - { - shame *= animtex * ARC_ANIM_TEX_COST; - } - - if (alpha) - { - shame *= alpha * ARC_ALPHA_COST; - } - - if(invisi) - { - shame *= invisi * ARC_INVISI_COST; - } - - if (glow) - { - shame *= glow * ARC_GLOW_MULT; - } - - if (bump) - { - shame *= bump * ARC_BUMP_MULT; - } - - if (shiny) - { - shame *= shiny * ARC_SHINY_MULT; - } - - - // multiply shame by multipliers - if (weighted_mesh) - { - shame *= weighted_mesh * ARC_WEIGHTED_MESH; - } - - if (flexi) - { - shame *= flexi * ARC_FLEXI_MULT; - } - - - // add additional costs - if (particles) - { - const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); - const LLPartData *part_data = &(part_sys_data->mPartData); - U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); - num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; - F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; - shame += num_particles * part_size * ARC_PARTICLE_COST; - } - - if (produces_light) - { - shame += ARC_LIGHT_COST; - } - - if (media_faces) - { - shame += media_faces * ARC_MEDIA_FACE_COST; - } + // shame currently has the "base" cost of 1 point per 15 triangles, min 2. + shame = num_triangles * 5.f; + shame = shame < 2.f ? 2.f : shame; + + // multiply by per-face modifiers + if (planar) + { + shame *= planar * ARC_PLANAR_COST; + } + + if (animtex) + { + shame *= animtex * ARC_ANIM_TEX_COST; + } + + if (alpha) + { + shame *= alpha * ARC_ALPHA_COST; + } + + if(invisi) + { + shame *= invisi * ARC_INVISI_COST; + } + + if (glow) + { + shame *= glow * ARC_GLOW_MULT; + } + + if (bump) + { + shame *= bump * ARC_BUMP_MULT; + } + + if (shiny) + { + shame *= shiny * ARC_SHINY_MULT; + } + + + // multiply shame by multipliers + if (weighted_mesh) + { + shame *= weighted_mesh * ARC_WEIGHTED_MESH; + } + + if (flexi) + { + shame *= flexi * ARC_FLEXI_MULT; + } + + + // add additional costs + if (particles) + { + const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); + const LLPartData *part_data = &(part_sys_data->mPartData); + U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); + num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; + F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; + shame += num_particles * part_size * ARC_PARTICLE_COST; + } + + if (produces_light) + { + shame += ARC_LIGHT_COST; + } + + if (media_faces) + { + shame += media_faces * ARC_MEDIA_FACE_COST; + } // Streaming cost for animated objects includes a fixed cost // per linkset. Add a corresponding charge here translated into @@ -4231,35 +4231,35 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const shame += (ANIMATED_OBJECT_BASE_COST/0.06) * 5.0f; } - if (shame > mRenderComplexity_current) - { - mRenderComplexity_current = (S32)shame; - } + if (shame > mRenderComplexity_current) + { + mRenderComplexity_current = (S32)shame; + } - return (U32)shame; + return (U32)shame; } F32 LLVOVolume::getEstTrianglesMax() const { - if (isMeshFast() && getVolume()) - { - return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); - } + if (isMeshFast() && getVolume()) + { + return gMeshRepo.getEstTrianglesMax(getVolume()->getParams().getSculptID()); + } return 0.f; } F32 LLVOVolume::getEstTrianglesStreamingCost() const { - if (isMeshFast() && getVolume()) - { - return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); - } + if (isMeshFast() && getVolume()) + { + return gMeshRepo.getEstTrianglesStreamingCost(getVolume()->getParams().getSculptID()); + } return 0.f; } F32 LLVOVolume::getStreamingCost() const { - F32 radius = getScale().length()*0.5f; + F32 radius = getScale().length()*0.5f; F32 linkset_base_cost = 0.f; LLMeshCostData costs; @@ -4303,87 +4303,87 @@ bool LLVOVolume::getCostData(LLMeshCostData& costs) const } else { - LLVolume* volume = getVolume(); - S32 counts[4]; - LLVolume::getLoDTriangleCounts(volume->getParams(), counts); + LLVolume* volume = getVolume(); + S32 counts[4]; + LLVolume::getLoDTriangleCounts(volume->getParams(), counts); LLMeshHeader header; - header.mLodSize[0] = counts[0] * 10; - header.mLodSize[1] = counts[1] * 10; - header.mLodSize[2] = counts[2] * 10; - header.mLodSize[3] = counts[3] * 10; + header.mLodSize[0] = counts[0] * 10; + header.mLodSize[1] = counts[1] * 10; + header.mLodSize[2] = counts[2] * 10; + header.mLodSize[3] = counts[3] * 10; - return gMeshRepo.getCostData(header, costs); + return gMeshRepo.getCostData(header, costs); } } -//static +//static void LLVOVolume::updateRenderComplexity() { - mRenderComplexity_last = mRenderComplexity_current; - mRenderComplexity_current = 0; + mRenderComplexity_last = mRenderComplexity_current; + mRenderComplexity_current = 0; } U32 LLVOVolume::getTriangleCount(S32* vcount) const { - U32 count = 0; - LLVolume* volume = getVolume(); - if (volume) - { - count = volume->getNumTriangles(vcount); - } + U32 count = 0; + LLVolume* volume = getVolume(); + if (volume) + { + count = volume->getNumTriangles(vcount); + } - return count; + return count; } U32 LLVOVolume::getHighLODTriangleCount() { - U32 ret = 0; - - LLVolume* volume = getVolume(); - - if (!isSculpted()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else if (isMesh()) - { - LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); - if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) - { - gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); - } - ret = ref->getNumTriangles(); - LLPrimitive::getVolumeManager()->unrefVolume(ref); - } - else - { //default sculpts have a constant number of triangles - ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch - } - - return ret; + U32 ret = 0; + + LLVolume* volume = getVolume(); + + if (!isSculpted()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else if (isMesh()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) + { + gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); + } + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } + else + { //default sculpts have a constant number of triangles + ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch + } + + return ret; } //static void LLVOVolume::preUpdateGeom() { - sNumLODChanges = 0; + sNumLODChanges = 0; } void LLVOVolume::parameterChanged(U16 param_type, bool local_origin) { - LLViewerObject::parameterChanged(param_type, local_origin); + LLViewerObject::parameterChanged(param_type, local_origin); } void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) { - LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); - if (mVolumeImpl) - { - mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); - } + LLViewerObject::parameterChanged(param_type, data, in_use, local_origin); + if (mVolumeImpl) + { + mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin); + } if (!local_origin && param_type == LLNetworkData::PARAMS_EXTENDED_MESH) { U32 extended_mesh_flags = getExtendedMeshFlags(); @@ -4399,15 +4399,15 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u onSetExtendedMeshFlags(extended_mesh_flags); } } - if (mDrawable.notNull()) - { - BOOL is_light = getIsLight(); - if (is_light != mDrawable->isState(LLDrawable::LIGHT)) - { - gPipeline.setLight(mDrawable, is_light); - } - } - + if (mDrawable.notNull()) + { + BOOL is_light = getIsLight(); + if (is_light != mDrawable->isState(LLDrawable::LIGHT)) + { + gPipeline.setLight(mDrawable, is_light); + } + } + updateReflectionProbePtr(); } @@ -4420,13 +4420,13 @@ void LLVOVolume::updateReflectionProbePtr() mReflectionProbe = gPipeline.mReflectionMapManager.registerViewerObject(this); } else if (mReflectionProbe.isNull() && getReflectionProbeIsMirror()) - { - // Geenz: This is a special case - what we want here is a hero probe. - // What we want to do here is instantiate a hero probe from the hero probe manager. - + { + // Geenz: This is a special case - what we want here is a hero probe. + // What we want to do here is instantiate a hero probe from the hero probe manager. + if (!mIsHeroProbe) mIsHeroProbe = gPipeline.mHeroProbeManager.registerViewerObject(this); - } + } } else if (mReflectionProbe.notNull() || getReflectionProbeIsMirror()) { @@ -4435,7 +4435,7 @@ void LLVOVolume::updateReflectionProbePtr() mReflectionProbe = nullptr; } - if (getReflectionProbeIsMirror()) + if (getReflectionProbeIsMirror()) { gPipeline.mHeroProbeManager.unregisterViewerObject(this); } @@ -4444,7 +4444,7 @@ void LLVOVolume::updateReflectionProbePtr() void LLVOVolume::setSelected(BOOL sel) { - LLViewerObject::setSelected(sel); + LLViewerObject::setSelected(sel); if (isAnimatedObject()) { getRootEdit()->recursiveMarkForUpdate(); @@ -4459,7 +4459,7 @@ void LLVOVolume::setSelected(BOOL sel) } void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) -{ +{ } F32 LLVOVolume::getBinRadius() @@ -4524,104 +4524,104 @@ F32 LLVOVolume::getBinRadius() const LLVector3 LLVOVolume::getPivotPositionAgent() const { - if (mVolumeImpl) - { - return mVolumeImpl->getPivotPosition(); - } - return LLViewerObject::getPivotPositionAgent(); + if (mVolumeImpl) + { + return mVolumeImpl->getPivotPosition(); + } + return LLViewerObject::getPivotPositionAgent(); } void LLVOVolume::onShift(const LLVector4a &shift_vector) { - if (mVolumeImpl) - { - mVolumeImpl->onShift(shift_vector); - } + if (mVolumeImpl) + { + mVolumeImpl->onShift(shift_vector); + } - updateRelativeXform(); + updateRelativeXform(); } const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const { - if (mVolumeImpl) - { - return mVolumeImpl->getWorldMatrix(xform); - } - return xform->getWorldMatrix(); + if (mVolumeImpl) + { + return mVolumeImpl->getWorldMatrix(xform); + } + return xform->getWorldMatrix(); } void LLVOVolume::markForUpdate() -{ +{ if (mDrawable) { shrinkWrap(); } - LLViewerObject::markForUpdate(); - mVolumeChanged = TRUE; + LLViewerObject::markForUpdate(); + mVolumeChanged = TRUE; } LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { - LLVector3 ret = pos - getRenderPosition(); - ret = ret * ~getRenderRotation(); - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - } - - return ret; + LLVector3 ret = pos - getRenderPosition(); + ret = ret * ~getRenderRotation(); + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + } + + return ret; } LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const { - LLVector3 ret = dir * ~getRenderRotation(); - - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - ret.scaleVec(objScale); + LLVector3 ret = dir * ~getRenderRotation(); - return ret; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + ret.scaleVec(objScale); + + return ret; } LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const { - LLVector3 ret = dir; - if (!isVolumeGlobal()) - { - LLVector3 objScale = getScale(); - ret.scaleVec(objScale); - } + LLVector3 ret = dir; + if (!isVolumeGlobal()) + { + LLVector3 objScale = getScale(); + ret.scaleVec(objScale); + } - ret = ret * getRenderRotation(); - ret += getRenderPosition(); - - return ret; + ret = ret * getRenderRotation(); + ret += getRenderPosition(); + + return ret; } LLVector3 LLVOVolume::volumeDirectionToAgent(const LLVector3& dir) const { - LLVector3 ret = dir; - LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); - LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); - ret.scaleVec(invObjScale); - ret = ret * getRenderRotation(); + LLVector3 ret = dir; + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); + LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); + ret.scaleVec(invObjScale); + ret = ret * getRenderRotation(); - return ret; + return ret; } 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) - + LLVector4a* intersection,LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) + { - if (!mbCanSelect - || mDrawable->isDead() - || !gPipeline.hasRenderType(mDrawable->getRenderType())) - { - return FALSE; - } + if (!mbCanSelect + || mDrawable->isDead() + || !gPipeline.hasRenderType(mDrawable->getRenderType())) + { + return FALSE; + } if (!pick_unselectable) { @@ -4636,203 +4636,203 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& return FALSE; } - BOOL ret = FALSE; + BOOL ret = FALSE; - LLVolume* volume = getVolume(); + LLVolume* volume = getVolume(); - bool transform = true; + bool transform = true; - if (mDrawable->isState(LLDrawable::RIGGED)) - { - if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) - { - updateRiggedVolume(true, LLRiggedVolume::DO_NOT_UPDATE_FACES); - volume = mRiggedVolume; - transform = false; - } - else - { //cannot pick rigged attachments on other avatars or when not in build mode - return FALSE; - } - } - - if (volume) - { - LLVector4a local_start = start; - LLVector4a local_end = end; - - if (transform) - { - LLVector3 v_start(start.getF32ptr()); - LLVector3 v_end(end.getF32ptr()); - - v_start = agentPositionToVolume(v_start); - v_end = agentPositionToVolume(v_end); - - local_start.load3(v_start.mV); - local_end.load3(v_end.mV); - } - - LLVector4a p; - LLVector4a n; - LLVector2 tc; - LLVector4a tn; - - if (intersection != NULL) - { - p = *intersection; - } - - if (tex_coord != NULL) - { - tc = *tex_coord; - } - - if (normal != NULL) - { - n = *normal; - } - - if (tangent != NULL) - { - tn = *tangent; - } - - S32 face_hit = -1; - - S32 start_face, end_face; - if (face == -1) - { - start_face = 0; - end_face = volume->getNumVolumeFaces(); - } - else - { - start_face = face; - end_face = face+1; - } - pick_transparent |= isHiglightedOrBeacon(); + if (mDrawable->isState(LLDrawable::RIGGED)) + { + if ((pick_rigged) || (getAvatar() && (getAvatar()->isSelf()) && (LLFloater::isVisible(gFloaterTools)))) + { + updateRiggedVolume(true, LLRiggedVolume::DO_NOT_UPDATE_FACES); + volume = mRiggedVolume; + transform = false; + } + else + { //cannot pick rigged attachments on other avatars or when not in build mode + return FALSE; + } + } + + if (volume) + { + LLVector4a local_start = start; + LLVector4a local_end = end; + + if (transform) + { + LLVector3 v_start(start.getF32ptr()); + LLVector3 v_end(end.getF32ptr()); + + v_start = agentPositionToVolume(v_start); + v_end = agentPositionToVolume(v_end); + + local_start.load3(v_start.mV); + local_end.load3(v_end.mV); + } + + LLVector4a p; + LLVector4a n; + LLVector2 tc; + LLVector4a tn; + + if (intersection != NULL) + { + p = *intersection; + } + + if (tex_coord != NULL) + { + tc = *tex_coord; + } + + if (normal != NULL) + { + n = *normal; + } + + if (tangent != NULL) + { + tn = *tangent; + } + + S32 face_hit = -1; + + S32 start_face, end_face; + if (face == -1) + { + start_face = 0; + end_face = volume->getNumVolumeFaces(); + } + else + { + start_face = face; + end_face = face+1; + } + pick_transparent |= isHiglightedOrBeacon(); // we *probably* shouldn't care about special cursor at all, but we *definitely* // don't care about special cursor for reflection probes -- makes alt-zoom // go through reflection probes on vehicles - bool special_cursor = mReflectionProbe.isNull() && specialHoverCursor(); + bool special_cursor = mReflectionProbe.isNull() && specialHoverCursor(); - for (S32 i = start_face; i < end_face; ++i) - { - if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) - { //don't attempt to pick completely transparent faces unless - //pick_transparent is true - continue; - } + for (S32 i = start_face; i < end_face; ++i) + { + if (!special_cursor && !pick_transparent && getTE(i) && getTE(i)->getColor().mV[3] == 0.f) + { //don't attempt to pick completely transparent faces unless + //pick_transparent is true + continue; + } // This calculates the bounding box of the skinned mesh from scratch. It's actually quite expensive, but not nearly as expensive as building a full octree. // rebuild_face_octrees = false because an octree for this face will be built later only if needed for narrow phase picking. updateRiggedVolume(true, i, false); - face_hit = volume->lineSegmentIntersect(local_start, local_end, i, - &p, &tc, &n, &tn); - - if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) - { - LLFace* face = mDrawable->getFace(face_hit); - - bool ignore_alpha = false; - - const LLTextureEntry* te = face->getTextureEntry(); - if (te) - { - LLMaterial* mat = te->getMaterialParams(); - if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE - || mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE - || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && mat->getAlphaMaskCutoff() == 0)) - { - ignore_alpha = true; - } - } - } + face_hit = volume->lineSegmentIntersect(local_start, local_end, i, + &p, &tc, &n, &tn); + + if (face_hit >= 0 && mDrawable->getNumFaces() > face_hit) + { + LLFace* face = mDrawable->getFace(face_hit); + + bool ignore_alpha = false; + + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + LLMaterial* mat = te->getMaterialParams(); + if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE + || mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE + || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && mat->getAlphaMaskCutoff() == 0)) + { + ignore_alpha = true; + } + } + } BOOL no_texture = !face->getTexture() || !face->getTexture()->hasGLTexture(); BOOL mask = no_texture ? FALSE : face->getTexture()->getMask(face->surfaceToTexture(tc, p, n)); - if (face && - (ignore_alpha || pick_transparent || no_texture || mask)) - { - local_end = p; - if (face_hitp != NULL) - { - *face_hitp = face_hit; - } - - if (intersection != NULL) - { - if (transform) - { - LLVector3 v_p(p.getF32ptr()); - - intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space - } - else - { - *intersection = p; - } - } - - if (normal != NULL) - { - if (transform) - { - LLVector3 v_n(n.getF32ptr()); - normal->load3(volumeDirectionToAgent(v_n).mV); - } - else - { - *normal = n; - } - (*normal).normalize3fast(); - } - - if (tangent != NULL) - { - if (transform) - { - LLVector3 v_tn(tn.getF32ptr()); - - LLVector4a trans_tangent; - trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); - - LLVector4Logical mask; - mask.clear(); - mask.setElement<3>(); - - tangent->setSelectWithMask(mask, tn, trans_tangent); - } - else - { - *tangent = tn; - } - (*tangent).normalize3fast(); - } - - if (tex_coord != NULL) - { - *tex_coord = tc; - } - - ret = TRUE; - } - } - } - } - - return ret; + if (face && + (ignore_alpha || pick_transparent || no_texture || mask)) + { + local_end = p; + if (face_hitp != NULL) + { + *face_hitp = face_hit; + } + + if (intersection != NULL) + { + if (transform) + { + LLVector3 v_p(p.getF32ptr()); + + intersection->load3(volumePositionToAgent(v_p).mV); // must map back to agent space + } + else + { + *intersection = p; + } + } + + if (normal != NULL) + { + if (transform) + { + LLVector3 v_n(n.getF32ptr()); + normal->load3(volumeDirectionToAgent(v_n).mV); + } + else + { + *normal = n; + } + (*normal).normalize3fast(); + } + + if (tangent != NULL) + { + if (transform) + { + LLVector3 v_tn(tn.getF32ptr()); + + LLVector4a trans_tangent; + trans_tangent.load3(volumeDirectionToAgent(v_tn).mV); + + LLVector4Logical mask; + mask.clear(); + mask.setElement<3>(); + + tangent->setSelectWithMask(mask, tn, trans_tangent); + } + else + { + *tangent = tn; + } + (*tangent).normalize3fast(); + } + + if (tex_coord != NULL) + { + *tex_coord = tc; + } + + ret = TRUE; + } + } + } + } + + return ret; } bool LLVOVolume::treatAsRigged() { - return isSelected() && + return isSelected() && (isAttachment() || isAnimatedObject()) && mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED); @@ -4840,52 +4840,52 @@ bool LLVOVolume::treatAsRigged() LLRiggedVolume* LLVOVolume::getRiggedVolume() { - return mRiggedVolume; + return mRiggedVolume; } void LLVOVolume::clearRiggedVolume() { - if (mRiggedVolume.notNull()) - { - mRiggedVolume = NULL; - updateRelativeXform(); - } + if (mRiggedVolume.notNull()) + { + mRiggedVolume = NULL; + updateRelativeXform(); + } } void LLVOVolume::updateRiggedVolume(bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index, bool rebuild_face_octrees) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - //Update mRiggedVolume to match current animation frame of avatar. - //Also update position/size in octree. + //Update mRiggedVolume to match current animation frame of avatar. + //Also update position/size in octree. if ((!force_treat_as_rigged) && (!treatAsRigged())) - { - clearRiggedVolume(); - - return; - } - - LLVolume* volume = getVolume(); - const LLMeshSkinInfo* skin = getSkinInfo(); - if (!skin) - { - clearRiggedVolume(); - return; - } - - LLVOAvatar* avatar = getAvatar(); - if (!avatar) - { - clearRiggedVolume(); - return; - } - - if (!mRiggedVolume) - { - LLVolumeParams p; - mRiggedVolume = new LLRiggedVolume(p); - updateRelativeXform(); - } + { + clearRiggedVolume(); + + return; + } + + LLVolume* volume = getVolume(); + const LLMeshSkinInfo* skin = getSkinInfo(); + if (!skin) + { + clearRiggedVolume(); + return; + } + + LLVOAvatar* avatar = getAvatar(); + if (!avatar) + { + clearRiggedVolume(); + return; + } + + if (!mRiggedVolume) + { + LLVolumeParams p; + mRiggedVolume = new LLRiggedVolume(p); + updateRelativeXform(); + } mRiggedVolume->update(skin, avatar, volume, face_index, rebuild_face_octrees); } @@ -4898,47 +4898,47 @@ void LLRiggedVolume::update( bool rebuild_face_octrees) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - bool copy = false; - if (volume->getNumVolumeFaces() != getNumVolumeFaces()) - { - copy = true; - } - - for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) - { - const LLVolumeFace& src_face = volume->getVolumeFace(i); - const LLVolumeFace& dst_face = getVolumeFace(i); - - if (src_face.mNumIndices != dst_face.mNumIndices || - src_face.mNumVertices != dst_face.mNumVertices) - { - copy = true; - } - } - - if (copy) - { - copyVolumeFaces(volume); - } + bool copy = false; + if (volume->getNumVolumeFaces() != getNumVolumeFaces()) + { + copy = true; + } + + for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) + { + const LLVolumeFace& src_face = volume->getVolumeFace(i); + const LLVolumeFace& dst_face = getVolumeFace(i); + + if (src_face.mNumIndices != dst_face.mNumIndices || + src_face.mNumVertices != dst_face.mNumVertices) + { + copy = true; + } + } + + if (copy) + { + copyVolumeFaces(volume); + } else { bool is_paused = avatar && avatar->areAnimationsPaused(); - if (is_paused) - { + if (is_paused) + { S32 frames_paused = LLFrameTimer::getFrameCount() - avatar->getMotionController().getPausedFrame(); if (frames_paused > 1) { return; } - } + } } - //build matrix palette - static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; + //build matrix palette + static const size_t kMaxJoints = LL_MAX_JOINTS_PER_MESH_OBJECT; - LLMatrix4a mat[kMaxJoints]; - U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); + LLMatrix4a mat[kMaxJoints]; + U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin); LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar); const LLMatrix4a bind_shape_matrix = skin->mBindShapeMatrix; @@ -4963,21 +4963,21 @@ void LLRiggedVolume::update( face_end = face_begin + 1; } for (S32 i = face_begin; i < face_end; ++i) - { - const LLVolumeFace& vol_face = volume->getVolumeFace(i); - - LLVolumeFace& dst_face = mVolumeFaces[i]; - - LLVector4a* weight = vol_face.mWeights; - - if ( weight ) - { + { + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + LLVolumeFace& dst_face = mVolumeFaces[i]; + + LLVector4a* weight = vol_face.mWeights; + + if ( weight ) + { LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin); - LLVector4a* pos = dst_face.mPositions; + LLVector4a* pos = dst_face.mPositions; - if (pos && dst_face.mExtents) - { + if (pos && dst_face.mExtents) + { U32 max_joints = LLSkinningUtil::getMaxJointCount(); rigged_vert_count += dst_face.mNumVertices; rigged_face_count++; @@ -4989,71 +4989,71 @@ void LLRiggedVolume::update( U8* joint_indices_cursor = vol_face.mJointIndices; LLVector4a* just_weights = vol_face.mJustWeights; for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; + { + LLMatrix4a final_mat; F32* w = just_weights[j].getF32ptr(); LLSkinningUtil::getPerVertexSkinMatrixWithIndices(w, joint_indices_cursor, mat, final_mat, src); joint_indices_cursor += 4; - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } } else #endif { - for (U32 j = 0; j < dst_face.mNumVertices; ++j) - { - LLMatrix4a final_mat; + for (U32 j = 0; j < dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints); - - LLVector4a& v = vol_face.mPositions[j]; - LLVector4a t; - LLVector4a dst; - bind_shape_matrix.affineTransform(v, t); - final_mat.affineTransform(t, dst); - pos[j] = dst; - } + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } } - //update bounding box - // VFExtents change - LLVector4a& min = dst_face.mExtents[0]; - LLVector4a& max = dst_face.mExtents[1]; + //update bounding box + // VFExtents change + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; - min = pos[0]; - max = pos[1]; + min = pos[0]; + max = pos[1]; if (i==0) { box_min = min; box_max = max; } - for (U32 j = 1; j < dst_face.mNumVertices; ++j) - { - min.setMin(min, pos[j]); - max.setMax(max, pos[j]); - } + for (U32 j = 1; j < dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } box_min.setMin(min,box_min); box_max.setMax(max,box_max); - dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); - dst_face.mCenter->mul(0.5f); + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); - } + } if (rebuild_face_octrees) - { + { dst_face.destroyOctree(); dst_face.createOctree(); - } - } - } + } + } + } mExtraDebugText = llformat("rigged %d/%d - box (%f %f %f) (%f %f %f)", rigged_face_count, rigged_vert_count, box_min[0], box_min[1], box_min[2], @@ -5062,111 +5062,111 @@ void LLRiggedVolume::update( U32 LLVOVolume::getPartitionType() const { - if (isHUDAttachment()) - { - return LLViewerRegion::PARTITION_HUD; - } - if (isAnimatedObject() && getControlAvatar()) - { - return LLViewerRegion::PARTITION_CONTROL_AV; - } - if (isAttachment()) - { - return LLViewerRegion::PARTITION_AVATAR; - } + if (isHUDAttachment()) + { + return LLViewerRegion::PARTITION_HUD; + } + if (isAnimatedObject() && getControlAvatar()) + { + return LLViewerRegion::PARTITION_CONTROL_AV; + } + if (isAttachment()) + { + return LLViewerRegion::PARTITION_AVATAR; + } - return LLViewerRegion::PARTITION_VOLUME; + return LLViewerRegion::PARTITION_VOLUME; } LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) : LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, regionp), LLVolumeGeometryManager() { - mLODPeriod = 32; - mDepthMask = FALSE; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_VOLUME; - mSlopRatio = 0.25f; + mLODPeriod = 32; + mDepthMask = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_VOLUME; + mSlopRatio = 0.25f; } LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) : LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), LLVolumeGeometryManager() { - mDepthMask = FALSE; - mLODPeriod = 32; - mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; - mPartitionType = LLViewerRegion::PARTITION_BRIDGE; - - mSlopRatio = 0.25f; + mDepthMask = FALSE; + mLODPeriod = 32; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLViewerRegion::PARTITION_BRIDGE; + + mSlopRatio = 0.25f; } LLAvatarBridge::LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp) - : LLVolumeBridge(drawablep, regionp) + : LLVolumeBridge(drawablep, regionp) { - mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; - mPartitionType = LLViewerRegion::PARTITION_AVATAR; + mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; + mPartitionType = LLViewerRegion::PARTITION_AVATAR; } LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp) - : LLVolumeBridge(drawablep, regionp) + : LLVolumeBridge(drawablep, regionp) { - mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV; - mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV; + mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV; + mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV; } void LLControlAVBridge::updateSpatialExtents() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE - LLSpatialGroup* root = (LLSpatialGroup*)mOctree->getListener(0); + LLSpatialGroup* root = (LLSpatialGroup*)mOctree->getListener(0); - bool rootWasDirty = root->isDirty(); + bool rootWasDirty = root->isDirty(); - super::updateSpatialExtents(); // root becomes non-dirty here + super::updateSpatialExtents(); // root becomes non-dirty here - // SL-18251 "On-screen animesh characters using pelvis offset animations - // disappear when root goes off-screen" - // - // Expand extents to include Control Avatar placed outside of the bounds + // SL-18251 "On-screen animesh characters using pelvis offset animations + // disappear when root goes off-screen" + // + // Expand extents to include Control Avatar placed outside of the bounds LLControlAvatar* controlAvatar = getVObj() ? getVObj()->getControlAvatar() : NULL; if (controlAvatar && controlAvatar->mDrawable && controlAvatar->mDrawable->getEntry() && (rootWasDirty || controlAvatar->mPlaying)) - { - root->expandExtents(controlAvatar->mDrawable->getSpatialExtents(), *mDrawable->getXform()); - } + { + root->expandExtents(controlAvatar->mDrawable->getSpatialExtents(), *mDrawable->getXform()); + } } bool can_batch_texture(LLFace* facep) { - if (facep->getTextureEntry()->getBumpmap()) - { //bump maps aren't worked into texture batching yet - return false; - } - - if (facep->getTextureEntry()->getMaterialParams().notNull()) - { //materials don't work with texture batching yet - return false; - } - - if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) - { //can't batch invisiprims - return false; - } - - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { //texture animation breaks batches - return false; - } - + if (facep->getTextureEntry()->getBumpmap()) + { //bump maps aren't worked into texture batching yet + return false; + } + + if (facep->getTextureEntry()->getMaterialParams().notNull()) + { //materials don't work with texture batching yet + return false; + } + + if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) + { //can't batch invisiprims + return false; + } + + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { //texture animation breaks batches + return false; + } + if (facep->getTextureEntry()->getGLTFRenderMaterial() != nullptr) { // PBR materials break indexed texture batching return false; } - return true; + return true; } const static U32 MAX_FACE_COUNT = 4096U; @@ -5181,27 +5181,27 @@ LLFace** LLVolumeGeometryManager::sPbrFaces[2] = { NULL }; LLFace** LLVolumeGeometryManager::sAlphaFaces[2] = { NULL }; LLVolumeGeometryManager::LLVolumeGeometryManager() - : LLGeometryManager() + : LLGeometryManager() { - llassert(sInstanceCount >= 0); - if (sInstanceCount == 0) - { - allocateFaces(MAX_FACE_COUNT); - } + llassert(sInstanceCount >= 0); + if (sInstanceCount == 0) + { + allocateFaces(MAX_FACE_COUNT); + } - ++sInstanceCount; + ++sInstanceCount; } LLVolumeGeometryManager::~LLVolumeGeometryManager() { - llassert(sInstanceCount > 0); - --sInstanceCount; + llassert(sInstanceCount > 0); + --sInstanceCount; - if (sInstanceCount <= 0) - { - freeFaces(); - sInstanceCount = 0; - } + if (sInstanceCount <= 0) + { + freeFaces(); + sInstanceCount = 0; + } } void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) @@ -5246,22 +5246,22 @@ void LLVolumeGeometryManager::freeFaces() void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - if ( type == LLRenderPass::PASS_ALPHA - && facep->getTextureEntry()->getMaterialParams().notNull() - && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT) - && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) - { - LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; - } + if ( type == LLRenderPass::PASS_ALPHA + && facep->getTextureEntry()->getMaterialParams().notNull() + && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT) + && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1) + { + LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; + } - bool selected = facep->getViewerObject()->isSelected(); + bool selected = facep->getViewerObject()->isSelected(); - if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) - { - return; - } + if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) + { + return; + } - LL_LABEL_VERTEX_BUFFER(facep->getVertexBuffer(), LLRenderPass::lookupPassName(type)); + LL_LABEL_VERTEX_BUFFER(facep->getVertexBuffer(), LLRenderPass::lookupPassName(type)); U32 passType = type; @@ -5273,66 +5273,66 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, // See LLRenderPass PASS_foo enum passType += 1; } - //add face to drawmap - LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[passType]; + //add face to drawmap + LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[passType]; - S32 idx = draw_vec.size()-1; + S32 idx = draw_vec.size()-1; - bool fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || - (type == LLRenderPass::PASS_INVISIBLE) || - (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || - (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || - (facep->getTextureEntry()->getFullbright()); - - if (!fullbright && - type != LLRenderPass::PASS_GLOW && + bool fullbright = (type == LLRenderPass::PASS_FULLBRIGHT) || + (type == LLRenderPass::PASS_INVISIBLE) || + (type == LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK) || + (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)) || + (facep->getTextureEntry()->getFullbright()); + + if (!fullbright && + type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) - { + { llassert(false); - LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; - return; - } + LL_WARNS() << "Non fullbright face has no normals!" << LL_ENDL; + return; + } - const LLMatrix4* tex_mat = NULL; - if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) - { - tex_mat = facep->mTextureMatrix; - } + const LLMatrix4* tex_mat = NULL; + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { + tex_mat = facep->mTextureMatrix; + } - const LLMatrix4* model_mat = NULL; + const LLMatrix4* model_mat = NULL; + + LLDrawable* drawable = facep->getDrawable(); - LLDrawable* drawable = facep->getDrawable(); - if (rigged) { // rigged meshes ignore their model matrix model_mat = nullptr; } - else if (drawable->isState(LLDrawable::ANIMATED_CHILD)) - { - model_mat = &drawable->getWorldMatrix(); - } - else if (drawable->isActive()) - { - model_mat = &drawable->getRenderMatrix(); - } - else - { - model_mat = &(drawable->getRegion()->mRenderMatrix); - } - - //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); + else if (drawable->isState(LLDrawable::ANIMATED_CHILD)) + { + model_mat = &drawable->getWorldMatrix(); + } + else if (drawable->isActive()) + { + model_mat = &drawable->getRenderMatrix(); + } + else + { + model_mat = &(drawable->getRegion()->mRenderMatrix); + } + + //drawable->getVObj()->setDebugText(llformat("%d", drawable->isState(LLDrawable::ANIMATED_CHILD))); const LLTextureEntry* te = facep->getTextureEntry(); - U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? te->getBumpmap() : 0; - U8 shiny = te->getShiny(); - - LLViewerTexture* tex = facep->getTexture(); + U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? te->getBumpmap() : 0; + U8 shiny = te->getShiny(); + + LLViewerTexture* tex = facep->getTexture(); - U8 index = facep->getTextureIndex(); + U8 index = facep->getTextureIndex(); LLMaterial* mat = nullptr; - + LLUUID mat_id; auto* gltf_mat = (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial(); @@ -5354,110 +5354,110 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } } - bool batchable = false; - - U32 shader_mask = 0xFFFFFFFF; //no shader - - if (mat) - { - BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) || (te->getColor().mV[3] < 0.999f) ? TRUE : FALSE; - if (type == LLRenderPass::PASS_ALPHA) - { - shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND, is_alpha); - } - else - { - shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT, is_alpha); - } - } - - if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0) - { - if (mat || gltf_mat || draw_vec[idx]->mMaterial) - { //can't batch textures when materials are present (yet) - batchable = false; - } - else if (index < draw_vec[idx]->mTextureList.size()) - { - if (draw_vec[idx]->mTextureList[index].isNull()) - { - batchable = true; - draw_vec[idx]->mTextureList[index] = tex; - } - else if (draw_vec[idx]->mTextureList[index] == tex) - { //this face's texture index can be used with this batch - batchable = true; - } - } - else - { //texture list can be expanded to fit this texture index - batchable = true; - } - } + bool batchable = false; + + U32 shader_mask = 0xFFFFFFFF; //no shader + + if (mat) + { + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) || (te->getColor().mV[3] < 0.999f) ? TRUE : FALSE; + if (type == LLRenderPass::PASS_ALPHA) + { + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND, is_alpha); + } + else + { + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT, is_alpha); + } + } + + if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0) + { + if (mat || gltf_mat || draw_vec[idx]->mMaterial) + { //can't batch textures when materials are present (yet) + batchable = false; + } + else if (index < draw_vec[idx]->mTextureList.size()) + { + if (draw_vec[idx]->mTextureList[index].isNull()) + { + batchable = true; + draw_vec[idx]->mTextureList[index] = tex; + } + else if (draw_vec[idx]->mTextureList[index] == tex) + { //this face's texture index can be used with this batch + batchable = true; + } + } + else + { //texture list can be expanded to fit this texture index + batchable = true; + } + } LLDrawInfo* info = idx >= 0 ? draw_vec[idx] : nullptr; - if (info && - info->mVertexBuffer == facep->getVertexBuffer() && - info->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && + if (info && + info->mVertexBuffer == facep->getVertexBuffer() && + info->mEnd == facep->getGeomIndex()-1 && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && #if LL_DARWIN - info->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && - info->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + info->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + info->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && #endif - info->mMaterialID == mat_id && - info->mFullbright == fullbright && - info->mBump == bump && - (!mat || (info->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different - info->mTextureMatrix == tex_mat && - info->mModelMatrix == model_mat && - info->mShaderMask == shader_mask && + info->mMaterialID == mat_id && + info->mFullbright == fullbright && + info->mBump == bump && + (!mat || (info->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different + info->mTextureMatrix == tex_mat && + info->mModelMatrix == model_mat && + info->mShaderMask == shader_mask && info->mAvatar == facep->mAvatar && info->getSkinHash() == facep->getSkinHash()) - { - info->mCount += facep->getIndicesCount(); - info->mEnd += facep->getGeomCount(); - - if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= info->mTextureList.size()) - { - info->mTextureList.resize(index+1); - info->mTextureList[index] = tex; - } - info->validate(); - } - else - { - U32 start = facep->getGeomIndex(); - U32 end = start + facep->getGeomCount()-1; - U32 offset = facep->getIndicesStart(); - U32 count = facep->getIndicesCount(); - LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, - facep->getVertexBuffer(), fullbright, bump); + { + info->mCount += facep->getIndicesCount(); + info->mEnd += facep->getGeomCount(); + + if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= info->mTextureList.size()) + { + info->mTextureList.resize(index+1); + info->mTextureList[index] = tex; + } + info->validate(); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLPointer draw_info = new LLDrawInfo(start,end,count,offset, tex, + facep->getVertexBuffer(), fullbright, bump); info = draw_info; - draw_vec.push_back(draw_info); - draw_info->mTextureMatrix = tex_mat; - draw_info->mModelMatrix = model_mat; - - draw_info->mBump = bump; - draw_info->mShiny = shiny; - - static const float alpha[4] = - { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - float spec = alpha[shiny & TEM_SHINY_MASK]; - LLVector4 specColor(spec, spec, spec, spec); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = spec; - draw_info->mSpecularMap = NULL; - draw_info->mMaterial = mat; + draw_vec.push_back(draw_info); + draw_info->mTextureMatrix = tex_mat; + draw_info->mModelMatrix = model_mat; + + draw_info->mBump = bump; + draw_info->mShiny = shiny; + + static const float alpha[4] = + { + 0.00f, + 0.25f, + 0.5f, + 0.75f + }; + float spec = alpha[shiny & TEM_SHINY_MASK]; + LLVector4 specColor(spec, spec, spec, spec); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = spec; + draw_info->mSpecularMap = NULL; + draw_info->mMaterial = mat; draw_info->mGLTFMaterial = gltf_mat; - draw_info->mShaderMask = shader_mask; + draw_info->mShaderMask = shader_mask; draw_info->mAvatar = facep->mAvatar; draw_info->mSkinInfo = facep->mSkinInfo; @@ -5467,58 +5467,58 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mMaterialID = mat_id; } else if (mat) - { - draw_info->mMaterialID = mat_id; - - // We have a material. Update our draw info accordingly. - - if (!mat->getSpecularID().isNull()) - { - LLVector4 specColor; - specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); - specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); - specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); - specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); - draw_info->mSpecColor = specColor; - draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); - draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); - } - - draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); - draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); - draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); - } - else - { - if (type == LLRenderPass::PASS_GRASS) - { - draw_info->mAlphaMaskCutoff = 0.5f; - } - else - { - draw_info->mAlphaMaskCutoff = 0.33f; - } - } - - // if (type == LLRenderPass::PASS_ALPHA) // always populate the draw_info ptr - { //for alpha sorting - facep->setDrawInfo(draw_info); - } - - if (index < FACE_DO_NOT_BATCH_TEXTURES) - { //initialize texture list for texture batching - draw_info->mTextureList.resize(index+1); - draw_info->mTextureList[index] = tex; - } - draw_info->validate(); - } + { + draw_info->mMaterialID = mat_id; + + // We have a material. Update our draw info accordingly. + + if (!mat->getSpecularID().isNull()) + { + LLVector4 specColor; + specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); + specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); + specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); + specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); + draw_info->mSpecColor = specColor; + draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); + draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); + } + + draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); + draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); + draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); + } + else + { + if (type == LLRenderPass::PASS_GRASS) + { + draw_info->mAlphaMaskCutoff = 0.5f; + } + else + { + draw_info->mAlphaMaskCutoff = 0.33f; + } + } + + // if (type == LLRenderPass::PASS_ALPHA) // always populate the draw_info ptr + { //for alpha sorting + facep->setDrawInfo(draw_info); + } + + if (index < FACE_DO_NOT_BATCH_TEXTURES) + { //initialize texture list for texture batching + draw_info->mTextureList.resize(index+1); + draw_info->mTextureList[index] = tex; + } + draw_info->validate(); + } llassert(info->mGLTFMaterial == nullptr || (info->mVertexBuffer->getTypeMask() & LLVertexBuffer::MAP_TANGENT) != 0); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR || info->mGLTFMaterial != nullptr); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_RIGGED || info->mGLTFMaterial != nullptr); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK || info->mGLTFMaterial != nullptr); llassert(type != LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED || info->mGLTFMaterial != nullptr); - + llassert(type != LLRenderPass::PASS_BUMP || (info->mVertexBuffer->getTypeMask() & LLVertexBuffer::MAP_TANGENT) != 0); llassert(type != LLRenderPass::PASS_NORMSPEC || info->mNormalMap.notNull()); llassert(type != LLRenderPass::PASS_SPECMAP || (info->mVertexBuffer->getTypeMask() & LLVertexBuffer::MAP_TEXCOORD2) != 0); @@ -5561,104 +5561,104 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) return; } - if (group->changeLOD()) - { - group->mLastUpdateDistance = group->mDistance; - } + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + } + + group->mLastUpdateViewAngle = group->mViewAngle; - group->mLastUpdateViewAngle = group->mViewAngle; + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) + { + if (group->hasState(LLSpatialGroup::MESH_DIRTY)) + { + rebuildMesh(group); + } + return; + } - if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) - { - if (group->hasState(LLSpatialGroup::MESH_DIRTY)) - { - rebuildMesh(group); - } - return; - } + group->mBuilt = 1.f; - group->mBuilt = 1.f; - - LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); LLViewerObject *vobj = NULL; LLVOVolume *vol_obj = NULL; - if (bridge) - { + if (bridge) + { vobj = bridge->mDrawable->getVObj(); vol_obj = dynamic_cast(vobj); - } + } if (vol_obj) { vol_obj->updateVisualComplexity(); } - group->mGeometryBytes = 0; - group->mSurfaceArea = 0; - - //cache object box size since it might be used for determining visibility - const LLVector4a* bounds = group->getObjectBounds(); - group->mObjectBoxSize = bounds[1].getLength3().getF32(); + group->mGeometryBytes = 0; + group->mSurfaceArea = 0; + + //cache object box size since it might be used for determining visibility + const LLVector4a* bounds = group->getObjectBounds(); + group->mObjectBoxSize = bounds[1].getLength3().getF32(); - group->clearDrawMap(); + group->clearDrawMap(); U32 fullbright_count[2] = { 0 }; - U32 bump_count[2] = { 0 }; - U32 simple_count[2] = { 0 }; - U32 alpha_count[2] = { 0 }; - U32 norm_count[2] = { 0 }; - U32 spec_count[2] = { 0 }; - U32 normspec_count[2] = { 0 }; - U32 pbr_count[2] = { 0 }; - - static LLCachedControl max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); - static LLCachedControl max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536); - U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - U32 max_total = (max_node_size * 1024) / LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); - - U32 cur_total = 0; - - bool emissive = false; - - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. + U32 bump_count[2] = { 0 }; + U32 simple_count[2] = { 0 }; + U32 alpha_count[2] = { 0 }; + U32 norm_count[2] = { 0 }; + U32 spec_count[2] = { 0 }; + U32 normspec_count[2] = { 0 }; + U32 pbr_count[2] = { 0 }; + + static LLCachedControl max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); + static LLCachedControl max_node_size(gSavedSettings, "RenderMaxNodeSize", 65536); + U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + U32 max_total = (max_node_size * 1024) / LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); + + U32 cur_total = 0; + + bool emissive = false; + + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. #if 0 - bool pelvisGotSet = false; + bool pelvisGotSet = false; #endif - { + { LL_PROFILE_ZONE_NAMED("rebuildGeom - face list"); - //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); + //get all the faces into a list + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) - { - continue; - } - - LLVOVolume* vobj = drawablep->getVOVolume(); - - if (!vobj || vobj->isDead()) - { - continue; - } + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - // HACK -- brute force this check every time a drawable gets rebuilt - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { - vobj->updateTEMaterialTextures(i); + continue; } - // apply any pending material overrides - gGLTFMaterialList.applyQueuedOverrides(vobj); + LLVOVolume* vobj = drawablep->getVOVolume(); - std::string vobj_name = llformat("Vol%p", vobj); + if (!vobj || vobj->isDead()) + { + continue; + } + + // HACK -- brute force this check every time a drawable gets rebuilt + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + vobj->updateTEMaterialTextures(i); + } + + // apply any pending material overrides + gGLTFMaterialList.applyQueuedOverrides(vobj); + + std::string vobj_name = llformat("Vol%p", vobj); bool is_mesh = vobj->isMesh(); if (is_mesh) @@ -5677,24 +5677,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } - LLVolume* volume = vobj->getVolume(); - if (volume) - { - const LLVector3& scale = vobj->getScale(); - group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); - } + LLVolume* volume = vobj->getVolume(); + if (volume) + { + const LLVector3& scale = vobj->getScale(); + group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]); + } + - F32 est_tris = vobj->getEstTrianglesMax(); vobj->updateControlAvatar(); - + LL_DEBUGS("AnimatedObjectsLinkset") << vobj_name << " rebuilding, isAttachment: " << (U32) vobj->isAttachment() << " is_mesh " << is_mesh << " est_tris " << est_tris << " is_animated " << vobj->isAnimatedObject() - << " can_animate " << vobj->canBeAnimatedObject() - << " cav " << vobj->getControlAvatar() + << " can_animate " << vobj->canBeAnimatedObject() + << " cav " << vobj->getControlAvatar() << " lod " << vobj->getLOD() << " drawable rigged " << (drawablep->isState(LLDrawable::RIGGED)) << " drawable state " << drawablep->getState() @@ -5702,11 +5702,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) << " frame " << LLFrameTimer::getFrameCount() << LL_ENDL; - llassert_always(vobj); - vobj->updateTextureVirtualSize(true); - vobj->preRebuild(); + llassert_always(vobj); + vobj->updateTextureVirtualSize(true); + vobj->preRebuild(); - drawablep->clearState(LLDrawable::HAS_ALPHA); + drawablep->clearState(LLDrawable::HAS_ALPHA); LLVOAvatar* avatar = nullptr; const LLMeshSkinInfo* skinInfo = nullptr; @@ -5732,23 +5732,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) avatar->addAttachmentOverridesForObject(vobj, NULL, false); } - // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); + // Standard rigged mesh attachments: + bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to // exclude static objects in animated object linksets. - rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && + rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); - bool any_rigged_face = false; + bool any_rigged_face = false; - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - LLFace* facep = drawablep->getFace(i); - if (!facep) - { - continue; - } + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + LLFace* facep = drawablep->getFace(i); + if (!facep) + { + continue; + } #if 0 #if LL_RELEASE_WITH_DEBUG_INFO const LLUUID pbr_id( "49c88210-7238-2a6b-70ac-92d4f35963cf" ); @@ -5762,12 +5762,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) bool is_pbr = gltf_mat != nullptr; #endif - //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); - - //sum up face verts and indices - drawablep->updateFaceSize(i); + //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); + + //sum up face verts and indices + drawablep->updateFaceSize(i); if (rigged) { @@ -5784,7 +5784,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) else { if (facep->isState(LLFace::RIGGED)) - { + { //face is not rigged but used to be, remove from rigged face pool LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); if (pool) @@ -5797,84 +5797,84 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } - if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) - { - facep->clearVertexBuffer(); - continue; - } + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) + { + facep->clearVertexBuffer(); + continue; + } - if (facep->hasGeometry() && + if (facep->hasGeometry() && (rigged || // <-- HACK FIXME -- getPixelArea might be incorrect for rigged objects facep->getPixelArea() > FORCE_CULL_AREA)) // <-- don't render tiny faces - { + { cur_total += facep->getGeomCount(); - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerTexture* tex = facep->getTexture(); + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerTexture* tex = facep->getTexture(); - if (te->getGlow() > 0.f) - { - emissive = true; - } + if (te->getGlow() > 0.f) + { + emissive = true; + } - if (facep->isState(LLFace::TEXTURE_ANIM)) - { - if (!vobj->mTexAnimMode) - { - facep->clearState(LLFace::TEXTURE_ANIM); - } - } + if (facep->isState(LLFace::TEXTURE_ANIM)) + { + if (!vobj->mTexAnimMode) + { + facep->clearState(LLFace::TEXTURE_ANIM); + } + } - BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); - U32 type = gPipeline.getPoolTypeFromTE(te, tex); + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); if (is_pbr && gltf_mat && gltf_mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_BLEND) { type = LLDrawPool::POOL_GLTF_PBR; } else - if (type != LLDrawPool::POOL_ALPHA && force_simple) - { - type = LLDrawPool::POOL_SIMPLE; - } - facep->setPoolType(type); - - if (vobj->isHUDAttachment() && !is_pbr) - { - facep->setState(LLFace::FULLBRIGHT); - } - - if (vobj->mTextureAnimp && vobj->mTexAnimMode) - { - if (vobj->mTextureAnimp->mFace <= -1) - { - S32 face; - for (face = 0; face < vobj->getNumTEs(); face++) - { - LLFace * facep = drawablep->getFace(face); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } - else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) - { - LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); - if (facep) - { - facep->setState(LLFace::TEXTURE_ANIM); - } - } - } - - if (type == LLDrawPool::POOL_ALPHA) - { - if (facep->canRenderAsMask()) - { //can be treated as alpha mask + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); + + if (vobj->isHUDAttachment() && !is_pbr) + { + facep->setState(LLFace::FULLBRIGHT); + } + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + LLFace * facep = drawablep->getFace(face); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + LLFace * facep = drawablep->getFace(vobj->mTextureAnimp->mFace); + if (facep) + { + facep->setState(LLFace::TEXTURE_ANIM); + } + } + } + + if (type == LLDrawPool::POOL_ALPHA) + { + if (facep->canRenderAsMask()) + { //can be treated as alpha mask add_face(sSimpleFaces, simple_count, facep); - } - else - { + } + else + { F32 alpha; if (is_pbr) { @@ -5885,33 +5885,33 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) alpha = te->getColor().mV[3]; } if (alpha > 0.f || te->getGlow() > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - add_face(sAlphaFaces, alpha_count, facep); - } - else if (LLDrawPoolAlpha::sShowDebugAlpha || - (gPipeline.sRenderHighlight && !drawablep->getParent() && - //only root objects are highlighted with red color in this case - drawablep->getVObj() && drawablep->getVObj()->flagScripted() && - (LLPipeline::getRenderScriptedBeacons() || - (LLPipeline::getRenderScriptedTouchBeacons() && drawablep->getVObj()->flagHandleTouch())))) - { //draw the transparent face for debugging purposes using a custom texture - add_face(sAlphaFaces, alpha_count, facep); - } - } - } - else - { - if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) - { - facep->mLastUpdateTime = gFrameTimeSeconds; - } - - { + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + add_face(sAlphaFaces, alpha_count, facep); + } + else if (LLDrawPoolAlpha::sShowDebugAlpha || + (gPipeline.sRenderHighlight && !drawablep->getParent() && + //only root objects are highlighted with red color in this case + drawablep->getVObj() && drawablep->getVObj()->flagScripted() && + (LLPipeline::getRenderScriptedBeacons() || + (LLPipeline::getRenderScriptedTouchBeacons() && drawablep->getVObj()->flagHandleTouch())))) + { //draw the transparent face for debugging purposes using a custom texture + add_face(sAlphaFaces, alpha_count, facep); + } + } + } + else + { + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; + } + + { LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); - if (gltf_mat != nullptr || (te->getMaterialParams().notNull())) - { + if (gltf_mat != nullptr || (te->getMaterialParams().notNull())) + { if (gltf_mat != nullptr) { add_face(sPbrFaces, pbr_count, facep); @@ -5940,91 +5940,91 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) add_face(sSimpleFaces, simple_count, facep); } } - } - else if (te->getBumpmap()) - { //needs normal + tangent + } + else if (te->getBumpmap()) + { //needs normal + tangent add_face(sBumpFaces, bump_count, facep); - } - else if (te->getShiny() || !te->getFullbright()) - { //needs normal + } + else if (te->getShiny() || !te->getFullbright()) + { //needs normal add_face(sSimpleFaces, simple_count, facep); - } - else - { //doesn't need normal - facep->setState(LLFace::FULLBRIGHT); + } + else + { //doesn't need normal + facep->setState(LLFace::FULLBRIGHT); add_face(sFullbrightFaces, fullbright_count, facep); - } - } - } - } - else - { //face has no renderable geometry - facep->clearVertexBuffer(); - } - } - - if (any_rigged_face) - { - if (!drawablep->isState(LLDrawable::RIGGED)) - { - drawablep->setState(LLDrawable::RIGGED); + } + } + } + } + else + { //face has no renderable geometry + facep->clearVertexBuffer(); + } + } + + if (any_rigged_face) + { + if (!drawablep->isState(LLDrawable::RIGGED)) + { + drawablep->setState(LLDrawable::RIGGED); LLDrawable* root = drawablep->getRoot(); if (root != drawablep) { root->setState(LLDrawable::RIGGED_CHILD); } - //first time this is drawable is being marked as rigged, - // do another LoD update to use avatar bounding box - vobj->updateLOD(); - } - } - else - { - drawablep->clearState(LLDrawable::RIGGED); + //first time this is drawable is being marked as rigged, + // do another LoD update to use avatar bounding box + vobj->updateLOD(); + } + } + else + { + drawablep->clearState(LLDrawable::RIGGED); vobj->updateRiggedVolume(false); - } - } - } - - //PROCESS NON-ALPHA FACES - U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO - U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - - U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; - U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; - U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; - - U32 pbr_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TANGENT; - - if (emissive) - { //emissive faces are present, include emissive byte to preserve batching - simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; - bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; - norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; - normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; - spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; + } + } + } + + //PROCESS NON-ALPHA FACES + U32 simple_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 alpha_mask = simple_mask | 0x80000000; //hack to give alpha verts their own VBO + U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; + + U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TANGENT; + U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2; + U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2; + + U32 pbr_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TANGENT; + + if (emissive) + { //emissive faces are present, include emissive byte to preserve batching + simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE; + bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE; + norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE; + normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE; + spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE; pbr_mask = pbr_mask | LLVertexBuffer::MAP_EMISSIVE; - } + } - BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; // add extra vertex data for deferred rendering (not necessarily for batching textures) - if (batch_textures) - { - bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; - simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; - fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; - } + if (batch_textures) + { + bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT; + simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2; + fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX; + } - group->mGeometryBytes = 0; + group->mGeometryBytes = 0; - U32 geometryBytes = 0; + U32 geometryBytes = 0; // generate render batches for static geometry U32 extra_mask = LLVertexBuffer::MAP_TEXTURE_INDEX; @@ -6046,70 +6046,70 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) rigged = TRUE; } - group->mGeometryBytes = geometryBytes; + group->mGeometryBytes = geometryBytes; - { - //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if(drawablep) - { + { + //drawables have been rebuilt, clear rebuild status + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(drawablep) + { drawablep->clearState(LLDrawable::REBUILD_ALL); } } - } + } - group->mLastUpdateTime = gFrameTimeSeconds; - group->mBuilt = 1.f; - group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); + group->mLastUpdateTime = gFrameTimeSeconds; + group->mBuilt = 1.f; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY); } void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - llassert(group); - if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) - { - { + llassert(group); + if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) + { + { LL_PROFILE_ZONE_NAMED("rebuildMesh - gen draw info"); group->mBuilt = 1.f; - - const U32 MAX_BUFFER_COUNT = 4096; - LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; - U32 buffer_count = 0; + const U32 MAX_BUFFER_COUNT = 4096; + LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; + + U32 buffer_count = 0; for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL)) - { - LLVOVolume* vobj = drawablep->getVOVolume(); - - if (!vobj) continue; - - if (vobj->isNoLOD()) continue; - - vobj->preRebuild(); - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } - - LLVolume* volume = vobj->getVolume(); - if (!volume) continue; - for (S32 i = 0; i < drawablep->getNumFaces(); ++i) - { - LLFace* face = drawablep->getFace(i); - if (face) - { - LLVertexBuffer* buff = face->getVertexBuffer(); - if (buff) - { + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL)) + { + LLVOVolume* vobj = drawablep->getVOVolume(); + + if (!vobj) continue; + + if (vobj->isNoLOD()) continue; + + vobj->preRebuild(); + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + + LLVolume* volume = vobj->getVolume(); + if (!volume) continue; + for (S32 i = 0; i < drawablep->getNumFaces(); ++i) + { + LLFace* face = drawablep->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { if (!face->getGeometryVolume(*volume, // volume face->getTEOffset(), // face_index vobj->getRelativeXform(), // mat_vert_in @@ -6124,72 +6124,72 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) } buff->unmapBuffer(); - } - } - } + } + } + } - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(); - } + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(); + } - drawablep->clearState(LLDrawable::REBUILD_ALL); - } - } + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + } - { + { LL_PROFILE_ZONE_NAMED("rebuildMesh - flush"); - for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) - { - (*iter)->unmapBuffer(); - } - - // don't forget alpha - if(group != NULL && - !group->mVertexBuffer.isNull()) - { - group->mVertexBuffer->unmapBuffer(); - } - } - - group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); - } - } + for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) + { + (*iter)->unmapBuffer(); + } + + // don't forget alpha + if(group != NULL && + !group->mVertexBuffer.isNull()) + { + group->mVertexBuffer->unmapBuffer(); + } + } + + group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); + } + } } struct CompareBatchBreaker { - bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) - { - const LLTextureEntry* lte = lhs->getTextureEntry(); - const LLTextureEntry* rte = rhs->getTextureEntry(); + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + const LLTextureEntry* lte = lhs->getTextureEntry(); + const LLTextureEntry* rte = rhs->getTextureEntry(); if (lte->getBumpmap() != rte->getBumpmap()) - { - return lte->getBumpmap() < rte->getBumpmap(); - } - else if (lte->getFullbright() != rte->getFullbright()) - { - return lte->getFullbright() < rte->getFullbright(); - } + { + return lte->getBumpmap() < rte->getBumpmap(); + } + else if (lte->getFullbright() != rte->getFullbright()) + { + return lte->getFullbright() < rte->getFullbright(); + } else if (lte->getMaterialID() != rte->getMaterialID()) { return lte->getMaterialID() < rte->getMaterialID(); } - else if (lte->getShiny() != rte->getShiny()) - { - return lte->getShiny() < rte->getShiny(); - } + else if (lte->getShiny() != rte->getShiny()) + { + return lte->getShiny() < rte->getShiny(); + } else if (lhs->getTexture() != rhs->getTexture()) - { - return lhs->getTexture() < rhs->getTexture(); - } - else + { + return lhs->getTexture() < rhs->getTexture(); + } + else { // all else being equal, maintain consistent draw order return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex(); } - } + } }; struct CompareBatchBreakerRigged @@ -6217,16 +6217,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; - U32 geometryBytes = 0; - - //calculate maximum number of vertices to store in a single buffer - static LLCachedControl max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); - U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); - max_vertices = llmin(max_vertices, (U32) 65535); + U32 geometryBytes = 0; + + //calculate maximum number of vertices to store in a single buffer + static LLCachedControl max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512); + U32 max_vertices = (max_vbo_size * 1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + max_vertices = llmin(max_vertices, (U32) 65535); - { + { LL_PROFILE_ZONE_NAMED("genDrawInfo - sort"); - + if (rigged) { if (!distance_sort) // <--- alpha "sort" rigged faces by maintaining original draw order @@ -6240,277 +6240,277 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace //sort faces by things that break batches, not including avatar and mesh id std::sort(faces, faces + face_count, CompareBatchBreaker()); } - else - { - //sort faces by distance - std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); - } - } - - bool hud_group = group->isHUDGroup() ; - LLFace** face_iter = faces; - LLFace** end_faces = faces+face_count; - - LLSpatialGroup::buffer_map_t buffer_map; - - LLViewerTexture* last_tex = NULL; - - S32 texture_index_channels = LLGLSLShader::sIndexedTextureChannels; - - bool flexi = false; - - while (face_iter != end_faces) - { - //pull off next face - LLFace* facep = *face_iter; - LLViewerTexture* tex = facep->getTexture(); + else + { + //sort faces by distance + std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater()); + } + } + + bool hud_group = group->isHUDGroup() ; + LLFace** face_iter = faces; + LLFace** end_faces = faces+face_count; + + LLSpatialGroup::buffer_map_t buffer_map; + + LLViewerTexture* last_tex = NULL; + + S32 texture_index_channels = LLGLSLShader::sIndexedTextureChannels; + + bool flexi = false; + + while (face_iter != end_faces) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerTexture* tex = facep->getTexture(); const LLTextureEntry* te = facep->getTextureEntry(); - LLMaterialPtr mat = te->getMaterialParams(); + LLMaterialPtr mat = te->getMaterialParams(); LLMaterialID matId = te->getMaterialID(); - if (distance_sort) - { - tex = NULL; - } + if (distance_sort) + { + tex = NULL; + } + + if (last_tex != tex) + { + last_tex = tex; + } + + bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); - if (last_tex != tex) - { - last_tex = tex; - } + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); - bool bake_sunlight = LLPipeline::sBakeSunlight && facep->getDrawable()->isStatic(); + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - U32 index_count = facep->getIndicesCount(); - U32 geom_count = facep->getGeomCount(); + //sum up vertices needed for this render batch + LLFace** i = face_iter; + ++i; - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + const U32 MAX_TEXTURE_COUNT = 32; + LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; - //sum up vertices needed for this render batch - LLFace** i = face_iter; - ++i; - - const U32 MAX_TEXTURE_COUNT = 32; - LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; - - U32 texture_count = 0; + U32 texture_count = 0; - { + { LL_PROFILE_ZONE_NAMED("genDrawInfo - face size"); - if (batch_textures) - { - U8 cur_tex = 0; - facep->setTextureIndex(cur_tex); - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } - - if (can_batch_texture(facep)) - { //populate texture_list with any textures that can be batched - //move i to the next unbatchable face - while (i != end_faces) - { - facep = *i; - - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - facep->setTextureIndex(0); - break; - } - - if (facep->getTexture() != tex) - { - if (distance_sort) - { //textures might be out of order, see if texture exists in current batch - bool found = false; - for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) - { - if (facep->getTexture() == texture_list[tex_idx]) - { - cur_tex = tex_idx; - found = true; - break; - } - } - - if (!found) - { - cur_tex = texture_count; - } - } - else - { - cur_tex++; - } - - if (cur_tex >= texture_index_channels) - { //cut batches when index channels are depleted - break; - } - - tex = facep->getTexture(); - - if (texture_count < MAX_TEXTURE_COUNT) - { - texture_list[texture_count++] = tex; - } - } - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } - - ++i; - - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); - - facep->setTextureIndex(cur_tex); - } - } - else - { - facep->setTextureIndex(0); - } - - tex = texture_list[0]; - } - else - { - while (i != end_faces && - (LLPipeline::sTextureBindTest || - (distance_sort || - ((*i)->getTexture() == tex)))) - { - facep = *i; + if (batch_textures) + { + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } + + if (can_batch_texture(facep)) + { //populate texture_list with any textures that can be batched + //move i to the next unbatchable face + while (i != end_faces) + { + facep = *i; + + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + facep->setTextureIndex(0); + break; + } + + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx) + { + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } + } + + if (!found) + { + cur_tex = texture_count; + } + } + else + { + cur_tex++; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + if (texture_count < MAX_TEXTURE_COUNT) + { + texture_list[texture_count++] = tex; + } + } + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + + facep->setTextureIndex(cur_tex); + } + } + else + { + facep->setTextureIndex(0); + } + + tex = texture_list[0]; + } + else + { + while (i != end_faces && + (LLPipeline::sTextureBindTest || + (distance_sort || + ((*i)->getTexture() == tex)))) + { + facep = *i; const LLTextureEntry* nextTe = facep->getTextureEntry(); if (nextTe->getMaterialID() != matId) { break; } - //face has no texture index - facep->mDrawInfo = NULL; - facep->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES); + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES); - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut batches on geom count too big - break; - } + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); - flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); - } - } - } + flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); + } + } + } - //create vertex buffer - LLPointer buffer; + //create vertex buffer + LLPointer buffer; - { + { LL_PROFILE_ZONE_NAMED("genDrawInfo - allocate"); - buffer = new LLVertexBuffer(mask); - if(!buffer->allocateBuffer(geom_count, index_count)) - { - LL_WARNS() << "Failed to allocate group Vertex Buffer to " - << geom_count << " vertices and " - << index_count << " indices" << LL_ENDL; - buffer = NULL; - } - } - - if (buffer) - { - geometryBytes += buffer->getSize() + buffer->getIndicesSize(); - buffer_map[mask][*face_iter].push_back(buffer); - } - - //add face geometry - - U32 indices_index = 0; - U16 index_offset = 0; + buffer = new LLVertexBuffer(mask); + if(!buffer->allocateBuffer(geom_count, index_count)) + { + LL_WARNS() << "Failed to allocate group Vertex Buffer to " + << geom_count << " vertices and " + << index_count << " indices" << LL_ENDL; + buffer = NULL; + } + } + + if (buffer) + { + geometryBytes += buffer->getSize() + buffer->getIndicesSize(); + buffer_map[mask][*face_iter].push_back(buffer); + } + + //add face geometry + + U32 indices_index = 0; + U16 index_offset = 0; while (face_iter < i) - { - //update face indices for new buffer - facep = *face_iter; - - if (buffer.isNull()) - { - // Bulk allocation failed - facep->setVertexBuffer(buffer); - facep->setSize(0, 0); // mark as no geometry - ++face_iter; - continue; - } - facep->setIndicesIndex(indices_index); - facep->setGeomIndex(index_offset); - facep->setVertexBuffer(buffer); - - if (batch_textures && facep->getTextureIndex() == FACE_DO_NOT_BATCH_TEXTURES) - { - LL_ERRS() << "Invalid texture index." << LL_ENDL; - } - - { - //for debugging, set last time face was updated vs moved - facep->updateRebuildFlags(); - - { //copy face geometry into vertex buffer - LLDrawable* drawablep = facep->getDrawable(); - LLVOVolume* vobj = drawablep->getVOVolume(); - LLVolume* volume = vobj->getVolume(); - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(true); - } - - U32 te_idx = facep->getTEOffset(); - - if (!facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) - { - LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; - } - - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { - vobj->updateRelativeXform(false); - } - } - } - - index_offset += facep->getGeomCount(); - indices_index += facep->getIndicesCount(); - - //append face to appropriate render batch - - BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; - BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); - if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) - { //paranoia check to make sure GL doesn't try to read non-existant normals - fullbright = TRUE; - } + { + //update face indices for new buffer + facep = *face_iter; + + if (buffer.isNull()) + { + // Bulk allocation failed + facep->setVertexBuffer(buffer); + facep->setSize(0, 0); // mark as no geometry + ++face_iter; + continue; + } + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + + if (batch_textures && facep->getTextureIndex() == FACE_DO_NOT_BATCH_TEXTURES) + { + LL_ERRS() << "Invalid texture index." << LL_ENDL; + } + + { + //for debugging, set last time face was updated vs moved + facep->updateRebuildFlags(); + + { //copy face geometry into vertex buffer + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(true); + } + + U32 te_idx = facep->getTEOffset(); + + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + LL_WARNS() << "Failed to get geometry for face!" << LL_ENDL; + } + + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { + vobj->updateRelativeXform(false); + } + } + } + + index_offset += facep->getGeomCount(); + indices_index += facep->getIndicesCount(); + + //append face to appropriate render batch + + BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) + { //paranoia check to make sure GL doesn't try to read non-existant normals + fullbright = TRUE; + } const LLTextureEntry* te = facep->getTextureEntry(); LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); - if (hud_group && gltf_mat == nullptr) - { //all hud attachments are fullbright - fullbright = TRUE; - } - - tex = facep->getTexture(); + if (hud_group && gltf_mat == nullptr) + { //all hud attachments are fullbright + fullbright = TRUE; + } + + tex = facep->getTexture(); - BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; LLMaterial* mat = nullptr; bool can_be_shiny = false; @@ -6530,8 +6530,8 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } F32 blinn_phong_alpha = te->getColor().mV[3]; - bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); - bool blinn_phong_opaque = blinn_phong_alpha >= 0.999f; + bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull()); + bool blinn_phong_opaque = blinn_phong_alpha >= 0.999f; bool blinn_phong_transparent = blinn_phong_alpha < 0.999f; if (!gltf_mat) @@ -6539,9 +6539,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace is_alpha = (is_alpha || blinn_phong_transparent) ? TRUE : FALSE; } - if (gltf_mat || (mat && !hud_group)) - { - bool material_pass = false; + if (gltf_mat || (mat && !hud_group)) + { + bool material_pass = false; if (gltf_mat) { // all other parameters ignored if gltf material is present @@ -6559,82 +6559,82 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace } } else - // do NOT use 'fullbright' for this logic or you risk sending - // things without normals down the materials pipeline and will - // render poorly if not crash NORSPEC-240,314 - // - if (te->getFullbright()) - { - if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - if (blinn_phong_opaque) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (is_alpha) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else - { - if (mat->getEnvironmentIntensity() > 0 || te->getShiny() > 0) - { - material_pass = true; - } - else - { + // do NOT use 'fullbright' for this logic or you risk sending + // things without normals down the materials pipeline and will + // render poorly if not crash NORSPEC-240,314 + // + if (te->getFullbright()) + { + if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + if (blinn_phong_opaque) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (is_alpha) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else + { + if (mat->getEnvironmentIntensity() > 0 || te->getShiny() > 0) + { + material_pass = true; + } + else + { if (blinn_phong_opaque) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); } else { registerFace(group, facep, LLRenderPass::PASS_ALPHA); } - } - } - } - else if (blinn_phong_transparent) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (use_legacy_bump) - { + } + } + } + else if (blinn_phong_transparent) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (use_legacy_bump) + { llassert(mask & LLVertexBuffer::MAP_TANGENT); - // we have a material AND legacy bump settings, but no normal map - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { - material_pass = true; - } - - if (material_pass) - { - static const U32 pass[] = - { - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, - LLRenderPass::PASS_MATERIAL_ALPHA_MASK, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, - LLRenderPass::PASS_SPECMAP_MASK, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, - LLRenderPass::PASS_NORMMAP_MASK, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, - LLRenderPass::PASS_NORMSPEC_MASK, - LLRenderPass::PASS_NORMSPEC_EMISSIVE, - }; + // we have a material AND legacy bump settings, but no normal map + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { + material_pass = true; + } + + if (material_pass) + { + static const U32 pass[] = + { + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA, + LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND, + LLRenderPass::PASS_SPECMAP_MASK, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND, + LLRenderPass::PASS_NORMMAP_MASK, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND, + LLRenderPass::PASS_NORMSPEC_MASK, + LLRenderPass::PASS_NORMSPEC_EMISSIVE, + }; U32 alpha_mode = mat->getDiffuseAlphaMode(); if (!distance_sort && alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) @@ -6645,180 +6645,180 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace U32 vb_mask = facep->getVertexBuffer()->getTypeMask(); - // HACK - this should also never happen, but sometimes we get here and the material thinks it has a specmap now + // HACK - this should also never happen, but sometimes we get here and the material thinks it has a specmap now // even though it didn't appear to have a specmap when the face was added to the list of faces if ((mask & 0x4) && !(vb_mask & LLVertexBuffer::MAP_TEXCOORD2)) { mask &= ~0x4; } - llassert(mask < sizeof(pass)/sizeof(U32)); + llassert(mask < sizeof(pass)/sizeof(U32)); - mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); + mask = llmin(mask, (U32)(sizeof(pass)/sizeof(U32)-1)); // if this is going into alpha pool, distance sort MUST be true llassert(pass[mask] == LLRenderPass::PASS_ALPHA ? distance_sort : true); - registerFace(group, facep, pass[mask]); - } - } - else if (mat) - { - U8 mode = mat->getDiffuseAlphaMode(); + registerFace(group, facep, pass[mask]); + } + } + else if (mat) + { + U8 mode = mat->getDiffuseAlphaMode(); is_alpha = (is_alpha || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)); - if (is_alpha) - { - mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; - } - - if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); - } - else if (is_alpha ) - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - else if (gPipeline.shadersLoaded() - && te->getShiny() - && can_be_shiny) - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); - } - else - { - registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); - } - } - else if (is_alpha) - { - // can we safely treat this as an alpha mask? - if (facep->getFaceColor().mV[3] <= 0.f) - { //100% transparent, don't render unless we're highlighting transparent - registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); - } - else if (facep->canRenderAsMask() && !hud_group) - { - if (te->getFullbright() || LLPipeline::sNoAlpha) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - } - else - { - registerFace(group, facep, LLRenderPass::PASS_ALPHA); - } - } - else if (gPipeline.shadersLoaded() - && te->getShiny() - && can_be_shiny) - { //shiny - if (tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (!hud_group) - { //deferred rendering - if (te->getFullbright()) - { //register in post deferred fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - if (te->getBumpmap()) - { //register in post deferred bump pass - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else if (use_legacy_bump) - { //register in deferred bump pass + if (is_alpha) + { + mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND; + } + + if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK); + } + else if (is_alpha ) + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + else if (gPipeline.shadersLoaded() + && te->getShiny() + && can_be_shiny) + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_SHINY : LLRenderPass::PASS_SHINY); + } + else + { + registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT : LLRenderPass::PASS_SIMPLE); + } + } + else if (is_alpha) + { + // can we safely treat this as an alpha mask? + if (facep->getFaceColor().mV[3] <= 0.f) + { //100% transparent, don't render unless we're highlighting transparent + registerFace(group, facep, LLRenderPass::PASS_ALPHA_INVISIBLE); + } + else if (facep->canRenderAsMask() && !hud_group) + { + if (te->getFullbright() || LLPipeline::sNoAlpha) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + } + else + { + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + } + else if (gPipeline.shadersLoaded() + && te->getShiny() + && can_be_shiny) + { //shiny + if (tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim+shiny + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (!hud_group) + { //deferred rendering + if (te->getFullbright()) + { //register in post deferred fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + if (te->getBumpmap()) + { //register in post deferred bump pass + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else if (use_legacy_bump) + { //register in deferred bump pass llassert(mask& LLVertexBuffer::MAP_TANGENT); - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //register in deferred simple pass (deferred simple includes shiny) - llassert(mask & LLVertexBuffer::MAP_NORMAL); - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - else if (fullbright) - { //not deferred, register in standard fullbright shiny pass - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); - } - else - { //not deferred or fullbright, register in standard shiny pass - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - else - { //not alpha and not shiny - if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) - { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); - } - else if (fullbright || bake_sunlight) - { //fullbright - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - } - if (!hud_group && use_legacy_bump) - { //if this is the deferred render and a bump map is present, register in post deferred bump - registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); - } - } - else - { - if (use_legacy_bump) - { //non-shiny or fullbright deferred bump + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //register in deferred simple pass (deferred simple includes shiny) + llassert(mask & LLVertexBuffer::MAP_NORMAL); + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + else if (fullbright) + { //not deferred, register in standard fullbright shiny pass + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY); + } + else + { //not deferred or fullbright, register in standard shiny pass + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + else + { //not alpha and not shiny + if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) + { //invisiprim + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright || bake_sunlight) + { //fullbright + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + if (!hud_group && use_legacy_bump) + { //if this is the deferred render and a bump map is present, register in post deferred bump + registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); + } + } + else + { + if (use_legacy_bump) + { //non-shiny or fullbright deferred bump llassert(mask& LLVertexBuffer::MAP_TANGENT); - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - else - { //all around simple - llassert(mask & LLVertexBuffer::MAP_NORMAL); - if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) - { //material alpha mask can be respected in non-deferred - registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); - } - else - { - registerFace(group, facep, LLRenderPass::PASS_SIMPLE); - } - } - } - - - if (!gPipeline.shadersLoaded() && - !is_alpha && - te->getShiny()) - { //shiny as an extra pass when shaders are disabled - registerFace(group, facep, LLRenderPass::PASS_SHINY); - } - } - - //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && hud_group) - { - llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); - facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); - - if (!force_simple && use_legacy_bump) - { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + else + { //all around simple + llassert(mask & LLVertexBuffer::MAP_NORMAL); + if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) + { //material alpha mask can be respected in non-deferred + registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + } + } + + + if (!gPipeline.shadersLoaded() && + !is_alpha && + te->getShiny()) + { //shiny as an extra pass when shaders are disabled + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + } + + //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 + if (!is_alpha && hud_group) + { + llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); + facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); + + if (!force_simple && use_legacy_bump) + { llassert(mask & LLVertexBuffer::MAP_TANGENT); - registerFace(group, facep, LLRenderPass::PASS_BUMP); - } - } + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + } - if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) - { + if (!is_alpha && LLPipeline::sRenderGlow && te->getGlow() > 0.f) + { if (gltf_mat) { registerFace(group, facep, LLRenderPass::PASS_GLTF_GLOW); @@ -6827,24 +6827,24 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { registerFace(group, facep, LLRenderPass::PASS_GLOW); } - } - - ++face_iter; - } + } - if (buffer) - { - buffer->unmapBuffer(); - } - } + ++face_iter; + } - group->mBufferMap[mask].clear(); - for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) - { - group->mBufferMap[mask][i->first] = i->second; - } + if (buffer) + { + buffer->unmapBuffer(); + } + } + + group->mBufferMap[mask].clear(); + for (LLSpatialGroup::buffer_texture_map_t::iterator i = buffer_map[mask].begin(); i != buffer_map[mask].end(); ++i) + { + group->mBufferMap[mask][i->first] = i->second; + } - return geometryBytes; + return geometryBytes; } void LLVolumeGeometryManager::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) @@ -6862,57 +6862,57 @@ void LLVolumeGeometryManager::addGeometryCount(LLSpatialGroup* group, U32& verte } void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) -{ +{ LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; //clear off any old faces mFaceList.clear(); - //for each drawable - for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) - { - LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - - if (!drawablep || drawablep->isDead()) - { - continue; - } - - //for each face - for (S32 i = 0; i < drawablep->getNumFaces(); i++) - { - //sum up face verts and indices - drawablep->updateFaceSize(i); - LLFace* facep = drawablep->getFace(i); - if (facep) - { - if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && - facep->getGeomCount() + vertex_count <= 65536) - { - vertex_count += facep->getGeomCount(); - index_count += facep->getIndicesCount(); - - //remember face (for sorting) - mFaceList.push_back(facep); - } - else - { - facep->clearVertexBuffer(); - } - } - } - } + //for each drawable + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) + { + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + + if (!drawablep || drawablep->isDead()) + { + continue; + } + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep) + { + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA && + facep->getGeomCount() + vertex_count <= 65536) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->clearVertexBuffer(); + } + } + } + } } LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) : LLBridgePartition(regionp) { - mPartitionType = LLViewerRegion::PARTITION_HUD; - mDrawableType = LLPipeline::RENDER_TYPE_HUD; - mSlopRatio = 0.f; - mLODPeriod = 1; + mPartitionType = LLViewerRegion::PARTITION_HUD; + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mSlopRatio = 0.f; + mLODPeriod = 1; } void LLHUDPartition::shift(const LLVector4a &offset) { - //HUD objects don't shift with region crossing. That would be silly. + //HUD objects don't shift with region crossing. That would be silly. } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index cac09609b3..44a964a363 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -1,25 +1,25 @@ -/** +/** * @file llvovolume.h * @brief LLVOVolume class header file * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -32,8 +32,8 @@ #include "llviewermedia.h" #include "llframetimer.h" #include "lllocalbitmaps.h" -#include "m3math.h" // LLMatrix3 -#include "m4math.h" // LLMatrix4 +#include "m3math.h" // LLMatrix3 +#include "m4math.h" // LLMatrix4 #include #include @@ -51,7 +51,7 @@ typedef std::vector media_list_t; enum LLVolumeInterfaceType { - INTERFACE_FLEXIBLE = 1, + INTERFACE_FLEXIBLE = 1, }; const F32 MAX_LOD_FACTOR = 4.0f; @@ -60,10 +60,10 @@ const F32 MAX_LOD_FACTOR = 4.0f; class LLRiggedVolume : public LLVolume { public: - LLRiggedVolume(const LLVolumeParams& params) - : LLVolume(params, 0.f) - { - } + LLRiggedVolume(const LLVolumeParams& params) + : LLVolume(params, 0.f) + { + } using FaceIndex = S32; static const FaceIndex UPDATE_ALL_FACES = -1; @@ -82,218 +82,218 @@ public: class LLVolumeInterface { public: - virtual ~LLVolumeInterface() { } - virtual LLVolumeInterfaceType getInterfaceType() const = 0; - virtual void doIdleUpdate() = 0; - virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; - virtual LLVector3 getPivotPosition() const = 0; - virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; - virtual void onSetScale(const LLVector3 &scale, BOOL damped) = 0; - virtual void onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin) = 0; - virtual void onShift(const LLVector4a &shift_vector) = 0; - virtual bool isVolumeUnique() const = 0; // Do we need a unique LLVolume instance? - virtual bool isVolumeGlobal() const = 0; // Are we in global space? - virtual bool isActive() const = 0; // Is this object currently active? - virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; - virtual void updateRelativeXform(bool force_identity = false) = 0; - virtual U32 getID() const = 0; - virtual void preRebuild() = 0; + virtual ~LLVolumeInterface() { } + virtual LLVolumeInterfaceType getInterfaceType() const = 0; + virtual void doIdleUpdate() = 0; + virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; + virtual LLVector3 getPivotPosition() const = 0; + virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; + virtual void onSetScale(const LLVector3 &scale, BOOL damped) = 0; + virtual void onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin) = 0; + virtual void onShift(const LLVector4a &shift_vector) = 0; + virtual bool isVolumeUnique() const = 0; // Do we need a unique LLVolume instance? + virtual bool isVolumeGlobal() const = 0; // Are we in global space? + virtual bool isActive() const = 0; // Is this object currently active? + virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; + virtual void updateRelativeXform(bool force_identity = false) = 0; + virtual U32 getID() const = 0; + virtual void preRebuild() = 0; }; // Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME) class LLVOVolume : public LLViewerObject { - LOG_CLASS(LLVOVolume); + LOG_CLASS(LLVOVolume); protected: - virtual ~LLVOVolume(); + virtual ~LLVOVolume(); public: - static void initClass(); - static void cleanupClass(); - static void preUpdateGeom(); - - enum - { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_TEXCOORD1) | - (1 << LLVertexBuffer::TYPE_COLOR) - }; + static void initClass(); + static void cleanupClass(); + static void preUpdateGeom(); + + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD0) | + (1 << LLVertexBuffer::TYPE_TEXCOORD1) | + (1 << LLVertexBuffer::TYPE_COLOR) + }; public: - LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - void markDead() override; // Override (and call through to parent) to clean up media references - - LLDrawable* createDrawable(LLPipeline *pipeline) override; - - void deleteFaces(); - - void animateTextures(); - - BOOL isVisible() const ; - BOOL isActive() const override; - BOOL isAttachment() const override; - BOOL isRootEdit() const override; // overridden for sake of attachments treating themselves as a root object - BOOL isHUDAttachment() const override; - - void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); - /*virtual*/ BOOL setParent(LLViewerObject* parent) override; - S32 getLOD() const override { return mLOD; } - void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; } - bool isNoLOD() const { return NO_LOD == mLOD; } - const LLVector3 getPivotPositionAgent() const override; - const LLMatrix4& getRelativeXform() const { return mRelativeXform; } - const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } - /*virtual*/ const LLMatrix4 getRenderMatrix() const override; - typedef std::unordered_set texture_cost_t; + LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); + void markDead() override; // Override (and call through to parent) to clean up media references + + LLDrawable* createDrawable(LLPipeline *pipeline) override; + + void deleteFaces(); + + void animateTextures(); + + BOOL isVisible() const ; + BOOL isActive() const override; + BOOL isAttachment() const override; + BOOL isRootEdit() const override; // overridden for sake of attachments treating themselves as a root object + BOOL isHUDAttachment() const override; + + void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); + /*virtual*/ BOOL setParent(LLViewerObject* parent) override; + S32 getLOD() const override { return mLOD; } + void setNoLOD() { mLOD = NO_LOD; mLODChanged = TRUE; } + bool isNoLOD() const { return NO_LOD == mLOD; } + const LLVector3 getPivotPositionAgent() const override; + const LLMatrix4& getRelativeXform() const { return mRelativeXform; } + const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } + /*virtual*/ const LLMatrix4 getRenderMatrix() const override; + typedef std::unordered_set texture_cost_t; static S32 getTextureCost(const LLViewerTexture* img); - U32 getRenderCost(texture_cost_t &textures) const; - /*virtual*/ F32 getEstTrianglesMax() const override; - /*virtual*/ F32 getEstTrianglesStreamingCost() const override; - /* virtual*/ F32 getStreamingCost() const override; + U32 getRenderCost(texture_cost_t &textures) const; + /*virtual*/ F32 getEstTrianglesMax() const override; + /*virtual*/ F32 getEstTrianglesStreamingCost() const override; + /* virtual*/ F32 getStreamingCost() const override; /*virtual*/ bool getCostData(LLMeshCostData& costs) const override; - /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const override; - /*virtual*/ U32 getHighLODTriangleCount() override; - /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - BOOL pick_rigged = FALSE, + /*virtual*/ U32 getTriangleCount(S32* vcount = NULL) const override; + /*virtual*/ U32 getHighLODTriangleCount() override; + /*virtual*/ BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + 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 - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ) override; - - LLVector3 agentPositionToVolume(const LLVector3& pos) const; - LLVector3 agentDirectionToVolume(const LLVector3& dir) const; - LLVector3 volumePositionToAgent(const LLVector3& dir) const; - LLVector3 volumeDirectionToAgent(const LLVector3& dir) const; - - - BOOL getVolumeChanged() const { return mVolumeChanged; } - - F32 getVObjRadius() const override { return mVObjRadius; }; - const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const override; - - void markForUpdate() override; - void faceMappingChanged() override { mFaceMappingChanged=TRUE; } - - /*virtual*/ void onShift(const LLVector4a &shift_vector) override; // Called when the drawable shifts - - /*virtual*/ void parameterChanged(U16 param_type, bool local_origin) override; - /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) override; + 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 + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ) override; + + LLVector3 agentPositionToVolume(const LLVector3& pos) const; + LLVector3 agentDirectionToVolume(const LLVector3& dir) const; + LLVector3 volumePositionToAgent(const LLVector3& dir) const; + LLVector3 volumeDirectionToAgent(const LLVector3& dir) const; + + + BOOL getVolumeChanged() const { return mVolumeChanged; } + + F32 getVObjRadius() const override { return mVObjRadius; }; + const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const override; + + void markForUpdate() override; + void faceMappingChanged() override { mFaceMappingChanged=TRUE; } + + /*virtual*/ void onShift(const LLVector4a &shift_vector) override; // Called when the drawable shifts + + /*virtual*/ void parameterChanged(U16 param_type, bool local_origin) override; + /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) override; // update mReflectionProbe based on isReflectionProbe() void updateReflectionProbePtr(); - /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, const EObjectUpdateType update_type, - LLDataPacker *dp) override; - - /*virtual*/ void setSelected(BOOL sel) override; - /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp) override; - - /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped) override; - - /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) override; - /*virtual*/ void setNumTEs(const U8 num_tes) override; - /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep) override; - /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid) override; - /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color) override; - /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color) override; - /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; - /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; - /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; - /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; - /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; - /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; - /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) override; - - static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te); - - /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) override; + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, const EObjectUpdateType update_type, + LLDataPacker *dp) override; + + /*virtual*/ void setSelected(BOOL sel) override; + /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp) override; + + /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped) override; + + /*virtual*/ void changeTEImage(S32 index, LLViewerTexture* new_image) override; + /*virtual*/ void setNumTEs(const U8 num_tes) override; + /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep) override; + /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid) override; + /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color) override; + /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color) override; + /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump) override; + /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny) override; + /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright) override; + /*virtual*/ S32 setTEBumpShinyFullbright(const U8 te, const U8 bump) override; + /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags) override; + /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow) override; + /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) override; + + static void setTEMaterialParamsCallbackTE(const LLUUID& objectID, const LLMaterialID& pMaterialID, const LLMaterialPtr pMaterialParams, U32 te); + + /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) override; S32 setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat) override; - /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t) override; - /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s) override; - /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t) override; - /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen) override; - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media) override; - /*virtual*/ BOOL setMaterial(const U8 material) override; - - void setTexture(const S32 face); - S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} - /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override; - void updateSculptTexture(); - void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} - void sculpt(); - static void rebuildMeshAssetCallback(const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); - - void updateRelativeXform(bool force_identity = false); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable) override; - /*virtual*/ void updateFaceSize(S32 idx) override; - /*virtual*/ BOOL updateLOD() override; - void updateRadius() override; - /*virtual*/ void updateTextures() override; - void updateTextureVirtualSize(bool forced = false); - - void updateFaceFlags(); - void regenFaces(); + /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t) override; + /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s) override; + /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t) override; + /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen) override; + /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media) override; + /*virtual*/ BOOL setMaterial(const U8 material) override; + + void setTexture(const S32 face); + S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} + /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override; + void updateSculptTexture(); + void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} + void sculpt(); + static void rebuildMeshAssetCallback(const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); + + void updateRelativeXform(bool force_identity = false); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable) override; + /*virtual*/ void updateFaceSize(S32 idx) override; + /*virtual*/ BOOL updateLOD() override; + void updateRadius() override; + /*virtual*/ void updateTextures() override; + void updateTextureVirtualSize(bool forced = false); + + void updateFaceFlags(); + void regenFaces(); BOOL genBBoxes(BOOL force_global, BOOL should_update_octree_bounds = TRUE); - void preRebuild(); - virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max) override; - virtual F32 getBinRadius() override; - - virtual U32 getPartitionType() const override; - - // For Lights - void setIsLight(BOOL is_light); + void preRebuild(); + virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max) override; + virtual F32 getBinRadius() override; + + virtual U32 getPartitionType() const override; + + // For Lights + void setIsLight(BOOL is_light); //set the gamma-corrected (sRGB) color of this light - void setLightSRGBColor(const LLColor3& color); + void setLightSRGBColor(const LLColor3& color); //set the linear color of this light void setLightLinearColor(const LLColor3& color); - void setLightIntensity(F32 intensity); - void setLightRadius(F32 radius); - void setLightFalloff(F32 falloff); - void setLightCutoff(F32 cutoff); - void setLightTextureID(LLUUID id); - void setSpotLightParams(LLVector3 params); + void setLightIntensity(F32 intensity); + void setLightRadius(F32 radius); + void setLightFalloff(F32 falloff); + void setLightCutoff(F32 cutoff); + void setLightTextureID(LLUUID id); + void setSpotLightParams(LLVector3 params); - BOOL getIsLight() const; + BOOL getIsLight() const; bool getIsLightFast() const; // Get the light color in sRGB color space NOT scaled by intensity. - LLColor3 getLightSRGBBaseColor() const; + LLColor3 getLightSRGBBaseColor() const; // Get the light color in linear color space NOT scaled by intensity. LLColor3 getLightLinearBaseColor() const; - - // Get the light color in linear color space scaled by intensity + + // Get the light color in linear color space scaled by intensity // this is the value that should be fed into shaders LLColor3 getLightLinearColor() const; // Get the light color in sRGB color space scaled by intensity. - LLColor3 getLightSRGBColor() const; + LLColor3 getLightSRGBColor() const; - LLUUID getLightTextureID() const; - bool isLightSpotlight() const; - LLVector3 getSpotLightParams() const; - void updateSpotLightPriority(); - F32 getSpotLightPriority() const; + LLUUID getLightTextureID() const; + bool isLightSpotlight() const; + LLVector3 getSpotLightParams() const; + void updateSpotLightPriority(); + F32 getSpotLightPriority() const; - LLViewerTexture* getLightTexture(); - F32 getLightIntensity() const; - F32 getLightRadius() const; - F32 getLightFalloff(const F32 fudge_factor = 1.f) const; - F32 getLightCutoff() const; + LLViewerTexture* getLightTexture(); + F32 getLightIntensity() const; + F32 getLightRadius() const; + F32 getLightFalloff(const F32 fudge_factor = 1.f) const; + F32 getLightCutoff() const; // Reflection Probes bool setIsReflectionProbe(BOOL is_probe); @@ -310,13 +310,13 @@ public: bool getReflectionProbeIsDynamic() const; bool getReflectionProbeIsMirror() const; - // Flexible Objects - U32 getVolumeInterfaceID() const; - virtual BOOL isFlexible() const override; - virtual BOOL isSculpted() const override; - virtual BOOL isMesh() const override; - virtual BOOL isRiggedMesh() const override; - virtual BOOL hasLightTexture() const override; + // Flexible Objects + U32 getVolumeInterfaceID() const; + virtual BOOL isFlexible() const override; + virtual BOOL isSculpted() const override; + virtual BOOL isMesh() const override; + virtual BOOL isRiggedMesh() const override; + virtual BOOL hasLightTexture() const override; // fast variants above that use state that is filled in later // not reliable early in the life of an object, but should be used after @@ -327,16 +327,16 @@ public: bool isRiggedMeshFast() const; bool isAnimatedObjectFast() const; - BOOL isVolumeGlobal() const; - BOOL canBeFlexible() const; - BOOL setIsFlexible(BOOL is_flexible); + BOOL isVolumeGlobal() const; + BOOL canBeFlexible() const; + BOOL setIsFlexible(BOOL is_flexible); const LLMeshSkinInfo* getSkinInfo() const; const bool isSkinInfoUnavaliable() const { return mSkinInfoUnavaliable; } //convenience accessor for mesh ID (which is stored in sculpt id for legacy reasons) const LLUUID& getMeshID() const { return getVolume()->getParams().getSculptID(); } - + // Extended Mesh Properties U32 getExtendedMeshFlags() const; void onSetExtendedMeshFlags(U32 flags); @@ -349,58 +349,58 @@ public: //virtual void updateRiggingInfo() override; S32 mLastRiggingInfoLOD; - + // Functions that deal with media, or media navigation - + // Update this object's media data with the given media data array // (typically this is only called upon a response from a server request) - void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version); - + void updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version); + // Bounce back media at the given index to its current URL (or home URL, if current URL is empty) - void mediaNavigateBounceBack(U8 texture_index); - - // Returns whether or not this object has permission to navigate or control - // the given media entry - enum MediaPermType { - MEDIA_PERM_INTERACT, MEDIA_PERM_CONTROL - }; + void mediaNavigateBounceBack(U8 texture_index); + + // Returns whether or not this object has permission to navigate or control + // the given media entry + enum MediaPermType { + MEDIA_PERM_INTERACT, MEDIA_PERM_CONTROL + }; bool hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type); - - void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location); - void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event); - - - // Sync the given media data with the impl and the given te - void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent); - - // Send media data update to the simulator. - void sendMediaDataUpdate(); - - viewer_media_t getMediaImpl(U8 face_id) const; - S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id); - F64 getTotalMediaInterest() const; - - bool hasMedia() const; - - LLVector3 getApproximateFaceNormal(U8 face_id); + + void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location); + void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event); + + + // Sync the given media data with the impl and the given te + void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent); + + // Send media data update to the simulator. + void sendMediaDataUpdate(); + + viewer_media_t getMediaImpl(U8 face_id) const; + S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id); + F64 getTotalMediaInterest() const; + + bool hasMedia() const; + + LLVector3 getApproximateFaceNormal(U8 face_id); // Flag any corresponding avatars as needing update. void updateVisualComplexity(); - - void notifyMeshLoaded(); - void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); - void notifySkinInfoUnavailable(); - - // Returns 'true' iff the media data for this object is in flight - bool isMediaDataBeingFetched() const; - - // Returns the "last fetched" media version, or -1 if not fetched yet - S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; } - - void addMDCImpl() { ++mMDCImplCount; } - void removeMDCImpl() { --mMDCImplCount; } - S32 getMDCImplCount() { return mMDCImplCount; } - + + void notifyMeshLoaded(); + void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); + void notifySkinInfoUnavailable(); + + // Returns 'true' iff the media data for this object is in flight + bool isMediaDataBeingFetched() const; + + // Returns the "last fetched" media version, or -1 if not fetched yet + S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; } + + void addMDCImpl() { ++mMDCImplCount; } + void removeMDCImpl() { --mMDCImplCount; } + S32 getMDCImplCount() { return mMDCImplCount; } + // Rigged volume update (for raycasting) // By default, this updates the bounding boxes of all the faces and builds an octree for precise per-triangle raycasting @@ -408,69 +408,69 @@ public: bool force_treat_as_rigged, LLRiggedVolume::FaceIndex face_index = LLRiggedVolume::UPDATE_ALL_FACES, bool rebuild_face_octrees = true); - LLRiggedVolume* getRiggedVolume(); + LLRiggedVolume* getRiggedVolume(); - //returns true if volume should be treated as a rigged volume - // - Build tools are open - // - object is an attachment - // - object is attached to self - // - object is rendered as rigged - bool treatAsRigged(); + //returns true if volume should be treated as a rigged volume + // - Build tools are open + // - object is an attachment + // - object is attached to self + // - object is rendered as rigged + bool treatAsRigged(); - //clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates - void clearRiggedVolume(); + //clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates + void clearRiggedVolume(); protected: - S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor); - BOOL calcLOD(); - LLFace* addFace(S32 face_index); - - // stats tracking for render complexity - static S32 mRenderComplexity_last; - static S32 mRenderComplexity_current; + S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor); + BOOL calcLOD(); + LLFace* addFace(S32 face_index); + + // stats tracking for render complexity + static S32 mRenderComplexity_last; + static S32 mRenderComplexity_current; void onDrawableUpdateFromServer(); - void requestMediaDataUpdate(bool isNew); - void cleanUpMediaImpls(); - void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; - void removeMediaImpl(S32 texture_index) ; + void requestMediaDataUpdate(bool isNew); + void cleanUpMediaImpls(); + void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; + void removeMediaImpl(S32 texture_index) ; private: bool lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled, BOOL &shouldUpdateOctreeBounds); public: - static S32 getRenderComplexityMax() {return mRenderComplexity_last;} - static void updateRenderComplexity(); + static S32 getRenderComplexityMax() {return mRenderComplexity_last;} + static void updateRenderComplexity(); - LLViewerTextureAnim *mTextureAnimp; - U8 mTexAnimMode; + LLViewerTextureAnim *mTextureAnimp; + U8 mTexAnimMode; F32 mLODDistance; F32 mLODAdjustedDistance; F32 mLODRadius; private: - friend class LLDrawable; - friend class LLFace; - - BOOL mFaceMappingChanged; - LLFrameTimer mTextureUpdateTimer; - S32 mLOD; - BOOL mLODChanged; - BOOL mSculptChanged; - BOOL mColorChanged; - F32 mSpotLightPriority; - LLMatrix4 mRelativeXform; - LLMatrix3 mRelativeXformInvTrans; - BOOL mVolumeChanged; - F32 mVObjRadius; - LLVolumeInterface *mVolumeImpl; - LLPointer mSculptTexture; - LLPointer mLightTexture; - media_list_t mMediaImplList; - S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 + friend class LLDrawable; + friend class LLFace; + + BOOL mFaceMappingChanged; + LLFrameTimer mTextureUpdateTimer; + S32 mLOD; + BOOL mLODChanged; + BOOL mSculptChanged; + BOOL mColorChanged; + F32 mSpotLightPriority; + LLMatrix4 mRelativeXform; + LLMatrix3 mRelativeXformInvTrans; + BOOL mVolumeChanged; + F32 mVObjRadius; + LLVolumeInterface *mVolumeImpl; + LLPointer mSculptTexture; + LLPointer mLightTexture; + media_list_t mMediaImplList; + S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1 U32 mServerDrawableUpdateCount; - S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; - S32 mMDCImplCount; + S32 mIndexInTex[LLRender::NUM_VOLUME_TEXTURE_CHANNELS]; + S32 mMDCImplCount; // cached value of getIsLight to avoid redundant map lookups // accessed by getIsLightFast @@ -479,24 +479,24 @@ private: // cached value of getIsAnimatedObject to avoid redundant map lookups // accessed by getIsAnimatedObjectFast mutable bool mIsAnimatedObject = false; - bool mResetDebugText; + bool mResetDebugText; - LLPointer mRiggedVolume; + LLPointer mRiggedVolume; - bool mSkinInfoUnavaliable; - LLConstPointer mSkinInfo; - // statics + bool mSkinInfoUnavaliable; + LLConstPointer mSkinInfo; + // statics public: - static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop - static F32 sLODFactor; // LOD scale factor - static F32 sDistanceFactor; // LOD distance factor + static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop + static F32 sLODFactor; // LOD scale factor + static F32 sDistanceFactor; // LOD distance factor - static LLPointer sObjectMediaClient; - static LLPointer sObjectMediaNavigateClient; + static LLPointer sObjectMediaClient; + static LLPointer sObjectMediaNavigateClient; protected: - static S32 sNumLODChanges; + static S32 sNumLODChanges; - friend class LLVolumeImplFlexible; + friend class LLVolumeImplFlexible; }; #endif // LL_LLVOVOLUME_H diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index 461d556946..1148e81fd5 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2009-03-18 * @brief Implementation for llxmlrpclistener. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -88,13 +88,13 @@ class StatusMapper: public StatusMapperBase public: StatusMapper(): StatusMapperBase("Status") { - mMap[LLXMLRPCTransaction::StatusNotStarted] = "NotStarted"; - mMap[LLXMLRPCTransaction::StatusStarted] = "Started"; - mMap[LLXMLRPCTransaction::StatusDownloading] = "Downloading"; - mMap[LLXMLRPCTransaction::StatusComplete] = "Complete"; - mMap[LLXMLRPCTransaction::StatusCURLError] = "CURLError"; - mMap[LLXMLRPCTransaction::StatusXMLRPCError] = "XMLRPCError"; - mMap[LLXMLRPCTransaction::StatusOtherError] = "OtherError"; + mMap[LLXMLRPCTransaction::StatusNotStarted] = "NotStarted"; + mMap[LLXMLRPCTransaction::StatusStarted] = "Started"; + mMap[LLXMLRPCTransaction::StatusDownloading] = "Downloading"; + mMap[LLXMLRPCTransaction::StatusComplete] = "Complete"; + mMap[LLXMLRPCTransaction::StatusCURLError] = "CURLError"; + mMap[LLXMLRPCTransaction::StatusXMLRPCError] = "XMLRPCError"; + mMap[LLXMLRPCTransaction::StatusOtherError] = "OtherError"; } }; @@ -285,7 +285,7 @@ public: XMLRPC_RequestSetData(request, xparams); mTransaction.reset(new LLXMLRPCTransaction(mUri, request, true, command.has("http_params")? LLSD(command["http_params"]) : LLSD())); - mPreviousStatus = mTransaction->status(NULL); + mPreviousStatus = mTransaction->status(NULL); // Free the XMLRPC_REQUEST object and the attached data values. XMLRPC_RequestFree(request, 1); @@ -323,42 +323,42 @@ public: data["error"] = ""; data["transfer_rate"] = 0.0; LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump)); - if (! done) + if (! done) { // Not done yet, carry on. - if (status == LLXMLRPCTransaction::StatusDownloading - && status != mPreviousStatus) - { - // If a response has been received, send the - // 'downloading' status if it hasn't been sent. - replyPump.post(data); - } - - mPreviousStatus = status; + if (status == LLXMLRPCTransaction::StatusDownloading + && status != mPreviousStatus) + { + // If a response has been received, send the + // 'downloading' status if it hasn't been sent. + replyPump.post(data); + } + + mPreviousStatus = status; return false; } // Here the transaction is complete. Check status. data["error"] = mTransaction->statusMessage(); - data["transfer_rate"] = mTransaction->transferRate(); + data["transfer_rate"] = mTransaction->transferRate(); LL_INFOS("LLXMLRPCListener") << mMethod << " result from " << mUri << ": status " << data["status"].asString() << ", errorcode " << data["errorcode"].asString() << " (" << data["error"].asString() << ")" << LL_ENDL; - - switch (curlcode) - { + + switch (curlcode) + { #if CURLE_SSL_PEER_CERTIFICATE != CURLE_SSL_CACERT - case CURLE_SSL_PEER_CERTIFICATE: + case CURLE_SSL_PEER_CERTIFICATE: #endif - case CURLE_SSL_CACERT: + case CURLE_SSL_CACERT: data["certificate"] = mTransaction->getErrorCertData(); - break; + break; - default: - break; - } + default: + break; + } // values of 'curlcode': // CURLE_COULDNT_RESOLVE_HOST, // CURLE_SSL_PEER_CERTIFICATE, @@ -547,7 +547,7 @@ private: const std::string mReplyPump; LLTempBoundListener mBoundListener; std::unique_ptr mTransaction; - LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes. + LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes. }; bool LLXMLRPCListener::process(const LLSD& command) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 8b1e46343b..65307fe279 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1,25 +1,25 @@ -/** +/** * @file pipeline.cpp * @brief Rendering pipeline. * * $LicenseInfo:firstyear=2005&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -40,11 +40,11 @@ #include "llvolume.h" #include "material_codes.h" #include "v3color.h" -#include "llui.h" +#include "llui.h" #include "llglheaders.h" #include "llrender.h" #include "llstartup.h" -#include "llwindow.h" // swapBuffers() +#include "llwindow.h" // swapBuffers() // newview includes #include "llagent.h" @@ -219,9 +219,9 @@ extern BOOL gDebugGL; extern BOOL gCubeSnapshot; extern BOOL gSnapshotNoPost; -bool gAvatarBacklight = false; +bool gAvatarBacklight = false; -bool gDebugPipeline = false; +bool gDebugPipeline = false; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; @@ -280,42 +280,42 @@ LLVertexBuffer* ll_create_cube_vb(U32 type_mask); void display_update_camera(); //---------------------------------------- -S32 LLPipeline::sCompiles = 0; - -bool LLPipeline::sPickAvatar = true; -bool LLPipeline::sDynamicLOD = true; -bool LLPipeline::sShowHUDAttachments = true; -bool LLPipeline::sRenderMOAPBeacons = false; -bool LLPipeline::sRenderPhysicalBeacons = true; -bool LLPipeline::sRenderScriptedBeacons = false; -bool LLPipeline::sRenderScriptedTouchBeacons = true; -bool LLPipeline::sRenderParticleBeacons = false; -bool LLPipeline::sRenderSoundBeacons = false; -bool LLPipeline::sRenderBeacons = false; -bool LLPipeline::sRenderHighlight = true; +S32 LLPipeline::sCompiles = 0; + +bool LLPipeline::sPickAvatar = true; +bool LLPipeline::sDynamicLOD = true; +bool LLPipeline::sShowHUDAttachments = true; +bool LLPipeline::sRenderMOAPBeacons = false; +bool LLPipeline::sRenderPhysicalBeacons = true; +bool LLPipeline::sRenderScriptedBeacons = false; +bool LLPipeline::sRenderScriptedTouchBeacons = true; +bool LLPipeline::sRenderParticleBeacons = false; +bool LLPipeline::sRenderSoundBeacons = false; +bool LLPipeline::sRenderBeacons = false; +bool LLPipeline::sRenderHighlight = true; LLRender::eTexIndex LLPipeline::sRenderHighlightTextureChannel = LLRender::DIFFUSE_MAP; -bool LLPipeline::sForceOldBakedUpload = false; -S32 LLPipeline::sUseOcclusion = 0; -bool LLPipeline::sAutoMaskAlphaDeferred = true; -bool LLPipeline::sAutoMaskAlphaNonDeferred = false; -bool LLPipeline::sRenderTransparentWater = true; -bool LLPipeline::sBakeSunlight = false; -bool LLPipeline::sNoAlpha = false; -bool LLPipeline::sUseFarClip = true; -bool LLPipeline::sShadowRender = false; -bool LLPipeline::sRenderGlow = false; -bool LLPipeline::sReflectionRender = false; +bool LLPipeline::sForceOldBakedUpload = false; +S32 LLPipeline::sUseOcclusion = 0; +bool LLPipeline::sAutoMaskAlphaDeferred = true; +bool LLPipeline::sAutoMaskAlphaNonDeferred = false; +bool LLPipeline::sRenderTransparentWater = true; +bool LLPipeline::sBakeSunlight = false; +bool LLPipeline::sNoAlpha = false; +bool LLPipeline::sUseFarClip = true; +bool LLPipeline::sShadowRender = false; +bool LLPipeline::sRenderGlow = false; +bool LLPipeline::sReflectionRender = false; bool LLPipeline::sDistortionRender = false; -bool LLPipeline::sImpostorRender = false; -bool LLPipeline::sImpostorRenderAlphaDepthPass = false; -bool LLPipeline::sUnderWaterRender = false; -bool LLPipeline::sTextureBindTest = false; -bool LLPipeline::sRenderAttachedLights = true; -bool LLPipeline::sRenderAttachedParticles = true; -bool LLPipeline::sRenderDeferred = false; -bool LLPipeline::sReflectionProbesEnabled = false; -S32 LLPipeline::sVisibleLightCount = 0; -bool LLPipeline::sRenderingHUDs; +bool LLPipeline::sImpostorRender = false; +bool LLPipeline::sImpostorRenderAlphaDepthPass = false; +bool LLPipeline::sUnderWaterRender = false; +bool LLPipeline::sTextureBindTest = false; +bool LLPipeline::sRenderAttachedLights = true; +bool LLPipeline::sRenderAttachedParticles = true; +bool LLPipeline::sRenderDeferred = false; +bool LLPipeline::sReflectionProbesEnabled = false; +S32 LLPipeline::sVisibleLightCount = 0; +bool LLPipeline::sRenderingHUDs; F32 LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f; // EventHost API LLPipeline listener. @@ -337,29 +337,29 @@ bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false) } LLPipeline::LLPipeline() : - mBackfaceCull(false), - mMatrixOpCount(0), - mTextureMatrixOps(0), - mNumVisibleNodes(0), - mNumVisibleFaces(0), - mPoissonOffset(0), - - mInitialized(false), - mShadersLoaded(false), - mTransformFeedbackPrimitives(0), - mRenderDebugFeatureMask(0), - mRenderDebugMask(0), - mOldRenderDebugMask(0), - mMeshDirtyQueryObject(0), - mGroupQ1Locked(false), - mResetVertexBuffers(false), - mLastRebuildPool(NULL), - mLightMask(0), - mLightMovingMask(0) -{ - mNoiseMap = 0; - mTrueNoiseMap = 0; - mLightFunc = 0; + mBackfaceCull(false), + mMatrixOpCount(0), + mTextureMatrixOps(0), + mNumVisibleNodes(0), + mNumVisibleFaces(0), + mPoissonOffset(0), + + mInitialized(false), + mShadersLoaded(false), + mTransformFeedbackPrimitives(0), + mRenderDebugFeatureMask(0), + mRenderDebugMask(0), + mOldRenderDebugMask(0), + mMeshDirtyQueryObject(0), + mGroupQ1Locked(false), + mResetVertexBuffers(false), + mLastRebuildPool(NULL), + mLightMask(0), + mLightMovingMask(0) +{ + mNoiseMap = 0; + mTrueNoiseMap = 0; + mLightFunc = 0; for(U32 i = 0; i < 8; i++) { @@ -369,99 +369,99 @@ LLPipeline::LLPipeline() : void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name) { - LLPointer cntrl_ptr = gSavedSettings.getControl(name); - if ( cntrl_ptr.isNull() ) - { - LL_WARNS() << "Global setting name not found:" << name << LL_ENDL; - } - else - { - cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); - } + LLPointer cntrl_ptr = gSavedSettings.getControl(name); + if ( cntrl_ptr.isNull() ) + { + LL_WARNS() << "Global setting name not found:" << name << LL_ENDL; + } + else + { + cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + } } void LLPipeline::init() { - refreshCachedSettings(); + refreshCachedSettings(); mRT = &mMainRT; - gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); - gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); - sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); - sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); - sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); + gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity"); + gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize"); + sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); + sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); + sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); mInitialized = true; - - stop_glerror(); - //create render pass pools - getPool(LLDrawPool::POOL_ALPHA_PRE_WATER); + stop_glerror(); + + //create render pass pools + getPool(LLDrawPool::POOL_ALPHA_PRE_WATER); getPool(LLDrawPool::POOL_ALPHA_POST_WATER); - getPool(LLDrawPool::POOL_SIMPLE); - getPool(LLDrawPool::POOL_ALPHA_MASK); - getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); - getPool(LLDrawPool::POOL_GRASS); - getPool(LLDrawPool::POOL_FULLBRIGHT); - getPool(LLDrawPool::POOL_BUMP); - getPool(LLDrawPool::POOL_MATERIALS); - getPool(LLDrawPool::POOL_GLOW); - getPool(LLDrawPool::POOL_GLTF_PBR); + getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_ALPHA_MASK); + getPool(LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK); + getPool(LLDrawPool::POOL_GRASS); + getPool(LLDrawPool::POOL_FULLBRIGHT); + getPool(LLDrawPool::POOL_BUMP); + getPool(LLDrawPool::POOL_MATERIALS); + getPool(LLDrawPool::POOL_GLOW); + getPool(LLDrawPool::POOL_GLTF_PBR); getPool(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK); - resetFrameStats(); - - if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) - { - clearAllRenderDebugFeatures(); - } - else - { - setAllRenderDebugFeatures(); // By default, all debugging features on - } - clearAllRenderDebugDisplays(); // All debug displays off - - if (gSavedSettings.getBOOL("DisableAllRenderTypes")) - { - clearAllRenderTypes(); - } - else if (gNonInteractive) - { - clearAllRenderTypes(); - } - else - { - setAllRenderTypes(); // By default, all rendering types start enabled - } - - // make sure RenderPerformanceTest persists (hackity hack hack) - // disables non-object rendering (UI, sky, water, etc) - if (gSavedSettings.getBOOL("RenderPerformanceTest")) - { - gSavedSettings.setBOOL("RenderPerformanceTest", FALSE); - gSavedSettings.setBOOL("RenderPerformanceTest", TRUE); - } - - mOldRenderDebugMask = mRenderDebugMask; - - mBackfaceCull = true; - - // Enable features - LLViewerShaderMgr::instance()->setShaders(); - - for (U32 i = 0; i < 2; ++i) - { - mSpotLightFade[i] = 1.f; - } - - if (mCubeVB.isNull()) - { - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); - } - - mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK); - mDeferredVB->allocateBuffer(8, 0); + resetFrameStats(); + + if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) + { + clearAllRenderDebugFeatures(); + } + else + { + setAllRenderDebugFeatures(); // By default, all debugging features on + } + clearAllRenderDebugDisplays(); // All debug displays off + + if (gSavedSettings.getBOOL("DisableAllRenderTypes")) + { + clearAllRenderTypes(); + } + else if (gNonInteractive) + { + clearAllRenderTypes(); + } + else + { + setAllRenderTypes(); // By default, all rendering types start enabled + } + + // make sure RenderPerformanceTest persists (hackity hack hack) + // disables non-object rendering (UI, sky, water, etc) + if (gSavedSettings.getBOOL("RenderPerformanceTest")) + { + gSavedSettings.setBOOL("RenderPerformanceTest", FALSE); + gSavedSettings.setBOOL("RenderPerformanceTest", TRUE); + } + + mOldRenderDebugMask = mRenderDebugMask; + + mBackfaceCull = true; + + // Enable features + LLViewerShaderMgr::instance()->setShaders(); + + for (U32 i = 0; i < 2; ++i) + { + mSpotLightFade[i] = 1.f; + } + + if (mCubeVB.isNull()) + { + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + + mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK); + mDeferredVB->allocateBuffer(8, 0); { mScreenTriangleVB = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX); @@ -476,83 +476,83 @@ void LLPipeline::init() mScreenTriangleVB->unmapBuffer(); } - // - // Update all settings to trigger a cached settings refresh - // - connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred"); - connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred"); - connectRefreshCachedSettingsSafe("RenderUseFarClip"); - connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors"); - connectRefreshCachedSettingsSafe("UseOcclusion"); - // DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); - // DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred"); - connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); - connectRefreshCachedSettingsSafe("RenderFSAASamples"); - connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); - connectRefreshCachedSettingsSafe("RenderUIBuffer"); - connectRefreshCachedSettingsSafe("RenderShadowDetail"); + // + // Update all settings to trigger a cached settings refresh + // + connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaDeferred"); + connectRefreshCachedSettingsSafe("RenderAutoMaskAlphaNonDeferred"); + connectRefreshCachedSettingsSafe("RenderUseFarClip"); + connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors"); + connectRefreshCachedSettingsSafe("UseOcclusion"); + // DEPRECATED -- connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders"); + // DEPRECATED -- connectRefreshCachedSettingsSafe("RenderDeferred"); + connectRefreshCachedSettingsSafe("RenderDeferredSunWash"); + connectRefreshCachedSettingsSafe("RenderFSAASamples"); + connectRefreshCachedSettingsSafe("RenderResolutionDivisor"); + connectRefreshCachedSettingsSafe("RenderUIBuffer"); + connectRefreshCachedSettingsSafe("RenderShadowDetail"); connectRefreshCachedSettingsSafe("RenderShadowSplits"); - connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); - connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); - connectRefreshCachedSettingsSafe("RenderDelayCreation"); - connectRefreshCachedSettingsSafe("RenderAnimateRes"); - connectRefreshCachedSettingsSafe("FreezeTime"); - connectRefreshCachedSettingsSafe("DebugBeaconLineWidth"); - connectRefreshCachedSettingsSafe("RenderHighlightBrightness"); - connectRefreshCachedSettingsSafe("RenderHighlightColor"); - connectRefreshCachedSettingsSafe("RenderHighlightThickness"); - connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred"); - connectRefreshCachedSettingsSafe("PreviewAmbientColor"); - connectRefreshCachedSettingsSafe("PreviewDiffuse0"); - connectRefreshCachedSettingsSafe("PreviewSpecular0"); - connectRefreshCachedSettingsSafe("PreviewDiffuse1"); - connectRefreshCachedSettingsSafe("PreviewSpecular1"); - connectRefreshCachedSettingsSafe("PreviewDiffuse2"); - connectRefreshCachedSettingsSafe("PreviewSpecular2"); - connectRefreshCachedSettingsSafe("PreviewDirection0"); - connectRefreshCachedSettingsSafe("PreviewDirection1"); - connectRefreshCachedSettingsSafe("PreviewDirection2"); - connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha"); - connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount"); - connectRefreshCachedSettingsSafe("RenderGlowLumWeights"); - connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights"); - connectRefreshCachedSettingsSafe("RenderGlowResolutionPow"); - connectRefreshCachedSettingsSafe("RenderGlowIterations"); - connectRefreshCachedSettingsSafe("RenderGlowWidth"); - connectRefreshCachedSettingsSafe("RenderGlowStrength"); - connectRefreshCachedSettingsSafe("RenderGlowNoise"); - connectRefreshCachedSettingsSafe("RenderDepthOfField"); - connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); - connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); - connectRefreshCachedSettingsSafe("CameraFNumber"); - connectRefreshCachedSettingsSafe("CameraFocalLength"); - connectRefreshCachedSettingsSafe("CameraFieldOfView"); - connectRefreshCachedSettingsSafe("RenderShadowNoise"); - connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); - connectRefreshCachedSettingsSafe("RenderSSAOScale"); - connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); - connectRefreshCachedSettingsSafe("RenderSSAOFactor"); - connectRefreshCachedSettingsSafe("RenderSSAOEffect"); - connectRefreshCachedSettingsSafe("RenderShadowOffsetError"); - connectRefreshCachedSettingsSafe("RenderShadowBiasError"); - connectRefreshCachedSettingsSafe("RenderShadowOffset"); - connectRefreshCachedSettingsSafe("RenderShadowBias"); - connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); - connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); - connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); - connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); - connectRefreshCachedSettingsSafe("RenderShadowGaussian"); - connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); - connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); - connectRefreshCachedSettingsSafe("RenderHighlightFadeTime"); - connectRefreshCachedSettingsSafe("RenderFarClip"); - connectRefreshCachedSettingsSafe("RenderShadowSplitExponent"); - connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff"); - connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff"); - connectRefreshCachedSettingsSafe("CameraOffset"); - connectRefreshCachedSettingsSafe("CameraMaxCoF"); - connectRefreshCachedSettingsSafe("CameraDoFResScale"); - connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); + connectRefreshCachedSettingsSafe("RenderDeferredSSAO"); + connectRefreshCachedSettingsSafe("RenderShadowResolutionScale"); + connectRefreshCachedSettingsSafe("RenderDelayCreation"); + connectRefreshCachedSettingsSafe("RenderAnimateRes"); + connectRefreshCachedSettingsSafe("FreezeTime"); + connectRefreshCachedSettingsSafe("DebugBeaconLineWidth"); + connectRefreshCachedSettingsSafe("RenderHighlightBrightness"); + connectRefreshCachedSettingsSafe("RenderHighlightColor"); + connectRefreshCachedSettingsSafe("RenderHighlightThickness"); + connectRefreshCachedSettingsSafe("RenderSpotLightsInNondeferred"); + connectRefreshCachedSettingsSafe("PreviewAmbientColor"); + connectRefreshCachedSettingsSafe("PreviewDiffuse0"); + connectRefreshCachedSettingsSafe("PreviewSpecular0"); + connectRefreshCachedSettingsSafe("PreviewDiffuse1"); + connectRefreshCachedSettingsSafe("PreviewSpecular1"); + connectRefreshCachedSettingsSafe("PreviewDiffuse2"); + connectRefreshCachedSettingsSafe("PreviewSpecular2"); + connectRefreshCachedSettingsSafe("PreviewDirection0"); + connectRefreshCachedSettingsSafe("PreviewDirection1"); + connectRefreshCachedSettingsSafe("PreviewDirection2"); + connectRefreshCachedSettingsSafe("RenderGlowMaxExtractAlpha"); + connectRefreshCachedSettingsSafe("RenderGlowWarmthAmount"); + connectRefreshCachedSettingsSafe("RenderGlowLumWeights"); + connectRefreshCachedSettingsSafe("RenderGlowWarmthWeights"); + connectRefreshCachedSettingsSafe("RenderGlowResolutionPow"); + connectRefreshCachedSettingsSafe("RenderGlowIterations"); + connectRefreshCachedSettingsSafe("RenderGlowWidth"); + connectRefreshCachedSettingsSafe("RenderGlowStrength"); + connectRefreshCachedSettingsSafe("RenderGlowNoise"); + connectRefreshCachedSettingsSafe("RenderDepthOfField"); + connectRefreshCachedSettingsSafe("RenderDepthOfFieldInEditMode"); + connectRefreshCachedSettingsSafe("CameraFocusTransitionTime"); + connectRefreshCachedSettingsSafe("CameraFNumber"); + connectRefreshCachedSettingsSafe("CameraFocalLength"); + connectRefreshCachedSettingsSafe("CameraFieldOfView"); + connectRefreshCachedSettingsSafe("RenderShadowNoise"); + connectRefreshCachedSettingsSafe("RenderShadowBlurSize"); + connectRefreshCachedSettingsSafe("RenderSSAOScale"); + connectRefreshCachedSettingsSafe("RenderSSAOMaxScale"); + connectRefreshCachedSettingsSafe("RenderSSAOFactor"); + connectRefreshCachedSettingsSafe("RenderSSAOEffect"); + connectRefreshCachedSettingsSafe("RenderShadowOffsetError"); + connectRefreshCachedSettingsSafe("RenderShadowBiasError"); + connectRefreshCachedSettingsSafe("RenderShadowOffset"); + connectRefreshCachedSettingsSafe("RenderShadowBias"); + connectRefreshCachedSettingsSafe("RenderSpotShadowOffset"); + connectRefreshCachedSettingsSafe("RenderSpotShadowBias"); + connectRefreshCachedSettingsSafe("RenderEdgeDepthCutoff"); + connectRefreshCachedSettingsSafe("RenderEdgeNormCutoff"); + connectRefreshCachedSettingsSafe("RenderShadowGaussian"); + connectRefreshCachedSettingsSafe("RenderShadowBlurDistFactor"); + connectRefreshCachedSettingsSafe("RenderDeferredAtmospheric"); + connectRefreshCachedSettingsSafe("RenderHighlightFadeTime"); + connectRefreshCachedSettingsSafe("RenderFarClip"); + connectRefreshCachedSettingsSafe("RenderShadowSplitExponent"); + connectRefreshCachedSettingsSafe("RenderShadowErrorCutoff"); + connectRefreshCachedSettingsSafe("RenderShadowFOVCutoff"); + connectRefreshCachedSettingsSafe("CameraOffset"); + connectRefreshCachedSettingsSafe("CameraMaxCoF"); + connectRefreshCachedSettingsSafe("CameraDoFResScale"); + connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflections"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionIterations"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionRayStep"); @@ -560,11 +560,11 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionDepthRejectBias"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); connectRefreshCachedSettingsSafe("RenderScreenSpaceReflectionGlossySamples"); - connectRefreshCachedSettingsSafe("RenderBufferVisualization"); + connectRefreshCachedSettingsSafe("RenderBufferVisualization"); connectRefreshCachedSettingsSafe("RenderMirrors"); connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate"); connectRefreshCachedSettingsSafe("RenderHeroProbeConservativeUpdateMultiplier"); - gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderAutoHideSurfaceAreaLimit")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -573,78 +573,78 @@ LLPipeline::~LLPipeline() void LLPipeline::cleanup() { - assertInitialized(); - - mGroupQ1.clear() ; - - for(pool_set_t::iterator iter = mPools.begin(); - iter != mPools.end(); ) - { - pool_set_t::iterator curiter = iter++; - LLDrawPool* poolp = *curiter; - if (poolp->isFacePool()) - { - LLFacePool* face_pool = (LLFacePool*) poolp; - if (face_pool->mReferences.empty()) - { - mPools.erase(curiter); - removeFromQuickLookup( poolp ); - delete poolp; - } - } - else - { - mPools.erase(curiter); - removeFromQuickLookup( poolp ); - delete poolp; - } - } - - if (!mTerrainPools.empty()) - { - LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL; - } - if (!mTreePools.empty()) - { - LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL; - } - - delete mAlphaPoolPreWater; + assertInitialized(); + + mGroupQ1.clear() ; + + for(pool_set_t::iterator iter = mPools.begin(); + iter != mPools.end(); ) + { + pool_set_t::iterator curiter = iter++; + LLDrawPool* poolp = *curiter; + if (poolp->isFacePool()) + { + LLFacePool* face_pool = (LLFacePool*) poolp; + if (face_pool->mReferences.empty()) + { + mPools.erase(curiter); + removeFromQuickLookup( poolp ); + delete poolp; + } + } + else + { + mPools.erase(curiter); + removeFromQuickLookup( poolp ); + delete poolp; + } + } + + if (!mTerrainPools.empty()) + { + LL_WARNS() << "Terrain Pools not cleaned up" << LL_ENDL; + } + if (!mTreePools.empty()) + { + LL_WARNS() << "Tree Pools not cleaned up" << LL_ENDL; + } + + delete mAlphaPoolPreWater; mAlphaPoolPreWater = nullptr; delete mAlphaPoolPostWater; mAlphaPoolPostWater = nullptr; - delete mSkyPool; - mSkyPool = NULL; - delete mTerrainPool; - mTerrainPool = NULL; - delete mWaterPool; - mWaterPool = NULL; - delete mSimplePool; - mSimplePool = NULL; - delete mFullbrightPool; - mFullbrightPool = NULL; - delete mGlowPool; - mGlowPool = NULL; - delete mBumpPool; - mBumpPool = NULL; - // don't delete wl sky pool it was handled above in the for loop - //delete mWLSkyPool; - mWLSkyPool = NULL; - - releaseGLBuffers(); - - mFaceSelectImagep = NULL; + delete mSkyPool; + mSkyPool = NULL; + delete mTerrainPool; + mTerrainPool = NULL; + delete mWaterPool; + mWaterPool = NULL; + delete mSimplePool; + mSimplePool = NULL; + delete mFullbrightPool; + mFullbrightPool = NULL; + delete mGlowPool; + mGlowPool = NULL; + delete mBumpPool; + mBumpPool = NULL; + // don't delete wl sky pool it was handled above in the for loop + //delete mWLSkyPool; + mWLSkyPool = NULL; + + releaseGLBuffers(); + + mFaceSelectImagep = NULL; mMovedList.clear(); mMovedBridge.clear(); mShiftList.clear(); - mInitialized = false; + mInitialized = false; - mDeferredVB = NULL; + mDeferredVB = NULL; mScreenTriangleVB = nullptr; - mCubeVB = NULL; + mCubeVB = NULL; mReflectionMapManager.cleanup(); mHeroProbeManager.cleanup(); @@ -652,21 +652,21 @@ void LLPipeline::cleanup() //============================================================================ -void LLPipeline::destroyGL() +void LLPipeline::destroyGL() { - stop_glerror(); - unloadShaders(); - mHighlightFaces.clear(); - - resetDrawOrders(); + stop_glerror(); + unloadShaders(); + mHighlightFaces.clear(); + + resetDrawOrders(); - releaseGLBuffers(); + releaseGLBuffers(); - if (mMeshDirtyQueryObject) - { - glDeleteQueries(1, &mMeshDirtyQueryObject); - mMeshDirtyQueryObject = 0; - } + if (mMeshDirtyQueryObject) + { + glDeleteQueries(1, &mMeshDirtyQueryObject); + mMeshDirtyQueryObject = 0; + } } void LLPipeline::requestResizeScreenTexture() @@ -689,86 +689,86 @@ void LLPipeline::resizeShadowTexture() void LLPipeline::resizeScreenTexture() { - if (gPipeline.shadersLoaded()) - { - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - - if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight())) - { - releaseScreenBuffers(); + if (gPipeline.shadersLoaded()) + { + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + + if (gResizeScreenTexture || (resX != mRT->screen.getWidth()) || (resY != mRT->screen.getHeight())) + { + releaseScreenBuffers(); releaseSunShadowTargets(); releaseSpotShadowTargets(); - allocateScreenBuffer(resX,resY); + allocateScreenBuffer(resX,resY); gResizeScreenTexture = FALSE; - } - } + } + } } bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - eFBOStatus ret = doAllocateScreenBuffer(resX, resY); + eFBOStatus ret = doAllocateScreenBuffer(resX, resY); - return ret == FBO_SUCCESS_FULLRES; + return ret == FBO_SUCCESS_FULLRES; } LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - // try to allocate screen buffers at requested resolution and samples - // - on failure, shrink number of samples and try again - // - if not multisampled, shrink resolution and try again (favor X resolution over Y) - // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state + // try to allocate screen buffers at requested resolution and samples + // - on failure, shrink number of samples and try again + // - if not multisampled, shrink resolution and try again (favor X resolution over Y) + // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state // refresh cached settings here to protect against inconsistent event handling order refreshCachedSettings(); - U32 samples = RenderFSAASamples; - - eFBOStatus ret = FBO_SUCCESS_FULLRES; - if (!allocateScreenBuffer(resX, resY, samples)) - { - //failed to allocate at requested specification, return false - ret = FBO_FAILURE; - - releaseScreenBuffers(); - //reduce number of samples - while (samples > 0) - { - samples /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { //success - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - } - - samples = 0; - - //reduce resolution - while (resY > 0 && resX > 0) - { - resY /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - - resX /= 2; - if (allocateScreenBuffer(resX, resY, samples)) - { - return FBO_SUCCESS_LOWRES; - } - releaseScreenBuffers(); - } - - LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL; - } - - return ret; + U32 samples = RenderFSAASamples; + + eFBOStatus ret = FBO_SUCCESS_FULLRES; + if (!allocateScreenBuffer(resX, resY, samples)) + { + //failed to allocate at requested specification, return false + ret = FBO_FAILURE; + + releaseScreenBuffers(); + //reduce number of samples + while (samples > 0) + { + samples /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { //success + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + } + + samples = 0; + + //reduce resolution + while (resY > 0 && resX > 0) + { + resY /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + + resX /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return FBO_SUCCESS_LOWRES; + } + releaseScreenBuffers(); + } + + LL_WARNS() << "Unable to allocate screen buffer at any resolution!" << LL_ENDL; + } + + return ret; } bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) @@ -791,7 +791,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) U32 res = mReflectionMapManager.mProbeResolution * 4; //multiply by 4 because probes will be 16x super sampled allocateScreenBuffer(res, res, samples); - if (RenderMirrors) + if (RenderMirrors) { mHeroProbeManager.initReflectionMaps(); res = mHeroProbeManager.mProbeResolution; // We also scale the hero probe RT to the probe res since we don't super sample it. @@ -803,59 +803,59 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) gCubeSnapshot = FALSE; } - // remember these dimensions - mRT->width = resX; - mRT->height = resY; - - U32 res_mod = RenderResolutionDivisor; + // remember these dimensions + mRT->width = resX; + mRT->height = resY; + + U32 res_mod = RenderResolutionDivisor; - if (res_mod > 1 && res_mod < resX && res_mod < resY) - { - resX /= res_mod; - resY /= res_mod; - } + if (res_mod > 1 && res_mod < resX && res_mod < resY) + { + resX /= res_mod; + resY /= res_mod; + } //water reflection texture (always needed as scratch space whether or not transparent water is enabled) mWaterDis.allocate(resX, resY, GL_RGBA16F, true); - if (RenderUIBuffer) - { - if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA)) - { - return false; - } - } - - S32 shadow_detail = RenderShadowDetail; - bool ssao = RenderDeferredSSAO; - - //allocate deferred rendering color buffers - if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true)) return false; - if (!addDeferredAttachments(mRT->deferredScreen)) return false; - - GLuint screenFormat = GL_RGBA16F; - - if (!mRT->screen.allocate(resX, resY, screenFormat)) return false; + if (RenderUIBuffer) + { + if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA)) + { + return false; + } + } + + S32 shadow_detail = RenderShadowDetail; + bool ssao = RenderDeferredSSAO; + + //allocate deferred rendering color buffers + if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true)) return false; + if (!addDeferredAttachments(mRT->deferredScreen)) return false; + + GLuint screenFormat = GL_RGBA16F; + + if (!mRT->screen.allocate(resX, resY, screenFormat)) return false; mRT->deferredScreen.shareDepthBuffer(mRT->screen); - if (samples > 0) - { - if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA)) return false; - } - else - { - mRT->fxaaBuffer.release(); - } - - if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) - { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa - if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16F)) return false; - } - else - { - mRT->deferredLight.release(); - } + if (samples > 0) + { + if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA)) return false; + } + else + { + mRT->fxaaBuffer.release(); + } + + if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0) + { //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa + if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16F)) return false; + } + else + { + mRT->deferredLight.release(); + } allocateShadowBuffer(resX, resY); @@ -864,7 +864,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) mSceneMap.allocate(resX, resY, GL_RGB, true); } - const bool post_hdr = gSavedSettings.getBOOL("RenderPostProcessingHDR"); + const bool post_hdr = gSavedSettings.getBOOL("RenderPostProcessingHDR"); const U32 post_color_fmt = post_hdr ? GL_RGBA16F : GL_RGBA; mPostMap.allocate(resX, resY, post_color_fmt); @@ -876,9 +876,9 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) gGL.getTexUnit(0)->disable(); - stop_glerror(); + stop_glerror(); - return true; + return true; } // must be even to avoid a stripe in the horizontal shadow blur @@ -937,7 +937,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) // set up shadow map filtering and compare modes if (shadow_detail > 0) - { + { for (U32 i = 0; i < 4; i++) { LLRenderTarget* shadow_target = getSunShadowTarget(i); @@ -970,7 +970,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) } } - return true; + return true; } //static @@ -983,86 +983,86 @@ void LLPipeline::updateRenderTransparentWater() void LLPipeline::refreshCachedSettings() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; - LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); - LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); - LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); - LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors"); - LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); - - LLPipeline::sUseOcclusion = - (!gUseWireframe - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") - && gSavedSettings.getBOOL("UseOcclusion")) ? 2 : 0; - + LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); + LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); + LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); + LLVOAvatar::sMaxNonImpostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors"); + LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); + + LLPipeline::sUseOcclusion = + (!gUseWireframe + && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") + && gSavedSettings.getBOOL("UseOcclusion")) ? 2 : 0; + WindLightUseAtmosShaders = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders"); RenderDeferred = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred"); - RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); - RenderFSAASamples = LLFeatureManager::getInstance()->isFeatureAvailable("RenderFSAASamples") ? gSavedSettings.getU32("RenderFSAASamples") : 0; - RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); - RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); - RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); + RenderDeferredSunWash = gSavedSettings.getF32("RenderDeferredSunWash"); + RenderFSAASamples = LLFeatureManager::getInstance()->isFeatureAvailable("RenderFSAASamples") ? gSavedSettings.getU32("RenderFSAASamples") : 0; + RenderResolutionDivisor = gSavedSettings.getU32("RenderResolutionDivisor"); + RenderUIBuffer = gSavedSettings.getBOOL("RenderUIBuffer"); + RenderShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); RenderShadowSplits = gSavedSettings.getS32("RenderShadowSplits"); - RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO"); - RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale"); - RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation"); - RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes"); - FreezeTime = gSavedSettings.getBOOL("FreezeTime"); - DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth"); - RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness"); - RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor"); - RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness"); - RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"); - PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor"); - PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0"); - PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0"); - PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1"); - PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1"); - PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2"); - PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2"); - PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0"); - PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1"); - PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2"); - RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); - RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); - RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); - RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights"); - RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow"); - RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations"); - RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); - RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); - RenderGlowNoise = gSavedSettings.getBOOL("RenderGlowNoise"); - RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); - RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); - CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); - CameraFNumber = gSavedSettings.getF32("CameraFNumber"); - CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); - CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); - RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); - RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); - RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); - RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale"); - RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor"); - RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect"); - RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError"); - RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError"); - RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset"); - RenderShadowBias = gSavedSettings.getF32("RenderShadowBias"); - RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset"); - RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias"); - RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff"); - RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff"); - RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian"); - RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); - RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric"); - RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime"); - RenderFarClip = gSavedSettings.getF32("RenderFarClip"); - RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent"); - RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff"); - RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff"); - CameraOffset = gSavedSettings.getBOOL("CameraOffset"); - CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); - CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); - RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); + RenderDeferredSSAO = gSavedSettings.getBOOL("RenderDeferredSSAO"); + RenderShadowResolutionScale = gSavedSettings.getF32("RenderShadowResolutionScale"); + RenderDelayCreation = gSavedSettings.getBOOL("RenderDelayCreation"); + RenderAnimateRes = gSavedSettings.getBOOL("RenderAnimateRes"); + FreezeTime = gSavedSettings.getBOOL("FreezeTime"); + DebugBeaconLineWidth = gSavedSettings.getS32("DebugBeaconLineWidth"); + RenderHighlightBrightness = gSavedSettings.getF32("RenderHighlightBrightness"); + RenderHighlightColor = gSavedSettings.getColor4("RenderHighlightColor"); + RenderHighlightThickness = gSavedSettings.getF32("RenderHighlightThickness"); + RenderSpotLightsInNondeferred = gSavedSettings.getBOOL("RenderSpotLightsInNondeferred"); + PreviewAmbientColor = gSavedSettings.getColor4("PreviewAmbientColor"); + PreviewDiffuse0 = gSavedSettings.getColor4("PreviewDiffuse0"); + PreviewSpecular0 = gSavedSettings.getColor4("PreviewSpecular0"); + PreviewDiffuse1 = gSavedSettings.getColor4("PreviewDiffuse1"); + PreviewSpecular1 = gSavedSettings.getColor4("PreviewSpecular1"); + PreviewDiffuse2 = gSavedSettings.getColor4("PreviewDiffuse2"); + PreviewSpecular2 = gSavedSettings.getColor4("PreviewSpecular2"); + PreviewDirection0 = gSavedSettings.getVector3("PreviewDirection0"); + PreviewDirection1 = gSavedSettings.getVector3("PreviewDirection1"); + PreviewDirection2 = gSavedSettings.getVector3("PreviewDirection2"); + RenderGlowMaxExtractAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha"); + RenderGlowWarmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount"); + RenderGlowLumWeights = gSavedSettings.getVector3("RenderGlowLumWeights"); + RenderGlowWarmthWeights = gSavedSettings.getVector3("RenderGlowWarmthWeights"); + RenderGlowResolutionPow = gSavedSettings.getS32("RenderGlowResolutionPow"); + RenderGlowIterations = gSavedSettings.getS32("RenderGlowIterations"); + RenderGlowWidth = gSavedSettings.getF32("RenderGlowWidth"); + RenderGlowStrength = gSavedSettings.getF32("RenderGlowStrength"); + RenderGlowNoise = gSavedSettings.getBOOL("RenderGlowNoise"); + RenderDepthOfField = gSavedSettings.getBOOL("RenderDepthOfField"); + RenderDepthOfFieldInEditMode = gSavedSettings.getBOOL("RenderDepthOfFieldInEditMode"); + CameraFocusTransitionTime = gSavedSettings.getF32("CameraFocusTransitionTime"); + CameraFNumber = gSavedSettings.getF32("CameraFNumber"); + CameraFocalLength = gSavedSettings.getF32("CameraFocalLength"); + CameraFieldOfView = gSavedSettings.getF32("CameraFieldOfView"); + RenderShadowNoise = gSavedSettings.getF32("RenderShadowNoise"); + RenderShadowBlurSize = gSavedSettings.getF32("RenderShadowBlurSize"); + RenderSSAOScale = gSavedSettings.getF32("RenderSSAOScale"); + RenderSSAOMaxScale = gSavedSettings.getU32("RenderSSAOMaxScale"); + RenderSSAOFactor = gSavedSettings.getF32("RenderSSAOFactor"); + RenderSSAOEffect = gSavedSettings.getVector3("RenderSSAOEffect"); + RenderShadowOffsetError = gSavedSettings.getF32("RenderShadowOffsetError"); + RenderShadowBiasError = gSavedSettings.getF32("RenderShadowBiasError"); + RenderShadowOffset = gSavedSettings.getF32("RenderShadowOffset"); + RenderShadowBias = gSavedSettings.getF32("RenderShadowBias"); + RenderSpotShadowOffset = gSavedSettings.getF32("RenderSpotShadowOffset"); + RenderSpotShadowBias = gSavedSettings.getF32("RenderSpotShadowBias"); + RenderEdgeDepthCutoff = gSavedSettings.getF32("RenderEdgeDepthCutoff"); + RenderEdgeNormCutoff = gSavedSettings.getF32("RenderEdgeNormCutoff"); + RenderShadowGaussian = gSavedSettings.getVector3("RenderShadowGaussian"); + RenderShadowBlurDistFactor = gSavedSettings.getF32("RenderShadowBlurDistFactor"); + RenderDeferredAtmospheric = gSavedSettings.getBOOL("RenderDeferredAtmospheric"); + RenderHighlightFadeTime = gSavedSettings.getF32("RenderHighlightFadeTime"); + RenderFarClip = gSavedSettings.getF32("RenderFarClip"); + RenderShadowSplitExponent = gSavedSettings.getVector3("RenderShadowSplitExponent"); + RenderShadowErrorCutoff = gSavedSettings.getF32("RenderShadowErrorCutoff"); + RenderShadowFOVCutoff = gSavedSettings.getF32("RenderShadowFOVCutoff"); + CameraOffset = gSavedSettings.getBOOL("CameraOffset"); + CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF"); + CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale"); + RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit"); RenderScreenSpaceReflections = gSavedSettings.getBOOL("RenderScreenSpaceReflections"); RenderScreenSpaceReflectionIterations = gSavedSettings.getS32("RenderScreenSpaceReflectionIterations"); RenderScreenSpaceReflectionRayStep = gSavedSettings.getF32("RenderScreenSpaceReflectionRayStep"); @@ -1070,7 +1070,7 @@ void LLPipeline::refreshCachedSettings() RenderScreenSpaceReflectionDepthRejectBias = gSavedSettings.getF32("RenderScreenSpaceReflectionDepthRejectBias"); RenderScreenSpaceReflectionAdaptiveStepMultiplier = gSavedSettings.getF32("RenderScreenSpaceReflectionAdaptiveStepMultiplier"); RenderScreenSpaceReflectionGlossySamples = gSavedSettings.getS32("RenderScreenSpaceReflectionGlossySamples"); - RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); + RenderBufferVisualization = gSavedSettings.getS32("RenderBufferVisualization"); if (gSavedSettings.getBOOL("RenderMirrors") != (BOOL)RenderMirrors) { RenderMirrors = gSavedSettings.getBOOL("RenderMirrors"); @@ -1081,57 +1081,57 @@ void LLPipeline::refreshCachedSettings() RenderHeroProbeConservativeUpdateMultiplier = gSavedSettings.getS32("RenderHeroProbeConservativeUpdateMultiplier"); sReflectionProbesEnabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionsEnabled") && gSavedSettings.getBOOL("RenderReflectionsEnabled"); - RenderSpotLight = nullptr; + RenderSpotLight = nullptr; - if (gNonInteractive) - { - LLVOAvatar::sMaxNonImpostors = 1; - LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); - } + if (gNonInteractive) + { + LLVOAvatar::sMaxNonImpostors = 1; + LLVOAvatar::updateImpostorRendering(LLVOAvatar::sMaxNonImpostors); + } } void LLPipeline::releaseGLBuffers() { - assertInitialized(); - - if (mNoiseMap) - { - LLImageGL::deleteTextures(1, &mNoiseMap); - mNoiseMap = 0; - } + assertInitialized(); + + if (mNoiseMap) + { + LLImageGL::deleteTextures(1, &mNoiseMap); + mNoiseMap = 0; + } + + if (mTrueNoiseMap) + { + LLImageGL::deleteTextures(1, &mTrueNoiseMap); + mTrueNoiseMap = 0; + } - if (mTrueNoiseMap) - { - LLImageGL::deleteTextures(1, &mTrueNoiseMap); - mTrueNoiseMap = 0; - } + releaseLUTBuffers(); - releaseLUTBuffers(); + mWaterDis.release(); - mWaterDis.release(); - mSceneMap.release(); mPostMap.release(); - for (U32 i = 0; i < 3; i++) - { - mGlow[i].release(); - } + for (U32 i = 0; i < 3; i++) + { + mGlow[i].release(); + } - releaseScreenBuffers(); + releaseScreenBuffers(); - gBumpImageList.destroyGL(); - LLVOAvatar::resetImpostors(); + gBumpImageList.destroyGL(); + LLVOAvatar::resetImpostors(); } void LLPipeline::releaseLUTBuffers() { - if (mLightFunc) - { - LLImageGL::deleteTextures(1, &mLightFunc); - mLightFunc = 0; - } + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } mPbrBrdfLut.release(); @@ -1155,11 +1155,11 @@ void LLPipeline::releaseScreenBuffers() mRT->deferredScreen.release(); mRT->deferredLight.release(); - mHeroProbeRT.uiScreen.release(); - mHeroProbeRT.screen.release(); - mHeroProbeRT.fxaaBuffer.release(); - mHeroProbeRT.deferredScreen.release(); - mHeroProbeRT.deferredLight.release(); + mHeroProbeRT.uiScreen.release(); + mHeroProbeRT.screen.release(); + mHeroProbeRT.fxaaBuffer.release(); + mHeroProbeRT.deferredScreen.release(); + mHeroProbeRT.deferredLight.release(); } void LLPipeline::releaseSunShadowTarget(U32 index) @@ -1170,10 +1170,10 @@ void LLPipeline::releaseSunShadowTarget(U32 index) void LLPipeline::releaseSunShadowTargets() { - for (U32 i = 0; i < 4; i++) - { + for (U32 i = 0; i < 4; i++) + { releaseSunShadowTarget(i); - } + } } void LLPipeline::releaseSpotShadowTargets() @@ -1191,16 +1191,16 @@ void LLPipeline::createGLBuffers() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; stop_glerror(); - assertInitialized(); + assertInitialized(); - stop_glerror(); + stop_glerror(); - GLuint resX = gViewerWindow->getWorldViewWidthRaw(); - GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); // allocate screen space glow buffers const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow"))); - const bool glow_hdr = gSavedSettings.getBOOL("RenderGlowHDR"); + const bool glow_hdr = gSavedSettings.getBOOL("RenderGlowHDR"); const U32 glow_color_fmt = glow_hdr ? GL_RGBA16F : GL_RGBA; for (U32 i = 0; i < 3; i++) { @@ -1211,100 +1211,100 @@ void LLPipeline::createGLBuffers() mRT->width = 0; mRT->height = 0; - - if (!mNoiseMap) - { - const U32 noiseRes = 128; - LLVector3 noise[noiseRes*noiseRes]; - - F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; - for (U32 i = 0; i < noiseRes*noiseRes; ++i) - { - noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); - noise[i].normVec(); - noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; - } - - LLImageGL::generateTextures(1, &mNoiseMap); - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - if (!mTrueNoiseMap) - { - const U32 noiseRes = 128; - F32 noise[noiseRes*noiseRes*3]; - for (U32 i = 0; i < noiseRes*noiseRes*3; i++) - { - noise[i] = ll_frand()*2.0-1.0; - } - - LLImageGL::generateTextures(1, &mTrueNoiseMap); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - - createLUTBuffers(); - - gBumpImageList.restoreGL(); + + if (!mNoiseMap) + { + const U32 noiseRes = 128; + LLVector3 noise[noiseRes*noiseRes]; + + F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f; + for (U32 i = 0; i < noiseRes*noiseRes; ++i) + { + noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f); + noise[i].normVec(); + noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f; + } + + LLImageGL::generateTextures(1, &mNoiseMap); + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + if (!mTrueNoiseMap) + { + const U32 noiseRes = 128; + F32 noise[noiseRes*noiseRes*3]; + for (U32 i = 0; i < noiseRes*noiseRes*3; i++) + { + noise[i] = ll_frand()*2.0-1.0; + } + + LLImageGL::generateTextures(1, &mTrueNoiseMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise, false); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + createLUTBuffers(); + + gBumpImageList.restoreGL(); } F32 lerpf(F32 a, F32 b, F32 w) { - return a + w * (b - a); + return a + w * (b - a); } void LLPipeline::createLUTBuffers() { - if (!mLightFunc) - { - U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); - U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); - F32* ls = new F32[lightResX*lightResY]; - F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); + if (!mLightFunc) + { + U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); + U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); + F32* ls = new F32[lightResX*lightResY]; + F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks) - for (U32 y = 0; y < lightResY; ++y) - { - for (U32 x = 0; x < lightResX; ++x) - { - ls[y*lightResX+x] = 0; - F32 sa = (F32) x/(lightResX-1); - F32 spec = (F32) y/(lightResY-1); - F32 n = spec * spec * specExp; - - // Nothing special here. Just your typical blinn-phong term. - spec = powf(sa, n); - - // Apply our normalization function. - // Note: This is the full equation that applies the full normalization curve, not an approximation. - // This is fine, given we only need to create our LUT once per buffer initialization. - spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); - - // Since we use R16F, we no longer have a dynamic range issue we need to work around here. - // Though some older drivers may not like this, newer drivers shouldn't have this problem. - ls[y*lightResX+x] = spec; - } - } - - U32 pix_format = GL_R16F; + for (U32 y = 0; y < lightResY; ++y) + { + for (U32 x = 0; x < lightResX; ++x) + { + ls[y*lightResX+x] = 0; + F32 sa = (F32) x/(lightResX-1); + F32 spec = (F32) y/(lightResY-1); + F32 n = spec * spec * specExp; + + // Nothing special here. Just your typical blinn-phong term. + spec = powf(sa, n); + + // Apply our normalization function. + // Note: This is the full equation that applies the full normalization curve, not an approximation. + // This is fine, given we only need to create our LUT once per buffer initialization. + spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n))); + + // Since we use R16F, we no longer have a dynamic range issue we need to work around here. + // Though some older drivers may not like this, newer drivers shouldn't have this problem. + ls[y*lightResX+x] = spec; + } + } + + U32 pix_format = GL_R16F; #if LL_DARWIN - // Need to work around limited precision with 10.6.8 and older drivers - // - pix_format = GL_R32F; + // Need to work around limited precision with 10.6.8 and older drivers + // + pix_format = GL_R32F; #endif - LLImageGL::generateTextures(1, &mLightFunc); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); - LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - delete [] ls; - } + LLImageGL::generateTextures(1, &mLightFunc); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, pix_format, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + delete [] ls; + } mPbrBrdfLut.allocate(512, 512, GL_RG16F); mPbrBrdfLut.bindTarget(); @@ -1336,23 +1336,23 @@ void LLPipeline::createLUTBuffers() void LLPipeline::restoreGL() { - assertInitialized(); + assertInitialized(); - LLViewerShaderMgr::instance()->setShaders(); + LLViewerShaderMgr::instance()->setShaders(); - 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->restoreGL(); - } - } - } + 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->restoreGL(); + } + } + } } bool LLPipeline::shadersLoaded() @@ -1367,338 +1367,338 @@ bool LLPipeline::canUseWindLightShaders() const bool LLPipeline::canUseAntiAliasing() const { - return true; + return true; } void LLPipeline::unloadShaders() { - LLViewerShaderMgr::instance()->unloadShaders(); - mShadersLoaded = false; + LLViewerShaderMgr::instance()->unloadShaders(); + mShadersLoaded = false; } void LLPipeline::assertInitializedDoError() { - LL_ERRS() << "LLPipeline used when uninitialized." << LL_ENDL; + LL_ERRS() << "LLPipeline used when uninitialized." << LL_ENDL; } //============================================================================ void LLPipeline::enableShadows(const bool enable_shadows) { - //should probably do something here to wrangle shadows.... + //should probably do something here to wrangle shadows.... } class LLOctreeDirtyTexture : public OctreeTraveler { public: - const std::set& mTextures; - - LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } - - virtual void visit(const OctreeNode* node) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) - { - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - LLDrawInfo* params = *j; - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture); - if (tex && mTextures.find(tex) != mTextures.end()) - { - group->setState(LLSpatialGroup::GEOM_DIRTY); - } - } - } - } - - for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) - { - LLSpatialBridge* bridge = *i; - traverse(bridge->mOctree); - } - } + const std::set& mTextures; + + LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } + + virtual void visit(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) + { + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* params = *j; + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params->mTexture); + if (tex && mTextures.find(tex) != mTextures.end()) + { + group->setState(LLSpatialGroup::GEOM_DIRTY); + } + } + } + } + + for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) + { + LLSpatialBridge* bridge = *i; + traverse(bridge->mOctree); + } + } }; // Called when a texture changes # of channels (causes faces to move to alpha pool) void LLPipeline::dirtyPoolObjectTextures(const std::set& textures) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - - // *TODO: This is inefficient and causes frame spikes; need a better way to do this - // Most of the time is spent in dirty.traverse. - - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (poolp->isFacePool()) - { - ((LLFacePool*) poolp)->dirtyTextures(textures); - } - } - - LLOctreeDirtyTexture dirty(textures); - 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) - { - dirty.traverse(part->mOctree); - } - } - } + assertInitialized(); + + // *TODO: This is inefficient and causes frame spikes; need a better way to do this + // Most of the time is spent in dirty.traverse. + + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (poolp->isFacePool()) + { + ((LLFacePool*) poolp)->dirtyTextures(textures); + } + } + + LLOctreeDirtyTexture dirty(textures); + 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) + { + dirty.traverse(part->mOctree); + } + } + } } LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) { - assertInitialized(); - - LLDrawPool *poolp = NULL; - switch( type ) - { - case LLDrawPool::POOL_SIMPLE: - poolp = mSimplePool; - break; - - case LLDrawPool::POOL_GRASS: - poolp = mGrassPool; - break; - - case LLDrawPool::POOL_ALPHA_MASK: - poolp = mAlphaMaskPool; - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - poolp = mFullbrightAlphaMaskPool; - break; - - case LLDrawPool::POOL_FULLBRIGHT: - poolp = mFullbrightPool; - break; - - case LLDrawPool::POOL_GLOW: - poolp = mGlowPool; - break; - - case LLDrawPool::POOL_TREE: - poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - - case LLDrawPool::POOL_TERRAIN: - poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - - case LLDrawPool::POOL_BUMP: - poolp = mBumpPool; - break; - case LLDrawPool::POOL_MATERIALS: - poolp = mMaterialsPool; - break; - case LLDrawPool::POOL_ALPHA_PRE_WATER: - poolp = mAlphaPoolPreWater; - break; + assertInitialized(); + + LLDrawPool *poolp = NULL; + switch( type ) + { + case LLDrawPool::POOL_SIMPLE: + poolp = mSimplePool; + break; + + case LLDrawPool::POOL_GRASS: + poolp = mGrassPool; + break; + + case LLDrawPool::POOL_ALPHA_MASK: + poolp = mAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + poolp = mFullbrightAlphaMaskPool; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + poolp = mFullbrightPool; + break; + + case LLDrawPool::POOL_GLOW: + poolp = mGlowPool; + break; + + case LLDrawPool::POOL_TREE: + poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); + break; + + case LLDrawPool::POOL_TERRAIN: + poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); + break; + + case LLDrawPool::POOL_BUMP: + poolp = mBumpPool; + break; + case LLDrawPool::POOL_MATERIALS: + poolp = mMaterialsPool; + break; + case LLDrawPool::POOL_ALPHA_PRE_WATER: + poolp = mAlphaPoolPreWater; + break; case LLDrawPool::POOL_ALPHA_POST_WATER: poolp = mAlphaPoolPostWater; break; - case LLDrawPool::POOL_AVATAR: - case LLDrawPool::POOL_CONTROL_AV: - break; // Do nothing + case LLDrawPool::POOL_AVATAR: + case LLDrawPool::POOL_CONTROL_AV: + break; // Do nothing - case LLDrawPool::POOL_SKY: - poolp = mSkyPool; - break; + case LLDrawPool::POOL_SKY: + poolp = mSkyPool; + break; - case LLDrawPool::POOL_WATER: - poolp = mWaterPool; - break; + case LLDrawPool::POOL_WATER: + poolp = mWaterPool; + break; - case LLDrawPool::POOL_WL_SKY: - poolp = mWLSkyPool; - break; + case LLDrawPool::POOL_WL_SKY: + poolp = mWLSkyPool; + break; - case LLDrawPool::POOL_GLTF_PBR: - poolp = mPBROpaquePool; - break; + case LLDrawPool::POOL_GLTF_PBR: + poolp = mPBROpaquePool; + break; case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK: poolp = mPBRAlphaMaskPool; break; - default: - llassert(0); - LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; - break; - } + default: + llassert(0); + LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; + break; + } - return poolp; + return poolp; } -LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0) +LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerTexture *tex0) { - LLDrawPool *poolp = findPool(type, tex0); - if (poolp) - { - return poolp; - } + LLDrawPool *poolp = findPool(type, tex0); + if (poolp) + { + return poolp; + } - LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); - addPool( new_poolp ); + LLDrawPool *new_poolp = LLDrawPool::createPool(type, tex0); + addPool( new_poolp ); - return new_poolp; + return new_poolp; } // static LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* imagep) { - U32 type = getPoolTypeFromTE(te, imagep); - return gPipeline.getPool(type, imagep); + U32 type = getPoolTypeFromTE(te, imagep); + return gPipeline.getPool(type, imagep); } -//static +//static U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep) { - if (!te || !imagep) - { - return 0; - } - - LLMaterial* mat = te->getMaterialParams().get(); + if (!te || !imagep) + { + return 0; + } + + LLMaterial* mat = te->getMaterialParams().get(); LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); - bool color_alpha = te->getColor().mV[3] < 0.999f; - bool alpha = color_alpha; - if (imagep) - { - alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); - } - - if (alpha && mat) - { - switch (mat->getDiffuseAlphaMode()) - { - case 1: - alpha = true; // Material's alpha mode is set to blend. Toss it into the alpha draw pool. - break; - case 0: //alpha mode set to none, never go to alpha pool - case 3: //alpha mode set to emissive, never go to alpha pool - alpha = color_alpha; - break; - default: //alpha mode set to "mask", go to alpha pool if fullbright - alpha = color_alpha; // Material's alpha mode is set to none, mask, or emissive. Toss it into the opaque material draw pool. - break; - } - } - - if (alpha || (gltf_mat && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND)) - { - return LLDrawPool::POOL_ALPHA; - } - else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) - { - return LLDrawPool::POOL_BUMP; - } + bool color_alpha = te->getColor().mV[3] < 0.999f; + bool alpha = color_alpha; + if (imagep) + { + alpha = alpha || (imagep->getComponents() == 4 && imagep->getType() != LLViewerTexture::MEDIA_TEXTURE) || (imagep->getComponents() == 2); + } + + if (alpha && mat) + { + switch (mat->getDiffuseAlphaMode()) + { + case 1: + alpha = true; // Material's alpha mode is set to blend. Toss it into the alpha draw pool. + break; + case 0: //alpha mode set to none, never go to alpha pool + case 3: //alpha mode set to emissive, never go to alpha pool + alpha = color_alpha; + break; + default: //alpha mode set to "mask", go to alpha pool if fullbright + alpha = color_alpha; // Material's alpha mode is set to none, mask, or emissive. Toss it into the opaque material draw pool. + break; + } + } + + if (alpha || (gltf_mat && gltf_mat->mAlphaMode == LLGLTFMaterial::ALPHA_MODE_BLEND)) + { + return LLDrawPool::POOL_ALPHA; + } + else if ((te->getBumpmap() || te->getShiny()) && (!mat || mat->getNormalID().isNull())) + { + return LLDrawPool::POOL_BUMP; + } else if (gltf_mat) { return LLDrawPool::POOL_GLTF_PBR; } - else if (mat && !alpha) - { - return LLDrawPool::POOL_MATERIALS; - } - else - { - return LLDrawPool::POOL_SIMPLE; - } + else if (mat && !alpha) + { + return LLDrawPool::POOL_MATERIALS; + } + else + { + return LLDrawPool::POOL_SIMPLE; + } } void LLPipeline::addPool(LLDrawPool *new_poolp) { - assertInitialized(); - mPools.insert(new_poolp); - addToQuickLookup( new_poolp ); + assertInitialized(); + mPools.insert(new_poolp); + addToQuickLookup( new_poolp ); } void LLPipeline::allocDrawable(LLViewerObject *vobj) { - LLDrawable *drawable = new LLDrawable(vobj); - vobj->mDrawable = drawable; - - //encompass completely sheared objects by taking - //the most extreme point possible (<1,1,0.5>) - drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); - if (vobj->isOrphaned()) - { - drawable->setState(LLDrawable::FORCE_INVISIBLE); - } - drawable->updateXform(TRUE); -} + LLDrawable *drawable = new LLDrawable(vobj); + vobj->mDrawable = drawable; + + //encompass completely sheared objects by taking + //the most extreme point possible (<1,1,0.5>) + drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); + if (vobj->isOrphaned()) + { + drawable->setState(LLDrawable::FORCE_INVISIBLE); + } + drawable->updateXform(TRUE); +} void LLPipeline::unlinkDrawable(LLDrawable *drawable) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - - LLPointer drawablep = drawable; // make sure this doesn't get deleted before we are done - - // Based on flags, remove the drawable from the queues that it's on. - if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); - if (iter != mMovedList.end()) - { - mMovedList.erase(iter); - } - } - - if (drawablep->getSpatialGroup()) - { - if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) - { + assertInitialized(); + + LLPointer drawablep = drawable; // make sure this doesn't get deleted before we are done + + // Based on flags, remove the drawable from the queues that it's on. + if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); + if (iter != mMovedList.end()) + { + mMovedList.erase(iter); + } + } + + if (drawablep->getSpatialGroup()) + { + if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) + { #ifdef LL_RELEASE_FOR_DOWNLOAD - LL_WARNS() << "Couldn't remove object from spatial group!" << LL_ENDL; + LL_WARNS() << "Couldn't remove object from spatial group!" << LL_ENDL; #else - LL_ERRS() << "Couldn't remove object from spatial group!" << LL_ENDL; + LL_ERRS() << "Couldn't remove object from spatial group!" << LL_ENDL; #endif - } - } - - mLights.erase(drawablep); - - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - if (iter->drawable == drawablep) - { - mNearbyLights.erase(iter); - break; - } - } - - for (U32 i = 0; i < 2; ++i) - { - if (mShadowSpotLight[i] == drawablep) - { - mShadowSpotLight[i] = NULL; - } - - if (mTargetShadowSpotLight[i] == drawablep) - { - mTargetShadowSpotLight[i] = NULL; - } - } + } + } + + mLights.erase(drawablep); + + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + if (iter->drawable == drawablep) + { + mNearbyLights.erase(iter); + break; + } + } + + for (U32 i = 0; i < 2; ++i) + { + if (mShadowSpotLight[i] == drawablep) + { + mShadowSpotLight[i] = NULL; + } + + if (mTargetShadowSpotLight[i] == drawablep) + { + mTargetShadowSpotLight[i] = NULL; + } + } } //static @@ -1726,239 +1726,239 @@ void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) U32 LLPipeline::addObject(LLViewerObject *vobj) { - if (RenderDelayCreation) - { - mCreateQ.push_back(vobj); - } - else - { - createObject(vobj); - } + if (RenderDelayCreation) + { + mCreateQ.push_back(vobj); + } + else + { + createObject(vobj); + } - return 1; + return 1; } void LLPipeline::createObjects(F32 max_dtime) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - LLTimer update_timer; + LLTimer update_timer; + + while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) + { + LLViewerObject* vobj = mCreateQ.front(); + if (!vobj->isDead()) + { + createObject(vobj); + } + mCreateQ.pop_front(); + } - while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime) - { - LLViewerObject* vobj = mCreateQ.front(); - if (!vobj->isDead()) - { - createObject(vobj); - } - mCreateQ.pop_front(); - } - - //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) - //{ - // createObject(*iter); - //} + //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter) + //{ + // createObject(*iter); + //} - //mCreateQ.clear(); + //mCreateQ.clear(); } void LLPipeline::createObject(LLViewerObject* vobj) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - LLDrawable* drawablep = vobj->mDrawable; - - if (!drawablep) - { - drawablep = vobj->createDrawable(this); - } - else - { - LL_ERRS() << "Redundant drawable creation!" << LL_ENDL; - } - - llassert(drawablep); - - if (vobj->getParent()) - { - vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 - } - else - { - vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 - } - - markRebuild(drawablep, LLDrawable::REBUILD_ALL); - - if (drawablep->getVOVolume() && RenderAnimateRes) - { - // fun animated res - drawablep->updateXform(TRUE); - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); - drawablep->setScale(LLVector3(0,0,0)); - drawablep->makeActive(); - } + LLDrawable* drawablep = vobj->mDrawable; + + if (!drawablep) + { + drawablep = vobj->createDrawable(this); + } + else + { + LL_ERRS() << "Redundant drawable creation!" << LL_ENDL; + } + + llassert(drawablep); + + if (vobj->getParent()) + { + vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 + } + else + { + vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 + } + + markRebuild(drawablep, LLDrawable::REBUILD_ALL); + + if (drawablep->getVOVolume() && RenderAnimateRes) + { + // fun animated res + drawablep->updateXform(TRUE); + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + drawablep->setScale(LLVector3(0,0,0)); + drawablep->makeActive(); + } } void LLPipeline::resetFrameStats() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); + assertInitialized(); - sCompiles = 0; - mNumVisibleFaces = 0; + sCompiles = 0; + mNumVisibleFaces = 0; - if (mOldRenderDebugMask != mRenderDebugMask) - { - gObjectList.clearDebugText(); - mOldRenderDebugMask = mRenderDebugMask; - } + if (mOldRenderDebugMask != mRenderDebugMask) + { + gObjectList.clearDebugText(); + mOldRenderDebugMask = mRenderDebugMask; + } } //external functions for asynchronous updating void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) { LL_PROFILE_ZONE_SCOPED; - if (FreezeTime) - { - return; - } - if (!drawablep) - { - LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; - return; - } - if (drawablep->isState(LLDrawable::EARLY_MOVE)) - { - return; - } - - assertInitialized(); - - // update drawable now - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED - drawablep->updateMove(); // returns done - drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame - // Put on move list so that EARLY_MOVE gets cleared - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - mMovedList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } + if (FreezeTime) + { + return; + } + if (!drawablep) + { + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; + return; + } + if (drawablep->isState(LLDrawable::EARLY_MOVE)) + { + return; + } + + assertInitialized(); + + // update drawable now + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); // force to DAMPED + drawablep->updateMove(); // returns done + drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame + // Put on move list so that EARLY_MOVE gets cleared + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + mMovedList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } } void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) { LL_PROFILE_ZONE_SCOPED; - if (FreezeTime) - { - return; - } - if (!drawablep) - { - LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; - return; - } - if (drawablep->isState(LLDrawable::EARLY_MOVE)) - { - return; - } - - assertInitialized(); - - // update drawable now - drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED - drawablep->updateMove(); - drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame - // Put on move list so that EARLY_MOVE gets cleared - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - mMovedList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } + if (FreezeTime) + { + return; + } + if (!drawablep) + { + LL_ERRS() << "updateMove called with NULL drawablep" << LL_ENDL; + return; + } + if (drawablep->isState(LLDrawable::EARLY_MOVE)) + { + return; + } + + assertInitialized(); + + // update drawable now + drawablep->setState(LLDrawable::MOVE_UNDAMPED); // force to UNDAMPED + drawablep->updateMove(); + drawablep->setState(LLDrawable::EARLY_MOVE); // flag says we already did an undamped move this frame + // Put on move list so that EARLY_MOVE gets cleared + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + mMovedList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } } void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) { LL_PROFILE_ZONE_SCOPED; - for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); - iter != moved_list.end(); ) - { - LLDrawable::drawable_vector_t::iterator curiter = iter++; - LLDrawable *drawablep = *curiter; - bool done = true; - if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) - { - done = drawablep->updateMove(); - } - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); - if (done) - { - if (drawablep->isRoot() && !drawablep->isState(LLDrawable::ACTIVE)) - { - drawablep->makeStatic(); - } - drawablep->clearState(LLDrawable::ON_MOVE_LIST); - if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) - { //will likely not receive any future world matrix updates - // -- this keeps attachments from getting stuck in space and falling off your avatar - drawablep->clearState(LLDrawable::ANIMATED_CHILD); - markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); - if (drawablep->getVObj()) - { - drawablep->getVObj()->dirtySpatialGroup(); - } - } - iter = moved_list.erase(curiter); - } - } + for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); + iter != moved_list.end(); ) + { + LLDrawable::drawable_vector_t::iterator curiter = iter++; + LLDrawable *drawablep = *curiter; + bool done = true; + if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) + { + done = drawablep->updateMove(); + } + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); + if (done) + { + if (drawablep->isRoot() && !drawablep->isState(LLDrawable::ACTIVE)) + { + drawablep->makeStatic(); + } + drawablep->clearState(LLDrawable::ON_MOVE_LIST); + if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) + { //will likely not receive any future world matrix updates + // -- this keeps attachments from getting stuck in space and falling off your avatar + drawablep->clearState(LLDrawable::ANIMATED_CHILD); + markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + if (drawablep->getVObj()) + { + drawablep->getVObj()->dirtySpatialGroup(); + } + } + iter = moved_list.erase(curiter); + } + } } void LLPipeline::updateMove() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - if (FreezeTime) - { - return; - } - - assertInitialized(); - - for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); - iter != mRetexturedList.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->updateTexture(); - } - } - mRetexturedList.clear(); - - updateMovedList(mMovedList); - - //balance octrees - 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->mOctree->balance(); - } - } - - //balance the VO Cache tree - LLVOCachePartition* vo_part = region->getVOCachePartition(); - if(vo_part) - { - vo_part->mOctree->balance(); - } - } + if (FreezeTime) + { + return; + } + + assertInitialized(); + + for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); + iter != mRetexturedList.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->updateTexture(); + } + } + mRetexturedList.clear(); + + updateMovedList(mMovedList); + + //balance octrees + 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->mOctree->balance(); + } + } + + //balance the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->mOctree->balance(); + } + } } ///////////////////////////////////////////////////////////////////////////// @@ -1969,299 +1969,299 @@ void LLPipeline::updateMove() F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera) { llassert(!gCubeSnapshot); // shouldn't be doing ANY of this during cube snap shots - LLVector3 lookAt = center - camera.getOrigin(); - F32 dist = lookAt.length(); + LLVector3 lookAt = center - camera.getOrigin(); + F32 dist = lookAt.length(); - //ramp down distance for nearby objects - //shrink dist by dist/16. - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } + //ramp down distance for nearby objects + //shrink dist by dist/16. + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } - //get area of circle around node - F32 app_angle = atanf(size.length()/dist); - F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * F_PI; + //get area of circle around node + F32 app_angle = atanf(size.length()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * F_PI; } //static F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera) { - LLVector4a origin; - origin.load3(camera.getOrigin().mV); + LLVector4a origin; + origin.load3(camera.getOrigin().mV); - LLVector4a lookAt; - lookAt.setSub(center, origin); - F32 dist = lookAt.getLength3().getF32(); + LLVector4a lookAt; + lookAt.setSub(center, origin); + F32 dist = lookAt.getLength3().getF32(); - //ramp down distance for nearby objects - //shrink dist by dist/16. - if (dist < 16.f) - { - dist /= 16.f; - dist *= dist; - dist *= 16.f; - } + //ramp down distance for nearby objects + //shrink dist by dist/16. + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } - //get area of circle around node - F32 app_angle = atanf(size.getLength3().getF32()/dist); - F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * F_PI; + //get area of circle around node + F32 app_angle = atanf(size.getLength3().getF32()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * F_PI; } void LLPipeline::grabReferences(LLCullResult& result) { - sCull = &result; + sCull = &result; } void LLPipeline::clearReferences() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - sCull = NULL; - mGroupSaveQ1.clear(); + sCull = NULL; + mGroupSaveQ1.clear(); } void check_references(LLSpatialGroup* group, LLDrawable* drawable) { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); - if (drawable == drawablep) - { - LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL; - } - } + if (drawable == drawablep) + { + LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL; + } + } } void check_references(LLDrawable* drawable, LLFace* face) { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - if (drawable->getFace(i) == face) - { - LL_ERRS() << "LLFace deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + if (drawable->getFace(i) == face) + { + LL_ERRS() << "LLFace deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } } void check_references(LLSpatialGroup* group, LLFace* face) { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); - if(drawable) - { - check_references(drawable, face); - } + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(drawable) + { + check_references(drawable, face); + } } } void LLPipeline::checkReferences(LLFace* face) { #if 0 - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, face); - } - - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) - { - LLDrawable* drawable = *iter; - check_references(drawable, face); - } - } + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + LLDrawable* drawable = *iter; + check_references(drawable, face); + } + } #endif } void LLPipeline::checkReferences(LLDrawable* drawable) { #if 0 - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, drawable); - } - - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) - { - if (drawable == *iter) - { - LL_ERRS() << "LLDrawable deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + if (drawable == *iter) + { + LL_ERRS() << "LLDrawable deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } #endif } void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info) { - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; - for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) - { - LLDrawInfo* params = *j; - if (params == draw_info) - { - LL_ERRS() << "LLDrawInfo deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* params = *j; + if (params == draw_info) + { + LL_ERRS() << "LLDrawInfo deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } } void LLPipeline::checkReferences(LLDrawInfo* draw_info) { #if 0 - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; - check_references(group, draw_info); - } - } + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + } #endif } void LLPipeline::checkReferences(LLSpatialGroup* group) { #if CHECK_PIPELINE_REFERENCES - if (sCull) - { - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - - for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - if (group == *iter) - { - LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; - } - } - } + if (sCull) + { + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + if (group == *iter) + { + LL_ERRS() << "LLSpatialGroup deleted while actively referenced by LLPipeline." << LL_ENDL; + } + } + } #endif } bool LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { - 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) - { - if (hasRenderType(part->mDrawableType)) - { - if (part->visibleObjectsInFrustum(camera)) - { - return true; - } - } - } - } - } - - return false; + 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) + { + if (hasRenderType(part->mDrawableType)) + { + if (part->visibleObjectsInFrustum(camera)) + { + return true; + } + } + } + } + } + + return false; } bool LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) { - const F32 X = 65536.f; + const F32 X = 65536.f; - min = LLVector3(X,X,X); - max = LLVector3(-X,-X,-X); + min = LLVector3(X,X,X); + max = LLVector3(-X,-X,-X); - LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; + LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - bool res = true; + bool res = true; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; + 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) - { - if (hasRenderType(part->mDrawableType)) - { - if (!part->getVisibleExtents(camera, min, max)) - { - res = false; - } - } - } - } - } + for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) + { + LLSpatialPartition* part = region->getSpatialPartition(i); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + if (!part->getVisibleExtents(camera, min, max)) + { + res = false; + } + } + } + } + } - LLViewerCamera::sCurCameraID = saved_camera_id; - return res; + LLViewerCamera::sCurCameraID = saved_camera_id; + return res; } static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); @@ -2270,7 +2270,7 @@ static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling"); bool LLPipeline::isWaterClip() { // We always pretend that we're not clipping water when rendering mirrors. - return (gPipeline.mHeroProbeManager.isMirrorPass()) ? false : (!sRenderTransparentWater || gCubeSnapshot) && !sRenderingHUDs; + return (gPipeline.mHeroProbeManager.isMirrorPass()) ? false : (!sRenderTransparentWater || gCubeSnapshot) && !sRenderingHUDs; } void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) @@ -2278,11 +2278,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL); LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out - bool water_clip = isWaterClip(); + bool water_clip = isWaterClip(); if (water_clip) { - + LLVector3 pnorm; F32 water_height = LLEnvironment::instance().getWaterHeight(); @@ -2297,7 +2297,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) //camera is above water, cull below water pnorm = LLVector3(0, 0, -1); } - + LLPlane plane; plane.setVec(LLVector3(0, 0, water_height), pnorm); @@ -2308,48 +2308,48 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) camera.disableUserClipPlane(); } - grabReferences(result); - - sCull->clear(); - - 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) - { - if (hasRenderType(part->mDrawableType)) - { - part->cull(camera); - } - } - } - - //scan the VO Cache tree - LLVOCachePartition* vo_part = region->getVOCachePartition(); - if(vo_part) - { - vo_part->cull(camera, sUseOcclusion > 0); - } - } - - if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && - gSky.mVOSkyp.notNull() && - gSky.mVOSkyp->mDrawable.notNull()) - { - gSky.mVOSkyp->mDrawable->setVisible(camera); - sCull->pushDrawable(gSky.mVOSkyp->mDrawable); - gSky.updateCull(); - stop_glerror(); - } - - if (hasRenderType(LLPipeline::RENDER_TYPE_WL_SKY) && + grabReferences(result); + + sCull->clear(); + + 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) + { + if (hasRenderType(part->mDrawableType)) + { + part->cull(camera); + } + } + } + + //scan the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->cull(camera, sUseOcclusion > 0); + } + } + + if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && + gSky.mVOSkyp.notNull() && + gSky.mVOSkyp->mDrawable.notNull()) + { + gSky.mVOSkyp->mDrawable->setVisible(camera); + sCull->pushDrawable(gSky.mVOSkyp->mDrawable); + gSky.updateCull(); + stop_glerror(); + } + + if (hasRenderType(LLPipeline::RENDER_TYPE_WL_SKY) && gPipeline.canUseWindLightShaders() && - gSky.mVOWLSkyp.notNull() && + gSky.mVOWLSkyp.notNull() && gSky.mVOWLSkyp->mDrawable.notNull()) { gSky.mVOWLSkyp->mDrawable->setVisible(camera); @@ -2359,60 +2359,60 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result) void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) { - if (group->isEmpty()) - { - return; - } - - group->setVisible(); - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) - { - group->updateDistance(camera); - } - - assertInitialized(); - - if (!group->getSpatialPartition()->mRenderByGroup) - { //render by drawable - sCull->pushDrawableGroup(group); - } - else - { //render by group - sCull->pushVisibleGroup(group); - } - - if (group->needsUpdate() || - group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) + if (group->isEmpty()) { - // include this group in occlusion groups, not because it is an occluder, but because we want to run - // an occlusion query to find out if it's an occluder + return; + } + + group->setVisible(); + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) + { + group->updateDistance(camera); + } + + assertInitialized(); + + if (!group->getSpatialPartition()->mRenderByGroup) + { //render by drawable + sCull->pushDrawableGroup(group); + } + else + { //render by group + sCull->pushVisibleGroup(group); + } + + if (group->needsUpdate() || + group->getVisible(LLViewerCamera::sCurCameraID) < LLDrawable::getCurrentFrame() - 1) + { + // include this group in occlusion groups, not because it is an occluder, but because we want to run + // an occlusion query to find out if it's an occluder markOccluder(group); } - mNumVisibleNodes++; + mNumVisibleNodes++; } void LLPipeline::markOccluder(LLSpatialGroup* group) { - if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION)) - { - LLSpatialGroup* parent = group->getParent(); - - if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { //only mark top most occluders as active occlusion - sCull->pushOcclusionGroup(group); - group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); - - if (parent && - !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) && - parent->getElementCount() == 0 && - parent->needsUpdate()) - { - sCull->pushOcclusionGroup(group); - parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); - } - } - } + if (sUseOcclusion > 1 && group && !group->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION)) + { + LLSpatialGroup* parent = group->getParent(); + + if (!parent || !parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { //only mark top most occluders as active occlusion + sCull->pushOcclusionGroup(group); + group->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); + + if (parent && + !parent->isOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION) && + parent->getElementCount() == 0 && + parent->needsUpdate()) + { + sCull->pushOcclusionGroup(group); + parent->setOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); + } + } + } } void LLPipeline::doOcclusion(LLCamera& camera) @@ -2440,7 +2440,7 @@ void LLPipeline::doOcclusion(LLCamera& camera) gGL.setColorMask(true, true); } - + if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot) { gGL.setColorMask(false, false); @@ -2462,138 +2462,138 @@ void LLPipeline::doOcclusion(LLCamera& camera) } if (LLPipeline::sUseOcclusion > 1 && - (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) - { - LLVertexBuffer::unbind(); + (sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck)) + { + LLVertexBuffer::unbind(); - gGL.setColorMask(false, false); + gGL.setColorMask(false, false); - LLGLDisable blend(GL_BLEND); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable blend(GL_BLEND); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); + LLGLDisable cull(GL_CULL_FACE); gOcclusionCubeProgram.bind(); - if (mCubeVB.isNull()) - { //cube VB will be used for issuing occlusion queries - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); - } - mCubeVB->setBuffer(); + if (mCubeVB.isNull()) + { //cube VB will be used for issuing occlusion queries + mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX); + } + mCubeVB->setBuffer(); - for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) - { - LLSpatialGroup* group = *iter; + for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) + { + LLSpatialGroup* group = *iter; if (!group->isDead()) { group->doOcclusion(&camera); group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } - } - - //apply occlusion culling to object cache tree - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLVOCachePartition* vo_part = (*iter)->getVOCachePartition(); - if(vo_part) - { - vo_part->processOccluders(&camera); - } - } - - gGL.setColorMask(true, true); - } -} - + } + + //apply occlusion culling to object cache tree + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLVOCachePartition* vo_part = (*iter)->getVOCachePartition(); + if(vo_part) + { + vo_part->processOccluders(&camera); + } + } + + gGL.setColorMask(true, true); + } +} + bool LLPipeline::updateDrawableGeom(LLDrawable* drawablep) { - bool update_complete = drawablep->updateGeometry(); - if (update_complete && assertInitialized()) - { - drawablep->setState(LLDrawable::BUILT); - } - return update_complete; + bool update_complete = drawablep->updateGeometry(); + if (update_complete && assertInitialized()) + { + drawablep->setState(LLDrawable::BUILT); + } + return update_complete; } void LLPipeline::updateGL() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - { - while (!LLGLUpdate::sGLQ.empty()) - { - LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); - glu->updateGL(); - glu->mInQ = FALSE; - LLGLUpdate::sGLQ.pop_front(); - } - } + { + while (!LLGLUpdate::sGLQ.empty()) + { + LLGLUpdate* glu = LLGLUpdate::sGLQ.front(); + glu->updateGL(); + glu->mInQ = FALSE; + LLGLUpdate::sGLQ.pop_front(); + } + } } void LLPipeline::clearRebuildGroups() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - LLSpatialGroup::sg_vector_t hudGroups; - - mGroupQ1Locked = true; - // Iterate through all drawables on the priority build queue, - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); - iter != mGroupQ1.end(); ++iter) - { - LLSpatialGroup* group = *iter; - - // If the group contains HUD objects, save the group - if (group->isHUDGroup()) - { - hudGroups.push_back(group); - } - // Else, no HUD objects so clear the build state - else - { - group->clearState(LLSpatialGroup::IN_BUILD_Q1); - } - } - - // Clear the group - mGroupQ1.clear(); - - // Copy the saved HUD groups back in - mGroupQ1.assign(hudGroups.begin(), hudGroups.end()); - mGroupQ1Locked = false; + LLSpatialGroup::sg_vector_t hudGroups; + + mGroupQ1Locked = true; + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + + // If the group contains HUD objects, save the group + if (group->isHUDGroup()) + { + hudGroups.push_back(group); + } + // Else, no HUD objects so clear the build state + else + { + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } + } + + // Clear the group + mGroupQ1.clear(); + + // Copy the saved HUD groups back in + mGroupQ1.assign(hudGroups.begin(), hudGroups.end()); + mGroupQ1Locked = false; } void LLPipeline::clearRebuildDrawables() { - // Clear all drawables on the priority build queue, - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); - iter != mBuildQ1.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q); - } - } - mBuildQ1.clear(); - - //clear all moving bridges - for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); - iter != mMovedBridge.end(); ++iter) - { - LLDrawable *drawablep = *iter; - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); - } - mMovedBridge.clear(); - - //clear all moving drawables - for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); - iter != mMovedList.end(); ++iter) - { - LLDrawable *drawablep = *iter; - drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); - } - mMovedList.clear(); + // Clear all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q); + } + } + mBuildQ1.clear(); + + //clear all moving bridges + for (LLDrawable::drawable_vector_t::iterator iter = mMovedBridge.begin(); + iter != mMovedBridge.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedBridge.clear(); + + //clear all moving drawables + for (LLDrawable::drawable_vector_t::iterator iter = mMovedList.begin(); + iter != mMovedList.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); + } + mMovedList.clear(); for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); ++iter) @@ -2609,305 +2609,305 @@ void LLPipeline::rebuildPriorityGroups() LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LL_PROFILE_GPU_ZONE("rebuildPriorityGroups"); - LLTimer update_timer; - assertInitialized(); + LLTimer update_timer; + assertInitialized(); - gMeshRepo.notifyLoadedMeshes(); + gMeshRepo.notifyLoadedMeshes(); - mGroupQ1Locked = true; - // Iterate through all drawables on the priority build queue, - for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); - iter != mGroupQ1.end(); ++iter) - { - LLSpatialGroup* group = *iter; - group->rebuildGeom(); - group->clearState(LLSpatialGroup::IN_BUILD_Q1); - } + mGroupQ1Locked = true; + // Iterate through all drawables on the priority build queue, + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); + iter != mGroupQ1.end(); ++iter) + { + LLSpatialGroup* group = *iter; + group->rebuildGeom(); + group->clearState(LLSpatialGroup::IN_BUILD_Q1); + } - mGroupSaveQ1 = mGroupQ1; - mGroupQ1.clear(); - mGroupQ1Locked = false; + mGroupSaveQ1 = mGroupQ1; + mGroupQ1.clear(); + mGroupQ1Locked = false; } void LLPipeline::updateGeom(F32 max_dtime) { - LLTimer update_timer; - LLPointer drawablep; + LLTimer update_timer; + LLPointer drawablep; - LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); + LL_RECORD_BLOCK_TIME(FTM_GEO_UPDATE); if (gCubeSnapshot) { return; } - assertInitialized(); - - // notify various object types to reset internal cost metrics, etc. - // for now, only LLVOVolume does this to throttle LOD changes - LLVOVolume::preUpdateGeom(); - - // Iterate through all drawables on the priority build queue, - for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); - iter != mBuildQ1.end();) - { - LLDrawable::drawable_list_t::iterator curiter = iter++; - LLDrawable* drawablep = *curiter; - if (drawablep && !drawablep->isDead()) - { - if (drawablep->isUnload()) - { - drawablep->unload(); - drawablep->clearState(LLDrawable::FOR_UNLOAD); - } - - if (updateDrawableGeom(drawablep)) - { - drawablep->clearState(LLDrawable::IN_REBUILD_Q); - mBuildQ1.erase(curiter); - } - } - else - { - mBuildQ1.erase(curiter); - } - } - - updateMovedList(mMovedBridge); + assertInitialized(); + + // notify various object types to reset internal cost metrics, etc. + // for now, only LLVOVolume does this to throttle LOD changes + LLVOVolume::preUpdateGeom(); + + // Iterate through all drawables on the priority build queue, + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); + iter != mBuildQ1.end();) + { + LLDrawable::drawable_list_t::iterator curiter = iter++; + LLDrawable* drawablep = *curiter; + if (drawablep && !drawablep->isDead()) + { + if (drawablep->isUnload()) + { + drawablep->unload(); + drawablep->clearState(LLDrawable::FOR_UNLOAD); + } + + if (updateDrawableGeom(drawablep)) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q); + mBuildQ1.erase(curiter); + } + } + else + { + mBuildQ1.erase(curiter); + } + } + + updateMovedList(mMovedBridge); } void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) { - if(drawablep && !drawablep->isDead()) - { - if (drawablep->isSpatialBridge()) - { - const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; - llassert(root); // trying to catch a bad assumption - - if (root && // // this test may not be needed, see above - root->getVObj()->isAttachment()) - { - LLDrawable* rootparent = root->getParent(); - if (rootparent) // this IS sometimes NULL - { - LLViewerObject *vobj = rootparent->getVObj(); - llassert(vobj); // trying to catch a bad assumption - if (vobj) // this test may not be needed, see above - { - LLVOAvatar* av = vobj->asAvatar(); - if (av && - ((!sImpostorRender && av->isImpostor()) //ignore impostor flag during impostor pass - || av->isInMuteList() - || (LLVOAvatar::AOA_JELLYDOLL == av->getOverallAppearance() && !av->needsImpostorUpdate()) )) - { - return; - } - } - } - } - sCull->pushBridge((LLSpatialBridge*) drawablep); - } - else - { - - sCull->pushDrawable(drawablep); - } - - drawablep->setVisible(camera); - } + if(drawablep && !drawablep->isDead()) + { + if (drawablep->isSpatialBridge()) + { + const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; + llassert(root); // trying to catch a bad assumption + + if (root && // // this test may not be needed, see above + root->getVObj()->isAttachment()) + { + LLDrawable* rootparent = root->getParent(); + if (rootparent) // this IS sometimes NULL + { + LLViewerObject *vobj = rootparent->getVObj(); + llassert(vobj); // trying to catch a bad assumption + if (vobj) // this test may not be needed, see above + { + LLVOAvatar* av = vobj->asAvatar(); + if (av && + ((!sImpostorRender && av->isImpostor()) //ignore impostor flag during impostor pass + || av->isInMuteList() + || (LLVOAvatar::AOA_JELLYDOLL == av->getOverallAppearance() && !av->needsImpostorUpdate()) )) + { + return; + } + } + } + } + sCull->pushBridge((LLSpatialBridge*) drawablep); + } + else + { + + sCull->pushDrawable(drawablep); + } + + drawablep->setVisible(camera); + } } void LLPipeline::markMoved(LLDrawable *drawablep, bool damped_motion) { - if (!drawablep) - { - //LL_ERRS() << "Sending null drawable to moved list!" << LL_ENDL; - return; - } - - if (drawablep->isDead()) - { - LL_WARNS() << "Marking NULL or dead drawable moved!" << LL_ENDL; - return; - } - - if (drawablep->getParent()) - { - //ensure that parent drawables are moved first - markMoved(drawablep->getParent(), damped_motion); - } - - assertInitialized(); - - if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) - { - if (drawablep->isSpatialBridge()) - { - mMovedBridge.push_back(drawablep); - } - else - { - mMovedList.push_back(drawablep); - } - drawablep->setState(LLDrawable::ON_MOVE_LIST); - } - if (! damped_motion) - { - drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED - } - else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) - { - drawablep->clearState(LLDrawable::MOVE_UNDAMPED); - } + if (!drawablep) + { + //LL_ERRS() << "Sending null drawable to moved list!" << LL_ENDL; + return; + } + + if (drawablep->isDead()) + { + LL_WARNS() << "Marking NULL or dead drawable moved!" << LL_ENDL; + return; + } + + if (drawablep->getParent()) + { + //ensure that parent drawables are moved first + markMoved(drawablep->getParent(), damped_motion); + } + + assertInitialized(); + + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) + { + if (drawablep->isSpatialBridge()) + { + mMovedBridge.push_back(drawablep); + } + else + { + mMovedList.push_back(drawablep); + } + drawablep->setState(LLDrawable::ON_MOVE_LIST); + } + if (! damped_motion) + { + drawablep->setState(LLDrawable::MOVE_UNDAMPED); // UNDAMPED trumps DAMPED + } + else if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + drawablep->clearState(LLDrawable::MOVE_UNDAMPED); + } } void LLPipeline::markShift(LLDrawable *drawablep) { - if (!drawablep || drawablep->isDead()) - { - return; - } + if (!drawablep || drawablep->isDead()) + { + return; + } - assertInitialized(); + assertInitialized(); - if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST)) - { - drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE); - if (drawablep->getParent()) - { - markShift(drawablep->getParent()); - } - mShiftList.push_back(drawablep); - drawablep->setState(LLDrawable::ON_SHIFT_LIST); - } + if (!drawablep->isState(LLDrawable::ON_SHIFT_LIST)) + { + drawablep->getVObj()->setChanged(LLXform::SHIFTED | LLXform::SILHOUETTE); + if (drawablep->getParent()) + { + markShift(drawablep->getParent()); + } + mShiftList.push_back(drawablep); + drawablep->setState(LLDrawable::ON_SHIFT_LIST); + } } void LLPipeline::shiftObjects(const LLVector3 &offset) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - - glClear(GL_DEPTH_BUFFER_BIT); - gDepthDirty = true; - - LLVector4a offseta; - offseta.load3(offset.mV); - - for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); - iter != mShiftList.end(); iter++) - { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) - { - continue; - } - drawablep->shiftPos(offseta); - drawablep->clearState(LLDrawable::ON_SHIFT_LIST); - } - mShiftList.resize(0); - - 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->shift(offseta); - } - } - } + assertInitialized(); + + glClear(GL_DEPTH_BUFFER_BIT); + gDepthDirty = true; + + LLVector4a offseta; + offseta.load3(offset.mV); + + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); iter++) + { + LLDrawable *drawablep = *iter; + if (drawablep->isDead()) + { + continue; + } + drawablep->shiftPos(offseta); + drawablep->clearState(LLDrawable::ON_SHIFT_LIST); + } + mShiftList.resize(0); + + 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->shift(offseta); + } + } + } mReflectionMapManager.shift(offseta); - LLHUDText::shiftAll(offset); - LLHUDNameTag::shiftAll(offset); + LLHUDText::shiftAll(offset); + LLHUDNameTag::shiftAll(offset); - display_update_camera(); + display_update_camera(); } void LLPipeline::markTextured(LLDrawable *drawablep) { - if (drawablep && !drawablep->isDead() && assertInitialized()) - { - mRetexturedList.insert(drawablep); - } + if (drawablep && !drawablep->isDead() && assertInitialized()) + { + mRetexturedList.insert(drawablep); + } } void LLPipeline::markGLRebuild(LLGLUpdate* glu) { - if (glu && !glu->mInQ) - { - LLGLUpdate::sGLQ.push_back(glu); - glu->mInQ = TRUE; - } + if (glu && !glu->mInQ) + { + LLGLUpdate::sGLQ.push_back(glu); + glu->mInQ = TRUE; + } } void LLPipeline::markPartitionMove(LLDrawable* drawable) { - if (!drawable->isState(LLDrawable::PARTITION_MOVE) && - !drawable->getPositionGroup().equals3(LLVector4a::getZero())) - { - drawable->setState(LLDrawable::PARTITION_MOVE); - mPartitionQ.push_back(drawable); - } + if (!drawable->isState(LLDrawable::PARTITION_MOVE) && + !drawable->getPositionGroup().equals3(LLVector4a::getZero())) + { + drawable->setState(LLDrawable::PARTITION_MOVE); + mPartitionQ.push_back(drawable); + } } void LLPipeline::processPartitionQ() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) - { - LLDrawable* drawable = *iter; - if (!drawable->isDead()) - { - drawable->updateBinRadius(); - drawable->movePartition(); - } - drawable->clearState(LLDrawable::PARTITION_MOVE); - } + for (LLDrawable::drawable_list_t::iterator iter = mPartitionQ.begin(); iter != mPartitionQ.end(); ++iter) + { + LLDrawable* drawable = *iter; + if (!drawable->isDead()) + { + drawable->updateBinRadius(); + drawable->movePartition(); + } + drawable->clearState(LLDrawable::PARTITION_MOVE); + } - mPartitionQ.clear(); + mPartitionQ.clear(); } void LLPipeline::markMeshDirty(LLSpatialGroup* group) { - mMeshDirtyGroup.push_back(group); + mMeshDirtyGroup.push_back(group); } void LLPipeline::markRebuild(LLSpatialGroup* group) { - if (group && !group->isDead() && group->getSpatialPartition()) - { - if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) - { - llassert_always(!mGroupQ1Locked); + if (group && !group->isDead() && group->getSpatialPartition()) + { + if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) + { + llassert_always(!mGroupQ1Locked); - mGroupQ1.push_back(group); - group->setState(LLSpatialGroup::IN_BUILD_Q1); - } - } + mGroupQ1.push_back(group); + group->setState(LLSpatialGroup::IN_BUILD_Q1); + } + } } void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag) { - if (drawablep && !drawablep->isDead() && assertInitialized()) - { - if (!drawablep->isState(LLDrawable::IN_REBUILD_Q)) - { - mBuildQ1.push_back(drawablep); - drawablep->setState(LLDrawable::IN_REBUILD_Q); // mark drawable as being in priority queue - } + if (drawablep && !drawablep->isDead() && assertInitialized()) + { + if (!drawablep->isState(LLDrawable::IN_REBUILD_Q)) + { + mBuildQ1.push_back(drawablep); + drawablep->setState(LLDrawable::IN_REBUILD_Q); // mark drawable as being in priority queue + } if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) - { - drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); - } - drawablep->setState(flag); - } + { + drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); + } + drawablep->setState(flag); + } } void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) @@ -2915,300 +2915,300 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LL_PROFILE_GPU_ZONE("stateSort"); - if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_CONTROL_AV, - LLPipeline::RENDER_TYPE_TERRAIN, - LLPipeline::RENDER_TYPE_TREE, - LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_VOIDWATER, - LLPipeline::RENDER_TYPE_WATER, - LLPipeline::END_RENDER_TYPES)) - { - //clear faces from face pools - gPipeline.resetDrawOrders(); - } - - //LLVertexBuffer::unbind(); - - grabReferences(result); - for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) - { - LLSpatialGroup* group = *iter; + if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_CONTROL_AV, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::END_RENDER_TYPES)) + { + //clear faces from face pools + gPipeline.resetDrawOrders(); + } + + //LLVertexBuffer::unbind(); + + grabReferences(result); + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; if (group->isDead()) { continue; } - group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - markOccluder(group); - } - else - { - group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + markOccluder(group); + } + else + { + group->setVisible(); + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); - markVisible(drawablep, camera); - } - - { //rebuild mesh as soon as we know it's visible - group->rebuildMesh(); - } - } - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) - { - LLSpatialGroup* last_group = NULL; - BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged(); - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLCullResult::bridge_iterator cur_iter = i; - LLSpatialBridge* bridge = *cur_iter; - LLSpatialGroup* group = bridge->getSpatialGroup(); - - if (last_group == NULL) - { - last_group = group; - } - - if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - stateSort(bridge, camera, fov_changed); - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - last_group != group && last_group->changeLOD()) - { - last_group->mLastUpdateDistance = last_group->mDistance; - } - - last_group = group; - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && - last_group && last_group->changeLOD()) - { - last_group->mLastUpdateDistance = last_group->mDistance; - } - } - - for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) - { - LLSpatialGroup* group = *iter; + markVisible(drawablep, camera); + } + + { //rebuild mesh as soon as we know it's visible + group->rebuildMesh(); + } + } + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) + { + LLSpatialGroup* last_group = NULL; + BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged(); + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + { + LLCullResult::bridge_iterator cur_iter = i; + LLSpatialBridge* bridge = *cur_iter; + LLSpatialGroup* group = bridge->getSpatialGroup(); + + if (last_group == NULL) + { + last_group = group; + } + + if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + stateSort(bridge, camera, fov_changed); + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group != group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + + last_group = group; + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + } + + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; if (group->isDead()) { continue; } - group->checkOcclusion(); - if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - markOccluder(group); - } - else - { - group->setVisible(); - stateSort(group, camera); - - { //rebuild mesh as soon as we know it's visible - group->rebuildMesh(); - } - } - } - - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWABLE("stateSort"); // LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); - for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); - iter != sCull->endVisibleList(); ++iter) - { - LLDrawable *drawablep = *iter; - if (!drawablep->isDead()) - { - stateSort(drawablep, camera); - } - } - } - - postSort(camera); + group->checkOcclusion(); + if (sUseOcclusion > 1 && group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + markOccluder(group); + } + else + { + group->setVisible(); + stateSort(group, camera); + + { //rebuild mesh as soon as we know it's visible + group->rebuildMesh(); + } + } + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWABLE("stateSort"); // LL_RECORD_BLOCK_TIME(FTM_STATESORT_DRAWABLE); + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); + iter != sCull->endVisibleList(); ++iter) + { + LLDrawable *drawablep = *iter; + if (!drawablep->isDead()) + { + stateSort(drawablep, camera); + } + } + } + + postSort(camera); } void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) { - if (group->changeLOD()) - { - for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) - { - LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); - stateSort(drawablep, camera); - } + if (group->changeLOD()) + { + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); + stateSort(drawablep, camera); + } - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) - { //avoid redundant stateSort calls - group->mLastUpdateDistance = group->mDistance; - } - } + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) + { //avoid redundant stateSort calls + group->mLastUpdateDistance = group->mDistance; + } + } } void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; if (bridge->getSpatialGroup()->changeLOD() || fov_changed) - { - bool force_update = false; - bridge->updateDistance(camera, force_update); - } + { + bool force_update = false; + bridge->updateDistance(camera, force_update); + } } void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; if (!drawablep - || drawablep->isDead() - || !hasRenderType(drawablep->getRenderType())) - { - return; - } - + || drawablep->isDead() + || !hasRenderType(drawablep->getRenderType())) + { + return; + } + // SL-11353 // ignore our own geo when rendering spotlight shadowmaps... - // + // if (RenderSpotLight && drawablep == RenderSpotLight) { return; } - if (LLSelectMgr::getInstance()->mHideSelectedObjects) - { - if (drawablep->getVObj().notNull() && - drawablep->getVObj()->isSelected()) - { - return; - } - } - - if (drawablep->isAvatar()) - { //don't draw avatars beyond render distance or if we don't have a spatial group. - if ((drawablep->getSpatialGroup() == NULL) || - (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance)) - { - return; - } - - LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get(); - if (!avatarp->isVisible()) - { - return; - } - } - - assertInitialized(); - - if (hasRenderType(drawablep->mRenderType)) - { - if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) - { - drawablep->setVisible(camera, NULL, FALSE); - } - } - - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) - { - //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here - { - if (!drawablep->isActive()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); - } - else if (drawablep->isAvatar()) - { - bool force_update = false; - drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() - } - } - } - - if (!drawablep->getVOVolume()) - { - for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); - iter != drawablep->mFaces.end(); iter++) - { - LLFace* facep = *iter; - - if (facep->hasGeometry()) - { - if (facep->getPool()) - { - facep->getPool()->enqueue(facep); - } - else - { - break; - } - } - } - } - - mNumVisibleFaces += drawablep->getNumFaces(); -} - - -void forAllDrawables(LLCullResult::sg_iterator begin, - LLCullResult::sg_iterator end, - void (*func)(LLDrawable*)) -{ - for (LLCullResult::sg_iterator i = begin; i != end; ++i) - { - LLSpatialGroup* group = *i; - if (group->isDead()) + if (LLSelectMgr::getInstance()->mHideSelectedObjects) + { + if (drawablep->getVObj().notNull() && + drawablep->getVObj()->isSelected()) + { + return; + } + } + + if (drawablep->isAvatar()) + { //don't draw avatars beyond render distance or if we don't have a spatial group. + if ((drawablep->getSpatialGroup() == NULL) || + (drawablep->getSpatialGroup()->mDistance > LLVOAvatar::sRenderDistance)) + { + return; + } + + LLVOAvatar* avatarp = (LLVOAvatar*) drawablep->getVObj().get(); + if (!avatarp->isVisible()) + { + return; + } + } + + assertInitialized(); + + if (hasRenderType(drawablep->mRenderType)) + { + if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) + { + drawablep->setVisible(camera, NULL, FALSE); + } + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && !gCubeSnapshot) + { + //if (drawablep->isVisible()) isVisible() check here is redundant, if it wasn't visible, it wouldn't be here + { + if (!drawablep->isActive()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); + } + else if (drawablep->isAvatar()) + { + bool force_update = false; + drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() + } + } + } + + if (!drawablep->getVOVolume()) + { + for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); + iter != drawablep->mFaces.end(); iter++) + { + LLFace* facep = *iter; + + if (facep->hasGeometry()) + { + if (facep->getPool()) + { + facep->getPool()->enqueue(facep); + } + else + { + break; + } + } + } + } + + mNumVisibleFaces += drawablep->getNumFaces(); +} + + +void forAllDrawables(LLCullResult::sg_iterator begin, + LLCullResult::sg_iterator end, + void (*func)(LLDrawable*)) +{ + for (LLCullResult::sg_iterator i = begin; i != end; ++i) + { + LLSpatialGroup* group = *i; + if (group->isDead()) { continue; } - for (LLSpatialGroup::element_iter j = group->getDataBegin(); j != group->getDataEnd(); ++j) - { - if((*j)->hasDrawable()) - { - func((LLDrawable*)(*j)->getDrawable()); - } - } - } + for (LLSpatialGroup::element_iter j = group->getDataBegin(); j != group->getDataEnd(); ++j) + { + if((*j)->hasDrawable()) + { + func((LLDrawable*)(*j)->getDrawable()); + } + } + } } void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*)) { - forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func); - forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func); + forAllDrawables(sCull->beginDrawableGroups(), sCull->endDrawableGroups(), func); + forAllDrawables(sCull->beginVisibleGroups(), sCull->endVisibleGroups(), func); } //function for creating scripted beacons void renderScriptedBeacons(LLDrawable* drawablep) { - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - && !vobj->getParent() - && vobj->flagScripted()) - { - if (gPipeline.sRenderBeacons) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); - } - - if (gPipeline.sRenderHighlight) - { - S32 face_id; - S32 count = drawablep->getNumFaces(); - for (face_id = 0; face_id < count; face_id++) - { - LLFace * facep = drawablep->getFace(face_id); - if (facep) - { - gPipeline.mHighlightFaces.push_back(facep); - } - } - } - } + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->flagScripted()) + { + if (gPipeline.sRenderBeacons) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), LLPipeline::DebugBeaconLineWidth); + } + + if (gPipeline.sRenderHighlight) + { + S32 face_id; + S32 count = drawablep->getNumFaces(); + for (face_id = 0; face_id < count; face_id++) + { + LLFace * facep = drawablep->getFace(face_id); + if (facep) + { + gPipeline.mHighlightFaces.push_back(facep); + } + } + } + } } void renderScriptedTouchBeacons(LLDrawable *drawablep) @@ -3611,169 +3611,169 @@ void LLPipeline::postSort(LLCamera &camera) void render_hud_elements() { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(FTM_RENDER_UI); - gPipeline.disableLights(); - - LLGLSUIDefault gls_ui; - - //LLGLEnable stencil(GL_STENCIL_TEST); - //glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); - //glStencilMask(0xFFFFFFFF); - //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - gUIProgram.bind(); + gPipeline.disableLights(); + + LLGLSUIDefault gls_ui; + + //LLGLEnable stencil(GL_STENCIL_TEST); + //glStencilFunc(GL_ALWAYS, 255, 0xFFFFFFFF); + //glStencilMask(0xFFFFFFFF); + //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + gUIProgram.bind(); gGL.color4f(1, 1, 1, 1); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - - if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() - - // Draw the tracking overlays - LLTracker::render3D(); - + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() + + // Draw the tracking overlays + LLTracker::render3D(); + if (LLWorld::instanceExists()) { // Show the property lines LLWorld::getInstance()->renderPropertyLines(); } - LLViewerParcelMgr::getInstance()->render(); - LLViewerParcelMgr::getInstance()->renderParcelCollision(); - } - else if (gForceRenderLandFence) - { - // This is only set when not rendering the UI, for parcel snapshots - LLViewerParcelMgr::getInstance()->render(); - } - else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - LLHUDText::renderAllHUD(); - } + LLViewerParcelMgr::getInstance()->render(); + LLViewerParcelMgr::getInstance()->renderParcelCollision(); + } + else if (gForceRenderLandFence) + { + // This is only set when not rendering the UI, for parcel snapshots + LLViewerParcelMgr::getInstance()->render(); + } + else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + LLHUDText::renderAllHUD(); + } - gUIProgram.unbind(); + gUIProgram.unbind(); } void LLPipeline::renderHighlights() { - assertInitialized(); - - // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) - // Render highlighted faces. - LLGLSPipelineAlpha gls_pipeline_alpha; - LLColor4 color(1.f, 1.f, 1.f, 0.5f); - disableLights(); - - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) - { - mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) - { - // Make sure the selection image gets downloaded and decoded - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); - } - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) - { - // Paint 'em red! - color.setVec(1.f, 0.f, 0.f, 0.5f); - - int count = mHighlightFaces.size(); - for (S32 i = 0; i < count; i++) - { - LLFace* facep = mHighlightFaces[i]; - facep->renderSelected(LLViewerTexture::sNullImagep, color); - } - } - - // Contains a list of the faces of objects that are physical or - // have touch-handlers. - mHighlightFaces.clear(); - - if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) - { - gHighlightProgram.unbind(); - } - - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) - { - color.setVec(1.0f, 0.5f, 0.5f, 0.5f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightNormalProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } - - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); - } - - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightNormalProgram.unbind(); - } - } - - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) - { - color.setVec(0.0f, 0.3f, 1.0f, 0.8f); - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightSpecularProgram.bind(); - gGL.diffuseColor4f(1,1,1,0.5f); - } - - mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - - U32 count = mSelectedFaces.size(); - for (U32 i = 0; i < count; i++) - { - LLFace *facep = mSelectedFaces[i]; - if (!facep || facep->getDrawable()->isDead()) - { - LL_ERRS() << "Bad face on selection" << LL_ENDL; - return; - } - - facep->renderSelected(mFaceSelectImagep, color); - } - - if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) - { - gHighlightSpecularProgram.unbind(); - } - } + assertInitialized(); + + // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) + // Render highlighted faces. + LLGLSPipelineAlpha gls_pipeline_alpha; + LLColor4 color(1.f, 1.f, 1.f, 0.5f); + disableLights(); + + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) + { + mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) + { + // Make sure the selection image gets downloaded and decoded + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) + { + // Paint 'em red! + color.setVec(1.f, 0.f, 0.f, 0.5f); + + int count = mHighlightFaces.size(); + for (S32 i = 0; i < count; i++) + { + LLFace* facep = mHighlightFaces[i]; + facep->renderSelected(LLViewerTexture::sNullImagep, color); + } + } + + // Contains a list of the faces of objects that are physical or + // have touch-handlers. + mHighlightFaces.clear(); + + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0) + { + gHighlightProgram.unbind(); + } + + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) + { + color.setVec(1.0f, 0.5f, 0.5f, 0.5f); + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.unbind(); + } + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) + { + color.setVec(0.0f, 0.3f, 1.0f, 0.8f); + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + LL_ERRS() << "Bad face on selection" << LL_ENDL; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.unbind(); + } + } } //debug use @@ -3781,8 +3781,8 @@ U32 LLPipeline::sCurRenderPoolType = 0 ; void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred"); + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY); LL_PROFILE_GPU_ZONE("renderGeomDeferred"); llassert(!sRenderingHUDs); @@ -3793,7 +3793,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) } if (&camera == LLViewerCamera::getInstance()) - { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and + { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and // current modelview matrix glh::matrix4f last_modelview(gGLLastModelView); glh::matrix4f cur_modelview(gGLModelView); @@ -3815,23 +3815,23 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) setupHWLights(); - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pools"); - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull(GL_CULL_FACE); - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (hasRenderType(poolp->getType())) - { - poolp->prerender(); - } - } + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (hasRenderType(poolp->getType())) + { + poolp->prerender(); + } + } - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); - LLGLState::checkStates(); + LLGLState::checkStates(); if (LLViewerShaderMgr::instance()->mShaderLevel[LLViewerShaderMgr::SHADER_DEFERRED] > 1) { @@ -3840,17 +3840,17 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) mHeroProbeManager.updateUniforms(); } - U32 cur_type = 0; + U32 cur_type = 0; + + gGL.setColorMask(true, true); + + pool_set_t::iterator iter1 = mPools.begin(); - gGL.setColorMask(true, true); - - pool_set_t::iterator iter1 = mPools.begin(); + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); + cur_type = poolp->getType(); if (occlude && cur_type >= LLDrawPool::POOL_GRASS) { @@ -3861,57 +3861,57 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) doOcclusion(camera); } - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pool render"); - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginDeferredPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } - } - poolp->endDeferredPass(i); - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); - } - } - else - { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } - } - iter1 = iter2; - stop_glerror(); - } - - gGLLastMatrix = NULL; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(gGLModelView); - - gGL.setColorMask(true, false); - - } // Tracy ZoneScoped + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred pool render"); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); } + } + poolp->endDeferredPass(i); + LLVertexBuffer::unbind(); + + LLGLState::checkStates(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(gGLModelView); + + gGL.setColorMask(true, false); + + } // Tracy ZoneScoped if (gUseWireframe) { @@ -3921,7 +3921,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LL_PROFILE_GPU_ZONE("renderGeomPostDeferred"); if (gUseWireframe) @@ -3929,9 +3929,9 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } - U32 cur_type = 0; + U32 cur_type = 0; - LLGLEnable cull(GL_CULL_FACE); + LLGLEnable cull(GL_CULL_FACE); bool done_atmospherics = LLPipeline::sRenderingHUDs; //skip atmospherics on huds bool done_water_haze = done_atmospherics; @@ -3947,24 +3947,24 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) // do water haze just before pre water alpha U32 water_haze_pass = LLDrawPool::POOL_ALPHA_PRE_WATER; - calcNearbyLights(camera); - setupHWLights(); + calcNearbyLights(camera); + setupHWLights(); gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.setColorMask(true, false); + gGL.setColorMask(true, false); - pool_set_t::iterator iter1 = mPools.begin(); + pool_set_t::iterator iter1 = mPools.begin(); if (gDebugGL || gDebugPipeline) { LLGLState::checkStates(GL_FALSE); } - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); if (cur_type >= atmospherics_pass && !done_atmospherics) { // do atmospherics against depth buffer before rendering alpha @@ -3978,56 +3978,56 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) done_water_haze = true; } - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) - { - LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred poolrender"); - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginPostDeferredPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - p->renderPostDeferred(i); - } - poolp->endPostDeferredPass(i); - LLVertexBuffer::unbind(); - - if (gDebugGL || gDebugPipeline) - { - LLGLState::checkStates(GL_FALSE); - } - } - } - else - { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } - } - iter1 = iter2; - stop_glerror(); - } - - gGLLastMatrix = NULL; - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.loadMatrix(gGLModelView); + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_DRAWPOOL("deferred poolrender"); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginPostDeferredPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderPostDeferred(i); + } + poolp->endPostDeferredPass(i); + LLVertexBuffer::unbind(); + + if (gDebugGL || gDebugPipeline) + { + LLGLState::checkStates(GL_FALSE); + } + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.loadMatrix(gGLModelView); if (!gCubeSnapshot) { @@ -4049,63 +4049,63 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LL_PROFILE_GPU_ZONE("renderGeomShadow"); U32 cur_type = 0; - - LLGLEnable cull(GL_CULL_FACE); - - LLVertexBuffer::unbind(); - - pool_set_t::iterator iter1 = mPools.begin(); - - while ( iter1 != mPools.end() ) - { - LLDrawPool *poolp = *iter1; - - cur_type = poolp->getType(); - - pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) - { - poolp->prerender() ; - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - - for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) - { - LLVertexBuffer::unbind(); - poolp->beginShadowPass(i); - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - - p->renderShadow(i); - } - poolp->endShadowPass(i); - LLVertexBuffer::unbind(); - } - } - else - { - // Skip all pools of this type - for (iter2 = iter1; iter2 != mPools.end(); iter2++) - { - LLDrawPool *p = *iter2; - if (p->getType() != cur_type) - { - break; - } - } - } - iter1 = iter2; - stop_glerror(); - } - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); + + LLGLEnable cull(GL_CULL_FACE); + + LLVertexBuffer::unbind(); + + pool_set_t::iterator iter1 = mPools.begin(); + + while ( iter1 != mPools.end() ) + { + LLDrawPool *poolp = *iter1; + + cur_type = poolp->getType(); + + pool_set_t::iterator iter2 = iter1; + if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0) + { + poolp->prerender() ; + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ ) + { + LLVertexBuffer::unbind(); + poolp->beginShadowPass(i); + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + + p->renderShadow(i); + } + poolp->endShadowPass(i); + LLVertexBuffer::unbind(); + } + } + else + { + // Skip all pools of this type + for (iter2 = iter1; iter2 != mPools.end(); iter2++) + { + LLDrawPool *p = *iter2; + if (p->getType() != cur_type) + { + break; + } + } + } + iter1 = iter2; + stop_glerror(); + } + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); } @@ -4126,10 +4126,10 @@ void LLPipeline::recordTrianglesDrawn() void LLPipeline::renderPhysicsDisplay() { - if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) - { - return; - } + if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) + { + return; + } gGL.flush(); gDebugProgram.bind(); @@ -4179,7 +4179,7 @@ void LLPipeline::renderPhysicsDisplay() } } glLineWidth(1.f); - gDebugProgram.unbind(); + gDebugProgram.unbind(); } @@ -4189,379 +4189,379 @@ void LLPipeline::renderDebug() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - - bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); - - if (!hud_only ) - { - //Render any navmesh geometry - LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); - if ( llPathingLibInstance != NULL ) - { - //character floater renderables - - LLHandle pathfindingCharacterHandle = LLFloaterPathfindingCharacters::getInstanceHandle(); - if ( !pathfindingCharacterHandle.isDead() ) - { - LLFloaterPathfindingCharacters *pathfindingCharacter = pathfindingCharacterHandle.get(); - - if ( pathfindingCharacter->getVisible() || gAgentCamera.cameraMouselook() ) - { - gPathfindingProgram.bind(); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - - //Requried character physics capsule render parameters - LLUUID id; - LLVector3 pos; - LLQuaternion rot; - - if ( pathfindingCharacter->isPhysicsCapsuleEnabled( id, pos, rot ) ) - { - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gGL.setColorMask(true, false); - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); - gPathfindingProgram.bind(); - } - } - } - - - //pathing console renderables - LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); - if (!pathfindingConsoleHandle.isDead()) - { - LLFloaterPathfindingConsole *pathfindingConsole = pathfindingConsoleHandle.get(); - - if ( pathfindingConsole->getVisible() || gAgentCamera.cameraMouselook() ) - { - F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); - - gPathfindingProgram.bind(); - - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - - if ( !pathfindingConsole->isRenderWorld() ) - { - const LLColor4 clearColor = gSavedSettings.getColor4("PathfindingNavMeshClear"); - gGL.setColorMask(true, true); - glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // no stencil -- deprecated | GL_STENCIL_BUFFER_BIT); - gGL.setColorMask(true, false); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - - //NavMesh - if ( pathfindingConsole->isRenderNavMesh() ) - { - gGL.flush(); - glLineWidth(2.0f); - LLGLEnable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - - if ( pathfindingConsole->isRenderWorld() ) - { - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.66f); - llPathingLibInstance->renderNavMesh(); - } - else - { - llPathingLibInstance->renderNavMesh(); - } - - //render edges - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - - gGL.flush(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - glLineWidth(1.0f); - gGL.flush(); - } - //User designated path - if ( LLPathfindingPathTool::getInstance()->isRenderPath() ) - { - //The path - gUIProgram.bind(); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); - llPathingLibInstance->renderPath(); - gPathfindingProgram.bind(); + assertInitialized(); - //The bookends - //remove blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - - gGL.setColorMask(true, false); - //render the bookends - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); - llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); - gPathfindingProgram.bind(); - } - - if ( pathfindingConsole->isRenderWaterPlane() ) - { - LLGLEnable blend(GL_BLEND); - gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); - llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); - } - //physics/exclusion shapes - if ( pathfindingConsole->isRenderAnyShapes() ) - { - U32 render_order[] = { - 1 << LLPathingLib::LLST_ObstacleObjects, - 1 << LLPathingLib::LLST_WalkableObjects, - 1 << LLPathingLib::LLST_ExclusionPhantoms, - 1 << LLPathingLib::LLST_MaterialPhantoms, - }; - - U32 flags = pathfindingConsole->getRenderShapeFlags(); - - for (U32 i = 0; i < 4; i++) - { - if (!(flags & render_order[i])) - { - continue; - } - - //turn off backface culling for volumes so they are visible when camera is inside volume - LLGLDisable cull(i >= 2 ? GL_CULL_FACE : 0); - - gGL.flush(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - - //get rid of some z-fighting - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.0f, 1.0f); - - //render to depth first to avoid blending artifacts - gGL.setColorMask(false, false); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.setColorMask(true, false); - - //get rid of some z-fighting - glPolygonOffset(0.f, 0.f); - - LLGLEnable blend(GL_BLEND); - - { - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - - { //draw solid overlay - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.flush(); - } - - LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - - F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); - - if (pathfindingConsole->isRenderXRay()) - { - gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - - glPolygonOffset(offset, -offset); - - if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) - { //draw hidden wireframe as darker and less opaque - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - } - else - { - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - } - - { //draw visible wireframe as brighter, thicker and more opaque - glPolygonOffset(offset, offset); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - gPathfindingProgram.uniform1f(sTint, 1.f); - gPathfindingProgram.uniform1f(sAlphaScale, 1.f); - - glLineWidth(gSavedSettings.getF32("PathfindingLineWidth")); - LLGLDisable blendOut(GL_BLEND); - llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); - gGL.flush(); - glLineWidth(1.f); - } - - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - } - } - - glPolygonOffset(0.f, 0.f); - - if ( pathfindingConsole->isRenderNavMesh() && pathfindingConsole->isRenderXRay() ) - { //render navmesh xray - F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); - - LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - - F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); - glPolygonOffset(offset, -offset); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.flush(); - glLineWidth(2.0f); - LLGLEnable cull(GL_CULL_FACE); - - gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - - if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) - { //draw hidden wireframe as darker and less opaque - glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - gPathfindingProgram.uniform1f(sAmbiance, 1.f); - llPathingLibInstance->renderNavMesh(); - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - } - else - { - gPathfindingProgram.uniform1f(sAmbiance, ambiance); - llPathingLibInstance->renderNavMesh(); - } - - //render edges - gPathfindingNoNormalsProgram.bind(); - gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); - gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); - llPathingLibInstance->renderNavMeshEdges(); - gPathfindingProgram.bind(); - - gGL.flush(); - glLineWidth(1.0f); - } - - glPolygonOffset(0.f, 0.f); - - gGL.flush(); - gPathfindingProgram.unbind(); - } - } - } - } - - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); - gGL.setColorMask(true, false); - - - if (!hud_only && !mDebugBlips.empty()) - { //render debug blips - gUIProgram.bind(); + bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); + + if (!hud_only ) + { + //Render any navmesh geometry + LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); + if ( llPathingLibInstance != NULL ) + { + //character floater renderables + + LLHandle pathfindingCharacterHandle = LLFloaterPathfindingCharacters::getInstanceHandle(); + if ( !pathfindingCharacterHandle.isDead() ) + { + LLFloaterPathfindingCharacters *pathfindingCharacter = pathfindingCharacterHandle.get(); + + if ( pathfindingCharacter->getVisible() || gAgentCamera.cameraMouselook() ) + { + gPathfindingProgram.bind(); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + + //Requried character physics capsule render parameters + LLUUID id; + LLVector3 pos; + LLQuaternion rot; + + if ( pathfindingCharacter->isPhysicsCapsuleEnabled( id, pos, rot ) ) + { + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gGL.setColorMask(true, false); + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot ); + gPathfindingProgram.bind(); + } + } + } + + + //pathing console renderables + LLHandle pathfindingConsoleHandle = LLFloaterPathfindingConsole::getInstanceHandle(); + if (!pathfindingConsoleHandle.isDead()) + { + LLFloaterPathfindingConsole *pathfindingConsole = pathfindingConsoleHandle.get(); + + if ( pathfindingConsole->getVisible() || gAgentCamera.cameraMouselook() ) + { + F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); + + gPathfindingProgram.bind(); + + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + + if ( !pathfindingConsole->isRenderWorld() ) + { + const LLColor4 clearColor = gSavedSettings.getColor4("PathfindingNavMeshClear"); + gGL.setColorMask(true, true); + glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // no stencil -- deprecated | GL_STENCIL_BUFFER_BIT); + gGL.setColorMask(true, false); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + + //NavMesh + if ( pathfindingConsole->isRenderNavMesh() ) + { + gGL.flush(); + glLineWidth(2.0f); + LLGLEnable cull(GL_CULL_FACE); + LLGLDisable blend(GL_BLEND); + + if ( pathfindingConsole->isRenderWorld() ) + { + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.66f); + llPathingLibInstance->renderNavMesh(); + } + else + { + llPathingLibInstance->renderNavMesh(); + } + + //render edges + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); + + gGL.flush(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glLineWidth(1.0f); + gGL.flush(); + } + //User designated path + if ( LLPathfindingPathTool::getInstance()->isRenderPath() ) + { + //The path + gUIProgram.bind(); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + llPathingLibInstance->renderPath(); + gPathfindingProgram.bind(); + + //The bookends + //remove blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + + gGL.setColorMask(true, false); + //render the bookends + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START ); + llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END ); + gPathfindingProgram.bind(); + } + + if ( pathfindingConsole->isRenderWaterPlane() ) + { + LLGLEnable blend(GL_BLEND); + gPathfindingProgram.uniform1f(sAlphaScale, 0.90f); + llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() ); + } + //physics/exclusion shapes + if ( pathfindingConsole->isRenderAnyShapes() ) + { + U32 render_order[] = { + 1 << LLPathingLib::LLST_ObstacleObjects, + 1 << LLPathingLib::LLST_WalkableObjects, + 1 << LLPathingLib::LLST_ExclusionPhantoms, + 1 << LLPathingLib::LLST_MaterialPhantoms, + }; + + U32 flags = pathfindingConsole->getRenderShapeFlags(); + + for (U32 i = 0; i < 4; i++) + { + if (!(flags & render_order[i])) + { + continue; + } + + //turn off backface culling for volumes so they are visible when camera is inside volume + LLGLDisable cull(i >= 2 ? GL_CULL_FACE : 0); + + gGL.flush(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + + //get rid of some z-fighting + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(1.0f, 1.0f); + + //render to depth first to avoid blending artifacts + gGL.setColorMask(false, false); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.setColorMask(true, false); + + //get rid of some z-fighting + glPolygonOffset(0.f, 0.f); + + LLGLEnable blend(GL_BLEND); + + { + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + + { //draw solid overlay + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.flush(); + } + + LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + + F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); + + if (pathfindingConsole->isRenderXRay()) + { + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + + glPolygonOffset(offset, -offset); + + if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) + { //draw hidden wireframe as darker and less opaque + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + } + else + { + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } + } + + { //draw visible wireframe as brighter, thicker and more opaque + glPolygonOffset(offset, offset); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + gPathfindingProgram.uniform1f(sTint, 1.f); + gPathfindingProgram.uniform1f(sAlphaScale, 1.f); + + glLineWidth(gSavedSettings.getF32("PathfindingLineWidth")); + LLGLDisable blendOut(GL_BLEND); + llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); + gGL.flush(); + glLineWidth(1.f); + } + + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + } + } + + glPolygonOffset(0.f, 0.f); + + if ( pathfindingConsole->isRenderNavMesh() && pathfindingConsole->isRenderXRay() ) + { //render navmesh xray + F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); + + LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + + F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); + glPolygonOffset(offset, -offset); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.flush(); + glLineWidth(2.0f); + LLGLEnable cull(GL_CULL_FACE); + + gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + + if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) + { //draw hidden wireframe as darker and less opaque + glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + gPathfindingProgram.uniform1f(sAmbiance, 1.f); + llPathingLibInstance->renderNavMesh(); + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + } + else + { + gPathfindingProgram.uniform1f(sAmbiance, ambiance); + llPathingLibInstance->renderNavMesh(); + } + + //render edges + gPathfindingNoNormalsProgram.bind(); + gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); + gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity")); + llPathingLibInstance->renderNavMeshEdges(); + gPathfindingProgram.bind(); + + gGL.flush(); + glLineWidth(1.0f); + } + + glPolygonOffset(0.f, 0.f); + + gGL.flush(); + gPathfindingProgram.unbind(); + } + } + } + } + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + gGL.setColorMask(true, false); + + + if (!hud_only && !mDebugBlips.empty()) + { //render debug blips + gUIProgram.bind(); gGL.color4f(1, 1, 1, 1); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); - - glPointSize(8.f); - LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - - gGL.begin(LLRender::POINTS); - for (std::list::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); ) - { - DebugBlip& blip = *iter; - - blip.mAge += gFrameIntervalSeconds.value(); - if (blip.mAge > 2.f) - { - mDebugBlips.erase(iter++); - } - else - { - iter++; - } - - blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; - - gGL.color4fv(blip.mColor.mV); - gGL.vertex3fv(blip.mPosition.mV); - } - gGL.end(); - gGL.flush(); - glPointSize(1.f); - } - - // Debug stuff. - 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) - { - if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || - (!hud_only && hasRenderType(part->mDrawableType)) ) - { - part->renderDebug(); - } - } - } - } - - for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLSpatialBridge* bridge = *i; - if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) - { - gGL.pushMatrix(); - gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); - bridge->renderDebug(); - gGL.popMatrix(); - } - } + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); + + glPointSize(8.f); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + + gGL.begin(LLRender::POINTS); + for (std::list::iterator iter = mDebugBlips.begin(); iter != mDebugBlips.end(); ) + { + DebugBlip& blip = *iter; + + blip.mAge += gFrameIntervalSeconds.value(); + if (blip.mAge > 2.f) + { + mDebugBlips.erase(iter++); + } + else + { + iter++; + } + + blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; + + gGL.color4fv(blip.mColor.mV); + gGL.vertex3fv(blip.mPosition.mV); + } + gGL.end(); + gGL.flush(); + glPointSize(1.f); + } + + // Debug stuff. + 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) + { + if ( (hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES)) || + (!hud_only && hasRenderType(part->mDrawableType)) ) + { + part->renderDebug(); + } + } + } + } + + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderDebug(); + gGL.popMatrix(); + } + } LL::GLTFSceneManager::instance().renderDebug(); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { //render visible selected group occlusion geometry - gDebugProgram.bind(); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.diffuseColor3f(1,0,1); - for (std::set::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter) - { - LLSpatialGroup* group = *iter; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { //render visible selected group occlusion geometry + gDebugProgram.bind(); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.diffuseColor3f(1,0,1); + for (std::set::iterator iter = visible_selected_groups.begin(); iter != visible_selected_groups.end(); ++iter) + { + LLSpatialGroup* group = *iter; - LLVector4a fudge; - fudge.splat(0.25f); //SG_OCCLUSION_FUDGE + LLVector4a fudge; + fudge.splat(0.25f); //SG_OCCLUSION_FUDGE - LLVector4a size; - const LLVector4a* bounds = group->getBounds(); - size.setAdd(fudge, bounds[1]); - - drawBox(bounds[0], size); - } - } + LLVector4a size; + const LLVector4a* bounds = group->getBounds(); + size.setAdd(fudge, bounds[1]); + + drawBox(bounds[0], size); + } + } - visible_selected_groups.clear(); + visible_selected_groups.clear(); //draw reflection probes and links between them if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_REFLECTION_PROBES) && !hud_only) @@ -4584,559 +4584,559 @@ void LLPipeline::renderDebug() unbindDeferredShader(gReflectionProbeDisplayProgram); } - gUIProgram.bind(); - - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) - { //draw crosshairs on particle intersection - if (gDebugRaycastParticle) - { - gDebugProgram.bind(); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); - LLVector3 size(0.1f, 0.1f, 0.1f); - - LLVector3 p[6]; - - p[0] = center + size.scaledVec(LLVector3(1,0,0)); - p[1] = center + size.scaledVec(LLVector3(-1,0,0)); - p[2] = center + size.scaledVec(LLVector3(0,1,0)); - p[3] = center + size.scaledVec(LLVector3(0,-1,0)); - p[4] = center + size.scaledVec(LLVector3(0,0,1)); - p[5] = center + size.scaledVec(LLVector3(0,0,-1)); - - gGL.begin(LLRender::LINES); - gGL.diffuseColor3f(1.f, 1.f, 0.f); - for (U32 i = 0; i < 6; i++) - { - gGL.vertex3fv(p[i].mV); - } - gGL.end(); - gGL.flush(); - - gDebugProgram.unbind(); - } - } - - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !hud_only) - { - LLVertexBuffer::unbind(); - - LLGLEnable blend(GL_BLEND); - LLGLDepthTest depth(TRUE, FALSE); - LLGLDisable cull(GL_CULL_FACE); - - gGL.color4f(1,1,1,1); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - F32 a = 0.1f; - - F32 col[] = - { - 1,0,0,a, - 0,1,0,a, - 0,0,1,a, - 1,0,1,a, - - 1,1,0,a, - 0,1,1,a, - 1,1,1,a, - 1,0,1,a, - }; - - for (U32 i = 0; i < 8; i++) - { - LLVector3* frust = mShadowCamera[i].mAgentFrustum; - - if (i > 3) - { //render shadow frusta as volumes - if (mShadowFrustPoints[i-4].empty()) - { - continue; - } - - gGL.color4fv(col+(i-4)*4); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.end(); - - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[0].mV); - gGL.vertex3fv(frust[1].mV); - gGL.vertex3fv(frust[3].mV); - gGL.vertex3fv(frust[2].mV); - gGL.end(); - - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[6].mV); - gGL.end(); - } - - - if (i < 4) - { - - //if (i == 0 || !mShadowFrustPoints[i].empty()) - { - //render visible point cloud - gGL.flush(); - glPointSize(8.f); - gGL.begin(LLRender::POINTS); - - F32* c = col+i*4; - gGL.color3fv(c); - - for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) - { - gGL.vertex3fv(mShadowFrustPoints[i][j].mV); - - } - gGL.end(); - - gGL.flush(); - glPointSize(1.f); - - LLVector3* ext = mShadowExtents[i]; - LLVector3 pos = (ext[0]+ext[1])*0.5f; - LLVector3 size = (ext[1]-ext[0])*0.5f; - drawBoxOutline(pos, size); - - //render camera frustum splits as outlines - gGL.begin(LLRender::LINES); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); - gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); - gGL.end(); - } - } - - /*gGL.flush(); - glLineWidth(16-i*2); - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) - { - LLSpatialPartition* part = region->getSpatialPartition(j); - if (part) - { - if (hasRenderType(part->mDrawableType)) - { - part->renderIntersectingBBoxes(&mShadowCamera[i]); - } - } - } - } - gGL.flush(); - glLineWidth(1.f);*/ - } - } - - if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS) - { - gAgent.getRegion()->mWind.renderVectors(); - } - - if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) - { - // Debug composition layers - F32 x, y; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - if (gAgent.getRegion()) - { - gGL.begin(LLRender::POINTS); - // Draw the composition layer for the region that I'm in. - for (x = 0; x <= 260; x++) - { - for (y = 0; y <= 260; y++) - { - if ((x > 255) || (y > 255)) - { - gGL.color4f(1.f, 0.f, 0.f, 1.f); - } - else - { - gGL.color4f(0.f, 0.f, 1.f, 1.f); - } - F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y); - z *= 5.f; - z += 50.f; - gGL.vertex3f(x, y, z); - } - } - gGL.end(); - } - } - - gGL.flush(); - gUIProgram.unbind(); + gUIProgram.bind(); + + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST) && !hud_only) + { //draw crosshairs on particle intersection + if (gDebugRaycastParticle) + { + gDebugProgram.bind(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector3 center(gDebugRaycastParticleIntersection.getF32ptr()); + LLVector3 size(0.1f, 0.1f, 0.1f); + + LLVector3 p[6]; + + p[0] = center + size.scaledVec(LLVector3(1,0,0)); + p[1] = center + size.scaledVec(LLVector3(-1,0,0)); + p[2] = center + size.scaledVec(LLVector3(0,1,0)); + p[3] = center + size.scaledVec(LLVector3(0,-1,0)); + p[4] = center + size.scaledVec(LLVector3(0,0,1)); + p[5] = center + size.scaledVec(LLVector3(0,0,-1)); + + gGL.begin(LLRender::LINES); + gGL.diffuseColor3f(1.f, 1.f, 0.f); + for (U32 i = 0; i < 6; i++) + { + gGL.vertex3fv(p[i].mV); + } + gGL.end(); + gGL.flush(); + + gDebugProgram.unbind(); + } + } + + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !hud_only) + { + LLVertexBuffer::unbind(); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(TRUE, FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gGL.color4f(1,1,1,1); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + F32 a = 0.1f; + + F32 col[] = + { + 1,0,0,a, + 0,1,0,a, + 0,0,1,a, + 1,0,1,a, + + 1,1,0,a, + 0,1,1,a, + 1,1,1,a, + 1,0,1,a, + }; + + for (U32 i = 0; i < 8; i++) + { + LLVector3* frust = mShadowCamera[i].mAgentFrustum; + + if (i > 3) + { //render shadow frusta as volumes + if (mShadowFrustPoints[i-4].empty()) + { + continue; + } + + gGL.color4fv(col+(i-4)*4); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.end(); + + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[2].mV); + gGL.end(); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[6].mV); + gGL.end(); + } + + + if (i < 4) + { + + //if (i == 0 || !mShadowFrustPoints[i].empty()) + { + //render visible point cloud + gGL.flush(); + glPointSize(8.f); + gGL.begin(LLRender::POINTS); + + F32* c = col+i*4; + gGL.color3fv(c); + + for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + { + gGL.vertex3fv(mShadowFrustPoints[i][j].mV); + + } + gGL.end(); + + gGL.flush(); + glPointSize(1.f); + + LLVector3* ext = mShadowExtents[i]; + LLVector3 pos = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + drawBoxOutline(pos, size); + + //render camera frustum splits as outlines + gGL.begin(LLRender::LINES); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.end(); + } + } + + /*gGL.flush(); + glLineWidth(16-i*2); + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part) + { + if (hasRenderType(part->mDrawableType)) + { + part->renderIntersectingBBoxes(&mShadowCamera[i]); + } + } + } + } + gGL.flush(); + glLineWidth(1.f);*/ + } + } + + if (mRenderDebugMask & RENDER_DEBUG_WIND_VECTORS) + { + gAgent.getRegion()->mWind.renderVectors(); + } + + if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) + { + // Debug composition layers + F32 x, y; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + if (gAgent.getRegion()) + { + gGL.begin(LLRender::POINTS); + // Draw the composition layer for the region that I'm in. + for (x = 0; x <= 260; x++) + { + for (y = 0; y <= 260; y++) + { + if ((x > 255) || (y > 255)) + { + gGL.color4f(1.f, 0.f, 0.f, 1.f); + } + else + { + gGL.color4f(0.f, 0.f, 1.f, 1.f); + } + F32 z = gAgent.getRegion()->getCompositionXY((S32)x, (S32)y); + z *= 5.f; + z += 50.f; + gGL.vertex3f(x, y, z); + } + } + gGL.end(); + } + } + + gGL.flush(); + gUIProgram.unbind(); } void LLPipeline::rebuildPools() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - - S32 max_count = mPools.size(); - pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); - while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) - { - if (iter1 == mPools.end()) - { - iter1 = mPools.begin(); - } - LLDrawPool* poolp = *iter1; - - if (poolp->isDead()) - { - mPools.erase(iter1++); - removeFromQuickLookup( poolp ); - if (poolp == mLastRebuildPool) - { - mLastRebuildPool = NULL; - } - delete poolp; - } - else - { - mLastRebuildPool = poolp; - iter1++; - } - max_count--; - } + assertInitialized(); + + S32 max_count = mPools.size(); + pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); + while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) + { + if (iter1 == mPools.end()) + { + iter1 = mPools.begin(); + } + LLDrawPool* poolp = *iter1; + + if (poolp->isDead()) + { + mPools.erase(iter1++); + removeFromQuickLookup( poolp ); + if (poolp == mLastRebuildPool) + { + mLastRebuildPool = NULL; + } + delete poolp; + } + else + { + mLastRebuildPool = poolp; + iter1++; + } + max_count--; + } } void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) { - assertInitialized(); - - switch( new_poolp->getType() ) - { - case LLDrawPool::POOL_SIMPLE: - if (mSimplePool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mSimplePool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_ALPHA_MASK: - if (mAlphaMaskPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; - break; - } - else - { - mAlphaMaskPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - if (mFullbrightAlphaMaskPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; - break; - } - else - { - mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_GRASS: - if (mGrassPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate grass pool." << LL_ENDL; - } - else - { - mGrassPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_FULLBRIGHT: - if (mFullbrightPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; - } - else - { - mFullbrightPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_GLOW: - if (mGlowPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate glow pool." << LL_ENDL; - } - else - { - mGlowPool = (LLRenderPass*) new_poolp; - } - break; - - case LLDrawPool::POOL_TREE: - mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; - - case LLDrawPool::POOL_TERRAIN: - mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; - - case LLDrawPool::POOL_BUMP: - if (mBumpPool) - { - llassert(0); - LL_WARNS() << "Ignoring duplicate bump pool." << LL_ENDL; - } - else - { - mBumpPool = new_poolp; - } - break; - case LLDrawPool::POOL_MATERIALS: - if (mMaterialsPool) - { - llassert(0); - LL_WARNS() << "Ignorning duplicate materials pool." << LL_ENDL; - } - else - { - mMaterialsPool = new_poolp; - } - break; - case LLDrawPool::POOL_ALPHA_PRE_WATER: - if( mAlphaPoolPreWater ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pre-water pool" << LL_ENDL; - } - else - { - mAlphaPoolPreWater = (LLDrawPoolAlpha*) new_poolp; - } - break; - case LLDrawPool::POOL_ALPHA_POST_WATER: - if (mAlphaPoolPostWater) + assertInitialized(); + + switch( new_poolp->getType() ) + { + case LLDrawPool::POOL_SIMPLE: + if (mSimplePool) { llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha post-water pool" << LL_ENDL; + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; } else { - mAlphaPoolPostWater = (LLDrawPoolAlpha*)new_poolp; + mSimplePool = (LLRenderPass*) new_poolp; } break; - case LLDrawPool::POOL_AVATAR: - case LLDrawPool::POOL_CONTROL_AV: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - if( mSkyPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << LL_ENDL; - } - else - { - mSkyPool = new_poolp; - } - break; - - case LLDrawPool::POOL_WATER: - if( mWaterPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water pool" << LL_ENDL; - } - else - { - mWaterPool = new_poolp; - } - break; - - case LLDrawPool::POOL_WL_SKY: - if( mWLSkyPool ) - { - llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << LL_ENDL; - } - else - { - mWLSkyPool = new_poolp; - } - break; + case LLDrawPool::POOL_ALPHA_MASK: + if (mAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; + } + else + { + mAlphaMaskPool = (LLRenderPass*) new_poolp; + } + break; - case LLDrawPool::POOL_GLTF_PBR: - if( mPBROpaquePool ) + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + if (mFullbrightAlphaMaskPool) { llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Opaque Pool" << LL_ENDL; + LL_WARNS() << "Ignoring duplicate alpha mask pool." << LL_ENDL; + break; } else { - mPBROpaquePool = new_poolp; + mFullbrightAlphaMaskPool = (LLRenderPass*) new_poolp; } break; - case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK: - if (mPBRAlphaMaskPool) + case LLDrawPool::POOL_GRASS: + if (mGrassPool) { llassert(0); - LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Alpha Mask Pool" << LL_ENDL; + LL_WARNS() << "Ignoring duplicate grass pool." << LL_ENDL; } else { - mPBRAlphaMaskPool = new_poolp; + mGrassPool = (LLRenderPass*) new_poolp; } break; + case LLDrawPool::POOL_FULLBRIGHT: + if (mFullbrightPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate simple pool." << LL_ENDL; + } + else + { + mFullbrightPool = (LLRenderPass*) new_poolp; + } + break; - default: - llassert(0); - LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL; - break; - } -} + case LLDrawPool::POOL_GLOW: + if (mGlowPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate glow pool." << LL_ENDL; + } + else + { + mGlowPool = (LLRenderPass*) new_poolp; + } + break; -void LLPipeline::removePool( LLDrawPool* poolp ) + case LLDrawPool::POOL_TREE: + mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + break; + + case LLDrawPool::POOL_TERRAIN: + mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + break; + + case LLDrawPool::POOL_BUMP: + if (mBumpPool) + { + llassert(0); + LL_WARNS() << "Ignoring duplicate bump pool." << LL_ENDL; + } + else + { + mBumpPool = new_poolp; + } + break; + case LLDrawPool::POOL_MATERIALS: + if (mMaterialsPool) + { + llassert(0); + LL_WARNS() << "Ignorning duplicate materials pool." << LL_ENDL; + } + else + { + mMaterialsPool = new_poolp; + } + break; + case LLDrawPool::POOL_ALPHA_PRE_WATER: + if( mAlphaPoolPreWater ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha pre-water pool" << LL_ENDL; + } + else + { + mAlphaPoolPreWater = (LLDrawPoolAlpha*) new_poolp; + } + break; + case LLDrawPool::POOL_ALPHA_POST_WATER: + if (mAlphaPoolPostWater) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Alpha post-water pool" << LL_ENDL; + } + else + { + mAlphaPoolPostWater = (LLDrawPoolAlpha*)new_poolp; + } + break; + + case LLDrawPool::POOL_AVATAR: + case LLDrawPool::POOL_CONTROL_AV: + break; // Do nothing + + case LLDrawPool::POOL_SKY: + if( mSkyPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << LL_ENDL; + } + else + { + mSkyPool = new_poolp; + } + break; + + case LLDrawPool::POOL_WATER: + if( mWaterPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water pool" << LL_ENDL; + } + else + { + mWaterPool = new_poolp; + } + break; + + case LLDrawPool::POOL_WL_SKY: + if( mWLSkyPool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate WLSky Pool" << LL_ENDL; + } + else + { + mWLSkyPool = new_poolp; + } + break; + + case LLDrawPool::POOL_GLTF_PBR: + if( mPBROpaquePool ) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Opaque Pool" << LL_ENDL; + } + else + { + mPBROpaquePool = new_poolp; + } + break; + + case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK: + if (mPBRAlphaMaskPool) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Alpha Mask Pool" << LL_ENDL; + } + else + { + mPBRAlphaMaskPool = new_poolp; + } + break; + + + default: + llassert(0); + LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL; + break; + } +} + +void LLPipeline::removePool( LLDrawPool* poolp ) { - assertInitialized(); - removeFromQuickLookup(poolp); - mPools.erase(poolp); - delete poolp; + assertInitialized(); + removeFromQuickLookup(poolp); + mPools.erase(poolp); + delete poolp; } void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) { - assertInitialized(); - switch( poolp->getType() ) - { - case LLDrawPool::POOL_SIMPLE: - llassert(mSimplePool == poolp); - mSimplePool = NULL; - break; - - case LLDrawPool::POOL_ALPHA_MASK: - llassert(mAlphaMaskPool == poolp); - mAlphaMaskPool = NULL; - break; - - case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: - llassert(mFullbrightAlphaMaskPool == poolp); - mFullbrightAlphaMaskPool = NULL; - break; - - case LLDrawPool::POOL_GRASS: - llassert(mGrassPool == poolp); - mGrassPool = NULL; - break; - - case LLDrawPool::POOL_FULLBRIGHT: - llassert(mFullbrightPool == poolp); - mFullbrightPool = NULL; - break; - - case LLDrawPool::POOL_WL_SKY: - llassert(mWLSkyPool == poolp); - mWLSkyPool = NULL; - break; - - case LLDrawPool::POOL_GLOW: - llassert(mGlowPool == poolp); - mGlowPool = NULL; - break; - - case LLDrawPool::POOL_TREE: - #ifdef _DEBUG - { - bool found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTreePools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_TERRAIN: - #ifdef _DEBUG - { - bool found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_BUMP: - llassert( poolp == mBumpPool ); - mBumpPool = NULL; - break; - - case LLDrawPool::POOL_MATERIALS: - llassert(poolp == mMaterialsPool); - mMaterialsPool = NULL; - break; - - case LLDrawPool::POOL_ALPHA_PRE_WATER: - llassert( poolp == mAlphaPoolPreWater ); - mAlphaPoolPreWater = nullptr; - break; - + assertInitialized(); + switch( poolp->getType() ) + { + case LLDrawPool::POOL_SIMPLE: + llassert(mSimplePool == poolp); + mSimplePool = NULL; + break; + + case LLDrawPool::POOL_ALPHA_MASK: + llassert(mAlphaMaskPool == poolp); + mAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK: + llassert(mFullbrightAlphaMaskPool == poolp); + mFullbrightAlphaMaskPool = NULL; + break; + + case LLDrawPool::POOL_GRASS: + llassert(mGrassPool == poolp); + mGrassPool = NULL; + break; + + case LLDrawPool::POOL_FULLBRIGHT: + llassert(mFullbrightPool == poolp); + mFullbrightPool = NULL; + break; + + case LLDrawPool::POOL_WL_SKY: + llassert(mWLSkyPool == poolp); + mWLSkyPool = NULL; + break; + + case LLDrawPool::POOL_GLOW: + llassert(mGlowPool == poolp); + mGlowPool = NULL; + break; + + case LLDrawPool::POOL_TREE: + #ifdef _DEBUG + { + bool found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTreePools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; + + case LLDrawPool::POOL_TERRAIN: + #ifdef _DEBUG + { + bool found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; + + case LLDrawPool::POOL_BUMP: + llassert( poolp == mBumpPool ); + mBumpPool = NULL; + break; + + case LLDrawPool::POOL_MATERIALS: + llassert(poolp == mMaterialsPool); + mMaterialsPool = NULL; + break; + + case LLDrawPool::POOL_ALPHA_PRE_WATER: + llassert( poolp == mAlphaPoolPreWater ); + mAlphaPoolPreWater = nullptr; + break; + case LLDrawPool::POOL_ALPHA_POST_WATER: llassert(poolp == mAlphaPoolPostWater); mAlphaPoolPostWater = nullptr; break; - case LLDrawPool::POOL_AVATAR: - case LLDrawPool::POOL_CONTROL_AV: - break; // Do nothing + case LLDrawPool::POOL_AVATAR: + case LLDrawPool::POOL_CONTROL_AV: + break; // Do nothing - case LLDrawPool::POOL_SKY: - llassert( poolp == mSkyPool ); - mSkyPool = NULL; - break; + case LLDrawPool::POOL_SKY: + llassert( poolp == mSkyPool ); + mSkyPool = NULL; + break; - case LLDrawPool::POOL_WATER: - llassert( poolp == mWaterPool ); - mWaterPool = NULL; - break; + case LLDrawPool::POOL_WATER: + llassert( poolp == mWaterPool ); + mWaterPool = NULL; + break; case LLDrawPool::POOL_GLTF_PBR: llassert( poolp == mPBROpaquePool ); @@ -5148,23 +5148,23 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mPBRAlphaMaskPool = NULL; break; - default: - llassert(0); - LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; - break; - } + default: + llassert(0); + LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; + break; + } } void LLPipeline::resetDrawOrders() { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - assertInitialized(); - // Iterate through all of the draw pools and rebuild them. - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->resetDrawOrders(); - } + assertInitialized(); + // Iterate through all of the draw pools and rebuild them. + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + poolp->resetDrawOrders(); + } } //============================================================================ @@ -5173,7 +5173,7 @@ void LLPipeline::resetDrawOrders() void LLPipeline::setupAvatarLights(bool for_edit) { - assertInitialized(); + assertInitialized(); LLEnvironment& environment = LLEnvironment::instance(); LLSettingsSky::ptr_t psky = environment.getCurrentSky(); @@ -5181,130 +5181,130 @@ void LLPipeline::setupAvatarLights(bool for_edit) bool sun_up = environment.getIsSunUp(); - if (for_edit) - { - LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); - LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light - LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); - LLMatrix4 camera_rot(camera_mat.getMat3()); - camera_rot.invert(); - LLVector4 light_pos = light_pos_cam * camera_rot; - - light_pos.normalize(); - - LLLightState* light = gGL.getLight(1); - - mHWLightColors[1] = diffuse; - - light->setDiffuse(diffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setPosition(light_pos); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) - { + if (for_edit) + { + LLColor4 diffuse(1.f, 1.f, 1.f, 0.f); + LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light + LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview(); + LLMatrix4 camera_rot(camera_mat.getMat3()); + camera_rot.invert(); + LLVector4 light_pos = light_pos_cam * camera_rot; + + light_pos.normalize(); + + LLLightState* light = gGL.getLight(1); + + mHWLightColors[1] = diffuse; + + light->setDiffuse(diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setPosition(light_pos); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } + else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) + { LLVector3 light_dir = sun_up ? LLVector3(mSunDir) : LLVector3(mMoonDir); - LLVector3 opposite_pos = -light_dir; - LLVector3 orthog_light_pos = light_dir % LLVector3::z_axis; - LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f); - backlight_pos.normalize(); - - LLColor4 light_diffuse = sun_up ? mSunDiffuse : mMoonDiffuse; - - LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f); - F32 max_component = 0.001f; - for (S32 i = 0; i < 3; i++) - { - if (backlight_diffuse.mV[i] > max_component) - { - max_component = backlight_diffuse.mV[i]; - } - } - F32 backlight_mag; - if (LLEnvironment::instance().getIsSunUp()) - { - backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; - } - else - { - backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT; - } - backlight_diffuse *= backlight_mag / max_component; - - mHWLightColors[1] = backlight_diffuse; - - LLLightState* light = gGL.getLight(1); - - light->setPosition(backlight_pos); - light->setDiffuse(backlight_diffuse); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - else - { - LLLightState* light = gGL.getLight(1); - - mHWLightColors[1] = LLColor4::black; - - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - } + LLVector3 opposite_pos = -light_dir; + LLVector3 orthog_light_pos = light_dir % LLVector3::z_axis; + LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f); + backlight_pos.normalize(); + + LLColor4 light_diffuse = sun_up ? mSunDiffuse : mMoonDiffuse; + + LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f); + F32 max_component = 0.001f; + for (S32 i = 0; i < 3; i++) + { + if (backlight_diffuse.mV[i] > max_component) + { + max_component = backlight_diffuse.mV[i]; + } + } + F32 backlight_mag; + if (LLEnvironment::instance().getIsSunUp()) + { + backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT; + } + else + { + backlight_mag = BACKLIGHT_NIGHT_MAGNITUDE_OBJECT; + } + backlight_diffuse *= backlight_mag / max_component; + + mHWLightColors[1] = backlight_diffuse; + + LLLightState* light = gGL.getLight(1); + + light->setPosition(backlight_pos); + light->setDiffuse(backlight_diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } + else + { + LLLightState* light = gGL.getLight(1); + + mHWLightColors[1] = LLColor4::black; + + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + } } static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_dist) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - F32 inten = light->getLightIntensity(); - if (inten < .001f) - { - return max_dist; - } - bool selected = light->isSelected(); - if (selected) - { + F32 inten = light->getLightIntensity(); + if (inten < .001f) + { + return max_dist; + } + bool selected = light->isSelected(); + if (selected) + { return 0.f; // selected lights get highest priority - } + } F32 radius = light->getLightRadius(); F32 dist = dist_vec(light->getRenderPosition(), cam_pos); dist = llmax(dist - radius, 0.f); - if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) - { - // moving lights get a little higher priority (too much causes artifacts) + if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) + { + // moving lights get a little higher priority (too much causes artifacts) dist = llmax(dist - light->getLightRadius()*0.25f, 0.f); - } - return dist; + } + return dist; } void LLPipeline::calcNearbyLights(LLCamera& camera) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - assertInitialized(); + assertInitialized(); - if (LLPipeline::sReflectionRender || gCubeSnapshot || LLPipeline::sRenderingHUDs) - { - return; - } + if (LLPipeline::sReflectionRender || gCubeSnapshot || LLPipeline::sRenderingHUDs) + { + return; + } static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); - if (local_light_count >= 1) - { - // mNearbyLight (and all light_set_t's) are sorted such that - // begin() == the closest light and rbegin() == the farthest light - const S32 MAX_LOCAL_LIGHTS = 6; + if (local_light_count >= 1) + { + // mNearbyLight (and all light_set_t's) are sorted such that + // begin() == the closest light and rbegin() == the farthest light + const S32 MAX_LOCAL_LIGHTS = 6; LLVector3 cam_pos = camera.getOrigin(); - + F32 max_dist; if (LLPipeline::sRenderDeferred) { @@ -5315,15 +5315,15 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) max_dist = llmin(RenderFarClip, LIGHT_MAX_RADIUS * 4.f); } - // UPDATE THE EXISTING NEARBY LIGHTS - light_set_t cur_nearby_lights; - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - const Light* light = &(*iter); - LLDrawable* drawable = light->drawable; + // UPDATE THE EXISTING NEARBY LIGHTS + light_set_t cur_nearby_lights; + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + const Light* light = &(*iter); + LLDrawable* drawable = light->drawable; const LLViewerObject *vobj = light->drawable->getVObj(); - if(vobj && vobj->getAvatar() + if(vobj && vobj->getAvatar() && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList() || vobj->getAvatar()->isTooSlow()) ) { @@ -5331,22 +5331,22 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) continue; } - LLVOVolume* volight = drawable->getVOVolume(); - if (!volight || !drawable->isState(LLDrawable::LIGHT)) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (light->fade <= -LIGHT_FADE_TIME) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } - if (!sRenderAttachedLights && volight && volight->isAttachment()) - { - drawable->clearState(LLDrawable::NEARBY_LIGHT); - continue; - } + LLVOVolume* volight = drawable->getVOVolume(); + if (!volight || !drawable->isState(LLDrawable::LIGHT)) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + if (light->fade <= -LIGHT_FADE_TIME) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } + if (!sRenderAttachedLights && volight && volight->isAttachment()) + { + drawable->clearState(LLDrawable::NEARBY_LIGHT); + continue; + } F32 dist = calc_light_dist(volight, cam_pos, max_dist); F32 fade = light->fade; @@ -5380,28 +5380,28 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) } } cur_nearby_lights.insert(Light(drawable, dist, fade)); - } - mNearbyLights = cur_nearby_lights; - - // FIND NEW LIGHTS THAT ARE IN RANGE - light_set_t new_nearby_lights; - for (LLDrawable::ordered_drawable_set_t::iterator iter = mLights.begin(); - iter != mLights.end(); ++iter) - { - LLDrawable* drawable = *iter; - LLVOVolume* light = drawable->getVOVolume(); - if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT)) - { - continue; - } - if (light->isHUDAttachment()) - { - continue; // no lighting from HUD objects - } + } + mNearbyLights = cur_nearby_lights; + + // FIND NEW LIGHTS THAT ARE IN RANGE + light_set_t new_nearby_lights; + for (LLDrawable::ordered_drawable_set_t::iterator iter = mLights.begin(); + iter != mLights.end(); ++iter) + { + LLDrawable* drawable = *iter; + LLVOVolume* light = drawable->getVOVolume(); + if (!light || drawable->isState(LLDrawable::NEARBY_LIGHT)) + { + continue; + } + if (light->isHUDAttachment()) + { + continue; // no lighting from HUD objects + } if (!sRenderAttachedLights && light && light->isAttachment()) - { - continue; - } + { + continue; + } LLVOAvatar * av = light->getAvatar(); if (av && (av->isTooComplex() || av->isInMuteList() || av->isTooSlow())) { @@ -5410,36 +5410,36 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) } F32 dist = calc_light_dist(light, cam_pos, max_dist); if (dist >= max_dist) - { - continue; - } - new_nearby_lights.insert(Light(drawable, dist, 0.f)); + { + continue; + } + new_nearby_lights.insert(Light(drawable, dist, 0.f)); if (!LLPipeline::sRenderDeferred && new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS) - { - new_nearby_lights.erase(--new_nearby_lights.end()); - const Light& last = *new_nearby_lights.rbegin(); - max_dist = last.dist; - } - } - - // INSERT ANY NEW LIGHTS - for (light_set_t::iterator iter = new_nearby_lights.begin(); - iter != new_nearby_lights.end(); iter++) - { - const Light* light = &(*iter); + { + new_nearby_lights.erase(--new_nearby_lights.end()); + const Light& last = *new_nearby_lights.rbegin(); + max_dist = last.dist; + } + } + + // INSERT ANY NEW LIGHTS + for (light_set_t::iterator iter = new_nearby_lights.begin(); + iter != new_nearby_lights.end(); iter++) + { + const Light* light = &(*iter); if (LLPipeline::sRenderDeferred || mNearbyLights.size() < (U32)MAX_LOCAL_LIGHTS) - { - mNearbyLights.insert(*light); - ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); - } - else - { - // crazy cast so that we can overwrite the fade value - // even though gcc enforces sets as const - // (fade value doesn't affect sort so this is safe) - Light* farthest_light = (const_cast(&(*(mNearbyLights.rbegin())))); - if (light->dist < farthest_light->dist) - { + { + mNearbyLights.insert(*light); + ((LLDrawable*) light->drawable)->setState(LLDrawable::NEARBY_LIGHT); + } + else + { + // crazy cast so that we can overwrite the fade value + // even though gcc enforces sets as const + // (fade value doesn't affect sort so this is safe) + Light* farthest_light = (const_cast(&(*(mNearbyLights.rbegin())))); + if (light->dist < farthest_light->dist) + { // mark light to fade out // visibility goes down from -0 to -LIGHT_FADE_TIME. // @@ -5456,29 +5456,29 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { farthest_light->fade -= LIGHT_FADE_TIME; } - } - else - { - break; // none of the other lights are closer - } - } - } - - //mark nearby lights not-removable. - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); iter++) - { - const Light* light = &(*iter); - ((LLViewerOctreeEntryData*) light->drawable)->setVisible(); - } - } + } + else + { + break; // none of the other lights are closer + } + } + } + + //mark nearby lights not-removable. + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); iter++) + { + const Light* light = &(*iter); + ((LLViewerOctreeEntryData*) light->drawable)->setVisible(); + } + } } void LLPipeline::setupHWLights() { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; - assertInitialized(); - + assertInitialized(); + if (LLPipeline::sRenderingHUDs) { return; @@ -5498,13 +5498,13 @@ void LLPipeline::setupHWLights() // Ambient LLColor4 ambient = psky->getTotalAmbient(); - gGL.setAmbientLightColor(ambient); + gGL.setAmbientLightColor(ambient); bool sun_up = environment.getIsSunUp(); bool moon_up = environment.getIsMoonUp(); - // Light 0 = Sun or Moon (All objects) - { + // Light 0 = Sun or Moon (All objects) + { LLVector4 sun_dir(environment.getSunDirection(), 0.0f); LLVector4 moon_dir(environment.getMoonDirection(), 0.0f); @@ -5514,12 +5514,12 @@ void LLPipeline::setupHWLights() mSunDiffuse.setVec(psky->getSunlightColor()); mMoonDiffuse.setVec(psky->getMoonlightColor()); - F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); - if (max_color > 1.f) - { - mSunDiffuse *= 1.f/max_color; - } - mSunDiffuse.clamp(); + F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]); + if (max_color > 1.f) + { + mSunDiffuse *= 1.f/max_color; + } + mSunDiffuse.clamp(); max_color = llmax(mMoonDiffuse.mV[0], mMoonDiffuse.mV[1], mMoonDiffuse.mV[2]); if (max_color > 1.f) @@ -5530,54 +5530,54 @@ void LLPipeline::setupHWLights() // prevent underlighting from having neither lightsource facing us if (!sun_up && !moon_up) - { + { mSunDiffuse.setVec(LLColor4(0.0, 0.0, 0.0, 1.0)); mMoonDiffuse.setVec(LLColor4(0.0, 0.0, 0.0, 1.0)); mSunDir.setVec(LLVector4(0.0, 1.0, 0.0, 0.0)); mMoonDir.setVec(LLVector4(0.0, 1.0, 0.0, 0.0)); - } + } LLVector4 light_dir = sun_up ? mSunDir : mMoonDir; mHWLightColors[0] = sun_up ? mSunDiffuse : mMoonDiffuse; - LLLightState* light = gGL.getLight(0); + LLLightState* light = gGL.getLight(0); light->setPosition(light_dir); light->setSunPrimary(sun_up); light->setDiffuse(mHWLightColors[0]); light->setDiffuseB(mMoonDiffuse); light->setAmbient(psky->getTotalAmbient()); - light->setSpecular(LLColor4::black); - light->setConstantAttenuation(1.f); - light->setLinearAttenuation(0.f); - light->setQuadraticAttenuation(0.f); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - } - - // Light 1 = Backlight (for avatars) - // (set by enableLightsAvatar) - - S32 cur_light = 2; - - // Nearby lights = LIGHT 2-7 - - mLightMovingMask = 0; - + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + } + + // Light 1 = Backlight (for avatars) + // (set by enableLightsAvatar) + + S32 cur_light = 2; + + // Nearby lights = LIGHT 2-7 + + mLightMovingMask = 0; + static LLCachedControl local_light_count(gSavedSettings, "RenderLocalLightCount", 256); - if (local_light_count >= 1) - { - for (light_set_t::iterator iter = mNearbyLights.begin(); - iter != mNearbyLights.end(); ++iter) - { - LLDrawable* drawable = iter->drawable; - LLVOVolume* light = drawable->getVOVolume(); - if (!light) - { - continue; - } + if (local_light_count >= 1) + { + for (light_set_t::iterator iter = mNearbyLights.begin(); + iter != mNearbyLights.end(); ++iter) + { + LLDrawable* drawable = iter->drawable; + LLVOVolume* light = drawable->getVOVolume(); + if (!light) + { + continue; + } if (light->isAttachment()) { @@ -5587,32 +5587,32 @@ void LLPipeline::setupHWLights() } } - if (drawable->isState(LLDrawable::ACTIVE)) - { - mLightMovingMask |= (1<isState(LLDrawable::ACTIVE)) + { + mLightMovingMask |= (1<getLightLinearColor() * light_scale; - light_color.mV[3] = 0.0f; - - F32 fade = iter->fade; - if (fade < LIGHT_FADE_TIME) - { - // fade in/out light - if (fade >= 0.f) - { - fade = fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); - } - else - { - fade = 1.f + fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); - } - fade = llclamp(fade,0.f,1.f); - light_color *= fade; - } + light_color.mV[3] = 0.0f; + + F32 fade = iter->fade; + if (fade < LIGHT_FADE_TIME) + { + // fade in/out light + if (fade >= 0.f) + { + fade = fade / LIGHT_FADE_TIME; + ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); + } + else + { + fade = 1.f + fade / LIGHT_FADE_TIME; + ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); + } + fade = llclamp(fade,0.f,1.f); + light_color *= fade; + } if (light_color.magVecSquared() < 0.001f) { @@ -5632,213 +5632,213 @@ void LLPipeline::setupHWLights() F32 linatten = x / adjusted_radius; // % of brightness at radius mHWLightColors[cur_light] = light_color; - LLLightState* light_state = gGL.getLight(cur_light); - - light_state->setPosition(light_pos_gl); - light_state->setDiffuse(light_color); - light_state->setAmbient(LLColor4::black); - light_state->setConstantAttenuation(0.f); + LLLightState* light_state = gGL.getLight(cur_light); + + light_state->setPosition(light_pos_gl); + light_state->setDiffuse(light_color); + light_state->setAmbient(LLColor4::black); + light_state->setConstantAttenuation(0.f); light_state->setSize(light->getLightRadius() * 1.5f); light_state->setFalloff(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF)); - if (sRenderDeferred) - { - light_state->setLinearAttenuation(linatten); - light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights - } - else - { - light_state->setLinearAttenuation(linatten); - light_state->setQuadraticAttenuation(0.f); - } - - - if (light->isLightSpotlight() // directional (spot-)light - && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on - { - LLQuaternion quat = light->getRenderRotation(); - LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction - at_axis *= quat; - - light_state->setSpotDirection(at_axis); - light_state->setSpotCutoff(90.f); - light_state->setSpotExponent(2.f); - - LLVector3 spotParams = light->getSpotLightParams(); - - const LLColor4 specular(0.f, 0.f, 0.f, spotParams[2]); - light_state->setSpecular(specular); - } - else // omnidirectional (point) light - { - light_state->setSpotExponent(0.f); - light_state->setSpotCutoff(180.f); - - // we use specular.z = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight - const LLColor4 specular(0.f, 0.f, 1.f, 0.f); - light_state->setSpecular(specular); - } - cur_light++; - if (cur_light >= 8) - { - break; // safety - } - } - } - for ( ; cur_light < 8 ; cur_light++) - { - mHWLightColors[cur_light] = LLColor4::black; - LLLightState* light = gGL.getLight(cur_light); - light->setSunPrimary(true); - light->setDiffuse(LLColor4::black); - light->setAmbient(LLColor4::black); - light->setSpecular(LLColor4::black); - } + if (sRenderDeferred) + { + light_state->setLinearAttenuation(linatten); + light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights + } + else + { + light_state->setLinearAttenuation(linatten); + light_state->setQuadraticAttenuation(0.f); + } - // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode), - // prev site of forward (non-deferred) character light injection, removed by SL-13522 09/20 - // Init GL state - for (S32 i = 0; i < 8; ++i) - { - gGL.getLight(i)->disable(); - } - mLightMask = 0; -} + if (light->isLightSpotlight() // directional (spot-)light + && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on + { + LLQuaternion quat = light->getRenderRotation(); + LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction + at_axis *= quat; -void LLPipeline::enableLights(U32 mask) -{ - assertInitialized(); - - if (mLightMask != mask) - { - stop_glerror(); - if (mask) - { - stop_glerror(); - for (S32 i=0; i<8; i++) - { - LLLightState* light = gGL.getLight(i); - if (mask & (1<enable(); - light->setDiffuse(mHWLightColors[i]); - } - else - { - light->disable(); - light->setDiffuse(LLColor4::black); - } - } - stop_glerror(); - } - mLightMask = mask; - stop_glerror(); - } + light_state->setSpotDirection(at_axis); + light_state->setSpotCutoff(90.f); + light_state->setSpotExponent(2.f); + + LLVector3 spotParams = light->getSpotLightParams(); + + const LLColor4 specular(0.f, 0.f, 0.f, spotParams[2]); + light_state->setSpecular(specular); + } + else // omnidirectional (point) light + { + light_state->setSpotExponent(0.f); + light_state->setSpotCutoff(180.f); + + // we use specular.z = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight + const LLColor4 specular(0.f, 0.f, 1.f, 0.f); + light_state->setSpecular(specular); + } + cur_light++; + if (cur_light >= 8) + { + break; // safety + } + } + } + for ( ; cur_light < 8 ; cur_light++) + { + mHWLightColors[cur_light] = LLColor4::black; + LLLightState* light = gGL.getLight(cur_light); + light->setSunPrimary(true); + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + } + + // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode), + // prev site of forward (non-deferred) character light injection, removed by SL-13522 09/20 + + // Init GL state + for (S32 i = 0; i < 8; ++i) + { + gGL.getLight(i)->disable(); + } + mLightMask = 0; +} + +void LLPipeline::enableLights(U32 mask) +{ + assertInitialized(); + + if (mLightMask != mask) + { + stop_glerror(); + if (mask) + { + stop_glerror(); + for (S32 i=0; i<8; i++) + { + LLLightState* light = gGL.getLight(i); + if (mask & (1<enable(); + light->setDiffuse(mHWLightColors[i]); + } + else + { + light->disable(); + light->setDiffuse(LLColor4::black); + } + } + stop_glerror(); + } + mLightMask = mask; + stop_glerror(); + } } void LLPipeline::enableLightsDynamic() { - assertInitialized(); - U32 mask = 0xff & (~2); // Local lights - enableLights(mask); - - if (isAgentAvatarValid()) - { - if (gAgentAvatarp->mSpecialRenderMode == 0) // normal - { - gPipeline.enableLightsAvatar(); - } - else if (gAgentAvatarp->mSpecialRenderMode == 2) // anim preview - { - gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); - } - } + assertInitialized(); + U32 mask = 0xff & (~2); // Local lights + enableLights(mask); + + if (isAgentAvatarValid()) + { + if (gAgentAvatarp->mSpecialRenderMode == 0) // normal + { + gPipeline.enableLightsAvatar(); + } + else if (gAgentAvatarp->mSpecialRenderMode == 2) // anim preview + { + gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); + } + } } void LLPipeline::enableLightsAvatar() { - U32 mask = 0xff; // All lights - setupAvatarLights(FALSE); - enableLights(mask); + U32 mask = 0xff; // All lights + setupAvatarLights(FALSE); + enableLights(mask); } void LLPipeline::enableLightsPreview() { - disableLights(); - - LLColor4 ambient = PreviewAmbientColor; - gGL.setAmbientLightColor(ambient); - - LLColor4 diffuse0 = PreviewDiffuse0; - LLColor4 specular0 = PreviewSpecular0; - LLColor4 diffuse1 = PreviewDiffuse1; - LLColor4 specular1 = PreviewSpecular1; - LLColor4 diffuse2 = PreviewDiffuse2; - LLColor4 specular2 = PreviewSpecular2; - - LLVector3 dir0 = PreviewDirection0; - LLVector3 dir1 = PreviewDirection1; - LLVector3 dir2 = PreviewDirection2; - - dir0.normVec(); - dir1.normVec(); - dir2.normVec(); - - LLVector4 light_pos(dir0, 0.0f); - - LLLightState* light = gGL.getLight(1); - - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse0); - light->setAmbient(ambient); - light->setSpecular(specular0); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir1, 0.f); - - light = gGL.getLight(2); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse1); - light->setAmbient(ambient); - light->setSpecular(specular1); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); - - light_pos = LLVector4(dir2, 0.f); - light = gGL.getLight(3); - light->enable(); - light->setPosition(light_pos); - light->setDiffuse(diffuse2); - light->setAmbient(ambient); - light->setSpecular(specular2); - light->setSpotExponent(0.f); - light->setSpotCutoff(180.f); + disableLights(); + + LLColor4 ambient = PreviewAmbientColor; + gGL.setAmbientLightColor(ambient); + + LLColor4 diffuse0 = PreviewDiffuse0; + LLColor4 specular0 = PreviewSpecular0; + LLColor4 diffuse1 = PreviewDiffuse1; + LLColor4 specular1 = PreviewSpecular1; + LLColor4 diffuse2 = PreviewDiffuse2; + LLColor4 specular2 = PreviewSpecular2; + + LLVector3 dir0 = PreviewDirection0; + LLVector3 dir1 = PreviewDirection1; + LLVector3 dir2 = PreviewDirection2; + + dir0.normVec(); + dir1.normVec(); + dir2.normVec(); + + LLVector4 light_pos(dir0, 0.0f); + + LLLightState* light = gGL.getLight(1); + + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse0); + light->setAmbient(ambient); + light->setSpecular(specular0); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir1, 0.f); + + light = gGL.getLight(2); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse1); + light->setAmbient(ambient); + light->setSpecular(specular1); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); + + light_pos = LLVector4(dir2, 0.f); + light = gGL.getLight(3); + light->enable(); + light->setPosition(light_pos); + light->setDiffuse(diffuse2); + light->setAmbient(ambient); + light->setSpecular(specular2); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } void LLPipeline::enableLightsAvatarEdit(const LLColor4& color) { - U32 mask = 0x2002; // Avatar backlight only, set ambient - setupAvatarLights(TRUE); - enableLights(mask); + U32 mask = 0x2002; // Avatar backlight only, set ambient + setupAvatarLights(TRUE); + enableLights(mask); - gGL.setAmbientLightColor(color); + gGL.setAmbientLightColor(color); } void LLPipeline::enableLightsFullbright() { - assertInitialized(); - U32 mask = 0x1000; // Non-0 mask, set ambient - enableLights(mask); + assertInitialized(); + U32 mask = 0x1000; // Non-0 mask, set ambient + enableLights(mask); } void LLPipeline::disableLights() { - enableLights(0); // no lighting (full bright) + enableLights(0); // no lighting (full bright) } //============================================================================ @@ -5851,58 +5851,58 @@ class LLVOLeaf; void LLPipeline::findReferences(LLDrawable *drawablep) { - assertInitialized(); - if (mLights.find(drawablep) != mLights.end()) - { - LL_INFOS() << "In mLights" << LL_ENDL; - } - if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) - { - LL_INFOS() << "In mMovedList" << LL_ENDL; - } - if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) - { - LL_INFOS() << "In mShiftList" << LL_ENDL; - } - if (mRetexturedList.find(drawablep) != mRetexturedList.end()) - { - LL_INFOS() << "In mRetexturedList" << LL_ENDL; - } - - if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) - { - LL_INFOS() << "In mBuildQ1" << LL_ENDL; - } - - S32 count; - - count = gObjectList.findReferences(drawablep); - if (count) - { - LL_INFOS() << "In other drawables: " << count << " references" << LL_ENDL; - } + assertInitialized(); + if (mLights.find(drawablep) != mLights.end()) + { + LL_INFOS() << "In mLights" << LL_ENDL; + } + if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) + { + LL_INFOS() << "In mMovedList" << LL_ENDL; + } + if (std::find(mShiftList.begin(), mShiftList.end(), drawablep) != mShiftList.end()) + { + LL_INFOS() << "In mShiftList" << LL_ENDL; + } + if (mRetexturedList.find(drawablep) != mRetexturedList.end()) + { + LL_INFOS() << "In mRetexturedList" << LL_ENDL; + } + + if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) + { + LL_INFOS() << "In mBuildQ1" << LL_ENDL; + } + + S32 count; + + count = gObjectList.findReferences(drawablep); + if (count) + { + LL_INFOS() << "In other drawables: " << count << " references" << LL_ENDL; + } } bool LLPipeline::verify() { - bool ok = assertInitialized(); - if (ok) - { - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (!poolp->verify()) - { - ok = false; - } - } - } - - if (!ok) - { - LL_WARNS() << "Pipeline verify failed!" << LL_ENDL; - } - return ok; + bool ok = assertInitialized(); + if (ok) + { + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) + { + LLDrawPool *poolp = *iter; + if (!poolp->verify()) + { + ok = false; + } + } + } + + if (!ok) + { + LL_WARNS() << "Pipeline verify failed!" << LL_ENDL; + } + return ok; } ////////////////////////////// @@ -5913,89 +5913,89 @@ bool LLPipeline::verify() /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** - * A method to compute a ray-AABB intersection. - * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 - * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) - * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only) + * A method to compute a ray-AABB intersection. + * Original code by Andrew Woo, from "Graphics Gems", Academic Press, 1990 + * Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500) + * Epsilon value added by Klaus Hartmann. (discarding it saves a few cycles only) * - * Hence this version is faster as well as more robust than the original one. + * Hence this version is faster as well as more robust than the original one. * - * Should work provided: - * 1) the integer representation of 0.0f is 0x00000000 - * 2) the sign bit of the float is the most significant one + * Should work provided: + * 1) the integer representation of 0.0f is 0x00000000 + * 2) the sign bit of the float is the most significant one * - * Report bugs: p.terdiman@codercorner.com + * Report bugs: p.terdiman@codercorner.com * - * \param aabb [in] the axis-aligned bounding box - * \param origin [in] ray origin - * \param dir [in] ray direction - * \param coord [out] impact coordinates - * \return true if ray intersects AABB + * \param aabb [in] the axis-aligned bounding box + * \param origin [in] ray origin + * \param dir [in] ray direction + * \param coord [out] impact coordinates + * \return true if ray intersects AABB */ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //#define RAYAABB_EPSILON 0.00001f -#define IR(x) ((U32&)x) +#define IR(x) ((U32&)x) bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon) { - bool Inside = true; - LLVector3 MinB = center - size; - LLVector3 MaxB = center + size; - LLVector3 MaxT; - MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f; - - // Find candidate planes. - for(U32 i=0;i<3;i++) - { - if(origin.mV[i] < MinB.mV[i]) - { - coord.mV[i] = MinB.mV[i]; - Inside = false; - - // Calculate T distances to candidate planes - if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i]; - } - else if(origin.mV[i] > MaxB.mV[i]) - { - coord.mV[i] = MaxB.mV[i]; - Inside = false; - - // Calculate T distances to candidate planes - if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i]; - } - } - - // Ray origin inside bounding box - if(Inside) - { - coord = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - U32 WhichPlane = 0; - if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1; - if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2; - - // Check final candidate actually inside box - if(IR(MaxT.mV[WhichPlane])&0x80000000) return false; - - for(U32 i=0;i<3;i++) - { - if(i!=WhichPlane) - { - coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i]; - if (epsilon > 0) - { - if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false; - } - else - { - if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false; - } - } - } - return true; // ray hits box + bool Inside = true; + LLVector3 MinB = center - size; + LLVector3 MaxB = center + size; + LLVector3 MaxT; + MaxT.mV[VX]=MaxT.mV[VY]=MaxT.mV[VZ]=-1.0f; + + // Find candidate planes. + for(U32 i=0;i<3;i++) + { + if(origin.mV[i] < MinB.mV[i]) + { + coord.mV[i] = MinB.mV[i]; + Inside = false; + + // Calculate T distances to candidate planes + if(IR(dir.mV[i])) MaxT.mV[i] = (MinB.mV[i] - origin.mV[i]) / dir.mV[i]; + } + else if(origin.mV[i] > MaxB.mV[i]) + { + coord.mV[i] = MaxB.mV[i]; + Inside = false; + + // Calculate T distances to candidate planes + if(IR(dir.mV[i])) MaxT.mV[i] = (MaxB.mV[i] - origin.mV[i]) / dir.mV[i]; + } + } + + // Ray origin inside bounding box + if(Inside) + { + coord = origin; + return true; + } + + // Get largest of the maxT's for final choice of intersection + U32 WhichPlane = 0; + if(MaxT.mV[1] > MaxT.mV[WhichPlane]) WhichPlane = 1; + if(MaxT.mV[2] > MaxT.mV[WhichPlane]) WhichPlane = 2; + + // Check final candidate actually inside box + if(IR(MaxT.mV[WhichPlane])&0x80000000) return false; + + for(U32 i=0;i<3;i++) + { + if(i!=WhichPlane) + { + coord.mV[i] = origin.mV[i] + MaxT.mV[WhichPlane] * dir.mV[i]; + if (epsilon > 0) + { + if(coord.mV[i] < MinB.mV[i] - epsilon || coord.mV[i] > MaxB.mV[i] + epsilon) return false; + } + else + { + if(coord.mV[i] < MinB.mV[i] || coord.mV[i] > MaxB.mV[i]) return false; + } + } + } + return true; // ray hits box } ////////////////////////////// @@ -6006,454 +6006,454 @@ bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& void LLPipeline::setLight(LLDrawable *drawablep, bool is_light) { - if (drawablep && assertInitialized()) - { - if (is_light) - { - mLights.insert(drawablep); - drawablep->setState(LLDrawable::LIGHT); - } - else - { - drawablep->clearState(LLDrawable::LIGHT); - mLights.erase(drawablep); - } - } + if (drawablep && assertInitialized()) + { + if (is_light) + { + mLights.insert(drawablep); + drawablep->setState(LLDrawable::LIGHT); + } + else + { + drawablep->clearState(LLDrawable::LIGHT); + mLights.erase(drawablep); + } + } } //static void LLPipeline::toggleRenderType(U32 type) { - gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; - if (type == LLPipeline::RENDER_TYPE_WATER) - { - gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER]; - } + gPipeline.mRenderTypeEnabled[type] = !gPipeline.mRenderTypeEnabled[type]; + if (type == LLPipeline::RENDER_TYPE_WATER) + { + gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER] = !gPipeline.mRenderTypeEnabled[LLPipeline::RENDER_TYPE_VOIDWATER]; + } } //static void LLPipeline::toggleRenderTypeControl(U32 type) { - gPipeline.toggleRenderType(type); + gPipeline.toggleRenderType(type); } //static bool LLPipeline::hasRenderTypeControl(U32 type) { - return gPipeline.hasRenderType(type); + return gPipeline.hasRenderType(type); } // Allows UI items labeled "Hide foo" instead of "Show foo" //static bool LLPipeline::toggleRenderTypeControlNegated(S32 type) { - return !gPipeline.hasRenderType(type); + return !gPipeline.hasRenderType(type); } //static void LLPipeline::toggleRenderDebug(U64 bit) { - if (gPipeline.hasRenderDebugMask(bit)) - { - LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << LL_ENDL; - } - else - { - LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << LL_ENDL; - } - gPipeline.mRenderDebugMask ^= bit; + if (gPipeline.hasRenderDebugMask(bit)) + { + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " off" << std::dec << LL_ENDL; + } + else + { + LL_INFOS() << "Toggling render debug mask " << std::hex << bit << " on" << std::dec << LL_ENDL; + } + gPipeline.mRenderDebugMask ^= bit; } //static bool LLPipeline::toggleRenderDebugControl(U64 bit) { - return gPipeline.hasRenderDebugMask(bit); + return gPipeline.hasRenderDebugMask(bit); } //static void LLPipeline::toggleRenderDebugFeature(U32 bit) { - gPipeline.mRenderDebugFeatureMask ^= bit; + gPipeline.mRenderDebugFeatureMask ^= bit; } //static bool LLPipeline::toggleRenderDebugFeatureControl(U32 bit) { - return gPipeline.hasRenderDebugFeatureMask(bit); + return gPipeline.hasRenderDebugFeatureMask(bit); } void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value) { - if (value) - { - gPipeline.mRenderDebugFeatureMask |= bit; - } - else - { - gPipeline.mRenderDebugFeatureMask &= !bit; - } + if (value) + { + gPipeline.mRenderDebugFeatureMask |= bit; + } + else + { + gPipeline.mRenderDebugFeatureMask &= !bit; + } } void LLPipeline::pushRenderDebugFeatureMask() { - mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); + mRenderDebugFeatureStack.push(mRenderDebugFeatureMask); } void LLPipeline::popRenderDebugFeatureMask() { - if (mRenderDebugFeatureStack.empty()) - { - LL_ERRS() << "Depleted render feature stack." << LL_ENDL; - } + if (mRenderDebugFeatureStack.empty()) + { + LL_ERRS() << "Depleted render feature stack." << LL_ENDL; + } - mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); - mRenderDebugFeatureStack.pop(); + mRenderDebugFeatureMask = mRenderDebugFeatureStack.top(); + mRenderDebugFeatureStack.pop(); } // static void LLPipeline::setRenderScriptedBeacons(bool val) { - sRenderScriptedBeacons = val; + sRenderScriptedBeacons = val; } // static void LLPipeline::toggleRenderScriptedBeacons() { - sRenderScriptedBeacons = !sRenderScriptedBeacons; + sRenderScriptedBeacons = !sRenderScriptedBeacons; } // static bool LLPipeline::getRenderScriptedBeacons() { - return sRenderScriptedBeacons; + return sRenderScriptedBeacons; } // static void LLPipeline::setRenderScriptedTouchBeacons(bool val) { - sRenderScriptedTouchBeacons = val; + sRenderScriptedTouchBeacons = val; } // static void LLPipeline::toggleRenderScriptedTouchBeacons() { - sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons; + sRenderScriptedTouchBeacons = !sRenderScriptedTouchBeacons; } // static bool LLPipeline::getRenderScriptedTouchBeacons() { - return sRenderScriptedTouchBeacons; + return sRenderScriptedTouchBeacons; } // static void LLPipeline::setRenderMOAPBeacons(bool val) { - sRenderMOAPBeacons = val; + sRenderMOAPBeacons = val; } // static void LLPipeline::toggleRenderMOAPBeacons() { - sRenderMOAPBeacons = !sRenderMOAPBeacons; + sRenderMOAPBeacons = !sRenderMOAPBeacons; } // static bool LLPipeline::getRenderMOAPBeacons() { - return sRenderMOAPBeacons; + return sRenderMOAPBeacons; } // static void LLPipeline::setRenderPhysicalBeacons(bool val) { - sRenderPhysicalBeacons = val; + sRenderPhysicalBeacons = val; } // static void LLPipeline::toggleRenderPhysicalBeacons() { - sRenderPhysicalBeacons = !sRenderPhysicalBeacons; + sRenderPhysicalBeacons = !sRenderPhysicalBeacons; } // static bool LLPipeline::getRenderPhysicalBeacons() { - return sRenderPhysicalBeacons; + return sRenderPhysicalBeacons; } // static void LLPipeline::setRenderParticleBeacons(bool val) { - sRenderParticleBeacons = val; + sRenderParticleBeacons = val; } // static void LLPipeline::toggleRenderParticleBeacons() { - sRenderParticleBeacons = !sRenderParticleBeacons; + sRenderParticleBeacons = !sRenderParticleBeacons; } // static bool LLPipeline::getRenderParticleBeacons() { - return sRenderParticleBeacons; + return sRenderParticleBeacons; } // static void LLPipeline::setRenderSoundBeacons(bool val) { - sRenderSoundBeacons = val; + sRenderSoundBeacons = val; } // static void LLPipeline::toggleRenderSoundBeacons() { - sRenderSoundBeacons = !sRenderSoundBeacons; + sRenderSoundBeacons = !sRenderSoundBeacons; } // static bool LLPipeline::getRenderSoundBeacons() { - return sRenderSoundBeacons; + return sRenderSoundBeacons; } // static void LLPipeline::setRenderBeacons(bool val) { - sRenderBeacons = val; + sRenderBeacons = val; } // static void LLPipeline::toggleRenderBeacons() { - sRenderBeacons = !sRenderBeacons; + sRenderBeacons = !sRenderBeacons; } // static bool LLPipeline::getRenderBeacons() { - return sRenderBeacons; + return sRenderBeacons; } // static void LLPipeline::setRenderHighlights(bool val) { - sRenderHighlight = val; + sRenderHighlight = val; } // static void LLPipeline::toggleRenderHighlights() { - sRenderHighlight = !sRenderHighlight; + sRenderHighlight = !sRenderHighlight; } // static bool LLPipeline::getRenderHighlights() { - return sRenderHighlight; + return sRenderHighlight; } // static void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) { - sRenderHighlightTextureChannel = channel; + sRenderHighlightTextureChannel = channel; } LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, - S32* face_hit) -{ - LLVector4a local_end = end; - - LLVector4a position; - - LLDrawable* drawable = NULL; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); - if (hit) - { - drawable = hit; - local_end = position; - } - } - } - - LLVOPartGroup* ret = NULL; - if (drawable) - { - //make sure we're returning an LLVOPartGroup - llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); - ret = (LLVOPartGroup*) drawable->getVObj().get(); - } - - if (intersection) - { - *intersection = position; - } - - return ret; + S32* face_hit) +{ + LLVector4a local_end = end; + + LLVector4a position; + + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_PARTICLE); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, TRUE, FALSE, TRUE, FALSE, face_hit, &position, NULL, NULL, NULL); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } + + LLVOPartGroup* ret = NULL; + if (drawable) + { + //make sure we're returning an LLVOPartGroup + llassert(drawable->getVObj()->getPCode() == LLViewerObject::LL_VO_PART_GROUP); + ret = (LLVOPartGroup*) drawable->getVObj().get(); + } + + if (intersection) + { + *intersection = position; + } + + return ret; } LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - bool pick_rigged, + bool pick_transparent, + bool pick_rigged, bool pick_unselectable, bool pick_reflection_probe, - S32* face_hit, + S32* face_hit, S32* gltf_node_hit, S32* gltf_primitive_hit, - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) { - LLDrawable* drawable = NULL; + LLDrawable* drawable = NULL; - LLVector4a local_end = end; + LLVector4a local_end = end; - LLVector4a position; + LLVector4a position; - sPickAvatar = false; //! LLToolMgr::getInstance()->inBuildMode(); - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; + sPickAvatar = false; //! LLToolMgr::getInstance()->inBuildMode(); + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; - for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) - { - if ((j == LLViewerRegion::PARTITION_VOLUME) || - (j == LLViewerRegion::PARTITION_BRIDGE) || + for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++) + { + if ((j == LLViewerRegion::PARTITION_VOLUME) || + (j == LLViewerRegion::PARTITION_BRIDGE) || (j == LLViewerRegion::PARTITION_AVATAR) || // for attachments - (j == LLViewerRegion::PARTITION_CONTROL_AV) || - (j == LLViewerRegion::PARTITION_TERRAIN) || - (j == LLViewerRegion::PARTITION_TREE) || - (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now - { - LLSpatialPartition* part = region->getSpatialPartition(j); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, &position, tex_coord, normal, tangent); - if (hit) - { - drawable = hit; - local_end = position; - } - } - } - } - } - - if (!sPickAvatar) - { - //save hit info in case we need to restore - //due to attachment override - LLVector4a local_normal; - LLVector4a local_tangent; - LLVector2 local_texcoord; - S32 local_face_hit = -1; - - if (face_hit) - { - local_face_hit = *face_hit; - } - if (tex_coord) - { - local_texcoord = *tex_coord; - } - if (tangent) - { - local_tangent = *tangent; - } - else - { - local_tangent.clear(); - } - if (normal) - { - local_normal = *normal; - } - else - { - local_normal.clear(); - } - - const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; - - //check against avatars - sPickAvatar = true; - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR); - if (part && hasRenderType(part->mDrawableType)) - { - LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, &position, tex_coord, normal, tangent); - if (hit) - { - LLVector4a delta; - delta.setSub(position, local_end); - - if (!drawable || - !drawable->getVObj()->isAttachment() || - delta.getLength3().getF32() > ATTACHMENT_OVERRIDE_DIST) - { //avatar overrides if previously hit drawable is not an attachment or - //attachment is far enough away from detected intersection - drawable = hit; - local_end = position; - } - else - { //prioritize attachments over avatars - position = local_end; - - if (face_hit) - { - *face_hit = local_face_hit; - } - if (tex_coord) - { - *tex_coord = local_texcoord; - } - if (tangent) - { - *tangent = local_tangent; - } - if (normal) - { - *normal = local_normal; - } - } - } - } - } - } - - //check all avatar nametags (silly, isn't it?) - for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); - ++iter) - { - LLVOAvatar* av = (LLVOAvatar*) *iter; - if (av->mNameText.notNull() - && av->mNameText->lineSegmentIntersect(start, local_end, position)) - { - drawable = av->mDrawable; - local_end = position; - } - } + (j == LLViewerRegion::PARTITION_CONTROL_AV) || + (j == LLViewerRegion::PARTITION_TERRAIN) || + (j == LLViewerRegion::PARTITION_TREE) || + (j == LLViewerRegion::PARTITION_GRASS)) // only check these partitions for now + { + LLSpatialPartition* part = region->getSpatialPartition(j); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, &position, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + local_end = position; + } + } + } + } + } + + if (!sPickAvatar) + { + //save hit info in case we need to restore + //due to attachment override + LLVector4a local_normal; + LLVector4a local_tangent; + LLVector2 local_texcoord; + S32 local_face_hit = -1; + + if (face_hit) + { + local_face_hit = *face_hit; + } + if (tex_coord) + { + local_texcoord = *tex_coord; + } + if (tangent) + { + local_tangent = *tangent; + } + else + { + local_tangent.clear(); + } + if (normal) + { + local_normal = *normal; + } + else + { + local_normal.clear(); + } + + const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; + + //check against avatars + sPickAvatar = true; + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR); + if (part && hasRenderType(part->mDrawableType)) + { + LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, face_hit, &position, tex_coord, normal, tangent); + if (hit) + { + LLVector4a delta; + delta.setSub(position, local_end); + + if (!drawable || + !drawable->getVObj()->isAttachment() || + delta.getLength3().getF32() > ATTACHMENT_OVERRIDE_DIST) + { //avatar overrides if previously hit drawable is not an attachment or + //attachment is far enough away from detected intersection + drawable = hit; + local_end = position; + } + else + { //prioritize attachments over avatars + position = local_end; + + if (face_hit) + { + *face_hit = local_face_hit; + } + if (tex_coord) + { + *tex_coord = local_texcoord; + } + if (tangent) + { + *tangent = local_tangent; + } + if (normal) + { + *normal = local_normal; + } + } + } + } + } + } + + //check all avatar nametags (silly, isn't it?) + for (std::vector< LLCharacter* >::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); + ++iter) + { + LLVOAvatar* av = (LLVOAvatar*) *iter; + if (av->mNameText.notNull() + && av->mNameText->lineSegmentIntersect(start, local_end, position)) + { + drawable = av->mDrawable; + local_end = position; + } + } S32 node_hit = -1; S32 primitive_hit = -1; @@ -6468,96 +6468,96 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start, { *gltf_node_hit = node_hit; } - + if (gltf_primitive_hit) { *gltf_primitive_hit = primitive_hit; } - if (intersection) - { - *intersection = position; - } + if (intersection) + { + *intersection = position; + } - return drawable ? drawable->getVObj().get() : NULL; + return drawable ? drawable->getVObj().get() : NULL; } LLViewerObject* LLPipeline::lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - S32* face_hit, - LLVector4a* intersection, // return the intersection point - LLVector2* tex_coord, // return the texture coordinates of the intersection point - LLVector4a* normal, // return the surface normal at the intersection point - LLVector4a* tangent // return the surface tangent at the intersection point - ) -{ - LLDrawable* drawable = NULL; - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); - iter != LLWorld::getInstance()->getRegionList().end(); ++iter) - { - LLViewerRegion* region = *iter; - - bool toggle = false; - if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - toggle = true; - } - - LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); - if (part) - { - LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, FALSE, face_hit, intersection, tex_coord, normal, tangent); - if (hit) - { - drawable = hit; - } - } - - if (toggle) - { - toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - } - } - return drawable ? drawable->getVObj().get() : NULL; + bool pick_transparent, + S32* face_hit, + LLVector4a* intersection, // return the intersection point + LLVector2* tex_coord, // return the texture coordinates of the intersection point + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point + ) +{ + LLDrawable* drawable = NULL; + + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + iter != LLWorld::getInstance()->getRegionList().end(); ++iter) + { + LLViewerRegion* region = *iter; + + bool toggle = false; + if (!hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + toggle = true; + } + + LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_HUD); + if (part) + { + LLDrawable* hit = part->lineSegmentIntersect(start, end, pick_transparent, FALSE, TRUE, FALSE, face_hit, intersection, tex_coord, normal, tangent); + if (hit) + { + drawable = hit; + } + } + + if (toggle) + { + toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + } + return drawable ? drawable->getVObj().get() : NULL; } LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) { - if (vobj) - { - LLViewerRegion* region = vobj->getRegion(); - if (region) - { - return region->getSpatialPartition(vobj->getPartitionType()); - } - } - return NULL; + if (vobj) + { + LLViewerRegion* region = vobj->getRegion(); + if (region) + { + return region->getSpatialPartition(vobj->getPartitionType()); + } + } + return NULL; } void LLPipeline::resetVertexBuffers(LLDrawable* drawable) { - if (!drawable) - { - return; - } + if (!drawable) + { + return; + } - for (S32 i = 0; i < drawable->getNumFaces(); i++) - { - LLFace* facep = drawable->getFace(i); - if (facep) - { - facep->clearVertexBuffer(); - } - } + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + facep->clearVertexBuffer(); + } + } } void LLPipeline::renderObjects(U32 type, bool texture, bool batch_texture, bool rigged) { - assertInitialized(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; if (rigged) { @@ -6569,7 +6569,7 @@ void LLPipeline::renderObjects(U32 type, bool texture, bool batch_texture, bool } gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + gGLLastMatrix = NULL; } void LLPipeline::renderGLTFObjects(U32 type, bool texture, bool rigged) @@ -6681,9 +6681,9 @@ void LLPipeline::renderAlphaObjects(bool rigged) // Currently only used for shadows -Cosmic,2023-04-19 void LLPipeline::renderMaskedObjects(U32 type, bool texture, bool batch_texture, bool rigged) { - assertInitialized(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; if (rigged) { mAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture); @@ -6692,16 +6692,16 @@ void LLPipeline::renderMaskedObjects(U32 type, bool texture, bool batch_texture, { mAlphaMaskPool->pushMaskBatches(type, texture, batch_texture); } - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; } // Currently only used for shadows -Cosmic,2023-04-19 void LLPipeline::renderFullbrightMaskedObjects(U32 type, bool texture, bool batch_texture, bool rigged) { - assertInitialized(); - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + assertInitialized(); + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; if (rigged) { mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, texture, batch_texture); @@ -6710,116 +6710,116 @@ void LLPipeline::renderFullbrightMaskedObjects(U32 type, bool texture, bool batc { mFullbrightAlphaMaskPool->pushMaskBatches(type, texture, batch_texture); } - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; } void apply_cube_face_rotation(U32 face) { - switch (face) - { - case 0: - gGL.rotatef(90.f, 0, 1, 0); - gGL.rotatef(180.f, 1, 0, 0); - break; - case 2: - gGL.rotatef(-90.f, 1, 0, 0); - break; - case 4: - gGL.rotatef(180.f, 0, 1, 0); - gGL.rotatef(180.f, 0, 0, 1); - break; - case 1: - gGL.rotatef(-90.f, 0, 1, 0); - gGL.rotatef(180.f, 1, 0, 0); - break; - case 3: - gGL.rotatef(90, 1, 0, 0); - break; - case 5: - gGL.rotatef(180, 0, 0, 1); - break; - } -} - -void validate_framebuffer_object() -{ - GLenum status; - status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); - switch(status) - { - case GL_FRAMEBUFFER_COMPLETE: - //framebuffer OK, no error. - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - // frame buffer not OK: probably means unsupported depth buffer format - LL_ERRS() << "Framebuffer Incomplete Missing Attachment." << LL_ENDL; - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - // frame buffer not OK: probably means unsupported depth buffer format - LL_ERRS() << "Framebuffer Incomplete Attachment." << LL_ENDL; - break; - case GL_FRAMEBUFFER_UNSUPPORTED: - /* choose different formats */ - LL_ERRS() << "Framebuffer unsupported." << LL_ENDL; - break; - default: - LL_ERRS() << "Unknown framebuffer status." << LL_ENDL; - break; - } -} - -void LLPipeline::bindScreenToTexture() -{ - + switch (face) + { + case 0: + gGL.rotatef(90.f, 0, 1, 0); + gGL.rotatef(180.f, 1, 0, 0); + break; + case 2: + gGL.rotatef(-90.f, 1, 0, 0); + break; + case 4: + gGL.rotatef(180.f, 0, 1, 0); + gGL.rotatef(180.f, 0, 0, 1); + break; + case 1: + gGL.rotatef(-90.f, 0, 1, 0); + gGL.rotatef(180.f, 1, 0, 0); + break; + case 3: + gGL.rotatef(90, 1, 0, 0); + break; + case 5: + gGL.rotatef(180, 0, 0, 1); + break; + } +} + +void validate_framebuffer_object() +{ + GLenum status; + status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + switch(status) + { + case GL_FRAMEBUFFER_COMPLETE: + //framebuffer OK, no error. + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + // frame buffer not OK: probably means unsupported depth buffer format + LL_ERRS() << "Framebuffer Incomplete Missing Attachment." << LL_ENDL; + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + // frame buffer not OK: probably means unsupported depth buffer format + LL_ERRS() << "Framebuffer Incomplete Attachment." << LL_ENDL; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + /* choose different formats */ + LL_ERRS() << "Framebuffer unsupported." << LL_ENDL; + break; + default: + LL_ERRS() << "Unknown framebuffer status." << LL_ENDL; + break; + } +} + +void LLPipeline::bindScreenToTexture() +{ + } static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom"); void LLPipeline::visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex) { - dst->bindTarget(); - gDeferredBufferVisualProgram.bind(); - gDeferredBufferVisualProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_BILINEAR, bufferIndex); + dst->bindTarget(); + gDeferredBufferVisualProgram.bind(); + gDeferredBufferVisualProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_BILINEAR, bufferIndex); - static LLStaticHashedString mipLevel("mipLevel"); - if (RenderBufferVisualization != 4) - gDeferredBufferVisualProgram.uniform1f(mipLevel, 0); - else - gDeferredBufferVisualProgram.uniform1f(mipLevel, 8); + static LLStaticHashedString mipLevel("mipLevel"); + if (RenderBufferVisualization != 4) + gDeferredBufferVisualProgram.uniform1f(mipLevel, 0); + else + gDeferredBufferVisualProgram.uniform1f(mipLevel, 8); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gDeferredBufferVisualProgram.unbind(); - dst->flush(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gDeferredBufferVisualProgram.unbind(); + dst->flush(); } void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) { - // luminance sample and mipmap generation - { - LL_PROFILE_GPU_ZONE("luminance sample"); + // luminance sample and mipmap generation + { + LL_PROFILE_GPU_ZONE("luminance sample"); - dst->bindTarget(); + dst->bindTarget(); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - gLuminanceProgram.bind(); + gLuminanceProgram.bind(); static LLCachedControl diffuse_luminance_scale(gSavedSettings, "RenderDiffuseLuminanceScale", 1.0f); - S32 channel = 0; - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); - if (channel > -1) - { - src->bindTexture(0, channel, LLTexUnit::TFO_POINT); - } + S32 channel = 0; + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_POINT); + } - channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - mGlow[1].bindTexture(0, channel); - } + channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + mGlow[1].bindTexture(0, channel); + } channel = gLuminanceProgram.enableTexture(LLShaderMgr::DEFERRED_NORMAL); if (channel > -1) @@ -6831,129 +6831,129 @@ void LLPipeline::generateLuminance(LLRenderTarget* src, LLRenderTarget* dst) static LLStaticHashedString diffuse_luminance_scale_s("diffuse_luminance_scale"); gLuminanceProgram.uniform1f(diffuse_luminance_scale_s, diffuse_luminance_scale); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - dst->flush(); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + dst->flush(); - // note -- unbind AFTER the glGenerateMipMap so time in generatemipmap can be profiled under "Luminance" - // also note -- keep an eye on the performance of glGenerateMipmap, might need to replace it with a mip generation shader - gLuminanceProgram.unbind(); - } + // note -- unbind AFTER the glGenerateMipMap so time in generatemipmap can be profiled under "Luminance" + // also note -- keep an eye on the performance of glGenerateMipmap, might need to replace it with a mip generation shader + gLuminanceProgram.unbind(); + } } void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history) { - // exposure sample - { - LL_PROFILE_GPU_ZONE("exposure sample"); - - if (use_history) - { - // copy last frame's exposure into mLastExposure - mLastExposure.bindTarget(); - gCopyProgram.bind(); - gGL.getTexUnit(0)->bind(dst); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - mLastExposure.flush(); - } - - dst->bindTarget(); - - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - LLGLSLShader* shader; - if (use_history) - { - shader = &gExposureProgram; - } - else - { - shader = &gExposureProgramNoFade; - } - - shader->bind(); - - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); - if (channel > -1) - { - src->bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); - } - - if (use_history) - { - channel = shader->enableTexture(LLShaderMgr::EXPOSURE_MAP); - if (channel > -1) - { - mLastExposure.bindTexture(0, channel); - } - } - - static LLStaticHashedString dt("dt"); - static LLStaticHashedString noiseVec("noiseVec"); - static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); - static LLCachedControl dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); - static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - - LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky(); - - F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust); - F32 exp_min = 1.f; - F32 exp_max = 1.f; - - if (probe_ambiance > 0.f) - { - F32 hdr_scale = sqrtf(LLEnvironment::instance().getCurrentSky()->getGamma()) * 2.f; - - if (hdr_scale > 1.f) - { - exp_min = 1.f / hdr_scale; - exp_max = hdr_scale; - } - } - shader->uniform1f(dt, gFrameIntervalSeconds); - shader->uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); - shader->uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - if (use_history) - { - gGL.getTexUnit(channel)->unbind(mLastExposure.getUsage()); - } - shader->unbind(); - dst->flush(); - } + // exposure sample + { + LL_PROFILE_GPU_ZONE("exposure sample"); + + if (use_history) + { + // copy last frame's exposure into mLastExposure + mLastExposure.bindTarget(); + gCopyProgram.bind(); + gGL.getTexUnit(0)->bind(dst); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + mLastExposure.flush(); + } + + dst->bindTarget(); + + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + LLGLSLShader* shader; + if (use_history) + { + shader = &gExposureProgram; + } + else + { + shader = &gExposureProgramNoFade; + } + + shader->bind(); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_EMISSIVE); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_TRILINEAR); + } + + if (use_history) + { + channel = shader->enableTexture(LLShaderMgr::EXPOSURE_MAP); + if (channel > -1) + { + mLastExposure.bindTexture(0, channel); + } + } + + static LLStaticHashedString dt("dt"); + static LLStaticHashedString noiseVec("noiseVec"); + static LLStaticHashedString dynamic_exposure_params("dynamic_exposure_params"); + static LLCachedControl dynamic_exposure_coefficient(gSavedSettings, "RenderDynamicExposureCoefficient", 0.175f); + static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); + + LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky(); + + F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust); + F32 exp_min = 1.f; + F32 exp_max = 1.f; + + if (probe_ambiance > 0.f) + { + F32 hdr_scale = sqrtf(LLEnvironment::instance().getCurrentSky()->getGamma()) * 2.f; + + if (hdr_scale > 1.f) + { + exp_min = 1.f / hdr_scale; + exp_max = hdr_scale; + } + } + shader->uniform1f(dt, gFrameIntervalSeconds); + shader->uniform2f(noiseVec, ll_frand() * 2.0 - 1.0, ll_frand() * 2.0 - 1.0); + shader->uniform3f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + if (use_history) + { + gGL.getTexUnit(channel)->unbind(mLastExposure.getUsage()); + } + shader->unbind(); + dst->flush(); + } } extern LLPointer gEXRImage; void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { - dst->bindTarget(); - // gamma correct lighting - { - LL_PROFILE_GPU_ZONE("gamma correct"); + dst->bindTarget(); + // gamma correct lighting + { + LL_PROFILE_GPU_ZONE("gamma correct"); static LLCachedControl buildNoPost(gSavedSettings, "RenderDisablePostProcessing", false); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); - // Apply gamma correction to the frame here. + // Apply gamma correction to the frame here. static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); - + LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); bool no_post = gSnapshotNoPost || (buildNoPost && gFloaterTools->isAvailable()); LLGLSLShader& shader = no_post ? gNoPostGammaCorrectProgram : // no post (no gamma, no exposure, no tonemapping) psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f ? gLegacyPostGammaCorrectProgram : gDeferredPostGammaCorrectProgram; - + shader.bind(); - S32 channel = 0; + S32 channel = 0; shader.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, false, LLTexUnit::TFO_POINT); @@ -6961,73 +6961,73 @@ void LLPipeline::gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst) { shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, src->getWidth(), src->getHeight()); - static LLCachedControl exposure(gSavedSettings, "RenderExposure", 1.f); + static LLCachedControl exposure(gSavedSettings, "RenderExposure", 1.f); - F32 e = llclamp(exposure(), 0.5f, 4.f); + F32 e = llclamp(exposure(), 0.5f, 4.f); - static LLStaticHashedString s_exposure("exposure"); + static LLStaticHashedString s_exposure("exposure"); static LLStaticHashedString aces_mix("aces_mix"); shader.uniform1f(s_exposure, e); shader.uniform1f(aces_mix, gEXRImage.notNull() ? 0.f : 0.3f); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gGL.getTexUnit(channel)->unbind(src->getUsage()); + gGL.getTexUnit(channel)->unbind(src->getUsage()); shader.unbind(); - } - dst->flush(); + } + dst->flush(); } -void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) +void LLPipeline::copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst) { - if (RenderScreenSpaceReflections && !gCubeSnapshot) - { - LL_PROFILE_GPU_ZONE("ssr copy"); - LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); + if (RenderScreenSpaceReflections && !gCubeSnapshot) + { + LL_PROFILE_GPU_ZONE("ssr copy"); + LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); - LLRenderTarget& depth_src = mRT->deferredScreen; + LLRenderTarget& depth_src = mRT->deferredScreen; - dst->bindTarget(); - dst->clear(); - gCopyDepthProgram.bind(); + dst->bindTarget(); + dst->clear(); + gCopyDepthProgram.bind(); - S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); - S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP); + S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - gGL.getTexUnit(diff_map)->bind(src); - gGL.getTexUnit(depth_map)->bind(&depth_src, true); + gGL.getTexUnit(diff_map)->bind(src); + gGL.getTexUnit(depth_map)->bind(&depth_src, true); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - dst->flush(); - } + dst->flush(); + } } -void LLPipeline::generateGlow(LLRenderTarget* src) +void LLPipeline::generateGlow(LLRenderTarget* src) { - if (sRenderGlow) - { - LL_PROFILE_GPU_ZONE("glow"); - mGlow[2].bindTarget(); - mGlow[2].clear(); - - gGlowExtractProgram.bind(); - F32 maxAlpha = RenderGlowMaxExtractAlpha; - F32 warmthAmount = RenderGlowWarmthAmount; - LLVector3 lumWeights = RenderGlowLumWeights; - LLVector3 warmthWeights = RenderGlowWarmthWeights; - - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, 9999); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], - lumWeights.mV[2]); - gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], - warmthWeights.mV[2]); - gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); + if (sRenderGlow) + { + LL_PROFILE_GPU_ZONE("glow"); + mGlow[2].bindTarget(); + mGlow[2].clear(); + + gGlowExtractProgram.bind(); + F32 maxAlpha = RenderGlowMaxExtractAlpha; + F32 warmthAmount = RenderGlowWarmthAmount; + LLVector3 lumWeights = RenderGlowLumWeights; + LLVector3 warmthWeights = RenderGlowWarmthWeights; + + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, 9999); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], + lumWeights.mV[2]); + gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], + warmthWeights.mV[2]); + gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount); if (RenderGlowNoise) { @@ -7042,406 +7042,406 @@ void LLPipeline::generateGlow(LLRenderTarget* src) mGlow[2].getHeight()); } - { - LLGLEnable blend_on(GL_BLEND); + { + LLGLEnable blend_on(GL_BLEND); + + gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + + gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, src); + + gGL.color4f(1, 1, 1, 1); + gPipeline.enableLightsFullbright(); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + mGlow[2].flush(); + } + + gGlowExtractProgram.unbind(); + + // power of two between 1 and 1024 + U32 glowResPow = RenderGlowResolutionPow; + const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow)); + + S32 kernel = RenderGlowIterations * 2; + F32 delta = RenderGlowWidth / glow_res; + // Use half the glow width if we have the res set to less than 9 so that it looks + // almost the same in either case. + if (glowResPow < 9) + { + delta *= 0.5f; + } + F32 strength = RenderGlowStrength; + + gGlowProgram.bind(); + gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength); + + for (S32 i = 0; i < kernel; i++) + { + mGlow[i % 2].bindTarget(); + mGlow[i % 2].clear(); + + if (i == 0) + { + gGlowProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mGlow[2]); + } + else + { + gGlowProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mGlow[(i - 1) % 2]); + } + + if (i % 2 == 0) + { + gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0); + } + else + { + gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta); + } + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + mGlow[i % 2].flush(); + } + + gGlowProgram.unbind(); + + } + else // !sRenderGlow, skip the glow ping-pong and just clear the result target + { + mGlow[1].bindTarget(); + mGlow[1].clear(); + mGlow[1].flush(); + } +} + +void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) +{ + { + llassert(!gCubeSnapshot); + bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete(); + LLGLSLShader* shader = &gGlowCombineProgram; + + S32 width = dst->getWidth(); + S32 height = dst->getHeight(); + + // Present everything. + if (multisample) + { + LL_PROFILE_GPU_ZONE("aa"); + // bake out texture2D with RGBL for FXAA shader + mRT->fxaaBuffer.bindTarget(); + + shader = &gGlowCombineFXAAProgram; + shader->bind(); + + S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + if (channel > -1) + { + src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); + } + + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); + shader->unbind(); - gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); + mRT->fxaaBuffer.flush(); - gGlowExtractProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, src); + dst->bindTarget(); + shader = &gFXAAProgram; + shader->bind(); - gGL.color4f(1, 1, 1, 1); - gPipeline.enableLightsFullbright(); + channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage()); + if (channel > -1) + { + mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); + } - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - mGlow[2].flush(); - } + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - gGlowExtractProgram.unbind(); + F32 scale_x = (F32)width / mRT->fxaaBuffer.getWidth(); + F32 scale_y = (F32)height / mRT->fxaaBuffer.getHeight(); + shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); + shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y, + 0.5f / width * scale_x, 0.5f / height * scale_y); + shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y, + 2.f / width * scale_x, 2.f / height * scale_y); - // power of two between 1 and 1024 - U32 glowResPow = RenderGlowResolutionPow; - const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow)); + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); + gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true); - S32 kernel = RenderGlowIterations * 2; - F32 delta = RenderGlowWidth / glow_res; - // Use half the glow width if we have the res set to less than 9 so that it looks - // almost the same in either case. - if (glowResPow < 9) - { - delta *= 0.5f; - } - F32 strength = RenderGlowStrength; + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } - gGlowProgram.bind(); - gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength); - - for (S32 i = 0; i < kernel; i++) - { - mGlow[i % 2].bindTarget(); - mGlow[i % 2].clear(); - - if (i == 0) - { - gGlowProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mGlow[2]); - } - else - { - gGlowProgram.bindTexture(LLShaderMgr::DIFFUSE_MAP, &mGlow[(i - 1) % 2]); - } - - if (i % 2 == 0) - { - gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0); - } - else - { - gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta); - } - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - mGlow[i % 2].flush(); - } - - gGlowProgram.unbind(); - - } - else // !sRenderGlow, skip the glow ping-pong and just clear the result target - { - mGlow[1].bindTarget(); - mGlow[1].clear(); - mGlow[1].flush(); - } -} - -void LLPipeline::applyFXAA(LLRenderTarget* src, LLRenderTarget* dst) -{ - { - llassert(!gCubeSnapshot); - bool multisample = RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete(); - LLGLSLShader* shader = &gGlowCombineProgram; - - S32 width = dst->getWidth(); - S32 height = dst->getHeight(); - - // Present everything. - if (multisample) - { - LL_PROFILE_GPU_ZONE("aa"); - // bake out texture2D with RGBL for FXAA shader - mRT->fxaaBuffer.bindTarget(); - - shader = &gGlowCombineFXAAProgram; - shader->bind(); - - S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); - if (channel > -1) - { - src->bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); - } - - { - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, src->getUsage()); - shader->unbind(); - - mRT->fxaaBuffer.flush(); - - dst->bindTarget(); - shader = &gFXAAProgram; - shader->bind(); - - channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mRT->fxaaBuffer.getUsage()); - if (channel > -1) - { - mRT->fxaaBuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR); - } - - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - - F32 scale_x = (F32)width / mRT->fxaaBuffer.getWidth(); - F32 scale_y = (F32)height / mRT->fxaaBuffer.getHeight(); - shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y); - shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y, - 0.5f / width * scale_x, 0.5f / height * scale_y); - shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y, - 2.f / width * scale_x, 2.f / height * scale_y); - - { - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); - S32 depth_channel = shader->getTextureChannel(LLShaderMgr::DEFERRED_DEPTH); - gGL.getTexUnit(depth_channel)->bind(&mRT->deferredScreen, true); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - shader->unbind(); - dst->flush(); - } - else { - copyRenderTarget(src, dst); - } - } + shader->unbind(); + dst->flush(); + } + else { + copyRenderTarget(src, dst); + } + } } void LLPipeline::copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst) { - LL_PROFILE_GPU_ZONE("copyRenderTarget"); - dst->bindTarget(); + LL_PROFILE_GPU_ZONE("copyRenderTarget"); + dst->bindTarget(); - gDeferredPostNoDoFProgram.bind(); + gDeferredPostNoDoFProgram.bind(); - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src); - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src); + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - { - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } + { + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } - gDeferredPostNoDoFProgram.unbind(); + gDeferredPostNoDoFProgram.unbind(); - dst->flush(); + dst->flush(); } void LLPipeline::combineGlow(LLRenderTarget* src, LLRenderTarget* dst) { - // Go ahead and do our glow combine here in our destination. We blit this later into the front buffer. + // Go ahead and do our glow combine here in our destination. We blit this later into the front buffer. - dst->bindTarget(); + dst->bindTarget(); - { + { - gGlowCombineProgram.bind(); + gGlowCombineProgram.bind(); - gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src); - gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]); + gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src); + gGlowCombineProgram.bindTexture(LLShaderMgr::DEFERRED_EMISSIVE, &mGlow[1]); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } - dst->flush(); + dst->flush(); } void LLPipeline::renderDoF(LLRenderTarget* src, LLRenderTarget* dst) { - { - bool dof_enabled = - (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && - RenderDepthOfField && - !gCubeSnapshot; - - gViewerWindow->setup3DViewport(); - - if (dof_enabled) - { - LL_PROFILE_GPU_ZONE("dof"); - LLGLDisable blend(GL_BLEND); - - // depth of field focal plane calculations - static F32 current_distance = 16.f; - static F32 start_distance = 16.f; - static F32 transition_time = 1.f; - - LLVector3 focus_point; - - LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); - if (obj && obj->mDrawable && obj->isSelected()) - { // focus on selected media object - S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); - if (obj && obj->mDrawable) - { - LLFace* face = obj->mDrawable->getFace(face_idx); - if (face) - { - focus_point = face->getPositionAgent(); - } - } - } - - if (focus_point.isExactlyZero()) - { - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { // focus on point under cursor - focus_point.set(gDebugRaycastIntersection.getF32ptr()); - } - else if (gAgentCamera.cameraMouselook()) - { // focus on point under mouselook crosshairs - LLVector4a result; - result.clear(); - - gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, nullptr, nullptr, nullptr, &result); - - focus_point.set(result.getF32ptr()); - } - else - { - // focus on alt-zoom target - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); - } - } - } - - LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); - F32 target_distance = 16.f; - if (!focus_point.isExactlyZero()) - { - target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye); - } - - if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f) - { // large shift happened, interpolate smoothly to new target distance - transition_time = 0.f; - start_distance = current_distance; - } - else if (transition_time < 1.f) - { // currently in a transition, continue interpolating - transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value(); - transition_time = llmin(transition_time, 1.f); - - F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f; - current_distance = start_distance + (target_distance - start_distance) * t; - } - else - { // small or no change, just snap to target distance - current_distance = target_distance; - } - - // convert to mm - F32 subject_distance = current_distance * 1000.f; - F32 fnumber = CameraFNumber; - F32 default_focal_length = CameraFocalLength; - - F32 fov = LLViewerCamera::getInstance()->getView(); - - const F32 default_fov = CameraFieldOfView * F_PI / 180.f; - - // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight(); - - F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f); - - F32 focal_length = dv / (2 * tanf(fov / 2.f)); - - // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); - - // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) - // where N = fnumber - // s2 = dot distance - // s1 = subject distance - // f = focal length - // - - F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length)); - blur_constant /= 1000.f; // convert to meters for shader - F32 magnification = focal_length / (subject_distance - focal_length); - - { // build diffuse+bloom+CoF - mRT->deferredLight.bindTarget(); - - gDeferredCoFProgram.bind(); - - gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); - gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - - gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); - gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - gDeferredCoFProgram.unbind(); - mRT->deferredLight.flush(); - } - - U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale); - U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale); - - { // perform DoF sampling at half-res (preserve alpha channel) - src->bindTarget(); - glViewport(0, 0, dof_width, dof_height); - - gGL.setColorMask(true, false); - - gDeferredPostProgram.bind(); - gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mRT->deferredLight, LLTexUnit::TFO_POINT); - - gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); - gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - gDeferredPostProgram.unbind(); - - src->flush(); - gGL.setColorMask(true, true); - } - - { // combine result based on alpha - - dst->bindTarget(); - if (RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete()) + { + bool dof_enabled = + (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) && + RenderDepthOfField && + !gCubeSnapshot; + + gViewerWindow->setup3DViewport(); + + if (dof_enabled) + { + LL_PROFILE_GPU_ZONE("dof"); + LLGLDisable blend(GL_BLEND); + + // depth of field focal plane calculations + static F32 current_distance = 16.f; + static F32 start_distance = 16.f; + static F32 transition_time = 1.f; + + LLVector3 focus_point; + + LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { // focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + } + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { // focus on point under cursor + focus_point.set(gDebugRaycastIntersection.getF32ptr()); + } + else if (gAgentCamera.cameraMouselook()) + { // focus on point under mouselook crosshairs + LLVector4a result; + result.clear(); + + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, TRUE, TRUE, nullptr, nullptr, nullptr, &result); + + focus_point.set(result.getF32ptr()); + } + else + { + // focus on alt-zoom target + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal()); + } + } + } + + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + F32 target_distance = 16.f; + if (!focus_point.isExactlyZero()) + { + target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye); + } + + if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f) + { // large shift happened, interpolate smoothly to new target distance + transition_time = 0.f; + start_distance = current_distance; + } + else if (transition_time < 1.f) + { // currently in a transition, continue interpolating + transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value(); + transition_time = llmin(transition_time, 1.f); + + F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f; + current_distance = start_distance + (target_distance - start_distance) * t; + } + else + { // small or no change, just snap to target distance + current_distance = target_distance; + } + + // convert to mm + F32 subject_distance = current_distance * 1000.f; + F32 fnumber = CameraFNumber; + F32 default_focal_length = CameraFocalLength; + + F32 fov = LLViewerCamera::getInstance()->getView(); + + const F32 default_fov = CameraFieldOfView * F_PI / 180.f; + + // F32 aspect_ratio = (F32) mRT->screen.getWidth()/(F32)mRT->screen.getHeight(); + + F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f); + + F32 focal_length = dv / (2 * tanf(fov / 2.f)); + + // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); + + // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) + // where N = fnumber + // s2 = dot distance + // s1 = subject distance + // f = focal length + // + + F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length)); + blur_constant /= 1000.f; // convert to meters for shader + F32 magnification = focal_length / (subject_distance - focal_length); + + { // build diffuse+bloom+CoF + mRT->deferredLight.bindTarget(); + + gDeferredCoFProgram.bind(); + + gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); + gDeferredCoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + + gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); + gDeferredCoFProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle)); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredCoFProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + gDeferredCoFProgram.unbind(); + mRT->deferredLight.flush(); + } + + U32 dof_width = (U32)(mRT->screen.getWidth() * CameraDoFResScale); + U32 dof_height = (U32)(mRT->screen.getHeight() * CameraDoFResScale); + + { // perform DoF sampling at half-res (preserve alpha channel) + src->bindTarget(); + glViewport(0, 0, dof_width, dof_height); + + gGL.setColorMask(true, false); + + gDeferredPostProgram.bind(); + gDeferredPostProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, &mRT->deferredLight, LLTexUnit::TFO_POINT); + + gDeferredPostProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredPostProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gDeferredPostProgram.unbind(); + + src->flush(); + gGL.setColorMask(true, true); + } + + { // combine result based on alpha + + dst->bindTarget(); + if (RenderFSAASamples > 1 && mRT->fxaaBuffer.isComplete()) { - glViewport(0, 0, dst->getWidth(), dst->getHeight()); - } - else + glViewport(0, 0, dst->getWidth(), dst->getHeight()); + } + else { - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - } - - gDeferredDoFCombineProgram.bind(); - gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); - gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mRT->deferredLight, LLTexUnit::TFO_POINT); - - gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); - gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); - gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); - gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth()); - gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)src->getHeight()); - - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - - gDeferredDoFCombineProgram.unbind(); - - dst->flush(); - } - } - else - { - copyRenderTarget(src, dst); - } - } + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); + } + + gDeferredDoFCombineProgram.bind(); + gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, src, LLTexUnit::TFO_POINT); + gDeferredDoFCombineProgram.bindTexture(LLShaderMgr::DEFERRED_LIGHT, &mRT->deferredLight, LLTexUnit::TFO_POINT); + + gDeferredDoFCombineProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, dst->getWidth(), dst->getHeight()); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_WIDTH, (dof_width - 1) / (F32)src->getWidth()); + gDeferredDoFCombineProgram.uniform1f(LLShaderMgr::DOF_HEIGHT, (dof_height - 1) / (F32)src->getHeight()); + + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + + gDeferredDoFCombineProgram.unbind(); + + dst->flush(); + } + } + else + { + copyRenderTarget(src, dst); + } + } } void LLPipeline::renderFinalize() @@ -7465,7 +7465,7 @@ void LLPipeline::renderFinalize() gGL.setColorMask(true, true); glClearColor(0, 0, 0, 0); - + copyScreenSpaceReflections(&mRT->screen, &mSceneMap); generateLuminance(&mRT->screen, &mLuminanceMap); @@ -7480,60 +7480,60 @@ void LLPipeline::renderFinalize() combineGlow(&mPostMap, &mRT->screen); - gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; - gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; - gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); - gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - - renderDoF(&mRT->screen, &mPostMap); - - applyFXAA(&mPostMap, &mRT->screen); - LLRenderTarget* finalBuffer = &mRT->screen; - if (RenderBufferVisualization > -1) - { - finalBuffer = &mPostMap; - switch (RenderBufferVisualization) - { - case 0: - case 1: - case 2: - case 3: - visualizeBuffers(&mRT->deferredScreen, finalBuffer, RenderBufferVisualization); - break; - case 4: - visualizeBuffers(&mLuminanceMap, finalBuffer, 0); - default: - break; - } - } - - // Present the screen target. - - gDeferredPostNoDoFProgram.bind(); - - // Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems. - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer); - gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); - - { - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - - gDeferredPostNoDoFProgram.unbind(); + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + renderDoF(&mRT->screen, &mPostMap); - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) + applyFXAA(&mPostMap, &mRT->screen); + LLRenderTarget* finalBuffer = &mRT->screen; + if (RenderBufferVisualization > -1) { - renderPhysicsDisplay(); + finalBuffer = &mPostMap; + switch (RenderBufferVisualization) + { + case 0: + case 1: + case 2: + case 3: + visualizeBuffers(&mRT->deferredScreen, finalBuffer, RenderBufferVisualization); + break; + case 4: + visualizeBuffers(&mLuminanceMap, finalBuffer, 0); + default: + break; + } } - /*if (LLRenderTarget::sUseFBO && !gCubeSnapshot) - { // copy depth buffer from mRT->screen to framebuffer - LLRenderTarget::copyContentsToFramebuffer(mRT->screen, 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), 0, 0, + // Present the screen target. + + gDeferredPostNoDoFProgram.bind(); + + // Whatever is last in the above post processing chain should _always_ be rendered directly here. If not, expect problems. + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DIFFUSE, finalBuffer); + gDeferredPostNoDoFProgram.bindTexture(LLShaderMgr::DEFERRED_DEPTH, &mRT->deferredScreen, true); + + { + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_ALWAYS); + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + + gDeferredPostNoDoFProgram.unbind(); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES)) + { + renderPhysicsDisplay(); + } + + /*if (LLRenderTarget::sUseFBO && !gCubeSnapshot) + { // copy depth buffer from mRT->screen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mRT->screen, 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), 0, 0, mRT->screen.getWidth(), mRT->screen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); }*/ @@ -7612,28 +7612,28 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ LLRenderTarget* deferred_target = &mRT->deferredScreen; LLRenderTarget* deferred_light_target = &mRT->deferredLight; - shader.bind(); - S32 channel = 0; + shader.bind(); + S32 channel = 0; channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage()); - if (channel > -1) - { + if (channel > -1) + { deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT); // frag_data[0] gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - } + } channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage()); - if (channel > -1) - { + if (channel > -1) + { deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT); // frag_data[1] gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - } + } channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage()); - if (channel > -1) - { + if (channel > -1) + { deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT); // frag_data[2] gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - } + } channel = shader.enableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage()); if (channel > -1) @@ -7664,32 +7664,32 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1) { - shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0], - (F32) gGLViewport[1], - (F32) gGLViewport[2], - (F32) gGLViewport[3]); - } + shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0], + (F32) gGLViewport[1], + (F32) gGLViewport[2], + (F32) gGLViewport[3]); + } if (sReflectionRender && !shader.getUniformLocation(LLShaderMgr::MODELVIEW_MATRIX)) { - shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_MATRIX, 1, FALSE, mReflectionModelView.m); + shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_MATRIX, 1, FALSE, mReflectionModelView.m); } - channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE); - if (channel > -1) - { + channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE); + if (channel > -1) + { gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } bindLightFunc(shader); - stop_glerror(); + stop_glerror(); light_target = light_target ? light_target : deferred_light_target; channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, light_target->getUsage()); - if (channel > -1) - { + if (channel > -1) + { if (light_target->isComplete()) { light_target->bindTexture(0, channel, LLTexUnit::TFO_POINT); @@ -7698,28 +7698,28 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ { gGL.getTexUnit(channel)->bindFast(LLViewerFetchedTexture::sWhiteImagep); } - } + } - stop_glerror(); + stop_glerror(); bindShadowMaps(shader); - stop_glerror(); + stop_glerror(); - F32 mat[16*6]; - for (U32 i = 0; i < 16; i++) - { - mat[i] = mSunShadowMatrix[0].m[i]; - mat[i+16] = mSunShadowMatrix[1].m[i]; - mat[i+32] = mSunShadowMatrix[2].m[i]; - mat[i+48] = mSunShadowMatrix[3].m[i]; - mat[i+64] = mSunShadowMatrix[4].m[i]; - mat[i+80] = mSunShadowMatrix[5].m[i]; - } + F32 mat[16*6]; + for (U32 i = 0; i < 16; i++) + { + mat[i] = mSunShadowMatrix[0].m[i]; + mat[i+16] = mSunShadowMatrix[1].m[i]; + mat[i+32] = mSunShadowMatrix[2].m[i]; + mat[i+48] = mSunShadowMatrix[3].m[i]; + mat[i+64] = mSunShadowMatrix[4].m[i]; + mat[i+80] = mSunShadowMatrix[5].m[i]; + } - shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat); + shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_SHADOW_MATRIX, 6, FALSE, mat); - stop_glerror(); + stop_glerror(); if (!LLPipeline::sReflectionProbesEnabled) { @@ -7781,55 +7781,55 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ { shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV); } - shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise); - shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize); - - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale); - - F32 ssao_factor = RenderSSAOFactor; - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); - shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor); - - LLVector3 ssao_effect = RenderSSAOEffect; - F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; - F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; - // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by - // value factor, and scales remainder by saturation factor - F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, - matrix_nondiag, matrix_diag, matrix_nondiag, - matrix_nondiag, matrix_nondiag, matrix_diag}; - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); - - //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); - F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; + shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash); + shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise); + shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize); + + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale); + + F32 ssao_factor = RenderSSAOFactor; + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor); + shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0/ssao_factor); + + LLVector3 ssao_effect = RenderSSAOEffect; + F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0; + F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0; + // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by + // value factor, and scales remainder by saturation factor + F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag, + matrix_nondiag, matrix_diag, matrix_nondiag, + matrix_nondiag, matrix_nondiag, matrix_diag}; + shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); + + //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; F32 shadow_bias = RenderShadowBias + shadow_bias_error; shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_target->getWidth(), deferred_target->getHeight()); - shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); + shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); + shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, shadow_bias); - shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset); - shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias); + shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset); + shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias); - shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV); + 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, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight()); - shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff); - shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff); - + shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].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); + shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLDeltaModelView); shader.uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLInverseDeltaModelView); shader.uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0); - if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { + if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) + { glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } + shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); + } // auto adjust legacy sun color if needed static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", true); @@ -7850,18 +7850,18 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_ LLColor3 pow3f(LLColor3 v, F32 f) { - v.mV[0] = powf(v.mV[0], f); - v.mV[1] = powf(v.mV[1], f); - v.mV[2] = powf(v.mV[2], f); - return v; + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; } LLVector4 pow4fsrgb(LLVector4 v, F32 f) { - v.mV[0] = powf(v.mV[0], f); - v.mV[1] = powf(v.mV[1], f); - v.mV[2] = powf(v.mV[2], f); - return v; + v.mV[0] = powf(v.mV[0], f); + v.mV[1] = powf(v.mV[1], f); + v.mV[2] = powf(v.mV[2], f); + return v; } void LLPipeline::renderDeferredLighting() @@ -7888,7 +7888,7 @@ void LLPipeline::renderDeferredLighting() { LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("deferred"); LLViewerCamera *camera = LLViewerCamera::getInstance(); - + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); @@ -8040,14 +8040,14 @@ void LLPipeline::renderDeferredLighting() static LLCachedControl ssao_max(gSavedSettings, "RenderSSAOIrradianceMax", 0.25f); static LLStaticHashedString ssao_scale_str("ssao_irradiance_scale"); static LLStaticHashedString ssao_max_str("ssao_irradiance_max"); - + soften_shader.uniform1f(ssao_scale_str, ssao_scale); soften_shader.uniform1f(ssao_max_str, ssao_max); LLEnvironment &environment = LLEnvironment::instance(); soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV); - + soften_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); { @@ -8341,7 +8341,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_CONTROL_AV, LLPipeline::RENDER_TYPE_ALPHA_MASK, LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_WATER, END_RENDER_TYPES); @@ -8422,7 +8422,7 @@ void LLPipeline::doAtmospherics() // full screen blit mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - + unbindDeferredShader(haze_shader); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -8461,1489 +8461,1489 @@ void LLPipeline::doWaterHaze() gPipeline.mScreenTriangleVB->setBuffer(); gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - dst.flush(); - mRT->screen.bindTarget(); - } + dst.flush(); + mRT->screen.bindTarget(); + } + + LLGLEnable blend(GL_BLEND); + gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA, LLRender::BF_ZERO, LLRender::BF_SOURCE_ALPHA); + + gGL.setColorMask(true, true); + + // apply haze + LLGLSLShader& haze_shader = gHazeWaterProgram; + + LL_PROFILE_GPU_ZONE("haze"); + bindDeferredShader(haze_shader, nullptr, &mWaterDis); + + haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); + + static LLStaticHashedString above_water_str("above_water"); + haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1); + + if (LLPipeline::sUnderWaterRender) + { + LLGLDepthTest depth(GL_FALSE); + + // full screen blit + mScreenTriangleVB->setBuffer(); + mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); + } + else + { + //render water patches like LLDrawPoolWater does + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable cull(GL_CULL_FACE); + + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + if (mWaterPool) + { + mWaterPool->pushFaceGeometry(); + } + } + + unbindDeferredShader(haze_shader); + + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } +} + +void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) +{ + //construct frustum + LLVOVolume* volume = drawablep->getVOVolume(); + LLVector3 params = volume->getSpotLightParams(); + + F32 fov = params.mV[0]; + F32 focus = params.mV[1]; + + LLVector3 pos = drawablep->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); + LLVector3 scale = volume->getScale(); + + //get near clip plane + LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); + at_axis *= quat; + + LLVector3 np = pos+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); + + LLVector3 origin = np - at_axis*dist; + + //matrix from volume space to agent space + LLMatrix4 light_mat(quat, LLVector4(origin,1.f)); + + glh::matrix4f light_to_agent((F32*) light_mat.mMatrix); + glh::matrix4f light_to_screen = get_current_modelview() * light_to_agent; + + glh::matrix4f screen_to_light = light_to_screen.inverse(); + + F32 s = volume->getLightRadius()*1.5f; + F32 near_clip = dist; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = s+dist-scale.mV[VZ]; + + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width/height; + + 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); + + glh::vec3f p1(0, 0, -(near_clip+0.01f)); + glh::vec3f p2(0, 0, -(near_clip+1.f)); + + glh::vec3f screen_origin(0, 0, 0); + + light_to_screen.mult_matrix_vec(p1); + light_to_screen.mult_matrix_vec(p2); + light_to_screen.mult_matrix_vec(screen_origin); + + glh::vec3f n = p2-p1; + n.normalize(); + + F32 proj_range = far_clip - near_clip; + glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip); + screen_to_light = trans * light_proj * screen_to_light; + shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m); + shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip); + shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v); + shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v); + shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v); + shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range); + shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]); + S32 s_idx = -1; + + for (U32 i = 0; i < 2; i++) + { + if (mShadowSpotLight[i] == drawablep) + { + s_idx = i; + } + } + + shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx); + + if (s_idx >= 0) + { + shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]); + } + else + { + shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f); + } + + // make sure we're not already targeting the same spot light with both shadow maps + llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull()); + + if (!gCubeSnapshot) + { + LLDrawable* potential = drawablep; + //determine if this light is higher priority than one of the existing spot shadows + F32 m_pri = volume->getSpotLightPriority(); + + for (U32 i = 0; i < 2; i++) + { + F32 pri = 0.f; + + if (mTargetShadowSpotLight[i].notNull()) + { + pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority(); + } + + if (m_pri > pri) + { + LLDrawable* temp = mTargetShadowSpotLight[i]; + mTargetShadowSpotLight[i] = potential; + potential = temp; + m_pri = pri; + } + } + } + + // make sure we didn't end up targeting the same spot light with both shadow maps + llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull()); + + LLViewerTexture* img = volume->getLightTexture(); + + if (img == NULL) + { + img = LLViewerFetchedTexture::sWhiteImagep; + } + + S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + + if (channel > -1) + { + if (img) + { + gGL.getTexUnit(channel)->bind(img); + + F32 lod_range = logf(img->getWidth())/logf(2.f); + + shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus); + shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range); + shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + } + } + +} + +void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) +{ + LLRenderTarget* deferred_target = &mRT->deferredScreen; + LLRenderTarget* deferred_light_target = &mRT->deferredLight; + + stop_glerror(); + shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_BRDF_LUT); + //shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage()); + shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage()); + shader.disableTexture(LLShaderMgr::DIFFUSE_MAP); + shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM); + + for (U32 i = 0; i < 4; i++) + { + if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + } + + for (U32 i = 4; i < 6; i++) + { + if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + } + + shader.disableTexture(LLShaderMgr::DEFERRED_NOISE); + shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC); + + if (!LLPipeline::sReflectionProbesEnabled) + { + S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + if (channel > -1) + { + LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; + if (cube_map) + { + cube_map->disable(); + } + } + } + + unbindReflectionProbes(shader); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->activate(); + shader.unbind(); +} + +void LLPipeline::setEnvMat(LLGLSLShader& shader) +{ + F32* m = gGLModelView; + + F32 mat[] = { m[0], m[1], m[2], + m[4], m[5], m[6], + m[8], m[9], m[10] }; + + shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); +} + +void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) +{ + if (!sReflectionProbesEnabled) + { + return; + } + + S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + bool bound = false; + if (channel > -1 && mReflectionMapManager.mTexture.notNull()) + { + mReflectionMapManager.mTexture->bind(channel); + bound = true; + } + + channel = shader.enableTexture(LLShaderMgr::IRRADIANCE_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mReflectionMapManager.mIrradianceMaps.notNull()) + { + mReflectionMapManager.mIrradianceMaps->bind(channel); + bound = true; + } + + if (RenderMirrors) + { + channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); + if (channel > -1 && mHeroProbeManager.mTexture.notNull()) + { + mHeroProbeManager.mTexture->bind(channel); + bound = true; + } + } + + + if (bound) + { + mReflectionMapManager.setUniforms(); + + setEnvMat(shader); + } + + // reflection probe shaders generally sample the scene map as well for SSR + channel = shader.enableTexture(LLShaderMgr::SCENE_MAP); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mSceneMap); + } + + + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ITR_COUNT, RenderScreenSpaceReflectionIterations); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_DIST_BIAS, RenderScreenSpaceReflectionDistanceBias); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_RAY_STEP, RenderScreenSpaceReflectionRayStep); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_GLOSSY_SAMPLES, RenderScreenSpaceReflectionGlossySamples); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_REJECT_BIAS, RenderScreenSpaceReflectionDepthRejectBias); + mPoissonOffset++; + + if (mPoissonOffset > 128 - RenderScreenSpaceReflectionGlossySamples) + mPoissonOffset = 0; + + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_NOISE_SINE, mPoissonOffset); + shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ADAPTIVE_STEP_MULT, RenderScreenSpaceReflectionAdaptiveStepMultiplier); + + channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH); + if (channel > -1) + { + gGL.getTexUnit(channel)->bind(&mSceneMap, true); + } + + +} + +void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader) +{ + S32 channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP); + if (channel > -1 && mReflectionMapManager.mTexture.notNull()) + { + mReflectionMapManager.mTexture->unbind(); + if (channel == 0) + { + gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE); + } + } +} + + +inline float sgn(float a) +{ + if (a > 0.0F) return (1.0F); + if (a < 0.0F) return (-1.0F); + return (0.0F); +} + +glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) +{ + glh::matrix4f ret; + + LLVector3 dirN; + LLVector3 upN; + LLVector3 lftN; + + lftN = dir % up; + lftN.normVec(); + + upN = lftN % dir; + upN.normVec(); + + dirN = dir; + dirN.normVec(); + + ret.m[ 0] = lftN[0]; + ret.m[ 1] = upN[0]; + ret.m[ 2] = -dirN[0]; + ret.m[ 3] = 0.f; + + ret.m[ 4] = lftN[1]; + ret.m[ 5] = upN[1]; + ret.m[ 6] = -dirN[1]; + ret.m[ 7] = 0.f; + + ret.m[ 8] = lftN[2]; + ret.m[ 9] = upN[2]; + ret.m[10] = -dirN[2]; + ret.m[11] = 0.f; + + ret.m[12] = -(lftN*pos); + ret.m[13] = -(upN*pos); + ret.m[14] = dirN*pos; + ret.m[15] = 1.f; + + return ret; +} + +glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) +{ + glh::matrix4f ret; + ret.m[ 0] = 2/(max[0]-min[0]); + ret.m[ 4] = 0; + ret.m[ 8] = 0; + ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); + + ret.m[ 1] = 0; + ret.m[ 5] = 2/(max[1]-min[1]); + ret.m[ 9] = 0; + ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); + + ret.m[ 2] = 0; + ret.m[ 6] = 0; + ret.m[10] = 2/(max[2]-min[2]); + ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); + + ret.m[ 3] = 0; + ret.m[ 7] = 0; + ret.m[11] = 0; + ret.m[15] = 1; + + return ret; +} + +static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA("Alpha Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_SIMPLE("Simple Shadow"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_GEOM("Shadow Geom"); + +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_MASKED("Alpha Masked"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_BLEND("Alpha Blend"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); +static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked"); + +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool depth_clamp) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); + LL_PROFILE_GPU_ZONE("renderShadow"); + + LLPipeline::sShadowRender = true; + + // disable occlusion culling during shadow render + U32 saved_occlusion = sUseOcclusion; + sUseOcclusion = 0; + + // List of render pass types that use the prim volume as the shadow, + // ignoring textures. + static const U32 types[] = { + LLRenderPass::PASS_SIMPLE, + LLRenderPass::PASS_FULLBRIGHT, + LLRenderPass::PASS_SHINY, + LLRenderPass::PASS_BUMP, + LLRenderPass::PASS_FULLBRIGHT_SHINY, + LLRenderPass::PASS_MATERIAL, + LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + LLRenderPass::PASS_SPECMAP, + LLRenderPass::PASS_SPECMAP_EMISSIVE, + LLRenderPass::PASS_NORMMAP, + LLRenderPass::PASS_NORMMAP_EMISSIVE, + LLRenderPass::PASS_NORMSPEC, + LLRenderPass::PASS_NORMSPEC_EMISSIVE + }; + + LLGLEnable cull(GL_CULL_FACE); + + //enable depth clamping if available + LLGLEnable clamp_depth(depth_clamp ? GL_DEPTH_CLAMP : 0); + + LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_LESS); + + updateCull(shadow_cam, result); + + stateSort(shadow_cam, result); + + //generate shadow map + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadMatrix(proj.m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadMatrix(view.m); + + stop_glerror(); + gGLLastMatrix = NULL; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + stop_glerror(); + + struct CompareVertexBuffer + { + bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs) + { + return lhs->mVertexBuffer > rhs->mVertexBuffer; + } + }; + + + LLVertexBuffer::unbind(); + for (int j = 0; j < 2; ++j) // 0 -- static, 1 -- rigged + { + bool rigged = j == 1; + gDeferredShadowProgram.bind(rigged); + + gGL.diffuseColor4f(1, 1, 1, 1); + + S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); + + // if not using VSM, disable color writes + if (shadow_detail <= 2) + { + gGL.setColorMask(false, false); + } + + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow simple"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); + LL_PROFILE_GPU_ZONE("shadow simple"); + gGL.getTexUnit(0)->disable(); + + for (U32 type : types) + { + renderObjects(type, false, false, rigged); + } + + renderGLTFObjects(LLRenderPass::PASS_GLTF_PBR, false, rigged); + + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + } + + if (LLPipeline::sUseOcclusion > 1) + { // do occlusion culling against non-masked only to take advantage of hierarchical Z + doOcclusion(shadow_cam); + } + + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom"); + renderGeomShadow(shadow_cam); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha"); + LL_PROFILE_GPU_ZONE("shadow alpha"); + const S32 sun_up = LLEnvironment::instance().getIsSunUp() ? 1 : 0; + U32 target_width = LLRenderTarget::sCurResX; + + for (int i = 0; i < 2; ++i) + { + bool rigged = i == 1; + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha masked"); + LL_PROFILE_GPU_ZONE("shadow alpha masked"); + gDeferredShadowAlphaMaskProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, true, true, rigged); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha blend"); + LL_PROFILE_GPU_ZONE("shadow alpha blend"); + renderAlphaObjects(rigged); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow fullbright alpha masked"); + LL_PROFILE_GPU_ZONE("shadow alpha masked"); + gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true, rigged); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha grass"); + LL_PROFILE_GPU_ZONE("shadow alpha grass"); + gDeferredTreeShadowProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); + + if (i == 0) + { + renderObjects(LLRenderPass::PASS_GRASS, true); + } + + { + LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha material"); + LL_PROFILE_GPU_ZONE("shadow alpha material"); + renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, true, false, rigged); + renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, true, false, rigged); + } + } + } + + for (int i = 0; i < 2; ++i) + { + bool rigged = i == 1; + gDeferredShadowGLTFAlphaMaskProgram.bind(rigged); + LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); + LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); + + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + + U32 type = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK; + + if (rigged) + { + mAlphaMaskPool->pushRiggedGLTFBatches(type + 1); + } + else + { + mAlphaMaskPool->pushGLTFBatches(type); + } + + gGL.loadMatrix(gGLModelView); + gGLLastMatrix = NULL; + } + } + + gDeferredShadowCubeProgram.bind(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + + gGL.setColorMask(true, true); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + gGLLastMatrix = NULL; + + // reset occlusion culling flag + sUseOcclusion = saved_occlusion; + LLPipeline::sShadowRender = false; +} - LLGLEnable blend(GL_BLEND); - gGL.blendFunc(LLRender::BF_ONE, LLRender::BF_SOURCE_ALPHA, LLRender::BF_ZERO, LLRender::BF_SOURCE_ALPHA); +bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; + //get point cloud of intersection of frust and min, max - gGL.setColorMask(true, true); + if (getVisibleExtents(camera, min, max)) + { + return false; + } - // apply haze - LLGLSLShader& haze_shader = gHazeWaterProgram; + //get set of planes on bounding box + LLPlane bp[] = { + LLPlane(min, LLVector3(-1,0,0)), + LLPlane(min, LLVector3(0,-1,0)), + LLPlane(min, LLVector3(0,0,-1)), + LLPlane(max, LLVector3(1,0,0)), + LLPlane(max, LLVector3(0,1,0)), + LLPlane(max, LLVector3(0,0,1))}; + + //potential points + std::vector pp; + + //add corners of AABB + pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); + + //add corners of camera frustum + for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++) + { + pp.push_back(camera.mAgentFrustum[i]); + } - LL_PROFILE_GPU_ZONE("haze"); - bindDeferredShader(haze_shader, nullptr, &mWaterDis); - haze_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV); + //bounding box line segments + U32 bs[] = + { + 0,1, + 1,3, + 3,2, + 2,0, + + 4,5, + 5,7, + 7,6, + 6,4, + + 0,4, + 1,5, + 3,7, + 2,6 + }; - static LLStaticHashedString above_water_str("above_water"); - haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1); + for (U32 i = 0; i < 12; i++) + { //for each line segment in bounding box + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++) + { //for each plane in camera frustum + const LLPlane& cp = camera.getAgentPlane(j); + const LLVector3& v1 = pp[bs[i*2+0]]; + const LLVector3& v2 = pp[bs[i*2+1]]; + LLVector3 n; + cp.getVector3(n); - if (LLPipeline::sUnderWaterRender) - { - LLGLDepthTest depth(GL_FALSE); + LLVector3 line = v1-v2; - // full screen blit - mScreenTriangleVB->setBuffer(); - mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); - } - else - { - //render water patches like LLDrawPoolWater does - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); + F32 t = d2/d1; - if (mWaterPool) + if (t > 0.f && t < 1.f) { - mWaterPool->pushFaceGeometry(); + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); } } + } - unbindDeferredShader(haze_shader); + //camera frustum line segments + const U32 fs[] = + { + 0,1, + 1,2, + 2,3, + 3,0, + + 4,5, + 5,6, + 6,7, + 7,4, + + 0,4, + 1,5, + 2,6, + 3,7 + }; + for (U32 i = 0; i < 12; i++) + { + for (U32 j = 0; j < 6; ++j) + { + const LLVector3& v1 = pp[fs[i*2+0]+8]; + const LLVector3& v2 = pp[fs[i*2+1]+8]; + const LLPlane& cp = bp[j]; + LLVector3 n; + cp.getVector3(n); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - } -} + LLVector3 line = v1-v2; -void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) -{ - //construct frustum - LLVOVolume* volume = drawablep->getVOVolume(); - LLVector3 params = volume->getSpotLightParams(); - - F32 fov = params.mV[0]; - F32 focus = params.mV[1]; - - LLVector3 pos = drawablep->getPositionAgent(); - LLQuaternion quat = volume->getRenderRotation(); - LLVector3 scale = volume->getScale(); - - //get near clip plane - LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); - at_axis *= quat; - - LLVector3 np = pos+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); - - LLVector3 origin = np - at_axis*dist; - - //matrix from volume space to agent space - LLMatrix4 light_mat(quat, LLVector4(origin,1.f)); - - glh::matrix4f light_to_agent((F32*) light_mat.mMatrix); - glh::matrix4f light_to_screen = get_current_modelview() * light_to_agent; - - glh::matrix4f screen_to_light = light_to_screen.inverse(); - - F32 s = volume->getLightRadius()*1.5f; - F32 near_clip = dist; - F32 width = scale.mV[VX]; - F32 height = scale.mV[VY]; - F32 far_clip = s+dist-scale.mV[VZ]; - - F32 fovy = fov * RAD_TO_DEG; - F32 aspect = width/height; - - 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); - - glh::vec3f p1(0, 0, -(near_clip+0.01f)); - glh::vec3f p2(0, 0, -(near_clip+1.f)); - - glh::vec3f screen_origin(0, 0, 0); - - light_to_screen.mult_matrix_vec(p1); - light_to_screen.mult_matrix_vec(p2); - light_to_screen.mult_matrix_vec(screen_origin); - - glh::vec3f n = p2-p1; - n.normalize(); - - F32 proj_range = far_clip - near_clip; - glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip); - screen_to_light = trans * light_proj * screen_to_light; - shader.uniformMatrix4fv(LLShaderMgr::PROJECTOR_MATRIX, 1, FALSE, screen_to_light.m); - shader.uniform1f(LLShaderMgr::PROJECTOR_NEAR, near_clip); - shader.uniform3fv(LLShaderMgr::PROJECTOR_P, 1, p1.v); - shader.uniform3fv(LLShaderMgr::PROJECTOR_N, 1, n.v); - shader.uniform3fv(LLShaderMgr::PROJECTOR_ORIGIN, 1, screen_origin.v); - shader.uniform1f(LLShaderMgr::PROJECTOR_RANGE, proj_range); - shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIANCE, params.mV[2]); - S32 s_idx = -1; - - for (U32 i = 0; i < 2; i++) - { - if (mShadowSpotLight[i] == drawablep) - { - s_idx = i; - } - } - - shader.uniform1i(LLShaderMgr::PROJECTOR_SHADOW_INDEX, s_idx); - - if (s_idx >= 0) - { - shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f-mSpotLightFade[s_idx]); - } - else - { - shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f); - } + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); - // make sure we're not already targeting the same spot light with both shadow maps - llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull()); + F32 t = d2/d1; - if (!gCubeSnapshot) - { - LLDrawable* potential = drawablep; - //determine if this light is higher priority than one of the existing spot shadows - F32 m_pri = volume->getSpotLightPriority(); - - for (U32 i = 0; i < 2; i++) - { - F32 pri = 0.f; - - if (mTargetShadowSpotLight[i].notNull()) - { - pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority(); - } - - if (m_pri > pri) - { - LLDrawable* temp = mTargetShadowSpotLight[i]; - mTargetShadowSpotLight[i] = potential; - potential = temp; - m_pri = pri; - } - } - } + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } + } + } - // make sure we didn't end up targeting the same spot light with both shadow maps - llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull()); + LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), + max+LLVector3(0.05f,0.05f,0.05f) }; - LLViewerTexture* img = volume->getLightTexture(); + for (U32 i = 0; i < pp.size(); ++i) + { + bool found = true; + + const F32* p = pp[i].mV; - if (img == NULL) - { - img = LLViewerFetchedTexture::sWhiteImagep; - } + for (U32 j = 0; j < 3; ++j) + { + if (p[j] < ext[0].mV[j] || + p[j] > ext[1].mV[j]) + { + found = false; + break; + } + } - S32 channel = shader.enableTexture(LLShaderMgr::DEFERRED_PROJECTION); + for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j) + { + const LLPlane& cp = camera.getAgentPlane(j); + F32 dist = cp.dist(pp[i]); + if (dist > 0.05f) //point is above some plane, not contained + { + found = false; + break; + } + } - if (channel > -1) - { - if (img) - { - gGL.getTexUnit(channel)->bind(img); + if (found) + { + fp.push_back(pp[i]); + } + } - F32 lod_range = logf(img->getWidth())/logf(2.f); + if (fp.empty()) + { + return false; + } - shader.uniform1f(LLShaderMgr::PROJECTOR_FOCUS, focus); - shader.uniform1f(LLShaderMgr::PROJECTOR_LOD, lod_range); - shader.uniform1f(LLShaderMgr::PROJECTOR_AMBIENT_LOD, llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); - } - } - + return true; } -void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) +void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) { - LLRenderTarget* deferred_target = &mRT->deferredScreen; - LLRenderTarget* deferred_light_target = &mRT->deferredLight; - - stop_glerror(); - shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_EMISSIVE, deferred_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_BRDF_LUT); - //shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage()); - shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage()); - shader.disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM); - - for (U32 i = 0; i < 4; i++) - { - if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - } - } - - for (U32 i = 4; i < 6; i++) - { - if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - } - } - - shader.disableTexture(LLShaderMgr::DEFERRED_NOISE); - shader.disableTexture(LLShaderMgr::DEFERRED_LIGHTFUNC); - - if (!LLPipeline::sReflectionProbesEnabled) + if (obj && obj->getVolume()) { - S32 channel = shader.disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - if (channel > -1) + for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter) { - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; - if (cube_map) + renderHighlight(*iter, fade); + } + + LLDrawable* drawable = obj->mDrawable; + if (drawable) + { + for (S32 i = 0; i < drawable->getNumFaces(); ++i) { - cube_map->disable(); + LLFace* face = drawable->getFace(i); + if (face) + { + face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade)); + } } } } +} - unbindReflectionProbes(shader); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->activate(); - shader.unbind(); +LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i) +{ + llassert(i < 4); + return &mRT->shadow[i]; } -void LLPipeline::setEnvMat(LLGLSLShader& shader) +LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i) { - F32* m = gGLModelView; - - F32 mat[] = { m[0], m[1], m[2], - m[4], m[5], m[6], - m[8], m[9], m[10] }; - - shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_ENV_MAT, 1, TRUE, mat); + llassert(i < 2); + return &mSpotShadow[i]; } -void LLPipeline::bindReflectionProbes(LLGLSLShader& shader) +static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); +static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render"); + +// helper class for disabling occlusion culling for the current stack frame +class LLDisableOcclusionCulling { - if (!sReflectionProbesEnabled) +public: + S32 mUseOcclusion; + + LLDisableOcclusionCulling() { - return; + mUseOcclusion = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 0; } - S32 channel = shader.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - bool bound = false; - if (channel > -1 && mReflectionMapManager.mTexture.notNull()) + ~LLDisableOcclusionCulling() { - mReflectionMapManager.mTexture->bind(channel); - bound = true; + LLPipeline::sUseOcclusion = mUseOcclusion; } +}; - channel = shader.enableTexture(LLShaderMgr::IRRADIANCE_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mReflectionMapManager.mIrradianceMaps.notNull()) +void LLPipeline::generateSunShadow(LLCamera& camera) +{ + if (!sRenderDeferred || RenderShadowDetail <= 0) { - mReflectionMapManager.mIrradianceMaps->bind(channel); - bound = true; + return; } - - if (RenderMirrors) + + LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW); + LL_PROFILE_GPU_ZONE("generateSunShadow"); + + LLDisableOcclusionCulling no_occlusion; + + bool skip_avatar_update = false; + if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) { - channel = shader.enableTexture(LLShaderMgr::HERO_PROBE, LLTexUnit::TT_CUBE_MAP_ARRAY); - if (channel > -1 && mHeroProbeManager.mTexture.notNull()) - { - mHeroProbeManager.mTexture->bind(channel); - bound = true; - } + skip_avatar_update = true; } - - if (bound) + if (!skip_avatar_update) { - mReflectionMapManager.setUniforms(); + gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON); + } - setEnvMat(shader); + F64 last_modelview[16]; + F64 last_projection[16]; + for (U32 i = 0; i < 16; i++) + { //store last_modelview of world camera + last_modelview[i] = gGLLastModelView[i]; + last_projection[i] = gGLLastProjection[i]; } - // reflection probe shaders generally sample the scene map as well for SSR - channel = shader.enableTexture(LLShaderMgr::SCENE_MAP); - if (channel > -1) + pushRenderTypeMask(); + andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, + LLPipeline::RENDER_TYPE_ALPHA, + LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER, + LLPipeline::RENDER_TYPE_ALPHA_POST_WATER, + LLPipeline::RENDER_TYPE_GRASS, + LLPipeline::RENDER_TYPE_GLTF_PBR, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_CONTROL_AV, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_PASS_ALPHA, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_GRASS, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_SHINY, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, + LLPipeline::RENDER_TYPE_PASS_MATERIAL, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_SPECMAP, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMMAP, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE, + LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SIMPLE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_BUMP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SHINY_RIGGED, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED, + LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED, + LLPipeline::RENDER_TYPE_PASS_GLTF_PBR, + LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_RIGGED, + LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK, + LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED, + END_RENDER_TYPES); + + gGL.setColorMask(false, false); + + LLEnvironment& environment = LLEnvironment::instance(); + + //get sun view matrix + + //store current projection/modelview matrix + glh::matrix4f saved_proj = get_current_projection(); + glh::matrix4f saved_view = get_current_modelview(); + glh::matrix4f inv_view = saved_view.inverse(); + + glh::matrix4f view[6]; + glh::matrix4f proj[6]; + + LLVector3 caster_dir(environment.getIsSunUp() ? mSunDir : mMoonDir); + + //put together a universal "near clip" plane for shadow frusta + LLPlane shadow_near_clip; { - gGL.getTexUnit(channel)->bind(&mSceneMap); + LLVector3 p = camera.getOrigin(); // gAgent.getPositionAgent(); + p += caster_dir * RenderFarClip*2.f; + shadow_near_clip.setVec(p, caster_dir); } - - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ITR_COUNT, RenderScreenSpaceReflectionIterations); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_DIST_BIAS, RenderScreenSpaceReflectionDistanceBias); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_RAY_STEP, RenderScreenSpaceReflectionRayStep); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_GLOSSY_SAMPLES, RenderScreenSpaceReflectionGlossySamples); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_REJECT_BIAS, RenderScreenSpaceReflectionDepthRejectBias); - mPoissonOffset++; + LLVector3 lightDir = -caster_dir; + lightDir.normVec(); - if (mPoissonOffset > 128 - RenderScreenSpaceReflectionGlossySamples) - mPoissonOffset = 0; + glh::vec3f light_dir(lightDir.mV); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_NOISE_SINE, mPoissonOffset); - shader.uniform1f(LLShaderMgr::DEFERRED_SSR_ADAPTIVE_STEP_MULT, RenderScreenSpaceReflectionAdaptiveStepMultiplier); + //create light space camera matrix - channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH); - if (channel > -1) + LLVector3 at = lightDir; + + LLVector3 up = camera.getAtAxis(); + + if (fabsf(up*lightDir) > 0.75f) { - gGL.getTexUnit(channel)->bind(&mSceneMap, true); + up = camera.getUpAxis(); } + up.normVec(); + at.normVec(); -} -void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader) -{ - S32 channel = shader.disableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP); - if (channel > -1 && mReflectionMapManager.mTexture.notNull()) + LLCamera main_camera = camera; + + F32 near_clip = 0.f; { - mReflectionMapManager.mTexture->unbind(); - if (channel == 0) + //get visible point cloud + std::vector fp; + + main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum); + + LLVector3 min,max; + getVisiblePointCloud(main_camera,min,max,fp); + + if (fp.empty()) { - gGL.getTexUnit(channel)->enable(LLTexUnit::TT_TEXTURE); + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowCamera[0] = main_camera; + mShadowExtents[0][0] = min; + mShadowExtents[0][1] = max; + + mShadowFrustPoints[0].clear(); + mShadowFrustPoints[1].clear(); + mShadowFrustPoints[2].clear(); + mShadowFrustPoints[3].clear(); + } + popRenderTypeMask(); + + if (!skip_avatar_update) + { + gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode()); + } + + return; + } + + //get good split distances for frustum + for (U32 i = 0; i < fp.size(); ++i) + { + glh::vec3f v(fp[i].mV); + saved_view.mult_matrix_vec(v); + fp[i].setVec(v.v); } - } -} + min = fp[0]; + max = fp[0]; -inline float sgn(float a) -{ - if (a > 0.0F) return (1.0F); - if (a < 0.0F) return (-1.0F); - return (0.0F); -} + //get camera space bounding box + for (U32 i = 1; i < fp.size(); ++i) + { + update_min_max(min, max, fp[i]); + } -glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) -{ - glh::matrix4f ret; + near_clip = llclamp(-max.mV[2], 0.01f, 4.0f); + F32 far_clip = llclamp(-min.mV[2]*2.f, 16.0f, 512.0f); - LLVector3 dirN; - LLVector3 upN; - LLVector3 lftN; + //far_clip = llmin(far_clip, 128.f); + far_clip = llmin(far_clip, camera.getFar()); - lftN = dir % up; - lftN.normVec(); - - upN = lftN % dir; - upN.normVec(); - - dirN = dir; - dirN.normVec(); + F32 range = far_clip-near_clip; - ret.m[ 0] = lftN[0]; - ret.m[ 1] = upN[0]; - ret.m[ 2] = -dirN[0]; - ret.m[ 3] = 0.f; + LLVector3 split_exp = RenderShadowSplitExponent; - ret.m[ 4] = lftN[1]; - ret.m[ 5] = upN[1]; - ret.m[ 6] = -dirN[1]; - ret.m[ 7] = 0.f; + F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) ); - ret.m[ 8] = lftN[2]; - ret.m[ 9] = upN[2]; - ret.m[10] = -dirN[2]; - ret.m[11] = 0.f; + da = powf(da, split_exp.mV[2]); - ret.m[12] = -(lftN*pos); - ret.m[13] = -(upN*pos); - ret.m[14] = dirN*pos; - ret.m[15] = 1.f; + F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da; - return ret; -} + for (U32 i = 0; i < 4; ++i) + { + F32 x = (F32)(i+1)/4.f; + x = powf(x, sxp); + mSunClipPlanes.mV[i] = near_clip+range*x; + } -glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) -{ - glh::matrix4f ret; - ret.m[ 0] = 2/(max[0]-min[0]); - ret.m[ 4] = 0; - ret.m[ 8] = 0; - ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]); + mSunClipPlanes.mV[0] *= 1.25f; //bump back first split for transition padding + } - ret.m[ 1] = 0; - ret.m[ 5] = 2/(max[1]-min[1]); - ret.m[ 9] = 0; - ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]); + if (gCubeSnapshot) + { // stretch clip planes for reflection probe renders to reduce number of shadow passes + mSunClipPlanes.mV[1] = mSunClipPlanes.mV[2]; + mSunClipPlanes.mV[2] = mSunClipPlanes.mV[3]; + mSunClipPlanes.mV[3] *= 1.5f; + } - ret.m[ 2] = 0; - ret.m[ 6] = 0; - ret.m[10] = 2/(max[2]-min[2]); - ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]); - ret.m[ 3] = 0; - ret.m[ 7] = 0; - ret.m[11] = 0; - ret.m[15] = 1; + // convenience array of 4 near clip plane distances + F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; - return ret; -} + if (mSunDiffuse == LLColor4::black) + { //sun diffuse is totally black shadows don't matter + skipRenderingShadows(); + } + else + { + for (S32 j = 0; j < (gCubeSnapshot ? 2 : 4); j++) + { + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowFrustPoints[j].clear(); + } -static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA("Alpha Shadow"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_SIMPLE("Simple Shadow"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_GEOM("Shadow Geom"); + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_MASKED("Alpha Masked"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_BLEND("Alpha Blend"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass"); -static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked"); + //restore render matrices + set_current_modelview(saved_view); + set_current_projection(saved_proj); -void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool depth_clamp) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER); - LL_PROFILE_GPU_ZONE("renderShadow"); - - LLPipeline::sShadowRender = true; + LLVector3 eye = camera.getOrigin(); + llassert(eye.isFinite()); - // disable occlusion culling during shadow render - U32 saved_occlusion = sUseOcclusion; - sUseOcclusion = 0; + //camera used for shadow cull/render + LLCamera shadow_cam; - // List of render pass types that use the prim volume as the shadow, - // ignoring textures. - static const U32 types[] = { - LLRenderPass::PASS_SIMPLE, - LLRenderPass::PASS_FULLBRIGHT, - LLRenderPass::PASS_SHINY, - LLRenderPass::PASS_BUMP, - LLRenderPass::PASS_FULLBRIGHT_SHINY, - LLRenderPass::PASS_MATERIAL, - LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, - LLRenderPass::PASS_SPECMAP, - LLRenderPass::PASS_SPECMAP_EMISSIVE, - LLRenderPass::PASS_NORMMAP, - LLRenderPass::PASS_NORMMAP_EMISSIVE, - LLRenderPass::PASS_NORMSPEC, - LLRenderPass::PASS_NORMSPEC_EMISSIVE - }; + //create world space camera frustum for this split + shadow_cam = camera; + shadow_cam.setFar(16.f); - LLGLEnable cull(GL_CULL_FACE); + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - //enable depth clamping if available - LLGLEnable clamp_depth(depth_clamp ? GL_DEPTH_CLAMP : 0); + LLVector3* frust = shadow_cam.mAgentFrustum; - LLGLDepthTest depth_test(GL_TRUE, GL_TRUE, GL_LESS); + LLVector3 pn = shadow_cam.getAtAxis(); - updateCull(shadow_cam, result); + LLVector3 min, max; - stateSort(shadow_cam, result); + //construct 8 corners of split frustum section + for (U32 i = 0; i < 4; i++) + { + LLVector3 delta = frust[i+4]-eye; + delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; + delta.normVec(); + F32 dp = delta*pn; + frust[i] = eye + (delta*dist[j]*0.75f)/dp; + frust[i+4] = eye + (delta*dist[j+1]*1.25f)/dp; + } - //generate shadow map - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadMatrix(proj.m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadMatrix(view.m); + shadow_cam.calcAgentFrustumPlanes(frust); + shadow_cam.mFrustumCornerDist = 0.f; - stop_glerror(); - gGLLastMatrix = NULL; + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowCamera[j] = shadow_cam; + } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + std::vector fp; - stop_glerror(); + if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir) + || j > RenderShadowSplits) + { + //no possible shadow receivers + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowExtents[j][0] = LLVector3(); + mShadowExtents[j][1] = LLVector3(); + mShadowCamera[j+4] = shadow_cam; + } - struct CompareVertexBuffer - { - bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs) - { - return lhs->mVertexBuffer > rhs->mVertexBuffer; - } - }; + mRT->shadow[j].bindTarget(); + { + LLGLDepthTest depth(GL_TRUE); + mRT->shadow[j].clear(); + } + mRT->shadow[j].flush(); + mShadowError.mV[j] = 0.f; + mShadowFOV.mV[j] = 0.f; - LLVertexBuffer::unbind(); - for (int j = 0; j < 2; ++j) // 0 -- static, 1 -- rigged - { - bool rigged = j == 1; - gDeferredShadowProgram.bind(rigged); + continue; + } - gGL.diffuseColor4f(1, 1, 1, 1); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowExtents[j][0] = min; + mShadowExtents[j][1] = max; + mShadowFrustPoints[j] = fp; + } - S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); - // if not using VSM, disable color writes - if (shadow_detail <= 2) - { - gGL.setColorMask(false, false); - } + //find a good origin for shadow projection + LLVector3 origin; - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow simple"); //LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE); - LL_PROFILE_GPU_ZONE("shadow simple"); - gGL.getTexUnit(0)->disable(); + //get a temporary view projection + view[j] = look(camera.getOrigin(), lightDir, -up); - for (U32 type : types) - { - renderObjects(type, false, false, rigged); - } + std::vector wpf; - renderGLTFObjects(LLRenderPass::PASS_GLTF_PBR, false, rigged); + for (U32 i = 0; i < fp.size(); i++) + { + glh::vec3f p = glh::vec3f(fp[i].mV); + view[j].mult_matrix_vec(p); + wpf.push_back(LLVector3(p.v)); + } - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - } + min = wpf[0]; + max = wpf[0]; - if (LLPipeline::sUseOcclusion > 1) - { // do occlusion culling against non-masked only to take advantage of hierarchical Z - doOcclusion(shadow_cam); - } + for (U32 i = 0; i < fp.size(); ++i) + { //get AABB in camera space + update_min_max(min, max, wpf[i]); + } + // Construct a perspective transform with perspective along y-axis that contains + // points in wpf + //Known: + // - far clip plane + // - near clip plane + // - points in frustum + //Find: + // - origin - { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow geom"); - renderGeomShadow(shadow_cam); - } + //get some "interesting" points of reference + LLVector3 center = (min+max)*0.5f; + LLVector3 size = (max-min)*0.5f; + LLVector3 near_center = center; + near_center.mV[1] += size.mV[1]*2.f; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha"); - LL_PROFILE_GPU_ZONE("shadow alpha"); - const S32 sun_up = LLEnvironment::instance().getIsSunUp() ? 1 : 0; - U32 target_width = LLRenderTarget::sCurResX; - for (int i = 0; i < 2; ++i) - { - bool rigged = i == 1; + //put all points in wpf in quadrant 0, reletive to center of min/max + //get the best fit line using least squares + F32 bfm = 0.f; + F32 bfb = 0.f; + for (U32 i = 0; i < wpf.size(); ++i) { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha masked"); - LL_PROFILE_GPU_ZONE("shadow alpha masked"); - gDeferredShadowAlphaMaskProgram.bind(rigged); - LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); - LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); - renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, true, true, rigged); + wpf[i] -= center; + wpf[i].mV[0] = fabsf(wpf[i].mV[0]); + wpf[i].mV[2] = fabsf(wpf[i].mV[2]); } + if (!wpf.empty()) { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha blend"); - LL_PROFILE_GPU_ZONE("shadow alpha blend"); - renderAlphaObjects(rigged); - } + F32 sx = 0.f; + F32 sx2 = 0.f; + F32 sy = 0.f; + F32 sxy = 0.f; - { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow fullbright alpha masked"); - LL_PROFILE_GPU_ZONE("shadow alpha masked"); - gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged); - LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); - LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); - renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, true, true, rigged); + for (U32 i = 0; i < wpf.size(); ++i) + { + sx += wpf[i].mV[0]; + sx2 += wpf[i].mV[0]*wpf[i].mV[0]; + sy += wpf[i].mV[1]; + sxy += wpf[i].mV[0]*wpf[i].mV[1]; + } + + bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2); + bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2); } { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha grass"); - LL_PROFILE_GPU_ZONE("shadow alpha grass"); - gDeferredTreeShadowProgram.bind(rigged); - LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(ALPHA_BLEND_CUTOFF); + // best fit line is y=bfm*x+bfb - if (i == 0) + //find point that is furthest to the right of line + F32 off_x = -1.f; + LLVector3 lp; + + for (U32 i = 0; i < wpf.size(); ++i) { - renderObjects(LLRenderPass::PASS_GRASS, true); + //y = bfm*x+bfb + //x = (y-bfb)/bfm + F32 lx = (wpf[i].mV[1]-bfb)/bfm; + + lx = wpf[i].mV[0]-lx; + + if (off_x < lx) + { + off_x = lx; + lp = wpf[i]; + } } + //get line with slope bfm through lp + // bfb = y-bfm*x + bfb = lp.mV[1]-bfm*lp.mV[0]; + + //calculate error + mShadowError.mV[j] = 0.f; + + for (U32 i = 0; i < wpf.size(); ++i) { - LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("shadow alpha material"); - LL_PROFILE_GPU_ZONE("shadow alpha material"); - renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, true, false, rigged); - renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, true, false, rigged); - renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, true, false, rigged); - renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, true, false, rigged); + F32 lx = (wpf[i].mV[1]-bfb)/bfm; + mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx); } - } - } - for (int i = 0; i < 2; ++i) - { - bool rigged = i == 1; - gDeferredShadowGLTFAlphaMaskProgram.bind(rigged); - LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up); - LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width); - - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; + mShadowError.mV[j] /= wpf.size(); + mShadowError.mV[j] /= size.mV[0]; - U32 type = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK; + if (mShadowError.mV[j] > RenderShadowErrorCutoff) + { //just use ortho projection + mShadowFOV.mV[j] = -1.f; + origin.clearVec(); + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + } + else + { + //origin is where line x = 0; + origin.setVec(0,bfb,0); - if (rigged) - { - mAlphaMaskPool->pushRiggedGLTFBatches(type + 1); - } - else - { - mAlphaMaskPool->pushGLTFBatches(type); - } + F32 fovz = 1.f; + F32 fovx = 1.f; - gGL.loadMatrix(gGLModelView); - gGLLastMatrix = NULL; - } - } + LLVector3 zp; + LLVector3 xp; - gDeferredShadowCubeProgram.bind(); - gGLLastMatrix = NULL; - gGL.loadMatrix(gGLModelView); + for (U32 i = 0; i < wpf.size(); ++i) + { + LLVector3 atz = wpf[i]-origin; + atz.mV[0] = 0.f; + atz.normVec(); + if (fovz > -atz.mV[1]) + { + zp = wpf[i]; + fovz = -atz.mV[1]; + } - gGL.setColorMask(true, true); + LLVector3 atx = wpf[i]-origin; + atx.mV[2] = 0.f; + atx.normVec(); + if (fovx > -atx.mV[1]) + { + fovx = -atx.mV[1]; + xp = wpf[i]; + } + } - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - gGLLastMatrix = NULL; + fovx = acos(fovx); + fovz = acos(fovz); - // reset occlusion culling flag - sUseOcclusion = saved_occlusion; - LLPipeline::sShadowRender = false; -} + F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f); -bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir) -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - //get point cloud of intersection of frust and min, max - - if (getVisibleExtents(camera, min, max)) - { - return false; - } - - //get set of planes on bounding box - LLPlane bp[] = { - LLPlane(min, LLVector3(-1,0,0)), - LLPlane(min, LLVector3(0,-1,0)), - LLPlane(min, LLVector3(0,0,-1)), - LLPlane(max, LLVector3(1,0,0)), - LLPlane(max, LLVector3(0,1,0)), - LLPlane(max, LLVector3(0,0,1))}; - - //potential points - std::vector pp; - - //add corners of AABB - pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); - pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); - pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); - pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); - pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); - pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); - pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); - pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); - - //add corners of camera frustum - for (U32 i = 0; i < LLCamera::AGENT_FRUSTRUM_NUM; i++) - { - pp.push_back(camera.mAgentFrustum[i]); - } - - - //bounding box line segments - U32 bs[] = - { - 0,1, - 1,3, - 3,2, - 2,0, - - 4,5, - 5,7, - 7,6, - 6,4, - - 0,4, - 1,5, - 3,7, - 2,6 - }; - - for (U32 i = 0; i < 12; i++) - { //for each line segment in bounding box - for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; j++) - { //for each plane in camera frustum - const LLPlane& cp = camera.getAgentPlane(j); - const LLVector3& v1 = pp[bs[i*2+0]]; - const LLVector3& v2 = pp[bs[i*2+1]]; - LLVector3 n; - cp.getVector3(n); - - LLVector3 line = v1-v2; - - F32 d1 = line*n; - F32 d2 = -cp.dist(v2); - - F32 t = d2/d1; - - if (t > 0.f && t < 1.f) - { - LLVector3 intersect = v2+line*t; - pp.push_back(intersect); - } - } - } - - //camera frustum line segments - const U32 fs[] = - { - 0,1, - 1,2, - 2,3, - 3,0, - - 4,5, - 5,6, - 6,7, - 7,4, - - 0,4, - 1,5, - 2,6, - 3,7 - }; - - for (U32 i = 0; i < 12; i++) - { - for (U32 j = 0; j < 6; ++j) - { - const LLVector3& v1 = pp[fs[i*2+0]+8]; - const LLVector3& v2 = pp[fs[i*2+1]+8]; - const LLPlane& cp = bp[j]; - LLVector3 n; - cp.getVector3(n); - - LLVector3 line = v1-v2; - - F32 d1 = line*n; - F32 d2 = -cp.dist(v2); - - F32 t = d2/d1; - - if (t > 0.f && t < 1.f) - { - LLVector3 intersect = v2+line*t; - pp.push_back(intersect); - } - } - } - - LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), - max+LLVector3(0.05f,0.05f,0.05f) }; - - for (U32 i = 0; i < pp.size(); ++i) - { - bool found = true; - - const F32* p = pp[i].mV; - - for (U32 j = 0; j < 3; ++j) - { - if (p[j] < ext[0].mV[j] || - p[j] > ext[1].mV[j]) - { - found = false; - break; - } - } - - for (U32 j = 0; j < LLCamera::AGENT_PLANE_NO_USER_CLIP_NUM; ++j) - { - const LLPlane& cp = camera.getAgentPlane(j); - F32 dist = cp.dist(pp[i]); - if (dist > 0.05f) //point is above some plane, not contained - { - found = false; - break; - } - } - - if (found) - { - fp.push_back(pp[i]); - } - } - - if (fp.empty()) - { - return false; - } - - return true; -} + mShadowFOV.mV[j] = fovx; -void LLPipeline::renderHighlight(const LLViewerObject* obj, F32 fade) -{ - if (obj && obj->getVolume()) - { - for (LLViewerObject::child_list_t::const_iterator iter = obj->getChildren().begin(); iter != obj->getChildren().end(); ++iter) - { - renderHighlight(*iter, fade); - } - - LLDrawable* drawable = obj->mDrawable; - if (drawable) - { - for (S32 i = 0; i < drawable->getNumFaces(); ++i) - { - LLFace* face = drawable->getFace(i); - if (face) - { - face->renderSelected(LLViewerTexture::sNullImagep, LLColor4(1,1,1,fade)); - } - } - } - } -} + if (fovx < cutoff && fovz > cutoff) + { + //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff + F32 d = zp.mV[2]/tan(cutoff); + F32 ny = zp.mV[1] + fabsf(d); + origin.mV[1] = ny; -LLRenderTarget* LLPipeline::getSunShadowTarget(U32 i) -{ - llassert(i < 4); - return &mRT->shadow[i]; -} + fovz = 1.f; + fovx = 1.f; -LLRenderTarget* LLPipeline::getSpotShadowTarget(U32 i) -{ - llassert(i < 2); - return &mSpotShadow[i]; -} + for (U32 i = 0; i < wpf.size(); ++i) + { + LLVector3 atz = wpf[i]-origin; + atz.mV[0] = 0.f; + atz.normVec(); + fovz = llmin(fovz, -atz.mV[1]); + + LLVector3 atx = wpf[i]-origin; + atx.mV[2] = 0.f; + atx.normVec(); + fovx = llmin(fovx, -atx.mV[1]); + } + + fovx = acos(fovx); + fovz = acos(fovz); + + mShadowFOV.mV[j] = cutoff; + } + + + origin += center; + + F32 ynear = -(max.mV[1]-origin.mV[1]); + F32 yfar = -(min.mV[1]-origin.mV[1]); + + if (ynear < 0.1f) //keep a sensible near clip plane + { + F32 diff = 0.1f-ynear; + origin.mV[1] += diff; + ynear += diff; + yfar += diff; + } + + if (fovx > cutoff) + { //just use ortho projection + origin.clearVec(); + mShadowError.mV[j] = -1.f; + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + } + else + { + //get perspective projection + view[j] = view[j].inverse(); + //llassert(origin.isFinite()); -static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow"); -static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render"); + glh::vec3f origin_agent(origin.mV); -// helper class for disabling occlusion culling for the current stack frame -class LLDisableOcclusionCulling -{ -public: - S32 mUseOcclusion; + //translate view to origin + view[j].mult_matrix_vec(origin_agent); - LLDisableOcclusionCulling() - { - mUseOcclusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - } + eye = LLVector3(origin_agent.v); + //llassert(eye.isFinite()); + if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowFrustOrigin[j] = eye; + } - ~LLDisableOcclusionCulling() - { - LLPipeline::sUseOcclusion = mUseOcclusion; - } -}; + view[j] = look(LLVector3(origin_agent.v), lightDir, -up); -void LLPipeline::generateSunShadow(LLCamera& camera) -{ - if (!sRenderDeferred || RenderShadowDetail <= 0) - { - return; - } + F32 fx = 1.f/tanf(fovx); + F32 fz = 1.f/tanf(fovz); - LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_GEN_SUN_SHADOW); - LL_PROFILE_GPU_ZONE("generateSunShadow"); + proj[j] = glh::matrix4f(-fx, 0, 0, 0, + 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar), + 0, 0, -fz, 0, + 0, -1.f, 0, 0); + } + } + } - LLDisableOcclusionCulling no_occlusion; + //shadow_cam.setFar(128.f); + shadow_cam.setOriginAndLookAt(eye, up, center); - bool skip_avatar_update = false; - if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson) - { - skip_avatar_update = true; - } - - if (!skip_avatar_update) - { - gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON); - } - - F64 last_modelview[16]; - F64 last_projection[16]; - for (U32 i = 0; i < 16; i++) - { //store last_modelview of world camera - last_modelview[i] = gGLLastModelView[i]; - last_projection[i] = gGLLastProjection[i]; - } - - pushRenderTypeMask(); - andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, - LLPipeline::RENDER_TYPE_ALPHA, - LLPipeline::RENDER_TYPE_ALPHA_PRE_WATER, - LLPipeline::RENDER_TYPE_ALPHA_POST_WATER, - LLPipeline::RENDER_TYPE_GRASS, - LLPipeline::RENDER_TYPE_GLTF_PBR, - LLPipeline::RENDER_TYPE_FULLBRIGHT, - LLPipeline::RENDER_TYPE_BUMP, - LLPipeline::RENDER_TYPE_VOLUME, - LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_CONTROL_AV, - LLPipeline::RENDER_TYPE_TREE, - LLPipeline::RENDER_TYPE_TERRAIN, - LLPipeline::RENDER_TYPE_WATER, - LLPipeline::RENDER_TYPE_VOIDWATER, - LLPipeline::RENDER_TYPE_PASS_ALPHA, - LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_GRASS, - LLPipeline::RENDER_TYPE_PASS_SIMPLE, - LLPipeline::RENDER_TYPE_PASS_BUMP, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, - LLPipeline::RENDER_TYPE_PASS_SHINY, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY, - LLPipeline::RENDER_TYPE_PASS_MATERIAL, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE, - LLPipeline::RENDER_TYPE_PASS_SPECMAP, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE, - LLPipeline::RENDER_TYPE_PASS_NORMMAP, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE, - LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SIMPLE_RIGGED, - LLPipeline::RENDER_TYPE_PASS_BUMP_RIGGED, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SHINY_RIGGED, - LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_RIGGED, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED, - LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED, - LLPipeline::RENDER_TYPE_PASS_GLTF_PBR, - LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_RIGGED, - LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK, - LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED, - END_RENDER_TYPES); + shadow_cam.setOrigin(0,0,0); - gGL.setColorMask(false, false); + set_current_modelview(view[j]); + set_current_projection(proj[j]); - LLEnvironment& environment = LLEnvironment::instance(); + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - //get sun view matrix - - //store current projection/modelview matrix - glh::matrix4f saved_proj = get_current_projection(); - glh::matrix4f saved_view = get_current_modelview(); - glh::matrix4f inv_view = saved_view.inverse(); + //shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip); - glh::matrix4f view[6]; - glh::matrix4f proj[6]; - - LLVector3 caster_dir(environment.getIsSunUp() ? mSunDir : mMoonDir); + //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); - //put together a universal "near clip" plane for shadow frusta - LLPlane shadow_near_clip; - { - LLVector3 p = camera.getOrigin(); // gAgent.getPositionAgent(); - p += caster_dir * RenderFarClip*2.f; - shadow_near_clip.setVec(p, caster_dir); - } - - LLVector3 lightDir = -caster_dir; - lightDir.normVec(); - - glh::vec3f light_dir(lightDir.mV); - - //create light space camera matrix - - LLVector3 at = lightDir; - - LLVector3 up = camera.getAtAxis(); - - if (fabsf(up*lightDir) > 0.75f) - { - up = camera.getUpAxis(); - } - - up.normVec(); - at.normVec(); - - - LLCamera main_camera = camera; - - F32 near_clip = 0.f; - { - //get visible point cloud - std::vector fp; - - main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum); - - LLVector3 min,max; - getVisiblePointCloud(main_camera,min,max,fp); - - if (fp.empty()) - { - if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowCamera[0] = main_camera; - mShadowExtents[0][0] = min; - mShadowExtents[0][1] = max; - - mShadowFrustPoints[0].clear(); - mShadowFrustPoints[1].clear(); - mShadowFrustPoints[2].clear(); - mShadowFrustPoints[3].clear(); - } - popRenderTypeMask(); - - if (!skip_avatar_update) - { - gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode()); - } - - return; - } - - //get good split distances for frustum - for (U32 i = 0; i < fp.size(); ++i) - { - glh::vec3f v(fp[i].mV); - saved_view.mult_matrix_vec(v); - fp[i].setVec(v.v); - } - - min = fp[0]; - max = fp[0]; - - //get camera space bounding box - for (U32 i = 1; i < fp.size(); ++i) - { - update_min_max(min, max, fp[i]); - } - - near_clip = llclamp(-max.mV[2], 0.01f, 4.0f); - F32 far_clip = llclamp(-min.mV[2]*2.f, 16.0f, 512.0f); - - //far_clip = llmin(far_clip, 128.f); - far_clip = llmin(far_clip, camera.getFar()); - - F32 range = far_clip-near_clip; - - LLVector3 split_exp = RenderShadowSplitExponent; - - F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) ); - - da = powf(da, split_exp.mV[2]); - - F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da; - - for (U32 i = 0; i < 4; ++i) - { - F32 x = (F32)(i+1)/4.f; - x = powf(x, sxp); - mSunClipPlanes.mV[i] = near_clip+range*x; - } - - mSunClipPlanes.mV[0] *= 1.25f; //bump back first split for transition padding - } + set_current_modelview(view[j]); + set_current_projection(proj[j]); - if (gCubeSnapshot) - { // stretch clip planes for reflection probe renders to reduce number of shadow passes - mSunClipPlanes.mV[1] = mSunClipPlanes.mV[2]; - mSunClipPlanes.mV[2] = mSunClipPlanes.mV[3]; - mSunClipPlanes.mV[3] *= 1.5f; - } + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = mShadowModelview[j].m[i]; + gGLLastProjection[i] = mShadowProjection[j].m[i]; + } + mShadowModelview[j] = view[j]; + mShadowProjection[j] = proj[j]; + mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; - // convenience array of 4 near clip plane distances - F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; - - if (mSunDiffuse == LLColor4::black) - { //sun diffuse is totally black shadows don't matter - skipRenderingShadows(); - } - else - { - for (S32 j = 0; j < (gCubeSnapshot ? 2 : 4); j++) - { - if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowFrustPoints[j].clear(); - } + stop_glerror(); - LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SUN_SHADOW0+j); + mRT->shadow[j].bindTarget(); + mRT->shadow[j].getViewport(gGLViewport); + mRT->shadow[j].clear(); - //restore render matrices - set_current_modelview(saved_view); - set_current_projection(saved_proj); + { + static LLCullResult result[4]; + renderShadow(view[j], proj[j], shadow_cam, result[j], true); + } - LLVector3 eye = camera.getOrigin(); - llassert(eye.isFinite()); + mRT->shadow[j].flush(); - //camera used for shadow cull/render - LLCamera shadow_cam; - - //create world space camera frustum for this split - shadow_cam = camera; - shadow_cam.setFar(16.f); - - LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - - LLVector3* frust = shadow_cam.mAgentFrustum; - - LLVector3 pn = shadow_cam.getAtAxis(); - - LLVector3 min, max; - - //construct 8 corners of split frustum section - for (U32 i = 0; i < 4; i++) - { - LLVector3 delta = frust[i+4]-eye; - delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; - delta.normVec(); - F32 dp = delta*pn; - frust[i] = eye + (delta*dist[j]*0.75f)/dp; - frust[i+4] = eye + (delta*dist[j+1]*1.25f)/dp; - } - - shadow_cam.calcAgentFrustumPlanes(frust); - shadow_cam.mFrustumCornerDist = 0.f; - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowCamera[j] = shadow_cam; - } - - std::vector fp; - - if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir) - || j > RenderShadowSplits) - { - //no possible shadow receivers - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowExtents[j][0] = LLVector3(); - mShadowExtents[j][1] = LLVector3(); - mShadowCamera[j+4] = shadow_cam; - } - - mRT->shadow[j].bindTarget(); - { - LLGLDepthTest depth(GL_TRUE); - mRT->shadow[j].clear(); - } - mRT->shadow[j].flush(); - - mShadowError.mV[j] = 0.f; - mShadowFOV.mV[j] = 0.f; - - continue; - } - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowExtents[j][0] = min; - mShadowExtents[j][1] = max; - mShadowFrustPoints[j] = fp; - } - - - //find a good origin for shadow projection - LLVector3 origin; - - //get a temporary view projection - view[j] = look(camera.getOrigin(), lightDir, -up); - - std::vector wpf; - - for (U32 i = 0; i < fp.size(); i++) - { - glh::vec3f p = glh::vec3f(fp[i].mV); - view[j].mult_matrix_vec(p); - wpf.push_back(LLVector3(p.v)); - } - - min = wpf[0]; - max = wpf[0]; - - for (U32 i = 0; i < fp.size(); ++i) - { //get AABB in camera space - update_min_max(min, max, wpf[i]); - } - - // Construct a perspective transform with perspective along y-axis that contains - // points in wpf - //Known: - // - far clip plane - // - near clip plane - // - points in frustum - //Find: - // - origin - - //get some "interesting" points of reference - LLVector3 center = (min+max)*0.5f; - LLVector3 size = (max-min)*0.5f; - LLVector3 near_center = center; - near_center.mV[1] += size.mV[1]*2.f; - - - //put all points in wpf in quadrant 0, reletive to center of min/max - //get the best fit line using least squares - F32 bfm = 0.f; - F32 bfb = 0.f; - - for (U32 i = 0; i < wpf.size(); ++i) - { - wpf[i] -= center; - wpf[i].mV[0] = fabsf(wpf[i].mV[0]); - wpf[i].mV[2] = fabsf(wpf[i].mV[2]); - } - - if (!wpf.empty()) - { - F32 sx = 0.f; - F32 sx2 = 0.f; - F32 sy = 0.f; - F32 sxy = 0.f; - - for (U32 i = 0; i < wpf.size(); ++i) - { - sx += wpf[i].mV[0]; - sx2 += wpf[i].mV[0]*wpf[i].mV[0]; - sy += wpf[i].mV[1]; - sxy += wpf[i].mV[0]*wpf[i].mV[1]; - } - - bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2); - bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2); - } - - { - // best fit line is y=bfm*x+bfb - - //find point that is furthest to the right of line - F32 off_x = -1.f; - LLVector3 lp; - - for (U32 i = 0; i < wpf.size(); ++i) - { - //y = bfm*x+bfb - //x = (y-bfb)/bfm - F32 lx = (wpf[i].mV[1]-bfb)/bfm; - - lx = wpf[i].mV[0]-lx; - - if (off_x < lx) - { - off_x = lx; - lp = wpf[i]; - } - } - - //get line with slope bfm through lp - // bfb = y-bfm*x - bfb = lp.mV[1]-bfm*lp.mV[0]; - - //calculate error - mShadowError.mV[j] = 0.f; - - for (U32 i = 0; i < wpf.size(); ++i) - { - F32 lx = (wpf[i].mV[1]-bfb)/bfm; - mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx); - } - - mShadowError.mV[j] /= wpf.size(); - mShadowError.mV[j] /= size.mV[0]; - - if (mShadowError.mV[j] > RenderShadowErrorCutoff) - { //just use ortho projection - mShadowFOV.mV[j] = -1.f; - origin.clearVec(); - proj[j] = gl_ortho(min.mV[0], max.mV[0], - min.mV[1], max.mV[1], - -max.mV[2], -min.mV[2]); - } - else - { - //origin is where line x = 0; - origin.setVec(0,bfb,0); - - F32 fovz = 1.f; - F32 fovx = 1.f; - - LLVector3 zp; - LLVector3 xp; - - for (U32 i = 0; i < wpf.size(); ++i) - { - LLVector3 atz = wpf[i]-origin; - atz.mV[0] = 0.f; - atz.normVec(); - if (fovz > -atz.mV[1]) - { - zp = wpf[i]; - fovz = -atz.mV[1]; - } - - LLVector3 atx = wpf[i]-origin; - atx.mV[2] = 0.f; - atx.normVec(); - if (fovx > -atx.mV[1]) - { - fovx = -atx.mV[1]; - xp = wpf[i]; - } - } - - fovx = acos(fovx); - fovz = acos(fovz); - - F32 cutoff = llmin((F32) RenderShadowFOVCutoff, 1.4f); - - mShadowFOV.mV[j] = fovx; - - if (fovx < cutoff && fovz > cutoff) - { - //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff - F32 d = zp.mV[2]/tan(cutoff); - F32 ny = zp.mV[1] + fabsf(d); - - origin.mV[1] = ny; - - fovz = 1.f; - fovx = 1.f; - - for (U32 i = 0; i < wpf.size(); ++i) - { - LLVector3 atz = wpf[i]-origin; - atz.mV[0] = 0.f; - atz.normVec(); - fovz = llmin(fovz, -atz.mV[1]); - - LLVector3 atx = wpf[i]-origin; - atx.mV[2] = 0.f; - atx.normVec(); - fovx = llmin(fovx, -atx.mV[1]); - } - - fovx = acos(fovx); - fovz = acos(fovz); - - mShadowFOV.mV[j] = cutoff; - } - - - origin += center; - - F32 ynear = -(max.mV[1]-origin.mV[1]); - F32 yfar = -(min.mV[1]-origin.mV[1]); - - if (ynear < 0.1f) //keep a sensible near clip plane - { - F32 diff = 0.1f-ynear; - origin.mV[1] += diff; - ynear += diff; - yfar += diff; - } - - if (fovx > cutoff) - { //just use ortho projection - origin.clearVec(); - mShadowError.mV[j] = -1.f; - proj[j] = gl_ortho(min.mV[0], max.mV[0], - min.mV[1], max.mV[1], - -max.mV[2], -min.mV[2]); - } - else - { - //get perspective projection - view[j] = view[j].inverse(); - //llassert(origin.isFinite()); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) + { + mShadowCamera[j+4] = shadow_cam; + } + } + } - glh::vec3f origin_agent(origin.mV); - - //translate view to origin - view[j].mult_matrix_vec(origin_agent); + //hack to disable projector shadows + bool gen_shadow = RenderShadowDetail > 1; - eye = LLVector3(origin_agent.v); - //llassert(eye.isFinite()); - if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowFrustOrigin[j] = eye; - } - - view[j] = look(LLVector3(origin_agent.v), lightDir, -up); - - F32 fx = 1.f/tanf(fovx); - F32 fz = 1.f/tanf(fovz); - - proj[j] = glh::matrix4f(-fx, 0, 0, 0, - 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar), - 0, 0, -fz, 0, - 0, -1.f, 0, 0); - } - } - } - - //shadow_cam.setFar(128.f); - shadow_cam.setOriginAndLookAt(eye, up, center); - - shadow_cam.setOrigin(0,0,0); - - set_current_modelview(view[j]); - set_current_projection(proj[j]); - - LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - - //shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); - shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_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); - - set_current_modelview(view[j]); - set_current_projection(proj[j]); - - for (U32 i = 0; i < 16; i++) - { - gGLLastModelView[i] = mShadowModelview[j].m[i]; - gGLLastProjection[i] = mShadowProjection[j].m[i]; - } - - mShadowModelview[j] = view[j]; - mShadowProjection[j] = proj[j]; - mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; - - stop_glerror(); - - mRT->shadow[j].bindTarget(); - mRT->shadow[j].getViewport(gGLViewport); - mRT->shadow[j].clear(); - - { - static LLCullResult result[4]; - renderShadow(view[j], proj[j], shadow_cam, result[j], true); - } - - mRT->shadow[j].flush(); - - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) - { - mShadowCamera[j+4] = shadow_cam; - } - } - } - - //hack to disable projector shadows - bool gen_shadow = RenderShadowDetail > 1; - - if (gen_shadow) - { + if (gen_shadow) + { if (!gCubeSnapshot) //skip updating spot shadow maps during cubemap updates { LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); @@ -10072,7 +10072,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); // - + mSpotShadow[i].bindTarget(); mSpotShadow[i].getViewport(gGLViewport); mSpotShadow[i].clear(); @@ -10090,56 +10090,56 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mSpotShadow[i].flush(); } } - } - else - { //no spotlight shadows - mShadowSpotLight[0] = mShadowSpotLight[1] = NULL; - } + } + else + { //no spotlight shadows + mShadowSpotLight[0] = mShadowSpotLight[1] = NULL; + } - if (!CameraOffset) - { - set_current_modelview(saved_view); - set_current_projection(saved_proj); - } - else - { - set_current_modelview(view[1]); - set_current_projection(proj[1]); - gGL.loadMatrix(view[1].m); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.loadMatrix(proj[1].m); - gGL.matrixMode(LLRender::MM_MODELVIEW); - } - gGL.setColorMask(true, true); + if (!CameraOffset) + { + set_current_modelview(saved_view); + set_current_projection(saved_proj); + } + else + { + set_current_modelview(view[1]); + set_current_projection(proj[1]); + gGL.loadMatrix(view[1].m); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.loadMatrix(proj[1].m); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + gGL.setColorMask(true, true); - for (U32 i = 0; i < 16; i++) - { - gGLLastModelView[i] = last_modelview[i]; - gGLLastProjection[i] = last_projection[i]; - } + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = last_modelview[i]; + gGLLastProjection[i] = last_projection[i]; + } - popRenderTypeMask(); + popRenderTypeMask(); - if (!skip_avatar_update) - { - gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode()); - } + if (!skip_avatar_update) + { + gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode()); + } } void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, bool texture) { - for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) - { - LLSpatialGroup* group = *i; - if (!group->isDead() && - (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && - gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && - group->mDrawMap.find(type) != group->mDrawMap.end()) - { - pass->renderGroup(group,type,texture); - } - } + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + { + LLSpatialGroup* group = *i; + if (!group->isDead() && + (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && + gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) + { + pass->renderGroup(group,type,texture); + } + } } void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture) @@ -10187,8 +10187,8 @@ void LLPipeline::profileAvatar(LLVOAvatar* avatar, bool profile_attachments) avatar->readProfileQuery(5); // allow up to 5 frames of latency } - else - { + else + { // profile attachments one at a time LLVOAvatar::attachment_map_t::iterator iter; LLVOAvatar::attachment_map_t::iterator begin = avatar->mAttachmentPoints.begin(); @@ -10231,27 +10231,27 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; LL_PROFILE_GPU_ZONE("generateImpostor"); - LLGLState::checkStates(); - - static LLCullResult result; - result.clear(); - grabReferences(result); - - if (!avatar || !avatar->mDrawable) - { + LLGLState::checkStates(); + + static LLCullResult result; + result.clear(); + grabReferences(result); + + if (!avatar || !avatar->mDrawable) + { LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL; - return; - } + return; + } LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL; - assertInitialized(); + assertInitialized(); // previews can't be muted or impostered - bool visually_muted = !for_profile && !preview_avatar && avatar->isVisuallyMuted(); + bool visually_muted = !for_profile && !preview_avatar && avatar->isVisuallyMuted(); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is " << ( visually_muted ? "" : "not ") << "visually muted" << LL_ENDL; - bool too_complex = !for_profile && !preview_avatar && avatar->isTooComplex(); + bool too_complex = !for_profile && !preview_avatar && avatar->isTooComplex(); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is " << ( too_complex ? "" : "not ") << "too complex" << LL_ENDL; @@ -10261,12 +10261,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool if (visually_muted || too_complex) { // only show jelly doll geometry - andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, - LLPipeline::RENDER_TYPE_CONTROL_AV, - END_RENDER_TYPES); - } - else - { + andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_CONTROL_AV, + END_RENDER_TYPES); + } + else + { //hide world geometry clearRenderTypeMask( RENDER_TYPE_SKY, @@ -10285,25 +10285,25 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool RENDER_TYPE_HUD_PARTICLES, END_RENDER_TYPES ); - } - + } + if (specific_attachment && specific_attachment->isHUDAttachment()) { //enable HUD rendering setRenderTypeMask(RENDER_TYPE_HUD, END_RENDER_TYPES); } - S32 occlusion = sUseOcclusion; - sUseOcclusion = 0; + S32 occlusion = sUseOcclusion; + sUseOcclusion = 0; - sReflectionRender = ! sRenderDeferred; + sReflectionRender = ! sRenderDeferred; - sShadowRender = true; - sImpostorRender = true; + sShadowRender = true; + sImpostorRender = true; - LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); + LLViewerCamera* viewer_camera = LLViewerCamera::getInstance(); - { - markVisible(avatar->mDrawable, *viewer_camera); + { + markVisible(avatar->mDrawable, *viewer_camera); if (preview_avatar) { @@ -10376,70 +10376,70 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool } } } - } + } - stateSort(*LLViewerCamera::getInstance(), result); - - LLCamera camera = *viewer_camera; - LLVector2 tdim; - U32 resY = 0; - U32 resX = 0; + stateSort(*LLViewerCamera::getInstance(), result); + + LLCamera camera = *viewer_camera; + LLVector2 tdim; + U32 resY = 0; + U32 resX = 0; if (!preview_avatar) - { - const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); - LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - - camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); - - LLVector4a half_height; - half_height.setSub(ext[1], ext[0]); - half_height.mul(0.5f); - - LLVector4a left; - left.load3(camera.getLeftAxis().mV); - left.mul(left); - llassert(left.dot3(left).getF32() > F_APPROXIMATELY_ZERO); - left.normalize3fast(); - - LLVector4a up; - up.load3(camera.getUpAxis().mV); - up.mul(up); - llassert(up.dot3(up).getF32() > F_APPROXIMATELY_ZERO); - up.normalize3fast(); - - tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); - tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - - F32 distance = (pos-camera.getOrigin()).length(); - F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; - glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); - set_current_projection(persp); - gGL.loadMatrix(persp.m); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - glh::matrix4f mat; - camera.getOpenGLTransform(mat.m); - - mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; - - gGL.loadMatrix(mat.m); - set_current_modelview(mat); - - glClearColor(0.0f,0.0f,0.0f,0.0f); - gGL.setColorMask(true, true); - - // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); - - //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) - resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); - resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + { + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); + LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); + + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); + + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); + + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + llassert(left.dot3(left).getF32() > F_APPROXIMATELY_ZERO); + left.normalize3fast(); + + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + llassert(up.dot3(up).getF32() > F_APPROXIMATELY_ZERO); + up.normalize3fast(); + + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + + F32 distance = (pos-camera.getOrigin()).length(); + F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; + F32 aspect = tdim.mV[0]/tdim.mV[1]; + glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); + set_current_projection(persp); + gGL.loadMatrix(persp.m); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + glh::matrix4f mat; + camera.getOpenGLTransform(mat.m); + + mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + + gGL.loadMatrix(mat.m); + set_current_modelview(mat); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + gGL.setColorMask(true, true); + + // get the number of pixels per angle + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + + //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) + resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); + resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); if (!for_profile) { @@ -10463,14 +10463,14 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool avatar->mImpostor.bindTarget(); } - } + } - F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; - if (visually_muted || too_complex) - { //disable alpha masking for muted avatars (get whole skin silhouette) - LLDrawPoolAvatar::sMinimumAlpha = 0.f; - } + if (visually_muted || too_complex) + { //disable alpha masking for muted avatars (get whole skin silhouette) + LLDrawPoolAvatar::sMinimumAlpha = 0.f; + } if (preview_avatar || for_profile) { @@ -10479,91 +10479,91 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool renderGeomPostDeferred(camera); } else - { - avatar->mImpostor.clear(); - renderGeomDeferred(camera); + { + avatar->mImpostor.clear(); + renderGeomDeferred(camera); - renderGeomPostDeferred(camera); + renderGeomPostDeferred(camera); - // Shameless hack time: render it all again, - // this time writing the depth - // values we need to generate the alpha mask below - // while preserving the alpha-sorted color rendering - // from the previous pass - // - sImpostorRenderAlphaDepthPass = true; - // depth-only here... - // - gGL.setColorMask(false,false); - renderGeomPostDeferred(camera); + // Shameless hack time: render it all again, + // this time writing the depth + // values we need to generate the alpha mask below + // while preserving the alpha-sorted color rendering + // from the previous pass + // + sImpostorRenderAlphaDepthPass = true; + // depth-only here... + // + gGL.setColorMask(false,false); + renderGeomPostDeferred(camera); - sImpostorRenderAlphaDepthPass = false; + sImpostorRenderAlphaDepthPass = false; - } + } - LLDrawPoolAvatar::sMinimumAlpha = old_alpha; + LLDrawPoolAvatar::sMinimumAlpha = old_alpha; if (!for_profile) - { //create alpha mask based on depth buffer (grey out if muted) - if (LLPipeline::sRenderDeferred) - { - GLuint buff = GL_COLOR_ATTACHMENT0; - glDrawBuffers(1, &buff); - } - - LLGLDisable blend(GL_BLEND); - - if (visually_muted || too_complex) - { - gGL.setColorMask(true, true); - } - else - { - gGL.setColorMask(false, true); - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - - gGL.flush(); - - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - - static const F32 clip_plane = 0.99999f; - - gDebugProgram.bind(); - - if (visually_muted) - { // Visually muted avatar + { //create alpha mask based on depth buffer (grey out if muted) + if (LLPipeline::sRenderDeferred) + { + GLuint buff = GL_COLOR_ATTACHMENT0; + glDrawBuffers(1, &buff); + } + + LLGLDisable blend(GL_BLEND); + + if (visually_muted || too_complex) + { + gGL.setColorMask(true, true); + } + else + { + gGL.setColorMask(false, true); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + + gGL.flush(); + + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + + static const F32 clip_plane = 0.99999f; + + gDebugProgram.bind(); + + if (visually_muted) + { // Visually muted avatar LLColor4 muted_color(avatar->getMutedAVColor()); LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set solid color " << muted_color << LL_ENDL; - gGL.diffuseColor4fv( muted_color.mV ); - } - else if (!preview_avatar) - { //grey muted avatar + gGL.diffuseColor4fv( muted_color.mV ); + } + else if (!preview_avatar) + { //grey muted avatar LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set grey" << LL_ENDL; - gGL.diffuseColor4fv(LLColor4::pink.mV ); - } + gGL.diffuseColor4fv(LLColor4::pink.mV ); + } - gGL.begin(LLRender::QUADS); - gGL.vertex3f(-1, -1, clip_plane); - gGL.vertex3f(1, -1, clip_plane); - gGL.vertex3f(1, 1, clip_plane); - gGL.vertex3f(-1, 1, clip_plane); - gGL.end(); - gGL.flush(); + gGL.begin(LLRender::QUADS); + gGL.vertex3f(-1, -1, clip_plane); + gGL.vertex3f(1, -1, clip_plane); + gGL.vertex3f(1, 1, clip_plane); + gGL.vertex3f(-1, 1, clip_plane); + gGL.end(); + gGL.flush(); - gDebugProgram.unbind(); + gDebugProgram.unbind(); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - } + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + } if (!preview_avatar && !for_profile) { @@ -10571,16 +10571,16 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool avatar->setImpostorDim(tdim); } - sUseOcclusion = occlusion; - sReflectionRender = false; - sImpostorRender = false; - sShadowRender = false; - popRenderTypeMask(); + sUseOcclusion = occlusion; + sReflectionRender = false; + sImpostorRender = false; + sShadowRender = false; + popRenderTypeMask(); - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); if (!preview_avatar && !for_profile) { @@ -10589,33 +10589,33 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar, bool avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds; } - LLVertexBuffer::unbind(); - LLGLState::checkStates(); + LLVertexBuffer::unbind(); + LLGLState::checkStates(); } bool LLPipeline::hasRenderBatches(const U32 type) const { - return sCull->getRenderMapSize(type) > 0; + return sCull->getRenderMapSize(type) > 0; } LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) { - return sCull->beginRenderMap(type); + return sCull->beginRenderMap(type); } LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) { - return sCull->endRenderMap(type); + return sCull->endRenderMap(type); } LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() { - return sCull->beginAlphaGroups(); + return sCull->beginAlphaGroups(); } LLCullResult::sg_iterator LLPipeline::endAlphaGroups() { - return sCull->endAlphaGroups(); + return sCull->endAlphaGroups(); } LLCullResult::sg_iterator LLPipeline::beginRiggedAlphaGroups() @@ -10633,278 +10633,278 @@ bool LLPipeline::hasRenderType(const U32 type) const // STORM-365 : LLViewerJointAttachment::setAttachmentVisibility() is setting type to 0 to actually mean "do not render" // We then need to test that value here and return false to prevent attachment to render (in mouselook for instance) // TODO: reintroduce RENDER_TYPE_NONE in LLRenderTypeMask and initialize its mRenderTypeEnabled[RENDER_TYPE_NONE] to false explicitely - return (type == 0 ? false : mRenderTypeEnabled[type]); + return (type == 0 ? false : mRenderTypeEnabled[type]); } void LLPipeline::setRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - mRenderTypeEnabled[type] = true; - type = va_arg(args, U32); - } - va_end(args); + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = true; + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } } bool LLPipeline::hasAnyRenderType(U32 type, ...) const { - va_list args; + va_list args; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - if (mRenderTypeEnabled[type]) - { - return true; - } - type = va_arg(args, U32); - } - va_end(args); + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + return true; + } + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } - return false; + return false; } void LLPipeline::pushRenderTypeMask() { - std::string cur_mask; - cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); - mRenderTypeEnableStack.push(cur_mask); + std::string cur_mask; + cur_mask.assign((const char*) mRenderTypeEnabled, sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.push(cur_mask); } void LLPipeline::popRenderTypeMask() { - if (mRenderTypeEnableStack.empty()) - { - LL_ERRS() << "Depleted render type stack." << LL_ENDL; - } + if (mRenderTypeEnableStack.empty()) + { + LL_ERRS() << "Depleted render type stack." << LL_ENDL; + } - memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); - mRenderTypeEnableStack.pop(); + memcpy(mRenderTypeEnabled, mRenderTypeEnableStack.top().data(), sizeof(mRenderTypeEnabled)); + mRenderTypeEnableStack.pop(); } void LLPipeline::andRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; - bool tmp[NUM_RENDER_TYPES]; - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - tmp[i] = false; - } + bool tmp[NUM_RENDER_TYPES]; + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + tmp[i] = false; + } - va_start(args, type); - while (type < END_RENDER_TYPES) - { - if (mRenderTypeEnabled[type]) - { - tmp[type] = true; - } + va_start(args, type); + while (type < END_RENDER_TYPES) + { + if (mRenderTypeEnabled[type]) + { + tmp[type] = true; + } - type = va_arg(args, U32); - } - va_end(args); + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } - for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = tmp[i]; - } + for (U32 i = 0; i < LLPipeline::NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = tmp[i]; + } } void LLPipeline::clearRenderTypeMask(U32 type, ...) { - va_list args; + va_list args; + + va_start(args, type); + while (type < END_RENDER_TYPES) + { + mRenderTypeEnabled[type] = false; - va_start(args, type); - while (type < END_RENDER_TYPES) - { - mRenderTypeEnabled[type] = false; - - type = va_arg(args, U32); - } - va_end(args); + type = va_arg(args, U32); + } + va_end(args); - if (type > END_RENDER_TYPES) - { - LL_ERRS() << "Invalid render type." << LL_ENDL; - } + if (type > END_RENDER_TYPES) + { + LL_ERRS() << "Invalid render type." << LL_ENDL; + } } void LLPipeline::setAllRenderTypes() { - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = true; - } + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = true; + } } void LLPipeline::clearAllRenderTypes() { - for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) - { - mRenderTypeEnabled[i] = false; - } + for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) + { + mRenderTypeEnabled[i] = false; + } } void LLPipeline::addDebugBlip(const LLVector3& position, const LLColor4& color) { - DebugBlip blip(position, color); - mDebugBlips.push_back(blip); + DebugBlip blip(position, color); + mDebugBlips.push_back(blip); } void LLPipeline::hidePermanentObjects( std::vector& restoreList ) { - //This method is used to hide any vo's from the object list that may have - //the permanent flag set. - - U32 objCnt = gObjectList.getNumObjects(); - for (U32 i = 0; i < objCnt; ++i) - { - LLViewerObject* pObject = gObjectList.getObject(i); - if ( pObject && pObject->flagObjectPermanent() ) - { - LLDrawable *pDrawable = pObject->mDrawable; - - if ( pDrawable ) - { - restoreList.push_back( i ); - hideDrawable( pDrawable ); - } - } - } - - skipRenderingOfTerrain( true ); + //This method is used to hide any vo's from the object list that may have + //the permanent flag set. + + U32 objCnt = gObjectList.getNumObjects(); + for (U32 i = 0; i < objCnt; ++i) + { + LLViewerObject* pObject = gObjectList.getObject(i); + if ( pObject && pObject->flagObjectPermanent() ) + { + LLDrawable *pDrawable = pObject->mDrawable; + + if ( pDrawable ) + { + restoreList.push_back( i ); + hideDrawable( pDrawable ); + } + } + } + + skipRenderingOfTerrain( true ); } void LLPipeline::restorePermanentObjects( const std::vector& restoreList ) { - //This method is used to restore(unhide) any vo's from the object list that may have - //been hidden because their permanency flag was set. - - std::vector::const_iterator itCurrent = restoreList.begin(); - std::vector::const_iterator itEnd = restoreList.end(); - - U32 objCnt = gObjectList.getNumObjects(); - - while ( itCurrent != itEnd ) - { - U32 index = *itCurrent; - LLViewerObject* pObject = NULL; - if ( index < objCnt ) - { - pObject = gObjectList.getObject( index ); - } - if ( pObject ) - { - LLDrawable *pDrawable = pObject->mDrawable; - if ( pDrawable ) - { - pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); - unhideDrawable( pDrawable ); - } - } - ++itCurrent; - } - - skipRenderingOfTerrain( false ); + //This method is used to restore(unhide) any vo's from the object list that may have + //been hidden because their permanency flag was set. + + std::vector::const_iterator itCurrent = restoreList.begin(); + std::vector::const_iterator itEnd = restoreList.end(); + + U32 objCnt = gObjectList.getNumObjects(); + + while ( itCurrent != itEnd ) + { + U32 index = *itCurrent; + LLViewerObject* pObject = NULL; + if ( index < objCnt ) + { + pObject = gObjectList.getObject( index ); + } + if ( pObject ) + { + LLDrawable *pDrawable = pObject->mDrawable; + if ( pDrawable ) + { + pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); + unhideDrawable( pDrawable ); + } + } + ++itCurrent; + } + + skipRenderingOfTerrain( false ); } void LLPipeline::skipRenderingOfTerrain( bool flag ) { - pool_set_t::iterator iter = mPools.begin(); - while ( iter != mPools.end() ) - { - LLDrawPool* pPool = *iter; - U32 poolType = pPool->getType(); - if ( hasRenderType( pPool->getType() ) && poolType == LLDrawPool::POOL_TERRAIN ) - { - pPool->setSkipRenderFlag( flag ); - } - ++iter; - } + pool_set_t::iterator iter = mPools.begin(); + while ( iter != mPools.end() ) + { + LLDrawPool* pPool = *iter; + U32 poolType = pPool->getType(); + if ( hasRenderType( pPool->getType() ) && poolType == LLDrawPool::POOL_TERRAIN ) + { + pPool->setSkipRenderFlag( flag ); + } + ++iter; + } } void LLPipeline::hideObject( const LLUUID& id ) { - LLViewerObject *pVO = gObjectList.findObject( id ); - - if ( pVO ) - { - LLDrawable *pDrawable = pVO->mDrawable; - - if ( pDrawable ) - { - hideDrawable( pDrawable ); - } - } + LLViewerObject *pVO = gObjectList.findObject( id ); + + if ( pVO ) + { + LLDrawable *pDrawable = pVO->mDrawable; + + if ( pDrawable ) + { + hideDrawable( pDrawable ); + } + } } void LLPipeline::hideDrawable( LLDrawable *pDrawable ) { - pDrawable->setState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( pDrawable, LLDrawable::REBUILD_ALL); - //hide the children - LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); - for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++ ) - { - LLViewerObject* child = *iter; - LLDrawable* drawable = child->mDrawable; - if ( drawable ) - { - drawable->setState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( drawable, LLDrawable::REBUILD_ALL); - } - } + pDrawable->setState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( pDrawable, LLDrawable::REBUILD_ALL); + //hide the children + LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); + for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++ ) + { + LLViewerObject* child = *iter; + LLDrawable* drawable = child->mDrawable; + if ( drawable ) + { + drawable->setState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( drawable, LLDrawable::REBUILD_ALL); + } + } } void LLPipeline::unhideDrawable( LLDrawable *pDrawable ) { - pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( pDrawable, LLDrawable::REBUILD_ALL); - //restore children - LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); - for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - LLDrawable* drawable = child->mDrawable; - if ( drawable ) - { - drawable->clearState( LLDrawable::FORCE_INVISIBLE ); - markRebuild( drawable, LLDrawable::REBUILD_ALL); - } - } + pDrawable->clearState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( pDrawable, LLDrawable::REBUILD_ALL); + //restore children + LLViewerObject::const_child_list_t& child_list = pDrawable->getVObj()->getChildren(); + for ( LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + LLDrawable* drawable = child->mDrawable; + if ( drawable ) + { + drawable->clearState( LLDrawable::FORCE_INVISIBLE ); + markRebuild( drawable, LLDrawable::REBUILD_ALL); + } + } } void LLPipeline::restoreHiddenObject( const LLUUID& id ) { - LLViewerObject *pVO = gObjectList.findObject( id ); - - if ( pVO ) - { - LLDrawable *pDrawable = pVO->mDrawable; - if ( pDrawable ) - { - unhideDrawable( pDrawable ); - } - } + LLViewerObject *pVO = gObjectList.findObject( id ); + + if ( pVO ) + { + LLDrawable *pDrawable = pVO->mDrawable; + if ( pDrawable ) + { + unhideDrawable( pDrawable ); + } + } } void LLPipeline::skipRenderingShadows() diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bfa4009a0b..62eba72e81 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -1,25 +1,25 @@ -/** +/** * @file pipeline.h * @brief Rendering pipeline definitions * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -56,8 +56,8 @@ class LLSettingsSky; typedef enum e_avatar_skinning_method { - SKIN_METHOD_SOFTWARE, - SKIN_METHOD_VERTEX_PROGRAM + SKIN_METHOD_SOFTWARE, + SKIN_METHOD_VERTEX_PROGRAM } EAvatarSkinningMethod; bool compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here! @@ -93,43 +93,43 @@ extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_2D; class LLPipeline { public: - LLPipeline(); - ~LLPipeline(); + LLPipeline(); + ~LLPipeline(); - void destroyGL(); - void restoreGL(); - void requestResizeScreenTexture(); // set flag only, no work, safer for callbacks... + void destroyGL(); + void restoreGL(); + void requestResizeScreenTexture(); // set flag only, no work, safer for callbacks... void requestResizeShadowTexture(); // set flag only, no work, safer for callbacks... - void resizeScreenTexture(); + void resizeScreenTexture(); void resizeShadowTexture(); - void releaseGLBuffers(); - void releaseLUTBuffers(); - void releaseScreenBuffers(); + void releaseGLBuffers(); + void releaseLUTBuffers(); + void releaseScreenBuffers(); void releaseShadowBuffers(); - void createGLBuffers(); - void createLUTBuffers(); + void createGLBuffers(); + void createLUTBuffers(); - //allocate the largest screen buffer possible up to resX, resY - //returns true if full size buffer allocated, false if some other size is allocated - bool allocateScreenBuffer(U32 resX, U32 resY); + //allocate the largest screen buffer possible up to resX, resY + //returns true if full size buffer allocated, false if some other size is allocated + bool allocateScreenBuffer(U32 resX, U32 resY); - typedef enum { - FBO_SUCCESS_FULLRES = 0, - FBO_SUCCESS_LOWRES, - FBO_FAILURE - } eFBOStatus; + typedef enum { + FBO_SUCCESS_FULLRES = 0, + FBO_SUCCESS_LOWRES, + FBO_FAILURE + } eFBOStatus; private: - //implementation of above, wrapped for easy error handling - eFBOStatus doAllocateScreenBuffer(U32 resX, U32 resY); + //implementation of above, wrapped for easy error handling + eFBOStatus doAllocateScreenBuffer(U32 resX, U32 resY); public: - //attempt to allocate screen buffers at resX, resY - //returns true if allocation successful, false otherwise - bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); + //attempt to allocate screen buffers at resX, resY + //returns true if allocation successful, false otherwise + bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); bool allocateShadowBuffer(U32 resX, U32 resY); // rebuild all LLVOVolume render batches @@ -138,7 +138,7 @@ public: void rebuildTerrain(); // Clear LLFace mVertexBuffer pointers - void resetVertexBuffers(LLDrawable* drawable); + void resetVertexBuffers(LLDrawable* drawable); // perform a profile of the given avatar // if profile_attachments is true, run a profile for each attachment @@ -148,173 +148,173 @@ public: // preview_avatar - if true, a preview window render is being performed // for_profile - if true, a profile is being performed, do not update actual impostor // specific_attachment - specific attachment to profile, or nullptr to profile entire avatar - void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false, bool for_profile = false, LLViewerObject* specific_attachment = nullptr); - - void bindScreenToTexture(); - void renderFinalize(); - void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst); - void generateLuminance(LLRenderTarget* src, LLRenderTarget* dst); - void generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history = true); - void gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst); - void generateGlow(LLRenderTarget* src); - void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst); - void renderDoF(LLRenderTarget* src, LLRenderTarget* dst); - void copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst); - void combineGlow(LLRenderTarget* src, LLRenderTarget* dst); - void visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex); - - void init(); - void cleanup(); - bool isInit() { return mInitialized; }; - - /// @brief Get a draw pool from pool type (POOL_SIMPLE, POOL_MEDIA) and texture. - /// @return Draw pool, or NULL if not found. - LLDrawPool *findPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); - - /// @brief Get a draw pool for faces of the appropriate type and texture. Create if necessary. - /// @return Always returns a draw pool. - LLDrawPool *getPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); - - /// @brief Figures out draw pool type from texture entry. Creates pool if necessary. - static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* te_image); - static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep); - - void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools! - void removePool( LLDrawPool* poolp ); - - void allocDrawable(LLViewerObject *obj); - - void unlinkDrawable(LLDrawable*); - - static void removeMutedAVsLights(LLVOAvatar*); - - // Object related methods - void markVisible(LLDrawable *drawablep, LLCamera& camera); - void markOccluder(LLSpatialGroup* group); - - void doOcclusion(LLCamera& camera); - void markNotCulled(LLSpatialGroup* group, LLCamera &camera); - void markMoved(LLDrawable *drawablep, bool damped_motion = false); - void markShift(LLDrawable *drawablep); - void markTextured(LLDrawable *drawablep); - void markGLRebuild(LLGLUpdate* glu); - void markRebuild(LLSpatialGroup* group); - void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL); - void markPartitionMove(LLDrawable* drawablep); - void markMeshDirty(LLSpatialGroup* group); - - //get the object between start and end that's closest to start. - LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - bool pick_rigged, + void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false, bool for_profile = false, LLViewerObject* specific_attachment = nullptr); + + void bindScreenToTexture(); + void renderFinalize(); + void copyScreenSpaceReflections(LLRenderTarget* src, LLRenderTarget* dst); + void generateLuminance(LLRenderTarget* src, LLRenderTarget* dst); + void generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool use_history = true); + void gammaCorrect(LLRenderTarget* src, LLRenderTarget* dst); + void generateGlow(LLRenderTarget* src); + void applyFXAA(LLRenderTarget* src, LLRenderTarget* dst); + void renderDoF(LLRenderTarget* src, LLRenderTarget* dst); + void copyRenderTarget(LLRenderTarget* src, LLRenderTarget* dst); + void combineGlow(LLRenderTarget* src, LLRenderTarget* dst); + void visualizeBuffers(LLRenderTarget* src, LLRenderTarget* dst, U32 bufferIndex); + + void init(); + void cleanup(); + bool isInit() { return mInitialized; }; + + /// @brief Get a draw pool from pool type (POOL_SIMPLE, POOL_MEDIA) and texture. + /// @return Draw pool, or NULL if not found. + LLDrawPool *findPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); + + /// @brief Get a draw pool for faces of the appropriate type and texture. Create if necessary. + /// @return Always returns a draw pool. + LLDrawPool *getPool(const U32 pool_type, LLViewerTexture *tex0 = NULL); + + /// @brief Figures out draw pool type from texture entry. Creates pool if necessary. + static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerTexture* te_image); + static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* imagep); + + void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools! + void removePool( LLDrawPool* poolp ); + + void allocDrawable(LLViewerObject *obj); + + void unlinkDrawable(LLDrawable*); + + static void removeMutedAVsLights(LLVOAvatar*); + + // Object related methods + void markVisible(LLDrawable *drawablep, LLCamera& camera); + void markOccluder(LLSpatialGroup* group); + + void doOcclusion(LLCamera& camera); + void markNotCulled(LLSpatialGroup* group, LLCamera &camera); + void markMoved(LLDrawable *drawablep, bool damped_motion = false); + void markShift(LLDrawable *drawablep); + void markTextured(LLDrawable *drawablep); + void markGLRebuild(LLGLUpdate* glu); + void markRebuild(LLSpatialGroup* group); + void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL); + void markPartitionMove(LLDrawable* drawablep); + void markMeshDirty(LLSpatialGroup* group); + + //get the object between start and end that's closest to start. + LLViewerObject* lineSegmentIntersectInWorld(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + bool pick_rigged, bool pick_unselectable, bool pick_reflection_probe, - S32* face_hit, // return the face hit + S32* face_hit, // return the face hit S32* gltf_node_hit = nullptr, // return the gltf node hit S32* gltf_primitive_hit = nullptr, // return the gltf primitive hit - LLVector4a* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); + LLVector4a* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); - //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index - LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, - S32* face_hit); + //get the closest particle to start between start and end, returns the LLVOPartGroup and particle index + LLVOPartGroup* lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, + S32* face_hit); - LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, - bool pick_transparent, - 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 - LLVector4a* normal = NULL, // return the surface normal at the intersection point - LLVector4a* tangent = NULL // return the surface tangent at the intersection point - ); + LLViewerObject* lineSegmentIntersectInHUD(const LLVector4a& start, const LLVector4a& end, + bool pick_transparent, + 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 + LLVector4a* normal = NULL, // return the surface normal at the intersection point + LLVector4a* tangent = NULL // return the surface tangent at the intersection point + ); - // Something about these textures has changed. Dirty them. - void dirtyPoolObjectTextures(const std::set& textures); + // Something about these textures has changed. Dirty them. + void dirtyPoolObjectTextures(const std::set& textures); - void resetDrawOrders(); + void resetDrawOrders(); - U32 addObject(LLViewerObject *obj); + U32 addObject(LLViewerObject *obj); - void enableShadows(const bool enable_shadows); + void enableShadows(const bool enable_shadows); void releaseSpotShadowTargets(); void releaseSunShadowTargets(); void releaseSunShadowTarget(U32 index); - bool shadersLoaded(); - bool canUseWindLightShaders() const; - bool canUseAntiAliasing() const; + bool shadersLoaded(); + bool canUseWindLightShaders() const; + bool canUseAntiAliasing() const; - // phases - void resetFrameStats(); + // phases + void resetFrameStats(); - void updateMoveDampedAsync(LLDrawable* drawablep); - void updateMoveNormalAsync(LLDrawable* drawablep); - void updateMovedList(LLDrawable::drawable_vector_t& move_list); - void updateMove(); - bool visibleObjectsInFrustum(LLCamera& camera); - bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); - bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); + void updateMoveDampedAsync(LLDrawable* drawablep); + void updateMoveNormalAsync(LLDrawable* drawablep); + void updateMovedList(LLDrawable::drawable_vector_t& move_list); + void updateMove(); + bool visibleObjectsInFrustum(LLCamera& camera); + bool getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); + bool getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); // Populate given LLCullResult with results of a frustum cull of the entire scene against the given LLCamera - void updateCull(LLCamera& camera, LLCullResult& result); - void createObjects(F32 max_dtime); - void createObject(LLViewerObject* vobj); - void processPartitionQ(); - void updateGeom(F32 max_dtime); - void updateGL(); - void rebuildPriorityGroups(); - void rebuildGroups(); - void clearRebuildGroups(); - void clearRebuildDrawables(); - - //calculate pixel area of given box from vantage point of given camera - static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); - static F32 calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera); - - void stateSort(LLCamera& camera, LLCullResult& result); - void stateSort(LLSpatialGroup* group, LLCamera& camera); - void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); - void stateSort(LLDrawable* drawablep, LLCamera& camera); - void postSort(LLCamera& camera); - - void forAllVisibleDrawables(void (*func)(LLDrawable*)); + void updateCull(LLCamera& camera, LLCullResult& result); + void createObjects(F32 max_dtime); + void createObject(LLViewerObject* vobj); + void processPartitionQ(); + void updateGeom(F32 max_dtime); + void updateGL(); + void rebuildPriorityGroups(); + void rebuildGroups(); + void clearRebuildGroups(); + void clearRebuildDrawables(); + + //calculate pixel area of given box from vantage point of given camera + static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); + static F32 calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera); + + void stateSort(LLCamera& camera, LLCullResult& result); + void stateSort(LLSpatialGroup* group, LLCamera& camera); + void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE); + void stateSort(LLDrawable* drawablep, LLCamera& camera); + void postSort(LLCamera& camera); + + void forAllVisibleDrawables(void (*func)(LLDrawable*)); void renderObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false); void renderGLTFObjects(U32 type, bool texture = true, bool rigged = false); - + void renderAlphaObjects(bool rigged = false); - void renderMaskedObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false); + void renderMaskedObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false); void renderFullbrightMaskedObjects(U32 type, bool texture = true, bool batch_texture = false, bool rigged = false); - void renderGroups(LLRenderPass* pass, U32 type, bool texture); + void renderGroups(LLRenderPass* pass, U32 type, bool texture); void renderRiggedGroups(LLRenderPass* pass, U32 type, bool texture); - void grabReferences(LLCullResult& result); - void clearReferences(); - - //check references will assert that there are no references in sCullResult to the provided data - void checkReferences(LLFace* face); - void checkReferences(LLDrawable* drawable); - void checkReferences(LLDrawInfo* draw_info); - void checkReferences(LLSpatialGroup* group); - - void renderGeomDeferred(LLCamera& camera, bool do_occlusion = false); - void renderGeomPostDeferred(LLCamera& camera); - void renderGeomShadow(LLCamera& camera); + void grabReferences(LLCullResult& result); + void clearReferences(); + + //check references will assert that there are no references in sCullResult to the provided data + void checkReferences(LLFace* face); + void checkReferences(LLDrawable* drawable); + void checkReferences(LLDrawInfo* draw_info); + void checkReferences(LLSpatialGroup* group); + + void renderGeomDeferred(LLCamera& camera, bool do_occlusion = false); + void renderGeomPostDeferred(LLCamera& camera); + void renderGeomShadow(LLCamera& camera); void bindLightFunc(LLGLSLShader& shader); // bind shadow maps // if setup is true, wil lset texture compare mode function and filtering options void bindShadowMaps(LLGLSLShader& shader); void bindDeferredShaderFast(LLGLSLShader& shader); - void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr, LLRenderTarget* depth_target = nullptr); - void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); + void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr, LLRenderTarget* depth_target = nullptr); + void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); - void unbindDeferredShader(LLGLSLShader& shader); + void unbindDeferredShader(LLGLSLShader& shader); // set env_mat parameter in given shader void setEnvMat(LLGLSLShader& shader); @@ -322,10 +322,10 @@ public: void bindReflectionProbes(LLGLSLShader& shader); void unbindReflectionProbes(LLGLSLShader& shader); - void renderDeferredLighting(); + void renderDeferredLighting(); // apply atmospheric haze based on contents of color and depth buffer - // should be called just before rendering water when camera is under water + // should be called just before rendering water when camera is under water // and just before rendering alpha when camera is above water void doAtmospherics(); @@ -333,367 +333,367 @@ public: // should be called just before rendering pre-water alpha objects void doWaterHaze(); - void postDeferredGammaCorrect(LLRenderTarget* screen_target); + void postDeferredGammaCorrect(LLRenderTarget* screen_target); - void generateSunShadow(LLCamera& camera); + void generateSunShadow(LLCamera& camera); LLRenderTarget* getSunShadowTarget(U32 i); LLRenderTarget* getSpotShadowTarget(U32 i); - void renderHighlight(const LLViewerObject* obj, F32 fade); - - void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool depth_clamp); - void renderHighlights(); - void renderDebug(); - void renderPhysicsDisplay(); - - void rebuildPools(); // Rebuild pools - - void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object - bool verify(); // Verify that all data in the pipeline is "correct" - - S32 getLightCount() const { return mLights.size(); } - - void calcNearbyLights(LLCamera& camera); - void setupHWLights(); - void setupAvatarLights(bool for_edit = false); - void enableLights(U32 mask); - void enableLightsDynamic(); - void enableLightsAvatar(); - void enableLightsPreview(); - void enableLightsAvatarEdit(const LLColor4& color); - void enableLightsFullbright(); - void disableLights(); - - void shiftObjects(const LLVector3 &offset); - - void setLight(LLDrawable *drawablep, bool is_light); - - bool hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_iterator endRenderMap(U32 type); - LLCullResult::sg_iterator beginAlphaGroups(); - LLCullResult::sg_iterator endAlphaGroups(); + void renderHighlight(const LLViewerObject* obj, F32 fade); + + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, bool depth_clamp); + void renderHighlights(); + void renderDebug(); + void renderPhysicsDisplay(); + + void rebuildPools(); // Rebuild pools + + void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object + bool verify(); // Verify that all data in the pipeline is "correct" + + S32 getLightCount() const { return mLights.size(); } + + void calcNearbyLights(LLCamera& camera); + void setupHWLights(); + void setupAvatarLights(bool for_edit = false); + void enableLights(U32 mask); + void enableLightsDynamic(); + void enableLightsAvatar(); + void enableLightsPreview(); + void enableLightsAvatarEdit(const LLColor4& color); + void enableLightsFullbright(); + void disableLights(); + + void shiftObjects(const LLVector3 &offset); + + void setLight(LLDrawable *drawablep, bool is_light); + + bool hasRenderBatches(const U32 type) const; + LLCullResult::drawinfo_iterator beginRenderMap(U32 type); + LLCullResult::drawinfo_iterator endRenderMap(U32 type); + LLCullResult::sg_iterator beginAlphaGroups(); + LLCullResult::sg_iterator endAlphaGroups(); LLCullResult::sg_iterator beginRiggedAlphaGroups(); LLCullResult::sg_iterator endRiggedAlphaGroups(); - - void addTrianglesDrawn(S32 index_count); + + void addTrianglesDrawn(S32 index_count); void recordTrianglesDrawn(); - bool hasRenderDebugFeatureMask(const U32 mask) const { return bool(mRenderDebugFeatureMask & mask); } - bool hasRenderDebugMask(const U64 mask) const { return bool(mRenderDebugMask & mask); } - void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } - void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } - void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffffffffffff; } - void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } - - bool hasRenderType(const U32 type) const; - bool hasAnyRenderType(const U32 type, ...) const; - - static bool isWaterClip(); - - void setRenderTypeMask(U32 type, ...); - // This is equivalent to 'setRenderTypeMask' - //void orRenderTypeMask(U32 type, ...); - void andRenderTypeMask(U32 type, ...); - void clearRenderTypeMask(U32 type, ...); - void setAllRenderTypes(); - void clearAllRenderTypes(); - - void pushRenderTypeMask(); - void popRenderTypeMask(); - - void pushRenderDebugFeatureMask(); - void popRenderDebugFeatureMask(); - - static void toggleRenderType(U32 type); - - // For UI control of render features - static bool hasRenderTypeControl(U32 data); - static void toggleRenderDebug(U64 data); - static void toggleRenderDebugFeature(U32 data); - static void toggleRenderTypeControl(U32 data); - static bool toggleRenderTypeControlNegated(S32 data); - static bool toggleRenderDebugControl(U64 data); - static bool toggleRenderDebugFeatureControl(U32 data); - static void setRenderDebugFeatureControl(U32 bit, bool value); - - static void setRenderParticleBeacons(bool val); - static void toggleRenderParticleBeacons(); - static bool getRenderParticleBeacons(); - - static void setRenderSoundBeacons(bool val); - static void toggleRenderSoundBeacons(); - static bool getRenderSoundBeacons(); - - static void setRenderMOAPBeacons(bool val); - static void toggleRenderMOAPBeacons(); - static bool getRenderMOAPBeacons(); - - static void setRenderPhysicalBeacons(bool val); - static void toggleRenderPhysicalBeacons(); - static bool getRenderPhysicalBeacons(); - - static void setRenderScriptedBeacons(bool val); - static void toggleRenderScriptedBeacons(); - static bool getRenderScriptedBeacons(); - - static void setRenderScriptedTouchBeacons(bool val); - static void toggleRenderScriptedTouchBeacons(); - static bool getRenderScriptedTouchBeacons(); - - static void setRenderBeacons(bool val); - static void toggleRenderBeacons(); - static bool getRenderBeacons(); - - static void setRenderHighlights(bool val); - static void toggleRenderHighlights(); - static bool getRenderHighlights(); - static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay - - static void updateRenderTransparentWater(); - static void refreshCachedSettings(); - - void addDebugBlip(const LLVector3& position, const LLColor4& color); - - void hidePermanentObjects( std::vector& restoreList ); - void restorePermanentObjects( const std::vector& restoreList ); - void skipRenderingOfTerrain( bool flag ); - void hideObject( const LLUUID& id ); - void restoreHiddenObject( const LLUUID& id ); + bool hasRenderDebugFeatureMask(const U32 mask) const { return bool(mRenderDebugFeatureMask & mask); } + bool hasRenderDebugMask(const U64 mask) const { return bool(mRenderDebugMask & mask); } + void setAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0xffffffff; } + void clearAllRenderDebugFeatures() { mRenderDebugFeatureMask = 0x0; } + void setAllRenderDebugDisplays() { mRenderDebugMask = 0xffffffffffffffff; } + void clearAllRenderDebugDisplays() { mRenderDebugMask = 0x0; } + + bool hasRenderType(const U32 type) const; + bool hasAnyRenderType(const U32 type, ...) const; + + static bool isWaterClip(); + + void setRenderTypeMask(U32 type, ...); + // This is equivalent to 'setRenderTypeMask' + //void orRenderTypeMask(U32 type, ...); + void andRenderTypeMask(U32 type, ...); + void clearRenderTypeMask(U32 type, ...); + void setAllRenderTypes(); + void clearAllRenderTypes(); + + void pushRenderTypeMask(); + void popRenderTypeMask(); + + void pushRenderDebugFeatureMask(); + void popRenderDebugFeatureMask(); + + static void toggleRenderType(U32 type); + + // For UI control of render features + static bool hasRenderTypeControl(U32 data); + static void toggleRenderDebug(U64 data); + static void toggleRenderDebugFeature(U32 data); + static void toggleRenderTypeControl(U32 data); + static bool toggleRenderTypeControlNegated(S32 data); + static bool toggleRenderDebugControl(U64 data); + static bool toggleRenderDebugFeatureControl(U32 data); + static void setRenderDebugFeatureControl(U32 bit, bool value); + + static void setRenderParticleBeacons(bool val); + static void toggleRenderParticleBeacons(); + static bool getRenderParticleBeacons(); + + static void setRenderSoundBeacons(bool val); + static void toggleRenderSoundBeacons(); + static bool getRenderSoundBeacons(); + + static void setRenderMOAPBeacons(bool val); + static void toggleRenderMOAPBeacons(); + static bool getRenderMOAPBeacons(); + + static void setRenderPhysicalBeacons(bool val); + static void toggleRenderPhysicalBeacons(); + static bool getRenderPhysicalBeacons(); + + static void setRenderScriptedBeacons(bool val); + static void toggleRenderScriptedBeacons(); + static bool getRenderScriptedBeacons(); + + static void setRenderScriptedTouchBeacons(bool val); + static void toggleRenderScriptedTouchBeacons(); + static bool getRenderScriptedTouchBeacons(); + + static void setRenderBeacons(bool val); + static void toggleRenderBeacons(); + static bool getRenderBeacons(); + + static void setRenderHighlights(bool val); + static void toggleRenderHighlights(); + static bool getRenderHighlights(); + static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay + + static void updateRenderTransparentWater(); + static void refreshCachedSettings(); + + void addDebugBlip(const LLVector3& position, const LLColor4& color); + + void hidePermanentObjects( std::vector& restoreList ); + void restorePermanentObjects( const std::vector& restoreList ); + void skipRenderingOfTerrain( bool flag ); + void hideObject( const LLUUID& id ); + void restoreHiddenObject( const LLUUID& id ); void handleShadowDetailChanged(); LLReflectionMapManager mReflectionMapManager; LLHeroProbeManager mHeroProbeManager; private: - void unloadShaders(); - void addToQuickLookup( LLDrawPool* new_poolp ); - void removeFromQuickLookup( LLDrawPool* poolp ); - bool updateDrawableGeom(LLDrawable* drawable); - void assertInitializedDoError(); - bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; - void connectRefreshCachedSettingsSafe(const std::string name); - void hideDrawable( LLDrawable *pDrawable ); - void unhideDrawable( LLDrawable *pDrawable ); + void unloadShaders(); + void addToQuickLookup( LLDrawPool* new_poolp ); + void removeFromQuickLookup( LLDrawPool* poolp ); + bool updateDrawableGeom(LLDrawable* drawable); + void assertInitializedDoError(); + bool assertInitialized() { const bool is_init = isInit(); if (!is_init) assertInitializedDoError(); return is_init; }; + void connectRefreshCachedSettingsSafe(const std::string name); + void hideDrawable( LLDrawable *pDrawable ); + void unhideDrawable( LLDrawable *pDrawable ); void skipRenderingShadows(); public: - enum {GPU_CLASS_MAX = 3 }; - - enum LLRenderTypeMask - { - // Following are pool types (some are also object types) - RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, - RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, - RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, - RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, - RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, - RENDER_TYPE_ALPHA_MASK = LLDrawPool::POOL_ALPHA_MASK, - RENDER_TYPE_FULLBRIGHT_ALPHA_MASK = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK, - RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, - RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, - RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, - RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, - RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh - RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, - RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, - RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, + enum {GPU_CLASS_MAX = 3 }; + + enum LLRenderTypeMask + { + // Following are pool types (some are also object types) + RENDER_TYPE_SKY = LLDrawPool::POOL_SKY, + RENDER_TYPE_WL_SKY = LLDrawPool::POOL_WL_SKY, + RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, + RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, + RENDER_TYPE_GRASS = LLDrawPool::POOL_GRASS, + RENDER_TYPE_ALPHA_MASK = LLDrawPool::POOL_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT_ALPHA_MASK = LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_FULLBRIGHT = LLDrawPool::POOL_FULLBRIGHT, + RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, + RENDER_TYPE_MATERIALS = LLDrawPool::POOL_MATERIALS, + RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, + RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh + RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, + RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, + RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, RENDER_TYPE_GLTF_PBR = LLDrawPool::POOL_GLTF_PBR, RENDER_TYPE_GLTF_PBR_ALPHA_MASK = LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK, - RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, + RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, RENDER_TYPE_ALPHA_PRE_WATER = LLDrawPool::POOL_ALPHA_PRE_WATER, RENDER_TYPE_ALPHA_POST_WATER = LLDrawPool::POOL_ALPHA_POST_WATER, - RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, - RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, + RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW, + RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE, RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED, - RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, - RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, + RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, + RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT_RIGGED, - RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, + RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, RENDER_TYPE_PASS_INVISIBLE_RIGGED = LLRenderPass::PASS_INVISIBLE_RIGGED, - RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, + RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, RENDER_TYPE_PASS_INVISI_SHINY_RIGGED = LLRenderPass::PASS_INVISI_SHINY_RIGGED, - RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, + RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY, RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED = LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, - RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, + RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY, RENDER_TYPE_PASS_SHINY_RIGGED = LLRenderPass::PASS_SHINY_RIGGED, - RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, + RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP, RENDER_TYPE_PASS_BUMP_RIGGED = LLRenderPass::PASS_BUMP_RIGGED, - RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, + RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP, RENDER_TYPE_PASS_POST_BUMP_RIGGED = LLRenderPass::PASS_POST_BUMP_RIGGED, - RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, + RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW, RENDER_TYPE_PASS_GLOW_RIGGED = LLRenderPass::PASS_GLOW_RIGGED, RENDER_TYPE_PASS_GLTF_GLOW = LLRenderPass::PASS_GLTF_GLOW, RENDER_TYPE_PASS_GLTF_GLOW_RIGGED = LLRenderPass::PASS_GLTF_GLOW_RIGGED, - RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, - RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, + RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA, + RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK, RENDER_TYPE_PASS_ALPHA_MASK_RIGGED = LLRenderPass::PASS_ALPHA_MASK_RIGGED, - RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, + RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, - RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, + RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL, RENDER_TYPE_PASS_MATERIAL_RIGGED = LLRenderPass::PASS_MATERIAL_RIGGED, - RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, + RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA, RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_RIGGED, - RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, + RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK, RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, - RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, + RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, - RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, + RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP, RENDER_TYPE_PASS_SPECMAP_RIGGED = LLRenderPass::PASS_SPECMAP_RIGGED, - RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, + RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND, RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED = LLRenderPass::PASS_SPECMAP_BLEND_RIGGED, - RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, + RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK, RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED = LLRenderPass::PASS_SPECMAP_MASK_RIGGED, - RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, + RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE, RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, - RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, + RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP, RENDER_TYPE_PASS_NORMMAP_RIGGED = LLRenderPass::PASS_NORMMAP_RIGGED, - RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, + RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND, RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED = LLRenderPass::PASS_NORMMAP_BLEND_RIGGED, - RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, + RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK, RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED = LLRenderPass::PASS_NORMMAP_MASK_RIGGED, - RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, + RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE, RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, - RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, + RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC, RENDER_TYPE_PASS_NORMSPEC_RIGGED = LLRenderPass::PASS_NORMSPEC_RIGGED, - RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, + RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND, RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED = LLRenderPass::PASS_NORMSPEC_BLEND_RIGGED, - RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, + RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK, RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, - RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, + RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE, RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, RENDER_TYPE_PASS_GLTF_PBR = LLRenderPass::PASS_GLTF_PBR, RENDER_TYPE_PASS_GLTF_PBR_RIGGED = LLRenderPass::PASS_GLTF_PBR_RIGGED, RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK, RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK_RIGGED = LLRenderPass::PASS_GLTF_PBR_ALPHA_MASK_RIGGED, - // Following are object types (only used in drawable mRenderType) - RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, - RENDER_TYPE_VOLUME, - RENDER_TYPE_PARTICLES, - RENDER_TYPE_CLOUDS, - RENDER_TYPE_HUD_PARTICLES, - NUM_RENDER_TYPES, - END_RENDER_TYPES = NUM_RENDER_TYPES - }; - - enum LLRenderDebugFeatureMask - { - RENDER_DEBUG_FEATURE_UI = 0x0001, - RENDER_DEBUG_FEATURE_SELECTED = 0x0002, - RENDER_DEBUG_FEATURE_HIGHLIGHTED = 0x0004, - RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES = 0x0008, -// RENDER_DEBUG_FEATURE_HW_LIGHTING = 0x0010, - RENDER_DEBUG_FEATURE_FLEXIBLE = 0x0010, - RENDER_DEBUG_FEATURE_FOG = 0x0020, - RENDER_DEBUG_FEATURE_FR_INFO = 0x0080, - RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100, - }; - - enum LLRenderDebugMask: U64 - { - RENDER_DEBUG_COMPOSITION = 0x00000001, - RENDER_DEBUG_VERIFY = 0x00000002, - RENDER_DEBUG_BBOXES = 0x00000004, - RENDER_DEBUG_OCTREE = 0x00000008, - RENDER_DEBUG_WIND_VECTORS = 0x00000010, - RENDER_DEBUG_OCCLUSION = 0x00000020, - RENDER_DEBUG_POINTS = 0x00000040, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080, - RENDER_DEBUG_TEXTURE_AREA = 0x00000100, - RENDER_DEBUG_FACE_AREA = 0x00000200, - RENDER_DEBUG_PARTICLES = 0x00000400, - RENDER_DEBUG_GLOW = 0x00000800, // not used - RENDER_DEBUG_TEXTURE_ANIM = 0x00001000, - RENDER_DEBUG_LIGHTS = 0x00002000, - RENDER_DEBUG_BATCH_SIZE = 0x00004000, - RENDER_DEBUG_ALPHA_BINS = 0x00008000, // not used - RENDER_DEBUG_RAYCAST = 0x00010000, - RENDER_DEBUG_AVATAR_DRAW_INFO = 0x00020000, - RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000, - RENDER_DEBUG_SCULPTED = 0x00080000, - RENDER_DEBUG_AVATAR_VOLUME = 0x00100000, - RENDER_DEBUG_AVATAR_JOINTS = 0x00200000, - RENDER_DEBUG_AGENT_TARGET = 0x00800000, - RENDER_DEBUG_UPDATE_TYPE = 0x01000000, - RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000, - RENDER_DEBUG_NORMALS = 0x04000000, - RENDER_DEBUG_LOD_INFO = 0x08000000, + // Following are object types (only used in drawable mRenderType) + RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES, + RENDER_TYPE_VOLUME, + RENDER_TYPE_PARTICLES, + RENDER_TYPE_CLOUDS, + RENDER_TYPE_HUD_PARTICLES, + NUM_RENDER_TYPES, + END_RENDER_TYPES = NUM_RENDER_TYPES + }; + + enum LLRenderDebugFeatureMask + { + RENDER_DEBUG_FEATURE_UI = 0x0001, + RENDER_DEBUG_FEATURE_SELECTED = 0x0002, + RENDER_DEBUG_FEATURE_HIGHLIGHTED = 0x0004, + RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES = 0x0008, +// RENDER_DEBUG_FEATURE_HW_LIGHTING = 0x0010, + RENDER_DEBUG_FEATURE_FLEXIBLE = 0x0010, + RENDER_DEBUG_FEATURE_FOG = 0x0020, + RENDER_DEBUG_FEATURE_FR_INFO = 0x0080, + RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100, + }; + + enum LLRenderDebugMask: U64 + { + RENDER_DEBUG_COMPOSITION = 0x00000001, + RENDER_DEBUG_VERIFY = 0x00000002, + RENDER_DEBUG_BBOXES = 0x00000004, + RENDER_DEBUG_OCTREE = 0x00000008, + RENDER_DEBUG_WIND_VECTORS = 0x00000010, + RENDER_DEBUG_OCCLUSION = 0x00000020, + RENDER_DEBUG_POINTS = 0x00000040, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080, + RENDER_DEBUG_TEXTURE_AREA = 0x00000100, + RENDER_DEBUG_FACE_AREA = 0x00000200, + RENDER_DEBUG_PARTICLES = 0x00000400, + RENDER_DEBUG_GLOW = 0x00000800, // not used + RENDER_DEBUG_TEXTURE_ANIM = 0x00001000, + RENDER_DEBUG_LIGHTS = 0x00002000, + RENDER_DEBUG_BATCH_SIZE = 0x00004000, + RENDER_DEBUG_ALPHA_BINS = 0x00008000, // not used + RENDER_DEBUG_RAYCAST = 0x00010000, + RENDER_DEBUG_AVATAR_DRAW_INFO = 0x00020000, + RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000, + RENDER_DEBUG_SCULPTED = 0x00080000, + RENDER_DEBUG_AVATAR_VOLUME = 0x00100000, + RENDER_DEBUG_AVATAR_JOINTS = 0x00200000, + RENDER_DEBUG_AGENT_TARGET = 0x00800000, + RENDER_DEBUG_UPDATE_TYPE = 0x01000000, + RENDER_DEBUG_PHYSICS_SHAPES = 0x02000000, + RENDER_DEBUG_NORMALS = 0x04000000, + RENDER_DEBUG_LOD_INFO = 0x08000000, RENDER_DEBUG_NODES = 0x20000000, - RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, - RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, - RENDER_DEBUG_IMPOSTORS = 0x100000000, + RENDER_DEBUG_TEXEL_DENSITY = 0x40000000, + RENDER_DEBUG_TRIANGLE_COUNT = 0x80000000, + RENDER_DEBUG_IMPOSTORS = 0x100000000, RENDER_DEBUG_REFLECTION_PROBES = 0x200000000, RENDER_DEBUG_PROBE_UPDATES = 0x400000000, - }; + }; public: - - LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj); - - void updateCamera(bool reset = false); - - LLVector3 mFlyCamPosition; - LLQuaternion mFlyCamRotation; - - bool mBackfaceCull; - S32 mMatrixOpCount; - S32 mTextureMatrixOps; - S32 mNumVisibleNodes; - - S32 mDebugTextureUploadCost; - S32 mDebugSculptUploadCost; - S32 mDebugMeshUploadCost; - - S32 mNumVisibleFaces; - - S32 mPoissonOffset; - - static S32 sCompiles; - - static bool sShowHUDAttachments; - static bool sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. - static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write - static bool sAutoMaskAlphaDeferred; - static bool sAutoMaskAlphaNonDeferred; - static bool sRenderTransparentWater; - static bool sBakeSunlight; - static bool sNoAlpha; - static bool sUseFarClip; - static bool sShadowRender; - static bool sDynamicLOD; - static bool sPickAvatar; - static bool sReflectionRender; - static bool sDistortionRender; - static bool sImpostorRender; - static bool sImpostorRenderAlphaDepthPass; - static bool sUnderWaterRender; - static bool sRenderGlow; - static bool sTextureBindTest; - static bool sRenderAttachedLights; - static bool sRenderAttachedParticles; - static bool sRenderDeferred; - static bool sReflectionProbesEnabled; - static S32 sVisibleLightCount; - static bool sRenderingHUDs; + + LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj); + + void updateCamera(bool reset = false); + + LLVector3 mFlyCamPosition; + LLQuaternion mFlyCamRotation; + + bool mBackfaceCull; + S32 mMatrixOpCount; + S32 mTextureMatrixOps; + S32 mNumVisibleNodes; + + S32 mDebugTextureUploadCost; + S32 mDebugSculptUploadCost; + S32 mDebugMeshUploadCost; + + S32 mNumVisibleFaces; + + S32 mPoissonOffset; + + static S32 sCompiles; + + static bool sShowHUDAttachments; + static bool sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. + static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write + static bool sAutoMaskAlphaDeferred; + static bool sAutoMaskAlphaNonDeferred; + static bool sRenderTransparentWater; + static bool sBakeSunlight; + static bool sNoAlpha; + static bool sUseFarClip; + static bool sShadowRender; + static bool sDynamicLOD; + static bool sPickAvatar; + static bool sReflectionRender; + static bool sDistortionRender; + static bool sImpostorRender; + static bool sImpostorRenderAlphaDepthPass; + static bool sUnderWaterRender; + static bool sRenderGlow; + static bool sTextureBindTest; + static bool sRenderAttachedLights; + static bool sRenderAttachedParticles; + static bool sRenderDeferred; + static bool sReflectionProbesEnabled; + static S32 sVisibleLightCount; + static bool sRenderingHUDs; static F32 sDistortionWaterClipPlaneMargin; - static LLTrace::EventStatHandle sStatBatchSize; + static LLTrace::EventStatHandle sStatBatchSize; class RenderTargetPack { public: - U32 width = 0; - U32 height = 0; + U32 width = 0; + U32 height = 0; //screen texture - LLRenderTarget screen; - LLRenderTarget uiScreen; - LLRenderTarget deferredScreen; - LLRenderTarget fxaaBuffer; - LLRenderTarget edgeMap; - LLRenderTarget deferredLight; + LLRenderTarget screen; + LLRenderTarget uiScreen; + LLRenderTarget deferredScreen; + LLRenderTarget fxaaBuffer; + LLRenderTarget edgeMap; + LLRenderTarget deferredLight; //sun shadow map - LLRenderTarget shadow[4]; + LLRenderTarget shadow[4]; }; // main full resoltuion render target @@ -703,7 +703,7 @@ public: // used by reflection probes and dynamic texture bakes RenderTargetPack mAuxillaryRT; - // Auxillary render target pack scaled to the hero probe's per-face size. + // Auxillary render target pack scaled to the hero probe's per-face size. RenderTargetPack mHeroProbeRT; // currently used render target pack @@ -729,336 +729,336 @@ public: LLCullResult mReflectedObjects; LLCullResult mRefractedObjects; - //utility buffers for rendering post effects - LLPointer mDeferredVB; + //utility buffers for rendering post effects + LLPointer mDeferredVB; // a single triangle that covers the whole screen LLPointer mScreenTriangleVB; - //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] - LLPointer mCubeVB; + //utility buffer for rendering cubes, 8 vertices are corners of a cube [-1, 1] + LLPointer mCubeVB; //list of currently bound reflection maps std::vector mReflectionMaps; - std::vector mShadowFrustPoints[4]; - LLVector4 mShadowError; - LLVector4 mShadowFOV; - LLVector3 mShadowFrustOrigin[4]; - LLCamera mShadowCamera[8]; - LLVector3 mShadowExtents[4][2]; + std::vector mShadowFrustPoints[4]; + LLVector4 mShadowError; + LLVector4 mShadowFOV; + 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]; + glh::matrix4f mSunShadowMatrix[6]; + glh::matrix4f mShadowModelview[6]; + glh::matrix4f mShadowProjection[6]; glh::matrix4f mReflectionModelView; - LLPointer mShadowSpotLight[2]; - F32 mSpotLightFade[2]; - LLPointer mTargetShadowSpotLight[2]; + LLPointer mShadowSpotLight[2]; + F32 mSpotLightFade[2]; + LLPointer mTargetShadowSpotLight[2]; - LLVector4 mSunClipPlanes; - LLVector4 mSunOrthoClipPlanes; - LLVector2 mScreenScale; + LLVector4 mSunClipPlanes; + LLVector4 mSunOrthoClipPlanes; + LLVector2 mScreenScale; - //water distortion texture (refraction) - LLRenderTarget mWaterDis; + //water distortion texture (refraction) + LLRenderTarget mWaterDis; static const U32 MAX_BAKE_WIDTH; - //texture for making the glow - LLRenderTarget mGlow[3]; + //texture for making the glow + LLRenderTarget mGlow[3]; - //noise map - U32 mNoiseMap; - U32 mTrueNoiseMap; - U32 mLightFunc; + //noise map + U32 mNoiseMap; + U32 mTrueNoiseMap; + U32 mLightFunc; - LLColor4 mSunDiffuse; - LLColor4 mMoonDiffuse; - LLVector4 mSunDir; - LLVector4 mMoonDir; + LLColor4 mSunDiffuse; + LLColor4 mMoonDiffuse; + LLVector4 mSunDir; + LLVector4 mMoonDir; bool mNeedsShadowTargetClear; - LLVector4 mTransformedSunDir; - LLVector4 mTransformedMoonDir; + LLVector4 mTransformedSunDir; + LLVector4 mTransformedMoonDir; - bool mInitialized; - bool mShadersLoaded; + bool mInitialized; + bool mShadersLoaded; - U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback + U32 mTransformFeedbackPrimitives; //number of primitives expected to be generated by transform feedback protected: - bool mRenderTypeEnabled[NUM_RENDER_TYPES]; - std::stack mRenderTypeEnableStack; - - U32 mRenderDebugFeatureMask; - U64 mRenderDebugMask; - U64 mOldRenderDebugMask; - std::stack mRenderDebugFeatureStack; - - ///////////////////////////////////////////// - // - // - LLDrawable::drawable_vector_t mMovedList; - LLDrawable::drawable_vector_t mMovedBridge; - LLDrawable::drawable_vector_t mShiftList; - - ///////////////////////////////////////////// - // - // - struct Light - { - Light(LLDrawable* ptr, F32 d, F32 f = 0.0f) - : drawable(ptr), - dist(d), - fade(f) - {} - LLPointer drawable; - F32 dist; - F32 fade; - struct compare - { - bool operator()(const Light& a, const Light& b) const - { - if ( a.dist < b.dist ) - return true; - else if ( a.dist > b.dist ) - return false; - else - return a.drawable < b.drawable; - } - }; - }; - typedef std::set< Light, Light::compare > light_set_t; - - LLDrawable::ordered_drawable_set_t mLights; - light_set_t mNearbyLights; // lights near camera - LLColor4 mHWLightColors[8]; - - ///////////////////////////////////////////// - // - // Different queues of drawables being processed. - // - LLDrawable::drawable_list_t mBuildQ1; // priority - LLSpatialGroup::sg_vector_t mGroupQ1; //priority - - LLSpatialGroup::sg_vector_t mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref - - LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called - U32 mMeshDirtyQueryObject; - - LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius - - bool mGroupQ1Locked; - - bool mResetVertexBuffers; //if true, clear vertex buffers on next update - - LLViewerObject::vobj_list_t mCreateQ; - - LLDrawable::drawable_set_t mRetexturedList; - - class HighlightItem - { - public: - const LLPointer mItem; - mutable F32 mFade; - - HighlightItem(LLDrawable* item) - : mItem(item), mFade(0) - { - } - - bool operator<(const HighlightItem& rhs) const - { - return mItem < rhs.mItem; - } - - bool operator==(const HighlightItem& rhs) const - { - return mItem == rhs.mItem; - } - - void incrFade(F32 val) const - { - mFade = llclamp(mFade+val, 0.f, 1.f); - } - }; - - ////////////////////////////////////////////////// - // - // Draw pools are responsible for storing all rendered data, - // and performing the actual rendering of objects. - // - struct compare_pools - { - bool operator()(const LLDrawPool* a, const LLDrawPool* b) const - { - if (!a) - return true; - else if (!b) - return false; - else - { - S32 atype = a->getType(); - S32 btype = b->getType(); - if (atype < btype) - return true; - else if (atype > btype) - return false; - else - return a->getId() < b->getId(); - } - } - }; - typedef std::set pool_set_t; - pool_set_t mPools; - LLDrawPool* mLastRebuildPool; - - // For quick-lookups into mPools (mapped by texture pointer) - std::map mTerrainPools; - std::map mTreePools; - LLDrawPoolAlpha* mAlphaPoolPreWater = nullptr; + bool mRenderTypeEnabled[NUM_RENDER_TYPES]; + std::stack mRenderTypeEnableStack; + + U32 mRenderDebugFeatureMask; + U64 mRenderDebugMask; + U64 mOldRenderDebugMask; + std::stack mRenderDebugFeatureStack; + + ///////////////////////////////////////////// + // + // + LLDrawable::drawable_vector_t mMovedList; + LLDrawable::drawable_vector_t mMovedBridge; + LLDrawable::drawable_vector_t mShiftList; + + ///////////////////////////////////////////// + // + // + struct Light + { + Light(LLDrawable* ptr, F32 d, F32 f = 0.0f) + : drawable(ptr), + dist(d), + fade(f) + {} + LLPointer drawable; + F32 dist; + F32 fade; + struct compare + { + bool operator()(const Light& a, const Light& b) const + { + if ( a.dist < b.dist ) + return true; + else if ( a.dist > b.dist ) + return false; + else + return a.drawable < b.drawable; + } + }; + }; + typedef std::set< Light, Light::compare > light_set_t; + + LLDrawable::ordered_drawable_set_t mLights; + light_set_t mNearbyLights; // lights near camera + LLColor4 mHWLightColors[8]; + + ///////////////////////////////////////////// + // + // Different queues of drawables being processed. + // + LLDrawable::drawable_list_t mBuildQ1; // priority + LLSpatialGroup::sg_vector_t mGroupQ1; //priority + + LLSpatialGroup::sg_vector_t mGroupSaveQ1; // a place to save mGroupQ1 until it is safe to unref + + LLSpatialGroup::sg_vector_t mMeshDirtyGroup; //groups that need rebuildMesh called + U32 mMeshDirtyQueryObject; + + LLDrawable::drawable_list_t mPartitionQ; //drawables that need to update their spatial partition radius + + bool mGroupQ1Locked; + + bool mResetVertexBuffers; //if true, clear vertex buffers on next update + + LLViewerObject::vobj_list_t mCreateQ; + + LLDrawable::drawable_set_t mRetexturedList; + + class HighlightItem + { + public: + const LLPointer mItem; + mutable F32 mFade; + + HighlightItem(LLDrawable* item) + : mItem(item), mFade(0) + { + } + + bool operator<(const HighlightItem& rhs) const + { + return mItem < rhs.mItem; + } + + bool operator==(const HighlightItem& rhs) const + { + return mItem == rhs.mItem; + } + + void incrFade(F32 val) const + { + mFade = llclamp(mFade+val, 0.f, 1.f); + } + }; + + ////////////////////////////////////////////////// + // + // Draw pools are responsible for storing all rendered data, + // and performing the actual rendering of objects. + // + struct compare_pools + { + bool operator()(const LLDrawPool* a, const LLDrawPool* b) const + { + if (!a) + return true; + else if (!b) + return false; + else + { + S32 atype = a->getType(); + S32 btype = b->getType(); + if (atype < btype) + return true; + else if (atype > btype) + return false; + else + return a->getId() < b->getId(); + } + } + }; + typedef std::set pool_set_t; + pool_set_t mPools; + LLDrawPool* mLastRebuildPool; + + // For quick-lookups into mPools (mapped by texture pointer) + std::map mTerrainPools; + std::map mTreePools; + LLDrawPoolAlpha* mAlphaPoolPreWater = nullptr; LLDrawPoolAlpha* mAlphaPoolPostWater = nullptr; - LLDrawPool* mSkyPool = nullptr; - LLDrawPool* mTerrainPool = nullptr; - LLDrawPool* mWaterPool = nullptr; - LLRenderPass* mSimplePool = nullptr; - LLRenderPass* mGrassPool = nullptr; - LLRenderPass* mAlphaMaskPool = nullptr; - LLRenderPass* mFullbrightAlphaMaskPool = nullptr; - LLRenderPass* mFullbrightPool = nullptr; - LLDrawPool* mGlowPool = nullptr; - LLDrawPool* mBumpPool = nullptr; - LLDrawPool* mMaterialsPool = nullptr; - LLDrawPool* mWLSkyPool = nullptr; - LLDrawPool* mPBROpaquePool = nullptr; + LLDrawPool* mSkyPool = nullptr; + LLDrawPool* mTerrainPool = nullptr; + LLDrawPool* mWaterPool = nullptr; + LLRenderPass* mSimplePool = nullptr; + LLRenderPass* mGrassPool = nullptr; + LLRenderPass* mAlphaMaskPool = nullptr; + LLRenderPass* mFullbrightAlphaMaskPool = nullptr; + LLRenderPass* mFullbrightPool = nullptr; + LLDrawPool* mGlowPool = nullptr; + LLDrawPool* mBumpPool = nullptr; + LLDrawPool* mMaterialsPool = nullptr; + LLDrawPool* mWLSkyPool = nullptr; + LLDrawPool* mPBROpaquePool = nullptr; LLDrawPool* mPBRAlphaMaskPool = nullptr; - // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar - + // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar + public: - std::vector mHighlightFaces; // highlight faces on physical objects + std::vector mHighlightFaces; // highlight faces on physical objects protected: - std::vector mSelectedFaces; - - class DebugBlip - { - public: - LLColor4 mColor; - LLVector3 mPosition; - F32 mAge; - - DebugBlip(const LLVector3& position, const LLColor4& color) - : mColor(color), mPosition(position), mAge(0.f) - { } - }; - - std::list mDebugBlips; - - LLPointer mFaceSelectImagep; - - U32 mLightMask; - U32 mLightMovingMask; - - static bool sRenderPhysicalBeacons; - static bool sRenderMOAPBeacons; - static bool sRenderScriptedTouchBeacons; - static bool sRenderScriptedBeacons; - static bool sRenderParticleBeacons; - static bool sRenderSoundBeacons; + std::vector mSelectedFaces; + + class DebugBlip + { + public: + LLColor4 mColor; + LLVector3 mPosition; + F32 mAge; + + DebugBlip(const LLVector3& position, const LLColor4& color) + : mColor(color), mPosition(position), mAge(0.f) + { } + }; + + std::list mDebugBlips; + + LLPointer mFaceSelectImagep; + + U32 mLightMask; + U32 mLightMovingMask; + + static bool sRenderPhysicalBeacons; + static bool sRenderMOAPBeacons; + static bool sRenderScriptedTouchBeacons; + static bool sRenderScriptedBeacons; + static bool sRenderParticleBeacons; + static bool sRenderSoundBeacons; public: - static bool sRenderBeacons; - static bool sRenderHighlight; - - // Determines which set of UVs to use in highlight display - // - static LLRender::eTexIndex sRenderHighlightTextureChannel; - - //debug use - static U32 sCurRenderPoolType ; - - //cached settings - static bool WindLightUseAtmosShaders; - static bool RenderDeferred; - static F32 RenderDeferredSunWash; - static U32 RenderFSAASamples; - static U32 RenderResolutionDivisor; - static bool RenderUIBuffer; - static S32 RenderShadowDetail; + static bool sRenderBeacons; + static bool sRenderHighlight; + + // Determines which set of UVs to use in highlight display + // + static LLRender::eTexIndex sRenderHighlightTextureChannel; + + //debug use + static U32 sCurRenderPoolType ; + + //cached settings + static bool WindLightUseAtmosShaders; + static bool RenderDeferred; + static F32 RenderDeferredSunWash; + static U32 RenderFSAASamples; + static U32 RenderResolutionDivisor; + static bool RenderUIBuffer; + static S32 RenderShadowDetail; static S32 RenderShadowSplits; - static bool RenderDeferredSSAO; - static F32 RenderShadowResolutionScale; - static bool RenderDelayCreation; - static bool RenderAnimateRes; - static bool FreezeTime; - static S32 DebugBeaconLineWidth; - static F32 RenderHighlightBrightness; - static LLColor4 RenderHighlightColor; - static F32 RenderHighlightThickness; - static bool RenderSpotLightsInNondeferred; - static LLColor4 PreviewAmbientColor; - static LLColor4 PreviewDiffuse0; - static LLColor4 PreviewSpecular0; - static LLColor4 PreviewDiffuse1; - static LLColor4 PreviewSpecular1; - static LLColor4 PreviewDiffuse2; - static LLColor4 PreviewSpecular2; - static LLVector3 PreviewDirection0; - static LLVector3 PreviewDirection1; - static LLVector3 PreviewDirection2; - static F32 RenderGlowMinLuminance; - static F32 RenderGlowMaxExtractAlpha; - static F32 RenderGlowWarmthAmount; - static LLVector3 RenderGlowLumWeights; - static LLVector3 RenderGlowWarmthWeights; - static S32 RenderGlowResolutionPow; - static S32 RenderGlowIterations; - static F32 RenderGlowWidth; - static F32 RenderGlowStrength; - static bool RenderGlowNoise; - static bool RenderDepthOfField; - static bool RenderDepthOfFieldInEditMode; - static F32 CameraFocusTransitionTime; - static F32 CameraFNumber; - static F32 CameraFocalLength; - static F32 CameraFieldOfView; - static F32 RenderShadowNoise; - static F32 RenderShadowBlurSize; - static F32 RenderSSAOScale; - static U32 RenderSSAOMaxScale; - static F32 RenderSSAOFactor; - static LLVector3 RenderSSAOEffect; - static F32 RenderShadowOffsetError; - static F32 RenderShadowBiasError; - static F32 RenderShadowOffset; - static F32 RenderShadowBias; - static F32 RenderSpotShadowOffset; - static F32 RenderSpotShadowBias; + static bool RenderDeferredSSAO; + static F32 RenderShadowResolutionScale; + static bool RenderDelayCreation; + static bool RenderAnimateRes; + static bool FreezeTime; + static S32 DebugBeaconLineWidth; + static F32 RenderHighlightBrightness; + static LLColor4 RenderHighlightColor; + static F32 RenderHighlightThickness; + static bool RenderSpotLightsInNondeferred; + static LLColor4 PreviewAmbientColor; + static LLColor4 PreviewDiffuse0; + static LLColor4 PreviewSpecular0; + static LLColor4 PreviewDiffuse1; + static LLColor4 PreviewSpecular1; + static LLColor4 PreviewDiffuse2; + static LLColor4 PreviewSpecular2; + static LLVector3 PreviewDirection0; + static LLVector3 PreviewDirection1; + static LLVector3 PreviewDirection2; + static F32 RenderGlowMinLuminance; + static F32 RenderGlowMaxExtractAlpha; + static F32 RenderGlowWarmthAmount; + static LLVector3 RenderGlowLumWeights; + static LLVector3 RenderGlowWarmthWeights; + static S32 RenderGlowResolutionPow; + static S32 RenderGlowIterations; + static F32 RenderGlowWidth; + static F32 RenderGlowStrength; + static bool RenderGlowNoise; + static bool RenderDepthOfField; + static bool RenderDepthOfFieldInEditMode; + static F32 CameraFocusTransitionTime; + static F32 CameraFNumber; + static F32 CameraFocalLength; + static F32 CameraFieldOfView; + static F32 RenderShadowNoise; + static F32 RenderShadowBlurSize; + static F32 RenderSSAOScale; + static U32 RenderSSAOMaxScale; + static F32 RenderSSAOFactor; + static LLVector3 RenderSSAOEffect; + static F32 RenderShadowOffsetError; + static F32 RenderShadowBiasError; + static F32 RenderShadowOffset; + static F32 RenderShadowBias; + static F32 RenderSpotShadowOffset; + static F32 RenderSpotShadowBias; static LLDrawable* RenderSpotLight; - static F32 RenderEdgeDepthCutoff; - static F32 RenderEdgeNormCutoff; - static LLVector3 RenderShadowGaussian; - static F32 RenderShadowBlurDistFactor; - static bool RenderDeferredAtmospheric; - static F32 RenderHighlightFadeTime; - static F32 RenderFarClip; - static LLVector3 RenderShadowSplitExponent; - static F32 RenderShadowErrorCutoff; - static F32 RenderShadowFOVCutoff; - static bool CameraOffset; - static F32 CameraMaxCoF; - static F32 CameraDoFResScale; - static F32 RenderAutoHideSurfaceAreaLimit; - static bool RenderScreenSpaceReflections; + static F32 RenderEdgeDepthCutoff; + static F32 RenderEdgeNormCutoff; + static LLVector3 RenderShadowGaussian; + static F32 RenderShadowBlurDistFactor; + static bool RenderDeferredAtmospheric; + static F32 RenderHighlightFadeTime; + static F32 RenderFarClip; + static LLVector3 RenderShadowSplitExponent; + static F32 RenderShadowErrorCutoff; + static F32 RenderShadowFOVCutoff; + static bool CameraOffset; + static F32 CameraMaxCoF; + static F32 CameraDoFResScale; + static F32 RenderAutoHideSurfaceAreaLimit; + static bool RenderScreenSpaceReflections; static S32 RenderScreenSpaceReflectionIterations; - static F32 RenderScreenSpaceReflectionRayStep; - static F32 RenderScreenSpaceReflectionDistanceBias; - static F32 RenderScreenSpaceReflectionDepthRejectBias; - static F32 RenderScreenSpaceReflectionAdaptiveStepMultiplier; - static S32 RenderScreenSpaceReflectionGlossySamples; - static S32 RenderBufferVisualization; - static bool RenderMirrors; - static S32 RenderHeroProbeUpdateRate; + static F32 RenderScreenSpaceReflectionRayStep; + static F32 RenderScreenSpaceReflectionDistanceBias; + static F32 RenderScreenSpaceReflectionDepthRejectBias; + static F32 RenderScreenSpaceReflectionAdaptiveStepMultiplier; + static S32 RenderScreenSpaceReflectionGlossySamples; + static S32 RenderBufferVisualization; + static bool RenderMirrors; + static S32 RenderHeroProbeUpdateRate; static S32 RenderHeroProbeConservativeUpdateMultiplier; }; -- cgit v1.2.3 From 33ad8db77584c66496f261a1cfd9aa535462a003 Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 14 May 2024 08:50:04 +0300 Subject: #1457 Fix the tests on mac (cherry picked from commit 82d713782529074b03720833038cb0df2b8bcffd) --- indra/llimage/tests/llimageworker_test.cpp | 3 ++- indra/test/test.cpp | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index 49fc1afd82..2568adf89e 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -68,6 +68,7 @@ U8* LLImageRaw::allocateData(S32 size) { return NULL; } U8* LLImageRaw::reallocateData(S32 size) { return NULL; } const U8* LLImageBase::getData() const { return NULL; } U8* LLImageBase::getData() { return NULL; } +const std::string& LLImage::getLastThreadError() { static std::string msg; return msg; } // End Stubbing // ------------------------------------------------------------------------------------------- @@ -98,7 +99,7 @@ namespace tut done = res; *done = false; } - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux, U32) + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux, U32 request_id) { *done = true; } diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 21232e88f5..61a4eb07c5 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -54,12 +54,6 @@ #endif #ifndef LL_WINDOWS - -typedef struct { - void *re_pcre; - size_t re_nsub; - size_t re_erroffset; -} regex_t; #include #include #endif -- cgit v1.2.3 From ae6a402b7a26aa4ec3258b3e0b68919602e03d23 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 15 May 2024 09:55:55 -0700 Subject: secondlife/viewer#1474: Remove small texture offset from PBR terrain --- .../shaders/class1/deferred/pbrterrainV.glsl | 14 ++++----- .../shaders/class1/deferred/textureUtilV.glsl | 35 ++++++++++++++++++++++ indra/newview/lldrawpoolterrain.cpp | 10 +------ 3 files changed, 43 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl index 489fc26e3f..d7c8fe1861 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainV.glsl @@ -50,8 +50,8 @@ out vec3 vary_position; // tangent_space_transform below. uniform vec4[2] texture_base_color_transform; -vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); -vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform); +vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform); +vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform); void main() { @@ -70,7 +70,7 @@ void main() // *HACK: Should be using texture_normal_transform here. The KHR texture // transform spec requires handling texture transforms separately for each // individual texture. - vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform, texture_matrix0)); + vary_tangent = normalize(terrain_tangent_space_transform(vec4(t, tangent.w), n, texture_base_color_transform)); vary_sign = tangent.w; vary_normal = normalize(n); @@ -80,13 +80,13 @@ void main() // separately for each individual texture. #if TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 3 // xy - vary_coords[0].xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0); + vary_coords[0].xy = terrain_texture_transform(position.xy, texture_base_color_transform); // yz - vary_coords[0].zw = texture_transform(position.yz, texture_base_color_transform, texture_matrix0); + vary_coords[0].zw = terrain_texture_transform(position.yz, texture_base_color_transform); // (-x)z - vary_coords[1].xy = texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform, texture_matrix0); + vary_coords[1].xy = terrain_texture_transform(position.xz * vec2(-1, 1), texture_base_color_transform); #elif TERRAIN_PLANAR_TEXTURE_SAMPLE_COUNT == 1 - vary_texcoord0.xy = texture_transform(position.xy, texture_base_color_transform, texture_matrix0); + vary_texcoord0.xy = terrain_texture_transform(position.xy, texture_base_color_transform); #endif vec4 tc = vec4(texcoord1,0,1); diff --git a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl index 732333311c..7c02cb9d4a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/textureUtilV.glsl @@ -77,6 +77,19 @@ vec2 texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform, mat4 sl return texcoord; } +// Similar to texture_transform but no offset during coordinate system +// conversion, and no texture animation support. +vec2 terrain_texture_transform(vec2 vertex_texcoord, vec4[2] khr_gltf_transform) +{ + vec2 texcoord = vertex_texcoord; + + texcoord.y = -texcoord.y; + texcoord = khr_texture_transform(texcoord, khr_gltf_transform[0].xy, khr_gltf_transform[0].z, khr_gltf_transform[1].xy); + texcoord.y = -texcoord.y; + + return texcoord; +} + // Take the rotation only from both transforms and apply to the tangent. This // accounts for the change of the topology of the normal texture when a texture // rotation is applied to it. @@ -120,3 +133,25 @@ vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] kh return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); } + +// Similar to tangent_space_transform but no no texture animation support. +vec3 terrain_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform) +{ + // Immediately convert to left-handed coordinate system ((0,1) -> (0, -1)) + vec2 weights = vec2(0, -1); + + // Apply KHR_texture_transform (rotation only) + float khr_rotation = khr_gltf_transform[0].z; + mat2 khr_rotation_mat = mat2( + cos(khr_rotation),-sin(khr_rotation), + sin(khr_rotation), cos(khr_rotation) + ); + weights = khr_rotation_mat * weights; + + // Convert back to right-handed coordinate system + weights.y = -weights.y; + + vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz); + + return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz); +} diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index c5932a6ad9..b33a2dd9bb 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -431,18 +431,10 @@ void LLDrawPoolTerrain::renderFullShaderPBR(BOOL local_materials) LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; llassert(shader); - - - // *TODO: Figure out why this offset is *sometimes* producing seams at the - // region edge, and repeat jumps when crossing regions, when - // RenderTerrainPBRScale is not a factor of the region scale. - LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal(); - F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; - F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sPBRDetailScale)*sPBRDetailScale; LLGLTFMaterial::TextureTransform base_color_transform; base_color_transform.mScale = LLVector2(sPBRDetailScale, sPBRDetailScale); - base_color_transform.mOffset = LLVector2(offset_x, offset_y); + // *TODO: mOffset and mRotation left at defaults for now. (per-material texture transforms are implemented in another branch) F32 base_color_packed[8]; base_color_transform.getPacked(base_color_packed); // *HACK: Use the same texture repeats for all PBR terrain textures for now -- cgit v1.2.3 From bbc9d9db4838e60724c8ba93c2efdbaa522595c1 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 15 May 2024 14:15:55 -0500 Subject: #1466 Loosen clamp on haze glow to fix skies that want to be bonkers (#1470) --- .../app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 40b7f9cf0e..d077670c96 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -98,7 +98,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) haze_glow *= glow.x; // higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = clamp(pow(haze_glow, glow.z), -10, 10); + haze_glow = clamp(pow(haze_glow, glow.z), -100000, 100000); // glow.z should be negative, so we're doing a sort of (1 / "angle") function // add "minimum anti-solar illumination" -- cgit v1.2.3 From 29be88d60d654193926add496d2d851f7c217356 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 15 May 2024 15:40:55 -0500 Subject: #1267 Fix for alpha cutoff of zero and base color factor alpha of zero making objects disappear (#1485) --- .../shaders/class1/deferred/pbrShadowAlphaMaskF.glsl | 2 +- .../app_settings/shaders/class1/deferred/pbropaqueF.glsl | 8 ++++++-- indra/newview/llface.cpp | 6 +++--- indra/newview/llfetchedgltfmaterial.cpp | 11 +---------- 4 files changed, 11 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl index 1d1545be7e..35b7602569 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrShadowAlphaMaskF.glsl @@ -35,7 +35,7 @@ uniform float minimum_alpha; void main() { - float alpha = texture(diffuseMap,vary_texcoord0.xy).a; + float alpha = texture(diffuseMap,vary_texcoord0.xy).a * vertex_color.a; if (alpha < minimum_alpha) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl index 1d5f810cf3..380d493636 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbropaqueF.glsl @@ -69,12 +69,16 @@ void main() mirrorClip(vary_position); vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba; + basecolor.rgb = srgb_to_linear(basecolor.rgb); + + basecolor *= vertex_color; + if (basecolor.a < minimum_alpha) { discard; } - vec3 col = vertex_color.rgb * srgb_to_linear(basecolor.rgb); + vec3 col = basecolor.rgb; // from mikktspace.com vec3 vNt = texture(bumpMap, normal_texcoord.xy).xyz*2.0-1.0; @@ -108,7 +112,7 @@ void main() //emissive = tnorm*0.5+0.5; // See: C++: addDeferredAttachments(), GLSL: softenLightF frag_data[0] = max(vec4(col, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(spec.rgb,vertex_color.a), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[1] = max(vec4(spec.rgb,0.0), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, environment intensity, flags frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index ccee57cf69..659e9e76a6 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1261,11 +1261,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { color = tep->getGLTFRenderMaterial()->mBaseColor; } - - if (rebuild_color) + + if (rebuild_color) { //decide if shiny goes in alpha channel of color if (tep && - !isInAlphaPool()) // <--- alpha channel MUST contain transparency, not shiny + !isInAlphaPool() && tep->getGLTFRenderMaterial() == nullptr) // <--- alpha channel MUST contain transparency, not shiny { LLMaterial* mat = tep->getMaterialParams().get(); diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 1dd1dbabbe..5296f40119 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -77,16 +77,7 @@ void LLFetchedGLTFMaterial::bind(LLViewerTexture* media_tex) { if (mAlphaMode == LLGLTFMaterial::ALPHA_MODE_MASK) { - // dividing the alpha cutoff by transparency here allows the shader to compare against - // the alpha value of the texture without needing the transparency value - if (mBaseColor.mV[3] > 0.f) - { - min_alpha = mAlphaCutoff / mBaseColor.mV[3]; - } - else - { - min_alpha = 1024.f; - } + min_alpha = mAlphaCutoff; } shader->uniform1f(LLShaderMgr::MINIMUM_ALPHA, min_alpha); } -- cgit v1.2.3 From 7ed053d9a257087b76937d750b9f2b0c96f6df38 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 20 May 2024 19:02:13 +0300 Subject: viewer#1520 Material upload floater displays wrong upload fee --- indra/llrender/llgltexture.cpp | 4 +++ indra/newview/llagentbenefits.cpp | 2 +- indra/newview/llmaterialeditor.cpp | 60 +++++++++++++++++++++++++------------- indra/newview/llmaterialeditor.h | 1 + 4 files changed, 45 insertions(+), 22 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index be4fc85985..104976fcc6 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -49,6 +49,10 @@ LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) mUseMipMaps = usemipmaps ; // Create an empty image of the specified size and width mGLTexturep = new LLImageGL(raw, usemipmaps) ; + mFullWidth = mGLTexturep->getCurrentWidth(); + mFullHeight = mGLTexturep->getCurrentHeight(); + mComponents = mGLTexturep->getComponents(); + setTexelsPerImage(); } LLGLTexture::~LLGLTexture() diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp index 4ac4d2136f..e9f00f6556 100644 --- a/indra/newview/llagentbenefits.cpp +++ b/indra/newview/llagentbenefits.cpp @@ -175,7 +175,7 @@ S32 LLAgentBenefits::getTextureUploadCost(const LLViewerTexture* tex) const return getTextureUploadCost(); } } - return getTextureUploadCost(); + return 0; } S32 LLAgentBenefits::getTextureUploadCost(const LLImageBase* tex) const diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 208b289ca9..36a0834845 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -489,10 +489,7 @@ BOOL LLMaterialEditor::postBuild() } else { - getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched))); - getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched))); - getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched))); - getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched))); + refreshUploadCost(); } boost::function changes_callback = [this](LLUICtrl * ctrl, void* userData) @@ -811,6 +808,37 @@ void LLMaterialEditor::resetUnsavedChanges() } } +void LLMaterialEditor::refreshUploadCost() +{ + mExpectedUploadCost = 0; + if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched) + { + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched); + mExpectedUploadCost += upload_cost; + getChild("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + } + if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched) + { + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched); + mExpectedUploadCost += upload_cost; + getChild("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + } + if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched) + { + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched); + mExpectedUploadCost += upload_cost; + getChild("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + } + if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched) + { + S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched); + mExpectedUploadCost += upload_cost; + getChild("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost)); + } + + getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); +} + void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) { mUnsavedChanges |= dirty_flag; @@ -841,25 +869,15 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag) setCanSave(false); } - mExpectedUploadCost = 0; - if (mBaseColorTextureUploadId.notNull() && mBaseColorTextureUploadId == getBaseColorId() && mBaseColorFetched) + if ((dirty_flag & MATERIAL_BASE_COLOR_TEX_DIRTY) + || (dirty_flag & MATERIAL_NORMAL_TEX_DIRTY) + || (dirty_flag & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) + || (dirty_flag & MATERIAL_EMISIVE_TEX_DIRTY) + || (dirty_flag == 0) + || (dirty_flag == U32_MAX)) { - mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mBaseColorFetched); + refreshUploadCost(); } - if (mMetallicTextureUploadId.notNull() && mMetallicTextureUploadId == getMetallicRoughnessId() && mMetallicRoughnessFetched) - { - mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mMetallicRoughnessFetched); - } - if (mEmissiveTextureUploadId.notNull() && mEmissiveTextureUploadId == getEmissiveId() && mEmissiveFetched) - { - mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mEmissiveFetched); - } - if (mNormalTextureUploadId.notNull() && mNormalTextureUploadId == getNormalId() && mNormalFetched) - { - mExpectedUploadCost += LLAgentBenefitsMgr::current().getTextureUploadCost(mNormalFetched); - } - - getChild("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost)); } void LLMaterialEditor::setCanSaveAs(bool value) diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index dda65476af..11809d26be 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -288,6 +288,7 @@ private: // utility function for building a description of the imported material // based on what we know about it. const std::string buildMaterialDescription(); + void refreshUploadCost(); void resetUnsavedChanges(); void markChangesUnsaved(U32 dirty_flag); -- cgit v1.2.3 From 10fb2fc411d17f323c521c4182fe9b081201e62a Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 19:18:20 +0200 Subject: Adjust Copy3rdPartyLibs.cmake for Visual Studio 2022 17.10.0 and greater --- indra/cmake/Copy3rdPartyLibs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 7938d4f54b..27b20ee3b1 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -107,7 +107,7 @@ if(WINDOWS) set(MSVC_VER 140) elseif (MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1930) # Visual Studio 2019 set(MSVC_VER 140) - elseif (MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1940) # Visual Studio 2022 + elseif (MSVC_VERSION GREATER_EQUAL 1930 AND MSVC_VERSION LESS 1950) # Visual Studio 2022 set(MSVC_VER 140) else (MSVC80) MESSAGE(WARNING "New MSVC_VERSION ${MSVC_VERSION} of MSVC: adapt Copy3rdPartyLibs.cmake") -- cgit v1.2.3 From 5f3a6bdd7f122688aff5c0e63f03928fa15bb0c9 Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 28 May 2024 13:25:02 -0700 Subject: secondlife/viewer#1531: Attempt to fix PBR terrain fragment shader. --- .../shaders/class1/deferred/pbrterrainF.glsl | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl index de4745c1c4..0de2d348c3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainF.glsl @@ -180,7 +180,7 @@ void main() rm_factors[3] = vec2(roughnessFactors.w, metallicFactors.w); #endif - PBRMix mix = init_pbr_mix(); + PBRMix pbr_mix = init_pbr_mix(); PBRMix mix2; switch (tm.type & MIX_X) { @@ -207,7 +207,7 @@ void main() , emissiveColors[0] #endif ); - mix = mix_pbr(mix, mix2, tm.weight.x); + pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.x); break; default: break; @@ -237,7 +237,7 @@ void main() , emissiveColors[1] #endif ); - mix = mix_pbr(mix, mix2, tm.weight.y); + pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.y); break; default: break; @@ -267,7 +267,7 @@ void main() , emissiveColors[2] #endif ); - mix = mix_pbr(mix, mix2, tm.weight.z); + pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.z); break; default: break; @@ -297,14 +297,14 @@ void main() , emissiveColors[3] #endif ); - mix = mix_pbr(mix, mix2, tm.weight.w); + pbr_mix = mix_pbr(pbr_mix, mix2, tm.weight.w); break; default: break; } float minimum_alpha = terrain_mix(tm, minimum_alphas); - if (mix.col.a < minimum_alpha) + if (pbr_mix.col.a < minimum_alpha) { discard; } @@ -312,7 +312,7 @@ void main() #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_NORMAL) // from mikktspace.com - vec3 vNt = mix.vNt; + vec3 vNt = pbr_mix.vNt; vec3 vN = vary_normal; vec3 vT = vary_tangent.xyz; @@ -327,21 +327,21 @@ void main() #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_EMISSIVE) -#define emissive mix.emissive +#define mix_emissive pbr_mix.emissive #else -#define emissive vec3(0) +#define mix_emissive vec3(0) #endif #if (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_OCCLUSION) -#define orm mix.orm +#define mix_orm pbr_mix.orm #elif (TERRAIN_PBR_DETAIL >= TERRAIN_PBR_DETAIL_METALLIC_ROUGHNESS) -#define orm vec3(1.0, mix.rm) +#define mix_orm vec3(1.0, pbr_mix.rm) #else // Matte plastic potato terrain -#define orm vec3(1.0, 1.0, 0.0) +#define mix_orm vec3(1.0, 1.0, 0.0) #endif - frag_data[0] = max(vec4(mix.col.xyz, 0.0), vec4(0)); // Diffuse - frag_data[1] = max(vec4(orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. + frag_data[0] = max(vec4(pbr_mix.col.xyz, 0.0), vec4(0)); // Diffuse + frag_data[1] = max(vec4(mix_orm.rgb, base_color_factor_alpha), vec4(0)); // PBR linear packed Occlusion, Roughness, Metal. frag_data[2] = vec4(tnorm, GBUFFER_FLAG_HAS_PBR); // normal, flags - frag_data[3] = max(vec4(emissive,0), vec4(0)); // PBR sRGB Emissive + frag_data[3] = max(vec4(mix_emissive,0), vec4(0)); // PBR sRGB Emissive } -- cgit v1.2.3 From 33bb511ab4acd5867fbe5f11393a01e438b72293 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 28 May 2024 14:19:18 -0700 Subject: Improvements to mirror probe update rates (#1570) #1494 Fix for mirror updates getting "stuck" on some faces. --- indra/newview/llheroprobemanager.cpp | 36 +++++++++++++----------------------- indra/newview/llheroprobemanager.h | 3 +++ indra/newview/llviewerdisplay.cpp | 5 +++-- 3 files changed, 19 insertions(+), 25 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 208dfe45bd..1c08424868 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -112,7 +112,6 @@ void LLHeroProbeManager::update() LLVector4a probe_pos; LLVector3 camera_pos = LLViewerCamera::instance().mOrigin; - F32 near_clip = 0.1f; bool probe_present = false; LLQuaternion cameraOrientation = LLViewerCamera::instance().getQuaternion(); LLVector3 cameraDirection = LLVector3::z_axis * cameraOrientation; @@ -192,20 +191,15 @@ void LLHeroProbeManager::update() // Iterate through each face of the cube for (int i = 0; i < 6; i++) { - float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])) * 0.6 + 0.4; + float cube_facing = fmax(-1, fmin(1.0f, cameraDirection * cubeFaces[i])); - float updateRate; - if (cube_facing < 0.1f) - { - updateRate = 0; - } - else - { - updateRate = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); - } + cube_facing = 1 - cube_facing; - mFaceUpdateList[i] = updateRate; + mFaceUpdateList[i] = ceilf(cube_facing * gPipeline.RenderHeroProbeConservativeUpdateMultiplier); } + + + mProbes[0]->mOrigin = probe_pos; } else { @@ -214,25 +208,23 @@ void LLHeroProbeManager::update() mHeroProbeStrength = 1; } - else - { - probe_pos.load3(camera_pos.mV); - } - +} +void LLHeroProbeManager::renderProbes() +{ static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); - if (mNearestHero != nullptr) + F32 near_clip = 0.01f; + if (mNearestHero != nullptr && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0) && + !gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent()) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); - // Probe 0 is always our mirror probe. - mProbes[0]->mOrigin = probe_pos; bool radiance_pass = gPipeline.mReflectionMapManager.isRadiancePass(); gPipeline.mReflectionMapManager.mRadiancePass = true; - mRenderingMirror = true; + mRenderingMirror = true; doOcclusion(); @@ -585,8 +577,6 @@ void LLHeroProbeManager::cleanup() mDefaultProbe = nullptr; mUpdatingProbe = nullptr; - /* - */ } void LLHeroProbeManager::doOcclusion() diff --git a/indra/newview/llheroprobemanager.h b/indra/newview/llheroprobemanager.h index 5df146f2f1..e45b0049b2 100644 --- a/indra/newview/llheroprobemanager.h +++ b/indra/newview/llheroprobemanager.h @@ -68,6 +68,8 @@ public: // maintain reflection probes void update(); + void renderProbes(); + // debug display, called from llspatialpartition if reflection // probe debug display is active void renderDebug(); @@ -152,5 +154,6 @@ private: std::vector> mHeroVOList; LLPointer mNearestHero; + }; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index d65b44fd3a..bb3378f4fe 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -658,10 +658,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { // Render mirrors and associated hero probes before we render the rest of the scene. // This ensures the scene state in the hero probes are exactly the same as the rest of the scene before we render it. - if (gPipeline.RenderMirrors && !gSnapshot && (gPipeline.RenderHeroProbeUpdateRate == 0 || (gFrameCount % gPipeline.RenderHeroProbeUpdateRate) == 0)) + if (gPipeline.RenderMirrors && !gSnapshot) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Update hero probes"); gPipeline.mHeroProbeManager.update(); + gPipeline.mHeroProbeManager.renderProbes(); } LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 1"); @@ -1072,7 +1073,7 @@ void display_cube_face() LLSpatialGroup::sNoDelete = TRUE; S32 occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 1; // occlusion data is from main camera point of view, don't read or write it during cube snapshots + LLPipeline::sUseOcclusion = 0; // occlusion data is from main camera point of view, don't read or write it during cube snapshots //gDepthDirty = TRUE; //let "real" render pipe know it can't trust the depth buffer for occlusion data static LLCullResult result; -- cgit v1.2.3 From 12cd8589b4de85bc7f69c2cddc0d367cadb3b3f3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 28 May 2024 18:29:51 +0300 Subject: viewer#1568 Revert "SL-17597 AV height in Shape dialog IS WRONG" This reverts commit f5a7c22cea16b51db12360436ce64c2433a5aa5f to fix viewer#1568. --- indra/llappearance/llavatarappearance.cpp | 87 ++++++++++++++++++++----------- indra/llappearance/llavatarappearance.h | 2 - 2 files changed, 56 insertions(+), 33 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index d73be024cf..83e43b11b7 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -494,45 +494,70 @@ void LLAvatarAppearance::computeBodySize() mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); - F32 old_height = mBodySize.mV[VZ]; + LLVector3 pelvis_scale = mPelvisp->getScale(); + + // some of the joints have not been cached + LLVector3 skull = mSkullp->getPosition(); + //LLVector3 skull_scale = mSkullp->getScale(); + + LLVector3 neck = mNeckp->getPosition(); + LLVector3 neck_scale = mNeckp->getScale(); + + LLVector3 chest = mChestp->getPosition(); + LLVector3 chest_scale = mChestp->getScale(); + + // the rest of the joints have been cached + LLVector3 head = mHeadp->getPosition(); + LLVector3 head_scale = mHeadp->getScale(); + + LLVector3 torso = mTorsop->getPosition(); + LLVector3 torso_scale = mTorsop->getScale(); + + LLVector3 hip = mHipLeftp->getPosition(); + LLVector3 hip_scale = mHipLeftp->getScale(); + + LLVector3 knee = mKneeLeftp->getPosition(); + LLVector3 knee_scale = mKneeLeftp->getScale(); + + LLVector3 ankle = mAnkleLeftp->getPosition(); + LLVector3 ankle_scale = mAnkleLeftp->getScale(); + + LLVector3 foot = mFootLeftp->getPosition(); + F32 old_offset = mAvatarOffset.mV[VZ]; - // TODO: Measure the real depth and width - mPelvisToFoot = computePelvisToFoot(); - F32 new_height = computeBodyHeight(); - mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height); - F32 new_offset = getVisualParamWeight(AVATAR_HOVER); - mAvatarOffset.set(0, 0, new_offset); + mAvatarOffset.mV[VZ] = getVisualParamWeight(AVATAR_HOVER); + + mPelvisToFoot = hip.mV[VZ] * pelvis_scale.mV[VZ] - + knee.mV[VZ] * hip_scale.mV[VZ] - + ankle.mV[VZ] * knee_scale.mV[VZ] - + foot.mV[VZ] * ankle_scale.mV[VZ]; - if (mBodySize.mV[VZ] != old_height || new_offset != old_offset) + LLVector3 new_body_size; + new_body_size.mV[VZ] = mPelvisToFoot + + // the sqrt(2) correction below is an approximate + // correction to get to the top of the head + F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) + + head.mV[VZ] * neck_scale.mV[VZ] + + neck.mV[VZ] * chest_scale.mV[VZ] + + chest.mV[VZ] * torso_scale.mV[VZ] + + torso.mV[VZ] * pelvis_scale.mV[VZ]; + + // TODO -- measure the real depth and width + new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH; + new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH; + + mAvatarOffset.mV[VX] = 0.0f; + mAvatarOffset.mV[VY] = 0.0f; + + if (new_body_size != mBodySize || old_offset != mAvatarOffset.mV[VZ]) { + mBodySize = new_body_size; + compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState); } } -F32 LLAvatarAppearance::computeBodyHeight() -{ - F32 result = mPelvisToFoot + - // all these relative positions usually are positive - mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] + - mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] + - mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] + - mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] + - mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2; - return result; -} - -F32 LLAvatarAppearance::computePelvisToFoot() -{ - F32 result = - // all these relative positions usually are negative - mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] + - mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] + - mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] + - mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2; - return -result; -} - //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 9dd1ddffad..dc2d48fb74 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -147,8 +147,6 @@ public: void compareJointStateMaps(joint_state_map_t& last_state, joint_state_map_t& curr_state); void computeBodySize(); - F32 computeBodyHeight(); - F32 computePelvisToFoot(); public: typedef std::vector avatar_joint_list_t; -- cgit v1.2.3 From 01c82642ac01342114f41f2428890042c3040c9b Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 29 May 2024 19:31:58 -0700 Subject: #1581 Only render mirrors when reflection probes are enabled. (#1592) --- indra/newview/llheroprobemanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index 1c08424868..ff47ca87ec 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -75,7 +75,7 @@ LLHeroProbeManager::~LLHeroProbeManager() // helper class to seed octree with probes void LLHeroProbeManager::update() { - if (!LLPipeline::RenderMirrors || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) + if (!LLPipeline::RenderMirrors || !LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE) { return; } @@ -212,6 +212,12 @@ void LLHeroProbeManager::update() void LLHeroProbeManager::renderProbes() { + if (!LLPipeline::RenderMirrors || !LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || + LLStartUp::getStartupState() < STATE_PRECACHE) + { + return; + } + static LLCachedControl sDetail(gSavedSettings, "RenderHeroReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderHeroReflectionProbeLevel", 3); -- cgit v1.2.3 From 83f9885d73a7ffb3c87ae29bcad6b01d0530eeb4 Mon Sep 17 00:00:00 2001 From: RunitaiLinden Date: Tue, 4 Jun 2024 10:26:34 -0500 Subject: #1614 Fix for moire pattern in specular highlights. Incidental cleanup. --- .../app_settings/shaders/class1/deferred/deferredUtil.glsl | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index 385920f622..01543732d0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -142,18 +142,9 @@ vec2 getScreenCoordinate(vec2 screenpos) } vec4 getNorm(vec2 screenpos) -{ - return texture(normalMap, screenpos.xy); -} - -// return packedNormalEnvIntensityFlags since GBUFFER_FLAG_HAS_PBR needs .w -// See: C++: addDeferredAttachments(), GLSL: softenLightF -vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity) { vec4 norm = texture(normalMap, screenpos.xy); - n = norm.xyz; - envIntensity = texture(emissiveRect, screenpos.xy).r; - + norm.xyz = normalize(norm.xyz); return norm; } -- cgit v1.2.3 From c413458fd48ff209f7bd536924a2df2c4dfe8716 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Tue, 4 Jun 2024 15:22:38 -0700 Subject: #1628 Disable spherical mirror probes for the time being. (#1631) --- indra/newview/llheroprobemanager.cpp | 2 +- indra/newview/llpanelvolume.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ff47ca87ec..efe72128d4 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -123,7 +123,7 @@ void LLHeroProbeManager::update() float camera_center_distance = 99999.f; for (auto vo : mHeroVOList) { - if (vo && !vo->isDead() && vo->mDrawable.notNull()) + if (vo && !vo->isDead() && vo->mDrawable.notNull() && vo->isReflectionProbe() && vo->getReflectionProbeIsBox()) { float distance = (LLViewerCamera::instance().getOrigin() - vo->getPositionAgent()).magVec(); float center_distance = cameraDirection * (vo->getPositionAgent() - camera_pos); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 7f111d7619..701882ac57 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -387,6 +387,7 @@ void LLPanelVolume::getState( ) // Reflection Probe BOOL is_probe = volobjp && volobjp->isReflectionProbe(); + bool is_mirror = volobjp && volobjp->getReflectionProbeIsMirror(); getChild("Reflection Probe")->setValue(is_probe); getChildView("Reflection Probe")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh()); @@ -400,9 +401,9 @@ void LLPanelVolume::getState( ) getChildView("Probe Dynamic")->setEnabled(probe_enabled); getChildView("Probe Update Type")->setEnabled(probe_enabled); - getChildView("Probe Volume Type")->setEnabled(probe_enabled); - getChildView("Probe Ambiance")->setEnabled(probe_enabled); - getChildView("Probe Near Clip")->setEnabled(probe_enabled); + getChildView("Probe Volume Type")->setEnabled(probe_enabled && !is_mirror); + getChildView("Probe Ambiance")->setEnabled(probe_enabled && !is_mirror); + getChildView("Probe Near Clip")->setEnabled(probe_enabled && !is_mirror); getChildView("Probe Update Label")->setEnabled(probe_enabled); if (!probe_enabled) @@ -441,8 +442,8 @@ void LLPanelVolume::getState( ) update_type = "Dynamic Mirror"; } - getChildView("Probe Ambiance")->setEnabled(update_type != "Mirror"); - getChildView("Probe Near Clip")->setEnabled(update_type != "Mirror"); + getChildView("Probe Ambiance")->setEnabled(!is_mirror); + getChildView("Probe Near Clip")->setEnabled(!is_mirror); getChild("Probe Volume Type", true)->setValue(volume_type); getChild("Probe Ambiance", true)->setValue(volobjp->getReflectionProbeAmbiance()); @@ -1434,6 +1435,8 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) bool is_mirror = update_type.find("Mirror") != std::string::npos; + self->getChildView("Probe Volume Type")->setEnabled(!is_mirror); + volobjp->setReflectionProbeIsDynamic(update_type.find("Dynamic") != std::string::npos); volobjp->setReflectionProbeIsMirror(is_mirror); @@ -1442,7 +1445,7 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata) std::string shape_type = self->getChild("Probe Volume Type")->getValue().asString(); - bool is_box = shape_type == "Box"; + bool is_box = shape_type == "Box" || is_mirror; if (volobjp->setReflectionProbeIsBox(is_box)) { -- cgit v1.2.3 From 9f97ff7286aceef5be4e7589ca4af911edf30f12 Mon Sep 17 00:00:00 2001 From: Brad Linden <46733234+brad-linden@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:09:03 -0700 Subject: #989 Fix for blurry terrain on Mac (#1633) Co-authored-by: Dave Parks --- indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index 8e1e4b54d5..b4ab7cd169 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -47,7 +47,9 @@ vec2 texgen_object(vec4 vpos, mat4 mat, vec4 tp0, vec4 tp1) tcoord.x = dot(vpos, tp0); tcoord.y = dot(vpos, tp1); - + tcoord.z = 0; + tcoord.w = 1; + tcoord = mat * tcoord; return tcoord.xy; -- cgit v1.2.3 From 391893a325871317d05a466eaf818ad3cb54a8e9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 5 Jun 2024 12:12:48 -0400 Subject: Make LLLeap iterate over child stdout while read data is pending instead of using mutual recursion to exhaust the read buffer. --- indra/llcommon/llleap.cpp | 220 +++++++++++++++++++++++----------------------- 1 file changed, 108 insertions(+), 112 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index d0fb586459..e93ba83434 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -18,9 +18,6 @@ #include // std headers // external library headers -#include -#include -#include // other Linden headers #include "llerror.h" #include "llstring.h" @@ -64,7 +61,9 @@ public: // Pass it a callback to our connect() method, so it can send events // from a particular LLEventPump to the plugin without having to know // this class or method name. - mListener(new LLLeapListener(boost::bind(&LLLeapImpl::connect, this, _1, _2))) + mListener(new LLLeapListener( + [this](LLEventPump& pump, const std::string& listener) + { return connect(pump, listener); })) { // Rule out unpopulated Params block if (! cparams.executable.isProvided()) @@ -93,7 +92,7 @@ public: } // Listen for child "termination" right away to catch launch errors. - mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::bad_launch, this, _1)); + mDonePump.listen("LLLeap", [this](const LLSD& data){ return bad_launch(data); }); // Okay, launch child. // Get a modifiable copy of params block to set files and postend. @@ -113,7 +112,7 @@ public: // Okay, launch apparently worked. Change our mDonePump listener. mDonePump.stopListening("LLLeap"); - mDonePump.listen("LLLeap", boost::bind(&LLLeapImpl::done, this, _1)); + mDonePump.listen("LLLeap", [this](const LLSD& data){ return done(data); }); // Child might pump large volumes of data through either stdout or // stderr. Don't bother copying all that data into notification event. @@ -128,13 +127,9 @@ public: // Listening on stdout is stateful. In general, we're either waiting // for the length prefix or waiting for the specified length of data. - // We address that with two different listener methods -- one of which - // is blocked at any given time. + mReadPrefix = true; mStdoutConnection = childout.getPump() - .listen("prefix", boost::bind(&LLLeapImpl::rstdout, this, _1)); - mStdoutDataConnection = childout.getPump() - .listen("data", boost::bind(&LLLeapImpl::rstdoutData, this, _1)); - mBlocker.reset(new LLEventPump::Blocker(mStdoutDataConnection)); + .listen("LLLeap", [this](const LLSD& data){ return rstdout(data); }); // Log anything sent up through stderr. When a typical program // encounters an error, it writes its error message to stderr and @@ -142,7 +137,7 @@ public: // interpreter behaves that way. More generally, though, a plugin // author can log whatever s/he wants to the viewer log using stderr. mStderrConnection = childerr.getPump() - .listen("LLLeap", boost::bind(&LLLeapImpl::rstderr, this, _1)); + .listen("LLLeap", [this](const LLSD& data){ return rstderr(data); }); // For our lifespan, intercept any LL_ERRS so we can notify plugin mRecorder = LLError::addGenericRecorder( @@ -255,120 +250,120 @@ public: return false; } - // Initial state of stateful listening on child stdout: wait for a length - // prefix, followed by ':'. - bool rstdout(const LLSD& data) + // Stateful listening on child stdout: + // wait for a length prefix, followed by ':'. + bool rstdout(const LLSD&) { LLProcess::ReadPipe& childout(mChild->getReadPipe(LLProcess::STDOUT)); - // It's possible we got notified of a couple digit characters without - // seeing the ':' -- unlikely, but still. Until we see ':', keep - // waiting. - if (childout.contains(':')) + while (childout.size()) { - std::istream& childstream(childout.get_istream()); - // Saw ':', read length prefix and store in mExpect. - size_t expect; - childstream >> expect; - int colon(childstream.get()); - if (colon != ':') + /*----------------- waiting for length prefix ------------------*/ + if (mReadPrefix) { - // Protocol failure. Clear out the rest of the pending data in - // childout (well, up to a max length) to log what was wrong. - LLProcess::ReadPipe::size_type - readlen((std::min)(childout.size(), LLProcess::ReadPipe::size_type(80))); - bad_protocol(STRINGIZE(expect << char(colon) << childout.read(readlen))); + // It's possible we got notified of a couple digit characters without + // seeing the ':' -- unlikely, but still. Until we see ':', keep + // waiting. + if (! childout.contains(':')) + { + if (childout.contains('\n')) + { + // Since this is the initial listening state, this is where we'd + // arrive if the child isn't following protocol at all -- say + // because the user specified 'ls' or some darn thing. + bad_protocol(childout.getline()); + } + // Either way, stop looping. + break; + } + + // Saw ':', read length prefix and store in mExpect. + std::istream& childstream(childout.get_istream()); + size_t expect; + childstream >> expect; + int colon(childstream.get()); + if (colon != ':') + { + // Protocol failure. Clear out the rest of the pending data in + // childout (well, up to a max length) to log what was wrong. + LLProcess::ReadPipe::size_type + readlen((std::min)(childout.size(), + LLProcess::ReadPipe::size_type(80))); + bad_protocol(stringize(expect, char(colon), childout.read(readlen))); + break; + } + else + { + // Saw length prefix, saw colon, life is good. Now wait for + // that length of data to arrive. + mExpect = expect; + LL_DEBUGS("LLLeap") << "got length, waiting for " + << mExpect << " bytes of data" << LL_ENDL; + // Transition to "read data" mode and loop back to check + // if we've already received all the advertised data. + mReadPrefix = false; + continue; + } } + /*----------------- saw prefix, wait for data ------------------*/ else { - // Saw length prefix, saw colon, life is good. Now wait for - // that length of data to arrive. - mExpect = expect; - LL_DEBUGS("LLLeap") << "got length, waiting for " - << mExpect << " bytes of data" << LL_ENDL; - // Block calls to this method; resetting mBlocker unblocks - // calls to the other method. - mBlocker.reset(new LLEventPump::Blocker(mStdoutConnection)); - // Go check if we've already received all the advertised data. - if (childout.size()) + // Until we've accumulated the promised length of data, keep waiting. + if (childout.size() < mExpect) { - LLSD updata(data); - updata["len"] = LLSD::Integer(childout.size()); - rstdoutData(updata); + break; } - } - } - else if (childout.contains('\n')) - { - // Since this is the initial listening state, this is where we'd - // arrive if the child isn't following protocol at all -- say - // because the user specified 'ls' or some darn thing. - bad_protocol(childout.getline()); - } - return false; - } - // State in which we listen on stdout for the specified length of data to - // arrive. - bool rstdoutData(const LLSD& data) - { - LLProcess::ReadPipe& childout(mChild->getReadPipe(LLProcess::STDOUT)); - // Until we've accumulated the promised length of data, keep waiting. - if (childout.size() >= mExpect) - { - // Ready to rock and roll. - LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got " - << childout.size() << ", parsing LLSD" << LL_ENDL; - LLSD data; + // We have the data we were told to expect! Ready to rock and roll. + LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got " + << childout.size() << ", parsing LLSD" << LL_ENDL; + LLSD data; #if 1 - // specifically require notation LLSD from child - LLPointer parser(new LLSDNotationParser()); - S32 parse_status(parser->parse(childout.get_istream(), data, mExpect)); - if (parse_status == LLSDParser::PARSE_FAILURE) + // specifically require notation LLSD from child + LLPointer parser(new LLSDNotationParser()); + S32 parse_status(parser->parse(childout.get_istream(), data, mExpect)); + if (parse_status == LLSDParser::PARSE_FAILURE) #else - // SL-18330: accept any valid LLSD serialization format from child - // Unfortunately this runs into trouble we have not yet debugged. - bool parse_status(LLSDSerialize::deserialize(data, childout.get_istream(), mExpect)); - if (! parse_status) + // SL-18330: accept any valid LLSD serialization format from child + // Unfortunately this runs into trouble we have not yet debugged. + bool parse_status(LLSDSerialize::deserialize(data, childout.get_istream(), mExpect)); + if (! parse_status) #endif - { - bad_protocol("unparseable LLSD data"); - } - else if (! (data.isMap() && data["pump"].isString() && data.has("data"))) - { - // we got an LLSD object, but it lacks required keys - bad_protocol("missing 'pump' or 'data'"); - } - else - { - try { - // The LLSD object we got from our stream contains the - // keys we need. - LLEventPumps::instance().obtain(data["pump"]).post(data["data"]); + bad_protocol("unparseable LLSD data"); + break; } - catch (const std::exception& err) + else if (! (data.isMap() && data["pump"].isString() && data.has("data"))) { - // No plugin should be allowed to crash the viewer by - // driving an exception -- intentionally or not. - LOG_UNHANDLED_EXCEPTION(stringize("handling request ", data)); - // Whether or not the plugin added a "reply" key to the - // request, send a reply. We happen to know who originated - // this request, and the reply LLEventPump of interest. - // Not our problem if the plugin ignores the reply event. - data["reply"] = mReplyPump.getName(); - sendReply(llsd::map("error", - stringize(LLError::Log::classname(err), ": ", err.what())), - data); + // we got an LLSD object, but it lacks required keys + bad_protocol("missing 'pump' or 'data'"); + break; } - // Block calls to this method; resetting mBlocker unblocks - // calls to the other method. - mBlocker.reset(new LLEventPump::Blocker(mStdoutDataConnection)); - // Go check for any more pending events in the buffer. - if (childout.size()) + else { - LLSD updata(data); - data["len"] = LLSD::Integer(childout.size()); - rstdout(updata); + try + { + // The LLSD object we got from our stream contains the + // keys we need. + LLEventPumps::instance().obtain(data["pump"]).post(data["data"]); + } + catch (const std::exception& err) + { + // No plugin should be allowed to crash the viewer by + // driving an exception -- intentionally or not. + LOG_UNHANDLED_EXCEPTION(stringize("handling request ", data)); + // Whether or not the plugin added a "reply" key to the + // request, send a reply. We happen to know who originated + // this request, and the reply LLEventPump of interest. + // Not our problem if the plugin ignores the reply event. + data["reply"] = mReplyPump.getName(); + sendReply(llsd::map("error", + stringize(LLError::Log::classname(err), ": ", err.what())), + data); + } + // Transition to "read prefix" mode and go check for any + // more pending events in the buffer. + mReadPrefix = true; + continue; } } } @@ -453,7 +448,8 @@ private: // child's stdin, suitably enriched with the pump name on which it was // received. return pump.listen(listener, - boost::bind(&LLLeapImpl::wstdin, this, pump.getName(), _1)); + [this, name=pump.getName()](const LLSD& data) + { return wstdin(name, data); }); } std::string mDesc; @@ -461,11 +457,11 @@ private: LLEventStream mReplyPump; LLProcessPtr mChild; LLTempBoundListener - mStdinConnection, mStdoutConnection, mStdoutDataConnection, mStderrConnection; - std::unique_ptr mBlocker; + mStdinConnection, mStdoutConnection, mStderrConnection; LLProcess::ReadPipe::size_type mExpect; LLError::RecorderPtr mRecorder; std::unique_ptr mListener; + bool mReadPrefix; }; // These must follow the declaration of LLLeapImpl, so they may as well be last. -- cgit v1.2.3