llgltfmaterial.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /**
  2. * @file llgltfmaterial.h
  3. * @brief LLGLTFMaterial definition
  4. *
  5. * $LicenseInfo:firstyear=2022&license=viewergpl$
  6. *
  7. * Copyright (c) 2022, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLGLTFMATERIAL_H
  33. #define LL_LLGLTFMATERIAL_H
  34. #include <array>
  35. #include <string>
  36. #include "llcolor3.h"
  37. #include "llcolor4.h"
  38. #include "hbfastmap.h"
  39. #include "llpointer.h"
  40. #include "llrefcount.h"
  41. #include "llsd.h"
  42. #include "llvector2.h"
  43. namespace tinygltf
  44. {
  45. class Model;
  46. }
  47. class LLFetchedGLTFMaterial;
  48. class LLTextureEntry;
  49. class LLGLTFMaterial : public LLRefCount
  50. {
  51. public:
  52. enum AlphaMode : U32
  53. {
  54. ALPHA_MODE_OPAQUE = 0,
  55. ALPHA_MODE_BLEND,
  56. ALPHA_MODE_MASK
  57. };
  58. LLGLTFMaterial();
  59. LL_INLINE LLGLTFMaterial(const LLGLTFMaterial& rhs)
  60. {
  61. *this = rhs;
  62. }
  63. LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs);
  64. LL_INLINE bool operator==(const LLGLTFMaterial& rhs) const
  65. {
  66. return mTextureId == rhs.mTextureId &&
  67. mTextureTransform == rhs.mTextureTransform &&
  68. mBaseColor == rhs.mBaseColor &&
  69. mEmissiveColor == rhs.mEmissiveColor &&
  70. mMetallicFactor == rhs.mMetallicFactor &&
  71. mRoughnessFactor == rhs.mRoughnessFactor &&
  72. mAlphaCutoff == rhs.mAlphaCutoff &&
  73. mAlphaMode == rhs.mAlphaMode &&
  74. mDoubleSided == rhs.mDoubleSided &&
  75. mOverrideAlphaMode == rhs.mOverrideAlphaMode &&
  76. mOverrideDoubleSided == rhs.mOverrideDoubleSided;
  77. }
  78. LL_INLINE bool operator!=(const LLGLTFMaterial& rhs) const
  79. {
  80. return mTextureId != rhs.mTextureId ||
  81. mTextureTransform != rhs.mTextureTransform ||
  82. mBaseColor != rhs.mBaseColor ||
  83. mEmissiveColor != rhs.mEmissiveColor ||
  84. mMetallicFactor != rhs.mMetallicFactor ||
  85. mRoughnessFactor != rhs.mRoughnessFactor ||
  86. mAlphaCutoff != rhs.mAlphaCutoff ||
  87. mAlphaMode != rhs.mAlphaMode ||
  88. mOverrideAlphaMode != rhs.mOverrideAlphaMode ||
  89. mDoubleSided != rhs.mDoubleSided ||
  90. mOverrideDoubleSided != rhs.mOverrideDoubleSided;
  91. }
  92. virtual LLFetchedGLTFMaterial* asFetched() { return NULL; }
  93. class TextureTransform
  94. {
  95. public:
  96. LL_INLINE TextureTransform()
  97. : mScale(1.f, 1.f),
  98. mRotation(0.f)
  99. {
  100. }
  101. LL_INLINE void getPacked(F32(&packed)[8])
  102. {
  103. packed[0] = mScale.mV[VX];
  104. packed[1] = mScale.mV[VY];
  105. packed[2] = mRotation;
  106. packed[4] = mOffset.mV[VX];
  107. packed[5] = mOffset.mV[VY];
  108. // Not used but nonetheless zeroed for proper hashing. HB
  109. packed[3] = packed[6] = packed[7] = 0.f;
  110. }
  111. LL_INLINE bool operator==(const TextureTransform& rhs) const
  112. {
  113. return mOffset == rhs.mOffset && mScale == rhs.mScale &&
  114. mRotation == rhs.mRotation;
  115. }
  116. LL_INLINE bool operator!=(const TextureTransform& rhs) const
  117. {
  118. return mOffset != rhs.mOffset || mScale != rhs.mScale ||
  119. mRotation != rhs.mRotation;
  120. }
  121. public:
  122. LLVector2 mScale;
  123. LLVector2 mOffset;
  124. F32 mRotation;
  125. };
  126. enum TextureInfo : U32
  127. {
  128. GLTF_TEXTURE_INFO_BASE_COLOR,
  129. GLTF_TEXTURE_INFO_NORMAL,
  130. GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
  131. // *NOTE: GLTF_TEXTURE_INFO_OCCLUSION is currently ignored, in favor of
  132. // the values specified with GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS.
  133. // Currently, only ORM materials are supported (materials which define
  134. // occlusion, roughness, and metallic in the same texture).
  135. // -Cosmic,2023-01-26
  136. GLTF_TEXTURE_INFO_OCCLUSION = GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
  137. GLTF_TEXTURE_INFO_EMISSIVE,
  138. GLTF_TEXTURE_INFO_COUNT
  139. };
  140. // Get a UUID based on a hash of this LLGLTFMaterial
  141. LLUUID getHash() const;
  142. // Setters for various members (will clamp to acceptable ranges)
  143. // for_override - set to true if this value is being set as part of an
  144. // override (important for handling override to default value)
  145. LL_INLINE void setTextureId(TextureInfo tex_info, const LLUUID& id,
  146. // Use 'const' to try and hint the compiler to
  147. // optimize out for_override test during
  148. // inlining when possible. HB
  149. const bool for_override = false)
  150. {
  151. mTextureId[tex_info] = id;
  152. if (for_override)
  153. {
  154. hackOverrideUUID(mTextureId[tex_info]);
  155. }
  156. }
  157. LL_INLINE void setBaseColorId(const LLUUID& id,
  158. const bool for_override = false)
  159. {
  160. setTextureId(GLTF_TEXTURE_INFO_BASE_COLOR, id, for_override);
  161. }
  162. LL_INLINE void setNormalId(const LLUUID& id,
  163. const bool for_override = false)
  164. {
  165. setTextureId(GLTF_TEXTURE_INFO_NORMAL, id, for_override);
  166. }
  167. LL_INLINE void setMetallicRoughnessId(const LLUUID& id,
  168. const bool overrd = false)
  169. {
  170. setTextureId(GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS, id, overrd);
  171. }
  172. LL_INLINE void setEmissiveId(const LLUUID& id,
  173. const bool for_override = false)
  174. {
  175. setTextureId(GLTF_TEXTURE_INFO_EMISSIVE, id, for_override);
  176. }
  177. // Inlined (non-overridden) texture UUIDs getters, for ease of use. HB
  178. LL_INLINE const LLUUID& getBaseColorId() const
  179. {
  180. return mTextureId[GLTF_TEXTURE_INFO_BASE_COLOR];
  181. }
  182. LL_INLINE const LLUUID& getNormalId() const
  183. {
  184. return mTextureId[GLTF_TEXTURE_INFO_NORMAL];
  185. }
  186. LL_INLINE const LLUUID& getMetallicRoughnessId() const
  187. {
  188. return mTextureId[GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS];
  189. }
  190. LL_INLINE const LLUUID& getEmissiveId() const
  191. {
  192. return mTextureId[GLTF_TEXTURE_INFO_EMISSIVE];
  193. }
  194. void setBaseColorFactor(const LLColor4& base_color,
  195. bool for_override = false);
  196. void setAlphaCutoff(F32 cutoff, bool for_override = false);
  197. void setEmissiveColorFactor(const LLColor3& emissive_color,
  198. bool for_override = false);
  199. void setMetallicFactor(F32 metallic, bool for_override = false);
  200. void setRoughnessFactor(F32 roughness, bool for_override = false);
  201. void setAlphaMode(U32 mode, bool for_override = false);
  202. void setDoubleSided(bool double_sided, bool for_override = false);
  203. // NOTE: texture offsets only exist in overrides, so "for_override" is not
  204. // needed
  205. LL_INLINE void setTextureOffset(TextureInfo tex_info,
  206. const LLVector2& offset)
  207. {
  208. mTextureTransform[tex_info].mOffset = offset;
  209. }
  210. LL_INLINE const LLVector2& getBaseColorOffset() const
  211. {
  212. return mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mOffset;
  213. }
  214. LL_INLINE void setTextureScale(TextureInfo tex_info,
  215. const LLVector2& scale)
  216. {
  217. mTextureTransform[tex_info].mScale = scale;
  218. }
  219. LL_INLINE const LLVector2& getBaseColorScale() const
  220. {
  221. return mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mScale;
  222. }
  223. LL_INLINE void setTextureRotation(TextureInfo tex_info, F32 rotation)
  224. {
  225. mTextureTransform[tex_info].mRotation = rotation;
  226. }
  227. LL_INLINE F32 getBaseColorRotation() const
  228. {
  229. return mTextureTransform[GLTF_TEXTURE_INFO_BASE_COLOR].mRotation;
  230. }
  231. // Default value accessors these MUST match the GLTF specification)
  232. LL_INLINE static F32 getDefaultAlphaCutoff()
  233. {
  234. return sDefault.mAlphaCutoff;
  235. }
  236. LL_INLINE static U32 getDefaultAlphaMode()
  237. {
  238. return sDefault.mAlphaMode;
  239. }
  240. LL_INLINE static F32 getDefaultMetallicFactor()
  241. {
  242. return sDefault.mMetallicFactor;
  243. }
  244. LL_INLINE static F32 getDefaultRoughnessFactor()
  245. {
  246. return sDefault.mRoughnessFactor;
  247. }
  248. LL_INLINE static const LLColor4& getDefaultBaseColor()
  249. {
  250. return sDefault.mBaseColor;
  251. }
  252. LL_INLINE static const LLColor3& getDefaultEmissiveColor()
  253. {
  254. return sDefault.mEmissiveColor;
  255. }
  256. LL_INLINE static bool getDefaultDoubleSided()
  257. {
  258. return sDefault.mDoubleSided;
  259. }
  260. LL_INLINE static const LLVector2& getDefaultTextureOffset()
  261. {
  262. return sDefault.mTextureTransform[0].mOffset;
  263. }
  264. LL_INLINE static const LLVector2& getDefaultTextureScale()
  265. {
  266. return sDefault.mTextureTransform[0].mScale;
  267. }
  268. LL_INLINE static F32 getDefaultTextureRotation()
  269. {
  270. return sDefault.mTextureTransform[0].mRotation;
  271. }
  272. // Sets mAlphaMode from string. Anything otherthan "MASK" or "BLEND" sets
  273. // mAlphaMode to ALPHA_MODE_OPAQUE.
  274. void setAlphaMode(const std::string& mode, bool for_override = false);
  275. const char* getAlphaMode() const;
  276. // Sets the contents of this LLGLTFMaterial from the given json; returns
  277. // true if successful, false if unsuccessful and the contents of this
  278. // LLGLTFMaterial is then left unchanged.
  279. // json - the json text to load from
  280. // warn_msg - warning message from TinyGLTF if any
  281. // error_msg - error_msg from TinyGLTF if any
  282. bool fromJSON(const std::string& json, std::string& warn_msg,
  283. std::string& error_msg);
  284. // Gets the contents of this LLGLTFMaterial as a json string
  285. std::string asJSON(bool prettyprint = false) const;
  286. // Initializes from given tinygltf::Model with the 'model' to reference
  287. // and the index of material 'mat_index' in the model's material array.
  288. void setFromModel(const tinygltf::Model& model, S32 mat_index);
  289. // Writes to given tinygltf::Model
  290. void writeToModel(tinygltf::Model& model, S32 mat_index) const;
  291. void applyOverride(const LLGLTFMaterial& override_mat);
  292. // Applies the given LLSD override data
  293. void applyOverrideLLSD(const LLSD& data);
  294. // Returns the override for this LLGLTFMaterial as an LLSD.
  295. LLSD getOverrideLLSD() const;
  296. // For base materials only (i.e. assets). Clears transforms to default
  297. // since they are not supported in assets yet.
  298. LL_INLINE void sanitizeAssetMaterial()
  299. {
  300. mTextureTransform = sDefault.mTextureTransform;
  301. }
  302. // For material overrides only. Clears most properties to
  303. // default/fallthrough, but preserves the transforms.
  304. bool setBaseMaterial();
  305. // True if setBaseMaterial() was just called
  306. bool isClearedForBaseMaterial() const;
  307. LL_INLINE static bool isAcceptedVersion(const std::string& version)
  308. {
  309. return version == "1.1" || version == "1.0";
  310. }
  311. // For local materials, we have to keep track of where they are assigned to
  312. // for full updates.
  313. LL_INLINE virtual void addTextureEntry(LLTextureEntry* tep) {}
  314. LL_INLINE virtual void removeTextureEntry(LLTextureEntry* tep) {}
  315. // For local materials, so that editor will know to track changes.
  316. void addLocalTextureTracking(const LLUUID& tracking_id,
  317. const LLUUID& tex_id);
  318. void removeLocalTextureTracking(const LLUUID& tracking_id);
  319. LL_INLINE bool hasLocalTextures() const
  320. {
  321. return !mTrackingIdToLocalTexture.empty();
  322. }
  323. virtual bool replaceLocalTexture(const LLUUID& tracking_id,
  324. const LLUUID& old_id,
  325. const LLUUID& new_id);
  326. LL_INLINE virtual void updateTextureTracking() {}
  327. private:
  328. static void hackOverrideUUID(LLUUID& id);
  329. template<typename T>
  330. void setFromTexture(const tinygltf::Model& model, const T& tex_info,
  331. TextureInfo tex_info_id);
  332. template<typename T>
  333. void writeToTexture(tinygltf::Model& model, T& tex_info,
  334. TextureInfo tex_info_id,
  335. bool force_write = false) const;
  336. LL_INLINE void setBaseMaterial(const LLGLTFMaterial& old_override_mat)
  337. {
  338. mTextureTransform = old_override_mat.mTextureTransform;
  339. }
  340. // Used to update the digest of the mTrackingIdToLocalTexture map each time
  341. // it is changed; this way, that digest can be used by the fast getHash()
  342. // method instead of having to hash all individual keys and values. HB
  343. void updateLocalTexDataDigest();
  344. public:
  345. // This is local to the viewer and part of local material support.
  346. // IMPORTANT: do not move this member down (and do not move
  347. // mLocalTexDataDigest either): the getHash() method does rely on the
  348. // current ordering. HB
  349. typedef fast_hmap<LLUUID, LLUUID> local_tex_map_t;
  350. local_tex_map_t mTrackingIdToLocalTexture;
  351. // Used to store a digest of mTrackingIdToLocalTexture when the latter is
  352. // not empty, or zero otherwise. HB
  353. U64 mLocalTexDataDigest;
  354. typedef std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> uuid_array_t;
  355. uuid_array_t mTextureId;
  356. typedef std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> tf_array_t;
  357. tf_array_t mTextureTransform;
  358. // These values should be in linear color space.
  359. LLColor4 mBaseColor;
  360. LLColor3 mEmissiveColor;
  361. F32 mMetallicFactor;
  362. F32 mRoughnessFactor;
  363. F32 mAlphaCutoff;
  364. U32 mAlphaMode;
  365. bool mDoubleSided;
  366. // Override specific flags for state that cannot use off-by-epsilon or UUID
  367. // hack
  368. bool mOverrideDoubleSided;
  369. bool mOverrideAlphaMode;
  370. static const char* const ASSET_VERSION;
  371. static const char* const ASSET_TYPE;
  372. // Default material for reference
  373. static const LLGLTFMaterial sDefault;
  374. };
  375. typedef std::vector<LLPointer<LLGLTFMaterial> > gltf_mat_vec_t;
  376. // Never-ending C++ names bother me to no end ! So, let's provide and use some
  377. // shortcuts for the sake of sanity ! HB
  378. constexpr U32 BASECOLIDX = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR;
  379. constexpr U32 NORMALIDX = LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL;
  380. constexpr U32 MROUGHIDX = LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS;
  381. constexpr U32 EMISSIVEIDX = LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE;
  382. #endif // LL_LLGLTFMATERIAL_H