From 6de0086ae9c678dafa8a26eb117279a487860f2f Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Wed, 15 May 2024 19:27:37 -0700 Subject: secondlife/viewer#1475: Add PBR terrain repeats editing --- indra/llprimitive/llgltfmaterial.cpp | 4 +- indra/llprimitive/llgltfmaterial.h | 2 +- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 11 + indra/newview/llfloaterregioninfo.cpp | 154 +++++- indra/newview/llfloaterregioninfo.h | 577 +++++++++---------- indra/newview/llpbrterrainfeatures.cpp | 198 +++++++ indra/newview/llpbrterrainfeatures.h | 48 ++ indra/newview/llviewerregion.cpp | 43 ++ indra/newview/llvlcomposition.cpp | 610 +++++++++++---------- indra/newview/llvlcomposition.h | 132 ++--- .../en/panel_region_terrain_texture_transform.xml | 263 +++++++++ .../xui/en/panel_settings_terrain_elevation.xml | 307 +++++++++++ .../xui/en/panel_settings_terrain_transform.xml | 365 ++++++++++++ 14 files changed, 2047 insertions(+), 669 deletions(-) create mode 100644 indra/newview/llpbrterrainfeatures.cpp create mode 100644 indra/newview/llpbrterrainfeatures.h create mode 100644 indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml create mode 100644 indra/newview/skins/default/xui/en/panel_settings_terrain_elevation.xml create mode 100644 indra/newview/skins/default/xui/en/panel_settings_terrain_transform.xml diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index 94bc5ef74c..008c72462c 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -681,7 +681,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) } } -void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) +void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) const { LL_PROFILE_ZONE_SCOPED; llassert(data.isUndefined()); @@ -690,7 +690,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { - LLUUID& texture_id = mTextureId[i]; + const LLUUID& texture_id = mTextureId[i]; const LLUUID& override_texture_id = override_mat.mTextureId[i]; if (override_texture_id.notNull() && override_texture_id != texture_id) { diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 67b22f56e2..e04b6d5eee 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -202,7 +202,7 @@ public: // Get the given override on this LLGLTFMaterial as LLSD // override_mat -- the override source data // data -- output LLSD object (should be passed in empty) - void getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data); + void getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) const; // For base materials only (i.e. assets). Clears transforms to // default since they're not supported in assets yet. diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e56534b84d..7568c08430 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -502,6 +502,7 @@ set(viewer_SOURCE_FILES llpathfindingobject.cpp llpathfindingobjectlist.cpp llpathfindingpathtool.cpp + llpbrterrainfeatures.cpp llpersistentnotificationstorage.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp @@ -1148,6 +1149,7 @@ set(viewer_HEADER_FILES llpathfindingobject.h llpathfindingobjectlist.h llpathfindingpathtool.h + llpbrterrainfeatures.h llpersistentnotificationstorage.h llphysicsmotion.h llphysicsshapebuilderutil.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c7999fc2e9..3c1f469f82 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9308,6 +9308,17 @@ Value 8.0 + RenderTerrainPBRTransformsEnabled + + Comment + EXPERIMENTAL: Enable PBR Terrain texture transforms. + Persist + 1 + Type + Boolean + Value + 0 + RenderTerrainPBRNormalsEnabled Comment diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 1f84da4b07..4b0e628a7e 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -68,6 +68,7 @@ #include "llnamelistctrl.h" #include "llnotifications.h" #include "llnotificationsutil.h" +#include "llpbrterrainfeatures.h" #include "llregioninfomodel.h" #include "llscrolllistitem.h" #include "llsliderctrl.h" @@ -263,7 +264,16 @@ bool LLFloaterRegionInfo::postBuild() panel = new LLPanelRegionTerrainInfo; mInfoPanels.push_back(panel); - panel->buildFromFile("panel_region_terrain.xml"); + static LLCachedControl feature_pbr_terrain_enabled(gSavedSettings, "RenderTerrainPBREnabled", false); + static LLCachedControl feature_pbr_terrain_transforms_enabled(gSavedSettings, "RenderTerrainPBRTransformsEnabled", false); + if (!feature_pbr_terrain_transforms_enabled || !feature_pbr_terrain_enabled) + { + panel->buildFromFile("panel_region_terrain.xml"); + } + else + { + panel->buildFromFile("panel_region_terrain_texture_transform.xml"); + } mTab->addTabPanel(panel); mEnvironmentPanel = new LLPanelRegionEnvironment; @@ -553,6 +563,20 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) } // else will rerequest on onOpen either way } +// static +void LLFloaterRegionInfo::sRefreshFromRegion(LLViewerRegion* region) +{ + if (region != gAgent.getRegion()) { return; } + + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance("region_info"); + if (!floater) { return; } + + if (floater->getVisible() && region == gAgent.getRegion()) + { + floater->refreshFromRegion(region); + } +} + // static LLPanelEstateInfo* LLFloaterRegionInfo::getPanelEstate() { @@ -825,6 +849,13 @@ void LLPanelRegionInfo::initCtrl(const std::string& name) getChild(name)->setCommitCallback(boost::bind(&LLPanelRegionInfo::onChangeAnything, this)); } +template +void LLPanelRegionInfo::initAndSetCtrl(CTRL*& ctrl, const std::string& name) +{ + initCtrl(name); + ctrl = findChild(name); +} + void LLPanelRegionInfo::onClickManageTelehub() { LLFloaterReg::hideInstance("region_info"); @@ -1494,11 +1525,17 @@ LLPanelRegionTerrainInfo::LLPanelRegionTerrainInfo() const LLUUID (&default_textures)[LLVLComposition::ASSET_COUNT] = LLVLComposition::getDefaultTextures(); for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { + mTextureDetailCtrl[i] = nullptr; + mMaterialDetailCtrl[i] = nullptr; + mLastSetTextures[i] = default_textures[i]; - } - for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { mLastSetMaterials[i] = BLANK_MATERIAL_ASSET_ID; + + mMaterialScaleUCtrl[i] = nullptr; + mMaterialScaleVCtrl[i] = nullptr; + mMaterialRotationCtrl[i] = nullptr; + mMaterialOffsetUCtrl[i] = nullptr; + mMaterialOffsetVCtrl[i] = nullptr; } } @@ -1517,22 +1554,21 @@ bool LLPanelRegionTerrainInfo::postBuild() std::string buffer; - for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { - buffer = llformat("texture_detail_%d", i); - initCtrl(buffer); - mTextureDetailCtrl[i] = findChild(buffer); - if (mTextureDetailCtrl) + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + initAndSetCtrl(mTextureDetailCtrl[i], llformat("texture_detail_%d", i)); + if (mTextureDetailCtrl[i]) { mTextureDetailCtrl[i]->setBakeTextureEnabled(false); } - } - for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) - { - buffer = llformat("material_detail_%d", i); - initCtrl(buffer); - mMaterialDetailCtrl[i] = findChild(buffer); - } + initAndSetCtrl(mMaterialDetailCtrl[i], llformat("material_detail_%d", i)); + + initAndSetCtrl(mMaterialScaleUCtrl[i], llformat("terrain%dScaleU", i)); + initAndSetCtrl(mMaterialScaleVCtrl[i], llformat("terrain%dScaleV", i)); + initAndSetCtrl(mMaterialRotationCtrl[i], llformat("terrain%dRotation", i)); + initAndSetCtrl(mMaterialOffsetUCtrl[i], llformat("terrain%dOffsetU", i)); + initAndSetCtrl(mMaterialOffsetVCtrl[i], llformat("terrain%dOffsetV", i)); + } for(S32 i = 0; i < CORNER_COUNT; ++i) { @@ -1583,6 +1619,17 @@ void LLPanelRegionTerrainInfo::updateForMaterialType() } } + // Toggle visibility of terrain tabs + LLTabContainer* terrain_tabs = findChild("terrain_tabs"); + if (terrain_tabs) + { + LLPanel* pbr_terrain_repeats_tab = findChild("terrain_transform_panel"); + if (pbr_terrain_repeats_tab) + { + terrain_tabs->setTabVisibility(pbr_terrain_repeats_tab, show_material_controls); + } + } + // Toggle visibility of labels LLUICtrl* texture_label = findChild("detail_texture_text"); if (texture_label) { texture_label->setVisible(show_texture_controls); } @@ -1711,6 +1758,21 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) } } + for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + if (!mMaterialScaleUCtrl[i] || !mMaterialScaleVCtrl[i] || !mMaterialRotationCtrl[i] || !mMaterialOffsetUCtrl[i] || !mMaterialOffsetVCtrl[i]) { continue; } + const LLGLTFMaterial* mat_override = compp->getMaterialOverride(i); + if (!mat_override) { mat_override = &LLGLTFMaterial::sDefault; } + + // Assume all texture transforms have the same value + const LLGLTFMaterial::TextureTransform& transform = mat_override->mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]; + mMaterialScaleUCtrl[i]->setValue(transform.mScale.mV[VX]); + mMaterialScaleVCtrl[i]->setValue(transform.mScale.mV[VY]); + mMaterialRotationCtrl[i]->setValue(transform.mRotation * RAD_TO_DEG); + mMaterialOffsetUCtrl[i]->setValue(transform.mOffset.mV[VX]); + mMaterialOffsetVCtrl[i]->setValue(transform.mOffset.mV[VY]); + } + std::string buffer; for(S32 i = 0; i < CORNER_COUNT; ++i) { @@ -1725,7 +1787,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) LL_DEBUGS() << "no region set" << LL_ENDL; getChild("region_text")->setValue(LLSD("")); } - + // Update visibility of terrain swatches, etc refresh(); @@ -1740,7 +1802,14 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) // virtual bool LLPanelRegionTerrainInfo::sendUpdate() { - LL_INFOS() << "LLPanelRegionTerrainInfo::sendUpdate" << LL_ENDL; + LL_INFOS() << __FUNCTION__ << LL_ENDL; + + LLUICtrl* apply_btn = getChild("apply_btn"); + if (apply_btn && !apply_btn->getEnabled()) + { + LL_WARNS() << "Duplicate update, ignored" << LL_ENDL; + return false; + } // Make sure user hasn't chosen wacky textures. if (!validateTextureSizes()) @@ -1841,7 +1910,52 @@ bool LLPanelRegionTerrainInfo::sendUpdate() sendEstateOwnerMessage(msg, "texturecommit", invoice, strings); - return true; + // ======================================== + // POST to ModifyRegion endpoint, if enabled + + static LLCachedControl feature_pbr_terrain_transforms_enabled(gSavedSettings, "RenderTerrainPBRTransformsEnabled", false); + if (material_type == LLTerrainMaterials::Type::PBR && feature_pbr_terrain_transforms_enabled) + { + LLTerrainMaterials composition; + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + LLPointer mat_override = new LLGLTFMaterial(); + + const bool transform_controls_valid = mMaterialScaleUCtrl[i] && mMaterialScaleVCtrl[i] && mMaterialRotationCtrl[i] && mMaterialOffsetUCtrl[i] && mMaterialOffsetVCtrl[i]; + if (transform_controls_valid) + { + // Set texture transforms for all texture infos to the same value, + // because the PBR terrain shader doesn't currently support + // different transforms per texture info. See also + // LLDrawPoolTerrain::renderFullShaderPBR . + for (U32 tt = 0; tt < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++tt) + { + LLGLTFMaterial::TextureTransform& transform = mat_override->mTextureTransform[tt]; + transform.mScale.mV[VX] = mMaterialScaleUCtrl[i]->getValue().asReal(); + transform.mScale.mV[VY] = mMaterialScaleVCtrl[i]->getValue().asReal(); + transform.mRotation = mMaterialRotationCtrl[i]->getValue().asReal() * DEG_TO_RAD; + transform.mOffset.mV[VX] = mMaterialOffsetUCtrl[i]->getValue().asReal(); + transform.mOffset.mV[VY] = mMaterialOffsetVCtrl[i]->getValue().asReal(); + } + } + + if (*mat_override == LLGLTFMaterial::sDefault) { mat_override = nullptr; } + composition.setMaterialOverride(i, mat_override.get()); + } + + // queueModify leads to a few messages being sent back and forth: + // viewer: POST ModifyRegion + // simulator: RegionHandshake + // viewer: GET ModifyRegion + LLViewerRegion* region = gAgent.getRegion(); + llassert(region); + if (region) + { + LLPBRTerrainFeatures::queueModify(*region, composition); + } + } + + return true; } bool LLPanelRegionTerrainInfo::callbackTextureHeights(const LLSD& notification, const LLSD& response) diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 4b81a26210..81167efdad 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,59 @@ 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; + void onOpen(const LLSD& key) override; + void onClose(bool app_quitting) override; bool postBuild() override; - static void processEstateOwnerRequest(LLMessageSystem* msg, void**); - - // 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 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; - - void onRegionChanged(); - void requestRegionInfo(); - void enableTopButtons(); - void disableTopButtons(); + static void processEstateOwnerRequest(LLMessageSystem* msg, void**); + + // get and process region info if necessary. + static void processRegionInfo(LLMessageSystem* msg); + static void sRefreshFromRegion(LLViewerRegion* region); + + 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(); + + // from LLPanel + void refresh() override; + + 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 +137,43 @@ 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; } - + 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(); - + 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); + template void initAndSetCtrl(CTRL*& ctrl, 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 +182,30 @@ protected: class LLPanelRegionGeneralInfo : public LLPanelRegionInfo { - + public: - LLPanelRegionGeneralInfo() - : LLPanelRegionInfo() {} - ~LLPanelRegionGeneralInfo() {} - - bool refreshFromRegion(LLViewerRegion* region) override; - + LLPanelRegionGeneralInfo() + : LLPanelRegionInfo() {} + ~LLPanelRegionGeneralInfo() {} + + bool refreshFromRegion(LLViewerRegion* region) override; + bool postBuild() override; - - void onBtnSet(); - void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} + + 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,73 +214,80 @@ protected: class LLPanelRegionDebugInfo : public LLPanelRegionInfo { public: - LLPanelRegionDebugInfo() - : LLPanelRegionInfo(), mTargetAvatar() {} - ~LLPanelRegionDebugInfo() {} + LLPanelRegionDebugInfo() + : LLPanelRegionInfo(), mTargetAvatar() {} + ~LLPanelRegionDebugInfo() {} bool postBuild() override; - - bool refreshFromRegion(LLViewerRegion* region) 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); - + 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() {} - + 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(); - //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; private: - bool mConfirmedTextureHeights; - bool mAskedTextureHeights; + 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]; + + LLSpinCtrl* mMaterialScaleUCtrl[LLTerrainMaterials::ASSET_COUNT]; + LLSpinCtrl* mMaterialScaleVCtrl[LLTerrainMaterials::ASSET_COUNT]; + LLSpinCtrl* mMaterialRotationCtrl[LLTerrainMaterials::ASSET_COUNT]; + LLSpinCtrl* mMaterialOffsetUCtrl[LLTerrainMaterials::ASSET_COUNT]; + LLSpinCtrl* mMaterialOffsetVCtrl[LLTerrainMaterials::ASSET_COUNT]; }; ///////////////////////////////////////////////////////////////////////////// @@ -286,59 +295,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; - + 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 updateChild(LLUICtrl* child_ctrl) override; + void refresh() override; - void refreshFromEstate(); - - static bool isLindenEstate(); - - const std::string getOwnerName() const; - void setOwnerName(const std::string& name); + 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); - - void commitEstateAccess(); - void commitEstateManagers(); + // confirmation dialog callback + bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response); - bool checkSunHourSlider(LLUICtrl* child_ctrl); + void commitEstateAccess(); + void commitEstateManagers(); + + bool checkSunHourSlider(LLUICtrl* child_ctrl); - U32 mEstateID; + U32 mEstateID; }; ///////////////////////////////////////////////////////////////////////////// @@ -346,59 +355,59 @@ protected: class LLPanelEstateCovenant : public LLPanelRegionInfo { public: - LLPanelEstateCovenant(); - ~LLPanelEstateCovenant() {} - + 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; + 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; + LLTextBox* mEstateNameText; + LLTextBox* mEstateOwnerText; + LLTextBox* mLastModifiedText; + // CovenantID from sim + LLUUID mCovenantID; + LLViewerTextEditor* mEditor; + EAssetStatus mAssetStatus; }; ///////////////////////////////////////////////////////////////////////////// @@ -409,96 +418,96 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo LOG_CLASS(LLPanelRegionExperiences); public: - LLPanelRegionExperiences(){} + LLPanelRegionExperiences(){} bool postBuild() override; + + static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); + static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); - 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 ); + 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; 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; + 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/llpbrterrainfeatures.cpp b/indra/newview/llpbrterrainfeatures.cpp new file mode 100644 index 0000000000..87720395f4 --- /dev/null +++ b/indra/newview/llpbrterrainfeatures.cpp @@ -0,0 +1,198 @@ +/** + * @file llpbrterrainfeatures.cpp + * + * $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 "llpbrterrainfeatures.h" + +#include "llappviewer.h" +#include "llgltfmaterial.h" +#include "llviewerregion.h" +#include "llvlcomposition.h" + +LLPBRTerrainFeatures gPBRTerrainFeatures; + +// static +void LLPBRTerrainFeatures::queueQuery(LLViewerRegion& region, void(*done_callback)(LLUUID, bool, const LLModifyRegion&)) +{ + llassert(on_main_thread()); + llassert(LLCoros::on_main_coro()); + + LLUUID region_id = region.getRegionID(); + + LLCoros::instance().launch("queryRegionCoro", + std::bind(&LLPBRTerrainFeatures::queryRegionCoro, + region.getCapability("ModifyRegion"), + region_id, + done_callback)); +} + +// static +void LLPBRTerrainFeatures::queueModify(LLViewerRegion& region, const LLModifyRegion& composition) +{ + llassert(on_main_thread()); + llassert(LLCoros::on_main_coro()); + + LLSD updates = LLSD::emptyMap(); + + LLSD override_updates = LLSD::emptyArray(); + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + const LLGLTFMaterial* material_override = composition.getMaterialOverride(i); + LLSD override_update; + if (material_override) + { + LLGLTFMaterial::sDefault.getOverrideLLSD(*material_override, override_update); + } + else + { + override_update = LLSD::emptyMap(); + } + override_updates.append(override_update); + } + updates["overrides"] = override_updates; + + LLCoros::instance().launch("modifyRegionCoro", + std::bind(&LLPBRTerrainFeatures::modifyRegionCoro, + region.getCapability("ModifyRegion"), // TODO: May actually need a cap for this + updates, + nullptr)); +} + +// static +void LLPBRTerrainFeatures::queryRegionCoro(std::string cap_url, LLUUID region_id, void(*done_callback)(LLUUID, bool, const LLModifyRegion&) ) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("queryRegionCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpHeaders::ptr_t httpHeaders; + + httpOpts->setFollowRedirects(true); + + LL_DEBUGS("GLTF") << "Querying features via ModifyRegion endpoint" << LL_ENDL; + + LLSD result = httpAdapter->getAndSuspend(httpRequest, cap_url, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + bool success = true; + if (!status || !result["success"].asBoolean()) + { + if (result["message"].isUndefined()) + { + LL_WARNS("PBRTerrain") << "Failed to query PBR terrain features." << LL_ENDL; + } + else + { + LL_WARNS("PBRTerrain") << "Failed to query PBR terrain features: " << result["message"] << LL_ENDL; + } + success = false; + } + + LLTerrainMaterials* composition = new LLTerrainMaterials(); + + if (success) + { + const LLSD& overrides = result["overrides"]; + if (!overrides.isArray() || overrides.size() < LLTerrainMaterials::ASSET_COUNT) + { + LL_WARNS("PBRTerrain") << "Invalid composition format: Missing/invalid overrides" << LL_ENDL; + success = false; + } + else + { + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + const LLSD& override_llsd = overrides[i]; + LLPointer material_override = new LLGLTFMaterial(); + material_override->applyOverrideLLSD(override_llsd); + if (*material_override == LLGLTFMaterial::sDefault) + { + material_override = nullptr; + } + composition->setMaterialOverride(i, material_override.get()); + } + } + } + + if (done_callback) + { + LLAppViewer::instance()->postToMainCoro([=]() + { + done_callback(region_id, success, *composition); + delete composition; + }); + } + else + { + delete composition; + } +} + +// static +void LLPBRTerrainFeatures::modifyRegionCoro(std::string cap_url, LLSD updates, void(*done_callback)(bool) ) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("modifyRegionCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + LLCore::HttpHeaders::ptr_t httpHeaders; + + httpOpts->setFollowRedirects(true); + + LL_DEBUGS("GLTF") << "Applying features via ModifyRegion endpoint: " << updates << LL_ENDL; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, cap_url, updates, httpOpts, httpHeaders); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + bool success = true; + if (!status || !result["success"].asBoolean()) + { + if (result["message"].isUndefined()) + { + LL_WARNS("PBRTerrain") << "Failed to modify PBR terrain features." << LL_ENDL; + } + else + { + LL_WARNS("PBRTerrain") << "Failed to modify PBR terrain features: " << result["message"] << LL_ENDL; + } + success = false; + } + + if (done_callback) + { + LLAppViewer::instance()->postToMainCoro([=]() + { + done_callback(success); + }); + } +} + diff --git a/indra/newview/llpbrterrainfeatures.h b/indra/newview/llpbrterrainfeatures.h new file mode 100644 index 0000000000..f29d4ebf50 --- /dev/null +++ b/indra/newview/llpbrterrainfeatures.h @@ -0,0 +1,48 @@ +/** + * @file llpbrterrainfeatures.h + * + * $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$ + */ + + +#pragma once + +#include + +class LLViewerRegion; +class LLMessageSystem; +class LLModifyRegion; + +// Queries/modifies PBR terrain repeats, possibly other features in the future +class LLPBRTerrainFeatures +{ +public: + static void queueQuery(LLViewerRegion& region, void(*done_callback)(LLUUID, bool, const LLModifyRegion&)); + static void queueModify(LLViewerRegion& region, const LLModifyRegion& composition); + +private: + static void queryRegionCoro(std::string cap_url, LLUUID region_id, void(*done_callback)(LLUUID, bool, const LLModifyRegion&) ); + static void modifyRegionCoro(std::string cap_url, LLSD updates, void(*done_callback)(bool) ); +}; + +extern LLPBRTerrainFeatures gPBRTerrainFeatures; + diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index bf4bdfd252..699cde8969 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -55,6 +55,7 @@ #include "llfloaterregioninfo.h" #include "llgltfmateriallist.h" #include "llhttpnode.h" +#include "llpbrterrainfeatures.h" #include "llregioninfomodel.h" #include "llsdutil.h" #include "llstartup.h" @@ -2462,6 +2463,26 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) gSavedSettings.setS32("max_texture_dimension_Y", 1024); } + if (features.has("PBRTerrainEnabled")) + { + bool enabled = features["PBRTerrainEnabled"]; + gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled); + } + else + { + gSavedSettings.setBOOL("RenderTerrainPBREnabled", false); + } + + if (features.has("PBRMaterialSwatchEnabled")) + { + bool enabled = features["PBRMaterialSwatchEnabled"]; + gSavedSettings.setBOOL("UIPreviewMaterial", enabled); + } + else + { + gSavedSettings.setBOOL("UIPreviewMaterial", false); + } + if (features.has("GLTFEnabled")) { bool enabled = features["GLTFEnabled"]; @@ -2471,6 +2492,16 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) { gSavedSettings.setBOOL("GLTFEnabled", false); } + + if (features.has("PBRTerrainTransformsEnabled")) + { + bool enabled = features["PBRTerrainTransformsEnabled"]; + gSavedSettings.setBOOL("RenderTerrainTransformsPBREnabled", enabled); + } + else + { + gSavedSettings.setBOOL("RenderTerrainTransformsPBREnabled", false); + } }; @@ -3109,6 +3140,17 @@ void LLViewerRegion::unpackRegionHandshake() { compp->setParamsReady(); } + + LLPBRTerrainFeatures::queueQuery(*this, [](LLUUID region_id, bool success, const LLModifyRegion& composition_changes) + { + if (!success) { return; } + LLViewerRegion* region = LLWorld::getInstance()->getRegionFromID(region_id); + if (!region) { return; } + LLVLComposition* compp = region->getComposition(); + if (!compp) { return; } + compp->apply(composition_changes); + LLFloaterRegionInfo::sRefreshFromRegion(region); + }); } @@ -3206,6 +3248,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("MapLayerGod"); capabilityNames.append("MeshUploadFlag"); capabilityNames.append("ModifyMaterialParams"); + capabilityNames.append("ModifyRegion"); capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("ObjectAnimation"); diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index bc2fab99c0..4c226073d3 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$ */ @@ -115,6 +115,16 @@ LLTerrainMaterials::~LLTerrainMaterials() unboost(); } +void LLTerrainMaterials::apply(const LLModifyRegion& other) +{ + for (S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) + { + const LLGLTFMaterial* other_override = other.getMaterialOverride(i); + LLGLTFMaterial* material_override = other_override ? new LLGLTFMaterial(*other_override) : nullptr; + setMaterialOverride(i, material_override); + } +} + bool LLTerrainMaterials::generateMaterials() { if (texturesReady(true, true)) @@ -161,7 +171,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,16 +193,16 @@ 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); mDetailRenderMaterials[asset] = nullptr; mMaterialTexturesSet[asset] = false; } -const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) +const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) const { return mDetailMaterialOverrides[asset]; } @@ -208,7 +218,7 @@ void LLTerrainMaterials::setMaterialOverride(S32 asset, LLGLTFMaterial* mat_over 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; @@ -418,24 +428,24 @@ const LLUUID (&LLVLComposition::getDefaultTextures())[ASSET_COUNT] LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale) : LLTerrainMaterials(), - LLViewerLayer(width, scale), - mParamsReady(false) + LLViewerLayer(width, scale), + mParamsReady(false) { - // 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"); + } } @@ -447,117 +457,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(); } @@ -665,22 +675,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) @@ -692,11 +702,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; @@ -769,14 +779,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 @@ -786,7 +796,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); @@ -797,8 +807,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) { @@ -812,150 +822,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++) @@ -968,38 +978,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 f7590348f0..5e6fe52f5f 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$ */ @@ -38,16 +38,24 @@ class LLViewerFetchedTexture; class LLGLTFMaterial; class LLFetchedGLTFMaterial; -class LLTerrainMaterials +class LLModifyRegion { public: - friend class LLDrawPoolTerrain; + virtual const LLGLTFMaterial* getMaterialOverride(S32 asset) const = 0; +}; + +class LLTerrainMaterials : public LLModifyRegion +{ +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. + void apply(const LLModifyRegion& other); + + // 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 @@ -57,14 +65,14 @@ public: COUNT }; - bool generateMaterials(); + bool generateMaterials(); void boost(); - virtual LLUUID getDetailAssetID(S32 asset); - virtual void setDetailAssetID(S32 asset, const LLUUID& id); - virtual const LLGLTFMaterial* getMaterialOverride(S32 asset); - virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override); + virtual LLUUID getDetailAssetID(S32 asset); + virtual void setDetailAssetID(S32 asset, const LLUUID& id); + const LLGLTFMaterial* getMaterialOverride(S32 asset) const override; + virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override); Type getMaterialType(); bool texturesReady(bool boost, bool strict); // strict = true -> all materials must be sufficiently loaded @@ -80,8 +88,8 @@ protected: // *NOTE: Prefer calling materialReady if mat is known to be LLFetchedGLTFMaterial static bool materialTexturesReady(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]; LLPointer mDetailMaterialOverrides[ASSET_COUNT]; LLPointer mDetailRenderMaterials[ASSET_COUNT]; bool mMaterialTexturesSet[ASSET_COUNT]; @@ -93,61 +101,61 @@ 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]; - - LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); - /*virtual*/ ~LLVLComposition(); - - 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); - bool generateTexture(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 - }; - - 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); - - friend class LLVOSurfacePatch; - friend class LLDrawPoolTerrain; - void setParamsReady() { mParamsReady = true; } - bool getParamsReady() const { return mParamsReady; } + static const LLUUID (&getDefaultTextures())[ASSET_COUNT]; + + LLVLComposition(LLSurface *surfacep, const U32 width, const F32 scale); + /*virtual*/ ~LLVLComposition(); + + 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); + bool generateTexture(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 + }; + + 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); + + friend class LLVOSurfacePatch; + friend class LLDrawPoolTerrain; + void setParamsReady() { mParamsReady = true; } + bool getParamsReady() const { return mParamsReady; } protected: - 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/skins/default/xui/en/panel_region_terrain_texture_transform.xml b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml new file mode 100644 index 0000000000..cbcbe418cd --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_region_terrain_texture_transform.xml @@ -0,0 +1,263 @@ + + + + Region: + + + unknown + + + Terrain Textures + + + Terrain Materials + + + + + + + + + + + + 1 (Low) + + + 2 + + + 3 + + + 4 (High) + + + + + + + + + +