Skip to content

Commit

Permalink
Fix: Add missing Asset and extensionsRequired parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
spnda committed Oct 16, 2022
1 parent dd329ee commit 0a78e2a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 71 deletions.
132 changes: 66 additions & 66 deletions src/fastgltf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,72 +150,6 @@ fg::glTF::glTF(std::unique_ptr<ParserData> data, fs::path file, size_t fileOffse
// in which the definition for ParserData is not available.
fg::glTF::~glTF() = default;

bool fg::glTF::checkAssetField() {
using namespace simdjson;

ondemand::object asset;
if (data->root["asset"].get_object().get(asset) != SUCCESS) {
errorCode = Error::InvalidOrMissingAssetField;
return false;
}

std::string_view version;
if (asset["version"].get_string().get(version) != SUCCESS) {
errorCode = Error::InvalidOrMissingAssetField;
return false;
}

return true;
}

// clang-format off
constexpr std::array<std::pair<std::string_view, fastgltf::Extensions>, 4> extensionStrings = {{
{ "KHR_texture_basisu", fastgltf::Extensions::KHR_texture_basisu },
{ "KHR_texture_transform", fastgltf::Extensions::KHR_texture_transform },
{ "MSFT_texture_dds", fastgltf::Extensions::MSFT_texture_dds },
{ "KHR_mesh_quantization", fastgltf::Extensions::KHR_mesh_quantization },
}};
// clang-format on

bool fg::glTF::checkExtensions() {
using namespace simdjson;

ondemand::array extensionsRequired;
if (data->root["extensionsRequired"].get_array().get(extensionsRequired) == SUCCESS) {
for (auto extension : extensionsRequired) {
std::string_view string;
if (extension.get_string().get(string) != SUCCESS) {
errorCode = Error::InvalidGltf;
return false;
}

// Check if the extension is known and listed in the parser.
bool known = false;
bool listed = false;
for (auto& [extensionString, extensionEnum] : extensionStrings) {
if (!known) {
known = extensionString == string;
}
if (!listed) {
listed = hasBit(extensions, extensionEnum);
}
if (known && listed)
break;
}
if (!known) {
errorCode = Error::UnsupportedExtensions;
return false;
}
if (!listed) {
errorCode = Error::MissingExtensions;
return false;
}
}
}

return true;
}

std::tuple<fg::Error, fg::DataSource, fg::DataLocation> fg::glTF::decodeUri(std::string_view uri) const {
if (uri.substr(0, 4) == "data") {
// This is a data URI.
Expand Down Expand Up @@ -502,8 +436,74 @@ fg::Error fg::glTF::validate() {
#define RETURN_SET_ERROR(error) errorCode = error; \
return;

// clang-format off
constexpr std::array<std::pair<std::string_view, fastgltf::Extensions>, 4> extensionStrings = {{
{ "KHR_texture_basisu", fastgltf::Extensions::KHR_texture_basisu },
{ "KHR_texture_transform", fastgltf::Extensions::KHR_texture_transform },
{ "MSFT_texture_dds", fastgltf::Extensions::MSFT_texture_dds },
{ "KHR_mesh_quantization", fastgltf::Extensions::KHR_mesh_quantization },
}};
// clang-format on

fg::Error fg::glTF::parse(Category categories) {
using namespace simdjson;

// We'll find the extensionsUsed, extensionsRequired, and asset objects beforehand.
ondemand::object asset;
if (!hasBit(options, Options::DontRequireValidAssetMember)) {
auto error = data->root["asset"].get_object().get(asset);
if (error == NO_SUCH_FIELD) {
errorCode = Error::InvalidOrMissingAssetField;
return errorCode;
} else if (error == SUCCESS) {
std::string_view version;
if (asset["version"].get_string().get(version) != SUCCESS) {
errorCode = Error::InvalidOrMissingAssetField;
return errorCode;
} else if (version != "2.0") {
errorCode = Error::UnsupportedVersion;
return errorCode;
}
} else {
errorCode = Error::InvalidJson;
return errorCode;
}
}

ondemand::array extensionsRequired;
if (data->root["extensionsRequired"].get_array().get(extensionsRequired) == SUCCESS) {
for (auto extension : extensionsRequired) {
std::string_view string;
if (extension.get_string().get(string) != SUCCESS) {
errorCode = Error::InvalidGltf;
return errorCode;
}

// Check if the extension is known and listed in the parser.
bool known = false;
bool listed = false;
for (auto& [extensionString, extensionEnum] : extensionStrings) {
if (!known) {
known = extensionString == string;
}
if (!listed) {
listed = hasBit(extensions, extensionEnum);
}
if (known && listed)
break;
}
if (!known) {
errorCode = Error::UnsupportedExtensions;
return errorCode;
}
if (!listed) {
errorCode = Error::MissingExtensions;
return errorCode;
}
}
}
data->root.reset();

Category readCategories = Category::None;
for (auto object : data->root) {
if (object.error() != SUCCESS) {
Expand Down
6 changes: 4 additions & 2 deletions src/fastgltf_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ namespace fastgltf {
enum class Error : uint64_t {
None = 0,
InvalidPath = 1,
// One or more extensions were not marked as supported by the client application but are
// required by the glTF.
MissingExtensions = 2,
// A required extensions is not supported by fastgltf.
UnsupportedExtensions = 3,
InvalidJson = 4,
InvalidGltf = 5,
InvalidOrMissingAssetField = 6,
InvalidGLB = 6,
MissingField = 7,
UnsupportedVersion = 8,
};

// clang-format off
Expand Down Expand Up @@ -154,8 +158,6 @@ namespace fastgltf {

static auto getMimeTypeFromString(std::string_view mime) -> MimeType;

[[nodiscard]] bool checkAssetField();
[[nodiscard]] bool checkExtensions();
[[nodiscard]] auto decodeUri(std::string_view uri) const -> std::tuple<Error, DataSource, DataLocation>;
[[gnu::always_inline]] inline Error parseTextureObject(void* object, std::string_view key, TextureInfo* info) noexcept;

Expand Down
8 changes: 5 additions & 3 deletions tests/basic_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ TEST_CASE("Loading some basic glTF", "[gltf-loader]") {
SECTION("Loading basic invalid glTF files") {
auto jsonData = std::make_unique<fastgltf::JsonData>(path / "empty_json.gltf");
auto emptyGltf = parser.loadGLTF(jsonData.get(), path);
REQUIRE(emptyGltf == nullptr);
REQUIRE(parser.getError() == fastgltf::Error::InvalidOrMissingAssetField);
REQUIRE(parser.getError() == fastgltf::Error::None);
REQUIRE(emptyGltf->parse() == fastgltf::Error::InvalidOrMissingAssetField);
REQUIRE(emptyGltf->getParsedAssetPointer() == nullptr);
}

SECTION("Load basic glTF file") {
Expand Down Expand Up @@ -164,7 +165,8 @@ TEST_CASE("Loading KHR_texture_basisu glTF files", "[gltf-loader]") {
// We specify no extensions, yet the StainedGlassLamp requires KHR_texture_basisu.
fastgltf::Parser parser(fastgltf::Extensions::None);
auto stainedGlassLamp = parser.loadGLTF(jsonData.get(), path, fastgltf::Options::DontRequireValidAssetMember);
REQUIRE(parser.getError() == fastgltf::Error::MissingExtensions);
REQUIRE(parser.getError() == fastgltf::Error::None);
REQUIRE(stainedGlassLamp->parse() == fastgltf::Error::MissingExtensions);
}
};

Expand Down

0 comments on commit 0a78e2a

Please sign in to comment.