extension_tests.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #include <catch2/catch_approx.hpp>
  2. #include <catch2/catch_test_macros.hpp>
  3. #include <catch2/benchmark/catch_benchmark.hpp>
  4. #include <glm/gtc/epsilon.hpp>
  5. #include <glm/gtc/type_ptr.hpp>
  6. #include <fastgltf/parser.hpp>
  7. #include "gltf_path.hpp"
  8. TEST_CASE("Loading KHR_texture_basisu glTF files", "[gltf-loader]") {
  9. auto stainedLamp = sampleModels / "2.0" / "StainedGlassLamp" / "glTF-KTX-BasisU";
  10. auto jsonData = std::make_unique<fastgltf::GltfDataBuffer>();
  11. REQUIRE(jsonData->loadFromFile(stainedLamp / "StainedGlassLamp.gltf"));
  12. SECTION("Loading KHR_texture_basisu") {
  13. fastgltf::Parser parser(fastgltf::Extensions::KHR_texture_basisu);
  14. auto asset = parser.loadGLTF(jsonData.get(), path, fastgltf::Options::DontRequireValidAssetMember,
  15. fastgltf::Category::Textures | fastgltf::Category::Images);
  16. REQUIRE(asset.error() == fastgltf::Error::None);
  17. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  18. REQUIRE(asset->textures.size() == 19);
  19. REQUIRE(!asset->images.empty());
  20. auto& texture = asset->textures[1];
  21. REQUIRE(texture.imageIndex == 1);
  22. REQUIRE(texture.samplerIndex == 0);
  23. REQUIRE(!texture.fallbackImageIndex.has_value());
  24. auto& image = asset->images.front();
  25. auto* filePath = std::get_if<fastgltf::sources::URI>(&image.data);
  26. REQUIRE(filePath != nullptr);
  27. REQUIRE(filePath->uri.valid());
  28. REQUIRE(filePath->uri.isLocalPath());
  29. REQUIRE(filePath->mimeType == fastgltf::MimeType::KTX2);
  30. }
  31. SECTION("Testing requiredExtensions") {
  32. // We specify no extensions, yet the StainedGlassLamp requires KHR_texture_basisu.
  33. fastgltf::Parser parser(fastgltf::Extensions::None);
  34. auto stainedGlassLamp = parser.loadGLTF(jsonData.get(), path, fastgltf::Options::DontRequireValidAssetMember);
  35. REQUIRE(stainedGlassLamp.error() == fastgltf::Error::MissingExtensions);
  36. }
  37. }
  38. TEST_CASE("Loading KHR_texture_transform glTF files", "[gltf-loader]") {
  39. auto transformTest = sampleModels / "2.0" / "TextureTransformMultiTest" / "glTF";
  40. auto jsonData = std::make_unique<fastgltf::GltfDataBuffer>();
  41. REQUIRE(jsonData->loadFromFile(transformTest / "TextureTransformMultiTest.gltf"));
  42. fastgltf::Parser parser(fastgltf::Extensions::KHR_texture_transform);
  43. auto asset = parser.loadGLTF(jsonData.get(), transformTest, fastgltf::Options::DontRequireValidAssetMember, fastgltf::Category::Materials);
  44. REQUIRE(asset.error() == fastgltf::Error::None);
  45. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  46. REQUIRE(!asset->materials.empty());
  47. auto& material = asset->materials.front();
  48. REQUIRE(material.pbrData.baseColorTexture.has_value());
  49. REQUIRE(material.pbrData.baseColorTexture->transform != nullptr);
  50. REQUIRE(material.pbrData.baseColorTexture->transform->uvOffset[0] == 0.705f);
  51. REQUIRE(material.pbrData.baseColorTexture->transform->rotation == Catch::Approx(1.5707963705062866f));
  52. }
  53. TEST_CASE("Test KHR_lights_punctual", "[gltf-loader]") {
  54. auto lightsLamp = sampleModels / "2.0" / "LightsPunctualLamp" / "glTF";
  55. fastgltf::GltfDataBuffer jsonData;
  56. REQUIRE(jsonData.loadFromFile(lightsLamp / "LightsPunctualLamp.gltf"));
  57. fastgltf::Parser parser(fastgltf::Extensions::KHR_lights_punctual);
  58. auto asset = parser.loadGLTF(&jsonData, lightsLamp, fastgltf::Options::None, fastgltf::Category::Nodes);
  59. REQUIRE(asset.error() == fastgltf::Error::None);
  60. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  61. REQUIRE(asset->lights.size() == 5);
  62. REQUIRE(asset->nodes.size() > 4);
  63. auto& nodes = asset->nodes;
  64. REQUIRE(nodes[3].lightIndex.has_value());
  65. REQUIRE(nodes[3].lightIndex.value() == 0);
  66. auto& lights = asset->lights;
  67. REQUIRE(lights[0].name == "Point");
  68. REQUIRE(lights[0].type == fastgltf::LightType::Point);
  69. REQUIRE(lights[0].intensity == 15.0f);
  70. REQUIRE(glm::epsilonEqual(lights[0].color[0], 1.0f, glm::epsilon<float>()));
  71. REQUIRE(glm::epsilonEqual(lights[0].color[1], 0.63187497854232788f, glm::epsilon<float>()));
  72. REQUIRE(glm::epsilonEqual(lights[0].color[2], 0.23909975588321689f, glm::epsilon<float>()));
  73. }
  74. TEST_CASE("Test KHR_materials_specular", "[gltf-loader]") {
  75. auto specularTest = sampleModels / "2.0" / "SpecularTest" / "glTF";
  76. fastgltf::GltfDataBuffer jsonData;
  77. REQUIRE(jsonData.loadFromFile(specularTest / "SpecularTest.gltf"));
  78. fastgltf::Parser parser(fastgltf::Extensions::KHR_materials_specular);
  79. auto asset = parser.loadGLTF(&jsonData, specularTest, fastgltf::Options::None, fastgltf::Category::Materials);
  80. REQUIRE(asset.error() == fastgltf::Error::None);
  81. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  82. REQUIRE(asset->materials.size() >= 12);
  83. auto& materials = asset->materials;
  84. REQUIRE(materials[1].specular != nullptr);
  85. REQUIRE(materials[1].specular->specularFactor == 0.0f);
  86. REQUIRE(materials[2].specular != nullptr);
  87. REQUIRE(glm::epsilonEqual(materials[2].specular->specularFactor, 0.051269f, glm::epsilon<float>()));
  88. REQUIRE(materials[8].specular != nullptr);
  89. REQUIRE(glm::epsilonEqual(materials[8].specular->specularColorFactor[0], 0.051269f, glm::epsilon<float>()));
  90. REQUIRE(glm::epsilonEqual(materials[8].specular->specularColorFactor[1], 0.051269f, glm::epsilon<float>()));
  91. REQUIRE(glm::epsilonEqual(materials[8].specular->specularColorFactor[2], 0.051269f, glm::epsilon<float>()));
  92. REQUIRE(materials[12].specular != nullptr);
  93. REQUIRE(materials[12].specular->specularColorTexture.has_value());
  94. REQUIRE(materials[12].specular->specularColorTexture.value().textureIndex == 2);
  95. }
  96. TEST_CASE("Test KHR_materials_ior and KHR_materials_iridescence", "[gltf-loader]") {
  97. auto specularTest = sampleModels / "2.0" / "IridescenceDielectricSpheres" / "glTF";
  98. fastgltf::GltfDataBuffer jsonData;
  99. REQUIRE(jsonData.loadFromFile(specularTest / "IridescenceDielectricSpheres.gltf"));
  100. fastgltf::Parser parser(fastgltf::Extensions::KHR_materials_iridescence | fastgltf::Extensions::KHR_materials_ior);
  101. auto asset = parser.loadGLTF(&jsonData, specularTest, fastgltf::Options::None, fastgltf::Category::Materials);
  102. REQUIRE(asset.error() == fastgltf::Error::None);
  103. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  104. REQUIRE(asset->materials.size() >= 50);
  105. auto& materials = asset->materials;
  106. REQUIRE(materials[0].iridescence != nullptr);
  107. REQUIRE(materials[0].iridescence->iridescenceFactor == 1.0f);
  108. REQUIRE(materials[0].iridescence->iridescenceIor == 1.0f);
  109. REQUIRE(materials[0].iridescence->iridescenceThicknessMaximum == 100.0f);
  110. REQUIRE(materials[0].ior.has_value());
  111. REQUIRE(materials[0].ior.value() == 1.0f);
  112. REQUIRE(materials[7].ior.has_value());
  113. REQUIRE(materials[7].ior.value() == 1.17f);
  114. REQUIRE(materials[50].iridescence != nullptr);
  115. REQUIRE(materials[50].iridescence->iridescenceFactor == 1.0f);
  116. REQUIRE(materials[50].iridescence->iridescenceIor == 1.17f);
  117. REQUIRE(materials[50].iridescence->iridescenceThicknessMaximum == 200.0f);
  118. }
  119. TEST_CASE("Test KHR_materials_volume and KHR_materials_transmission", "[gltf-loader]") {
  120. auto beautifulGame = sampleModels / "2.0" / "ABeautifulGame" / "glTF";
  121. fastgltf::GltfDataBuffer jsonData;
  122. REQUIRE(jsonData.loadFromFile(beautifulGame / "ABeautifulGame.gltf"));
  123. fastgltf::Parser parser(fastgltf::Extensions::KHR_materials_volume | fastgltf::Extensions::KHR_materials_transmission);
  124. auto asset = parser.loadGLTF(&jsonData, beautifulGame, fastgltf::Options::None, fastgltf::Category::Materials);
  125. REQUIRE(asset.error() == fastgltf::Error::None);
  126. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  127. REQUIRE(asset->materials.size() >= 5);
  128. auto& materials = asset->materials;
  129. REQUIRE(materials[5].volume != nullptr);
  130. REQUIRE(glm::epsilonEqual(materials[5].volume->thicknessFactor, 0.2199999988079071f, glm::epsilon<float>()));
  131. REQUIRE(glm::epsilonEqual(materials[5].volume->attenuationColor[0], 0.800000011920929f, glm::epsilon<float>()));
  132. REQUIRE(glm::epsilonEqual(materials[5].volume->attenuationColor[1], 0.800000011920929f, glm::epsilon<float>()));
  133. REQUIRE(glm::epsilonEqual(materials[5].volume->attenuationColor[2], 0.800000011920929f, glm::epsilon<float>()));
  134. REQUIRE(materials[5].transmission != nullptr);
  135. REQUIRE(materials[5].transmission->transmissionFactor == 1.0f);
  136. }
  137. TEST_CASE("Test KHR_materials_clearcoat", "[gltf-loader]") {
  138. auto clearcoatTest = sampleModels / "2.0" / "ClearCoatTest" / "glTF";
  139. fastgltf::GltfDataBuffer jsonData;
  140. REQUIRE(jsonData.loadFromFile(clearcoatTest / "ClearCoatTest.gltf"));
  141. fastgltf::Parser parser(fastgltf::Extensions::KHR_materials_clearcoat);
  142. auto asset = parser.loadGLTF(&jsonData, clearcoatTest, fastgltf::Options::None, fastgltf::Category::Materials);
  143. REQUIRE(asset.error() == fastgltf::Error::None);
  144. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  145. REQUIRE(asset->materials.size() >= 7);
  146. auto& materials = asset->materials;
  147. REQUIRE(materials[1].clearcoat != nullptr);
  148. REQUIRE(materials[1].clearcoat->clearcoatFactor == 1.0f);
  149. REQUIRE(materials[1].clearcoat->clearcoatRoughnessFactor == 0.03f);
  150. REQUIRE(materials[7].clearcoat != nullptr);
  151. REQUIRE(materials[7].clearcoat->clearcoatFactor == 1.0f);
  152. REQUIRE(materials[7].clearcoat->clearcoatRoughnessFactor == 1.0f);
  153. REQUIRE(materials[7].clearcoat->clearcoatRoughnessTexture.has_value());
  154. REQUIRE(materials[7].clearcoat->clearcoatRoughnessTexture->textureIndex == 2);
  155. REQUIRE(materials[7].clearcoat->clearcoatRoughnessTexture->texCoordIndex == 0);
  156. }
  157. TEST_CASE("Test EXT_mesh_gpu_instancing", "[gltf-loader]") {
  158. auto simpleInstancingTest = sampleModels / "2.0" / "SimpleInstancing" / "glTF";
  159. fastgltf::GltfDataBuffer jsonData;
  160. REQUIRE(jsonData.loadFromFile(simpleInstancingTest / "SimpleInstancing.gltf"));
  161. fastgltf::Parser parser(fastgltf::Extensions::EXT_mesh_gpu_instancing);
  162. auto asset = parser.loadGLTF(&jsonData, simpleInstancingTest, fastgltf::Options::None, fastgltf::Category::Accessors | fastgltf::Category::Nodes);
  163. REQUIRE(asset.error() == fastgltf::Error::None);
  164. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  165. REQUIRE(asset->accessors.size() >= 6);
  166. REQUIRE(asset->nodes.size() >= 1);
  167. auto& nodes = asset->nodes;
  168. REQUIRE(nodes[0].instancingAttributes.size() == 3u);
  169. REQUIRE(nodes[0].findInstancingAttribute("TRANSLATION") != nodes[0].instancingAttributes.cend());
  170. REQUIRE(nodes[0].findInstancingAttribute("SCALE") != nodes[0].instancingAttributes.cend());
  171. REQUIRE(nodes[0].findInstancingAttribute("ROTATION") != nodes[0].instancingAttributes.cend());
  172. }
  173. #if FASTGLTF_ENABLE_DEPRECATED_EXT
  174. TEST_CASE("Test KHR_materials_pbrSpecularGlossiness", "[gltf-loader]") {
  175. auto specularGlossinessTest = sampleModels / "2.0" / "SpecGlossVsMetalRough" / "glTF";
  176. fastgltf::GltfDataBuffer jsonData;
  177. REQUIRE(jsonData.loadFromFile(specularGlossinessTest / "SpecGlossVsMetalRough.gltf"));
  178. fastgltf::Parser parser(fastgltf::Extensions::KHR_materials_pbrSpecularGlossiness | fastgltf::Extensions::KHR_materials_specular);
  179. auto asset = parser.loadGLTF(&jsonData, specularGlossinessTest);
  180. REQUIRE(asset.error() == fastgltf::Error::None);
  181. REQUIRE(fastgltf::validate(asset.get()) == fastgltf::Error::None);
  182. REQUIRE(asset->materials.size() == 4);
  183. auto& materials = asset->materials;
  184. REQUIRE(materials[0].specularGlossiness != nullptr);
  185. REQUIRE(materials[0].specularGlossiness->diffuseFactor[0] == 1.0f);
  186. REQUIRE(materials[0].specularGlossiness->diffuseFactor[1] == 1.0f);
  187. REQUIRE(materials[0].specularGlossiness->diffuseFactor[2] == 1.0f);
  188. REQUIRE(materials[0].specularGlossiness->diffuseFactor[3] == 1.0f);
  189. REQUIRE(materials[0].specularGlossiness->specularFactor[0] == 1.0f);
  190. REQUIRE(materials[0].specularGlossiness->specularFactor[1] == 1.0f);
  191. REQUIRE(materials[0].specularGlossiness->specularFactor[2] == 1.0f);
  192. REQUIRE(materials[0].specularGlossiness->glossinessFactor == 1.0f);
  193. REQUIRE(materials[0].specularGlossiness->diffuseTexture.has_value());
  194. REQUIRE(materials[0].specularGlossiness->diffuseTexture.value().textureIndex == 5);
  195. REQUIRE(materials[0].specularGlossiness->specularGlossinessTexture.has_value());
  196. REQUIRE(materials[0].specularGlossiness->specularGlossinessTexture.value().textureIndex == 6);
  197. REQUIRE(materials[3].specularGlossiness != nullptr);
  198. REQUIRE(materials[3].specularGlossiness->diffuseFactor[0] == 1.0f);
  199. REQUIRE(materials[3].specularGlossiness->diffuseFactor[1] == 1.0f);
  200. REQUIRE(materials[3].specularGlossiness->diffuseFactor[2] == 1.0f);
  201. REQUIRE(materials[3].specularGlossiness->diffuseFactor[3] == 1.0f);
  202. REQUIRE(materials[3].specularGlossiness->specularFactor[0] == 0.0f);
  203. REQUIRE(materials[3].specularGlossiness->specularFactor[1] == 0.0f);
  204. REQUIRE(materials[3].specularGlossiness->specularFactor[2] == 0.0f);
  205. REQUIRE(materials[3].specularGlossiness->glossinessFactor == 0.0f);
  206. REQUIRE(materials[3].specularGlossiness->diffuseTexture.has_value());
  207. REQUIRE(materials[3].specularGlossiness->diffuseTexture.value().textureIndex == 7);
  208. }
  209. #endif