Merge pull request #447 from nyalldawson/draco_fix

Handle the situation where the recorded component type does not match the required type for the actual number of stored points
This commit is contained in:
Syoyo Fujita 2023-09-03 02:17:12 +09:00 committed by GitHub
commit 51530ee500
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4873,8 +4873,9 @@ static bool GetAttributeForAllPoints(uint32_t componentType, draco::Mesh *mesh,
}
static bool ParseDracoExtension(Primitive *primitive, Model *model,
std::string *err,
const Value &dracoExtensionValue) {
std::string *err, std::string *warn,
const Value &dracoExtensionValue,
ParseStrictness strictness) {
(void)err;
auto bufferViewValue = dracoExtensionValue.Get("bufferView");
if (!bufferViewValue.IsInt()) return false;
@ -4906,6 +4907,33 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
// create new bufferView for indices
if (primitive->indices >= 0) {
if (strictness == ParseStrictness::PERMISSIVE) {
const draco::PointIndex::ValueType numPoint = mesh->num_points();
// handle the situation where the stored component type does not match the
// required type for the actual number of stored points
int supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
if (numPoint < static_cast<draco::PointIndex::ValueType>(
std::numeric_limits<uint8_t>::max())) {
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE;
} else if (
numPoint < static_cast<draco::PointIndex::ValueType>(
std::numeric_limits<uint16_t>::max())) {
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT;
} else {
supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT;
}
if (supposedComponentType > model->accessors[primitive->indices].componentType) {
model->accessors[primitive->indices].componentType = supposedComponentType;
if (warn) {
(*warn) +=
"GLTF component type " + std::to_string(model->accessors[primitive->indices].componentType) +
" is not sufficient for number of stored points,"
" treating as " + std::to_string(supposedComponentType) + "\n";
}
}
}
int32_t componentSize = GetComponentSizeInBytes(
model->accessors[primitive->indices].componentType);
Buffer decodedIndexBuffer;
@ -4971,9 +4999,11 @@ static bool ParseDracoExtension(Primitive *primitive, Model *model,
}
#endif
static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
static bool ParsePrimitive(Primitive *primitive, Model *model,
std::string *err, std::string *warn,
const detail::json &o,
bool store_original_json_for_extras_and_extensions) {
bool store_original_json_for_extras_and_extensions,
ParseStrictness strictness) {
int material = -1;
ParseIntegerProperty(&material, err, o, "material", false);
primitive->material = material;
@ -5022,18 +5052,21 @@ static bool ParsePrimitive(Primitive *primitive, Model *model, std::string *err,
auto dracoExtension =
primitive->extensions.find("KHR_draco_mesh_compression");
if (dracoExtension != primitive->extensions.end()) {
ParseDracoExtension(primitive, model, err, dracoExtension->second);
ParseDracoExtension(primitive, model, err, warn, dracoExtension->second, strictness);
}
#else
(void)model;
(void)warn;
#endif
return true;
}
static bool ParseMesh(Mesh *mesh, Model *model, std::string *err,
static bool ParseMesh(Mesh *mesh, Model *model,
std::string *err, std::string *warn,
const detail::json &o,
bool store_original_json_for_extras_and_extensions) {
bool store_original_json_for_extras_and_extensions,
ParseStrictness strictness) {
ParseStringProperty(&mesh->name, err, o, "name", false);
mesh->primitives.clear();
@ -5046,8 +5079,9 @@ static bool ParseMesh(Mesh *mesh, Model *model, std::string *err,
detail::ArrayBegin(detail::GetValue(primObject));
i != primEnd; ++i) {
Primitive primitive;
if (ParsePrimitive(&primitive, model, err, *i,
store_original_json_for_extras_and_extensions)) {
if (ParsePrimitive(&primitive, model, err, warn, *i,
store_original_json_for_extras_and_extensions,
strictness)) {
// Only add the primitive if the parsing succeeds.
mesh->primitives.emplace_back(std::move(primitive));
}
@ -6078,8 +6112,9 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
return false;
}
Mesh mesh;
if (!ParseMesh(&mesh, model, err, o,
store_original_json_for_extras_and_extensions_)) {
if (!ParseMesh(&mesh, model, err, warn, o,
store_original_json_for_extras_and_extensions_,
strictness_)) {
return false;
}