diff options
-rw-r--r-- | indra/llmath/v3color.h | 32 | ||||
-rw-r--r-- | indra/llmath/v4color.h | 29 | ||||
-rw-r--r-- | indra/llprimitive/CMakeLists.txt | 1 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.cpp | 199 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 34 | ||||
-rw-r--r-- | indra/newview/llgltfmateriallist.cpp | 13 | ||||
-rw-r--r-- | indra/newview/lllocalgltfmaterials.cpp | 2 | ||||
-rw-r--r-- | indra/newview/lltinygltfhelper.cpp | 65 | ||||
-rw-r--r-- | indra/newview/lltinygltfhelper.h | 1 |
9 files changed, 293 insertions, 83 deletions
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 0b3b4ea3e1..d925f56e97 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -88,6 +88,16 @@ public: const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z) const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec + + // set from a vector of unknown type and size + // may leave some data unmodified + template<typename T> + const LLColor3& set(const std::vector<T>& v); + + // write to a vector of unknown type and size + // maye leave some data unmodified + template<typename T> + void write(std::vector<T>& v) const; F32 magVec() const; // deprecated F32 magVecSquared() const; // deprecated @@ -504,4 +514,26 @@ inline const LLVector3 linearColor3v(const T& a) { return LLVector3(linearColor3p(a.mV).mV); } +template<typename T> +const LLColor3& LLColor3::set(const std::vector<T>& v) +{ + for (S32 i = 0; i < llmin((S32)v.size(), 3); ++i) + { + mV[i] = v[i]; + } + + return *this; +} + +// write to a vector of unknown type and size +// maye leave some data unmodified +template<typename T> +void LLColor3::write(std::vector<T>& v) const +{ + for (int i = 0; i < llmin((S32)v.size(), 3); ++i) + { + v[i] = mV[i]; + } +} + #endif diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index f2863be531..daa61594fb 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -91,6 +91,15 @@ class LLColor4 const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled. + // set from a vector of unknown type and size + // may leave some data unmodified + template<typename T> + const LLColor4& set(const std::vector<T>& v); + + // write to a vector of unknown type and size + // maye leave some data unmodified + template<typename T> + void write(std::vector<T>& v) const; const LLColor4& setAlpha(F32 a); @@ -690,5 +699,25 @@ inline const LLColor4 linearColor4(const LLColor4 &a) return linearColor; } +template<typename T> +const LLColor4& LLColor4::set(const std::vector<T>& v) +{ + for (S32 i = 0; i < llmin((S32)v.size(), 4); ++i) + { + mV[i] = v[i]; + } + + return *this; +} + +template<typename T> +void LLColor4::write(std::vector<T>& v) const +{ + for (int i = 0; i < llmin((S32)v.size(), 4); ++i) + { + v[i] = mV[i]; + } +} + #endif diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index bb14bb9242..328b22f900 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -33,6 +33,7 @@ include_directories(SYSTEM set(llprimitive_SOURCE_FILES lldaeloader.cpp llgltfloader.cpp + llgltfmaterial.cpp llmaterialid.cpp llmaterial.cpp llmaterialtable.cpp diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp new file mode 100644 index 0000000000..369a1786a3 --- /dev/null +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -0,0 +1,199 @@ +/** + * @file llgltfmaterial.cpp + * @brief Material definition + * + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2022, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llgltfmaterial.h" + +#include "tiny_gltf.h" + +bool LLGLTFMaterial::fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg) +{ + tinygltf::TinyGLTF gltf; + + tinygltf::Model model_in; + + if (gltf.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, json.c_str(), json.length(), "")) + { + setFromModel(model_in, 0); + + //DEBUG generate json and print + LL_INFOS() << asJSON(true) << LL_ENDL; + + return true; + } + + return false; +} + +std::string LLGLTFMaterial::asJSON(bool prettyprint) const +{ + tinygltf::TinyGLTF gltf; + tinygltf::Model model_out; + + std::ostringstream str; + + writeToModel(model_out, 0); + + gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false); + + return str.str(); +} + +void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index) +{ + if (model.materials.size() <= mat_index) + { + return; + } + + const tinygltf::Material& material_in = model.materials[mat_index]; + + // get base color texture + S32 tex_index = material_in.pbrMetallicRoughness.baseColorTexture.index; + if (tex_index >= 0) + { + mBaseColorId.set(model.images[tex_index].uri); + } + else + { + mBaseColorId.setNull(); + } + + // get normal map + tex_index = material_in.normalTexture.index; + if (tex_index >= 0) + { + mNormalId.set(model.images[tex_index].uri); + } + else + { + mNormalId.setNull(); + } + + // get metallic-roughness texture + tex_index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index; + if (tex_index >= 0) + { + mMetallicRoughnessId.set(model.images[tex_index].uri); + } + else + { + mMetallicRoughnessId.setNull(); + } + + // get emissive texture + tex_index = material_in.emissiveTexture.index; + if (tex_index >= 0) + { + mEmissiveId.set(model.images[tex_index].uri); + } + else + { + mEmissiveId.setNull(); + } + + setAlphaMode(material_in.alphaMode); + mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f); + + mBaseColor.set(material_in.pbrMetallicRoughness.baseColorFactor); + mEmissiveColor.set(material_in.emissiveFactor); + + mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f); + mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f); + + mDoubleSided = material_in.doubleSided; +} + +void LLGLTFMaterial::writeToModel(tinygltf::Model& model, S32 mat_index) const +{ + if (model.materials.size() < mat_index+1) + { + model.materials.resize(mat_index + 1); + } + + tinygltf::Material& material_out = model.materials[mat_index]; + + // set base color texture + if (mBaseColorId.notNull()) + { + U32 idx = model.images.size(); + model.images.resize(idx + 1); + model.textures.resize(idx + 1); + + material_out.pbrMetallicRoughness.baseColorTexture.index = idx; + model.textures[idx].source = idx; + model.images[idx].uri = mBaseColorId.asString(); + } + + // set normal texture + if (mNormalId.notNull()) + { + U32 idx = model.images.size(); + model.images.resize(idx + 1); + model.textures.resize(idx + 1); + + material_out.normalTexture.index = idx; + model.textures[idx].source = idx; + model.images[idx].uri = mNormalId.asString(); + } + + // set metallic-roughness texture + if (mMetallicRoughnessId.notNull()) + { + U32 idx = model.images.size(); + model.images.resize(idx + 1); + model.textures.resize(idx + 1); + + material_out.pbrMetallicRoughness.metallicRoughnessTexture.index = idx; + model.textures[idx].source = idx; + model.images[idx].uri = mMetallicRoughnessId.asString(); + } + + // set emissive texture + if (mEmissiveId.notNull()) + { + U32 idx = model.images.size(); + model.images.resize(idx + 1); + model.textures.resize(idx + 1); + + material_out.emissiveTexture.index = idx; + model.textures[idx].source = idx; + model.images[idx].uri = mEmissiveId.asString(); + } + + material_out.alphaMode = getAlphaMode(); + material_out.alphaCutoff = mAlphaCutoff; + + mBaseColor.write(material_out.pbrMetallicRoughness.baseColorFactor); + mEmissiveColor.write(material_out.emissiveFactor); + + material_out.pbrMetallicRoughness.metallicFactor = mMetallicFactor; + material_out.pbrMetallicRoughness.roughnessFactor = mRoughnessFactor; + + material_out.doubleSided = mDoubleSided; +} + diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 36636c3b4e..8efcc9d753 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -32,6 +32,13 @@ #include "lluuid.h" #include "llmd5.h" +#include <string> + +namespace tinygltf +{ + class Model; +} + class LLGLTFMaterial : public LLRefCount { public: @@ -48,8 +55,8 @@ public: LLUUID mMetallicRoughnessId; LLUUID mEmissiveId; - LLColor4 mBaseColor = LLColor4(1,1,1,1); - LLColor3 mEmissiveColor = LLColor3(0,0,0); + LLColor4 mBaseColor = LLColor4(1, 1, 1, 1); + LLColor3 mEmissiveColor = LLColor3(0, 0, 0); F32 mMetallicFactor = 0.f; F32 mRoughnessFactor = 0.f; @@ -63,7 +70,7 @@ public: { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLMD5 md5; - md5.update((unsigned char*) this, sizeof(this)); + md5.update((unsigned char*)this, sizeof(this)); md5.finalize(); LLUUID id; md5.raw_digest(id.mData); @@ -88,7 +95,7 @@ public: } } - const char* getAlphaMode() + const char* getAlphaMode() const { switch (mAlphaMode) { @@ -97,7 +104,24 @@ public: default: return "OPAQUE"; } } -}; + // set the contents of this LLGLTFMaterial from the given json + // returns true if successful + // json - the json text to load from + // warn_msg - warning message from TinyGLTF if any + // error_msg - error_msg from TinyGLTF if any + bool fromJSON(const std::string& json, std::string& warn_msg, std::string& error_msg); + // get the contents of this LLGLTFMaterial as a json string + std::string asJSON(bool prettyprint = false) const; + + // initialize from given tinygltf::Model + // model - the model to reference + // mat_index - index of material in model's material array + void setFromModel(const tinygltf::Model& model, S32 mat_index); + + // write to given tinygltf::Model + void writeToModel(tinygltf::Model& model, S32 mat_index) const; + +}; diff --git a/indra/newview/llgltfmateriallist.cpp b/indra/newview/llgltfmateriallist.cpp index 9c71f11bbc..24fd623231 100644 --- a/indra/newview/llgltfmateriallist.cpp +++ b/indra/newview/llgltfmateriallist.cpp @@ -106,18 +106,9 @@ LLGLTFMaterial* LLGLTFMaterialList::getMaterial(const LLUUID& id) { std::string data = asset["data"]; - tinygltf::TinyGLTF gltf; - tinygltf::TinyGLTF loader; - std::string error_msg; - std::string warn_msg; + std::string warn_msg, error_msg; - tinygltf::Model model_in; - - if (loader.LoadASCIIFromString(&model_in, &error_msg, &warn_msg, data.c_str(), data.length(), "")) - { - LLTinyGLTFHelper::setFromModel(mat, model_in, 0); - } - else + if (!mat->fromJSON(data, warn_msg, error_msg)) { LL_WARNS() << "Failed to decode material asset: " << LL_ENDL; LL_WARNS() << warn_msg << LL_ENDL; diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp index 1f16549a47..fe2b7ac816 100644 --- a/indra/newview/lllocalgltfmaterials.cpp +++ b/indra/newview/lllocalgltfmaterials.cpp @@ -270,7 +270,7 @@ bool LLLocalGLTFMaterial::loadMaterial(LLPointer<LLGLTFMaterial> mat, S32 index) } // sets everything, but textures will have inaccurate ids - LLTinyGLTFHelper::setFromModel(mat, model_in, index); + mat->setFromModel(model_in, index); std::string folder = gDirUtilp->getDirName(filename_lc); tinygltf::Material material_in = model_in.materials[index]; diff --git a/indra/newview/lltinygltfhelper.cpp b/indra/newview/lltinygltfhelper.cpp index c3dc10c2a0..c80e87652a 100644 --- a/indra/newview/lltinygltfhelper.cpp +++ b/indra/newview/lltinygltfhelper.cpp @@ -122,71 +122,6 @@ void LLTinyGLTFHelper::initFetchedTextures(tinygltf::Material& material, } } -void LLTinyGLTFHelper::setFromModel(LLGLTFMaterial* mat, tinygltf::Model& model, S32 mat_index) -{ - if (model.materials.size() <= mat_index) - { - return; - } - - tinygltf::Material& material_in = model.materials[mat_index]; - - // get base color texture - S32 tex_index = material_in.pbrMetallicRoughness.baseColorTexture.index; - if (tex_index >= 0) - { - mat->mBaseColorId.set(model.images[tex_index].uri); - } - else - { - mat->mBaseColorId.setNull(); - } - - // get normal map - tex_index = material_in.normalTexture.index; - if (tex_index >= 0) - { - mat->mNormalId.set(model.images[tex_index].uri); - } - else - { - mat->mNormalId.setNull(); - } - - // get metallic-roughness texture - tex_index = material_in.pbrMetallicRoughness.metallicRoughnessTexture.index; - if (tex_index >= 0) - { - mat->mMetallicRoughnessId.set(model.images[tex_index].uri); - } - else - { - mat->mMetallicRoughnessId.setNull(); - } - - // get emissive texture - tex_index = material_in.emissiveTexture.index; - if (tex_index >= 0) - { - mat->mEmissiveId.set(model.images[tex_index].uri); - } - else - { - mat->mEmissiveId.setNull(); - } - - mat->setAlphaMode(material_in.alphaMode); - mat->mAlphaCutoff = llclamp((F32)material_in.alphaCutoff, 0.f, 1.f); - - mat->mBaseColor= getColor(material_in.pbrMetallicRoughness.baseColorFactor); - mat->mEmissiveColor = getColor(material_in.emissiveFactor); - - mat->mMetallicFactor = llclamp((F32)material_in.pbrMetallicRoughness.metallicFactor, 0.f, 1.f); - mat->mRoughnessFactor = llclamp((F32)material_in.pbrMetallicRoughness.roughnessFactor, 0.f, 1.f); - - mat->mDoubleSided = material_in.doubleSided; -} - LLColor4 LLTinyGLTFHelper::getColor(const std::vector<double>& in) { LLColor4 out; diff --git a/indra/newview/lltinygltfhelper.h b/indra/newview/lltinygltfhelper.h index afe4517417..9c2e5afc17 100644 --- a/indra/newview/lltinygltfhelper.h +++ b/indra/newview/lltinygltfhelper.h @@ -35,7 +35,6 @@ class LLViewerFetchedTexture; namespace LLTinyGLTFHelper { - void setFromModel(LLGLTFMaterial* mat, tinygltf::Model& model, S32 index); LLColor4 getColor(const std::vector<double>& in); const tinygltf::Image* getImageFromTextureIndex(const tinygltf::Model& model, S32 texture_index); LLImageRaw* getTexture(const std::string& folder, const tinygltf::Model& model, S32 texture_index, std::string& name); |