llgltfloader.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /**
  2. * @file llgltfloader.cpp
  3. * @brief LLGLTFLoader implementation
  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. // Import & define single-header gltf import/export lib
  33. #define TINYGLTF_IMPLEMENTATION
  34. #define TINYGLTF_USE_CPP14 // default is C++11
  35. // To avoid an issue with missing <filesystem> header with gcc 7. HB
  36. #define JSON_HAS_CPP_14
  37. // tinygltf by default loads image files using STB
  38. #define STB_IMAGE_IMPLEMENTATION
  39. // To use our own image loading:
  40. // 1.- replace this definition with TINYGLTF_NO_STB_IMAGE
  41. // 2.- provide image loader callback with
  42. // TinyGLTF::SetImageLoader(LoadimageDataFunction LoadImageData, void* data)
  43. // tinygltf saves image files using STB
  44. #define STB_IMAGE_WRITE_IMPLEMENTATION
  45. // similarly, can override with TINYGLTF_NO_STB_IMAGE_WRITE and
  46. // TinyGLTF::SetImageWriter(fxn, data)
  47. // Additionally, disable inclusion of STB header files entirely with
  48. // TINYGLTF_NO_INCLUDE_STB_IMAGE
  49. // TINYGLTF_NO_INCLUDE_STB_IMAGE_WRITE
  50. #include "tinygltf/tiny_gltf.h"
  51. // For GL_LINEAR
  52. #include "epoxy/gl.h"
  53. #include "llgltfloader.h"
  54. static const std::string lod_suffix[LLModel::NUM_LODS] =
  55. {
  56. "_LOD0",
  57. "_LOD1",
  58. "_LOD2",
  59. "",
  60. "_PHYS",
  61. };
  62. LLGLTFLoader::LLGLTFLoader(const std::string& filename, S32 lod,
  63. load_callback_t load_cb,
  64. joint_lookup_func_t joint_lookup_func,
  65. texture_load_func_t texture_load_func,
  66. state_callback_t state_cb, void* userdata,
  67. JointTransformMap& joint_transform_map,
  68. JointNameSet& joints_from_nodes,
  69. JointMap& legal_joint_names,
  70. U32 max_joints_per_mesh)
  71. : LLModelLoader(filename, lod, load_cb, joint_lookup_func, texture_load_func,
  72. state_cb, userdata, joint_transform_map, joints_from_nodes,
  73. legal_joint_names, max_joints_per_mesh),
  74. mMeshesLoaded(false),
  75. mMaterialsLoaded(false)
  76. {
  77. }
  78. bool LLGLTFLoader::openFile(const std::string& filename)
  79. {
  80. tinygltf::TinyGLTF loader;
  81. std::string error_msg, warn_msg;
  82. std::string filename_lc(filename);
  83. LLStringUtil::toLower(filename_lc);
  84. // Load a tinygltf model fom a file. Assumes that the input filename has
  85. // already been sanitized to one of (.gltf , .glb) extensions, so does a
  86. // simple find to distinguish.
  87. if (std::string::npos == filename_lc.rfind(".gltf"))
  88. {
  89. // File is binary
  90. mGltfLoaded = loader.LoadBinaryFromFile(&mGltfModel, &error_msg,
  91. &warn_msg, filename);
  92. }
  93. else
  94. {
  95. // File is ASCII
  96. mGltfLoaded = loader.LoadASCIIFromFile(&mGltfModel, &error_msg,
  97. &warn_msg, filename);
  98. }
  99. if (!mGltfLoaded)
  100. {
  101. if (!warn_msg.empty())
  102. {
  103. llwarns << "gltf load warning: " << warn_msg.c_str() << llendl;
  104. }
  105. if (!error_msg.empty())
  106. {
  107. llwarns << "gltf load error: " << error_msg.c_str() << llendl;
  108. }
  109. return false;
  110. }
  111. mMeshesLoaded = parseMeshes();
  112. #if 0 // *TOTO
  113. if (mMeshesLoaded)
  114. {
  115. uploadMeshes();
  116. }
  117. #endif
  118. mMaterialsLoaded = parseMaterials();
  119. if (mMaterialsLoaded)
  120. {
  121. uploadMaterials();
  122. }
  123. return mMeshesLoaded || mMaterialsLoaded;
  124. }
  125. bool LLGLTFLoader::parseMeshes()
  126. {
  127. if (!mGltfLoaded) return false;
  128. // 2022-04 DJH Volume params from dae example. *TODO understand PCODE
  129. LLVolumeParams volume_params;
  130. volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
  131. for (tinygltf::Mesh mesh : mGltfModel.meshes)
  132. {
  133. LLModel* modelp = new LLModel(volume_params, 0.f);
  134. if (populateModelFromMesh(modelp, mesh) &&
  135. modelp->getStatus() == LLModel::NO_ERRORS &&
  136. modelp->validate(true))
  137. {
  138. mModelList.push_back(modelp);
  139. }
  140. else
  141. {
  142. setLoadState(ERROR_MODEL + modelp->getStatus());
  143. delete modelp;
  144. return false;
  145. }
  146. }
  147. return true;
  148. }
  149. bool LLGLTFLoader::populateModelFromMesh(LLModel* modelp,
  150. const tinygltf::Mesh& mesh)
  151. {
  152. modelp->mLabel = mesh.name;
  153. tinygltf::Accessor indices_a, positions_a, normals_a, uv0_a, color0_a;
  154. auto prims = mesh.primitives;
  155. for (auto prim : prims)
  156. {
  157. if (prim.indices >= 0)
  158. {
  159. indices_a = mGltfModel.accessors[prim.indices];
  160. }
  161. S32 pos_idx = -1;
  162. if (prim.attributes.count("POSITION"))
  163. {
  164. pos_idx = prim.attributes.at("POSITION");
  165. }
  166. if (pos_idx >= 0)
  167. {
  168. positions_a = mGltfModel.accessors[pos_idx];
  169. if (positions_a.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT)
  170. {
  171. continue;
  172. }
  173. auto positions_bv = mGltfModel.bufferViews[positions_a.bufferView];
  174. auto positions_buf = mGltfModel.buffers[positions_bv.buffer];
  175. }
  176. #if 0
  177. S32 norm_idx = prim.attributes.count("NORMAL") ? prim.attributes.at("NORMAL") : -1;
  178. S32 tan_idx = prim.attributes.count("TANGENT") ? prim.attributes.at("TANGENT") : -1;
  179. S32 uv0_idx = prim.attributes.count("TEXCOORDS_0") ? prim.attributes.at("TEXCOORDS_0") : -1;
  180. S32 uv1_idx = prim.attributes.count("TEXCOORDS_1") ? prim.attributes.at("TEXCOORDS_1") : -1;
  181. S32 color0_idx = prim.attributes.count("COLOR_0") ? prim.attributes.at("COLOR_0") : -1;
  182. S32 color1_idx = prim.attributes.count("COLOR_1") ? prim.attributes.at("COLOR_1") : -1;
  183. if (prim.mode == TINYGLTF_MODE_TRIANGLES)
  184. {
  185. // auto pos = mesh. TODO resume here DJH 2022-04
  186. }
  187. #endif
  188. }
  189. #if 0
  190. modelp->addFace()
  191. #endif
  192. return false;
  193. }
  194. bool LLGLTFLoader::parseMaterials()
  195. {
  196. if (!mGltfLoaded) return false;
  197. // Fill local texture data structures
  198. mSamplers.clear();
  199. for (auto in_sampler : mGltfModel.samplers)
  200. {
  201. gltf_sampler sampler;
  202. sampler.magFilter =
  203. in_sampler.magFilter > 0 ? in_sampler.magFilter : GL_LINEAR;
  204. sampler.minFilter =
  205. in_sampler.minFilter > 0 ? in_sampler.minFilter : GL_LINEAR;
  206. sampler.wrapS = in_sampler.wrapS;
  207. sampler.wrapT = in_sampler.wrapT;
  208. sampler.name = in_sampler.name; // unused
  209. mSamplers.push_back(sampler);
  210. }
  211. mImages.clear();
  212. for (auto in_image : mGltfModel.images)
  213. {
  214. gltf_image image;
  215. image.numChannels = in_image.component;
  216. image.bytesPerChannel = in_image.bits >> 3; // Convert bits to bytes
  217. // Maps exactly, i.e.
  218. // TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE == GL_UNSIGNED_BYTE, etc
  219. image.pixelType = in_image.pixel_type;
  220. image.size = in_image.image.size();
  221. image.height = in_image.height;
  222. image.width = in_image.width;
  223. image.data = in_image.image.data();
  224. if (in_image.as_is)
  225. {
  226. llwarns << "Unsupported image encoding" << llendl;
  227. return false;
  228. }
  229. if (image.size != image.height * image.width * image.numChannels *
  230. image.bytesPerChannel)
  231. {
  232. llwarns << "Image size error" << llendl;
  233. return false;
  234. }
  235. mImages.push_back(image);
  236. }
  237. mTextures.clear();
  238. for (auto in_tex : mGltfModel.textures)
  239. {
  240. gltf_texture tex;
  241. tex.imageIdx = in_tex.source;
  242. tex.samplerIdx = in_tex.sampler;
  243. tex.imageUuid.setNull();
  244. if (tex.imageIdx >= mImages.size() || tex.samplerIdx >= mSamplers.size())
  245. {
  246. llwarns << "Texture sampler/image index error" << llendl;
  247. return false;
  248. }
  249. mTextures.push_back(tex);
  250. }
  251. // Parse each material
  252. for (tinygltf::Material gltf_material : mGltfModel.materials)
  253. {
  254. gltf_render_material mat;
  255. mat.name = gltf_material.name;
  256. tinygltf::PbrMetallicRoughness& pbr = gltf_material.pbrMetallicRoughness;
  257. mat.hasPBR = true; // Always true, for now
  258. mat.baseColor.set(pbr.baseColorFactor.data());
  259. mat.hasBaseTex = pbr.baseColorTexture.index >= 0;
  260. mat.baseColorTexIdx = pbr.baseColorTexture.index;
  261. mat.baseColorTexCoords = pbr.baseColorTexture.texCoord;
  262. mat.metalness = pbr.metallicFactor;
  263. mat.roughness = pbr.roughnessFactor;
  264. mat.hasMRTex = pbr.metallicRoughnessTexture.index >= 0;
  265. mat.metalRoughTexIdx = pbr.metallicRoughnessTexture.index;
  266. mat.metalRoughTexCoords = pbr.metallicRoughnessTexture.texCoord;
  267. mat.normalScale = gltf_material.normalTexture.scale;
  268. mat.hasNormalTex = gltf_material.normalTexture.index >= 0;
  269. mat.normalTexIdx = gltf_material.normalTexture.index;
  270. mat.normalTexCoords = gltf_material.normalTexture.texCoord;
  271. mat.occlusionScale = gltf_material.occlusionTexture.strength;
  272. mat.hasOcclusionTex = gltf_material.occlusionTexture.index >= 0;
  273. mat.occlusionTexIdx = gltf_material.occlusionTexture.index;
  274. mat.occlusionTexCoords = gltf_material.occlusionTexture.texCoord;
  275. mat.emissiveColor.set(gltf_material.emissiveFactor.data());
  276. mat.hasEmissiveTex = gltf_material.emissiveTexture.index >= 0;
  277. mat.emissiveTexIdx = gltf_material.emissiveTexture.index;
  278. mat.emissiveTexCoords = gltf_material.emissiveTexture.texCoord;
  279. mat.alphaMode = gltf_material.alphaMode;
  280. mat.alphaMask = gltf_material.alphaCutoff;
  281. size_t tex_size = mTextures.size();
  282. if ((mat.hasNormalTex && mat.normalTexIdx >= tex_size) ||
  283. (mat.hasOcclusionTex && mat.occlusionTexIdx >= tex_size) ||
  284. (mat.hasEmissiveTex && mat.emissiveTexIdx >= tex_size) ||
  285. (mat.hasBaseTex && mat.baseColorTexIdx >= tex_size) ||
  286. (mat.hasMRTex && mat.metalRoughTexIdx >= tex_size))
  287. {
  288. llwarns << "Texture resource index error" << llendl;
  289. return false;
  290. }
  291. // Note: mesh can have up to 3 sets of UV
  292. if ((mat.hasNormalTex && mat.normalTexCoords > 2) ||
  293. (mat.hasOcclusionTex && mat.occlusionTexCoords > 2) ||
  294. (mat.hasEmissiveTex && mat.emissiveTexCoords > 2) ||
  295. (mat.hasBaseTex && mat.baseColorTexCoords > 2) ||
  296. (mat.hasMRTex && mat.metalRoughTexCoords > 2))
  297. {
  298. llwarns << "Image texcoord index error" << llendl;
  299. return false;
  300. }
  301. mMaterials.emplace_back(mat);
  302. }
  303. return true;
  304. }
  305. // Convert raw image buffers to texture UUIDs & assemble into a render material
  306. void LLGLTFLoader::uploadMaterials()
  307. {
  308. // Initially 1 material per gltf file, but design for multiple
  309. for (gltf_render_material mat : mMaterials)
  310. {
  311. if (mat.hasBaseTex)
  312. {
  313. gltf_texture& gtex = mTextures[mat.baseColorTexIdx];
  314. if (gtex.imageUuid.isNull())
  315. {
  316. gtex.imageUuid = imageBufferToTextureUUID(gtex);
  317. }
  318. }
  319. if (mat.hasMRTex)
  320. {
  321. gltf_texture& gtex = mTextures[mat.metalRoughTexIdx];
  322. if (gtex.imageUuid.isNull())
  323. {
  324. gtex.imageUuid = imageBufferToTextureUUID(gtex);
  325. }
  326. }
  327. if (mat.hasNormalTex)
  328. {
  329. gltf_texture& gtex = mTextures[mat.normalTexIdx];
  330. if (gtex.imageUuid.isNull())
  331. {
  332. gtex.imageUuid = imageBufferToTextureUUID(gtex);
  333. }
  334. }
  335. if (mat.hasOcclusionTex)
  336. {
  337. gltf_texture& gtex = mTextures[mat.occlusionTexIdx];
  338. if (gtex.imageUuid.isNull())
  339. {
  340. gtex.imageUuid = imageBufferToTextureUUID(gtex);
  341. }
  342. }
  343. if (mat.hasEmissiveTex)
  344. {
  345. gltf_texture& gtex = mTextures[mat.emissiveTexIdx];
  346. if (gtex.imageUuid.isNull())
  347. {
  348. gtex.imageUuid = imageBufferToTextureUUID(gtex);
  349. }
  350. }
  351. }
  352. }