-
Andrey Kleshchev authoredAndrey Kleshchev authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
llgltfmaterial.h 10.08 KiB
/**
* @file llgltfmaterial.h
* @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$
*/
#pragma once
#include "llrefcount.h"
#include "llmemory.h"
#include "v4color.h"
#include "v3color.h"
#include "v2math.h"
#include "lluuid.h"
#include "hbxxh.h"
#include <array>
#include <string>
#include <map>
namespace tinygltf
{
class Model;
struct TextureInfo;
class Value;
}
class LLTextureEntry;
class LLGLTFMaterial : public LLRefCount
{
public:
// default material for reference
static const LLGLTFMaterial sDefault;
static const char* const ASSET_VERSION;
static const char* const ASSET_TYPE;
// Max allowed size of a GLTF material asset or override, when serialized
// as a minified JSON string
static constexpr size_t MAX_ASSET_LENGTH = 2048;
static const std::array<std::string, 2> ACCEPTED_ASSET_VERSIONS;
static bool isAcceptedVersion(const std::string& version) { return std::find(ACCEPTED_ASSET_VERSIONS.cbegin(), ACCEPTED_ASSET_VERSIONS.cend(), version) != ACCEPTED_ASSET_VERSIONS.cend(); }
struct TextureTransform
{
LLVector2 mOffset = { 0.f, 0.f };
LLVector2 mScale = { 1.f, 1.f };
F32 mRotation = 0.f;
void getPacked(F32 (&packed)[8]) const;
bool operator==(const TextureTransform& other) const;
bool operator!=(const TextureTransform& other) const { return !(*this == other); }
};
enum AlphaMode
{
ALPHA_MODE_OPAQUE = 0,
ALPHA_MODE_BLEND,
ALPHA_MODE_MASK
};
LLGLTFMaterial() {}
LLGLTFMaterial(const LLGLTFMaterial& rhs);
LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs);
bool operator==(const LLGLTFMaterial& rhs) const;
bool operator!=(const LLGLTFMaterial& rhs) const { return !(*this == rhs); }
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
};
static const char* const GLTF_FILE_EXTENSION_TRANSFORM;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_SCALE;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_OFFSET;
static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION;
static const LLUUID GLTF_OVERRIDE_NULL_UUID;
std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId;
std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
// NOTE: initialize values to defaults according to the GLTF spec
// NOTE: these values should be in linear color space
LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
F32 mMetallicFactor = 1.f;
F32 mRoughnessFactor = 1.f;
F32 mAlphaCutoff = 0.5f;
bool mDoubleSided = false;
AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE;
// override specific flags for state that can't use off-by-epsilon or UUID hack
bool mOverrideDoubleSided = false;
bool mOverrideAlphaMode = false;
// get a UUID based on a hash of this LLGLTFMaterial
LLUUID getHash() const;
//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 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);
void setAlphaCutoff(F32 cutoff, bool for_override = false);
void setEmissiveColorFactor(const LLColor3& emissiveColor, bool for_override = false);
void setMetallicFactor(F32 metallic, bool for_override = false);
void setRoughnessFactor(F32 roughness, bool for_override = false);
void setAlphaMode(S32 mode, bool for_override = false);
void setDoubleSided(bool double_sided, bool for_override = false);
// *NOTE: texture offsets only exist in overrides, so "for_override" is not needed
void setTextureOffset(TextureInfo texture_info, const LLVector2& offset);
void setTextureScale(TextureInfo texture_info, const LLVector2& scale);
void setTextureRotation(TextureInfo texture_info, float rotation);
// Default value accessors
static F32 getDefaultAlphaCutoff();
static S32 getDefaultAlphaMode();
static F32 getDefaultMetallicFactor();
static F32 getDefaultRoughnessFactor();
static LLColor4 getDefaultBaseColor();
static LLColor3 getDefaultEmissiveColor();
static bool getDefaultDoubleSided();
static LLVector2 getDefaultTextureOffset();
static LLVector2 getDefaultTextureScale();
static F32 getDefaultTextureRotation();
static void hackOverrideUUID(LLUUID& id);
static void applyOverrideUUID(LLUUID& dst_id, const LLUUID& override_id);
// set mAlphaMode from string.
// Anything otherthan "MASK" or "BLEND" sets mAlphaMode to ALPHA_MODE_OPAQUE
void setAlphaMode(const std::string& mode, bool for_override = false);
const char* getAlphaMode() const;
// set the contents of this LLGLTFMaterial from the given json
// returns true if successful
// if unsuccessful, the contents of this LLGLTFMaterial should be left unchanged and false is returned
// 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;
virtual void applyOverride(const LLGLTFMaterial& override_mat);
// apply the given LLSD override data
void applyOverrideLLSD(const LLSD& data);
// Get the given override on this LLGLTFMaterial as LLSD
// override_mat -- the override source data
// data -- output LLSD object (should be passed in empty)
void getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data);
// For base materials only (i.e. assets). Clears transforms to
// default since they're not supported in assets yet.
void sanitizeAssetMaterial();
// For material overrides only. Clears most properties to
// default/fallthrough, but preserves the transforms.
bool setBaseMaterial();
void setBaseMaterial(const LLGLTFMaterial& old_override_mat);
// True if setBaseMaterial() was just called
bool isClearedForBaseMaterial() const;
// For local materials, they have to keep track of where
// they are assigned to for full updates
virtual void addTextureEntry(LLTextureEntry* te) {};
virtual void removeTextureEntry(LLTextureEntry* te) {};
// For local textures so that editor will know to track changes
void addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID &tex_id);
void removeLocalTextureTracking(const LLUUID& tracking_id);
bool hasLocalTextures() { return !mTrackingIdToLocalTexture.empty(); }
virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id);
virtual void updateTextureTracking();
// These fields are local to viewer and are a part of local bitmap support
typedef std::map<LLUUID, LLUUID> local_tex_map_t;
local_tex_map_t mTrackingIdToLocalTexture;
protected:
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
template<typename T>
static void allocateTextureImage(tinygltf::Model& model, T& texture_info, const std::string& uri);
template<typename T>
void setFromTexture(const tinygltf::Model& model, const T& texture_info, TextureInfo texture_info_id);
template<typename T>
static void setFromTexture(const tinygltf::Model& model, const T& texture_info, LLUUID& texture_id, TextureTransform& transform);
template<typename T>
void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const;
template<typename T>
static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false);
};