diff options
| author | Cosmic Linden <cosmic@lindenlab.com> | 2023-02-09 15:04:46 -0800 | 
|---|---|---|
| committer | Cosmic Linden <cosmic@lindenlab.com> | 2023-02-09 15:05:19 -0800 | 
| commit | d6841c07983a46ff805ed23a7318efbf9cca3b24 (patch) | |
| tree | c6b8432f722f939f1ed088681bcb2dada1bf5587 /indra | |
| parent | 627e3d51c61778e07e350689ce68ede24afe61ab (diff) | |
SL-19080: Update GLTF Material asset upload to v1.1, with stricter GLTF compliance and removal of unsupported features
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llprimitive/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llprimitive/llgltfmaterial.cpp | 151 | ||||
| -rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 53 | ||||
| -rw-r--r-- | indra/llprimitive/tests/llgltfmaterial_test.cpp | 255 | ||||
| -rw-r--r-- | indra/newview/llgltfmateriallist.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.cpp | 209 | ||||
| -rw-r--r-- | indra/newview/llmaterialeditor.h | 9 | ||||
| -rw-r--r-- | indra/newview/lltinygltfhelper.cpp | 16 | ||||
| -rw-r--r-- | indra/newview/llviewermenufile.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerobject.cpp | 8 | 
10 files changed, 441 insertions, 274 deletions
diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 328b22f900..dd25c19713 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -99,6 +99,8 @@ if (LL_TESTS)      SET(llprimitive_TEST_SOURCE_FILES        llmediaentry.cpp        llprimitive.cpp +      llgltfmaterial.cpp        ) +          LL_ADD_PROJECT_UNIT_TESTS(llprimitive "${llprimitive_TEST_SOURCE_FILES}")  endif (LL_TESTS) diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index a8dad89292..2e920aa44e 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -31,6 +31,10 @@  // NOTE -- this should be the one and only place tiny_gltf.h is included  #include "tinygltf/tiny_gltf.h" +const char* LLGLTFMaterial::ASSET_VERSION = "1.1"; +const char* LLGLTFMaterial::ASSET_TYPE = "GLTF 2.0"; +const std::array<char*, 2> LLGLTFMaterial::ACCEPTED_ASSET_VERSIONS = { "1.0", "1.1" }; +  const char* GLTF_FILE_EXTENSION_TRANSFORM = "KHR_texture_transform";  const char* GLTF_FILE_EXTENSION_TRANSFORM_SCALE = "scale";  const char* GLTF_FILE_EXTENSION_TRANSFORM_OFFSET = "offset"; @@ -73,16 +77,14 @@ LLGLTFMaterial::LLGLTFMaterial(const LLGLTFMaterial& rhs)  LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)  { -    LL_PROFILE_ZONE_SCOPED; -    //have to do a manual operator= because of LLRefCount -    mBaseColorId = rhs.mBaseColorId; -    mNormalId = rhs.mNormalId; -    mMetallicRoughnessId = rhs.mMetallicRoughnessId; -    mEmissiveId = rhs.mEmissiveId; +    //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; @@ -90,8 +92,6 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)      mDoubleSided = rhs.mDoubleSided;      mAlphaMode = rhs.mAlphaMode; -    mTextureTransform = rhs.mTextureTransform; -      mOverrideDoubleSided = rhs.mOverrideDoubleSided;      mOverrideAlphaMode = rhs.mOverrideAlphaMode; @@ -100,10 +100,9 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs)  bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const  { -    return mBaseColorId == rhs.mBaseColorId && -        mNormalId == rhs.mNormalId && -        mMetallicRoughnessId == rhs.mMetallicRoughnessId && -        mEmissiveId == rhs.mEmissiveId && +    return mTextureId == rhs.mTextureId && + +        mTextureTransform == rhs.mTextureTransform &&          mBaseColor == rhs.mBaseColor &&          mEmissiveColor == rhs.mEmissiveColor && @@ -115,8 +114,6 @@ bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const          mDoubleSided == rhs.mDoubleSided &&          mAlphaMode == rhs.mAlphaMode && -        mTextureTransform == rhs.mTextureTransform && -          mOverrideDoubleSided == rhs.mOverrideDoubleSided &&          mOverrideAlphaMode == rhs.mOverrideAlphaMode;  } @@ -148,6 +145,8 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const      writeToModel(model_out, 0); +    // To ensure consistency in asset upload, this should be the only reference +    // to WriteGltfSceneToStream in the viewer.      gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false);      return str.str(); @@ -164,13 +163,13 @@ void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index)      const tinygltf::Material& material_in = model.materials[mat_index];      // Apply base color texture -    setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId); +    setFromTexture(model, material_in.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR);      // Apply normal map -    setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId); +    setFromTexture(model, material_in.normalTexture, GLTF_TEXTURE_INFO_NORMAL);      // Apply metallic-roughness texture -    setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId); +    setFromTexture(model, material_in.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS);      // Apply emissive texture -    setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId); +    setFromTexture(model, material_in.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE);      setAlphaMode(material_in.alphaMode);      mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f); @@ -264,11 +263,11 @@ std::string gltf_get_texture_image(const tinygltf::Model& model, const T& textur  // *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, LLUUID& texture_id_out) +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); -    texture_id_out.set(uri); +    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); @@ -297,21 +296,24 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const      tinygltf::Material& material_out = model.materials[mat_index];      // set base color texture -    writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR, mBaseColorId); +    writeToTexture(model, material_out.pbrMetallicRoughness.baseColorTexture, GLTF_TEXTURE_INFO_BASE_COLOR);      // set normal texture -    writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL, mNormalId); +    writeToTexture(model, material_out.normalTexture, GLTF_TEXTURE_INFO_NORMAL);      // set metallic-roughness texture -    writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, mMetallicRoughnessId); +    writeToTexture(model, material_out.pbrMetallicRoughness.metallicRoughnessTexture, GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS);      // set emissive texture -    writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE, mEmissiveId); +    writeToTexture(model, material_out.emissiveTexture, GLTF_TEXTURE_INFO_EMISSIVE); +    // set occlusion texture +    // *NOTE: This is required for ORM materials for GLTF compliance. +    // See: https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#_material_occlusiontexture +    writeToTexture(model, material_out.occlusionTexture, GLTF_TEXTURE_INFO_OCCLUSION); +      material_out.alphaMode = getAlphaMode();      material_out.alphaCutoff = mAlphaCutoff; - +          mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor); -    material_out.emissiveFactor.resize(3); // 0 size by default -      if (mEmissiveColor != LLGLTFMaterial::getDefaultEmissiveColor())      {          material_out.emissiveFactor.resize(3); @@ -323,7 +325,6 @@ void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const      material_out.doubleSided = mDoubleSided; -      // generate "extras" string      tinygltf::Value::Object extras;      bool write_extras = false; @@ -364,28 +365,43 @@ void gltf_allocate_texture_image(tinygltf::Model& model, T& texture_info, const  }  template<typename T> -void LLGLTFMaterial::writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const +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]; -    if (texture_id.isNull() && transform == sDefault.mTextureTransform[0]) +    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()); -    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); +    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;  }  bool LLGLTFMaterial::setBaseMaterial() @@ -419,40 +435,33 @@ void LLGLTFMaterial::hackOverrideUUID(LLUUID& id)      }  } -void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override) +void LLGLTFMaterial::setTextureId(TextureInfo texture_info, const LLUUID& id, bool for_override)  { -    mBaseColorId = id; +    mTextureId[texture_info] = id;      if (for_override)      { -        hackOverrideUUID(mBaseColorId); +        hackOverrideUUID(mTextureId[texture_info]);      }  } +void LLGLTFMaterial::setBaseColorId(const LLUUID& id, bool for_override) +{ +    setTextureId(GLTF_TEXTURE_INFO_BASE_COLOR, id, for_override); +} +  void LLGLTFMaterial::setNormalId(const LLUUID& id, bool for_override)  { -    mNormalId = id; -    if (for_override) -    { -        hackOverrideUUID(mNormalId); -    } +    setTextureId(GLTF_TEXTURE_INFO_NORMAL, id, for_override);  } -void LLGLTFMaterial::setMetallicRoughnessId(const LLUUID& id, bool for_override) +void LLGLTFMaterial::setOcclusionRoughnessMetallicId(const LLUUID& id, bool for_override)  { -    mMetallicRoughnessId = id; -    if (for_override) -    { -        hackOverrideUUID(mMetallicRoughnessId); -    } +    setTextureId(GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, id, for_override);  }  void LLGLTFMaterial::setEmissiveId(const LLUUID& id, bool for_override)  { -    mEmissiveId = id; -    if (for_override) -    { -        hackOverrideUUID(mEmissiveId); -    } +    setTextureId(GLTF_TEXTURE_INFO_EMISSIVE, id, for_override);  }  void LLGLTFMaterial::setBaseColorFactor(const LLColor4& baseColor, bool for_override) @@ -533,10 +542,7 @@ const char* LLGLTFMaterial::getAlphaMode() const  void LLGLTFMaterial::setAlphaMode(S32 mode, bool for_override)  {      mAlphaMode = (AlphaMode) llclamp(mode, (S32) ALPHA_MODE_OPAQUE, (S32) ALPHA_MODE_MASK); -    if (for_override) -    { -        mOverrideAlphaMode = true; -    } +    mOverrideAlphaMode = for_override && mAlphaMode == getDefaultAlphaMode();  }  void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override) @@ -544,10 +550,7 @@ void LLGLTFMaterial::setDoubleSided(bool double_sided, bool for_override)      // sure, no clamping will ever be needed for a bool, but include the      // setter for consistency with the clamping API      mDoubleSided = double_sided; -    if (for_override) -    { -        mOverrideDoubleSided = true; -    } +    mOverrideDoubleSided = for_override && mDoubleSided == getDefaultDoubleSided();  }  void LLGLTFMaterial::setTextureOffset(TextureInfo texture_info, const LLVector2& offset) @@ -640,10 +643,12 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat)  {      LL_PROFILE_ZONE_SCOPED; -    applyOverrideUUID(mBaseColorId, override_mat.mBaseColorId); -    applyOverrideUUID(mNormalId, override_mat.mNormalId); -    applyOverrideUUID(mMetallicRoughnessId, override_mat.mMetallicRoughnessId); -    applyOverrideUUID(mEmissiveId, override_mat.mEmissiveId); +    for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) +    { +        LLUUID& texture_id = mTextureId[i]; +        const LLUUID& override_texture_id = override_mat.mTextureId[i]; +        applyOverrideUUID(texture_id, override_texture_id); +    }      if (override_mat.mBaseColor != getDefaultBaseColor())      { diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index dec7b696f8..fd26e7563c 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -49,6 +49,11 @@ public:      // default material for reference      static const LLGLTFMaterial sDefault; +    static const char* ASSET_VERSION; +    static const char* ASSET_TYPE; +    static const std::array<char*, 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(); } +      struct TextureTransform      {          LLVector2 mOffset = { 0.f, 0.f }; @@ -74,10 +79,25 @@ public:      bool operator==(const LLGLTFMaterial& rhs) const;      bool operator!=(const LLGLTFMaterial& rhs) const { return !(*this == rhs); } -    LLUUID mBaseColorId; -    LLUUID mNormalId; -    LLUUID mMetallicRoughnessId; -    LLUUID mEmissiveId; +    enum TextureInfo : U32 +    { +        GLTF_TEXTURE_INFO_BASE_COLOR, +        GLTF_TEXTURE_INFO_NORMAL, +        GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, +        // *NOTE: GLTF_TEXTURE_INFO_OCCLUSION is currently ignored, in favor of +        // the values specified with GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS. +        // Currently, only ORM materials are supported (materials which define +        // occlusion, roughness, and metallic in the same texture). +        // -Cosmic,2023-01-26 +        GLTF_TEXTURE_INFO_OCCLUSION = GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, +        GLTF_TEXTURE_INFO_EMISSIVE, + +        GLTF_TEXTURE_INFO_COUNT +    }; + +    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      LLColor4 mBaseColor = LLColor4(1, 1, 1, 1); @@ -106,24 +126,14 @@ public:          return id;      } -    enum TextureInfo : U32 -    { -        GLTF_TEXTURE_INFO_BASE_COLOR, -        GLTF_TEXTURE_INFO_NORMAL, -        GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, -        GLTF_TEXTURE_INFO_EMISSIVE, - -        GLTF_TEXTURE_INFO_COUNT -    }; - -    std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform; -      //setters for various members (will clamp to acceptable ranges)      // for_override - set to true if this value is being set as part of an override (important for handling override to default value) +    void setTextureId(TextureInfo texture_info, const LLUUID& id, bool for_override = false); +      void setBaseColorId(const LLUUID& id, bool for_override = false);      void setNormalId(const LLUUID& id, bool for_override = false); -    void setMetallicRoughnessId(const LLUUID& id, bool for_override = false); +    void setOcclusionRoughnessMetallicId(const LLUUID& id, bool for_override = false);      void setEmissiveId(const LLUUID& id, bool for_override = false);      void setBaseColorFactor(const LLColor4& baseColor, bool for_override = false); @@ -182,6 +192,10 @@ public:      void applyOverride(const LLGLTFMaterial& override_mat); +    // For base materials only (i.e. assets). Clears transforms to +    // default since they're not supported in assets yet. +    void sanitizeAssetMaterial(); +      // For material overrides only. Clears most properties to      // default/fallthrough, but preserves the transforms.      bool setBaseMaterial(); @@ -189,12 +203,11 @@ public:      bool isClearedForBaseMaterial();  private: -      template<typename T> -    void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out); +    void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id);      template<typename T> -    void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, const LLUUID& texture_id) const; +    void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;      void setBaseMaterial(const LLGLTFMaterial& old_override_mat);  }; diff --git a/indra/llprimitive/tests/llgltfmaterial_test.cpp b/indra/llprimitive/tests/llgltfmaterial_test.cpp new file mode 100644 index 0000000000..4f58f4e567 --- /dev/null +++ b/indra/llprimitive/tests/llgltfmaterial_test.cpp @@ -0,0 +1,255 @@ +/**  + * @file llgltfmaterial_test.cpp + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$                                + * Second Life Viewer Source Code + * Copyright (C) 2023, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$                                                                + */ + +#pragma once + +#include "linden_common.h" +#include "lltut.h" + +#include "../llgltfmaterial.h" +#include "lluuid.cpp" + +// Import & define single-header gltf import/export lib +#define TINYGLTF_IMPLEMENTATION +#define TINYGLTF_USE_CPP14  // default is C++ 11 + +// tinygltf by default loads image files using STB +#define STB_IMAGE_IMPLEMENTATION +// to use our own image loading: +// 1. replace this definition with TINYGLTF_NO_STB_IMAGE +// 2. provide image loader callback with TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void *user_data) + +// tinygltf saves image files using STB +#define STB_IMAGE_WRITE_IMPLEMENTATION +// similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and TinyGLTF::SetImageWriter(fxn, data) + +// Disable reading external images to prevent warnings and speed up the tests. +// We don't need this for the tests, but still need the filesystem +// implementation to be defined in order for llprimitive to link correctly. +#define TINYGLTF_NO_EXTERNAL_IMAGE 1 + +#include "tinygltf/tiny_gltf.h" + +namespace tut +{ +    struct llgltfmaterial +    { +    }; +    typedef test_group<llgltfmaterial> llgltfmaterial_t; +    typedef llgltfmaterial_t::object llgltfmaterial_object_t; +    tut::llgltfmaterial_t tut_llgltfmaterial("llgltfmaterial"); + +    // A positive 32-bit float with a long string representation +    constexpr F32 test_fraction = 1.09045365e-32; +    // A larger positive 32-bit float for values that get zeroed if below a threshold +    constexpr F32 test_fraction_big = 0.109045; + +    void apply_test_material_texture_ids(LLGLTFMaterial& material) +    { +        material.setBaseColorId(LLUUID::generateNewID()); +        material.setNormalId(LLUUID::generateNewID()); +        material.setOcclusionRoughnessMetallicId(LLUUID::generateNewID()); +        material.setEmissiveId(LLUUID::generateNewID()); +    } + +    void apply_test_material_texture_transforms(LLGLTFMaterial& material) +    { +        LLGLTFMaterial::TextureTransform test_transform; +        test_transform.mOffset.mV[VX] = test_fraction; +        test_transform.mOffset.mV[VY] = test_fraction; +        test_transform.mScale.mV[VX] = test_fraction; +        test_transform.mScale.mV[VY] = test_fraction; +        test_transform.mRotation = test_fraction; +        for (LLGLTFMaterial::TextureInfo i = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; i = LLGLTFMaterial::TextureInfo((U32)i + 1)) +        { +            material.setTextureOffset(i, test_transform.mOffset); +            material.setTextureScale(i, test_transform.mScale); +            material.setTextureRotation(i, test_transform.mRotation); +        } +    } + +    void apply_test_material_factors(LLGLTFMaterial& material) +    { +        material.setBaseColorFactor(LLColor4(test_fraction_big, test_fraction_big, test_fraction_big, test_fraction_big)); +        material.setEmissiveColorFactor(LLColor3(test_fraction_big, test_fraction_big, test_fraction_big)); +        material.setMetallicFactor(test_fraction); +        material.setRoughnessFactor(test_fraction); +    } + +    LLGLTFMaterial create_test_material() +    { +        LLGLTFMaterial material; + +        apply_test_material_texture_ids(material); + +        apply_test_material_texture_transforms(material); + +        apply_test_material_factors(material); + +        material.setAlphaCutoff(test_fraction); +        // Because this is the default value, it should append to the extras field to mark it as an override +        material.setAlphaMode(LLGLTFMaterial::ALPHA_MODE_OPAQUE); +        // Because this is the default value, it should append to the extras field to mark it as an override +        material.setDoubleSided(false); + +        return material; +    } + +    void ensure_gltf_material_serialize(const std::string& ensure_suffix, const LLGLTFMaterial& material_in) +    { +        const std::string json_in = material_in.asJSON(); +        LLGLTFMaterial material_out; +        std::string warn_msg; +        std::string error_msg; +        bool serialize_success = material_out.fromJSON(json_in, warn_msg, error_msg); +        ensure_equals("LLGLTFMaterial serialization has no warnings: " + ensure_suffix, "", warn_msg); +        ensure_equals("LLGLTFMaterial serialization has no errors: " + ensure_suffix, "", error_msg); +        ensure("LLGLTFMaterial serializes successfully: " + ensure_suffix, serialize_success); +        ensure("LLGLTFMaterial is preserved when deserialized: " + ensure_suffix, material_in == material_out); +        const std::string json_out = material_out.asJSON(); +        ensure_equals("LLGLTFMaterial is preserved when serialized: " + ensure_suffix, json_in, json_out); +    } + +    void ensure_gltf_material_trimmed(const std::string& material_json, const std::string& must_not_contain) +    { +        ensure("LLGLTFMaterial serialization trims property '" + must_not_contain + "'", material_json.find(must_not_contain) == std::string::npos); +    } + +    // Test that GLTF material fields have not changed since these tests were written +    template<> template<> +    void llgltfmaterial_object_t::test<1>() +    { +        if (sizeof(void*) > 4) // Don't bother running this test for 32-bit systems +        { +            // If any fields are added/changed, these tests should be updated (consider also updating ASSET_VERSION in LLGLTFMaterial) +            ensure_equals("fields supported for GLTF (sizeof check)", sizeof(LLGLTFMaterial), 216); +        } +        ensure_equals("LLGLTFMaterial texture info count", (U32)LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT, 4); +    } + +    // Test that occlusion and metallicRoughness are the same (They are different for asset validation. See lluploadmaterial.cpp) +    template<> template<> +    void llgltfmaterial_object_t::test<2>() +    { +        ensure_equals("LLGLTFMaterial occlusion does not differ from metallic roughness", LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, LLGLTFMaterial::GLTF_TEXTURE_INFO_OCCLUSION); +    } + +    // Ensure double sided and alpha mode overrides serialize as expected +    template<> template<> +    void llgltfmaterial_object_t::test<3>() +    { +        const bool doubleSideds[] { false, true }; +        const LLGLTFMaterial::AlphaMode alphaModes[] { LLGLTFMaterial::ALPHA_MODE_OPAQUE, LLGLTFMaterial::ALPHA_MODE_BLEND, LLGLTFMaterial::ALPHA_MODE_MASK }; +        const bool forOverrides[] { false, true }; + +        for (bool doubleSided : doubleSideds) +        { +            for (bool forOverride : forOverrides) +            { +                LLGLTFMaterial material; +                material.setDoubleSided(doubleSided, forOverride); +                const bool overrideBit = (doubleSided == false) && forOverride; +                ensure_equals("LLGLTFMaterial: double sided = " + std::to_string(doubleSided) + " override bit when forOverride = " + std::to_string(forOverride), material.mOverrideDoubleSided, overrideBit); +                ensure_gltf_material_serialize("double sided = " + std::to_string(doubleSided), material); +            } +        } + +        for (LLGLTFMaterial::AlphaMode alphaMode : alphaModes) +        { +            for (bool forOverride : forOverrides) +            { +                LLGLTFMaterial material; +                material.setAlphaMode(alphaMode, forOverride); +                const bool overrideBit = (alphaMode == LLGLTFMaterial::ALPHA_MODE_OPAQUE) && forOverride; +                ensure_equals("LLGLTFMaterial: alpha mode = " + std::to_string(alphaMode) + " override bit when forOverride = " + std::to_string(forOverride), material.mOverrideAlphaMode, overrideBit); +                ensure_gltf_material_serialize("alpha mode = " + std::to_string(alphaMode), material); +            } +        } +    } + +    // Test that a GLTF material's transform components serialize as expected +    template<> template<> +    void llgltfmaterial_object_t::test<4>() +    { +        LLGLTFMaterial material; +        LLGLTFMaterial::TextureTransform& transform = material.mTextureTransform[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]; +        transform.mOffset[VX] = 1.f; +        transform.mOffset[VY] = 2.f; +        transform.mScale[VX] = 0.05f; +        transform.mScale[VY] = 100.f; +        transform.mRotation = 1.571f; +        ensure_gltf_material_serialize("material with transform", material); +    } + +    // Test that a GLTF material avoids serializing a material unnecessarily +    template<> template<> +    void llgltfmaterial_object_t::test<5>() +    { +        { +            const LLGLTFMaterial material; +            const std::string material_json = material.asJSON(); +            ensure_gltf_material_trimmed(material_json, "pbrMetallicRoughness"); +            ensure_gltf_material_trimmed(material_json, "normalTexture"); +            ensure_gltf_material_trimmed(material_json, "emissiveTexture"); +            ensure_gltf_material_trimmed(material_json, "occlusionTexture"); +        } + +        { +            LLGLTFMaterial metallic_factor_material; +            metallic_factor_material.setMetallicFactor(0.5); +            const std::string metallic_factor_material_json = metallic_factor_material.asJSON(); +            ensure_gltf_material_trimmed(metallic_factor_material_json, "baseColorTexture"); +            ensure_gltf_material_trimmed(metallic_factor_material_json, "metallicRoughnessTexture"); +        } +    } + +    // Test that a GLTF material preserves values on serialization +    template<> template<> +    void llgltfmaterial_object_t::test<6>() +    { +        { +            const LLGLTFMaterial full_material = create_test_material(); +            ensure_gltf_material_serialize("full material", full_material); +        } + +        { +            LLGLTFMaterial texture_ids_only_material; +            apply_test_material_texture_ids(texture_ids_only_material); +            ensure_gltf_material_serialize("material with texture IDs only", texture_ids_only_material); +        } + +        { +            LLGLTFMaterial texture_transforms_only_material; +            apply_test_material_texture_ids(texture_transforms_only_material); +            ensure_gltf_material_serialize("material with texture transforms only", texture_transforms_only_material); +        } + +        { +            LLGLTFMaterial factors_only_material; +            apply_test_material_factors(factors_only_material); +            ensure_gltf_material_serialize("material with scaling/tint factors only", factors_only_material); +        } +    } +} diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index bc094ac838..4051521ad4 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -564,9 +564,9 @@ void LLGLTFMaterialList::onAssetLoadComplete(const LLUUID& id, LLAssetType::ETyp                  if (LLSDSerialize::deserialize(asset, str, buffer.size()))                  { -                    if (asset.has("version") && asset["version"] == "1.0") +                    if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString()))                      { -                        if (asset.has("type") && asset["type"].asString() == "GLTF 2.0") +                        if (asset.has("type") && asset["type"].asString() == LLGLTFMaterial::ASSET_TYPE)                          {                              if (asset.has("data") && asset["data"].isString())                              { diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 5628327ebe..173f5620c6 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -277,10 +277,10 @@ bool LLSelectedTEGetMatData::apply(LLViewerObject* objectp, S32 te_index)              llassert(mat.notNull()); // by this point shouldn't be null              if (mat.notNull())              { -                tex_color_id = mat->mBaseColorId; -                tex_metal_id = mat->mMetallicRoughnessId; -                tex_emissive_id = mat->mEmissiveId; -                tex_normal_id = mat->mNormalId; +                tex_color_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]; +                tex_metal_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]; +                tex_emissive_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]; +                tex_normal_id = mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL];              }              if (mFirst)              { @@ -949,7 +949,7 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_                      }                      case MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY:                      { -                        nodep->mSavedGLTFOverrideMaterials[te]->setMetallicRoughnessId(mCtrl->getValue().asUUID(), true); +                        nodep->mSavedGLTFOverrideMaterials[te]->setOcclusionRoughnessMetallicId(mCtrl->getValue().asUUID(), true);                          break;                      }                      case MATERIAL_EMISIVE_TEX_DIRTY: @@ -991,30 +991,6 @@ void LLMaterialEditor::onSelectCtrl(LLUICtrl* ctrl, const LLSD& data, S32 dirty_      LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func);  } -static void write_color(const LLColor4& color, std::vector<double>& c) -{ -    for (int i = 0; i < c.size(); ++i) // NOTE -- use c.size because some gltf colors are 3-component -    { -        c[i] = color.mV[i]; -    } -} - -static U32 write_texture(const LLUUID& id, tinygltf::Model& model) -{ -    tinygltf::Image image; -    image.uri = id.asString(); -    model.images.push_back(image); -    U32 image_idx = model.images.size() - 1; - -    tinygltf::Texture texture; -    texture.source = image_idx; -    model.textures.push_back(texture); -    U32 texture_idx = model.textures.size() - 1; - -    return texture_idx; -} - -  void LLMaterialEditor::onClickSave()  {      if (!capabilitiesAvailable()) @@ -1034,109 +1010,14 @@ void LLMaterialEditor::onClickSave()      saveIfNeeded();  } - -std::string LLMaterialEditor::getGLTFJson(bool prettyprint) -{ -    tinygltf::Model model; -    getGLTFModel(model); - -    std::ostringstream str; - -    tinygltf::TinyGLTF gltf; -     -    gltf.WriteGltfSceneToStream(&model, str, prettyprint, false); - -    std::string dump = str.str(); - -    return dump; -} - -void LLMaterialEditor::getGLBData(std::vector<U8>& data) -{ -    tinygltf::Model model; -    getGLTFModel(model); - -    std::ostringstream str; - -    tinygltf::TinyGLTF gltf; - -    gltf.WriteGltfSceneToStream(&model, str, false, true); - -    std::string dump = str.str(); - -    data.resize(dump.length()); - -    memcpy(&data[0], dump.c_str(), dump.length()); -} - -void LLMaterialEditor::getGLTFModel(tinygltf::Model& model) -{ -    model.materials.resize(1); -    tinygltf::PbrMetallicRoughness& pbrMaterial = model.materials[0].pbrMetallicRoughness; - -    // write base color -    LLColor4 base_color = getBaseColor(); -    base_color.mV[3] = getTransparency(); -    write_color(base_color, pbrMaterial.baseColorFactor); - -    model.materials[0].alphaCutoff = getAlphaCutoff(); -    model.materials[0].alphaMode = getAlphaMode(); - -    LLUUID base_color_id = getBaseColorId(); - -    if (base_color_id.notNull()) -    { -        U32 texture_idx = write_texture(base_color_id, model); - -        pbrMaterial.baseColorTexture.index = texture_idx; -    } - -    // write metallic/roughness -    F32 metalness = getMetalnessFactor(); -    F32 roughness = getRoughnessFactor(); - -    pbrMaterial.metallicFactor = metalness; -    pbrMaterial.roughnessFactor = roughness; - -    LLUUID mr_id = getMetallicRoughnessId(); -    if (mr_id.notNull()) -    { -        U32 texture_idx = write_texture(mr_id, model); -        pbrMaterial.metallicRoughnessTexture.index = texture_idx; -    } - -    //write emissive -    LLColor4 emissive_color = getEmissiveColor(); -    model.materials[0].emissiveFactor.resize(3); -    write_color(emissive_color, model.materials[0].emissiveFactor); - -    LLUUID emissive_id = getEmissiveId(); -    if (emissive_id.notNull()) -    { -        U32 idx = write_texture(emissive_id, model); -        model.materials[0].emissiveTexture.index = idx; -    } - -    //write normal -    LLUUID normal_id = getNormalId(); -    if (normal_id.notNull()) -    { -        U32 idx = write_texture(normal_id, model); -        model.materials[0].normalTexture.index = idx; -    } - -    //write doublesided -    model.materials[0].doubleSided = getDoubleSided(); - -    model.asset.version = "2.0"; -} -  std::string LLMaterialEditor::getEncodedAsset()  {      LLSD asset; -    asset["version"] = "1.0"; -    asset["type"] = "GLTF 2.0"; -    asset["data"] = getGLTFJson(false); +    asset["version"] = LLGLTFMaterial::ASSET_VERSION; +    asset["type"] = LLGLTFMaterial::ASSET_TYPE; +    LLGLTFMaterial mat; +    getGLTFMaterial(&mat); +    asset["data"] = mat.asJSON();      std::ostringstream str;      LLSDSerialize::serialize(asset, str, LLSDSerialize::LLSD_BINARY); @@ -1151,9 +1032,9 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)      std::istrstream str(&buffer[0], buffer.size());      if (LLSDSerialize::deserialize(asset, str, buffer.size()))      { -        if (asset.has("version") && asset["version"] == "1.0") +        if (asset.has("version") && LLGLTFMaterial::isAcceptedVersion(asset["version"].asString()))          { -            if (asset.has("type") && asset["type"] == "GLTF 2.0") +            if (asset.has("type") && asset["type"] == LLGLTFMaterial::ASSET_TYPE)              {                  if (asset.has("data") && asset["data"].isString())                  { @@ -1169,6 +1050,12 @@ bool LLMaterialEditor::decodeAsset(const std::vector<char>& buffer)                      if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), ""))                      {                          // assets are only supposed to have one item +                        // *NOTE: This duplicates some functionality from +                        // LLGLTFMaterial::fromJSON, but currently does the job +                        // better for the material editor use case. +                        // However, LLGLTFMaterial::asJSON should always be +                        // used when uploading materials, to ensure the +                        // asset is valid.                          return setFromGltfModel(model_in, 0, true);                      }                      else @@ -1977,7 +1864,9 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con          {              // don't use override material here, it has 'hacked ids'              // and values, use end result, apply it on top of local. -            me->setBaseColor(render_material->mBaseColor); +            const LLColor4& base_color = render_material->mBaseColor; +            me->setBaseColor(LLColor3(base_color)); +            me->setTransparency(base_color[VW]);              me->setMetalnessFactor(render_material->mMetallicFactor);              me->setRoughnessFactor(render_material->mRoughnessFactor);              me->setEmissiveColor(render_material->mEmissiveColor); @@ -1988,24 +1877,24 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con              // most things like colors we can apply without verifying              // but texture ids are going to be different from both, base and override              // so only apply override id if there is actually a difference -            if (local_material->mBaseColorId != render_material->mBaseColorId) +            if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR])              { -                me->setBaseColorId(render_material->mBaseColorId); +                me->setBaseColorId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]);                  me->childSetValue("base_color_upload_fee", me->getString("no_upload_fee_string"));              } -            if (local_material->mNormalId != render_material->mNormalId) +            if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL])              { -                me->setNormalId(render_material->mNormalId); +                me->setNormalId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]);                  me->childSetValue("normal_upload_fee", me->getString("no_upload_fee_string"));              } -            if (local_material->mMetallicRoughnessId != render_material->mMetallicRoughnessId) +            if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS])              { -                me->setMetallicRoughnessId(render_material->mMetallicRoughnessId); +                me->setMetallicRoughnessId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);                  me->childSetValue("metallic_upload_fee", me->getString("no_upload_fee_string"));              } -            if (local_material->mEmissiveId != render_material->mEmissiveId) +            if (local_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] != render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE])              { -                me->setEmissiveId(render_material->mEmissiveId); +                me->setEmissiveId(render_material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);                  me->childSetValue("emissive_upload_fee", me->getString("no_upload_fee_string"));              } @@ -2019,7 +1908,11 @@ void LLMaterialEditor::saveMaterialAs(const LLGLTFMaterial* render_material, con      LLSD payload;      if (render_material)      { -        payload["data"] = render_material->asJSON(); +        // Make a copy of the render material with unsupported transforms removed +        LLGLTFMaterial asset_material = *render_material; +        asset_material.sanitizeAssetMaterial(); +        // Serialize the sanitized render material +        payload["data"] = asset_material.asJSON();      }      else      { @@ -2042,8 +1935,9 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati      if (0 == option)      {          LLSD asset; -        asset["version"] = "1.0"; -        asset["type"] = "GLTF 2.0"; +        asset["version"] = LLGLTFMaterial::ASSET_VERSION; +        asset["type"] = LLGLTFMaterial::ASSET_TYPE; +        // This is the string serialized from LLGLTFMaterial::asJSON          asset["data"] = notification["payload"]["data"];          std::ostringstream str; @@ -2586,7 +2480,7 @@ public:              }              else if ((reverted_flags & MATERIAL_BASE_COLOR_TEX_DIRTY) && revert_mat.notNull())              { -                material->setBaseColorId(revert_mat->mBaseColorId, false); +                material->setBaseColorId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR], false);              }              if (changed_flags & MATERIAL_NORMAL_TEX_DIRTY) @@ -2595,16 +2489,16 @@ public:              }              else if ((reverted_flags & MATERIAL_NORMAL_TEX_DIRTY) && revert_mat.notNull())              { -                material->setNormalId(revert_mat->mNormalId, false); +                material->setNormalId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL], false);              }              if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY)              { -                material->setMetallicRoughnessId(mEditor->getMetallicRoughnessId(), true); +                material->setOcclusionRoughnessMetallicId(mEditor->getMetallicRoughnessId(), true);              }              else if ((reverted_flags & MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY) && revert_mat.notNull())              { -                material->setMetallicRoughnessId(revert_mat->mMetallicRoughnessId, false); +                material->setOcclusionRoughnessMetallicId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS], false);              }              if (changed_flags & MATERIAL_METALLIC_ROUGHTNESS_METALNESS_DIRTY) @@ -2640,7 +2534,7 @@ public:              }              else if ((reverted_flags & MATERIAL_EMISIVE_TEX_DIRTY) && revert_mat.notNull())              { -                material->setEmissiveId(revert_mat->mEmissiveId, false); +                material->setEmissiveId(revert_mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE], false);              }              if (changed_flags & MATERIAL_DOUBLE_SIDED_DIRTY) @@ -2753,20 +2647,23 @@ void LLMaterialEditor::applyToSelection()      }  } +// Get a dump of the json representation of the current state of the editor UI +// in GLTF format, excluding transforms as they are not supported in material +// assets. (See also LLGLTFMaterial::sanitizeAssetMaterial())  void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)  {      mat->mBaseColor = getBaseColor();      mat->mBaseColor.mV[3] = getTransparency(); -    mat->mBaseColorId = getBaseColorId(); +    mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = getBaseColorId(); -    mat->mNormalId = getNormalId(); +    mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = getNormalId(); -    mat->mMetallicRoughnessId = getMetallicRoughnessId(); +    mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = getMetallicRoughnessId();      mat->mMetallicFactor = getMetalnessFactor();      mat->mRoughnessFactor = getRoughnessFactor();      mat->mEmissiveColor = getEmissiveColor(); -    mat->mEmissiveId = getEmissiveId(); +    mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = getEmissiveId();      mat->mDoubleSided = getDoubleSided();      mat->setAlphaMode(getAlphaMode()); @@ -2776,15 +2673,15 @@ void LLMaterialEditor::getGLTFMaterial(LLGLTFMaterial* mat)  void LLMaterialEditor::setFromGLTFMaterial(LLGLTFMaterial* mat)  {      setBaseColor(mat->mBaseColor); -    setBaseColorId(mat->mBaseColorId); -    setNormalId(mat->mNormalId); +    setBaseColorId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); +    setNormalId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); -    setMetallicRoughnessId(mat->mMetallicRoughnessId); +    setMetallicRoughnessId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]);      setMetalnessFactor(mat->mMetallicFactor);      setRoughnessFactor(mat->mRoughnessFactor);      setEmissiveColor(mat->mEmissiveColor); -    setEmissiveId(mat->mEmissiveId); +    setEmissiveId(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);      setDoubleSided(mat->mDoubleSided);      setAlphaMode(mat->getAlphaMode()); diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h index 74c776031e..0401190773 100644 --- a/indra/newview/llmaterialeditor.h +++ b/indra/newview/llmaterialeditor.h @@ -84,8 +84,7 @@ protected:  };  class LLMaterialEditor : public LLPreview, public LLVOInventoryListener -{ -public: +{ public:  	LLMaterialEditor(const LLSD& key);      bool setFromGltfModel(const tinygltf::Model& model, S32 index, bool set_textures = false); @@ -98,6 +97,7 @@ public:      // for live preview, apply current material to currently selected object      void applyToSelection(); +    // get a dump of the json representation of the current state of the editor UI as a material object      void getGLTFMaterial(LLGLTFMaterial* mat);      void loadAsset() override; @@ -131,11 +131,6 @@ public:      void onClickSave(); -    // get a dump of the json representation of the current state of the editor UI in GLTF format -    std::string getGLTFJson(bool prettyprint = true); - -    void getGLBData(std::vector<U8>& data); -      void getGLTFModel(tinygltf::Model& model);      std::string getEncodedAsset(); diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index 611911014a..1a8e868d11 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -309,48 +309,48 @@ bool LLTinyGLTFHelper::getMaterialFromFile(      if (base_color_tex)      {          base_color_tex->addTextureStats(64.f * 64.f, TRUE); -        material->mBaseColorId = base_color_tex->getID(); +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = base_color_tex->getID();          material->mBaseColorTexture = base_color_tex;      }      else      { -        material->mBaseColorId = LLUUID::null; +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR] = LLUUID::null;          material->mBaseColorTexture = nullptr;      }      if (normal_tex)      {          normal_tex->addTextureStats(64.f * 64.f, TRUE); -        material->mNormalId = normal_tex->getID(); +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = normal_tex->getID();          material->mNormalTexture = normal_tex;      }      else      { -        material->mNormalId = LLUUID::null; +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL] = LLUUID::null;          material->mNormalTexture = nullptr;      }      if (mr_tex)      {          mr_tex->addTextureStats(64.f * 64.f, TRUE); -        material->mMetallicRoughnessId = mr_tex->getID(); +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = mr_tex->getID();          material->mMetallicRoughnessTexture = mr_tex;      }      else      { -        material->mMetallicRoughnessId = LLUUID::null; +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS] = LLUUID::null;          material->mMetallicRoughnessTexture = nullptr;      }      if (emissive_tex)      {          emissive_tex->addTextureStats(64.f * 64.f, TRUE); -        material->mEmissiveId = emissive_tex->getID(); +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = emissive_tex->getID();          material->mEmissiveTexture = emissive_tex;      }      else      { -        material->mEmissiveId = LLUUID::null; +        material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE] = LLUUID::null;          material->mEmissiveTexture = nullptr;      } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 84b0010545..9743f00ab8 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -543,19 +543,19 @@ bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S3                      // Todo: make it account for possibility of same texture in different                      // materials and even in scope of same material                      S32 texture_count = 0; -                    if (material->mBaseColorId.notNull()) +                    if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR].notNull())                      {                          texture_count++;                      } -                    if (material->mMetallicRoughnessId.notNull()) +                    if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS].notNull())                      {                          texture_count++;                      } -                    if (material->mNormalId.notNull()) +                    if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL].notNull())                      {                          texture_count++;                      } -                    if (material->mEmissiveId.notNull()) +                    if (material->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE].notNull())                      {                          texture_count++;                      } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 5a365c79ea..88d5d50845 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4993,10 +4993,10 @@ void LLViewerObject::updateTEMaterialTextures(U8 te)      if (mat != nullptr)      { -        mat->mBaseColorTexture = fetch_texture(mat->mBaseColorId); -        mat->mNormalTexture = fetch_texture(mat->mNormalId); -        mat->mMetallicRoughnessTexture = fetch_texture(mat->mMetallicRoughnessId); -        mat->mEmissiveTexture= fetch_texture(mat->mEmissiveId); +        mat->mBaseColorTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR]); +        mat->mNormalTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL]); +        mat->mMetallicRoughnessTexture = fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS]); +        mat->mEmissiveTexture= fetch_texture(mat->mTextureId[LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE]);      }  }  | 
