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 3dc72553dc..498b14e211 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..1c4874eae5 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; } } @@ -1519,19 +1556,18 @@ bool LLPanelRegionTerrainInfo::postBuild() for(S32 i = 0; i < LLTerrainMaterials::ASSET_COUNT; ++i) { - buffer = llformat("texture_detail_%d", i); - initCtrl(buffer); - mTextureDetailCtrl[i] = findChild(buffer); - if (mTextureDetailCtrl) + 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,6 +1910,51 @@ bool LLPanelRegionTerrainInfo::sendUpdate() sendEstateOwnerMessage(msg, "texturecommit", invoice, strings); + // ======================================== + // 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; } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 4b81a26210..1634683d90 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$ */ @@ -85,6 +85,7 @@ public: // 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(); } @@ -101,14 +102,14 @@ public: // from LLPanel void refresh() override; - + void onRegionChanged(); void requestRegionInfo(); void enableTopButtons(); void disableTopButtons(); private: - + LLFloaterRegionInfo(const LLSD& seed); ~LLFloaterRegionInfo(); @@ -137,30 +138,31 @@ 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(); - + protected: 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( @@ -168,8 +170,8 @@ protected: const std::string& request, const LLUUID& invoice, const strings_t& strings); - - + + // member data LLHost mHost; }; @@ -180,16 +182,16 @@ 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;} @@ -217,9 +219,9 @@ public: ~LLPanelRegionDebugInfo() {} bool postBuild() override; - + bool refreshFromRegion(LLViewerRegion* region) override; - + protected: bool sendUpdate() override; @@ -233,7 +235,7 @@ protected: bool callbackRestart(const LLSD& notification, const LLSD& response); static void onClickCancelRestart(void* data); static void onClickDebugConsole(void* data); - + private: LLUUID mTargetAvatar; }; @@ -247,9 +249,9 @@ class LLPanelRegionTerrainInfo : public LLPanelRegionInfo public: 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 @@ -258,7 +260,7 @@ public: bool validateTextureHeights(); //static void onChangeAnything(LLUICtrl* ctrl, void* userData); // callback for any change, to enable commit button - + void onSelectMaterialType(); void updateForMaterialType(); @@ -277,8 +279,15 @@ private: 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]; }; ///////////////////////////////////////////////////////////////////////////// @@ -287,13 +296,13 @@ class LLPanelEstateInfo : public LLPanelRegionInfo { public: static void initDispatch(LLDispatcher& dispatch); - + void onChangeFixedSun(); void onChangeUseGlobalTime(); void onChangeAccessOverride(); - + void onClickEditSky(); - void onClickEditSkyHelp(); + void onClickEditSkyHelp(); void onClickEditDayCycle(); void onClickEditDayCycleHelp(); @@ -305,26 +314,26 @@ public: 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); @@ -335,7 +344,7 @@ protected: void commitEstateAccess(); void commitEstateManagers(); - + bool checkSunHourSlider(LLUICtrl* child_ctrl); U32 mEstateID; @@ -348,7 +357,7 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo public: LLPanelEstateCovenant(); ~LLPanelEstateCovenant() {} - + bool postBuild() override; void updateChild(LLUICtrl* child_ctrl) override; bool refreshFromRegion(LLViewerRegion* region) override; @@ -411,7 +420,7 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo public: LLPanelRegionExperiences(){} bool postBuild() override; - + static bool experienceCoreConfirm(const LLSD& notification, const LLSD& response); static void sendEstateExperienceDelta(U32 flags, const LLUUID& agent_id); @@ -473,7 +482,7 @@ private: 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); diff --git a/indra/newview/llpbrterrainfeatures.cpp b/indra/newview/llpbrterrainfeatures.cpp new file mode 100644 index 0000000000..bb771c6963 --- /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"), + 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..c509d656e1 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)) @@ -192,7 +202,7 @@ void LLTerrainMaterials::setDetailAssetID(S32 asset, const LLUUID& id) mMaterialTexturesSet[asset] = false; } -const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) +const LLGLTFMaterial* LLTerrainMaterials::getMaterialOverride(S32 asset) const { return mDetailMaterialOverrides[asset]; } @@ -461,7 +471,7 @@ bool LLVLComposition::generateHeights(const F32 x, const F32 y, llassert(mSurfacep); - if (!mSurfacep || !mSurfacep->getRegion()) + if (!mSurfacep || !mSurfacep->getRegion()) { // We don't always have the region yet here.... return false; @@ -529,7 +539,7 @@ bool LLVLComposition::generateHeights(const F32 x, const F32 y, 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 + // Choose material value by adding to the exact height a random value // vec1[0] = vec[0]*(0.2222222222f); vec1[1] = vec[1]*(0.2222222222f); @@ -863,7 +873,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, U32 st_comps = 3; U32 st_width = BASE_SIZE; U32 st_height = BASE_SIZE; - + if (tex_comps != st_comps) { llassert(false); @@ -968,7 +978,7 @@ bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y, { unboost_minimap_material(mDetailMaterials[i]); } - + return true; } diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h index f7590348f0..a003f74eda 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,7 +38,13 @@ class LLViewerFetchedTexture; class LLGLTFMaterial; class LLFetchedGLTFMaterial; -class LLTerrainMaterials +class LLModifyRegion +{ +public: + virtual const LLGLTFMaterial* getMaterialOverride(S32 asset) const = 0; +}; + +class LLTerrainMaterials : public LLModifyRegion { public: friend class LLDrawPoolTerrain; @@ -46,6 +52,8 @@ public: LLTerrainMaterials(); virtual ~LLTerrainMaterials(); + 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; @@ -63,7 +71,7 @@ public: virtual LLUUID getDetailAssetID(S32 asset); virtual void setDetailAssetID(S32 asset, const LLUUID& id); - virtual const LLGLTFMaterial* getMaterialOverride(S32 asset); + const LLGLTFMaterial* getMaterialOverride(S32 asset) const override; virtual void setMaterialOverride(S32 asset, LLGLTFMaterial* mat_override); Type getMaterialType(); bool texturesReady(bool boost, bool strict); @@ -107,8 +115,8 @@ public: 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); + 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 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) + + + + + + + + + +