diff --git a/tiny_gltf.h b/tiny_gltf.h index 3e807cc..d6ea042 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -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( + std::numeric_limits::max())) { + supposedComponentType = TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE; + } else if ( + numPoint < static_cast( + std::numeric_limits::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; }