SL-19080: Update GLTF Material asset upload to v1.1, with stricter GLTF compliance and removal of unsupported features

master
Cosmic Linden 2023-02-09 15:04:46 -08:00
parent 627e3d51c6
commit d6841c0798
10 changed files with 442 additions and 275 deletions

View File

@ -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)

View File

@ -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())
{

View File

@ -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);
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id, LLUUID& texture_id_out);
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);
};

View File

@ -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);
}
}
}

View File

@ -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())
{

View File

@ -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());

View File

@ -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();

View File

@ -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;
}

View File

@ -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++;
}

View File

@ -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]);
}
}