diff options
Diffstat (limited to 'src/3rdparty/assimp/code/glTFAsset.inl')
-rw-r--r-- | src/3rdparty/assimp/code/glTFAsset.inl | 466 |
1 files changed, 421 insertions, 45 deletions
diff --git a/src/3rdparty/assimp/code/glTFAsset.inl b/src/3rdparty/assimp/code/glTFAsset.inl index d52c825c4..a5d74f5a0 100644 --- a/src/3rdparty/assimp/code/glTFAsset.inl +++ b/src/3rdparty/assimp/code/glTFAsset.inl @@ -1,8 +1,9 @@ -/* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -39,11 +40,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "StringUtils.h" +#include <iomanip> + +// Header files, Assimp +#include <assimp/DefaultLogger.hpp> + +#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC + // Header files, Open3DGC. +# include <Open3DGC/o3dgcSC3DMCDecoder.h> +#endif + +using namespace Assimp; namespace glTF { namespace { - + // // JSON Value reading helpers // @@ -52,7 +64,7 @@ namespace { struct ReadHelper { static bool Read(Value& val, T& out) { return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false; }}; - + template<> struct ReadHelper<bool> { static bool Read(Value& val, bool& out) { return val.IsBool() ? out = val.GetBool(), true : false; }}; @@ -60,7 +72,7 @@ namespace { template<> struct ReadHelper<float> { static bool Read(Value& val, float& out) { return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false; }}; - + template<unsigned int N> struct ReadHelper<float[N]> { static bool Read(Value& val, float (&out)[N]) { if (!val.IsArray() || val.Size() != N) return false; for (unsigned int i = 0; i < N; ++i) { @@ -117,6 +129,12 @@ namespace { return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; } + inline Value* FindNumber(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0; + } + inline Value* FindArray(Value& val, const char* id) { Value::MemberIterator it = val.FindMember(id); @@ -241,9 +259,14 @@ Ref<T> LazyDict<T>::Create(const char* id) inline Buffer::Buffer() -: byteLength(0), type(Type_arraybuffer), mIsSpecial(false) + : byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) { } +inline Buffer::~Buffer() +{ + for(SEncodedRegion* reg : EncodedRegion_List) delete reg; +} + inline const char* Buffer::TranslateId(Asset& r, const char* id) { // Compatibility with old spec @@ -277,14 +300,14 @@ inline void Buffer::Read(Value& obj, Asset& r) this->mData.reset(data); if (statedLength > 0 && this->byteLength != statedLength) { - throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + std::to_string(statedLength) + - " bytes, but found " + std::to_string(dataURI.dataLength)); + throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + + " bytes, but found " + to_string(dataURI.dataLength)); } } else { // assume raw data if (statedLength != dataURI.dataLength) { - throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + std::to_string(statedLength) + - " bytes, but found " + std::to_string(dataURI.dataLength)); + throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + + " bytes, but found " + to_string(dataURI.dataLength)); } this->mData.reset(new uint8_t[dataURI.dataLength]); @@ -293,11 +316,13 @@ inline void Buffer::Read(Value& obj, Asset& r) } else { // Local file if (byteLength > 0) { - IOStream* file = r.OpenFile(uri, "rb"); + std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : ""; + + IOStream* file = r.OpenFile(dir + uri, "rb"); if (file) { bool ok = LoadFromStream(*file, byteLength); delete file; - + if (!ok) throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" ); } @@ -316,7 +341,7 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO stream.Seek(baseOffset, aiOrigin_SET); } - mData.reset(new uint8_t[byteLength]); + mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>()); if (stream.Read(mData.get(), byteLength, 1) != 1) { return false; @@ -324,6 +349,79 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO return true; } +inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID) +{ + // Check pointer to data + if(pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided."); + + // Check offset + if(pOffset > byteLength) + { + const uint8_t val_size = 32; + + char val[val_size]; + + ai_snprintf(val, val_size, "%llu", (long long)pOffset); + throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region."); + } + + // Check length + if((pOffset + pEncodedData_Length) > byteLength) + { + const uint8_t val_size = 64; + + char val[val_size]; + + ai_snprintf(val, val_size, "%llu, %llu", (long long)pOffset, (long long)pEncodedData_Length); + throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range."); + } + + // Add new region + EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID)); + // And set new value for "byteLength" + byteLength += (pDecodedData_Length - pEncodedData_Length); +} + +inline void Buffer::EncodedRegion_SetCurrent(const std::string& pID) +{ + if((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return; + + for(SEncodedRegion* reg : EncodedRegion_List) + { + if(reg->ID == pID) + { + EncodedRegion_Current = reg; + + return; + } + + } + + throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found."); +} + +inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) +{ +const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + +uint8_t* new_data; + + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; + + new_data = new uint8_t[new_data_size]; + // Copy data which place before replacing part. + memcpy(new_data, mData.get(), pBufferData_Offset); + // Copy new data. + memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); + // Copy data which place after replacing part. + memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); + // Apply new data + mData.reset(new_data); + byteLength = new_data_size; + + return true; +} + inline size_t Buffer::AppendData(uint8_t* data, size_t length) { size_t offset = this->byteLength; @@ -341,6 +439,9 @@ inline void Buffer::Grow(size_t amount) byteLength += amount; } +// +// struct BufferView +// inline void BufferView::Read(Value& obj, Asset& r) { @@ -348,12 +449,14 @@ inline void BufferView::Read(Value& obj, Asset& r) if (bufferId) { buffer = r.buffers.Get(bufferId); } - + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); byteLength = MemberOrDefault(obj, "byteLength", 0u); } - +// +// struct Accessor +// inline void Accessor::Read(Value& obj, Asset& r) { @@ -393,7 +496,18 @@ inline uint8_t* Accessor::GetPointer() if (!basePtr) return 0; size_t offset = byteOffset + bufferView->byteOffset; - return basePtr + offset; + + // Check if region is encoded. + if(bufferView->buffer->EncodedRegion_Current != nullptr) + { + const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset; + const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length; + + if((offset >= begin) && (offset < end)) + return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; } namespace { @@ -495,7 +609,7 @@ inline Image::Image() inline void Image::Read(Value& obj, Asset& r) { - // Check for extensions first (to detect binary embedded data) + // Check for extensions first (to detect binary embedded data) if (Value* extensions = FindObject(obj, "extensions")) { if (r.extensionsUsed.KHR_binary_glTF) { if (Value* ext = FindObject(*extensions, "KHR_binary_glTF")) { @@ -561,12 +675,35 @@ inline void Image::SetData(uint8_t* data, size_t length, Asset& r) } } +inline void Sampler::Read(Value& obj, Asset& /*r*/) +{ + SetDefaults(); + + ReadMember(obj, "magFilter", magFilter); + ReadMember(obj, "minFilter", minFilter); + ReadMember(obj, "wrapS", wrapS); + ReadMember(obj, "wrapT", wrapT); +} + +inline void Sampler::SetDefaults() +{ + magFilter = SamplerMagFilter_Linear; + minFilter = SamplerMinFilter_Linear; + wrapS = SamplerWrap_Repeat; + wrapT = SamplerWrap_Repeat; +} + inline void Texture::Read(Value& obj, Asset& r) { const char* sourcestr; if (ReadMember(obj, "source", sourcestr)) { source = r.images.Get(sourcestr); } + + const char* samplerstr; + if (ReadMember(obj, "sampler", samplerstr)) { + sampler = r.samplers.Get(samplerstr); + } } namespace { @@ -592,6 +729,7 @@ inline void Material::Read(Value& material, Asset& r) ReadMaterialProperty(r, *values, "diffuse", this->diffuse); ReadMaterialProperty(r, *values, "specular", this->specular); + ReadMember(*values, "transparency", transparency); ReadMember(*values, "shininess", shininess); } @@ -676,9 +814,10 @@ namespace { } } -inline void Mesh::Read(Value& obj, Asset& r) -{ - if (Value* primitives = FindArray(obj, "primitives")) { +inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) +{ + /****************** Mesh primitives ******************/ + if (Value* primitives = FindArray(pJSON_Object, "primitives")) { this->primitives.resize(primitives->Size()); for (unsigned int i = 0; i < primitives->Size(); ++i) { Value& primitive = (*primitives)[i]; @@ -698,24 +837,263 @@ inline void Mesh::Read(Value& obj, Asset& r) if (GetAttribVector(prim, attr, vec, undPos)) { size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; if ((*vec).size() <= idx) (*vec).resize(idx + 1); - (*vec)[idx] = r.accessors.Get(it->value.GetString()); + (*vec)[idx] = pAsset_Root.accessors.Get(it->value.GetString()); } } } if (Value* indices = FindString(primitive, "indices")) { - prim.indices = r.accessors.Get(indices->GetString()); + prim.indices = pAsset_Root.accessors.Get(indices->GetString()); } if (Value* material = FindString(primitive, "material")) { - prim.material = r.materials.Get(material->GetString()); + prim.material = pAsset_Root.materials.Get(material->GetString()); } } } + + /****************** Mesh extensions ******************/ + Value* json_extensions = FindObject(pJSON_Object, "extensions"); + + if(json_extensions == nullptr) goto mr_skip_extensions; + + for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); it_memb++) + { +#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC + if(it_memb->name.GetString() == std::string("Open3DGC-compression")) + { + // Search for compressed data. + // Compressed data contain description of part of "buffer" which is encoded. This part must be decoded and + // new data will replace old encoded part by request. In fact \"compressedData\" is kind of "accessor" structure. + Value* comp_data = FindObject(it_memb->value, "compressedData"); + + if(comp_data == nullptr) throw DeadlyImportError("GLTF: \"Open3DGC-compression\" must has \"compressedData\"."); + + DefaultLogger::get()->info("GLTF: Decompressing Open3DGC data."); + + /************** Read data from JSON-document **************/ + #define MESH_READ_COMPRESSEDDATA_MEMBER(pFieldName, pOut) \ + if(!ReadMember(*comp_data, pFieldName, pOut)) \ + { \ + throw DeadlyImportError(std::string("GLTF: \"compressedData\" must has \"") + pFieldName + "\"."); \ + } + + const char* mode_str; + const char* type_str; + ComponentType component_type; + SCompression_Open3DGC* ext_o3dgc = new SCompression_Open3DGC; + + MESH_READ_COMPRESSEDDATA_MEMBER("buffer", ext_o3dgc->Buffer); + MESH_READ_COMPRESSEDDATA_MEMBER("byteOffset", ext_o3dgc->Offset); + MESH_READ_COMPRESSEDDATA_MEMBER("componentType", component_type); + MESH_READ_COMPRESSEDDATA_MEMBER("type", type_str); + MESH_READ_COMPRESSEDDATA_MEMBER("count", ext_o3dgc->Count); + MESH_READ_COMPRESSEDDATA_MEMBER("mode", mode_str); + MESH_READ_COMPRESSEDDATA_MEMBER("indicesCount", ext_o3dgc->IndicesCount); + MESH_READ_COMPRESSEDDATA_MEMBER("verticesCount", ext_o3dgc->VerticesCount); + + #undef MESH_READ_COMPRESSEDDATA_MEMBER + + // Check some values + if(strcmp(type_str, "SCALAR")) throw DeadlyImportError("GLTF: only \"SCALAR\" type is supported for compressed data."); + if(component_type != ComponentType_UNSIGNED_BYTE) throw DeadlyImportError("GLTF: only \"UNSIGNED_BYTE\" component type is supported for compressed data."); + + // Set read/write data mode. + if(strcmp(mode_str, "binary") == 0) + ext_o3dgc->Binary = true; + else if(strcmp(mode_str, "ascii") == 0) + ext_o3dgc->Binary = false; + else + throw DeadlyImportError(std::string("GLTF: for compressed data supported modes is: \"ascii\", \"binary\". Not the: \"") + mode_str + "\"."); + + /************************ Decoding ************************/ + Decode_O3DGC(*ext_o3dgc, pAsset_Root); + Extension.push_back(ext_o3dgc);// store info in mesh extensions list. + }// if(it_memb->name.GetString() == "Open3DGC-compression") + else +#endif + { + throw DeadlyImportError(std::string("GLTF: Unknown mesh extension: \"") + it_memb->name.GetString() + "\"."); + } + }// for(Value::MemberIterator it_memb = json_extensions->MemberBegin(); it_memb != json_extensions->MemberEnd(); json_extensions++) + +mr_skip_extensions: + + return;// After label some operators must be present. } +#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC +inline void Mesh::Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root) +{ +typedef unsigned short IndicesType;///< \sa glTFExporter::ExportMeshes. + +o3dgc::SC3DMCDecoder<IndicesType> decoder; +o3dgc::IndexedFaceSet<IndicesType> ifs; +o3dgc::BinaryStream bstream; +uint8_t* decoded_data; +size_t decoded_data_size = 0; +Ref<Buffer> buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); + + // Read data from buffer and place it in BinaryStream for decoder. + // Just "Count" because always is used type equivalent to uint8_t. + bstream.LoadFromBuffer(&buf->GetPointer()[pCompression_Open3DGC.Offset], static_cast<unsigned long>(pCompression_Open3DGC.Count)); + + // After decoding header we can get size of primitives. + if(decoder.DecodeHeader(ifs, bstream) != o3dgc::O3DGC_OK) throw DeadlyImportError("GLTF: can not decode Open3DGC header."); + + /****************** Get sizes of arrays and check sizes ******************/ + // Note. See "Limitations for meshes when using Open3DGC-compression". + + // Indices + size_t size_coordindex = ifs.GetNCoordIndex() * 3;// See float attributes note. + + if(primitives[0].indices->count != size_coordindex) + throw DeadlyImportError("GLTF: Open3DGC. Compressed indices count (" + std::to_string(size_coordindex) + + ") not equal to uncompressed (" + std::to_string(primitives[0].indices->count) + ")."); + + size_coordindex *= sizeof(IndicesType); + // Coordinates + size_t size_coord = ifs.GetNCoord();// See float attributes note. + + if(primitives[0].attributes.position[0]->count != size_coord) + throw DeadlyImportError("GLTF: Open3DGC. Compressed positions count (" + std::to_string(size_coord) + + ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.position[0]->count) + ")."); + + size_coord *= 3 * sizeof(float); + // Normals + size_t size_normal = ifs.GetNNormal();// See float attributes note. + + if(primitives[0].attributes.normal[0]->count != size_normal) + throw DeadlyImportError("GLTF: Open3DGC. Compressed normals count (" + std::to_string(size_normal) + + ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.normal[0]->count) + ")."); + + size_normal *= 3 * sizeof(float); + // Additional attributes. + std::vector<size_t> size_floatattr; + std::vector<size_t> size_intattr; + + size_floatattr.resize(ifs.GetNumFloatAttributes()); + size_intattr.resize(ifs.GetNumIntAttributes()); + + decoded_data_size = size_coordindex + size_coord + size_normal; + for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) + { + // size = number_of_elements * components_per_element * size_of_component. + // Note. But as you can see above, at first we are use this variable in meaning "count". After checking count of objects... + size_t tval = ifs.GetNFloatAttribute(static_cast<unsigned long>(idx)); + + switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))) + { + case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD: + // Check situation when encoded data contain texture coordinates but primitive not. + if(idx_texcoord < primitives[0].attributes.texcoord.size()) + { + if(primitives[0].attributes.texcoord[idx]->count != tval) + throw DeadlyImportError("GLTF: Open3DGC. Compressed texture coordinates count (" + std::to_string(tval) + + ") not equal to uncompressed (" + std::to_string(primitives[0].attributes.texcoord[idx]->count) + ")."); + + idx_texcoord++; + } + else + { + ifs.SetNFloatAttribute(static_cast<unsigned long>(idx), 0ul);// Disable decoding this attribute. + } + + break; + default: + throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))); + } + + tval *= ifs.GetFloatAttributeDim(static_cast<unsigned long>(idx)) * sizeof(o3dgc::Real);// After checking count of objects we can get size of array. + size_floatattr[idx] = tval; + decoded_data_size += tval; + } + + for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) + { + // size = number_of_elements * components_per_element * size_of_component. See float attributes note. + size_t tval = ifs.GetNIntAttribute(static_cast<unsigned long>(idx)); + switch( ifs.GetIntAttributeType(static_cast<unsigned long>(idx) ) ) + { + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID: + break; + + default: + throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx)))); + } + + tval *= ifs.GetIntAttributeDim(static_cast<unsigned long>(idx)) * sizeof(long);// See float attributes note. + size_intattr[idx] = tval; + decoded_data_size += tval; + } + + // Create array for decoded data. + decoded_data = new uint8_t[decoded_data_size]; + + /****************** Set right array regions for decoder ******************/ + + auto get_buf_offset = [](Ref<Accessor>& pAccessor) -> size_t { return pAccessor->byteOffset + pAccessor->bufferView->byteOffset; }; + + // Indices + ifs.SetCoordIndex((IndicesType* const)(decoded_data + get_buf_offset(primitives[0].indices))); + // Coordinates + ifs.SetCoord((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.position[0]))); + // Normals + if(size_normal) + { + ifs.SetNormal((o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.normal[0]))); + } + + for(size_t idx = 0, idx_end = size_floatattr.size(), idx_texcoord = 0; idx < idx_end; idx++) + { + switch(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx))) + { + case o3dgc::O3DGC_IFS_FLOAT_ATTRIBUTE_TYPE_TEXCOORD: + if(idx_texcoord < primitives[0].attributes.texcoord.size()) + { + // See above about absent attributes. + ifs.SetFloatAttribute(static_cast<unsigned long>(idx), (o3dgc::Real* const)(decoded_data + get_buf_offset(primitives[0].attributes.texcoord[idx]))); + idx_texcoord++; + } + + break; + default: + throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of float attribute: " + to_string(ifs.GetFloatAttributeType(static_cast<unsigned long>(idx)))); + } + } + + for(size_t idx = 0, idx_end = size_intattr.size(); idx < idx_end; idx++) { + switch(ifs.GetIntAttributeType(static_cast<unsigned int>(idx))) { + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_UNKOWN: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_JOINT_ID: + case o3dgc::O3DGC_IFS_INT_ATTRIBUTE_TYPE_INDEX_BUFFER_ID: + break; + + // ifs.SetIntAttribute(idx, (long* const)(decoded_data + get_buf_offset(primitives[0].attributes.joint))); + default: + throw DeadlyImportError("GLTF: Open3DGC. Unsupported type of int attribute: " + to_string(ifs.GetIntAttributeType(static_cast<unsigned long>(idx)))); + } + } + + // + // Decode data + // + if ( decoder.DecodePayload( ifs, bstream ) != o3dgc::O3DGC_OK ) { + throw DeadlyImportError( "GLTF: can not decode Open3DGC data." ); + } + + // Set encoded region for "buffer". + buf->EncodedRegion_Mark(pCompression_Open3DGC.Offset, pCompression_Open3DGC.Count, decoded_data, decoded_data_size, id); + // No. Do not delete "output_data". After calling "EncodedRegion_Mark" bufferView is owner of "output_data". + // "delete [] output_data;" +} +#endif -inline void Camera::Read(Value& obj, Asset& r) +inline void Camera::Read(Value& obj, Asset& /*r*/) { type = MemberOrDefault(obj, "type", Camera::Perspective); @@ -738,7 +1116,7 @@ inline void Camera::Read(Value& obj, Asset& r) } } -inline void Light::Read(Value& obj, Asset& r) +inline void Light::Read(Value& obj, Asset& /*r*/) { SetDefaults(); @@ -798,7 +1176,7 @@ inline void Node::Read(Value& obj, Asset& r) } } - + if (Value* matrix = FindArray(obj, "matrix")) { ReadValue(*matrix, this->matrix); } @@ -859,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r) inline void AssetMetadata::Read(Document& doc) { // read the version, etc. - int statedVersion = 0; if (Value* obj = FindObject(doc, "asset")) { ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - statedVersion = MemberOrDefault(*obj, "version", 0); + + if (Value* versionString = FindString(*obj, "version")) { + version = versionString->GetString(); + } else if (Value* versionNumber = FindNumber (*obj, "version")) { + char buf[4]; + + ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble()); + + version = buf; + } if (Value* profile = FindObject(*obj, "profile")) { ReadMember(*profile, "api", this->profile.api); @@ -873,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc) } } - version = std::max(statedVersion, version); - if (version == 0) { - // if missing version, we'll assume version 1... - version = 1; - } - - if (version != 1) { - char msg[128]; - ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %d", version); - throw DeadlyImportError(msg); + if (version.empty() || version[0] != '1') { + throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); } } @@ -904,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream) } AI_SWAP4(header.version); - asset.version = header.version; + asset.version = to_string(header.version); if (header.version != 1) { throw DeadlyImportError("GLTF: Unsupported binary glTF version"); } @@ -1036,7 +1414,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc) #undef CHECK_EXT } -inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool absolute) +inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool /*absolute*/) { #ifdef ASSIMP_API return mIOSystem->Open(path, mode); @@ -1074,13 +1452,13 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi id = buffer; it = mUsedIds.find(id); } - + return id; } namespace Util { - inline + inline bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) { if ( NULL == const_uri ) { return false; @@ -1264,6 +1642,4 @@ namespace Util { } -} - - +} // ns glTF |