diff options
author | Cosmic Linden <cosmic@lindenlab.com> | 2023-10-13 14:02:51 -0700 |
---|---|---|
committer | Cosmic Linden <cosmic@lindenlab.com> | 2023-10-13 14:02:51 -0700 |
commit | a91f08ba84844647bbcdecac11e85c449579527c (patch) | |
tree | 9bfdc77c9e7de33413b95f2648cb139b19cb06f0 /indra/llprimitive | |
parent | cc0f831aaa960552b218da436da57b44cb2dfe0f (diff) | |
parent | cba71633559ccdfd394983a6086da816e739a730 (diff) |
Merge branch 'DRTVWR-559' into DRTVWR-592
Diffstat (limited to 'indra/llprimitive')
-rw-r--r-- | indra/llprimitive/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.cpp | 297 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 45 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial_templates.h | 142 | ||||
-rw-r--r-- | indra/llprimitive/llmaterial.cpp | 29 | ||||
-rw-r--r-- | indra/llprimitive/llmaterial.h | 4 | ||||
-rw-r--r-- | indra/llprimitive/llmaterialid.h | 26 | ||||
-rw-r--r-- | indra/llprimitive/llprimitive.cpp | 2 |
8 files changed, 397 insertions, 149 deletions
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 76d261ab3e..2bd1edaacc 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -34,6 +34,7 @@ set(llprimitive_HEADER_FILES lldaeloader.h llgltfloader.h llgltfmaterial.h + llgltfmaterial_templates.h legacy_object_types.h llmaterial.h llmaterialid.h diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index c16803d39d..f42c11ee21 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -24,24 +24,28 @@ * $/LicenseInfo$ */ + #include "linden_common.h" #include "llgltfmaterial.h" +#include "llsdserialize.h" + // NOTE -- this should be the one and only place tiny_gltf.h is included #include "tinygltf/tiny_gltf.h" +#include "llgltfmaterial_templates.h" const char* const LLGLTFMaterial::ASSET_VERSION = "1.1"; const char* const LLGLTFMaterial::ASSET_TYPE = "GLTF 2.0"; const std::array<std::string, 2> LLGLTFMaterial::ACCEPTED_ASSET_VERSIONS = { "1.0", "1.1" }; -const char* const GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform"; -const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale"; -const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset"; -const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation"; +const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform"; +const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale"; +const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset"; +const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rotation"; // special UUID that indicates a null UUID in override data -static const LLUUID GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff"); +const LLUUID LLGLTFMaterial::GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff"); void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const { @@ -67,14 +71,14 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs) LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) { - //have to do a manual operator= because of LLRefCount + //have to do a manual operator= because of LLRefCount mTextureId = rhs.mTextureId; mTextureTransform = rhs.mTextureTransform; mBaseColor = rhs.mBaseColor; mEmissiveColor = rhs.mEmissiveColor; - + mMetallicFactor = rhs.mMetallicFactor; mRoughnessFactor = rhs.mRoughnessFactor; mAlphaCutoff = rhs.mAlphaCutoff; @@ -96,7 +100,7 @@ bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const mBaseColor == rhs.mBaseColor && mEmissiveColor == rhs.mEmissiveColor && - + mMetallicFactor == rhs.mMetallicFactor && mRoughnessFactor == rhs.mRoughnessFactor && mAlphaCutoff == rhs.mAlphaCutoff && @@ -121,6 +125,7 @@ bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, st return true; } + return false; } @@ -189,7 +194,8 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index) } } -LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value) +// static +LLVector2 LLGLTFMaterial::vec2FromJson(const tinygltf::Value::Object& object, const char* key, const LLVector2& default_value) { const auto it = object.find(key); if (it == object.end()) @@ -214,7 +220,8 @@ LLVector2 vec2_from_json(const tinygltf::Value::Object& object, const char* key, return value; } -F32 float_from_json(const tinygltf::Value::Object& object, const char* key, const F32 default_value) +// static +F32 LLGLTFMaterial::floatFromJson(const tinygltf::Value::Object& object, const char* key, const F32 default_value) { const auto it = object.find(key); if (it == object.end()) @@ -229,52 +236,6 @@ F32 float_from_json(const tinygltf::Value::Object& object, const char* key, cons return (F32)real_json.GetNumberAsDouble(); } -template<typename T> -std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info) -{ - const S32 texture_idx = texture_info.index; - if (texture_idx < 0 || texture_idx >= model.textures.size()) - { - return ""; - } - const tinygltf::Texture& texture = model.textures[texture_idx]; - - // Ignore texture.sampler for now - - const S32 image_idx = texture.source; - if (image_idx < 0 || image_idx >= model.images.size()) - { - return ""; - } - const tinygltf::Image& image = model.images[image_idx]; - - return image.uri; -} - -// *NOTE: Use template here as workaround for the different similar texture info classes -template<typename T> -void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id) -{ - LL_PROFILE_ZONE_SCOPED; - const std::string uri = gltf_get_texture_image(model, texture_info); - mTextureId[texture_info_id].set(uri); - - const tinygltf::Value::Object& extensions_object = texture_info.extensions; - const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM); - if (transform_it != extensions_object.end()) - { - const tinygltf::Value& transform_json = std::get<1>(*transform_it); - if (transform_json.IsObject()) - { - const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>(); - TextureTransform& transform = mTextureTransform[texture_info_id]; - transform.mOffset = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset()); - transform.mScale = vec2_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale()); - transform.mRotation = float_from_json(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation()); - } - } -} - void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const { LL_PROFILE_ZONE_SCOPED; @@ -301,7 +262,7 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const material_out.alphaMode = getAlphaMode(); material_out.alphaCutoff = mAlphaCutoff; - + mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor); if (mEmissiveColor != LLGLTFMaterial::getDefaultEmissiveColor()) @@ -319,7 +280,7 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const tinygltf::Value::Object extras; bool write_extras = false; if (mOverrideAlphaMode && mAlphaMode == getDefaultAlphaMode()) - { + { extras["override_alpha_mode"] = tinygltf::Value(mOverrideAlphaMode); write_extras = true; } @@ -338,57 +299,6 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const model.asset.version = "2.0"; } -template<typename T> -void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const std::string& uri) -{ - const S32 image_idx = model.images.size(); - model.images.emplace_back(); - model.images[image_idx].uri = uri; - - // The texture, not to be confused with the texture info - const S32 texture_idx = model.textures.size(); - model.textures.emplace_back(); - tinygltf::Texture& texture = model.textures[texture_idx]; - texture.source = image_idx; - - texture_info.index = texture_idx; -} - -template<typename T> -void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const -{ - LL_PROFILE_ZONE_SCOPED; - const LLUUID& texture_id = mTextureId[texture_info_id]; - const TextureTransform& transform = mTextureTransform[texture_info_id]; - const bool is_blank_transform = transform == sDefault.mTextureTransform[0]; - // Check if this material matches all the fallback values, and if so, then - // skip including it to reduce material size - if (!force_write && texture_id.isNull() && is_blank_transform) - { - return; - } - - // tinygltf will discard this texture info if there is no valid texture, - // causing potential loss of information for overrides, so ensure one is - // defined. -Cosmic,2023-01-30 - gltf_allocate_texture_image(model, texture_info, texture_id.asString()); - - if (!is_blank_transform) - { - tinygltf::Value::Object transform_map; - transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({ - tinygltf::Value(transform.mOffset.mV[VX]), - tinygltf::Value(transform.mOffset.mV[VY]) - })); - transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({ - tinygltf::Value(transform.mScale.mV[VX]), - tinygltf::Value(transform.mScale.mV[VY]) - })); - transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation); - texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map); - } -} - void LLGLTFMaterial::sanitizeAssetMaterial() { mTextureTransform = sDefault.mTextureTransform; @@ -402,19 +312,19 @@ bool LLGLTFMaterial::setBaseMaterial() return *this != old_override; } -bool LLGLTFMaterial::isClearedForBaseMaterial() -{ - LLGLTFMaterial cleared_override = sDefault; - cleared_override.setBaseMaterial(*this); - return *this == cleared_override; -} - // For material overrides only. Copies transforms from the old override. void LLGLTFMaterial::setBaseMaterial(const LLGLTFMaterial& old_override_mat) { mTextureTransform = old_override_mat.mTextureTransform; } +bool LLGLTFMaterial::isClearedForBaseMaterial() const +{ + LLGLTFMaterial cleared_override = sDefault; + cleared_override.setBaseMaterial(*this); + return *this == cleared_override; +} + // static void LLGLTFMaterial::hackOverrideUUID(LLUUID& id) @@ -515,7 +425,7 @@ void LLGLTFMaterial::setAlphaMode(const std::string& mode, bool for_override) { m = ALPHA_MODE_BLEND; } - + setAlphaMode(m, for_override); } @@ -693,6 +603,159 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) } } +void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) +{ + LL_PROFILE_ZONE_SCOPED; + llassert(data.isUndefined()); + + // make every effort to shave bytes here + + for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + LLUUID& texture_id = mTextureId[i]; + const LLUUID& override_texture_id = override_mat.mTextureId[i]; + if (override_texture_id.notNull() && override_texture_id != texture_id) + { + data["tex"][i] = LLSD::UUID(override_texture_id); + } + } + + if (override_mat.mBaseColor != getDefaultBaseColor()) + { + data["bc"] = override_mat.mBaseColor.getValue(); + } + + if (override_mat.mEmissiveColor != getDefaultEmissiveColor()) + { + data["ec"] = override_mat.mEmissiveColor.getValue(); + } + + if (override_mat.mMetallicFactor != getDefaultMetallicFactor()) + { + data["mf"] = override_mat.mMetallicFactor; + } + + if (override_mat.mRoughnessFactor != getDefaultRoughnessFactor()) + { + data["rf"] = override_mat.mRoughnessFactor; + } + + if (override_mat.mAlphaMode != getDefaultAlphaMode() || override_mat.mOverrideAlphaMode) + { + data["am"] = override_mat.mAlphaMode; + } + + if (override_mat.mAlphaCutoff != getDefaultAlphaCutoff()) + { + data["ac"] = override_mat.mAlphaCutoff; + } + + if (override_mat.mDoubleSided != getDefaultDoubleSided() || override_mat.mOverrideDoubleSided) + { + data["ds"] = override_mat.mDoubleSided; + } + + for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset()) + { + data["ti"][i]["o"] = override_mat.mTextureTransform[i].mOffset.getValue(); + } + + if (override_mat.mTextureTransform[i].mScale != getDefaultTextureScale()) + { + data["ti"][i]["s"] = override_mat.mTextureTransform[i].mScale.getValue(); + } + + if (override_mat.mTextureTransform[i].mRotation != getDefaultTextureRotation()) + { + data["ti"][i]["r"] = override_mat.mTextureTransform[i].mRotation; + } + } +} + + +void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data) +{ + const LLSD& tex = data["tex"]; + + if (tex.isArray()) + { + for (int i = 0; i < tex.size(); ++i) + { + mTextureId[i] = tex[i].asUUID(); + } + } + + const LLSD& bc = data["bc"]; + if (bc.isDefined()) + { + mBaseColor.setValue(bc); + } + + const LLSD& ec = data["ec"]; + if (ec.isDefined()) + { + mEmissiveColor.setValue(ec); + } + + const LLSD& mf = data["mf"]; + if (mf.isReal()) + { + mMetallicFactor = mf.asReal(); + } + + const LLSD& rf = data["rf"]; + if (rf.isReal()) + { + mRoughnessFactor = rf.asReal(); + } + + const LLSD& am = data["am"]; + if (am.isInteger()) + { + mAlphaMode = (AlphaMode) am.asInteger(); + } + + const LLSD& ac = data["ac"]; + if (ac.isReal()) + { + mAlphaCutoff = ac.asReal(); + } + + const LLSD& ds = data["ds"]; + if (ds.isBoolean()) + { + mDoubleSided = ds.asBoolean(); + mOverrideDoubleSided = true; + } + + const LLSD& ti = data["ti"]; + if (ti.isArray()) + { + for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + const LLSD& o = ti[i]["o"]; + if (o.isDefined()) + { + mTextureTransform[i].mOffset.setValue(o); + } + + const LLSD& s = ti[i]["s"]; + if (s.isDefined()) + { + mTextureTransform[i].mScale.setValue(s); + } + + const LLSD& r = ti[i]["r"]; + if (r.isReal()) + { + mTextureTransform[i].mRotation = r.asReal(); + } + } + } +} + LLUUID LLGLTFMaterial::getHash() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index ad7784f6d1..a078a530a4 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -35,10 +35,13 @@ #include "hbxxh.h" #include <string> +#include <map> namespace tinygltf { class Model; + struct TextureInfo; + class Value; } class LLTextureEntry; @@ -52,6 +55,9 @@ public: static const char* const ASSET_VERSION; static const char* const ASSET_TYPE; + // Max allowed size of a GLTF material asset or override, when serialized + // as a minified JSON string + static constexpr size_t MAX_ASSET_LENGTH = 2048; static const std::array<std::string, 2> ACCEPTED_ASSET_VERSIONS; static bool isAcceptedVersion(const std::string& version) { return std::find(ACCEPTED_ASSET_VERSIONS.cbegin(), ACCEPTED_ASSET_VERSIONS.cend(), version) != ACCEPTED_ASSET_VERSIONS.cend(); } @@ -64,6 +70,7 @@ public: void getPacked(F32 (&packed)[8]) const; bool operator==(const TextureTransform& other) const; + bool operator!=(const TextureTransform& other) const { return !(*this == other); } }; enum AlphaMode @@ -96,8 +103,13 @@ public: GLTF_TEXTURE_INFO_COUNT }; - std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId; + static const char* const GLTF_FILE_EXTENSION_TRANSFORM; + static const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE; + static const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET; + static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION; + static const LLUUID GLTF_OVERRIDE_NULL_UUID; + std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId; std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform; // NOTE: initialize values to defaults according to the GLTF spec @@ -137,7 +149,7 @@ public: void setAlphaMode(S32 mode, bool for_override = false); void setDoubleSided(bool double_sided, bool for_override = false); - //NOTE: texture offsets only exist in overrides, so "for_override" is not needed + // *NOTE: texture offsets only exist in overrides, so "for_override" is not needed void setTextureOffset(TextureInfo texture_info, const LLVector2& offset); void setTextureScale(TextureInfo texture_info, const LLVector2& scale); @@ -155,7 +167,6 @@ public: static LLVector2 getDefaultTextureScale(); static F32 getDefaultTextureRotation(); - static void hackOverrideUUID(LLUUID& id); static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id); @@ -164,7 +175,7 @@ public: void setAlphaMode(const std::string& mode, bool for_override = false); const char* getAlphaMode() const; - + // set the contents of this LLGLTFMaterial from the given json // returns true if successful // if unsuccessful, the contents of this LLGLTFMaterial should be left unchanged and false is returned @@ -185,6 +196,14 @@ public: void writeToModel(tinygltf::Model& model, S32 mat_index) const; void applyOverride(const LLGLTFMaterial& override_mat); + + // apply the given LLSD override data + void applyOverrideLLSD(const LLSD& data); + + // 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); // For base materials only (i.e. assets). Clears transforms to // default since they're not supported in assets yet. @@ -193,21 +212,29 @@ public: // For material overrides only. Clears most properties to // default/fallthrough, but preserves the transforms. bool setBaseMaterial(); + void setBaseMaterial(const LLGLTFMaterial& old_override_mat); // True if setBaseMaterial() was just called - bool isClearedForBaseMaterial(); + bool isClearedForBaseMaterial() const; // For local materials, they have to keep track of where // they are assigned to for full updates virtual void addTextureEntry(LLTextureEntry* te) {}; virtual void removeTextureEntry(LLTextureEntry* te) {}; -private: +protected: + static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value); + static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value); + + template<typename T> + static void allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri); + template<typename T> void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id); + template<typename T> + static void setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform); template<typename T> void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const; - - void setBaseMaterial(const LLGLTFMaterial& old_override_mat); + template<typename T> + static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false); }; - diff --git a/indra/llprimitive/llgltfmaterial_templates.h b/indra/llprimitive/llgltfmaterial_templates.h new file mode 100644 index 0000000000..f607dfe967 --- /dev/null +++ b/indra/llprimitive/llgltfmaterial_templates.h @@ -0,0 +1,142 @@ +/** + * @file llgltfmaterial_templates.h + * @brief Material template definition + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#pragma once + +#include "llgltfmaterial.h" + +// Use templates here as workaround for the different similar texture info classes in tinygltf +// Includer must first include tiny_gltf.h with the desired flags + +template<typename T> +std::string gltf_get_texture_image(const tinygltf::Model& model, const T& texture_info) +{ + const S32 texture_idx = texture_info.index; + if (texture_idx < 0 || texture_idx >= model.textures.size()) + { + return ""; + } + const tinygltf::Texture& texture = model.textures[texture_idx]; + + // Ignore texture.sampler for now + + const S32 image_idx = texture.source; + if (image_idx < 0 || image_idx >= model.images.size()) + { + return ""; + } + const tinygltf::Image& image = model.images[image_idx]; + + return image.uri; +} + +template<typename T> +void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id) +{ + setFromTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id]); + const std::string uri = gltf_get_texture_image(model, texture_info); +} + +// static +template<typename T> +void LLGLTFMaterial::setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform) +{ + LL_PROFILE_ZONE_SCOPED; + const std::string uri = gltf_get_texture_image(model, texture_info); + texture_id.set(uri); + + const tinygltf::Value::Object& extensions_object = texture_info.extensions; + const auto transform_it = extensions_object.find(GLTF_FILE_EXTENSION_TRANSFORM); + if (transform_it != extensions_object.end()) + { + const tinygltf::Value& transform_json = std::get<1>(*transform_it); + if (transform_json.IsObject()) + { + const tinygltf::Value::Object& transform_object = transform_json.Get<tinygltf::Value::Object>(); + transform.mOffset = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_OFFSET, getDefaultTextureOffset()); + transform.mScale = vec2FromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_SCALE, getDefaultTextureScale()); + transform.mRotation = floatFromJson(transform_object, GLTF_FILE_EXTENSION_TRANSFORM_ROTATION, getDefaultTextureRotation()); + } + } +} + +// static +template<typename T> +void LLGLTFMaterial::allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri) +{ + const S32 image_idx = model.images.size(); + model.images.emplace_back(); + model.images[image_idx].uri = uri; + + // The texture, not to be confused with the texture info + const S32 texture_idx = model.textures.size(); + model.textures.emplace_back(); + tinygltf::Texture& texture = model.textures[texture_idx]; + texture.source = image_idx; + + texture_info.index = texture_idx; +} + +// static +template<typename T> +void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write) const +{ + writeToTexture(model, texture_info, mTextureId[texture_info_id], mTextureTransform[texture_info_id], force_write); +} + +// static +template<typename T> +void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write) +{ + LL_PROFILE_ZONE_SCOPED; + const bool is_blank_transform = transform == sDefault.mTextureTransform[0]; + // Check if this material matches all the fallback values, and if so, then + // skip including it to reduce material size + if (!force_write && texture_id.isNull() && is_blank_transform) + { + return; + } + + // tinygltf will discard this texture info if there is no valid texture, + // causing potential loss of information for overrides, so ensure one is + // defined. -Cosmic,2023-01-30 + allocateTextureImage(model, texture_info, texture_id.asString()); + + if (!is_blank_transform) + { + tinygltf::Value::Object transform_map; + transform_map[GLTF_FILE_EXTENSION_TRANSFORM_OFFSET] = tinygltf::Value(tinygltf::Value::Array({ + tinygltf::Value(transform.mOffset.mV[VX]), + tinygltf::Value(transform.mOffset.mV[VY]) + })); + transform_map[GLTF_FILE_EXTENSION_TRANSFORM_SCALE] = tinygltf::Value(tinygltf::Value::Array({ + tinygltf::Value(transform.mScale.mV[VX]), + tinygltf::Value(transform.mScale.mV[VY]) + })); + transform_map[GLTF_FILE_EXTENSION_TRANSFORM_ROTATION] = tinygltf::Value(transform.mRotation); + texture_info.extensions[GLTF_FILE_EXTENSION_TRANSFORM] = tinygltf::Value(transform_map); + } +} diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp index 37525e4a3d..0d146de949 100644 --- a/indra/llprimitive/llmaterial.cpp +++ b/indra/llprimitive/llmaterial.cpp @@ -332,17 +332,6 @@ void LLMaterial::setAlphaMaskCutoff(U8 cutoff) mAlphaMaskCutoff = cutoff; } -LLUUID LLMaterial::getMaterialID() const -{ - // TODO - not null - return LLUUID::null; -} - -void LLMaterial::setMaterialID(const LLUUID &material_id) -{ - // TODO - set -} - LLSD LLMaterial::asLLSD() const { LLSD material_data; @@ -438,18 +427,18 @@ bool LLMaterial::operator != (const LLMaterial& rhs) const } -U32 LLMaterial::getShaderMask(U32 alpha_mode) +U32 LLMaterial::getShaderMask(U32 alpha_mode, BOOL is_alpha) { //NEVER incorporate this value into the message system -- this function will vary depending on viewer implementation - U32 ret = 0; - //two least significant bits are "diffuse alpha mode" - if (alpha_mode != DIFFUSE_ALPHA_MODE_DEFAULT) - { - ret = alpha_mode; - } - else + //two least significant bits are "diffuse alpha mode" + U32 ret = alpha_mode; + if (ret == DIFFUSE_ALPHA_MODE_DEFAULT) { - ret = getDiffuseAlphaMode(); + ret = getDiffuseAlphaMode(); + if (ret == DIFFUSE_ALPHA_MODE_BLEND && !is_alpha) + { + ret = DIFFUSE_ALPHA_MODE_NONE; + } } llassert(ret < SHADER_COUNT); diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h index d715671ae1..81f41ddc51 100644 --- a/indra/llprimitive/llmaterial.h +++ b/indra/llprimitive/llmaterial.h @@ -115,8 +115,6 @@ public: void setDiffuseAlphaMode(U8 alpha_mode); U8 getAlphaMaskCutoff() const; void setAlphaMaskCutoff(U8 cutoff); - LLUUID getMaterialID() const; - void setMaterialID(LLUUID const & material_id); bool isNull() const; static const LLMaterial null; @@ -124,7 +122,7 @@ public: bool operator == (const LLMaterial& rhs) const; bool operator != (const LLMaterial& rhs) const; - U32 getShaderMask(U32 alpha_mode = DIFFUSE_ALPHA_MODE_DEFAULT); + U32 getShaderMask(U32 alpha_mode, BOOL is_alpha); LLUUID getHash() const; protected: diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index e6165dfc91..5eb463b0fd 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -67,6 +67,14 @@ public: static const LLMaterialID null; + // Returns a 64 bits digest of the material Id, by XORing its two 64 bits + // long words. HB + inline U64 getDigest64() const + { + U64* tmp = (U64*)mID; + return tmp[0] ^ tmp[1]; + } + private: void parseFromBinary(const LLSD::Binary& pMaterialID); void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID); @@ -75,5 +83,23 @@ private: U8 mID[MATERIAL_ID_SIZE]; } ; +// std::hash implementation for LLMaterialID +namespace std +{ + template<> struct hash<LLMaterialID> + { + inline size_t operator()(const LLMaterialID& id) const noexcept + { + return (size_t)id.getDigest64(); + } + }; +} + +// For use with boost containers. +inline size_t hash_value(const LLMaterialID& id) noexcept +{ + return (size_t)id.getDigest64(); +} + #endif // LL_LLMATERIALID_H diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 5dfce4ae16..350d84ae6c 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -85,6 +85,8 @@ const F32 LIGHT_MAX_CUTOFF = 180.f; const F32 REFLECTION_PROBE_MIN_AMBIANCE = 0.f; const F32 REFLECTION_PROBE_MAX_AMBIANCE = 100.f; const F32 REFLECTION_PROBE_DEFAULT_AMBIANCE = 0.f; +// *NOTE: Clip distances are clamped in LLCamera::setNear. The max clip +// distance is currently limited by the skybox const F32 REFLECTION_PROBE_MIN_CLIP_DISTANCE = 0.f; const F32 REFLECTION_PROBE_MAX_CLIP_DISTANCE = 1024.f; const F32 REFLECTION_PROBE_DEFAULT_CLIP_DISTANCE = 0.f; |